diff --git a/certificates/admin.py b/certificates/admin.py index de9ba72..f1eff8a 100644 --- a/certificates/admin.py +++ b/certificates/admin.py @@ -12,9 +12,7 @@ class CertificateTemplateAdmin(admin.ModelAdmin): @admin.register(CertificateInstance) class CertificateInstanceAdmin(admin.ModelAdmin): - list_display = ('process_instance', 'rendered_title', 'issued_at', 'approved') + list_display = ('process_instance', 'rendered_title', 'hologram_code', 'issued_at', 'approved') list_filter = ('approved', 'issued_at') - search_fields = ('process_instance__code', 'rendered_title') + search_fields = ('process_instance__code', 'rendered_title', 'hologram_code') autocomplete_fields = ('process_instance', 'template') - - diff --git a/certificates/migrations/0003_alter_certificateinstance_hologram_code.py b/certificates/migrations/0003_alter_certificateinstance_hologram_code.py new file mode 100644 index 0000000..00fb9cd --- /dev/null +++ b/certificates/migrations/0003_alter_certificateinstance_hologram_code.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.4 on 2025-10-09 08:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('certificates', '0002_certificateinstance_hologram_code'), + ] + + operations = [ + migrations.AlterField( + model_name='certificateinstance', + name='hologram_code', + field=models.CharField(blank=True, max_length=50, null=True, unique=True, verbose_name='کد یکتا هولوگرام'), + ), + ] diff --git a/certificates/models.py b/certificates/models.py index a7afe72..c374035 100644 --- a/certificates/models.py +++ b/certificates/models.py @@ -28,7 +28,7 @@ class CertificateInstance(BaseModel): issued_at = models.DateField(auto_now_add=True, verbose_name='تاریخ صدور') approved = models.BooleanField(default=False, verbose_name='تایید شده') approved_at = models.DateTimeField(null=True, blank=True, verbose_name='تاریخ تایید') - hologram_code = models.CharField(max_length=50, null=True, blank=True, verbose_name='کد یکتا هولوگرام') + hologram_code = models.CharField(max_length=50, null=True, blank=True, verbose_name='کد یکتا هولوگرام', unique=True) class Meta: verbose_name = 'گواهی' diff --git a/certificates/views.py b/certificates/views.py index 5149334..c16e7e9 100644 --- a/certificates/views.py +++ b/certificates/views.py @@ -6,6 +6,7 @@ from django.urls import reverse from django.utils import timezone from django.template import Template, Context from django.utils.safestring import mark_safe +from django.db import IntegrityError from processes.models import ProcessInstance, StepInstance from invoices.models import Invoice @@ -157,15 +158,56 @@ def certificate_print(request, instance_id): if request.method == 'POST': # Save/update hologram code then print code = (request.POST.get('hologram_code') or '').strip() - if cert: - if code: + + if not code: + messages.error(request, 'کد یکتای هولوگرام الزامی است') + # Find certificate step to redirect back + certificate_step = instance.process.steps.filter(order=9).first() + if certificate_step and instance.current_step: + return redirect('processes:step_detail', instance_id=instance.id, step_id=certificate_step.id) + return redirect('processes:instance_summary', instance_id=instance.id) + + try: + if cert: + # Check if hologram code is already used by another certificate + if CertificateInstance.objects.filter(hologram_code=code).exclude(id=cert.id).exists(): + messages.error(request, 'این کد هولوگرام قبلاً استفاده شده است. لطفاً کد دیگری وارد کنید') + # Find certificate step to redirect back + certificate_step = instance.process.steps.filter(order=9).first() + if certificate_step and instance.current_step: + return redirect('processes:step_detail', instance_id=instance.id, step_id=certificate_step.id) + return redirect('processes:instance_summary', instance_id=instance.id) + cert.hologram_code = code cert.save(update_fields=['hologram_code']) - else: - template = CertificateTemplate.objects.filter(is_active=True).order_by('-created').first() - if template: - title, body = _render_template(template, instance) - cert = CertificateInstance.objects.create(process_instance=instance, template=template, rendered_title=title, rendered_body=body, hologram_code=code or None) + else: + # Check if hologram code is already used + if CertificateInstance.objects.filter(hologram_code=code).exists(): + messages.error(request, 'این کد هولوگرام قبلاً استفاده شده است. لطفاً کد دیگری وارد کنید') + # Find certificate step to redirect back + certificate_step = instance.process.steps.filter(order=9).first() + if certificate_step and instance.current_step: + return redirect('processes:step_detail', instance_id=instance.id, step_id=certificate_step.id) + return redirect('processes:instance_summary', instance_id=instance.id) + + template = CertificateTemplate.objects.filter(is_active=True).order_by('-created').first() + if template: + title, body = _render_template(template, instance) + cert = CertificateInstance.objects.create( + process_instance=instance, + template=template, + rendered_title=title, + rendered_body=body, + hologram_code=code + ) + except IntegrityError: + messages.error(request, 'این کد هولوگرام قبلاً استفاده شده است. لطفاً کد دیگری وارد کنید') + # Find certificate step to redirect back + certificate_step = instance.process.steps.filter(order=9).first() + if certificate_step and instance.current_step: + return redirect('processes:step_detail', instance_id=instance.id, step_id=certificate_step.id) + return redirect('processes:instance_summary', instance_id=instance.id) + # proceed to rendering page after saving code return render(request, 'certificates/print.html', { 'instance': instance, diff --git a/db.sqlite3 b/db.sqlite3 index 088d726..18e25d4 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