Commit Graph

66 Commits

Author SHA1 Message Date
gsinghpal
d1fc3d8720 fix(express): show Tax on totals + add tooling as real SO line
Three related fixes on the Express Orders totals card:

1. Totals card now breaks out Subtotal / Tax / Tooling Charge /
   Grand Total. Previously the "Subtotal" and "Grand Total" rows
   both read from total_amount (same value rendered twice) and no
   tax was shown at all. Customers on a fiscal position-mapped
   tax rate (Ontario HST, etc.) had their taxes silently dropped
   from the preview.

2. tooling_charge now feeds the Grand Total. The total_amount
   compute previously summed line subtotals only. Added a real
   SO line for the tooling charge in action_create_order so the
   eventual sale.order.amount_total matches the preview AND the
   invoice carries a "Tooling Charge" line item.

3. tax_ids is now visible as an optional column on the lines
   list. Operator can see + override the auto-applied tax per
   line. Default still comes from FP-SERVICE product mapped
   through partner.property_account_position_id (fiscal position).

New compute fields on fp.direct.order.wizard:
  - total_subtotal (sum of line.qty * line.unit_price, pre-tax)
  - total_tax (sum of line + tooling taxes via compute_all)
  - total_amount (subtotal + tax + tooling — was just subtotal)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 10:33:31 -04:00
