feat(fusion_plating): Express masking reference images → mask step + workstation viewer
Order-entry shortcut: when masking is toggled ON for an Express order line, an amber "MASK" button appears to attach reference image(s)/PDF(s). The files ride the existing _fp_apply_express_overrides_to_job path onto the job's masking step, so the operator sees exactly what to mask — no recipe edit or custom prompt needed. - configurator: masking_attachment_ids on the wizard line + SO line; action_upload_masking_ref; override branch writes refs onto mask steps; amber multi-file MASK button (express_action_btns) shown when masking is on. - jobs: x_fc_masking_attachment_ids on fp.job.step (per-step) + computed rollup on fp.job; office "Masking Refs" form page (readonly preview). - shopfloor: workspace step payload carries masking_refs (sudo'd attachment read, rule 13m); operator sees thumbnail/PDF tiles on the mask step that open in Odoo's full-screen FileViewer (zoom + swipe). Verified end-to-end on entech: SO-line refs land on the mask step + job rollup (WO-30091); payload mask_refs shape correct (is_image, /web/image). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ from . import fp_job_workflow_state # Sub 14 — must load before fp_job (FK t
|
||||
from . import fp_job
|
||||
from . import fp_job_sticker
|
||||
from . import fp_job_step
|
||||
from . import fp_job_masking
|
||||
from . import fp_job_node_override
|
||||
from . import fp_portal_job
|
||||
from . import account_move
|
||||
|
||||
36
fusion_plating/fusion_plating_jobs/models/fp_job_masking.py
Normal file
36
fusion_plating/fusion_plating_jobs/models/fp_job_masking.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2026 Nexa Systems Inc.
|
||||
"""Masking reference attachments — captured at Express order entry, surfaced
|
||||
on the job's masking step (operator workstation) and rolled up to the job
|
||||
form (office). Populated by sale.order.line._fp_apply_express_overrides_to_job.
|
||||
"""
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class FpJobStep(models.Model):
|
||||
_inherit = 'fp.job.step'
|
||||
|
||||
x_fc_masking_attachment_ids = fields.Many2many(
|
||||
'ir.attachment',
|
||||
'fp_job_step_masking_att_rel', 'step_id', 'attachment_id',
|
||||
string='Masking Reference(s)',
|
||||
help='Reference image(s)/PDF(s) of what to mask, attached at order '
|
||||
'entry (Express) and shown to the operator on the masking step.',
|
||||
)
|
||||
|
||||
|
||||
class FpJob(models.Model):
|
||||
_inherit = 'fp.job'
|
||||
|
||||
x_fc_masking_attachment_ids = fields.Many2many(
|
||||
'ir.attachment',
|
||||
compute='_compute_masking_attachment_ids',
|
||||
string='Masking References',
|
||||
help='All masking reference files across this job\'s masking steps.',
|
||||
)
|
||||
|
||||
@api.depends('step_ids.x_fc_masking_attachment_ids')
|
||||
def _compute_masking_attachment_ids(self):
|
||||
for job in self:
|
||||
atts = job.step_ids.mapped('x_fc_masking_attachment_ids')
|
||||
job.x_fc_masking_attachment_ids = [(6, 0, atts.ids)]
|
||||
@@ -302,6 +302,17 @@
|
||||
<xpath expr="//group[@name='x_fc_notes']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='costs']" position="before">
|
||||
<page string="Masking Refs" name="masking_refs"
|
||||
invisible="not x_fc_masking_attachment_ids">
|
||||
<div class="text-muted mb-2">
|
||||
Masking reference image(s)/PDF(s) attached at order entry (Express).
|
||||
The operator sees these on the masking step in the workstation.
|
||||
</div>
|
||||
<field name="x_fc_masking_attachment_ids" widget="many2many_binary"
|
||||
readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='costs']" position="before">
|
||||
<page string="Notes" name="notes">
|
||||
<group>
|
||||
|
||||
Reference in New Issue
Block a user