Commit Graph

31 Commits

Author SHA1 Message Date
gsinghpal
a2fe1fcbcc changes 2026-04-29 03:35:33 -04:00
gsinghpal
7d3b8f132a fix(sub12c+): close 3 known gaps — rack travel ticket, cert statement, CoC actuals
Gap 1 — Rack Travel Ticket PDF (Sub 12b's Save+Print 404):
  + report_fp_rack_travel.xml in fusion_plating_reports — A5 landscape
    single page, big rack name, Code 128 of FP-RACK:<name>, tag chips,
    contained part-batches table.
  + ir.actions.report bound to fusion.plating.rack so it appears in
    the rack form's Print menu too.
  + Sub 12b's rack_parts_dialog.js Save+Print URL fixed to use the
    standard /report/pdf/<xmlid>/<id> route.

Gap 2 — Per-customer cert statement:
  + res.company.x_fc_default_cert_statement (company-level fallback).
  + res.partner.x_fc_cert_statement (per-customer override).
  + Surfaced on the partner form under the existing Cert + Document
    Routing block.
  + Chronological CoC body resolves: customer override → company
    default → hardcoded AS9100/ISO 9001 boilerplate. Three-tier
    fallback so existing certs without overrides keep working.

Gap 3 — Chronological CoC 'Actual' column:
  + Build a captured_values_by_input dict from the move's
    transition_input_value_ids (Sub 12b captures these on every
    Move Parts commit).
  + Render typed Actual: text → as-is, number → with target unit,
    boolean → PASS/FAIL, date → formatted, attachment → '[Attachment]'
    placeholder.
  + Falls back to prompts from the destination step's step_input list
    when no values were captured (still useful as audit-of-what-was-
    asked even if blank).

Version bumps:
  fusion_plating → 19.0.10.3.0
  fusion_plating_reports → 19.0.10.1.0
  fusion_plating_certificates → 19.0.5.3.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 21:55:48 -04:00
gsinghpal
f55193fb1b feat(sub12c): bump versions + manifest scaffolding (Task 1)
fusion_plating → 19.0.10.2.0 (Labor History views)
fusion_plating_jobs → 19.0.7.0.0 (Operator Traveller v2)
fusion_plating_reports → 19.0.10.0.0 (Chronological CoC body)

Adds data entries for the 2 new XML files (timelog views + coc
chronological).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 21:37:24 -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
160198edb1 chore(reports): drop duplicate Print menu entries on legacy MRP models
After the fp.job migration, every MRP-bound Print action in
fusion_plating_reports has a fp.job-bound canonical version in
fusion_plating_jobs. Having both registered means clicking Print on a
record shows two identical entries.

Removed 7 ir.actions.report records (templates kept for backwards
compat — only the menu bindings are gone):

  action_report_wo_margin                   (mrp.production)
  action_report_fp_work_order_portrait      (mrp.workorder)
  action_report_fp_work_order_landscape     (mrp.workorder)
  action_report_fp_wo_sticker               (mrp.workorder)
  action_report_fp_mo_sticker               (mrp.production)
  action_report_fp_job_traveller_mo_landscape (mrp.production)
  action_report_fp_job_traveller_mo_portrait  (mrp.production)

Kept:
  action_report_fp_job_traveller_so_*  (sale.order)
  action_report_fp_so_sticker          (sale.order)

The shared inner sticker templates (report_fp_wo_sticker_inner /
_defaults) stay registered because fp.job + sale.order stickers
both t-call them.

Version: reports 19.0.7.17 -> 19.0.7.18.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 10:53:19 -04:00
gsinghpal
9fe7855fc3 fix(shopfloor,reports): scanner status line + sticker rev cleanup
- Re-detect BarcodeDetector / window.jsQR at every modal open instead
  of only at component setup. Avoids the trap where a stale cached
  bundle reports "no decoder" even after a redeploy.
- Add a one-line status indicator at the top of the scan modal showing
  exactly which decoder is active ("Decoder: native" / "Decoder: jsqr"
  / "Decoder: none — paste URL below"). Lets the operator see at a
  glance whether scanning is even possible without round-tripping
  through Safari Web Inspector.
- Sticker: strip a leading "Rev " (case-insensitive) from
  fp.part.catalog.revision before printing so values like "Rev 1"
  don't render as "Rev Rev 1".

Versions: shopfloor 19.0.18 -> 19.0.19, reports 19.0.7.16 -> 19.0.7.17.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 13:30:40 -04:00
gsinghpal
b93633d728 fix(shopfloor,reports): make QR scan actually navigate after decode
Two bugs were colluding to make iPhone scans look like "nothing
happens":

1. The in-app scanner was calling action.doAction({res_model: 'fp.job',
   res_id: <decoded-id>}). Old physical stickers (still on every box)
   encode /fp/wo/<mrp.production.id> — that id space doesn't match
   fp.job, so the form opened on a non-existent record and silently
   showed nothing. New /fp/job/<id> stickers happened to work because
   the IDs lined up by coincidence.

2. The /fp/wo/<id> controller redirected to mrp.production / mrp.workorder
   forms, both of which still exist as legacy records but aren't the
   canonical source of truth post-migration.

Fix:
- qr_scanner._handleCode now navigates via window.location.href instead
  of action.doAction. It hands /fp/job/<n> and /fp/wo/<n> URLs straight
  to the existing server-side controllers, which know how to resolve
  the right record. Bare numeric ids pasted manually -> /fp/job/<n>.
  Anything else surfaces the decoded text as an error so the operator
  can see decode worked but the value isn't a sticker.

- Modal now shows "Detected: <value>" the moment a code is decoded
  (before navigation), so even on slow phones the operator sees
  immediate feedback that the camera read the QR.

- wo_scan.py now resolves in this order:
    1. fp.job by legacy_mrp_production_id (migration-aware — old
       stickers route to the new model)
    2. mrp.production direct browse
    3. mrp.workorder direct browse
    4. fall back to /odoo/plating-jobs (or work-orders list)

Versions: shopfloor 19.0.17.0.0 -> 19.0.18.0.0,
          reports   19.0.7.15.0 -> 19.0.7.16.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 13:14:06 -04:00
gsinghpal
ecac43eef4 fix(reports): restore the original ENTECH box-sticker layout for fp.job + sale.order
The original mrp.production / mrp.workorder sticker (logo + WO# stack
on the left, big QR on the right, 7-row body with PO/Customer/Process/
Part Number/Due/Qty/Notes — the design ENTECH has been printing for
months) lives in fusion_plating_reports.report_fp_wo_sticker_inner.

The new fp.job sticker had been rebuilt from scratch with a different
look. This wires fp.job into the existing canonical template instead.

What changed:

- report_fp_wo_sticker_inner — every t-set now uses the
  "_var or fallback-from-_mo" pattern so callers can pre-resolve
  values; mrp.production/mrp.workorder callers still work via the
  fallback path.
- report_fp_wo_sticker_defaults — new shared template that initialises
  every overridable name to False so the inner's `or` chain doesn't
  NameError when an outer hasn't set it.
- report_fp_job_sticker_template — replaces the parallel layout with
  a t-call to report_fp_wo_sticker_inner, feeding it from fp.job
  fields (name, partner_id, qty, date_deadline, sale_order_id,
  sale_order_line_ids, recipe_id, part_catalog_id, coating_config_id).
- report_fp_so_sticker — new outer that iterates sale.order.order_line
  and emits one sticker per line that has a part_catalog_id. Bound to
  sale.order's print menu via action_report_fp_so_sticker.

Versions: reports 19.0.7.14.0 -> 19.0.7.15.0,
          jobs    19.0.5.0.0  -> 19.0.5.1.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 13:03:29 -04:00
gsinghpal
41d0908ade changes 2026-04-24 21:04:38 -04:00
gsinghpal
0eab4b4efb fix(reports): sticker PDF KeyError: 'quote' on fusion_pdf_preview path
The QR <img> src used `% quote(_scan_url)` to URL-encode the value,
but `quote` isn't always in the QWeb render context — particularly
on the fusion_pdf_preview / account render chains. Result:
KeyError: 'quote' when printing from the browser.

_scan_url is always base_url + '/fp/wo/<int>' — no characters that
need encoding. Replaced the % + quote() formatting with simple
string concatenation, dropping the quote dependency entirely.

Smoke verified on entech: MO + WO stickers render cleanly at 27KB
each (with QR image included).

fusion_plating_reports → 19.0.7.2.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:58:24 -04:00
gsinghpal
e32ff4b056 feat(reports): MO-bound WO sticker + polished professional layout
User reported two issues with the sticker:

1. "Print → WO Box Sticker" didn't appear on the MO form
   (WH/MO/00067). The operator workflow lives on the MO form, not
   the WO — binding only to mrp.workorder meant they couldn't see
   the option. Now bound to BOTH:
     * mrp.workorder (per-WO sticker)
     * mrp.production (per-MO sticker — prints the MO friendly
       name after "WO #" so it reads naturally in shop-floor
       vocabulary)
   Internal refactor: factored the layout into a shared inner
   template report_fp_wo_sticker_inner; the two outer templates
   normalise their input to the same _order_id / _scan_id / _mo
   variables and t-call the inner.

2. Design polish. The previous layout was a plain label/value
   table that looked rough. Redesigned with:
     * Proper sticker chrome: 0.5mm black border, 1.5mm rounded
       corners, edge padding.
     * Header row with bottom border rule separating logo+WO-# on
       the left from QR+caption on the right.
     * Grid rows now alternate white / #f4f5f7 zebra-striping with
       a right-aligned vertical rule between label and value.
     * ALL-CAPS, letter-spaced, gray-333 labels at 7.5pt; values
       at 8.5pt with strong (9.5pt, 700) emphasis on the key data
       (PO, Part Number, Qty) so it reads at a glance from across
       the warehouse.
     * Helvetica Neue font stack.
     * "SCAN TO OPEN" caption under the QR.

Scan endpoint updated: /fp/wo/<id> now tries mrp.production first
(operator home form) then falls back to mrp.workorder. Numeric
collisions between the two id spaces are possible; MO wins because
the MO view carries the full context.

fusion_plating_reports → 19.0.7.1.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:52:22 -04:00
gsinghpal
be33a76ad2 feat(reports): WO box sticker + QR-scan-to-WO endpoint
Client is migrating from Steelhead and needs to keep the small
parts-box sticker format the warehouse crew already knows. Two
pieces shipped together so scanning is seamless from day one:

1. report_fp_wo_sticker — 4x3" QWeb label bound to mrp.workorder.
   Layout mirrors the Steelhead sticker:
     * ENTECH logo top-left (via env.company.logo)
     * QR code top-right encoding /fp/wo/<id>
     * Grid: PO (RO) / Customer / Process / Part Number / Due
       Date / Qty / Notes
   Dedicated paperformat_fp_wo_sticker at 102x76mm, 300 DPI,
   landscape, 3mm margins — sized for thermal / inkjet label
   printers without shrink-to-fit.
   Binding added so "Print → WO Box Sticker" appears on every
   mrp.workorder record.

2. FpWoScanController — GET /fp/wo/<int:wo_id> redirects the
   scanner straight to the work-order form
   (/odoo/action-mrp.action_mrp_workorder/<id>). auth='user' so
   logged-in scanners land on the WO immediately; others bounce
   through Odoo's login and return to the same URL. No custom
   client work needed — any phone camera, handheld barcode
   scanner, or tablet browser opens the URL on scan.

Process row resolution chain: part.default_process_id →
coating.recipe_id → fallback. So the sticker prints whichever
process is actually going to drive WO generation for this line,
matching the direct-order wizard's Effective Process column.

fusion_plating_reports → 19.0.7.0.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:39:35 -04:00
gsinghpal
eddf803d4c feat(reports): split customer-facing line header into Part Number + Description columns
User request: on customer-facing PDFs the single "Part" column was
stacking part number + revision + description together. Split into
two distinct columns so customers see Part Number in its own field
and the Description column carries only the prose.

Macro split:
  * customer_line_part_number — strong part number + "(Rev X)"
  * customer_line_description  — line.name + any populated line
    metadata (serial, job#, thickness)
  * customer_line_header (legacy) kept as a thin wrapper that
    t-calls both macros stacked so older reports still render.

Reports updated — each gains a new first "PART NUMBER" column and
the old "PART" column renamed to "DESCRIPTION":
  * report_fp_sale (both portrait variants)
  * report_fp_invoice (both portrait variants)
  * report_fp_packing_slip (both variants — delivery + MO-origin)

Column widths rebalanced per report. Section / note colspans bumped
to account for the extra column.

report_fp_bol left as-is — its "Description of Goods" td is a
freight-convention combined field, intentionally keeps the stacked
layout via the legacy customer_line_header macro.

fusion_plating_reports → 19.0.6.0.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:17:56 -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
d959775648 feat(reports): customer_line_header QWeb macro + version bump (Sub 2 Task 17) 2026-04-21 22:54:17 -04:00
gsinghpal
f09bef9083 refactor(reports): consolidate SO Acknowledgement back into the Sales Order PDF
Earlier I built report_fp_so_acknowledgement.xml as a separate
customer-facing document. On review there was no good reason — our
existing report_fp_sale.xml already flips its title between
"Quotation" and "Sales Order" based on state, and carried ~90% of
the same content. Two documents would have meant the shop had to
remember which to send when, and the customer would get two
near-identical PDFs in their inbox.

Consolidation:

1. Merged the four unique blocks from the acknowledgement into
   report_fp_sale.xml (both portrait AND landscape variants):
   - CUSTOMER JOB # / PLANNED START / CUSTOMER DEADLINE / SHIP VIA
     info row (shown only when any of those fields is populated)
   - Blanket / block-partial highlight-box callout (shown only
     when the flags are set)
   - External notes (x_fc_external_note) block above Terms and
     Conditions

2. Deleted fusion_plating_reports/report/report_fp_so_acknowledgement.xml
   and removed it from the module manifest. Also purged the orphan
   ir.actions.report and ir.ui.view DB rows + the stale
   ir.model.data entries.

3. Re-pointed the fp_mail_template_so_confirmed mail template's
   report_template_ids from the now-gone acknowledgement report to
   action_report_fp_sale_portrait. Updated hooks.py accordingly; the
   hook now uses "set" semantics (replace all) instead of "add" so
   re-running it cleans up stale attachments from prior refactors.

4. UAT on S00071: the Send button pre-selects the FP: Order
   Confirmation template with SalesOrder_S00071.pdf attached. The
   PDF renders with the new plating rows populated — Customer Job #
   AMPH-2026-0420-01, Customer Deadline 05/14/2026 08:00:00 PM,
   "Partial shipments blocked" callout, all lines + totals.

One PDF, one Send button behaviour, matching what Odoo and most
ERP systems do.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 01:30:06 -04:00
gsinghpal
c8ca37099b refactor(reports): move SO Acknowledgement into fusion_plating_reports with house style
D7 template was originally in fusion_plating_configurator with a
Bootstrap-only look-and-feel that didn't match the other Fusion
Plating reports. Re-styled and relocated:

- Moved to fusion_plating_reports/report/report_fp_so_acknowledgement.xml
  alongside sale / work-order / job-traveller / invoice templates.
- Uses fp_portrait_styles (company primary colour for headers, .bordered
  tables, .info-header row, .totals-table, .highlight-box, .sig-box /
  .sig-line / .small-muted).
- Layout now mirrors report_fp_sale.xml: Billing / Shipping address
  pair, references row (Customer PO / Customer Job / Order Date /
  Salesperson), scheduling row (Planned Start / Internal / Customer
  Deadline / Ship Via), blanket-order callout, order line table
  (PART / DESCRIPTION / TREATMENT / QTY / UNIT PRICE / SUBTOTAL),
  totals table with subtotal / taxes / grand total, and a two-column
  signature block.

fusion_plating_configurator no longer ships report/ files — it
depends on fusion_plating_reports transitively via installed modules
order. Report XML ID changed from
'fusion_plating_configurator.report_fp_so_acknowledgement_doc' to
'fusion_plating_reports.report_fp_so_acknowledgement_doc'.

UAT on S00066: PDF renders cleanly with ENTECH branding, contact
footer, subtotal \$3,025 / taxes \$393.25 / grand total \$3,418.25,
signature lines — visually identical to the Quotation/Sales Order
report.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 00:10:33 -04:00
gsinghpal
fa82ce17dd feat(reports): sequence-sort the Print dropdown so FP reports are #1
Odoo 19's `ir.actions.actions._get_bindings` returns the print-menu
bindings via `ORDER BY a.id` (insertion order) and only sequence-sorts
the `action`-type bindings — `report`-type bindings are returned in
raw SQL order. Result: FP reports installed after Odoo's stock ones
appear at the BOTTOM of the dropdown, even when they're the
customer-facing primary report (e.g. Timesheets above Quotation on
sale.order).

Two changes in fusion_plating_reports/models/ir_actions_report.py:

1. **Add `sequence` (Integer, default 100) to ir.actions.report** —
   gives every report a sortable knob.

2. **Override `ir.actions.actions._get_bindings`** to also sort the
   `report` slice by `(sequence, name.lower())`. super() returns the
   cached frozendict; we rebuild with the sorted reports.

Then set sequences in fp_hide_default_reports.xml (lower = top):

| Model           | seq 10 (#1)              | seq 15 (#2)              | seq 20+               |
|-----------------|--------------------------|--------------------------|-----------------------|
| sale.order      | FP Quotation Portrait    | FP Quotation Landscape   | FP Job Traveller (20) |
| account.move    | FP Invoice Portrait      | FP Invoice Landscape     |                       |
| stock.picking   | FP Packing Slip Portrait | FP Packing Slip Landscape|                       |
| mrp.production  | FP Job Traveller Portrait| FP Job Traveller Landscape| FP WO Margin (20)   |
| account.payment | FP Receipt Portrait      | FP Receipt Landscape     |                       |
| fp.delivery     | FP BoL Portrait          | FP BoL Landscape         |                       |
| portal.job      | FP CoC Portrait          | FP CoC Landscape         |                       |
| fp.certificate  | FP CoC English           | FP CoC Français          |                       |

Odoo defaults stay at sequence 100 (default) → always at bottom.

Verified on entech: sale.order print menu now shows
Quotation Portrait → Quotation Landscape → Job Traveller × 2 →
PRO-FORMA → Timesheets. Same pattern across all touched models.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 09:05:29 -04:00
gsinghpal
9a1ee4b369 feat(reports): hide Odoo's default PDFs where FP ships a branded one
Users were seeing both Odoo's stock PDFs and FP's branded equivalents
in the Print dropdown side-by-side, and accidentally sending the wrong
(unbranded, missing PO# / job ref / plating fields) PDF to customers.

Add fp_hide_default_reports.xml that drops the Print-menu binding on:

| Model           | Hidden                                                      | FP replacement                  |
|-----------------|-------------------------------------------------------------|---------------------------------|
| sale.order      | sale.action_report_saleorder                                | action_report_fp_sale_*         |
| sale.order      | sale_pdf_quote_builder.action_report_saleorder_raw          | action_report_fp_sale_*         |
| account.move    | account.account_invoices                                    | action_report_fp_invoice_*      |
| account.move    | account.account_invoices_without_payment                    | action_report_fp_invoice_*      |
| stock.picking   | stock.action_report_delivery                                | action_report_fp_packing_slip_* |
| mrp.production  | mrp.action_report_production_order                          | action_report_fp_job_traveller_*|
| account.payment | account.action_report_payment_receipt                       | action_report_fp_receipt_*      |

Mechanism: set binding_model_id=False + binding_type=action — removes
from the Print dropdown but leaves the report record + template intact.
Fully reversible from Settings → Technical → Reports if anyone needs
the stock PDF back.

Intentionally NOT touched:
- sale.action_report_pro_forma_invoice (no FP pro-forma yet)
- account.action_account_original_vendor_bill (vendor bills, internal)
- stock.action_report_picking / picking_packages / return_label_report
  (internal warehouse ops, not customer-facing)
- mrp.action_report_finished_product / mrp.label_manufacture_template
  (production labels — ZPL, not customer-facing)
- sale_timesheet.* (timesheet integration)

Added sale_pdf_quote_builder to depends so the data file always finds
that record when applied (it ships in entech's repackaged enterprise
bundle and was already installed there).

Verified on entech: re-running the print-menu audit shows zero stock
Odoo customer-facing PDFs left where FP has an equivalent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 08:57:38 -04:00
gsinghpal
cb9baa03ad fix(reports): collapse sig-row to one bordered table — kill duplicate borders
User reported "multiple unwanted vertical lines in the boxes" on the
portrait BoL. Pixel analysis confirmed it: previous design had 3
separate `<div class="sig-box">` each with its own 1px border, with a
4-8px gap between adjacent boxes — visually those adjacent borders
read as a doubled / "duplicate" line between cells.

Fix: replace 3-box layout with a single `<table class="bordered
sig-table">` containing 3 td cells. With border-collapse: collapse,
adjacent cells share their border — so the row now shows 4 vertical
lines (1 outer left + 2 internal dividers + 1 outer right) instead
of 6 close-together border lines.

- Dropped `.sig-box` class entirely (no per-box border anymore)
- Added `.sig-table` + `.sig-cell` with explicit 1px borders so the
  layout works without depending on `.bordered` class inheritance
- Applied to both portrait + landscape variants
- Landscape sig-row was still using the OLD Bootstrap row+col-4
  layout (never got replaced earlier) — also migrated to the new
  table layout

Verified: page count unchanged (portrait 1, landscape 1), all
labels and content present, structure clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 08:14:07 -04:00
gsinghpal
ed72ed496b fix(reports): compact landscape BoL so it fits on one page
Last fix kept signatures intact but the landscape BoL still overflowed
to a second page (with the signature row pushed entirely to page 2).
The real ask was for the landscape variant to fit on one page since
landscape has plenty of vertical room.

Aggressive landscape compaction:
- Body font 11pt → 10pt, td font 10 → 9.5pt, th font 10 → 9pt
- Cell padding 8/10px → 4/8px
- Table margin-bottom 12px → 6px
- h2 title 26pt → 18pt with tighter top/bottom margins
- BoL # subtitle 14pt → 11pt
- Shipper/consignee row height 120 → 70px
- highlight-box (cert) padding 10px → 6/10, font 10 → 9pt
- sig-box padding 12 → 8/10px
- sig-line height 70 → 45px

Verified with pypdf: landscape BoL now renders as exactly 1 page
with cert + all 3 signature labels + company info all present.
137 KB clean PDF.

Portrait variant left untouched (it already fit on one page and
the bigger title is appropriate for portrait).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 07:43:25 -04:00
gsinghpal
b26aa45068 fix(reports): use table layout for BoL signature row, drop flex on sig-box
Last fix added page-break-inside: avoid but the boxes still split
because wkhtmltopdf 0.12 ignores that rule inside flex containers,
and BOTH the .sig-box (display: flex) AND the Bootstrap .row
wrapper were flex.

Replace both with non-flex equivalents:

- .sig-box: dropped `display: flex` + `flex-direction: column` +
  `justify-content: flex-end`. Layout now uses padding + a fixed-
  height .sig-line block + the muted label below. Same visual
  result, but a plain block element so wkhtmltopdf honors the
  page-break rule.

- Replaced `<div class="row">` + 3 `<div class="col-4">` (Bootstrap
  flex grid) with a `<table class="sig-table">` containing one row
  of three 33% tds. wkhtmltopdf treats table rows as atomic for
  page-breaking, so the whole signature row now stays on a single
  page.

Verified with pypdf: page 1 has the cert statement, page 2 has
all three signature labels together — no more sliced boxes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 07:38:59 -04:00
gsinghpal
b16486f66b fix(reports): keep BoL signature row intact across page breaks
Landscape BoL was splitting the signature row down the middle —
boxes half on page 1, half on page 2. Two complementary fixes:

1. **Per-element rule**: added `page-break-inside: avoid` +
   `break-inside: avoid` to `.sig-box` (both portrait + landscape
   styles) so an individual signature box can never split across
   pages.

2. **Wrapper rule**: introduced `.fp-keep-together` utility +
   wrapped the BoL's certification statement + signature row in
   it, so the whole "sign here" block moves to the next page as
   one unit if it doesn't fit. Also applied
   `page-break-inside: avoid` to `table tr` so cargo lines don't
   split mid-row either.

Lives in shared `report_base_styles.xml` so any FP template that
opts into `.fp-keep-together` benefits automatically.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 07:35:55 -04:00
gsinghpal
7ad7481195 fix(bol): bigger title, shipper info, uniform headers, cargo qty, taller signatures
Five fixes applied to the Bill of Lading and (where relevant) all
report templates:

1. **Bigger title + BoL #** — portrait now uses h2 24pt (was h4 16pt),
   landscape h2 26pt; BoL # ticker is 13/14pt instead of body size.

2. **Shipper info missing** — root cause: `_fp_build_delivery_vals`
   was creating deliveries without `company_id`, so the BoL's
   `<span t-field="doc.company_id.name"/>` rendered empty. Two fixes:
   - Hook now sets `company_id = mo.company_id.id or env.company.id`.
   - Template falls back defensively to `env.company` when
     `doc.company_id` is empty (covers any legacy delivery that
     somehow slips through without it).
   - Backfilled 14 existing deliveries via SQL on entech.

3. **Uniform header backgrounds** — replaced mixed `info-header`
   (gray) + default-th (brand black) headers with a single
   `fp-header-primary` (brand black) across all sub-tables for a
   consistent look.

4. **Cargo description alignment + missing column** — added a QTY
   column (matches landscape variant), pulled from the linked MO
   via job_ref → mrp.production.product_qty. Added `.fp-cell-mid`
   utility class with `vertical-align: middle !important;` and
   applied it to every cargo + info cell so values sit centred
   instead of jammed against the top border.

5. **Signature box too short** — bumped `.sig-box` from 70 → 110 px
   (portrait) / 130 px (landscape), `.sig-line` from 28 → 60/70 px,
   added flex layout so the label sits at the bottom and signers
   have a real space to write in. Lives in the shared
   `report_base_styles.xml` so EVERY FP template benefits, not just
   the BoL.

Verified: BoL portrait renders cleanly at 140 KB with full shipper
block + uniform headers + middle-aligned cargo cells.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 07:29:28 -04:00
gsinghpal
16a4bdddf3 fix(reports): BoL PDF — t-field needs dotted path, branch on delivery_address_id
The Bill of Lading template assigned a temp variable
`<t t-set="dest" t-value="doc.delivery_address_id or doc.partner_id"/>`
and then tried `<div t-field="dest" .../>`. Odoo 19 QWeb asserts
t-field must be `record.field_name` (have a dot) — the temp variable
form fails compilation and the report renders as a multi-page
"Oops! Something went wrong" PDF stuffed with the traceback.

Fix: branch with `t-if`/`t-else` and call `t-field="doc.delivery_address_id"`
or `t-field="doc.partner_id"` directly. Same pattern in both header
and second-page-header sections (lines 49/235).

Verified: BoL render goes from 39 KB error page to 138 KB clean PDF.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 07:14:33 -04:00
gsinghpal
633427bcf8 fix(plating): CoC + invoice PDFs render full content
Three reported PDF bugs from the customer-facing email package:

1. Invoice body was empty — Odoo 19 sets display_type='product' on
   regular invoice/SO lines (was empty string in 18.0). Both
   report_fp_invoice.xml and report_fp_sale.xml only matched
   `not line.display_type`, so every product line was skipped.
   Fixed both portrait + landscape variants to also match
   display_type == 'product'.

2. CoC PDF was a bare 30 KB header — _fp_generate_cert_pdf was
   rendering action_report_coc, which is bound to portal_job and
   has minimal content. Rewrote to use the rich fp.certificate-bound
   report (action_report_coc_en / action_report_coc_fr based on
   cert.partner_id.lang) and slugged the filename to
   CoC-<Customer>-<CertName>.pdf so the email attachment reads
   nicely instead of CERT-00123.pdf.

3. Thickness cert was an exact duplicate of the CoC — the CoC
   template already embeds thickness readings. Skip thickness cert
   creation entirely when the customer also wants CoC; only create
   a standalone thickness cert when the customer opted out of CoC.

Also: dispatcher in fp_notification_template now prefers
portal_job.coc_attachment_id (the rich one we just generated) and
falls back to rendering action_report_coc_en against fp.certificate
by partner.lang — never the bare portal-job report.

Versions bumped: bridge_mrp 19.0.6.0.0, notifications 19.0.4.0.0,
reports 19.0.4.0.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 01:16:27 -04:00
gsinghpal
6c4ff7751f feat(plating): comprehensive timezone fix across dashboards/PDFs/emails
Database stores datetimes naive-UTC, but the dashboards and emails were
showing UTC strings to users in EST/EDT — making 9pm Toronto look like 1am
the next day. Adds a single helper module + auto-detection on install.

Core changes (fusion_plating):
- New fp_tz.py helper: fp_user_tz, fp_format, fp_isoformat_utc, fp_time_ago
  Resolves user.tz → company.x_fc_default_tz → UTC.
- res.company.x_fc_default_tz Selection (full pytz IANA list)
- res.config.settings exposes the company tz under a new "Regional
  Settings" block in Settings > Fusion Plating
- post_init_hook auto-populates the tz on first install: tries admin
  user → server /etc/timezone → America/Toronto fallback
- fp_process_node._to_dict now sends create_date/write_date as ISO with
  explicit +00:00 marker so JS new Date() parses it as UTC and the
  recipe tree editor's "time ago" math works correctly

Shop-floor controllers:
- shopfloor_controller.py: every fields.Datetime.to_string() and naive
  .strftime() swapped for fp_format(env, ...) — due_at, bake times,
  last_log_date, gates, server_time all now in user's tz
- _time_ago() removed; replaced with fp_time_ago helper which compares
  tz-aware datetimes (the local one was naive-vs-naive and could be
  off by hours)
- manager_controller.py date_planned: str(...)[:10] slice replaced
  with fp_format MM/DD in user's tz

Notifications + reports:
- mail_template_data.xml: 5 .strftime() calls in body_html → babel
  format_datetime / format_date with tz=(user.tz or company tz)
- report_fp_job_traveller.xml: rec.received_date (Datetime) gets
  t-options="{'widget':'datetime'}" so Odoo's QWeb renders in user tz

Settings view layout:
- fusion_plating now owns the Settings page "Fusion Plating" app shell
- fusion_plating_certificates xpaths into it instead of redefining
  (prevents app-name collision)

Verified on odoo-entech (LXC 111): post_init_hook detects
America/Toronto from /etc/timezone, MO date_start 2026-04-17 05:28 UTC
correctly displays as 2026-04-17 01:28 EDT.

Module versions bumped: fusion_plating 19.0.3.0.0,
fusion_plating_shopfloor 19.0.9.0.0, plus certificates / notifications /
reports → 19.0.3.0.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 21:03:02 -04:00
gsinghpal
3b5b5cbf7c feat(reports): centralised Job Traveller / Shop Router
One PDF that follows a job through the shop — prints from either the
Sale Order or the Manufacturing Order. Matches existing design language
(fp_landscape_styles, .fp-header-primary banners, bordered tables,
.sig-line for sign-off, .highlight-box for callouts).

Sections per traveller:
  1. Title bar with REWORK / RUSH ORDER badges
  2. Job header — customer, PO #, part #, coating, recipe, facility,
     qty, dates, current parts location
  3. Receiving summary — received qty, state, damage flag
  4. Process Routing table — one row per WO with step #, operation,
     work centre, bath, tank, target thickness, dwell, expected
     duration, + sign-off columns (operator, date/time, initials,
     qty pass/reject)
  5. Bath chemistry targets snapshot per bath used
  6. Quality holds — red callout only when present
  7. Certificates issued + Delivery info (side-by-side)
  8. Rework reason block (only on rework MOs)
  9. Ruled notes / exceptions area
  10. Final supervisor + QA sign-off

Four ir.actions.report entries registered:
  - Job Traveller (Landscape) on mrp.production  [default print]
  - Job Traveller (Portrait)  on mrp.production
  - Job Traveller (Landscape) on sale.order      [iterates MOs]
  - Job Traveller (Portrait)  on sale.order

Regression-tested all 15 existing reports (SO, WO, MO margin, invoice,
BoL, CoC EN, receipt) — every one still renders.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 02:48:03 -04:00
gsinghpal
d3dd6376a6 feat(fusion_plating): quote-to-cash infra, notifications, wizards, Tier 1 plating features
Quote-to-cash PDF reports (portrait + landscape variants, 16 new actions):
- Quotation / Sales Order, Work Order Traveller, Packing Slip, Bill of Lading,
  Certificate of Conformance (portrait added), Invoice, Payment Receipt
- Shared fp_portrait_styles + fp_landscape_styles base templates

Workflow gap fixes (fusion_plating_bridge_mrp):
- Auto-assign recipe from SO coating config in MrpProduction.action_confirm
- Auto-create draft CoC (fp.certificate) on MrpProduction.button_mark_done

Notifications overhaul (fusion_plating_notifications v2.0):
- Expanded TRIGGER_EVENTS to 7 (added quote_sent, mo_complete, shipped, payment_received)
- Shared _dispatch method replaces three duplicated send helpers
- Auto-attach PDF reports per template config (quote, SO, CoC, invoice, receipt, BoL)
- Rebuilt 7 email templates with fusion_claims accent-bar design
  (info/success color-coded, theme-safe, 600px max-width)
- New hooks: MrpProduction done, FpDelivery mark_delivered, AccountPayment post,
  SaleOrder action_quotation_send

Wizards (fusion_plating_configurator):
- fp.direct.order.wizard — skip quotation for repeat customers with PO in hand;
  optional new-revision drawing upload bumps fp.part.catalog revision and links
  new rev to the SO; creates + confirms the SO in one step
- fp.part.catalog.import.wizard — 3-step CSV import with dry-run preview,
  tolerant parsing (customer by name/email/xmlid, human-readable selections),
  duplicate detection, create-missing-customers option, single transaction commit
- Partner form stat buttons: Direct Order, Import Parts
- CSV template download button

Tier 1 practical plating features:
- T1.1 Hydrogen bake window enforcement (fp.coating.config.requires_bake_relief,
  auto-create fusion.plating.bake.window on plating WO finish, FpDelivery lockout
  when window is open)
- T1.2 Bath replenishment rules + pending suggestion queue
  (fusion.plating.bath.replenishment.rule + .suggestion, hook on bath log line
  create, operator Apply / Dismiss actions)
- T1.3 Rack/fixture library (fusion.plating.rack with MTO counter, strip
  schedule, lifecycle: active → needs_strip → stripping → retired)
- T1.4 Rework / strip-and-replate MOs (x_fc_is_rework, x_fc_original_production_id,
  Create Rework stat button on completed MOs)
- T1.5 Parts location (x_fc_current_location computed on mrp.production —
  "In progress: Alkaline Clean" / "Queued: Bake Oven" / "Ready to Ship")

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 23:41:12 -04:00
gsinghpal
7c7ef06057 folder rename 2026-04-16 20:53:53 -04:00