This commit is contained in:
gsinghpal
2026-04-30 00:21:08 -04:00
parent f990f29019
commit c5d21e0519
10 changed files with 105 additions and 44 deletions

View File

@@ -0,0 +1,21 @@
step = env['fp.job.step'].search([('job_id.name', '=', 'WH/JOB/00337')], limit=1, order='sequence')
print('Step:', step.name)
# Simulate the EXACT OWL get_views call for this action
result = step._fp_open_input_wizard(advance_after=True)
print('view_id:', result.get('view_id'))
print('views:', result.get('views'))
# Now invoke get_views with this view_id explicitly
view_id = result.get('view_id')
W = env['fp.job.step.input.wizard']
gv = W.get_views([(view_id, 'form')])
print('models served:')
for mname, minfo in gv['models'].items():
print(' ', mname, '->', list((minfo.get('fields') or {}).keys())[:10])
# Check arch
arch = gv['views']['form']['arch']
print('arch has <list>?', '<list' in arch)
print('arch has <field name="name">?', '<field name="name"' in arch)
print('arch has <field name="line_ids">', '<field name="line_ids"' in arch)

View File

@@ -0,0 +1,12 @@
# Simulate the Finish & Next button to see the exact action returned
step = env['fp.job.step'].search([('job_id.name', '=', 'WH/JOB/00337')], limit=1, order='sequence')
print('Step:', step.name, 'id:', step.id, 'state:', step.state)
result = step._fp_open_input_wizard(advance_after=True)
print('Action returned:')
print(' type:', result.get('type'))
print(' res_model:', result.get('res_model'))
print(' view_mode:', result.get('view_mode'))
print(' view_id:', result.get('view_id'))
print(' views:', result.get('views'))
print(' target:', result.get('target'))
print(' context (keys):', list(result.get('context', {}).keys()))

View File

@@ -0,0 +1,7 @@
import re
v = env['ir.ui.view'].search([('name', '=', 'fp.job.step.input.wizard.form')])
print('view id:', v.id)
print('xml_id:', v.xml_id)
print('arch length:', len(v.arch or ''))
for i, m in enumerate(re.finditer(r'<field\s+name="([^"]+)"', v.arch or '')):
print(' field[%d]: %s' % (i, m.group(1)))

View File

@@ -0,0 +1,15 @@
# Simulate what the server returns to OWL via load_views.
W = env['fp.job.step.input.wizard']
result = W.with_context(default_step_id=1).get_views([(False, 'form')])
print('=== views key ===')
print(' keys:', list(result.get('views', {}).keys()))
print('=== models key ===')
print(' models keys:', list(result.get('models', {}).keys()))
for mname, minfo in (result.get('models') or {}).items():
print(' model:', mname, '-- has name field:', 'name' in (minfo.get('fields') or {}))
fields_keys = list((minfo.get('fields') or {}).keys())
print(' fields:', fields_keys[:30])
print('=== form arch ===')
arch = (result.get('views') or {}).get('form', {}).get('arch', '')
print('FULL ARCH LEN:', len(arch))
print(arch)

View File

