diff --git a/fusion_plating/fusion_plating_certificates/models/fp_certificate.py b/fusion_plating/fusion_plating_certificates/models/fp_certificate.py index 65be18b3..359bb441 100644 --- a/fusion_plating/fusion_plating_certificates/models/fp_certificate.py +++ b/fusion_plating/fusion_plating_certificates/models/fp_certificate.py @@ -551,6 +551,27 @@ class FpCertificate(models.Model): 'name': rec.name or rec.display_name, 'c': rec.contact_partner_id.name, }) + # Orphan cert types (Nadcap / Mill Test / Customer-Specific) + # are manual-attach only — operator uploads supplier doc / + # regulator-issued cert / filled customer template. Block + # issuance until an attachment is present so the customer + # doesn't receive an empty PDF. See spec 2026-05-27. + ORPHAN_TYPES = ('nadcap_cert', 'mill_test', 'customer_specific') + if (rec.certificate_type in ORPHAN_TYPES + and not rec.attachment_id): + type_label = dict( + rec._fields['certificate_type'].selection + ).get(rec.certificate_type, rec.certificate_type) + raise UserError(_( + 'Cannot issue %(type)s "%(name)s" — no PDF attached.' + '\n\nThis certificate type expects a PDF you upload ' + 'from disk (supplier doc / regulator-issued cert / ' + 'filled customer template). Upload the PDF to the ' + 'Attachment field on this cert before clicking Issue.' + ) % { + 'type': type_label, + 'name': rec.name or rec.display_name, + }) # Thickness data requirement — unified gate covering both # cert types. A customer needs thickness data on the cert # when ANY of these is true: @@ -729,6 +750,13 @@ class FpCertificate(models.Model): import base64 import io self.ensure_one() + # Orphan cert types (Nadcap / Mill Test / Customer-Specific) are + # manual-attach only — never render a CoC QWeb template for them. + # action_issue's precondition gate already enforces the + # attachment requirement, so by the time we get here the operator + # has uploaded the right PDF. See spec 2026-05-27 §4. + if self.certificate_type != 'coc': + return self.attachment_id or False if self.attachment_id: return self.attachment_id report = (