This commit is contained in:
gsinghpal
2026-04-27 08:16:20 -04:00
parent f08f328688
commit 2a4909be25
12 changed files with 788 additions and 20 deletions

View File

@@ -5,7 +5,7 @@
{
'name': 'Fusion Plating — Quality (QMS)',
'version': '19.0.4.7.0',
'version': '19.0.4.8.0',
'category': 'Manufacturing/Plating',
'summary': 'Native QMS for plating shops: NCR, CAPA, calibration, AVL, FAIR, '
'internal audits, customer specs, document control. CE + EE compatible.',

View File

@@ -237,6 +237,14 @@ class FpQualityCheck(models.Model):
) % self.env.user.name)
def action_fail(self):
"""Mark QC failed AND auto-spawn a fusion.plating.quality.hold
so the parts have an AS9100 disposition record. Without this
spawning the parts are in limbo — operator can't ship and
nothing tracks scrap/rework/use-as-is decisions.
v19.0.4.x — Hold auto-spawn added per the tablet usability pass.
"""
Hold = self.env.get('fusion.plating.quality.hold')
for rec in self:
rec.write({
'state': 'failed',
@@ -247,6 +255,53 @@ class FpQualityCheck(models.Model):
rec.message_post(body=Markup(
'<b>QC FAILED</b> — inspector %s.'
) % self.env.user.name)
# Auto-spawn the Hold (best-effort; QC failure stands even
# if Hold creation fails for some odd reason).
if Hold is not None and rec.job_id:
# Avoid dupes if the manager calls fail twice
existing = Hold.sudo().search([
('x_fc_job_id', '=', rec.job_id.id),
('hold_reason', '=', 'qc_failure'),
('state', 'in', ('on_hold', 'under_review')),
], limit=1) if 'x_fc_job_id' in Hold._fields else False
if not existing:
fail_lines = ', '.join(
l.name for l in rec.line_ids.filtered(
lambda l: l.result == 'fail'
)
) or '(see checklist)'
vals = {
'part_ref': rec.job_id.name or '',
'qty_on_hold': int(rec.job_id.qty or 1),
'qty_original': int(rec.job_id.qty or 1),
'hold_reason': (
'qc_failure'
if 'qc_failure' in dict(
Hold._fields['hold_reason'].selection
)
else 'other'
),
'description': (
'QC %s failed. Failed checks: %s. '
'Inspector: %s. Manager: review and decide '
'rework / scrap / use-as-is.'
) % (rec.name, fail_lines, self.env.user.name),
}
if 'x_fc_job_id' in Hold._fields:
vals['x_fc_job_id'] = rec.job_id.id
if 'partner_id' in Hold._fields and rec.partner_id:
vals['partner_id'] = rec.partner_id.id
try:
hold = Hold.sudo().create(vals)
rec.message_post(body=Markup(
'Hold <b>%s</b> auto-created for failed QC. '
'Manager must dispose.'
) % hold.name)
except Exception as e:
_logger.warning(
'QC %s: failed to auto-spawn hold: %s',
rec.name, e,
)
def action_rework(self):
for rec in self:

View File

@@ -56,6 +56,10 @@ class FpQualityHold(models.Model):
('contamination', 'Contamination'),
('customer_complaint', 'Customer Complaint'),
('process_deviation', 'Process Deviation'),
# v19.0.4.8.0 — Distinct bucket so QA can split QC-failed
# holds (auto-spawned by fusion.plating.quality.check.action_fail)
# from operator-flagged process deviations / contamination.
('qc_failure', 'QC Failure'),
('other', 'Other'),
],
string='Hold Reason',