@@ -3,7 +3,7 @@
# License OPL-1 (Odoo Proprietary License v1.0)
{
'name': 'Fusion Plating — Native Jobs',
'version': '19.0.8.14.2',
'version': '19.0.8.14.5',
'category': 'Manufacturing/Plating',
'summary': 'Native plating job model — replaces mrp.production / mrp.workorder bridge.',
'author': 'Nexa Systems Inc.',

View File

@@ -402,16 +402,24 @@ class FpJobStep(models.Model):
is True, the wizard's Save button finishes the step and starts
the next one as a single atomic flow."""
self.ensure_one()
action = self.env['ir.actions.act_window']._for_xml_id(
'fusion_plating_jobs.action_fp_job_step_input_wizard'
view = self.env.ref(
'fusion_plating_jobs.view_fp_job_step_input_wizard_form_v2'
)
action['context'] = {
**dict(self.env.context),
'default_step_id': self.id,
'active_id': self.id,
'fp_advance_after_save': advance_after,
return {
'type': 'ir.actions.act_window',
'res_model': 'fp.job.step.input.wizard',
'view_mode': 'form',
'view_id': view.id,
'views': [(view.id, 'form')],
'target': 'new',
'name': _('Record Inputs — %s') % self.name,
'context': {
**dict(self.env.context),
'default_step_id': self.id,
'active_id': self.id,
'fp_advance_after_save': advance_after,
},
}
return action
# NB: action_open_input_wizard is defined further down (line ~829)
# — that one stays as the per-row "Record" button entry-point.

View File

@@ -20,6 +20,30 @@ $fp-ql-panel: var(--fp-card-bg, #{$_fp_ql_panel_hex});
$fp-ql-border: var(--fp-border-color, #{$_fp_ql_border_hex});
$fp-ql-text: var(--fp-text, #{$_fp_ql_text_hex});
// Compress the info-button column on the embedded step list. Odoo
// gives button columns a generous min-width by default, leaving an
// awkward gap between the icon and the Name column. Belt + braces:
// the <button width="30"/> attribute does most of the work; these
// rules tighten the inner padding so the icon hugs the cell edges.
.o_list_view td:has(> button.o_fp_step_info_btn),
.o_list_view td:has(> .o_list_button_cell button.o_fp_step_info_btn) {
width: 32px !important;
max-width: 32px !important;
min-width: 32px !important;
padding-left: 2px !important;
padding-right: 2px !important;
}
button.o_fp_step_info_btn {
padding: 2px 6px !important;
margin: 0 !important;
min-width: 0 !important;
line-height: 1 !important;
}
button.o_fp_step_info_btn .fa,
button.o_fp_step_info_btn i {
margin: 0 !important;
}
// Container around the rich-text instructions inside the quick-look
// modal. Bordered + scrollable + readable in both light and dark modes.
.o_fp_quick_look_instructions {

View File

@@ -86,7 +86,8 @@
<button name="action_open_quick_look" type="object"
title="View step details"
icon="fa-info-circle"
class="btn-link"/>
width="30"
class="btn-link o_fp_step_info_btn"/>
<field name="name"/>
<field name="work_centre_id" optional="show"/>
<field name="tank_id" optional="hide"/>

View File

@@ -59,31 +59,11 @@ class FpJobStepInputWizard(models.TransientModel):
job_id = fields.Many2one(
related='step_id.job_id', string='Job', store=False, readonly=True,
)
# Sub 12d — surface the office-authored instructions to the operator
# at the exact moment they're recording values. Sourced from the
# recipe node's description (rich-text); empty when the recipe
# author left it blank.
instructions = fields.Html(
string='Operator Instructions',
compute='_compute_instructions',
readonly=True,
)
has_instructions = fields.Boolean(
compute='_compute_instructions',
)
line_ids = fields.One2many(
'fp.job.step.input.wizard.line', 'wizard_id',
string='Inputs',
)
@api.depends('step_id', 'step_id.recipe_node_id', 'step_id.recipe_node_id.description')
def _compute_instructions(self):
for rec in self:
node = rec.step_id.recipe_node_id if rec.step_id else False
html = (node and node.description) or ''
rec.instructions = html
rec.has_instructions = bool(html and html.strip())
@api.model
def default_get(self, fields_list):
defaults = super().default_get(fields_list)

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="view_fp_job_step_input_wizard_form" model="ir.ui.view">
<field name="name">fp.job.step.input.wizard.form</field>
<record id="view_fp_job_step_input_wizard_form_v2" model="ir.ui.view">
<field name="name">fp.job.step.input.wizard.form.v2</field>
<field name="model">fp.job.step.input.wizard</field>
<field name="arch" type="xml">
<form string="Record Step Inputs">
@@ -11,17 +11,6 @@
<field name="step_id" readonly="1"/>
<field name="job_id" readonly="1"/>
</group>
<field name="has_instructions" invisible="1"/>
<div class="alert alert-info"
role="alert"
invisible="not has_instructions"
style="margin-bottom: 12px;">
<h4 style="margin-top: 0;">
<i class="fa fa-info-circle"/>
Instructions for this step
</h4>
<field name="instructions" nolabel="1" readonly="1"/>
</div>
<separator string="Measurements"/>
<p class="text-muted" invisible="line_ids">
Click <strong>Add a line</strong> to record one or
@@ -39,13 +28,16 @@
<field name="name"
string="Measurement"
readonly="is_authored"
width="220"
placeholder="e.g. Oven Temp, Bath Reading, Operator Initials"/>
<field name="input_type"
string="Type"
readonly="is_authored"/>
readonly="is_authored"
width="120"/>
<field name="target_unit"
string="Unit"
readonly="is_authored"
width="100"
optional="show"/>
<field name="value_number"
string="Number"
@@ -105,6 +97,7 @@
<field name="name">Record Step Inputs</field>
<field name="res_model">fp.job.step.input.wizard</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_fp_job_step_input_wizard_form_v2"/>
<field name="target">new</field>
</record>