gsinghpal
416daa36d2 feat(configurator): pack right column alongside tall PO block — no dead space
Previous tightening removed the row-span but reintroduced a worse
problem: the tall PO block (with PO Pending + Expected By + chase
warning visible = ~250px) had only 2 small cells next to it
(Customer Job # / Job Sorting). 200px+ of vertical air below them
before row 3 started.

Layout now:
- Row 1: Customer (1-2) + Delivery Address (3-4)
- Rows 2-5 left: PO Block spans 4 grid rows (cols 1-2)
- Rows 2-5 right: 4 PAIRS of fields fill cols 3-4 in DOM order:
    Row 2: Customer Job # + Job Sorting
    Row 3: Material/Process + Lead Time
    Row 4: Payment Terms + Delivery Method
    Row 5: Pricelist + Quote Validity
- Row 6: Blanket SO + Invoice Strategy + conditional Deposit % / Progress %
  (full 4-col width, kicks in after the PO block ends)

CSS Grid auto-flow places the right-side cells in the open positions
next to the row-span-4 PO block. Each grid row auto-sizes to the max
of the cells in that row (PO block top portion or the right pair),
so PO block height naturally aligns with the 4 right rows — no dead
air on either side.
2026-05-27 00:40:06 -04:00
gsinghpal
b7f280141f feat(configurator): tighten header spacing — remove row-span, smaller gaps
User reported too much vertical air between fields. Two changes:

1. Removed grid-row: span 2 from the PO block. The row-span pattern
   stretched each grid row to half the PO block's height (~125px each),
   leaving empty space below Customer Job # / Job Sorting on row 2 and
   below Material/Lead Time on row 3.

   New layout:
   - Row 1: Customer (1-2) + Delivery Address (3-4)
   - Row 2: PO Block (1-2, naturally tall) + Customer Job # + Job Sorting
   - Row 3: Material/Process + Lead Time + Payment Terms + Delivery Method
   - Row 4: Pricelist + Quote Validity + Blanket SO + Invoice Strategy
   - Row 5 (conditional): Deposit % or Progress % (when invoice strategy uses them)

   PO block forces row 2 to be tall but cols 3-4 just sit at top — that
   was the original mockup pattern, and it's denser overall because
   rows 3+ are all the standard short height.

2. Tightened spacing in SCSS:
   - Grid row gap 14px → 6px
   - Cell label margin 0 (was 2px)
   - Input padding 5px → 2px vertical, min-height 30px → 24px
   - PO block padding 10px → 6/12/8px
   - PO row gap 2px padding → 0 (min-height 28px keeps clickable target)
   - PO chase text 11px → 10px, tighter line-height
2026-05-27 00:34:46 -04:00
gsinghpal
9c7b7c54e5 feat(configurator): Part cell rows 2-3 now editable — type to save
Customer feedback: rows 2 (description) and 3 (serials) in the Part
cell rendered as read-only spans. User wanted to edit directly.

New writable computed fields on fp.direct.order.line:
- part_name_editable: compute reads part_catalog_id.name, inverse
  writes back to part.name on the linked catalog record
- serials_text: compute joins serial_ids names with commas; inverse
  parses the typed string and find-or-creates fp.serial records,
  updates the line's serial_ids M2M

Removed the redundant rev separator (display_name already includes
'(Rev X)' so showing it twice was clutter). Rev edits happen by
editing the part record directly via the OPEN button.

OWL widget templates updated:
- Row 2: <input> bound to part_name_editable, t-on-change saves
- Row 3: <input> bound to serials_text, t-on-change parses + saves

SCSS:
- Row 2 input: italic, transparent border, focus tints background yellow
- Row 3 input: small grey text, comma-separated friendly placeholder
- Both disabled-look when no part is picked

Both inputs trigger the inverse method on blur. The G4 sync chain
takes over from there to push line.line_description etc. back to
the part as before — so editing in the line keeps the part defaults
fresh for future orders.
2026-05-26 23:26:58 -04:00
gsinghpal
48c2a4bfe1 feat(configurator): 19.0.22.1.0 — recipe-driven orders + auto-sync to part
Four customer-feedback fixes (G1-G4):

G1 — Part cell display redundancy. fp.part.catalog.display_name was
showing 'PART (Rev X) — Name' which duplicated with my Part cell widget's
separately-rendered revision + name rows. Added @api.depends_context
('fp_express_part_picker') to _compute_display_name: when the context
flag is True, display_name returns JUST the part_number. The Express
view passes the flag on the part_catalog_id field, so the picker shows
'9876699373' and the widget's row 2/3 show the rev + name.

G2 — Material/Process Tag is now the order's RECIPE, not a free-text
shop tag. Converted material_process from Char to Many2One(fusion.
plating.process.node) with domain [('node_type','=','recipe')] on both
fp.direct.order.wizard AND sale.order. Pre-migration (19.0.22.1.0/
pre-migrate.py) drops the old VARCHAR column so Odoo recreates as
INTEGER FK. Per dev-stage policy, old tag data is dropped.

G3 — Auto-apply order recipe to every line. New onchange
_onchange_material_process_apply_to_lines on the wizard: when the
header recipe is picked / changed, propagate to every line's
process_variant_id (unless the line has an explicit per-line override
that doesn't match the previous header value).

Plus an override on fp.direct.order.line.create that seeds new lines'
process_variant_id from wizard.material_process. So a newly-added
line auto-inherits the order's recipe.

G4 — Auto-sync line edits back to the part catalog. New
_fp_sync_to_part method called from create() + write() on
fp.direct.order.line. Tracked fields:
- line_description     → part.default_specification_text
- bake_instructions    → part.default_bake_instructions
- thickness_range      → part.x_fc_default_thickness_range
- masking_enabled      → part.default_masking_enabled
- process_variant_id   → part.default_process_variant_id

Future orders for the same part will auto-pull these updated defaults
via the existing _onchange_part_default_thickness chain. Last-write-
wins semantics across concurrent edits (acceptable per dev-stage).
2026-05-26 23:20:27 -04:00
gsinghpal
4c5ee6143c feat(configurator): reorganize header — PO block spans 2 grid rows, fill the right side
Wasted-space audit revealed:
1. PO Block occupied a wide 2-col span but its inner inputs didn't
   fill the available width (130px label column + narrow input area)
2. Customer Job # + Job Sorting placed in row 2 cols 3-4 next to the
   tall PO block left empty vertical space below them
3. Row 2 col 3-4 was sparse because the PO block forced row 2 to be tall

Reorganized:
- PO Block now spans 2 grid ROWS (.row-span-2 class → grid-row: span 2)
- Customer Job # / Job Sorting flow into row 2 cols 3-4 (alongside PO top)
- Material/Process Tag / Lead Time flow into row 3 cols 3-4 (alongside
  PO bottom) — filling the previously-empty space next to the PO block
- Row 4 (after PO ends): Payment Terms / Delivery Method / Pricelist /
  Quote Validity — full 4-col width back
- Row 5: Blanket Sales Order + Invoice Strategy + conditional Deposit % /
  Progress Initial % (only show when relevant invoice strategy picked)

Inside the PO block:
- Label column tightened 130px → 110px so the input takes more width
- Inputs + Many2One wrappers now have width: 100% propagated, so PO #
  and Expected By inputs fill the available row width
- Upload button restyled with the accent colour (was the green default)

Net effect: same field count but tighter packing, no empty vertical
or horizontal space next to the PO block.
2026-05-26 22:54:35 -04:00
gsinghpal
faffdca592 fix(configurator): proper column widths via arch + show blanket SO checkbox
Root cause for column widths: Odoo 19's column_width_hook.js dynamically
sets inline widths on every cell at render time, overriding any CSS
width on td/th selectors. Confirmed by reading the hook source on
entech: 'A width can also be hardcoded in the arch (width="60px").'

Fix: set width='Npx' as an ARCH ATTRIBUTE on each <field> in the line
list:
- Part Number 230px, Line Job # 80px, Thickness 100px, Mask 55px,
  Bake 120px, Qty 55px, Price 80px, Subtotal 90px, Action stack 60px
- Specification + Internal Notes get NO width → take remaining flex
  space (responsive: layout adapts to viewport)

Root cause for missing checkbox: my SCSS underline-style override
selected ALL .o_field_widget input including type=checkbox, rendering
checkboxes as 30px-tall full-width transparent text inputs.

Fix: exclude type=checkbox/radio/file from the underline rule, and
add explicit rendering for type=checkbox (18px square, accent-coloured)
inside .o_fp_xpr_cell. The Blanket Sales Order checkbox + the inline
Block partial shipments checkbox are now both visible.
2026-05-26 22:48:59 -04:00
gsinghpal
15e25ca50b feat(configurator): Express form polish — 4 fixes per user review
1. Blanket Sales Order — match legacy field shape. Renamed label from
   'Blanket SO' to 'Blanket Sales Order' (matches legacy view), removed
   the boolean_toggle widget (defaults to checkbox), and added the
   sibling 'block_partial_shipments' field inline (only visible when
   blanket is checked, with 'Block partial shipments' helper text).

2. Column widths — give roomier columns where data needs space, tighten
   numeric columns. Part Number 230px, Specification min 220px,
   Internal Notes min 140px, Qty 60px, Price 80px, Subtotal 90px,
   Mask 55px, Bake 130px, Action stack 60px.

3. Stacked DWG / OPEN buttons — new OWL widget FpExpressActionBtns
   (express_action_btns.js + .xml) renders both buttons vertically in
   ONE column to save horizontal space. Widget binds to a new
   action_btns_anchor field (related from part_catalog_id) on the
   line. Each button shows tooltip + disabled state when no part is
   picked; DWG triggers the native file picker, OPEN navigates to the
   part record.

4. Field activation — clicking the cell anywhere now focuses the
   input, not just clicking the label. Achieved via:
   - cursor: text on .o_fp_xpr_cell
   - cursor: pointer on labels
   - min-height: 30px on all inputs (larger click target)
   - width: 100% propagated through Many2One wrappers (.o-dropdown,
     .o-autocomplete) so the input genuinely fills the cell
   - box-sizing: border-box so widths are predictable
   - Background tint on focus for visual feedback
2026-05-26 22:35:00 -04:00
gsinghpal
0f2ed5cc16 feat(configurator): OWL widgets + Express form polish to match mockup
NEW OWL widgets:
- FpExpressPartCell (static/src/js/express_part_cell.js + .xml) — multi-row
  Part cell. Wraps Many2OneField for the part picker (row 1: part# / rev,
  bold). Below it: row 2 part description (italic muted), row 3 serial #s
  joined + '+ bulk' button that triggers the existing bulk-add wizard.
- FpExpressBakePill (static/src/js/express_bake_pill.js + .xml) — click-
  to-edit Bake pill. Renders amber pill when set, italic muted 'no bake'
  when empty. Click swaps to inline textarea + Save / Clear / Cancel.

NEW fields:
- fp.direct.order.line.part_number_display / part_revision_display /
  part_name_display (related Char from fp.part.catalog) — fed to the
  Part cell widget so it can render multi-row without RPC.
- fp.direct.order.wizard.tooling_charge (Monetary) — surfaced in the
  Totals card on the Express form.
- fp.direct.order.wizard.po_status (computed Selection
  received/pending/missing) — drives the PO Block status badge.
- sale.order.x_fc_tooling_charge (Monetary) — receives wizard.tooling_charge
  at confirm.

View updates (fp_express_order_views.xml):
- PO block header now shows the PO status pill (green Received,
  amber Pending, red Missing)
- Order Lines legend bar (Mask / Bake pill / DWG / OPEN explainers)
- Part Number column uses widget='fp_express_part_cell' — single cell
  with 3 internal rows
- Bake column uses widget='fp_express_bake_pill' — interactive pill
- Totals card now has Subtotal / Tooling Charge / Total Lines / Total
  Quantity / Grand Total + currency pill

SCSS adds:
- Multi-row part cell styles (internal borders, bold/italic/muted rows)
- Bake pill (has-bake amber, no-bake italic muted) + inline editor
- Legend bar (section background, gap-spaced explainer chips)
- PO status pill colour scheme
- Bulk button styling

Wizard's action_create_order now carries tooling_charge to the SO at
confirm so it persists on the resulting sale.order.
2026-05-26 22:13:54 -04:00
gsinghpal
1d674e587c feat(configurator): Express form CSS-Grid rebuild — match mockup pixel layout
Previous rebuild used Odoo's <group col='4'> which renders as an HTML
table — colspan+nesting broke into a vertical stack. Replaced entirely
with raw <div> + CSS Grid (display: grid; grid-template-columns:
repeat(4, 1fr)) so the header layout matches the mockup exactly:

- Row 1: Customer (span 2) + Shipping Address (span 2)
- Row 2: PO block (span 2, accent-bordered card with PO#/PDF/Pending
  toggle/Expected date stacked + chase warning) + Customer Job # + Job Sorting
- Row 3: Material/Process Tag + Lead Time (inline X to Y) + Payment
  Terms + Delivery Method
- Row 4: Blanket SO + Currency/Pricelist + Quote Validity + Invoice Strategy

Footer also rebuilt as CSS Grid (1fr 320px) — Notes/Terms cards
stacked in the left column, Totals card with Grand Total + currency
pill in the right column. Each card has a title + subtitle + body
matching the mockup's card chrome.

SCSS overrides Odoo's default field chrome inside .o_fp_xpr_cell so
inputs render with the mockup's underline style (no Bootstrap form-
control border, just a 1px bottom-border that thickens on focus).
2026-05-26 21:51:02 -04:00
gsinghpal
713ba17e37 feat(configurator): Express form layout rebuild — match mockup
Restructures the Express form to align with the brainstorming mockup:

Header (4-column grid via <group col='4'>):
- Row 1: Customer (colspan=2) + Shipping Address (colspan=2)
- Row 2: Consolidated PO Block (colspan=2 with PO#/PDF/Pending toggle/
  Expected date stacked + chase warning inline) + Customer Job # + Job Sorting
- Row 3: Material/Process Tag + Lead Time (X to Y inline) + Payment Terms + Delivery Method
- Row 4: Blanket SO + Currency/Pricelist + Quote Validity + Invoice Strategy

Lines: 13 inline columns including the Express-specific Line Job #,
masking toggle, bake text, plus per-line action buttons (DWG, OPEN,
+ bulk) wired to the Phase B helpers.

Footer: side-by-side cards — Notes + Terms stacked in the left card,
Totals card on the right with Total Lines / Total Qty / Grand Total
+ currency pill.

SCSS adds:
- PO block: accent-bordered card-within-card
- Lines: tight spreadsheet borders, hover row highlight
- Bake column: amber pill style, italic 'no bake' for empty
- Customer Line Job #: bold, uppercase, narrow column
- Inline action buttons: small uppercase bordered chips
- Footer cards with prominent Grand Total + currency pill

OWL multi-row Part cell (FpExpressPartCell) and click-to-edit Bake
pill (FpExpressBakePill) are still deferred — they need real OWL
components, separate pass.
2026-05-26 21:35:54 -04:00
gsinghpal
43abb8ef25 feat(configurator): C1+C3 - pricelist currency picker + Express SCSS (light + dark)
C1: product.pricelist._compute_display_name override gated by the
'fp_express_currency_picker' context flag (set on the Express form's
pricelist_id field). When active, prefixes the dropdown label with
the currency code: 'CAD — Public Pricelist (CAD)'. Elsewhere the
standard display name is unchanged.

C3: SCSS tokens + base styles for the Express form. Tokens use the
compile-time @if $o-webclient-color-scheme branch per the project's
'Dark Mode' rule — same SCSS compiles into both bundles with different
hex values. Token vars wrapped in CSS custom properties so downstream
modules can override for per-shop branding without recompiling.
Base styles: spreadsheet-feel table borders, bake-cell inset-pill,
customer line ref bold/uppercase, accent section markers.
2026-05-26 21:25:59 -04:00
gsinghpal
01df46f79f feat(configurator): C6 - Express Orders form view + menu (v1, stock widgets)
Spreadsheet-style flat entry view on the existing fp.direct.order.wizard
model. Renders:
- Customer + Shipping prominent (row 1)
- PO block (PO# + attachment + Pending toggle + Expected date)
- Scheduling/Lead Time + Pricing/Pricelist (row 2)
- Order Lines spreadsheet with: Part #, Specification, Line Job #,
  Thickness, Mask toggle, Bake text, Internal Notes, Serials, Qty,
  Price, Subtotal, Process/Recipe (optional-show)
- Notes + Terms split (internal vs customer-facing)
- View-switch buttons to bounce between Express and Legacy on a draft

New menu: Plating > Sales > '+ New Express Order' (sequence 3).
Same DB rows as legacy view (view_source='express' for routing).

v1 deferments: OWL FpExpressPartCell (multi-row part cell), OWL
FpExpressBakePill (click-to-edit), DWG/OPEN/+bulk inline buttons,
custom SCSS, quick-create part view, pricelist display_name override.
These come in later iterations.
2026-05-26 21:03:47 -04:00
gsinghpal
7bcbcb4008 fix(plating-perms): deploy-time cascade fixes from entech I3
5 fixes discovered during the live deploy to entech LXC 111:

1. pre-migrate.py to rename old configurator's 'Shop Manager' group BEFORE
   new core 'Shop Manager v2' XML loads (cross-module name collision on
   res_groups_name_uniq).

2. res_company_views.xml: dropped ref() inside <field domain=> attribute
   (Odoo 19 view validator interprets it as a field name).

3. sale_order_views.xml: replaced 3 separate xpaths for amount_total /
   amount_untaxed / amount_tax with a single xpath on tax_totals widget
   (Odoo 19 sale.view_order_form uses one widget instead of separate fields).

4. fp_cert_security.xml: certificate_type field, not cert_type. FAIR is a
   separate model so the rule only restricts cert_type='nadcap_cert' now.

5. fp_certificate_views.xml + fp_capa_views.xml + fp_customer_spec_views.xml:
   stripped user_has_groups() from invisible= / readonly= attrs (Odoo 19
   view validator interprets as field name). Model-layer ACLs and ir.rules
   already enforce the same restrictions.

Also fixed res.groups.users -> user_ids in fp_migration.py (Odoo 19 rename,
caught when manually invoking _fp_notify_owners post-deploy).

CLAUDE.md updated with 4 new rules (13e cross-module name collisions,
13f ref() in domain, 13g tax_totals widget, 13h user_has_groups in attrs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 09:07:13 -04:00
gsinghpal
0047f49d2c fix(plating-perms): address final-reviewer critical + important issues
Pre-deploy fixes for Phase 1 permissions overhaul branch (catches by
final-reviewer subagent + main session).

CRITICAL FIXES:

C1: groups_id -> group_ids (Odoo 19 field rename). Affected ~30 sites
    across 4 model files, 1 view, 7 test files. Documented project
    gotcha (feedback_odoo19_groups_id_renamed.md) that the implementer
    subagents missed because they don't see user memory.

C2: action_fp_resolve_plating_landing server action now calls
    env['ir.actions.act_window'].sudo()._fp_resolve_landing_for_current_user()
    instead of the old inline priority chain. Phase E's role-based
    dispatch was previously dead code.

C3: New migrations/19.0.21.1.0/post-migrate.py triggers
    _fp_post_init_role_migration(env) on -u. post_init_hook only fires
    on INSTALL in Odoo 19, not UPGRADE -- so Phase H's preview creation
    wouldn't have auto-fired on entech without this script. Module
    version bumped to 19.0.21.1.0 to match the migration directory.

C4: Team kanban template rewritten for Odoo 19 (<t t-name='card'> with
    semantic <aside>/<main>) instead of legacy <t t-name='kanban-box'>.
    Previous template threw 'Missing card template' at render.

IMPORTANT FIXES:

I1: SO state=sent Confirm button (id='action_confirm') now also gated
    to group_fp_sales_manager. Previously only the state=draft button
    was gated; Sales Reps could send-and-confirm via the secondary path.

I2: Designated Officials picker domain uses all_group_ids (transitive)
    instead of group_ids (explicit only). Owner users now correctly
    appear as eligible CGP DO candidates via the implied_ids chain.

I3: test_menu_visibility.py compliance hub xmlid corrected to
    fusion_plating.menu_fp_compliance_hub (was
    fusion_plating_compliance.menu_fp_compliance_hub which doesn't exist
    -- the hub menu is defined in core's fp_menu.xml). Tests were
    silently skipTest-ing.

I4: _inverse_plating_role chatter audit reads old role from DB via SQL
    (bypasses cache) so 'old -> new' displays actual values, and
    short-circuits no-op writes.

I5: _FP_ROLE_MAPPING_RULES reordered: cgp_designated_official fires
    BEFORE admin/uid_1_or_2 so admin+DO users keep the capability_delta
    marker that triggers res.company.x_fc_cgp_designated_official_id
    auto-set during migration.

I6: _cron_purge_expired_migrations skips groups with active users
    instead of unlink-ing unconditionally. Defense against rollback
    safety being bypassed by manual role assignments post-migration.

CLAUDE.md updated with 3 new durable rules (13b kanban card template,
13c group_ids vs all_group_ids, 13d post_init_hook only on install).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 08:37:13 -04:00
gsinghpal
269f9984ef feat(plating-views): Layer 3 — field/button gates per role
Phase D Task D5 of permissions overhaul. Adds explicit groups= to
form-level elements so non-matching roles don't even SEE the buttons
they can't use:

- SO Confirm button → group_fp_sales_manager (Sales Rep sees the SO
  in draft but no Confirm button — matches model-level gate from Phase G)
- SO pricing fields (price_unit/subtotal/total/untaxed/tax) →
  group_fp_sales_rep (Technician/Shop Manager don't see pricing if
  they navigate to an SO)
- Partner Account Hold tab → group_fp_manager (was the fold-in
  group_fp_accounting; the audit-finding-11 _administrator typo lives
  in res_partner.py and is Phase G's fix)
- CAPA Close + all state-transition buttons → group_fp_quality_manager;
  edit fields use readonly="not user_has_groups(...)" so Manager
  retains read+comment per spec section 2.C
- Audit Start/Findings/Close buttons → group_fp_quality_manager
- AVL Approve/Suspend/Reinstate/Remove → group_fp_quality_manager
  (model uses Suspend+Remove instead of spec's literal 'Disqualify';
  both surfaces gated, semantics match)
- Customer Spec edit fields → readonly for non-QM (Manager keeps
  read access per spec; only inputs lock)
- FAIR Approve/Reject buttons → group_fp_quality_manager (Submit-
  for-Review and Reset stay open to whoever created the FAIR)
- Certificate Issue button — Strategy B chosen: single button hidden
  when cert_type=nadcap_cert AND user is not QM. Cleaner than splitting
  into two buttons; no separate action_sign exists on fp.certificate
  (Issue is the sign+publish action). FAIR lives in its own model;
  fp.certificate only has nadcap_cert as a special type. The ir.rule
  from Phase C enforces model-level writes independently.
- CGP form buttons (7 view files: ai, controlled_good, psa,
  receipt_shipment, registration, security_incident, visitor) →
  group_fp_quality_manager on every action button

Defense in depth: ir.rules and ACLs (from Phases B + C) already
restrict model access. These view gates are the UI layer that
matches.

Concerns:
- Spec line 192 names 'sale.order view — x_fc_account_hold_override'
  but no such field exists in the codebase. Closest practical match
  was the partner-side Account Hold management tab, which already had
  a group= attribute. Re-gated there; no SO-side field to gate.
- AVL model has no action_disqualify per spec; uses suspend+remove.
  Both gated to QM.
- fp.certificate has no action_sign (only action_issue). FAIR's
  approve/reject covers the FAIR side; nadcap-cert Issue covers the
  cert side via Strategy B.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 01:45:39 -04:00
gsinghpal
36cd4341a7 feat(plating-menu): Layer 1+2 — explicit groups on top-level menus + submenus
Phase D Tasks D1-D4 of permissions overhaul. Adds explicit groups=
attributes to:
- 9 top-level Plating menus (matrix per spec Section 2.E)
- Quality submenus: Audits, Customer Specs, AVL → QM-only
- Compliance hub child submenus (CGP, General, Safety, Aerospace,
  Nuclear) → QM-only
- Operations submenus: Maintenance, Move Log, Labor History → Shop
  Manager+; Replenishment Suggestions → Manager+

Replaces fragile inheritance + action-ACL-based visibility with
explicit per-menu gates. Now every role's menu tree is deterministic.

Also adds fusion_plating/tests/test_menu_visibility.py — per-role
matrix tests using ir.ui.menu.search_count with the test user.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 01:35:11 -04:00
gsinghpal
f661724c72 changes 2026-05-22 18:01:31 -04:00
gsinghpal
d127e19b45 changes 2026-05-21 21:00:10 -04:00
gsinghpal
b395600a1c changes 2026-05-21 05:18:32 -04:00
gsinghpal
d6d6249857 changes 2026-05-21 04:47:45 -04:00
gsinghpal
1314f4581d changes 2026-05-21 03:37:25 -04:00
gsinghpal
091f98e1f9 changes 2026-05-18 22:33:23 -04:00
gsinghpal
152ed86c3a feat(thickness): single Char range field — drop fp.recipe.thickness picker
Per client direction: every order is a thickness RANGE (e.g.
"0.0005-0.0008 mils" or "5-10 mils"), never a single value. The
old picker model (fp.recipe.thickness with a single 'value' Float)
was modelling the wrong concept and overcrowding the order entry
UI. Replaced with one free-text Char field that auto-fills from
last-used or part default.

DELETED entirely:
- fp.recipe.thickness model (file + view + ACL + manifest entry)
- recipe.thickness_option_ids One2many (the picker source)
- "Thickness Options" inline list on the recipe form
- sale.order.line.x_fc_thickness_id (M2O picker)
- account.move.line.x_fc_thickness_id
- fp.delivery.x_fc_thickness_id
- fp.direct.order.line.thickness_id

ADDED:
- sale.order.line.x_fc_thickness_range (Char) — operator types range
- account.move.line.x_fc_thickness_range — for invoice rendering
- fp.delivery.x_fc_thickness_range — for packing slip
- fp.direct.order.line.thickness_range — for the wizard
- fp.part.catalog.x_fc_default_thickness_range — part default

AUTO-FILL CHAIN (sale.order.line + wizard line):
1. Operator already typed → keep
2. Most recent SO line for (this part, this customer) with a
   non-empty thickness_range → copy that
3. part.x_fc_default_thickness_range → copy
4. Blank — operator types

Implemented as both an @api.onchange (interactive) AND a
create() override (programmatic — wizard, sale_mrp bridge,
imports). Same logic in both paths.

WIZARD push-to-defaults: when "Save as Default" toggle is ticked
on a wizard line, persist the line's thickness_range to
part.x_fc_default_thickness_range so future first-customer orders
get a sensible starting point.

REPORTS: customer_line_header.xml + report_fp_wo_sticker.xml now
print the Char range as-typed (no display_name lookup needed).

KEPT (admin documentation only — doesn't affect order entry):
- recipe.thickness_min, thickness_max, thickness_uom on the recipe
  root: documents the recipe's CAPABILITY range. No UI gate; just
  for spec authors to record what the chemistry can produce.

JOB GROUPING: fp.job auto-create groups SO lines by (recipe, part,
spec, thickness, serial). Updated to key on the thickness_range
Char (stripped) instead of the deleted thickness_id integer.

DB cleanup: --update=base ran on the upgrade, dropping the
fp_recipe_thickness table + the four x_fc_thickness_id columns.
Existing data was already nulled in earlier dev work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 08:54:40 -04:00
gsinghpal
1ed414c6fb chore(menu): retire Configurator top-level — fold survivors into Configuration hub
After Phase E removed Coating Config + Treatments + Customer Price List
+ Coating Thickness from the Configurator submenu, only 3 admin items
remained — not enough to justify a top-level menu just for an
estimator.

Re-homed:
- Pricing Rules                → Configuration → Pricing & Billing
                                  (sequence 40, joins Invoice Strategy
                                   Defaults + Account Holds)
- Materials                    → Configuration → Materials & Tanks
                                  (sequence 40, joins Bath Parameters,
                                   Replenishment Rules, Chemicals,
                                   Rack Tags, Calibration Equipment)
- Line Description Templates   → Configuration → Quality & Documents
                                  (sequence 90, joins Notification
                                   Templates — same "templates" pattern)

All three keep estimator visibility (group_fp_estimator) plus manager
access. Top-level menu count under "Plating" drops from 9 visible to 8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:52:53 -04:00
gsinghpal
d891002c84 feat(promote-customer-spec): Phase E — final removal of coating + treatment
DELETED entirely (model + view + ACL + data file + menu):
- fp.coating.config (configurator)
- fp.treatment (configurator + seeded data)
- fp.coating.thickness (configurator) — replaced by fp.recipe.thickness in Phase A
- fp.customer.price.list (configurator) — coating-keyed, no replacement

Field deletions:
- sale.order.x_fc_coating_config_id
- sale.order.line.x_fc_coating_config_id + x_fc_treatment_ids
- account.move.line.x_fc_coating_config_id
- fp.part.catalog.x_fc_default_coating_config_id + x_fc_default_treatment_ids
- fp.job.coating_config_id
- fp.pricing.rule.coating_config_id
- fp.quality.point.coating_config_ids
- fp.direct.order.line.coating_config_id + treatment_ids
- fp.sale.description.template.coating_config_id

Refactored:
- fp.quote.configurator.coating_config_id → recipe_id (now points at
  fusion.plating.process.node, the actual recipe). All compute, onchange,
  and matcher logic updated to use recipe directly. Quality inherit
  extends matcher with spec-tier scoring.
- fp.job._fp_create_certificates now reads spec from job.customer_spec_id
  and formats spec_reference as "code Rev rev". Same for thickness
  source — bake fields read from recipe_root (Phase A).
- fp.job.step.button_finish bake-window auto-spawn reads bake settings
  from recipe_root instead of coating.
- fp.certificate auto-fill spec_min_mils/max_mils from recipe (Phase A
  thickness fields) instead of coating.
- jobs/sale_order.py: job creation reads x_fc_customer_spec_id from
  line, drops coating refs and the legacy header-coating fallback.
- Wizards drop coating + treatment fields and refs.
- Configurator views drop x_fc_coating_config_id + x_fc_treatment_ids
  fields entirely. Quality inherits re-anchor on stable fields
  (x_fc_part_catalog_id, x_fc_internal_description, default_process_id,
  process_variant_id, substrate_material) so they keep working.
- Reports drop coating fallback elifs; print recipe / spec.
- Tablet payload drops coating_config_id from job.read fields.

Skipped (deferred to backlog):
- fusion_plating_bridge_mrp — module is uninstalled per Sub 11; source
  files retain coating refs but no runtime impact.
- fusion_plating_portal — circular dep (portal → quality → certs →
  portal). Customer-facing portal coating picker stays for now;
  promote-spec polish is a separate sub-project.

Verification: grep for "coating_config_id|fp.coating.config|
fp.treatment|fp.coating.thickness" in live (non-bridge_mrp,
non-portal, non-script, non-test) Python/XML/CSV returns 3 hits,
all in module / class docstrings explaining Phase E history.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 02:00:41 -04:00
gsinghpal
7cafab1b9f feat(promote-customer-spec): Phase B — two-picker SO line UX
Spec-side picker (x_fc_customer_spec_id / customer_spec_id) added on:
- sale.order.line (via quality inherit — onchange autofill, create()
  fallback to part default, _prepare_invoice_line carry)
- account.move.line (via quality inherit — invoice rendering)
- fp.part.catalog (via quality inherit — x_fc_default_customer_spec_id)
- fp.direct.order.line (via quality inherit — wizard picker + autofill)
- fp.direct.order.wizard (action_create_order post-creates spec on SO line)

Thickness picker switched to fp.recipe.thickness (replaces coating-scoped):
- sale.order.line.x_fc_thickness_id comodel + domain rewired to recipe
- account.move.line + fp.delivery same
- fp.direct.order.line.thickness_id same

View inherits in quality add Specification picker next to legacy
Primary Treatment column on:
- SO form line tree
- part catalog Default Treatments block
- direct-order wizard line tree + drawer

Wizard files (fp.contract.review.client.email.wizard) pulled from
entech into the repo — they were ahead of the repo. Quality __init__
now imports wizards/.

Legacy x_fc_coating_config_id + treatment_ids remain visible during
transition; Phase E removes them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 01:16:25 -04:00
gsinghpal
6b7b44264a changes 2026-05-10 10:25:12 -04:00
gsinghpal
1da27ed6bf changes 2026-05-01 00:20:40 -04:00
gsinghpal
b187192c58 feat(step-library): full plating workflow coverage + per-recipe configurability + audit
Implements 2026-04-29-step-library-audit-design.md. Bumps fusion_plating
to 19.0.18.7.0, fusion_plating_jobs to 19.0.8.12.0, fusion_plating_reports
to 19.0.10.2.0.

LIBRARY EXPANSION
- 8 new Step Kinds: Receiving, Electroclean, Strike, Salt Spray,
  Adhesion Test, Hardness Test, Packaging, Tank Replenishment
- 4 new input types: photo, multi_point_thickness, bath_chemistry_panel, ph
- DEFAULT_INPUTS_BY_KIND rewritten to seed audit-grade prompts on every
  kind (bath IDs, photos, multi-point thickness, signatures, etc.)
- + Common Audit Fields one-click button on the library template form
- Default Operator Instructions relabel + alert callout

PER-RECIPE CONFIGURABILITY
- collect (Boolean) per recipe-step input prompt — opt out without delete
- collect_measurements (Boolean) master switch on recipe step — when off,
  wizard skips entirely
- template_input_id (Many2one) traceability link from recipe to library
- Recipe-step backend form view exposes the new fields with handle drag,
  toggle, target range, and library-source column

RUNTIME WIRING
- Step input wizard filters node.input_ids to step_input AND collect=True;
  short-circuits on collect_measurements=False
- New input types: photo (image widget + ir.attachment), multi-point
  thickness (5 readings + auto avg, skips empty cells), bath chemistry
  panel (pH/conc/temp/bath bundle), pH (0-14 numeric)
- Composite values JSON-serialized into value_text; photo via attachment

CoC REPORT
- Filters captured prompts to collect=True only
- Renders new input types with appropriate format

MIGRATION (post-migrate.py for 19.0.18.7.0)
- Backfills collect=True on recipe-step inputs
- Backfills collect_measurements=True on recipe steps
- Re-runs action_seed_default_inputs on every existing template
  (idempotent, preserves user edits)
- Backfills template_input_id by name-matching against source library
  template (handles JSONB vs varchar name columns)

SEED DATA
- 8 example templates (one per new kind) in fp_step_template_data.xml
  with noupdate=1

BATTLE TEST
- bt_step_library_audit.py: 29 assertions all PASS on entech

OWL EDITOR EXTENSION DEFERRED
- The simple recipe editor's per-step Instructions/Measurements
  expansions were not implemented in this pass; users configure via the
  backend recipe-step form. Track follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 22:13:54 -04:00
gsinghpal
a2fe1fcbcc changes 2026-04-29 03:35:33 -04:00
gsinghpal
13e300d90e changes 2026-04-28 19:39:37 -04:00
gsinghpal
0ad382e1a6 feat(phase1): top-level menu consolidation + landing-page resolver
Phase 1 collapses the Plating app's 17 top-level menus down to 6
domains (Sales, Operations, Receiving & Shipping, Quality,
Compliance, Configuration) so users no longer scroll a 17-item
sidebar to find one thing.

Re-parented (no XML id changes — bookmarks still work):
- fusion_plating_compliance.menu_fp_compliance_root
    → menu_fp_compliance_hub  (renamed 'General')
- fusion_plating_safety.menu_fp_safety_root
    → menu_fp_compliance_hub  (renamed 'Safety / WHMIS')
- fusion_plating_aerospace.menu_fp_aerospace
    → menu_fp_compliance_hub  (renamed 'Aerospace (AS9100 / Nadcap)')
- fusion_plating_nuclear.menu_fp_nuclear
    → menu_fp_compliance_hub  (renamed 'Nuclear (CSA N299 / CNSC)')
- fusion_plating_cgp.menu_fp_cgp
    → menu_fp_compliance_hub  (renamed 'Controlled Goods (CGP)')
- fusion_plating_certificates.menu_fp_certificates
    → menu_fp_quality (Certs are a Quality output, not a separate
      top-level concern)
- fusion_plating_bridge_maintenance.menu_fp_maintenance
    → menu_fp_operations
- fusion_plating.menu_fp_job_step_move (Move Log)
    → menu_fp_operations
- fusion_plating.menu_fp_job_step_timelog (Labor History)
    → menu_fp_operations

The new menu_fp_compliance_hub is supervisor-gated; underlying
verticals retain their own group locks (CGP officer, etc.).

Settings menu remains manager-gated through inheritance from
menu_fp_config (already in place).

NEW — Plating landing-page resolver:
- ir.actions.act_window.x_fc_pickable_landing  (Boolean tag for
  curated picklist; flagged on Sale Orders, Quotations, Process
  Recipes for Phase 1; more in Phase 2)
- res.company.x_fc_default_landing_action_id (admin sets fallback)
- res.users.x_fc_plating_landing_action_id (per-user override)
- ir.actions.server action_fp_resolve_plating_landing — picks
  user → company → Sale Orders fallback at click time
- menu_fp_root rewired to call the resolver
- User profile + Settings tabs surface the dropdowns

Configurator's earlier menu_fp_root override (action_fp_sale_orders
direct) removed — core's resolver now owns the routing.

Versions bumped: fusion_plating 19.0.11.0.0, configurator
19.0.17.16.0, plus 7 dependent modules patched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 22:33:37 -04:00
gsinghpal
cfe776be4c chore: session housekeeping — tank UX, plating menu defaults, WO label
- fusion_plating: tank field labels (Code → Tank Number, Tank → Tank Name)
  + state-control header buttons (Mark Empty/Filled/In Use/Draining/
  Maintenance/Out of Service) with chatter audit logging.
- fusion_plating_configurator: Plating app default landing screen = Sale
  Orders, while keeping menu name as 'Plating'.
- fusion_plating_jobs: SO smart-button label 'Plating Jobs' → 'WO'.

Already deployed and verified on entech earlier in the session.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 20:27:35 -04:00
gsinghpal
f08f328688 changes 2026-04-27 00:11:18 -04:00
gsinghpal
d9f58b9851 changes 2026-04-26 15:05:17 -04:00
gsinghpal
41d0908ade changes 2026-04-24 21:04:38 -04:00
gsinghpal
8142bd229a feat(configurator): "PO Pending" escape hatch for customers who send PO later
Customer feedback: some customers don't send their PO with the
initial order — they send it days or weeks later. The system was
blocking SO confirmation without a PO, which forced the shop to
either wait on paperwork or ask a manager for a formal override.

New estimator-level path: a "PO Pending" boolean on sale.order +
an optional "PO Expected By" date.

  * Confirm without a PO# / PO document when PO Pending is ticked.
  * action_confirm skips the hard error if po_pending OR po_override
    is set (keeps the existing manager-override path too).
  * On confirm with PO Pending, the system schedules a chase
    activity for po_expected_date (or +3 days if blank), assigned
    via mail.activity so it shows up in the sales user's activity
    list. Chatter note logged so audit is obvious.
  * Direct-order wizard: po_number and po_attachment_file become
    optional. Ticking "PO Pending" in the wizard is the trade-in;
    a help note under the toggle explains the chase behaviour.
  * Once the PO arrives, user fills in the PO# / uploads the doc,
    and turns PO Pending off — existing downstream flow resumes.

Difference from x_fc_po_override (kept):
  * PO Override = manager waiver, permanent ("handshake deal").
  * PO Pending = estimator flag, time-boxed ("customer will send it
    by Friday").

fusion_plating_configurator → 19.0.14.0.0
fusion_plating_invoicing    → 19.0.3.0.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:08:00 -04:00
gsinghpal
625f6560f1 feat(plating): split templates vs part-scoped processes + Process smart button
Two user-reported gaps:

1. The Process Recipes list was about to be flooded by part-scoped
   clones as soon as parts started carrying customised processes —
   thousands of clones would bury the handful of real shared
   templates (General Processing, Anodize, etc.).

   Fix: the main Process Recipes action now narrows to
   part_catalog_id = False so shared templates stay alone in that
   view. A sibling menu "Part Processes" (Plating → Operations →
   Part Processes) shows the inverse list — every part-cloned
   process, grouped by part — so admins can audit clones without
   cluttering the templates list.

   Search view gains two toggle filters (Shared Templates /
   Part-Scoped) and a "Group by Part" option. The node list gains
   an optional "Part" column.

   Split across modules: core owns the base search / tree / action
   (unchanged); configurator owns all the part_catalog_id-dependent
   pieces (filter extensions, list column, narrower domain,
   "Part Processes" action + menu). Keeps the dependency direction
   clean — configurator always depends on core, never the other way.

2. Added a "Process" smart button to the part form's button box.
   Shows either a green check (composed) or "None" (not yet
   composed) and opens the part-scoped Composer on click. Gives
   users one-tap access from any part form without hunting through
   the Process tab.

fusion_plating → 19.0.8.0.0
fusion_plating_configurator → 19.0.13.1.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 08:45:24 -04:00
gsinghpal
25c3f6f8d1 feat(plating): Sub 5 — order-line fields (serial, job#, thickness, revision)
Four new fields on every sale.order.line, propagated through to MO,
Delivery, and Invoice for end-to-end traceability:

- fp.serial registry (new model in configurator) with smart-button
  traceability to Sale Order, MO, Delivery, Invoice, Part. M2O on SO
  line; optional; user types a customer serial or clicks Generate
  Serial for a sequence-backed one. Reverse O2M links split across
  configurator (invoice) / bridge_mrp (MO) / logistics (delivery) so
  module load order is respected.
- x_fc_job_number on SO line, auto-sequenced FP-JOB-NNNNN on SO
  confirm. Editable — shops can override for customer/legacy schemes.
- fp.coating.thickness (new child of fp.coating.config) with per-
  config discrete thickness options; x_fc_thickness_id on SO line
  domain-filtered to the line's coating. Auto-clears when coating
  changes.
- x_fc_revision_snapshot Char on SO line, frozen from
  x_fc_part_catalog_id.revision at save. Protects historical SOs from
  later catalog edits. Secondary "Revision" picker on the tree view
  lets users switch between prior revisions of the same part number;
  the Part M2O still surfaces only is_latest_revision rows.

Reports (CoC, packing slip, invoice, BoL) pick up all four via the
Sub 2 customer_line_header macro — one macro edit, four reports.

Smoke on entech: 11 assertions pass including revision snapshot,
generate-serial button, typed-serial create-on-fly, coating→thickness
domain reset, SO confirm auto job#, and MO traceability carry.

Module version bumps:
  fusion_plating_configurator  → 19.0.12.0.0
  fusion_plating_bridge_mrp    → 19.0.11.0.0
  fusion_plating_logistics     → 19.0.2.0.0 (+depends configurator)
  fusion_plating_reports       → 19.0.5.1.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 23:04:44 -04:00
gsinghpal
3de37ea735 feat(configurator): Sub 3 Phase B — part-scoped Process Composer client action + part form Compose button
- Add fp_part_composer_controller with 3 JSON-RPC endpoints:
  /fp/part/composer/state, /fp/part/composer/templates,
  /fp/part/composer/load_template (deep-clones a shared template
  into a part-owned tree inside a cr.savepoint, sets
  fp.part.catalog.default_process_id atomically)
- _clone_subtree copies name/sequence/opt_in_out/treatment_uom plus
  description/notes/icon/color/timing/behaviour/work_center/process_type
  and stamps part_catalog_id + cloned_from_id on every node
- Add fp_part_process_composer OWL client action (JS + XML + SCSS):
  picks template from dropdown, clones, hands off to existing
  fp_recipe_tree_editor via context={recipe_id, part_id}
- Add Process tab on part form with readonly default_process_id
  field and Compose button calling action_open_part_composer
- Register new assets in web.assets_backend, bump configurator
  version to 19.0.11.0.0
2026-04-22 09:02:03 -04:00
gsinghpal
1eac630d87 feat(configurator): drop legacy description column after dual-field migration (Sub 2 Task 27)
Removes the `description` field from `fp.sale.description.template` now
that all readers (reports, wizard, sale line) consume the new
`internal_description` + `customer_facing_description` pair.

- Model: drop `description = fields.Text(...)` declaration
- Migration 19.0.9.0.0 Step 6: `ALTER TABLE ... DROP COLUMN IF EXISTS description`
- Template form/search views: swap `description` for the two new fields
- Seed data: write new fields instead of legacy column (dupes old text into both)
- Direct-order wizard: remove `tpl.description` fallback in both onchange handlers

Entech column dropped via Odoo's auto-schema-sync during module upgrade
(migration step is for fresh installs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 23:27:22 -04:00
gsinghpal
a659eba8f5 feat(configurator): SO-line template picker + dual descriptions + onchange (Sub 2 Task 15)
Surfaces the per-part description template on the SO line list alongside
a hidden-by-default internal description column. Picking a template
fires an onchange that copies `customer_facing_description` into Odoo's
standard `name` (customer-visible) and `internal_description` into
x_fc_internal_description (shop-floor / WO only). Estimator can edit
either field after the template is applied.

The template picker's domain filters by the line's part, and the field
stays hidden until a part is chosen — avoids showing every global
template when the line is blank.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 22:49:49 -04:00
gsinghpal
d1c855698a feat(configurator): two-column dual-description repeater on part form (Sub 2 Task 14) 2026-04-21 22:47:05 -04:00
gsinghpal
afee8d5ee8 feat(configurator): cert requirement + SKU relabel on part form (Sub 2 Task 13) 2026-04-21 22:46:10 -04:00
gsinghpal
bee5ba4d3f fix(plating): UAT-caught UX annoyances + lurking bugs
Five fixes from the end-to-end UAT debrief:

1. Menu discoverability (HIGH)
   Added a prominent "+ New Direct Order" button in the Sale Orders
   list header toolbar (class=btn-primary, display=always). The
   existing menuitem at Plating > Sales > New Direct Order was
   buried in a submenu that didn't always expand; the toolbar
   button is a guaranteed entry point from the most common screen.

2. Escape/X destroys wizard state (HIGH)
   Added a prominent info banner at the top of the wizard form:
   "Changes are not saved until you click Create & Confirm Order.
   Closing this window (Esc or X) discards your entries." The
   Cancel button now has confirm="Discard this order? All header
   data and line items will be lost." so the intentional-cancel
   path also prompts.

3. Shell/cron crash in _fp_auto_create_mo (MEDIUM)
   bridge_mrp/models/sale_order.py:232-264 used _() inside list
   comprehensions to format the internal chatter summary of newly
   created / adopted MOs. _() resolves language from env.context,
   which is empty in odoo-shell and cron contexts — triggering a
   translate.get_text_alias crash AFTER the MOs had been created.
   These strings are internal audit log text, not user-facing UI;
   dropped the _() wrappers so the message builds safely from any
   context. Same for the per-group error-message on savepoint
   rollback.

4. Misleading "100%" margin (MEDIUM)
   x_fc_margin_percent displayed 100% on every SO because the cost
   rollup from fp.coating.config.unit_cost isn't populated yet.
   Added x_fc_margin_available Boolean (True only when at least
   one line's coating has a non-zero unit_cost). The SO Plating
   tab now hides the margin numbers when margin_available=False
   and shows an inline muted note: "Margin n/a — coating cost
   rollup not yet populated on any line's treatment."

5. Account Hold banner too loud (LOW)
   fusion_plating_invoicing was injecting a full-height danger
   alert above every SO header. Slimmed it to a one-line compact
   alert with icon: "Account Hold — SO confirmation, invoicing
   and shipping are blocked for non-managers." Half the vertical
   footprint, less visual competition with the Plating chip bar.

Verified via UAT on S00071.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 01:03:26 -04:00
gsinghpal
b834ae3117 feat(configurator): complete all deferred Phase D/E/F tasks
Ships the remaining items from the Sales UX Uplift plan:

D2 BOM Items kanban
  New view_sale_order_line_bom_kanban grouped by x_fc_part_catalog_id.
  Smart button 'BOM Items' on SO form opens it.

D5 Archive line
  x_fc_archived Boolean on sale.order.line plus action_archive_line /
  action_unarchive_line. Acknowledgement report filters out archived
  lines.

D6 Add Quoted Lines sub-wizard
  New fp.add.from.quote.wizard parallel to fp.add.from.so.wizard. Pick
  quotes for this customer and clone them into direct-order lines
  carrying part, coating, qty, unit price (from calculated or
  override), and notes. Button '+ Add From Quotes' on wizard Lines tab.

D7 SO Acknowledgement PDF
  New ir.actions.report + QWeb template in configurator/report/.
  Header shows customer / contact / PO / Customer Job #, Bill-To,
  Ship-To, planned start + customer deadline + ship-via. Line table
  skips archived lines. Includes external notes, blanket-order
  callout, and customer-signature + vendor-signature blocks.
  Binding added to sale.order so it shows up under Print menu.

D9 Quick-nav chip bar
  New smart buttons on SO form: Invoices / Pickings / NCRs / Files
  with counts and icons. Each opens a filtered list. NCR button
  appears only when fusion_plating_quality is installed.

D10 SO/WO perspective toggle
  view_sale_order_line_wo_kanban grouped by x_fc_wo_group_tag. Smart
  button 'By WO' on SO form.

D11 Assemblies minimal model
  fp.sale.assembly + fp.sale.assembly.line with name, ship_to, count,
  procured_count, completed_at. UX (forms / kanbans / integration
  into receiving) deferred — model only for now.

D14 Uploaded Files
  Files smart button on SO form opens ir.attachment kanban filtered
  to this SO. Count appears in the chip bar.

F4 Signed tracking
  x_fc_signed_at / x_fc_signed_by / x_fc_is_signed on sale.order +
  action_mark_signed helper. Signed column on quotes list view.

F10 New Quote
  Kept on existing action_fp_quotations (already surfaces the
  default New button).

E5/F9 Action icons per row
  Deferred — requires a custom widget; the native PDF action via the
  Print menu covers 80% of the use case.

Bumped to 19.0.8.0.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:45:17 -04:00
gsinghpal
97c733b7c3 feat(configurator): Phase F — quotations list uplift
F1 follow-up: x_fc_follow_up_date + x_fc_follow_up_user_id fields on
sale.order, surfaced in the quotations list + a 'Needs Follow-Up'
preset filter.

F2 expires: native validity_date exposed as togglable column on the
quotes list + an 'Expired' preset filter.

F3 email status pills: x_fc_email_status computed (draft / sent /
opened / won). 'Opened' detects via mail.notification.is_read on any
email-type mail.message attached to this SO.

F5 part numbers summary: x_fc_part_numbers_summary ("PN1, PN2 (+3
more)") across order_line parts, togglable column.

F7 from-RFQ filter reuses existing x_fc_rfq_attachment_id.

Views:
- view_sale_order_list_fp_quotes (new list dedicated to quotes).
- view_sale_order_search_fp_quotes with filters Draft / Sent / Won /
  From RFQ / Needs Follow-Up / Expired + group-bys.
- action_fp_quotations rewired to both of the above.

Bumped to 19.0.7.2.0. Closes all six phases originally planned.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:23:41 -04:00
gsinghpal
94eb7ef415 feat(configurator): Phase E — SO list view uplift
E1/E2/E3/E4: list view gets new togglable columns for
- x_fc_wo_completion (e.g. '3/5'): count of completed vs total WOs
- x_fc_invoiced_amount (Monetary): sum of posted customer invoices
  minus credit notes
- x_fc_margin_amount + x_fc_margin_percent: reuses Phase D8 computes
- x_fc_is_blanket_order toggle

New sale.order.search view (sale.order.search.fp) with preset
filters: My Orders / Open / Confirmed / Done / Blanket / Has Rush /
Overdue, plus group-bys for Customer / Status / Customer Deadline.

Bumped to 19.0.7.1.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:18:52 -04:00
gsinghpal
842efd828c feat(configurator): Phase D batch 2 — active WOs stat button on SO form
D3 first half: x_fc_workorder_count computes live count of active MRP
work orders linked to this SO (via mo.origin = so.name). Adds a
'Active WOs' smart button next to the existing PO / RFQ buttons on
the sale.order form. Clicking opens a filtered mrp.workorder list
grouped by MO.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:12:34 -04:00