docs(jobs): split fp.job §5.1 fields by module ownership (Task 1.4)

Originally Task 1.4 was to add all spec §5.1 extension fields to
fp.job in core. The dependency-graph audit during implementation
revealed that 6 of those fields point to models in dependent
modules (configurator, quality, portal, logistics, bridge_mrp).
Adding them in core would invert the dependency graph.

Spec §5.1 now has a Module column. Core-safe fields stay in
fusion_plating/models/fp_job.py; cross-module fields are deferred
to their owning modules via _inherit = 'fp.job' in Phase 2.

Plan Task 1.4 narrative updated to reflect the reduced scope.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-24 21:54:35 -04:00
parent e4111ad000
commit f7a4cba5a8
2 changed files with 75 additions and 73 deletions

View File

@@ -96,50 +96,57 @@ process tree with cost/time aggregates.
Replaces `mrp.production` for plating jobs. One record per shop-floor job.
| Field | Type | Notes |
|---|---|---|
| `name` | Char | Sequence: `WH/JOB/00033`. The legacy "WH/MO/00033" labels stay only on migrated records (see §7). |
| `state` | Selection | `draft`, `confirmed`, `in_progress`, `done`, `cancelled`, `on_hold` |
| `partner_id` | Many2one(res.partner) | Customer; copied from SO |
| `product_id` | Many2one(product.product) | Reference part product (for inventory only) |
| `part_catalog_id` | Many2one(fp.part.catalog) | The actual part being plated; primary identifier |
| `qty` | Float | Quantity to plate |
| `qty_done` | Float | Quantity completed |
| `qty_scrapped` | Float | Quantity scrapped (rolled up from holds) |
| `date_deadline` | Datetime | Promised completion date |
| `date_planned_start` | Datetime | Planned start |
| `date_started` | Datetime | Actual start (first step start) |
| `date_finished` | Datetime | Actual completion |
| `origin` | Char | SO name for traceability |
| `sale_order_id` | Many2one(sale.order) | Source SO |
| `sale_order_line_ids` | Many2many(sale.order.line) | Lines that fed this job (group_tag collapse) |
| `recipe_id` | Many2one(fusion.plating.process.node) | The recipe template used |
| `step_ids` | One2many(fp.job.step, job_id) | The operations |
| `step_count` | Integer | Computed |
| `step_done_count` | Integer | Computed |
| `step_progress_pct` | Float | Computed: `step_done_count / step_count * 100` |
| `current_step_id` | Many2one(fp.job.step) | The operation currently in progress (or next ready) |
| `coating_config_id` | Many2one(fp.coating.config) | The coating spec |
| `facility_id` | Many2one(fp.facility) | Hard gate at confirm |
| `manager_id` | Many2one(res.users) | Plating manager |
| `priority` | Selection | `low`, `normal`, `high`, `rush` (operator-relevant ordering) |
| `customer_spec_id` | Many2one(fp.customer.spec) | Optional spec |
| `portal_job_id` | Many2one(fp.portal.job) | Customer portal binding (renamed from `x_fc_portal_job_id`) |
| `delivery_id` | Many2one(fp.delivery) | The shipment |
| `invoice_ids` | Many2many(account.move) | Linked invoices |
| `certificate_ids` | One2many(fp.certificate, job_id) | Certs generated |
| `batch_ids` | One2many(fp.batch, job_id) | Batches that ran through |
| `quality_hold_ids` | One2many(fp.quality.hold, job_id) | Holds raised |
| `consumption_ids` | One2many(fp.job.consumption, job_id) | Consumables |
| `qc_check_id` | Many2one(fp.quality.check) | Active QC check |
| `quoted_revenue` | Monetary | From SO |
| `actual_cost` | Monetary | Computed from steps + consumables |
| `margin` | Monetary | Computed |
| `margin_pct` | Float | Computed |
| `start_at_node_id` | Many2one(fusion.plating.process.node) | Rework: start at this recipe node |
| `override_ids` | One2many(fp.job.node.override, job_id) | Per-job opt-in/out |
| `current_location` | Char | Computed: "Queued: Bath 3" / "In progress: Oven A" / "Ready to ship" |
| `mail.thread, mail.activity.mixin` | Inherits | Chatter |
**Module ownership:** `fp.job` lives in `fusion_plating` core. Cross-module fields
(referencing models from `fusion_plating_configurator`, `_portal`, `_logistics`,
`_quality`, `_bridge_mrp`) **cannot** live in core without inverting the dependency
graph. Each owning module extends `fp.job` via `_inherit` to add its field. The
Phase 2 module `fusion_plating_jobs` becomes the umbrella that pulls all the
extensions together. Ownership is called out in the **Module** column below.
| Field | Type | Module | Notes |
|---|---|---|---|
| `name` | Char | core | Sequence: `WH/JOB/00033`. The legacy "WH/MO/00033" labels stay only on migrated records (see §7). |
| `state` | Selection | core | `draft`, `confirmed`, `in_progress`, `done`, `cancelled`, `on_hold` |
| `partner_id` | Many2one(res.partner) | core | Customer; copied from SO |
| `product_id` | Many2one(product.product) | core | Reference part product (for inventory only) |
| `qty` | Float | core | Quantity to plate |
| `qty_done` | Float | core | Quantity completed |
| `qty_scrapped` | Float | core | Quantity scrapped (rolled up from holds) |
| `date_deadline` | Datetime | core | Promised completion date |
| `date_planned_start` | Datetime | core | Planned start |
| `date_started` | Datetime | core | Actual start (first step start) |
| `date_finished` | Datetime | core | Actual completion |
| `origin` | Char | core | SO name for traceability |
| `sale_order_id` | Many2one(sale.order) | core | Source SO (sale_management is in core depends) |
| `sale_order_line_ids` | Many2many(sale.order.line) | core | Lines that fed this job (group_tag collapse) |
| `recipe_id` | Many2one(fusion.plating.process.node) | core | The recipe template used |
| `step_ids` | One2many(fp.job.step, job_id) | core | The operations |
| `step_count` | Integer | core | Computed |
| `step_done_count` | Integer | core | Computed |
| `step_progress_pct` | Float | core | Computed: `step_done_count / step_count * 100` |
| `current_step_id` | Many2one(fp.job.step) | core | The operation currently in progress (or next ready) |
| `facility_id` | Many2one(fusion.plating.facility) | core | Hard gate at confirm |
| `manager_id` | Many2one(res.users) | core | Plating manager |
| `priority` | Selection | core | `low`, `normal`, `high`, `rush` (operator-relevant ordering) |
| `invoice_ids` | Many2many(account.move) | core | Linked invoices (account is reachable via sale_management → sale → account) |
| `quoted_revenue` | Monetary | core | From SO |
| `actual_cost` | Monetary | core | Computed from steps + consumables |
| `margin` | Monetary | core | Computed |
| `margin_pct` | Float | core | Computed |
| `start_at_node_id` | Many2one(fusion.plating.process.node) | core | Rework: start at this recipe node |
| `current_location` | Char | core | Computed: "Queued: Bath 3" / "In progress: Oven A" / "Ready to ship" |
| `mail.thread, mail.activity.mixin` | Inherits | core | Chatter |
| `part_catalog_id` | Many2one(fp.part.catalog) | **`fusion_plating_configurator`** (`_inherit = 'fp.job'`) | The actual part being plated; primary identifier |
| `coating_config_id` | Many2one(fp.coating.config) | **`fusion_plating_configurator`** | The coating spec |
| `customer_spec_id` | Many2one(fusion.plating.customer.spec) | **`fusion_plating_quality`** | Optional spec |
| `portal_job_id` | Many2one(fusion.plating.portal.job) | **`fusion_plating_portal`** | Customer portal binding |
| `delivery_id` | Many2one(fusion.plating.delivery) | **`fusion_plating_logistics`** | The shipment |
| `qc_check_id` | Many2one(fusion.plating.quality.check) | **`fusion_plating_jobs`** (Phase 2) | Active QC check; model lives in current bridge_mrp, will move to jobs module |
| `certificate_ids` | One2many(fp.certificate, job_id) | **`fusion_plating_certificates`** | Certs generated |
| `batch_ids` | One2many(fp.batch, job_id) | **`fusion_plating_batch`** | Batches that ran through |
| `quality_hold_ids` | One2many(fp.quality.hold, job_id) | **`fusion_plating_quality`** | Holds raised |
| `consumption_ids` | One2many(fp.job.consumption, job_id) | **`fusion_plating_jobs`** (Phase 2) | Consumables |
| `override_ids` | One2many(fp.job.node.override, job_id) | **`fusion_plating_jobs`** (Phase 2) | Per-job opt-in/out |
**State machine:**
```