changes
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
{
|
||||
'name': 'Fusion Plating — Shop Floor',
|
||||
'version': '19.0.24.0.0',
|
||||
'version': '19.0.24.2.0',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': 'Shop-floor tablet stations, QR scanning, bake window enforcer, '
|
||||
'first-piece inspection gates.',
|
||||
|
||||
@@ -208,8 +208,17 @@ class FpShopfloorController(http.Controller):
|
||||
'name': step.name,
|
||||
'state': step.state,
|
||||
'duration_actual': step.duration_actual,
|
||||
'duration_expected': step.duration_expected,
|
||||
'job_name': step.job_id.name or '',
|
||||
'product_name': step.job_id.product_id.display_name or '',
|
||||
# Recipe-author instructions surfaced to the operator on
|
||||
# scan. Without this the operator never sees bake
|
||||
# setpoints, masking patterns, dwell times, etc.
|
||||
'instructions': step.instructions or '',
|
||||
'thickness_target': step.thickness_target or 0,
|
||||
'thickness_uom': step.thickness_uom or '',
|
||||
'dwell_time_minutes': step.dwell_time_minutes or 0,
|
||||
'bake_setpoint_temp': step.bake_setpoint_temp or 0,
|
||||
}
|
||||
|
||||
# FP-QC:<ref> → directly into the mobile checklist screen
|
||||
@@ -1083,6 +1092,15 @@ class FpShopfloorController(http.Controller):
|
||||
'duration_display': _dur_disp(step.duration_actual or 0),
|
||||
'duration_expected_display': _dur_disp(step.duration_expected or 0),
|
||||
'missing_for_release': '',
|
||||
# Operator-facing recipe guidance — without this the
|
||||
# tablet UI has no way to surface bake setpoints,
|
||||
# masking patterns, dwell times, etc.
|
||||
'instructions': step.instructions or '',
|
||||
'thickness_target': step.thickness_target or 0,
|
||||
'thickness_uom': step.thickness_uom or '',
|
||||
'dwell_time_minutes': step.dwell_time_minutes or 0,
|
||||
'bake_setpoint_temp': step.bake_setpoint_temp or 0,
|
||||
'requires_signoff': bool(step.requires_signoff),
|
||||
}
|
||||
|
||||
attached_step_ids = set()
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class FpBakeWindow(models.Model):
|
||||
@@ -247,12 +248,48 @@ class FpBakeWindow(models.Model):
|
||||
# Actions
|
||||
# ==========================================================================
|
||||
def action_start_bake(self):
|
||||
"""Move into bake_in_progress.
|
||||
|
||||
Hard guard: cannot start a bake on a missed_window record without
|
||||
manager override (context `fp_skip_missed_window=True`). AS9100 /
|
||||
Nadcap can't be retroactively documented — starting a bake after
|
||||
the window means the parts are likely scrap. The override exists
|
||||
for the rare case the customer accepts a deviation in writing;
|
||||
every override posts to chatter so the audit trail is intact.
|
||||
"""
|
||||
skip = self.env.context.get('fp_skip_missed_window')
|
||||
is_manager = self.env.user.has_group(
|
||||
'fusion_plating.group_fusion_plating_manager'
|
||||
)
|
||||
for rec in self:
|
||||
if rec.state == 'missed_window':
|
||||
if not skip or not is_manager:
|
||||
raise UserError(_(
|
||||
'Bake window %s has expired (required by %s). '
|
||||
'A manager must override via the "Force Start "'
|
||||
'(missed window)" action — the override is '
|
||||
'logged on chatter for audit. Otherwise the '
|
||||
'parts must be scrapped.'
|
||||
) % (rec.name, rec.bake_required_by))
|
||||
rec.message_post(body=_(
|
||||
'MANAGER OVERRIDE: bake started after missed window. '
|
||||
'Window required by %s — actual start %s. Customer '
|
||||
'deviation must be on file.'
|
||||
) % (rec.bake_required_by, fields.Datetime.now()))
|
||||
rec.write({
|
||||
'state': 'bake_in_progress',
|
||||
'bake_start_time': fields.Datetime.now(),
|
||||
})
|
||||
|
||||
def action_force_start_missed(self):
|
||||
"""Manager-only: force-start a bake on a missed_window record.
|
||||
|
||||
Just calls action_start_bake with the override context. Exists
|
||||
as a separate button so the form view can guard visibility on
|
||||
manager group.
|
||||
"""
|
||||
return self.with_context(fp_skip_missed_window=True).action_start_bake()
|
||||
|
||||
def action_end_bake(self):
|
||||
for rec in self:
|
||||
vals = {
|
||||
|
||||
Reference in New Issue
Block a user