Files
Odoo-Modules/fusion-plating/docs/superpowers/specs/2026-04-12-entech-plating-workflow-design.md
gsinghpal d424dfdb19 docs: address spec review findings — 5 critical, 8 major issues fixed
- Add model naming convention table (fp.* for new, fusion.plating.* for existing)
- Add fusion_plating_certificates as dedicated module with fp.thickness.reading model
- Fix complexity_surcharge: companion model instead of JSON text field
- Add recipe_id domain constraint [('node_type', '=', 'recipe')]
- Align security groups with existing 4-level privilege hierarchy
- Add currency_id to all monetary models
- Clarify fp.quote.configurator as persistent model with state lifecycle
- Fix canonical model names (fusion.plating.portal.job, fusion.plating.delivery)
- Add auto-population rules for invoice strategy and configurator defaults
- Lighten bridge_mrp deps: gates as mixins in receiving/invoicing modules
- Add deployment strategy for fusion_tasks (same server, not standalone)
- Add data migration section for existing quote request coexistence
- Add work centre mapping note (fusion.plating.work.center ↔ mrp.workcenter)
- Change x_fc_account_hold_date to Datetime for audit precision
- Add bilingual CoC implementation note (QWeb, not ir.translation)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:05:42 -04:00

39 KiB

EN Tech Plating — End-to-End Workflow Design Spec

Date: 2026-04-12 Author: Nexa Systems (Claude-assisted) Client: EN Technologies (Electroless Nickel Technologies Inc.) Status: Approved for implementation planning


1. Overview

Complete end-to-end ERP workflow for an electroless nickel plating shop, replacing Steelhead Software. The system covers customer inquiry through invoicing, with a quotation configurator, parts receiving/inspection, flexible invoicing strategies, automated email notifications, certificate management, and local delivery dispatch.

Model Naming Convention

Context Convention Example
New custom models (all new modules) fp.* prefix fp.part.catalog, fp.certificate
Existing custom models (already in codebase) Keep fusion.plating.* fusion.plating.portal.job, fusion.plating.delivery
New fields on standard Odoo models x_fc_* prefix x_fc_po_number on sale.order
Legacy fields (from Studio era) x_studio_* Preserved, not renamed

The fp.* prefix is the new short-form convention for all models created in the new modules. Existing fusion.plating.* models are NOT renamed — they keep their current _name. All references in this spec use canonical _name values.

Architecture: Approach 2 — Dedicated Modules per Sub-System

Module Purpose Location
fusion_plating_configurator Quotation configurator, 3D viewer, pricing engine, part catalog fusion-plating/
fusion_plating_receiving Parts receiving, inspection, damage logging, PO matching fusion-plating/
fusion_plating_invoicing Invoice strategy engine (deposit/progress/net/COD), account holds fusion-plating/
fusion_plating_notifications Auto-email engine, notification templates, audit log fusion-plating/
fusion_plating_certificates Certificate registry (CoC, thickness, Nadcap, customer-specific) fusion-plating/
fusion_tasks Local delivery dispatch (forked from Westin, stripped of claims) Entech Plating/

Plus updates to existing modules:

  • fusion_plating_bridge_mrp — Recipe-to-WO generation (lightweight; gates live in their own modules)
  • fusion_plating_portal — Customer-facing configurator UI, 3D preview
  • fusion_plating_reports — CoC template updates, thickness report template
  • fusion_plating_quality — Thickness reading model for Fischerscope data

2. Sales Integration — Fusion Plating as Single Hub

The Fusion Plating app becomes the single workspace. Users never leave it. Sale orders are managed with custom plating-specific views.

Menu Structure

Fusion Plating (app)
├── Sales (default landing)
│   ├── Quotations                        (sale.order, state=draft/sent)
│   ├── Sale Orders                       (sale.order, state=sale)
│   ├── Customers                         (res.partner, customer_rank > 0)
│   └── Part Catalog                      (fp.part.catalog)
├── Configurator
│   ├── New Quote                         (fp.quote.configurator, persistent model)
│   ├── Coating Configurations            (fp.coating.config)
│   └── Pricing Rules                     (fp.pricing.rule)
├── Manufacturing
│   ├── Manufacturing Orders
│   ├── Work Orders
│   └── Plant Overview
├── Receiving & Inspection
├── Shipping & Delivery
│   ├── Deliveries                        (fp.delivery)
│   ├── Local Delivery Tasks              (fusion.delivery.task)
│   └── Routes                            (fp.route)
├── Certificates
│   ├── All Certificates                  (fp.certificate)
│   ├── Certificates of Conformance       (filtered: type=coc)
│   └── Thickness Reports                 (filtered: type=thickness_report)
├── Quality
├── Portal Jobs
├── Reports
└── Configuration

Sale Order Extensions (fields on sale.order)

  • x_fc_configurator_id — link back to configurator session
  • x_fc_part_catalog_id — customer part being ordered
  • x_fc_coating_config_id — coating configuration
  • x_fc_po_number — customer PO reference (Char)
  • x_fc_po_attachment_id — uploaded PO document
  • x_fc_po_received — Boolean
  • x_fc_po_override — Boolean (manager override — proceed without PO)
  • x_fc_po_override_reason — Text
  • x_fc_invoice_strategy — Selection (deposit, progress, net_terms, cod_prepay)
  • x_fc_deposit_percent — Float
  • x_fc_rush_order — Boolean
  • x_fc_delivery_method — Selection (local_delivery, shipping_partner, customer_pickup)
  • x_fc_receiving_status — Selection (not_received, partial, received, inspected) — computed
  • Smart buttons: Portal Job, Manufacturing Order, Delivery, Receiving, Invoices, Certificates

Custom Sale Order Views

  • List: Customer, PO#, Part, Coating, Qty, Total, Receiving Status, Job Status, Delivery Method
  • Form: inherits sale.order form, adds plating tabs (Part Details, Coating Config, Receiving, Job Tracking)
  • Kanban: cards grouped by stage (Draft → Quoted → PO Received → Parts Received → In Production → Shipped → Invoiced)

Permission-Based Visibility

The existing codebase defines a 4-level privilege hierarchy in fusion_plating/security/fp_security.xml: Operator → Supervisor → Manager → Administrator. These new groups are role-based and work alongside (not replacing) the existing privilege levels. A user has both a privilege level (what they can do: read/write/create/delete) and one or more roles (what they can see: which menus appear).

Role Group Menu Visibility Required Privilege Level
fp_group_estimator Sales, Configurator, Customers, Part Catalog Supervisor+
fp_group_shop_manager Everything (full menu) Manager+
fp_group_shop_floor Manufacturing, Work Orders, Plant Overview only Operator+
fp_group_receiving Receiving & Inspection, can view Sales (read-only) Operator+
fp_group_shipping Shipping & Delivery, can view Sales (read-only) Operator+
fp_group_quality Quality, can view Manufacturing Supervisor+
fp_group_accounting Sales (invoicing fields), Reports Supervisor+

Users are assigned to one or more role groups. The existing privilege hierarchy controls CRUD permissions; role groups control menu/view visibility. fp_group_shop_manager implies all other role groups (full access).

Standard Odoo groups are still required for underlying model access (e.g. sales_team.group_sale_salesman for SO access).


3. fusion_plating_configurator — Quotation Configurator & Pricing Engine

Users

  • Primary: Internal estimator (full control, detailed configurator, price override)
  • Secondary: Portal customer (simplified self-service, estimated pricing, 3D preview, lead gen)

Core Models

fp.part.catalog — Customer Part Library

Field Type Description
partner_id Many2one res.partner Customer (required)
name Char Part name/description
part_number Char Customer's part number
revision Char Revision letter/number
substrate_material Selection aluminium, steel, stainless, copper, titanium, other
geometry_source Selection 3d_model, manual, pdf_drawing
model_attachment_id Many2one ir.attachment STEP/STL/IGES file
drawing_attachment_ids Many2many ir.attachment PDF drawings
surface_area Float Surface area value
surface_area_uom Selection sq_in, sq_ft, sq_cm, sq_m
weight Float For shipping cost calc
dimensions_length Float Manual measurement
dimensions_width Float Manual measurement
dimensions_height Float Manual measurement
complexity Selection simple, moderate, complex, very_complex
masking_zones Integer Number of areas requiring masking
masking_description Text e.g. "mask threaded holes"
has_blind_holes Boolean Complexity flag
has_recesses Boolean Complexity flag
has_threads Boolean Complexity flag
notes Html
active Boolean Archivable

fp.coating.config — Coating Configuration Template

Field Type Description
name Char e.g. "EN Mid-Phos AMS 2404"
process_type_id Many2one fusion.plating.process.type Process type
recipe_id Many2one fusion.plating.process.node Default recipe. Domain: [('node_type', '=', 'recipe')]
phosphorus_level Selection low_phos, mid_phos, high_phos, na
thickness_min Float Min thickness
thickness_max Float Max thickness
thickness_uom Selection mils, microns, inches
spec_reference Char e.g. "AMS 2404"
certification_level Selection commercial, mil_spec, nadcap, nuclear
pre_treatment_ids Many2many fp.treatment Bead blast, zincate, etc.
post_treatment_ids Many2many fp.treatment Bake, passivate, chromate, etc.
active Boolean

fp.treatment — Pre/Post Treatment

Field Type Description
name Char e.g. "Bead Blast", "Zincate", "Bake"
treatment_type Selection pre, post
default_duration_minutes Float Estimated duration
currency_id Many2one res.currency Company currency (default)
default_cost Monetary Cost per application

fp.pricing.rule — Formula-Based Pricing Engine

Field Type Description
name Char Rule description
coating_config_id Many2one fp.coating.config Optional filter (global if blank)
substrate_material Selection Optional filter
certification_level Selection Optional filter
pricing_method Selection per_sqin, per_sqft, per_piece, flat_rate, formula
currency_id Many2one res.currency Company currency (default)
base_rate Monetary $ per unit
thickness_factor Float Multiplier per mil of thickness
complexity_surcharge_ids One2many fp.pricing.complexity.surcharge Surcharges by complexity level
masking_rate_per_zone Monetary $ per masking area
setup_fee Monetary One-time per batch
minimum_charge Monetary Floor price
rush_surcharge_percent Float Rush premium %
sequence Integer Priority — first matching rule wins
active Boolean

fp.pricing.complexity.surcharge — Complexity-Based Surcharge Line

Field Type Description
rule_id Many2one fp.pricing.rule Parent rule (cascade)
complexity Selection simple, moderate, complex, very_complex
surcharge_percent Float Surcharge % for this complexity level

fp.quote.configurator — The Configurator Session (Persistent Model)

This is a models.Model (NOT transient). Records persist for audit trail, re-quoting, and linking back from sale orders. The SO links back via x_fc_configurator_id.

Field Type Description
name Char Auto-sequence (CFG-00001)
state Selection draft, confirmed, cancelled
partner_id Many2one res.partner Customer
part_catalog_id Many2one fp.part.catalog For repeat parts
coating_config_id Many2one fp.coating.config Coating selection
quantity Integer Number of parts
batch_size Integer Parts per rack/barrel
surface_area Float From catalog or entered
thickness_requested Float
masking_zones Integer
complexity Selection simple, moderate, complex, very_complex
rush_order Boolean
turnaround_days Integer
delivery_method Selection local_delivery, shipping_partner, customer_pickup
currency_id Many2one res.currency Company currency (default)
shipping_fee Monetary
delivery_fee Monetary
calculated_price Monetary Computed from pricing rules
price_breakdown_html Html Rendered breakdown
estimator_override_price Monetary Final price (defaults to calculated)
sale_order_id Many2one sale.order Created SO (set on "Create Quotation")
notes Text

Lifecycle: draft → (estimator builds quote) → confirmed (when SO created) → cancelled (if abandoned). Confirmed records are read-only. Re-quoting creates a new configurator record.

Price Calculation Flow

Part Catalog (surface area, complexity, masking)
  + Coating Config (process, thickness, spec level)
  + Pricing Rules (matched by coating + substrate + cert level)
  + Quantity / Batch Size
  + Rush surcharge (if applicable)
  + Delivery / Shipping fees
  = Calculated Price
  → Estimator reviews & overrides if needed
  → Final quote price

3D Viewer

  • OWL component using Three.js for STL rendering and OCCT (OpenCascade) WASM for STEP parsing
  • Renders on both backend configurator form and portal page
  • Features: wireframe/solid toggle, rotate/zoom, surface area highlight
  • Server-side surface area calculation: Python trimesh (STL) / cadquery/OCP (STEP)
  • Fallback: manual measurements if server can't parse the file
  • Roadmap: Claude Vision for PDF drawing measurement extraction

Portal Side (Customer-Facing)

  • Simplified wizard: upload part → select coating type → see estimated price range
  • Uses same fp.quote.configurator model with restricted fields
  • Customer sees estimated price range (not exact), 3D preview
  • Submits → creates fp.quote.request with configurator data attached
  • Internal estimator sees customer's config and refines it

Configurator → Sale Order Flow

  1. Estimator opens Configurator → builds quote
  2. Clicks "Create Quotation" → sale.order created with all x_fc_* fields
  3. SO line(s) auto-created (product = service product per coating type, qty, price = estimator's final price)
  4. Estimator reviews SO → sends quotation
  5. Customer accepts → confirms SO → triggers downstream flow

4. fusion_plating_receiving — Parts Receiving & Inspection

Core Models

fp.receiving — Receiving Record

Field Type Description
name Char Auto-sequence (RCV-00001)
sale_order_id Many2one sale.order Required. Design decision: one receiving record per SO. If a customer ships parts for multiple SOs in one box, create separate receiving records per SO (receiver splits the count). This keeps the SO↔receiving link clean and avoids Many2many complexity.
partner_id Many2one res.partner Related from SO
po_number Char Related from SO x_fc_po_number
received_by_id Many2one res.users Who logged it
received_date Datetime Default=now
state Selection draft, inspecting, accepted, discrepancy, resolved
expected_qty Integer From SO line
received_qty Integer Entered by receiver
qty_match Boolean Computed: received == expected
carrier_name Char Who delivered
carrier_tracking Char Inbound tracking #
notes Html
line_ids One2many fp.receiving.line Per-part detail
damage_ids One2many fp.receiving.damage Damage log
attachment_ids Many2many ir.attachment Photos

fp.receiving.line — Per-Part Receiving Detail

Field Type Description
receiving_id Many2one fp.receiving Cascade
part_catalog_id Many2one fp.part.catalog Optional
part_number Char
description Char
expected_qty Integer
received_qty Integer
condition Selection good, damaged, mixed
notes Text

fp.receiving.damage — Damage Log Entry

Field Type Description
receiving_id Many2one fp.receiving Cascade
description Text What's damaged
severity Selection cosmetic, functional, rejected
photo_ids Many2many ir.attachment
action_required Selection none, notify_customer, return_parts, proceed_as_is
customer_notified Boolean
customer_response Text
resolved Boolean

Workflow

SO Confirmed → Receiving record auto-created (state=draft)
  → Parts arrive → receiver enters qty, inspects condition
  → Match + good → state=accepted
  → Mismatch or damage → state=discrepancy
    → SO flagged, follow-up activity created
    → Customer contacted → resolution logged → state=resolved
  → Accepted/Resolved → SO x_fc_receiving_status = 'received'
  → Manufacturing can proceed

Manufacturing Gate

  • mrp.production.action_confirm() checks sale_order.x_fc_receiving_status
  • If not received → warning dialog (manager can override)
  • Soft gate — warns, doesn't hard-block (flexibility for handshake deals, urgent jobs)

5. fusion_plating_invoicing — Invoice Strategy Engine

Invoice Strategies

Strategy Behaviour
deposit Deposit invoice for X% on SO confirmation. Balance after shipping.
progress Invoice per MO as each completes.
net_terms Single invoice after shipping. Payment on terms.
cod_prepay Full invoice on SO confirmation. Manufacturing blocked until paid.

Core Models

fp.invoice.strategy.default — Customer-Level Default

Field Type Description
partner_id Many2one res.partner Unique per customer
default_strategy Selection deposit, progress, net_terms, cod_prepay
default_deposit_percent Float e.g. 50.0
payment_term_id Many2one account.payment.term
notes Text

Auto-Population Rules

When a customer is selected on a new SO:

  1. Look up fp.invoice.strategy.default for that partner_id
  2. If found → auto-fill x_fc_invoice_strategy and x_fc_deposit_percent from the default
  3. If not found → leave blank (estimator must select manually)
  4. Estimator can always override per order

When a coating config is selected in the configurator:

  1. Auto-fill thickness_requested from coating_config.thickness_min (default to minimum)
  2. Auto-fill surface area UOM from company default setting

When a part catalog entry is selected:

  1. Auto-fill surface_area, complexity, masking_zones, substrate_material from the catalog entry
  2. These can be overridden per-quote if the part has changed

Account Hold (extends res.partner)

Field Type Description
x_fc_account_hold Boolean Manually set by accounting
x_fc_account_hold_reason Text Why hold was placed
x_fc_account_hold_date Datetime When placed (Datetime for audit precision)
x_fc_account_hold_by_id Many2one res.users Who placed it

Account Hold Behaviour

Action Hold Active Result
Create new SO Yes Warning banner. SO can still be created.
Confirm SO Yes Blocked. Manager override available.
Create invoice Yes Blocked. Manager override available.
Ship / mark delivered Yes Blocked. Manager override available.
Customer visits portal Yes No visible indication.

Roadmap: auto-hold computed from account.move aging.

Invoice Automation

  • Deposit: SO confirmed → auto-create deposit invoice (X%) → balance invoice after shipping
  • Progress: Each MO done → invoice for that MO's portion → final invoice for remaining balance
  • Net terms: Delivery complete → auto-create full invoice → payment terms applied
  • COD/Prepay: SO confirmed → auto-create full invoice → MO blocked until payment reconciled

Shipping Method Price Adjustment

  • Method changes after invoicing:
    • Draft invoice → amend the line
    • Posted invoice → supplementary invoice or credit note

6. fusion_plating_notifications — Auto-Email Engine

Notification Triggers

Trigger Event Email Name Attachments Recipient
Quotation sent Quote Ready Quote PDF Customer contact
SO confirmed Order Confirmation SO PDF Customer contact
Parts received Parts Received Customer contact
MO complete Ready for Pickup/Ship Customer contact
Delivery shipped (carrier) Shipment Notification CoC, Thickness Report, Invoice Customer contact
Delivery completed (local) Delivery Confirmation CoC, Thickness Report, Invoice, POD Customer contact
Invoice posted Invoice Notification Invoice PDF Billing contact
Deposit invoice created Deposit Required Deposit Invoice PDF Billing contact

Core Models

fp.notification.template — Configurable Email Templates

Field Type Description
name Char Template name
trigger_event Selection Event type
mail_template_id Many2one mail.template Actual Odoo template
active Boolean Can disable specific notifications
attach_coc Boolean
attach_thickness_report Boolean
attach_invoice Boolean
attach_packing_list Boolean
attach_pod Boolean
cc_internal_ids Many2many res.users Internal CCs

fp.notification.log — Audit Trail

Field Type Description
template_id Many2one fp.notification.template
trigger_event Selection
sale_order_id Many2one sale.order
partner_id Many2one res.partner
sent_date Datetime
recipient_email Char
attachment_names Text Comma-separated list
status Selection sent, failed, bounced
error_message Text
mail_mail_id Many2one mail.mail

Document Assembly (Shipment Email)

  1. Find portal job linked to SO/MO
  2. Generate CoC PDF (bilingual EN/FR, customer logo, Nadcap badge if applicable)
  3. Attach thickness report if available
  4. Attach invoice PDF
  5. Include tracking info in email body (carrier tracking # or driver ETA)
  6. Send to customer contact
  7. Log in fp.notification.log

CoC Report Updates

  • Customer logo placement (from partner.image_1920)
  • Nadcap badge (conditional)
  • EN Tech branding (replace Steelhead)
  • Recorded thickness field
  • Process description with spec references
  • Bilingual certification statement
  • Quantities: Shipped/Exp, NC Qty columns
  • Configurable certifying authority signature

Thickness / Measurement Report (NEW template)

Based on Fischerscope XDAL 600 output:

  • EN Tech header
  • Equipment info (model, product, application)
  • Microscope image (attached photo)
  • Reading data table (NiP mils, Ni %, P %)
  • Statistical summary (Mean, Std Dev, CoV%, Range)
  • Calibration standard reference
  • Operator, date/time
  • Data entry: manual for now, future Fischerscope CSV import

Work Centre Mapping Note

The codebase has two work centre models: fusion.plating.work.center (core) and mrp.workcenter (standard MRP). Recipe nodes reference fusion.plating.work.center; MRP work orders use mrp.workcenter. The recipe-to-WO generation logic in fusion_plating_bridge_mrp must map between them. Each fusion.plating.work.center should have an x_fc_mrp_workcenter_id field linking to the corresponding mrp.workcenter. This mapping field should be added to the core module.


7. fusion_plating_certificates — Certificate Registry

Module owner: fusion_plating_certificates (NEW dedicated module). Dependencies: fusion_plating, fusion_plating_portal, fusion_plating_reports, mrp

This module owns fp.certificate and fp.thickness.reading. It depends on fusion_plating_portal for the fusion.plating.portal.job link and on fusion_plating_reports for report generation.

Model: fp.certificate

Field Type Description
name Char Auto-sequence (CERT-00001)
certificate_type Selection coc, thickness_report, mill_test, nadcap_cert, customer_specific
partner_id Many2one res.partner Customer
sale_order_id Many2one sale.order
production_id Many2one mrp.production
portal_job_id Many2one fusion.plating.portal.job Uses canonical model name
part_number Char Denormalized for fast search
process_description Char e.g. "ELECTROLESS NICKEL PLATING PER AMS 2404"
spec_reference Char
po_number Char Customer PO ref
entech_wo_number Char Internal WO #
quantity_shipped Integer
issued_by_id Many2one res.users
certified_by_id Many2one res.users Signing authority
issue_date Date Default=today
attachment_id Many2one ir.attachment Generated PDF
thickness_reading_ids One2many fp.thickness.reading Linked measurements
state Selection draft, issued, voided
void_reason Text
notes Html

Model: fp.thickness.reading — Fischerscope Measurement Data

Field Type Description
certificate_id Many2one fp.certificate Parent certificate (cascade)
production_id Many2one mrp.production Link to MO (independent of cert)
reading_number Integer Reading sequence (n=1, n=2, n=3)
nip_mils Float(10,4) NiP thickness in mils
ni_percent Float(6,3) Nickel content %
p_percent Float(6,4) Phosphorus content %
position_label Char Where on the part this reading was taken
equipment_model Char e.g. "Fischerscope XDAL 600"
product_ref Char e.g. "2805031 / NiP/Al-alloys 2805030"
calibration_std_ref Char e.g. "NiP/Al STD SET SN 100174568"
microscope_image_id Many2one ir.attachment Microscope photo
operator_id Many2one res.users Who took the reading
reading_datetime Datetime When reading was taken
measuring_time_seconds Integer e.g. 120

Statistical fields (computed from reading lines per certificate):

  • mean_nip_mils, stddev_nip_mils, cov_percent, range_nip_mils — computed on fp.certificate from its thickness_reading_ids

Auto-Creation

When CoC or thickness report is generated, fp.certificate record auto-created with PDF attached.

Views

  • List (default, newest first): Issue Date, Cert #, Type, Customer, Part #, PO #, Entech WO#, Process, Qty, Issued By, Status
  • Search: Quick filters by Customer, Certificate Type, Date Range, Part Number, PO Number. Group by: Customer, Type, Month, Issued By.
  • Form: Certificate type badge, state buttons (Issue/Void), customer info, part details, tabs for Thickness Readings, Attachments, Notes. "Regenerate PDF" and "Send to Customer" buttons.

CoC Bilingual Implementation

The bilingual EN/FR certification statement uses QWeb template logic with t-if on a bilingual flag (default: True for Canadian compliance). The English and French text blocks are both rendered in the same template — not using Odoo's ir.translation system, since both languages must appear on the same document simultaneously.


8. fusion_tasks (Entech Plating) — Local Delivery Dispatch

Fork & Strip Strategy

Remove:

  • Cross-instance sync (fusion.task.sync.config, shadow tasks)
  • fusion_claims.* config parameters → rename to fusion_tasks.*
  • sales_team dependency
  • Irrelevant task types (repair, troubleshoot, assessment, ltc_visit, maintenance, installation)
  • All sync-related fields (x_fc_sync_*)

Keep:

  • Google Maps integration (Leaflet.js map view)
  • GPS tracking (fusion.technician.location → fusion.driver.location)
  • Geocoding (_geocode_address())
  • Route planning / scheduling / conflict avoidance
  • Push notifications (fusion.push.subscription)
  • Map view JS/SCSS/XML

Adapted Model: fusion.delivery.task

Renamed from fusion.technician.task.

Task Types (reduced):

  • delivery — outbound delivery
  • pickup — collect parts from customer
  • return — return rejected/damaged parts
  • rush — same-day urgent

Status Workflow:

  • pendingscheduleden_routedelivered (or failed)

Key Fields:

Field Type Description
delivery_id Many2one fusion.plating.delivery Links to logistics
sale_order_id Many2one sale.order
portal_job_id Many2one fusion.plating.portal.job Uses canonical model name
partner_id Many2one res.partner Customer
driver_id Many2one hr.employee Renamed from technician_id
vehicle_id Many2one fusion.plating.vehicle From logistics module
packages_count Integer Number of boxes/crates
weight_total Float Total weight
requires_signature Boolean POD required
requires_photo Boolean Photo proof required
coc_attachment_id Many2one ir.attachment CoC to hand to customer

Delivery Integration:

  • action_mark_delivered(): logs GPS + timestamp, captures signature/photo, updates fp.delivery → delivered, cascades to portal job → shipped, triggers shipment notification email
  • action_mark_failed(): logs reason, creates follow-up activity

Dependencies & Deployment

'depends': ['base', 'mail', 'hr', 'fusion_plating_logistics'],

Deployment strategy: fusion_tasks lives in a separate repo (Entech Plating/) but is deployed to the SAME server as the fusion_plating modules. Both repos are copied to /mnt/extra-addons/custom/ on the target server. The fusion_plating_logistics dependency is therefore always available at install time. There is no standalone driver-only install scenario — drivers access the system via the same Odoo instance. The standalone "Delivery Dispatch" menu (below) provides a driver-focused view without needing a separate deployment.

Menu Placement

Inside Fusion Plating: Shipping & Delivery → Local Delivery Tasks, Driver Map

Standalone (optional): Delivery Dispatch app for drivers.


9. Complete End-to-End Workflow

Stage 1: Customer Inquiry

  • Portal path: Customer uploads 3D/PDF on portal → sees estimated price → submits → fp.quote.request created
  • Email/phone path: Estimator creates fp.quote.request manually, uploads customer's files
  • Modules: fusion_plating_portal, fusion_plating_configurator

Stage 2: Quotation

  • Estimator opens Configurator inside Fusion Plating app
  • Selects/creates part in Part Catalog
  • 3D model → auto surface area + 3D preview; PDF → manual measurements
  • Selects Coating Configuration
  • Pricing engine calculates from rules; estimator reviews/overrides
  • Adds delivery/shipping fees, sets invoice strategy
  • "Create Quotation" → sale.order with all x_fc_* fields
  • Sends quotation → email notification with Quote PDF
  • Modules: fusion_plating_configurator, fusion_plating_notifications

Stage 3: Order Confirmation

  • Customer accepts + submits PO (email or portal)
  • PO number entered on SO, PO document uploaded (or manager override for handshake deals)
  • SO confirmed:
    • Account hold check → blocked if hold active (manager override)
    • Invoice strategy fires (deposit/COD → auto-invoice; net_terms/progress → no invoice yet)
    • Email: Order Confirmation + SO PDF
    • Receiving record auto-created (draft)
    • Portal job auto-created (received)
  • Modules: fusion_plating_invoicing, fusion_plating_receiving, fusion_plating_bridge_mrp, fusion_plating_notifications

Stage 4: Parts Receiving

  • Parts arrive → receiver opens receiving record
  • Counts parts, inspects condition
  • Good → accepted; damage/mismatch → discrepancy → follow-up → resolved
  • Email: Parts Received
  • Portal job → in_progress
  • Modules: fusion_plating_receiving, fusion_plating_notifications

Stage 5: Manufacturing Planning

  • MO created from SO (standard sale_mrp)
  • Receiving gate: warns if parts not received
  • COD gate: warns if prepay not paid
  • Planner assigns recipe, configures opt-in/out steps
  • Recipe → Work Orders generated (one WO per operation node, steps = WO instructions)
  • Modules: fusion_plating_bridge_mrp

Stage 6: Manufacturing Execution

  • Operators work WOs on shopfloor (Plant Overview kanban, timers, bath/tank assignment)
  • Quality holds if needed
  • All WOs done → MO done:
    • Portal job → ready_to_ship
    • fp.delivery auto-created (draft)
    • Thickness readings entered
    • CoC + thickness report generated → fp.certificate records created
  • Progress invoicing: if strategy=progress, invoice this MO's portion
  • Modules: fusion_plating_shopfloor, fusion_plating_bridge_mrp, fusion_plating_quality, fusion_plating_invoicing

Stage 7: Shipping / Local Delivery

Shipping Partner (Purolator, FedEx, UPS, etc.):

  • fp.delivery scheduled with carrier + tracking #
  • Packing list generated, delivery marked shipped
  • Module: fusion_plating_logistics

Local Delivery (EN Tech driver):

  • fusion.delivery.task created, driver + vehicle assigned
  • Driver Map shows live GPS tracking
  • Driver delivers → signature/photo POD → cascades to fp.delivery
  • Module: fusion_tasks (Entech Plating)

Customer Pickup:

  • Email: Ready for Pickup
  • Customer arrives → parts released → signature → fp.delivery marked delivered

All paths:

  • Portal job → shipped
  • Email: CoC + Thickness Report + Invoice + Tracking/ETA
  • Modules: fusion_plating_logistics, fusion_tasks, fusion_plating_notifications

Stage 8: Invoicing & Payment

  • Strategy determines timing:
    • deposit → balance invoice after shipping
    • progress → final invoice for remaining balance
    • net_terms → full invoice after shipping
    • cod_prepay → already invoiced & paid
  • Delivery method change after invoice → supplementary invoice or credit note
  • Invoice posted → portal job → complete → email with Invoice PDF
  • Modules: fusion_plating_invoicing, fusion_plating_bridge_mrp, fusion_plating_notifications

Stage 9: Customer Portal

  • Full job lifecycle visible: progress bar (received → complete)
  • Documents tab: CoC, thickness report, invoice — downloadable
  • Part catalog: saved parts with 3D preview
  • Order history: past orders, re-order from catalog
  • Quote request history, tracking info, notification history
  • Modules: fusion_plating_portal

10. Module Dependency Graph

fusion_plating (core)
  ├── fusion_plating_configurator
  │     └── depends: fusion_plating, sale_management
  ├── fusion_plating_receiving
  │     └── depends: fusion_plating, sale_management
  │     └── provides: mrp.production gate mixin (overrides action_confirm)
  ├── fusion_plating_invoicing
  │     └── depends: fusion_plating, sale_management, account
  │     └── provides: invoice strategy automation, account hold on res.partner
  ├── fusion_plating_notifications
  │     └── depends: fusion_plating, fusion_plating_reports, mail
  ├── fusion_plating_certificates
  │     └── depends: fusion_plating, fusion_plating_portal,
  │                  fusion_plating_reports, mrp
  ├── fusion_plating_bridge_mrp  (lighter — gates live in receiving/invoicing)
  │     └── depends: fusion_plating, fusion_plating_configurator, mrp
  │     └── soft-depends: fusion_plating_receiving, fusion_plating_invoicing
  ├── fusion_plating_portal
  │     └── depends: fusion_plating, fusion_plating_configurator,
  │                  fusion_plating_notifications, portal
  ├── fusion_plating_logistics
  │     └── depends: fusion_plating
  └── fusion_tasks (Entech Plating — separate repo, same server)
        └── depends: fusion_plating_logistics, hr, mail

Note on bridge_mrp: The receiving gate and invoice strategy gates are implemented as lightweight mixins within fusion_plating_receiving and fusion_plating_invoicing respectively (each overrides mrp.production independently). This avoids funnelling all dependencies through bridge_mrp. Bridge_mrp focuses on recipe-to-WO generation and the configurator link.


11. Pricing Variables Reference

All 10 pricing variables that drive the configurator:

  1. Surface area — more area = more chemistry consumed
  2. Coating type — EN, chrome, anodize, black oxide (different bath costs)
  3. Thickness spec — more passes/dwell time
  4. Substrate material — aluminium needs zincate pre-treatment
  5. Quantity / batch size — more parts per rack = lower per-unit cost
  6. Part complexity — blind holes, recesses, masking areas
  7. Masking requirements — labour-intensive
  8. Spec / certification level — Nadcap/aerospace = more QC overhead
  9. Turnaround time — rush = premium
  10. Pre/post treatment — bead blast, bake, passivate

12. Key Architectural Decisions

Decision Resolution
Configurator primary user Internal estimator; portal is simplified lead-gen
3D file handling STEP/STL auto surface area calc + 3D preview; PDF manual (Claude Vision roadmap)
Pricing model Formula-calculated with estimator override
Part catalog Customer part library for repeat business + one-off support
PO requirement Required before manufacturing, but manager override available
Invoice strategies All 4 supported (deposit, progress, net_terms, cod_prepay), configurable per order
Account hold Manual for now, auto from aging on roadmap
Shipping decision Set at quote time, changeable later with price adjustment
Local delivery Fork fusion_tasks, strip claims, keep GPS/maps
Certificate management Unified fp.certificate registry with filters, auto-creation on report generation
Recipe → WO mapping One WO per operation node, steps become WO instructions

13. Data Migration: Existing Quote Request Flow

The existing fusion.plating.quote.request model has an action_create_sale_order() method that creates basic SOs. The new configurator introduces a parallel, richer path.

Coexistence strategy:

  • The existing action_create_sale_order() on fusion.plating.quote.request remains functional — it is the "quick path" for simple quotes that don't need the full configurator
  • The new configurator is the "full path" for detailed quotes with part catalog, coating config, and pricing rules
  • When a quote request comes in via portal, the estimator chooses: use the configurator (creates fp.quote.configurator → SO) or use the quick path (existing action_create_sale_order())
  • Both paths create SOs with x_fc_* fields. The quick path leaves configurator-specific fields blank; the full path populates everything
  • No existing data needs migration — the two paths coexist

14. Roadmap Items (Not in Initial Build)

  • Claude Vision for PDF drawing measurement extraction
  • Auto account hold computed from invoice aging
  • Fischerscope CSV import (auto-populate thickness readings)
  • Multi-driver route optimization
  • Customer-specific certificate templates
  • Product configurator on portal (dynamic pricing preview)
  • Tags on recipe nodes
  • Dashboard transitions on recipe nodes
  • Treatment groups / choices on recipe nodes