complete first version of main proccess
This commit is contained in:
parent
6ff4740d04
commit
f2fc2362a7
61 changed files with 3280 additions and 28 deletions
0
contracts/__init__.py
Normal file
0
contracts/__init__.py
Normal file
15
contracts/admin.py
Normal file
15
contracts/admin.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
from django.contrib import admin
|
||||
from .models import ContractTemplate, ContractInstance
|
||||
|
||||
@admin.register(ContractTemplate)
|
||||
class ContractTemplateAdmin(admin.ModelAdmin):
|
||||
list_display = ['name',]
|
||||
search_fields = ['name']
|
||||
prepopulated_fields = {'slug': ('name',)}
|
||||
readonly_fields = ['created', 'updated']
|
||||
|
||||
@admin.register(ContractInstance)
|
||||
class ContractInstanceAdmin(admin.ModelAdmin):
|
||||
list_display = ['process_instance', 'template']
|
||||
search_fields = ['process_instance__code', 'template__name']
|
||||
readonly_fields = ['created', 'updated']
|
8
contracts/apps.py
Normal file
8
contracts/apps.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ContractsConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'contracts'
|
||||
verbose_name = 'قراردادها'
|
||||
|
118
contracts/migrations/0001_initial.py
Normal file
118
contracts/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,118 @@
|
|||
# Generated by Django 5.2.4 on 2025-08-21 06:00
|
||||
|
||||
import django.db.models.deletion
|
||||
import simple_history.models
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('processes', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ContractTemplate',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='تاریخ ایجاد')),
|
||||
('updated', models.DateTimeField(auto_now=True, verbose_name='تاریخ بروزرسانی')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='فعال')),
|
||||
('is_deleted', models.BooleanField(default=False, verbose_name='حذف شده')),
|
||||
('deleted_at', models.DateTimeField(blank=True, null=True, verbose_name='تاریخ حذف')),
|
||||
('slug', models.SlugField(max_length=100, unique=True, verbose_name='اسلاگ')),
|
||||
('name', models.CharField(max_length=100, verbose_name='نام')),
|
||||
('body', models.TextField(verbose_name='متن قرارداد')),
|
||||
('company_logo', models.ImageField(blank=True, null=True, upload_to='contracts/logos/%Y/%m/%d/', verbose_name='لوگوی شرکت')),
|
||||
('company_signature', models.ImageField(blank=True, null=True, upload_to='contracts/signatures/%Y/%m/%d/', verbose_name='امضای شرکت')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'قالب قرارداد',
|
||||
'verbose_name_plural': 'قالب\u200cهای قرارداد',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ContractInstance',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='تاریخ ایجاد')),
|
||||
('updated', models.DateTimeField(auto_now=True, verbose_name='تاریخ بروزرسانی')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='فعال')),
|
||||
('is_deleted', models.BooleanField(default=False, verbose_name='حذف شده')),
|
||||
('deleted_at', models.DateTimeField(blank=True, null=True, verbose_name='تاریخ حذف')),
|
||||
('rendered_body', models.TextField(verbose_name='متن نهایی قرارداد')),
|
||||
('approved', models.BooleanField(default=False, verbose_name='تایید شده')),
|
||||
('approved_at', models.DateTimeField(blank=True, null=True, verbose_name='تاریخ تایید')),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='ایجاد کننده')),
|
||||
('process_instance', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contracts', to='processes.processinstance', verbose_name='نمونه فرآیند')),
|
||||
('template', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='contracts.contracttemplate', verbose_name='قالب مورد استفاده')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'قرارداد',
|
||||
'verbose_name_plural': 'قراردادها',
|
||||
'ordering': ['-created'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='HistoricalContractInstance',
|
||||
fields=[
|
||||
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
|
||||
('created', models.DateTimeField(blank=True, editable=False, verbose_name='تاریخ ایجاد')),
|
||||
('updated', models.DateTimeField(blank=True, editable=False, verbose_name='تاریخ بروزرسانی')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='فعال')),
|
||||
('is_deleted', models.BooleanField(default=False, verbose_name='حذف شده')),
|
||||
('deleted_at', models.DateTimeField(blank=True, null=True, verbose_name='تاریخ حذف')),
|
||||
('rendered_body', models.TextField(verbose_name='متن نهایی قرارداد')),
|
||||
('approved', models.BooleanField(default=False, verbose_name='تایید شده')),
|
||||
('approved_at', models.DateTimeField(blank=True, null=True, verbose_name='تاریخ تایید')),
|
||||
('history_id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('history_date', models.DateTimeField(db_index=True)),
|
||||
('history_change_reason', models.CharField(max_length=100, null=True)),
|
||||
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
|
||||
('created_by', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='ایجاد کننده')),
|
||||
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||
('process_instance', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='processes.processinstance', verbose_name='نمونه فرآیند')),
|
||||
('template', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='contracts.contracttemplate', verbose_name='قالب مورد استفاده')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'historical قرارداد',
|
||||
'verbose_name_plural': 'historical قراردادها',
|
||||
'ordering': ('-history_date', '-history_id'),
|
||||
'get_latest_by': ('history_date', 'history_id'),
|
||||
},
|
||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='HistoricalContractTemplate',
|
||||
fields=[
|
||||
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
|
||||
('created', models.DateTimeField(blank=True, editable=False, verbose_name='تاریخ ایجاد')),
|
||||
('updated', models.DateTimeField(blank=True, editable=False, verbose_name='تاریخ بروزرسانی')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='فعال')),
|
||||
('is_deleted', models.BooleanField(default=False, verbose_name='حذف شده')),
|
||||
('deleted_at', models.DateTimeField(blank=True, null=True, verbose_name='تاریخ حذف')),
|
||||
('slug', models.SlugField(max_length=100, verbose_name='اسلاگ')),
|
||||
('name', models.CharField(max_length=100, verbose_name='نام')),
|
||||
('body', models.TextField(verbose_name='متن قرارداد')),
|
||||
('company_logo', models.TextField(blank=True, max_length=100, null=True, verbose_name='لوگوی شرکت')),
|
||||
('company_signature', models.TextField(blank=True, max_length=100, null=True, verbose_name='امضای شرکت')),
|
||||
('history_id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('history_date', models.DateTimeField(db_index=True)),
|
||||
('history_change_reason', models.CharField(max_length=100, null=True)),
|
||||
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
|
||||
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'historical قالب قرارداد',
|
||||
'verbose_name_plural': 'historical قالب\u200cهای قرارداد',
|
||||
'ordering': ('-history_date', '-history_id'),
|
||||
'get_latest_by': ('history_date', 'history_id'),
|
||||
},
|
||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,38 @@
|
|||
# Generated by Django 5.2.4 on 2025-08-21 06:33
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0002_company'),
|
||||
('contracts', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='historicalcontracttemplate',
|
||||
name='history_user',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='contracttemplate',
|
||||
name='company_logo',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='contracttemplate',
|
||||
name='company_signature',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='contracttemplate',
|
||||
name='company',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.company', verbose_name='شرکت'),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='HistoricalContractInstance',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='HistoricalContractTemplate',
|
||||
),
|
||||
]
|
0
contracts/migrations/__init__.py
Normal file
0
contracts/migrations/__init__.py
Normal file
36
contracts/models.py
Normal file
36
contracts/models.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
from django.db import models
|
||||
from django.contrib.auth import get_user_model
|
||||
from common.models import NameSlugModel, BaseModel
|
||||
from accounts.models import Company
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class ContractTemplate(NameSlugModel):
|
||||
body = models.TextField(verbose_name='متن قرارداد')
|
||||
company = models.ForeignKey(Company, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='شرکت')
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'قالب قرارداد'
|
||||
verbose_name_plural = 'قالبهای قرارداد'
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ContractInstance(BaseModel):
|
||||
process_instance = models.ForeignKey('processes.ProcessInstance', on_delete=models.CASCADE, related_name='contracts', verbose_name='نمونه فرآیند')
|
||||
template = models.ForeignKey(ContractTemplate, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='قالب مورد استفاده')
|
||||
rendered_body = models.TextField(verbose_name='متن نهایی قرارداد')
|
||||
approved = models.BooleanField(default=False, verbose_name='تایید شده')
|
||||
approved_at = models.DateTimeField(null=True, blank=True, verbose_name='تاریخ تایید')
|
||||
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='ایجاد کننده')
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'قرارداد'
|
||||
verbose_name_plural = 'قراردادها'
|
||||
ordering = ['-created']
|
||||
|
||||
def __str__(self):
|
||||
return f"Contract for {self.process_instance}"
|
||||
|
29
contracts/templates/contracts/contract_missing.html
Normal file
29
contracts/templates/contracts/contract_missing.html
Normal file
|
@ -0,0 +1,29 @@
|
|||
{% extends '_base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% include 'sidebars/admin.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block navbar %}
|
||||
{% include 'navbars/admin.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}قالب قرارداد یافت نشد{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="alert alert-warning">
|
||||
<h5 class="alert-heading mb-2">قالب قرارداد تعریف نشده است</h5>
|
||||
<p class="mb-2">برای نمایش این مرحله، ابتدا یک «قالب قرارداد» ایجاد کنید.</p>
|
||||
<ul class="mb-2">
|
||||
<li>از منوی ادمین یک قالب با متن قرارداد ایجاد کنید.</li>
|
||||
<li>در متن میتوانید از جاینگهدارهایی مثل {{customer_full_name}} ، {{national_code}} ، {{water_subscription_number}} استفاده کنید.</li>
|
||||
</ul>
|
||||
<a class="btn btn-primary" href="/admin/contracts/contracttemplate/add/">ایجاد قالب قرارداد</a>
|
||||
<a class="btn btn-outline-secondary" href="{% url 'processes:request_list' %}">بازگشت</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
52
contracts/templates/contracts/contract_print.html
Normal file
52
contracts/templates/contracts/contract_print.html
Normal file
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fa" dir="rtl">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>چاپ قرارداد {{ instance.code }}</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
@page { size: A4; margin: 1.2cm; }
|
||||
body { font-family: 'Vazirmatn', sans-serif; }
|
||||
.logo { max-height: 80px; }
|
||||
.signature { height: 90px; border: 1px dashed #ccc; }
|
||||
</style>
|
||||
<script>
|
||||
window.addEventListener('load', function(){ setTimeout(function(){ window.print(); }, 300); });
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<div>
|
||||
<h5>{{ contract.template.company.name }}</h5>
|
||||
<h5 class="mb-1">{{ contract.template.name }}</h5>
|
||||
<div class="text-muted small">کد درخواست: {{ instance.code }} | تاریخ: {{ contract.jcreated }}</div>
|
||||
</div>
|
||||
{% if contract.template.company.logo %}
|
||||
<img class="logo" src="{{ contract.template.company.logo.url }}" alt="لوگو" />
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
<div style="white-space: pre-line; line-height: 1.9;">{{ contract.rendered_body|safe }}</div>
|
||||
<hr>
|
||||
<div class="row mt-4">
|
||||
<div class="col-6 text-center">
|
||||
<div>امضای مشترک</div>
|
||||
<div class="signature mt-2"></div>
|
||||
</div>
|
||||
<div class="col-6 text-center">
|
||||
<div>امضای شرکت</div>
|
||||
<div class="signature mt-2">
|
||||
{% if contract.template.company.signature %}
|
||||
<img src="{{ contract.template.company.signature.url }}" alt="امضای شرکت" style="max-height: 80px;" />
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
92
contracts/templates/contracts/contract_step.html
Normal file
92
contracts/templates/contracts/contract_step.html
Normal file
|
@ -0,0 +1,92 @@
|
|||
{% extends '_base.html' %}
|
||||
{% load static %}
|
||||
{% load processes_tags %}
|
||||
{% load humanize %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% include 'sidebars/admin.html' %}
|
||||
{% endblock sidebar %}
|
||||
|
||||
{% block navbar %}
|
||||
{% include 'navbars/admin.html' %}
|
||||
{% endblock navbar %}
|
||||
|
||||
{% block title %}{{ step.name }} - درخواست {{ instance.code }}{% endblock %}
|
||||
|
||||
{% block style %}
|
||||
<link rel="stylesheet" href="{% static 'assets/vendor/libs/bs-stepper/bs-stepper.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% include '_toasts.html' %}
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<div class="row">
|
||||
<div class="col-12 mb-4">
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
<div>
|
||||
<h4 class="mb-1">{{ step.name }}: {{ instance.process.name }}</h4>
|
||||
<small class="text-muted d-block">
|
||||
اشتراک آب: {{ instance.well.water_subscription_number|default:"-" }}
|
||||
| نماینده: {{ instance.representative.profile.national_code|default:"-" }}
|
||||
</small>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{% url 'processes:request_list' %}" class="btn btn-outline-secondary">بازگشت</a>
|
||||
<a href="{% url 'contracts:contract_print' instance.id %}" target="_blank" class="btn btn-outline-secondary">پرینت</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bs-stepper wizard-vertical vertical mt-2">
|
||||
{% stepper_header instance step %}
|
||||
<div class="bs-stepper-content">
|
||||
<div class="card border">
|
||||
<div class="card-body">
|
||||
{% if template.company.logo %}
|
||||
<div class="text-center mb-3">
|
||||
<img src="{{ template.company.logo.url }}" alt="لوگوی شرکت" style="max-height:80px;">
|
||||
<h4 class="text-muted">{{ contract.template.company.name }}</h4>
|
||||
<h5 class="text-muted">{{ contract.template.name }}</h5>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="small text-muted mb-2">تاریخ: {{ contract.jcreated }}</div>
|
||||
<hr>
|
||||
<div class="contract-body" style="white-space: pre-line; line-height:1.9;">{{ contract.rendered_body|safe }}</div>
|
||||
<hr>
|
||||
<div class="row mt-4">
|
||||
<div class="col-6 text-center">
|
||||
<div>امضای مشترک</div>
|
||||
<div style="height:90px;border:1px dashed #ccc; margin-top:10px;"></div>
|
||||
</div>
|
||||
<div class="col-6 text-center">
|
||||
<div>امضای شرکت</div>
|
||||
<div style="height:90px;border:1px dashed #ccc; margin-top:10px;">
|
||||
{% if template.company.signature %}
|
||||
<img src="{{ template.company.signature.url }}" alt="امضای شرکت" style="max-height:80px;">
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form method="post" class="d-flex justify-content-between mt-3">
|
||||
{% csrf_token %}
|
||||
{% if previous_step %}
|
||||
<a href="{% url 'processes:step_detail' instance.id previous_step.id %}" class="btn btn-label-secondary">قبلی</a>
|
||||
{% else %}
|
||||
<span></span>
|
||||
{% endif %}
|
||||
{% if next_step %}
|
||||
<button type="submit" class="btn btn-primary">بعدی</button>
|
||||
{% else %}
|
||||
<button class="btn btn-success" type="button">اتمام</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
11
contracts/urls.py
Normal file
11
contracts/urls.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
app_name = 'contracts'
|
||||
|
||||
urlpatterns = [
|
||||
path('instance/<int:instance_id>/step/<int:step_id>/', views.contract_step, name='contract_step'),
|
||||
path('instance/<int:instance_id>/print/', views.contract_print, name='contract_print'),
|
||||
]
|
||||
|
||||
|
89
contracts/views.py
Normal file
89
contracts/views.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.template import Template, Context
|
||||
from processes.models import ProcessInstance, StepInstance
|
||||
from .models import ContractTemplate, ContractInstance
|
||||
from _helpers.utils import jalali_converter2
|
||||
|
||||
|
||||
def build_contract_context(instance: ProcessInstance) -> dict:
|
||||
representative = instance.representative
|
||||
profile = getattr(representative, 'profile', None)
|
||||
well = instance.well
|
||||
return {
|
||||
'customer_full_name': representative.get_full_name() if representative else '',
|
||||
'national_code': profile.national_code if profile else '',
|
||||
'address': profile.address if profile else '',
|
||||
'phone': profile.phone_number_1 if profile else '',
|
||||
'phone2': profile.phone_number_2 if profile else '',
|
||||
'water_subscription_number': well.water_subscription_number if well else '',
|
||||
'electricity_subscription_number': well.electricity_subscription_number if well else '',
|
||||
'water_meter_serial_number': well.water_meter_serial_number if well else '',
|
||||
'well_power': well.well_power if well else '',
|
||||
'request_code': instance.code,
|
||||
'today': jalali_converter2(timezone.now()),
|
||||
}
|
||||
|
||||
|
||||
@login_required
|
||||
def contract_step(request, instance_id, step_id):
|
||||
instance = get_object_or_404(ProcessInstance, id=instance_id)
|
||||
# Resolve step navigation
|
||||
step = get_object_or_404(instance.process.steps, id=step_id)
|
||||
previous_step = instance.process.steps.filter(order__lt=step.order).last()
|
||||
next_step = instance.process.steps.filter(order__gt=step.order).first()
|
||||
template_obj = ContractTemplate.objects.first()
|
||||
if not template_obj:
|
||||
return render(request, 'contracts/contract_missing.html', {'instance': instance})
|
||||
|
||||
ctx = build_contract_context(instance)
|
||||
rendered = Template(template_obj.body).render(Context(ctx))
|
||||
|
||||
contract, _ = ContractInstance.objects.get_or_create(
|
||||
process_instance=instance,
|
||||
defaults={
|
||||
'template': template_obj,
|
||||
'rendered_body': rendered,
|
||||
'created_by': request.user,
|
||||
}
|
||||
)
|
||||
# keep latest rendering if template changed (optional)
|
||||
contract.template = template_obj
|
||||
contract.rendered_body = rendered
|
||||
contract.save()
|
||||
|
||||
# If user submits to go next, mark this step completed and go to next
|
||||
if request.method == 'POST':
|
||||
StepInstance.objects.update_or_create(
|
||||
process_instance=instance,
|
||||
step=step,
|
||||
defaults={'status': 'completed', 'completed_at': timezone.now()}
|
||||
)
|
||||
if next_step:
|
||||
instance.current_step = next_step
|
||||
instance.save()
|
||||
return redirect('processes:step_detail', instance_id=instance.id, step_id=next_step.id)
|
||||
return redirect('processes:request_list')
|
||||
|
||||
return render(request, 'contracts/contract_step.html', {
|
||||
'instance': instance,
|
||||
'step': step,
|
||||
'contract': contract,
|
||||
'template': template_obj,
|
||||
'previous_step': previous_step,
|
||||
'next_step': next_step,
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
def contract_print(request, instance_id):
|
||||
instance = get_object_or_404(ProcessInstance, id=instance_id)
|
||||
contract = get_object_or_404(ContractInstance, process_instance=instance)
|
||||
return render(request, 'contracts/contract_print.html', {
|
||||
'instance': instance,
|
||||
'contract': contract,
|
||||
})
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue