Files
Odoo-Modules/fusion_plating/fusion_plating/views/fp_bath_views.xml
gsinghpal b85642816f feat(configurator): menu reorder, currency/unit display polish, line description templates
Three UX improvements:

1. Sales menu reordered — New Quote (seq 1) is now the first entry,
   followed by New Direct Order (5), Quotations (10), Sale Orders (20).
   "New Quote" moved out of Configurator submenu into Sales so both
   quote-creation paths live side-by-side.

2. Currency + unit display audit:
   - fp.customer.price.list.unit_price flipped from Float to Monetary
     with currency_field='currency_id' — list view now shows $ symbol
     and a Total sum row
   - fp.direct.order.wizard.unit_price flipped to Monetary, added
     currency_id field and computed line_subtotal ($)
   - % suffix appended to deposit_percent and progress_initial_percent
     in the wizard
   - Unit suffixes added where missing: bake_window.quantity (pcs),
     window_hours (h), bake_temp (°F), bake_duration_hours (h);
     bath.volume (L), bath.mto_count (turnovers); tank.volume shows
     volume_uom inline

3. Saved line descriptions (new feature):
   - New model fp.sale.description.template with name, description,
     tag (standard/masking/rework/aerospace/nuclear/packaging/other),
     optional coating_config_id and partner_id, usage_count bumped
     on each use
   - List + form + search views; new "Line Descriptions" menu under
     Configurator
   - 8 starter templates seeded (noupdate=1): ENP Standard/Aerospace/
     Nuclear, masking variants, rework, packaging, delicate handling
   - Direct Order Wizard gets a template picker (searchable Many2one)
     + editable paragraph; picking a template copies text to the
     editable field, user tweaks freely, tweaked text lands on the
     SO line as "<header>\n\n<description>"
   - Auto-suggests template on coating+partner match if nothing
     picked yet

Smoke-tested end-to-end: picked aerospace template, tweaked text,
confirmed wizard → SO S00030 has full description on line, usage
counter bumped from 0 to 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 18:43:58 -04:00

216 lines
11 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<record id="view_fp_bath_list" model="ir.ui.view">
<field name="name">fp.bath.list</field>
<field name="model">fusion.plating.bath</field>
<field name="arch" type="xml">
<list string="Baths" decoration-muted="state == 'dumped'"
decoration-warning="last_log_status == 'warning'"
decoration-danger="last_log_status == 'out_of_spec'">
<field name="name"/>
<field name="tank_id"/>
<field name="process_type_id"/>
<field name="facility_id" groups="base.group_multi_company"/>
<field name="state" widget="badge"
decoration-success="state == 'operational'"
decoration-info="state == 'new'"
decoration-warning="state == 'under_review'"
decoration-danger="state == 'dump_scheduled'"
decoration-muted="state == 'dumped'"/>
<field name="mto_count"/>
<field name="last_log_date"/>
<field name="last_log_status" widget="badge"
decoration-success="last_log_status == 'ok'"
decoration-warning="last_log_status == 'warning'"
decoration-danger="last_log_status == 'out_of_spec'"/>
<field name="makeup_date" optional="hide"/>
</list>
</field>
</record>
<record id="view_fp_bath_form" model="ir.ui.view">
<field name="name">fp.bath.form</field>
<field name="model">fusion.plating.bath</field>
<field name="arch" type="xml">
<form string="Bath">
<header>
<button name="action_make_operational" string="Set Operational" type="object"
class="oe_highlight" invisible="state != 'new'"/>
<button name="action_mark_under_review" string="Flag for Review" type="object"
invisible="state not in ('operational',)"/>
<button name="action_schedule_dump" string="Schedule Dump" type="object"
invisible="state not in ('operational','under_review')"/>
<button name="action_dump" string="Dump" type="object"
invisible="state != 'dump_scheduled'"/>
<field name="state" widget="statusbar"
statusbar_visible="new,operational,under_review,dump_scheduled,dumped"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="%(action_fp_bath_log)d" type="action" class="oe_stat_button" icon="fa-flask"
context="{'search_default_bath_id': id}">
<field name="log_count" widget="statinfo" string="Logs"/>
</button>
</div>
<div class="oe_title">
<label for="name"/>
<h1><field name="name" readonly="state != 'new'"/></h1>
</div>
<group>
<group>
<field name="tank_id"/>
<field name="process_type_id"/>
<field name="facility_id" readonly="1"/>
<label for="volume"/>
<div class="o_row">
<field name="volume" nolabel="1" class="oe_inline"/>
<span class="ms-1">L</span>
</div>
</group>
<group>
<field name="makeup_date"/>
<field name="makeup_by_id"/>
<label for="mto_count"/>
<div class="o_row">
<field name="mto_count" nolabel="1" readonly="1" class="oe_inline"/>
<span class="ms-1">turnovers</span>
</div>
<field name="last_log_date" readonly="1"/>
<field name="last_log_status" readonly="1" widget="badge"
decoration-success="last_log_status == 'ok'"
decoration-warning="last_log_status == 'warning'"
decoration-danger="last_log_status == 'out_of_spec'"/>
</group>
</group>
<notebook>
<page string="Target Ranges">
<field name="target_line_ids">
<list editable="bottom">
<field name="sequence" widget="handle"/>
<field name="parameter_id"/>
<field name="target_min"/>
<field name="target_max"/>
<field name="uom"/>
</list>
</field>
<p class="text-muted mt-2">
Per-bath target overrides. If empty, the parameter's default range is used.
</p>
</page>
<page string="Chemistry Logs">
<field name="log_ids" readonly="1">
<list decoration-success="status == 'ok'"
decoration-warning="status == 'warning'"
decoration-danger="status == 'out_of_spec'">
<field name="name"/>
<field name="log_date"/>
<field name="operator_id"/>
<field name="shift"/>
<field name="status"/>
</list>
</field>
</page>
<page string="Notes">
<field name="notes"/>
</page>
<page string="Dump" invisible="state not in ('dump_scheduled','dumped')">
<group>
<field name="dump_scheduled_date"/>
<field name="dumped_date"/>
<field name="dump_reason"/>
</group>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<record id="view_fp_bath_kanban" model="ir.ui.view">
<field name="name">fp.bath.kanban</field>
<field name="model">fusion.plating.bath</field>
<field name="arch" type="xml">
<kanban default_group_by="state" class="o_fp_bath_kanban">
<field name="id"/>
<field name="name"/>
<field name="tank_id"/>
<field name="process_type_id"/>
<field name="state"/>
<field name="last_log_status"/>
<field name="mto_count"/>
<field name="status_color"/>
<templates>
<t t-name="card">
<div class="o_fp_card o_fp_bath_card"
t-att-data-log-status="record.last_log_status.raw_value">
<div class="d-flex justify-content-between align-items-start">
<strong class="o_fp_card_title"><field name="name"/></strong>
<span class="o_fp_health_dot"
t-att-data-status="record.last_log_status.raw_value or 'ok'"/>
</div>
<div class="small text-muted">
<field name="process_type_id"/>
</div>
<div class="small"><i class="fa fa-flask me-1 text-muted"/><field name="tank_id"/></div>
<div class="d-flex justify-content-between mt-2 small">
<span class="text-muted">MTO</span>
<span class="fw-bold"><field name="mto_count"/></span>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="view_fp_bath_search" model="ir.ui.view">
<field name="name">fp.bath.search</field>
<field name="model">fusion.plating.bath</field>
<field name="arch" type="xml">
<search string="Baths">
<field name="name"/>
<field name="tank_id"/>
<field name="process_type_id"/>
<field name="facility_id"/>
<separator/>
<filter string="Pre-Treatments" name="family_pre"
domain="[('process_type_id.process_family', '=', 'pre_treatment')]"/>
<filter string="Plating Baths" name="family_plating"
domain="[('process_type_id.process_family', '=', 'plating')]"/>
<filter string="Post-Treatments" name="family_post"
domain="[('process_type_id.process_family', '=', 'post_treatment')]"/>
<filter string="Strip Baths" name="family_strip"
domain="[('process_type_id.process_family', '=', 'strip')]"/>
<separator/>
<filter string="Operational" name="operational" domain="[('state','=','operational')]"/>
<filter string="Under Review" name="review" domain="[('state','=','under_review')]"/>
<filter string="Out of Spec" name="oos" domain="[('last_log_status','=','out_of_spec')]"/>
<filter string="Warning" name="warn" domain="[('last_log_status','=','warning')]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group>
<filter string="Facility" name="group_facility" context="{'group_by':'facility_id'}"/>
<filter string="Process" name="group_process" context="{'group_by':'process_type_id'}"/>
<filter string="Tank" name="group_tank" context="{'group_by':'tank_id'}"/>
<filter string="Status" name="group_state" context="{'group_by':'state'}"/>
</group>
</search>
</field>
</record>
<record id="action_fp_bath" model="ir.actions.act_window">
<field name="name">Baths</field>
<field name="res_model">fusion.plating.bath</field>
<field name="view_mode">kanban,list,form</field>
<field name="search_view_id" ref="view_fp_bath_search"/>
</record>
</odoo>