feat(certificates): orphan-cert attachment gate + render early-return
Block fp.certificate.action_issue on Nadcap / Mill Test / Customer- Specific certs when attachment_id is empty. These three cert types are manual-attach only — operator uploads the supplier doc / regulator-issued cert / filled customer template PDF before the cert can be issued. Prevents shipping the customer an empty PDF. _fp_render_and_attach_pdf gets an early-return guard so an orphan- type cert never tries to render a CoC QWeb template. Sub: docs/superpowers/specs/2026-05-27-recipe-cert-toggles-design.md Task: T5. Makes test_orphan_cert_issue_blocks_without_attachment pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -551,6 +551,27 @@ class FpCertificate(models.Model):
|
|||||||
'name': rec.name or rec.display_name,
|
'name': rec.name or rec.display_name,
|
||||||
'c': rec.contact_partner_id.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
|
# Thickness data requirement — unified gate covering both
|
||||||
# cert types. A customer needs thickness data on the cert
|
# cert types. A customer needs thickness data on the cert
|
||||||
# when ANY of these is true:
|
# when ANY of these is true:
|
||||||
@@ -729,6 +750,13 @@ class FpCertificate(models.Model):
|
|||||||
import base64
|
import base64
|
||||||
import io
|
import io
|
||||||
self.ensure_one()
|
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:
|
if self.attachment_id:
|
||||||
return self.attachment_id
|
return self.attachment_id
|
||||||
report = (
|
report = (
|
||||||
|
|||||||
Reference in New Issue
Block a user