from django.shortcuts import render, get_object_or_404, redirect from django.contrib.auth.decorators import login_required from django.contrib import messages from django.http import JsonResponse from django.urls import reverse from django.utils import timezone from processes.models import ProcessInstance, StepInstance from invoices.models import Invoice from installations.models import InstallationReport from .models import CertificateTemplate, CertificateInstance from _helpers.jalali import Gregorian def _to_jalali(date_obj): try: g = Gregorian(date_obj) y, m, d = g.persian_tuple() return f"{y}/{m:02d}/{d:02d}" except Exception: return '' def _render_template(template: CertificateTemplate, instance: ProcessInstance): well = instance.well rep = instance.representative latest_report = InstallationReport.objects.filter(assignment__process_instance=instance).order_by('-created').first() ctx = { 'today_jalali': _to_jalali(timezone.now().date()), 'request_code': instance.code, 'company_name': (template.company.name if template.company else '') or '', 'customer_full_name': rep.get_full_name() if rep else '', 'water_subscription_number': getattr(well, 'water_subscription_number', '') or '', 'address': getattr(well, 'address', '') or '', 'visit_date_jalali': _to_jalali(getattr(latest_report, 'visited_date', None)) if latest_report else '', } title = (template.title or '').format(**ctx) body = (template.body or '') for k, v in ctx.items(): body = body.replace(f"{{{{ {k} }}}}", str(v)) return title, body @login_required def certificate_step(request, instance_id, step_id): instance = get_object_or_404(ProcessInstance, id=instance_id) # Ensure all previous steps are completed and invoice settled prior_steps = instance.process.steps.filter(order__lt=instance.current_step.order if instance.current_step else 9999) incomplete = StepInstance.objects.filter(process_instance=instance, step__in=prior_steps).exclude(status='completed').exists() if incomplete: messages.error(request, 'ابتدا همه مراحل قبلی را تکمیل کنید') return redirect('processes:request_list') inv = Invoice.objects.filter(process_instance=instance).first() if inv: inv.calculate_totals() if inv.remaining_amount != 0: messages.error(request, 'مانده فاکتور باید صفر باشد') return redirect('processes:request_list') template = CertificateTemplate.objects.filter(is_active=True).order_by('-created').first() if not template: return render(request, 'certificates/missing.html', {}) title, body = _render_template(template, instance) cert, _ = CertificateInstance.objects.get_or_create( process_instance=instance, defaults={'template': template, 'rendered_title': title, 'rendered_body': body} ) # keep rendered up-to-date cert.template = template cert.rendered_title = title cert.rendered_body = body cert.save() previous_step = instance.process.steps.filter(order__lt=instance.current_step.order).last() if instance.current_step else None next_step = instance.process.steps.filter(order__gt=instance.current_step.order).first() if instance.current_step else None if request.method == 'POST': cert.approved = True cert.approved_at = timezone.now() cert.save() step_instance, _ = StepInstance.objects.get_or_create(process_instance=instance, step_id=step_id) step_instance.status = 'completed' step_instance.completed_at = timezone.now() step_instance.save() 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, 'certificates/step.html', { 'instance': instance, 'template': template, 'cert': cert, 'previous_step': previous_step, 'next_step': next_step, }) @login_required def certificate_print(request, instance_id): instance = get_object_or_404(ProcessInstance, id=instance_id) cert = CertificateInstance.objects.filter(process_instance=instance).order_by('-created').first() template = cert.template if cert else None return render(request, 'certificates/print.html', { 'instance': instance, 'cert': cert, 'template': template, })