This page describes the sub-modules of src/cluster_erp/modules/production/ that define how a product is made: routings/ (with the scaffold in routings/scaffold.py), operation_types/, routing_templates/ (with cut technology rules), and component_allocations/. A routing (Routing) is the operation sequence of one product breakdown. Its component allocations tie BOM items and other inputs to operations; together they form the operation BOM (eBOM). The BOM side is on the BOM module.
Scope and source¶
- Defined in: the
models.py,schemas.py,services.py, androutes.pyof the four sub-modules,routings/scaffold.py(RoutingScaffolder), androuting_templates/metadata.py. - Count: 9 tables; 28 routing routes, 8 operation type routes, 16 routing template and rule routes, and 6 allocation routes (
@router.and@rules_router.decorators).
Routing fields¶
| Entity | Table | Key fields | Source |
|---|---|---|---|
Routing |
production_routings |
product_id, product_model_id, product_version_id, code, name, status (default draft), valid_from, scaffold_bom_version_id, is_stale |
src/cluster_erp/modules/production/routings/models.py:15-68 |
RoutingOperation |
production_routing_operations |
operation_no, work_center_id, operation_type_code, description, setup_time_min, run_time_per_unit_min, scrap_pct, output_description, output_product_id with model and version, source, source_fields |
src/cluster_erp/modules/production/routings/models.py:71-140 |
PrepOperation |
production_prep_operations |
routing_id, bom_item_id, seq, operation_type_code, work_center_id, setup_time_min, run_time_per_unit_min, note, source |
src/cluster_erp/modules/production/routings/models.py:143-202 |
ComponentAllocation |
production_component_allocations |
routing_operation_id, input_kind (bom_item, operation_output, or product), bom_item_id, bom_version_id, source_operation_id, product breakdown, qty |
src/cluster_erp/modules/production/component_allocations/models.py:14-117 |
OperationType |
production_operation_types |
code, name, numeric_code, op_group, has_material_io, default_setup_min, translations, is_active |
src/cluster_erp/modules/production/operation_types/models.py:13-57 |
RoutingTemplate, RoutingTemplateOp |
production_routing_templates, production_routing_template_ops |
code, name, product_category_id, material_type; ops with seq, operation_type_code, default times |
src/cluster_erp/modules/production/routing_templates/models.py:20-104 |
CutTechnologyRule |
production_cut_technology_rules |
material_type, stock_form (length or sheet), operation_type_code |
src/cluster_erp/modules/production/routing_templates/models.py:107-146, src/cluster_erp/modules/production/routing_templates/schemas.py:104 |
Routing statuses¶
A routing moves from draft to active to obsolete (src/cluster_erp/modules/production/routings/services.py:44-48). Activation is refused while blockers remain: an operation without a work center, without an operation type, or with zero run time per unit, or a prep operation without an operation type (src/cluster_erp/modules/production/routings/services.py:541-599, src/cluster_erp/modules/production/routings/services.py:610-649). GET /routings/{routing_id}/readiness returns these blockers (src/cluster_erp/modules/production/routings/routes.py:319). When a new BOM version becomes active, live routings of the same breakdown are marked stale (src/cluster_erp/modules/production/module.py:195-224).
eBOM scaffold¶
The scaffold derives a routing from the BOM of one product breakdown. The diagram shows the plan and apply path.
flowchart TD P["POST /routings/scaffold-plan with product, model, version"] --> T["load_tree: GetBomScaffoldTree"] T --> F["flatten_inputs: phantom children lifted, qty multiplied"] F --> J["final joining operation with material inputs"] F --> C["cut prep for make_from_stock items"] J --> TP["resolve_template: RoutingTemplate by category and material type"] C --> CR["cut_rules: CutTechnologyRule by material and stock form"] TP --> WC["wc_candidates from work center capabilities"] CR --> WC WC --> Q["plan with questions and plan_hash"] Q --> A["POST /routings/scaffold-apply with answers"] A --> H["plan_hash recomputed from current BOM"] H --> M["Routing, RoutingOperation, PrepOperation, ComponentAllocation rows"] M --> I["CreateScaffoldIntermediate for operation outputs"]
In prose: scaffold-plan is a dry run that needs the full product breakdown (src/cluster_erp/modules/production/routings/routes.py:155-206). The scaffolder reads the BOM tree with GetBomScaffoldTree (src/cluster_erp/modules/production/routings/scaffold.py:177-217). Non-phantom items become material inputs of one final joining operation; phantom items are never inputs, and their children are lifted with the phantom's quantity multiplied (src/cluster_erp/modules/production/routings/scaffold.py:8-12, src/cluster_erp/modules/production/routings/scaffold.py:247-335). A make-from-stock item with length stock and a cut length gets a mandatory cut prep step; sheet stock gets a 2D cut candidate (src/cluster_erp/modules/production/routings/scaffold.py:13-15, src/cluster_erp/modules/production/routings/scaffold.py:336-348). A routing template that matches the product's category and material type supplies the operation sequence; two equally specific templates are refused (src/cluster_erp/modules/production/routings/scaffold.py:22-28, src/cluster_erp/modules/production/routings/scaffold.py:470-540). A cut technology rule answers the cut question (src/cluster_erp/modules/production/routings/scaffold.py:29-31, src/cluster_erp/modules/production/routings/scaffold.py:589-622). Work centers come only from declared capabilities (src/cluster_erp/modules/production/routings/scaffold.py:16-21, src/cluster_erp/modules/production/routings/scaffold.py:388-469). Process operations are never created automatically unless a template declares them (src/cluster_erp/modules/production/routings/scaffold.py:22-24). The plan carries a plan_hash over the breakdown, BOM version, and item quantities (src/cluster_erp/modules/production/routings/scaffold.py:41-43, src/cluster_erp/modules/production/routings/scaffold.py:218-246).
scaffold-apply writes the plan in one transaction. A changed BOM gives a 409, a missing required answer a 422, and an existing live routing on the breakdown a 409 (src/cluster_erp/modules/production/routings/routes.py:207-262, src/cluster_erp/modules/production/routings/scaffold.py:1038-1354). When an operation has an output, the scaffolder asks products_and_services to create or reuse an intermediate product with CreateScaffoldIntermediate (src/cluster_erp/modules/production/routings/scaffold.py:2234). Tree mode plans and applies sub-assemblies all or nothing (src/cluster_erp/modules/production/routings/scaffold.py:962-1037, src/cluster_erp/modules/production/routings/scaffold.py:1355-1425). copy-to deep-copies a routing onto another breakdown and re-binds allocations to the target's active BOM; unmatched rows are reported (src/cluster_erp/modules/production/routings/scaffold.py:35-39, src/cluster_erp/modules/production/routings/scaffold.py:2077-2460).
Routes¶
| Method and path | Permission | Source |
|---|---|---|
GET, POST /routings/; GET, PUT, DELETE /routings/{routing_id}; POST /routings/bulk-delete; POST /routings/{routing_id}/status |
routing.read, .create, .update, .delete, .bulk_delete |
src/cluster_erp/modules/production/routings/routes.py:46-398 |
POST /routings/scaffold-from-bom, /scaffold-tree-from-bom, /scaffold-plan, /scaffold-apply, /{routing_id}/copy-to |
routing.create |
src/cluster_erp/modules/production/routings/routes.py:86-263 |
GET /routings/for-product/{product_id}, /{routing_id}/readiness, /{routing_id}/full |
routing.read |
src/cluster_erp/modules/production/routings/routes.py:298-333 |
Operations, operation inputs, and prep operations under /routings |
routing.read, routing.update |
src/cluster_erp/modules/production/routings/routes.py:415-672 |
/operation-types routes, including POST /operation-types/seed-defaults |
routing.* |
src/cluster_erp/modules/production/operation_types/routes.py:26-121 |
/routing-templates, template ops, and cut technology rules |
routing_template.*, routing_template_op.*, cut_technology_rule.* |
src/cluster_erp/modules/production/routing_templates/routes.py:42-261 |
| Component allocations | routing.read, routing.update, routing.bulk_delete |
src/cluster_erp/modules/production/component_allocations/routes.py:29-114 |
Constraints and validation¶
- A component allocation is unique per BOM item and operation, per operation and source operation, and per operation and product, among live rows (
src/cluster_erp/modules/production/component_allocations/models.py:27-56). - The
bommodule reads allocations throughGetComponentAllocationsto fill operation type and work center in its explosion (src/cluster_erp/modules/production/module.py:145-147).
Discrepancies¶
Terms introduced¶
| Term | Code identifier | Definition | Turkish term | Source |
|---|---|---|---|---|
| routing | Routing |
The operation sequence that makes one product breakdown. | Rota | src/cluster_erp/modules/production/routings/models.py:15 |
| prep operation | PrepOperation |
A preparation step for one BOM item, such as a cut. | Hazırlık operasyonu | src/cluster_erp/modules/production/routings/models.py:143 |
| component allocation | ComponentAllocation |
An input edge saying which operation consumes which item, output, or product. | Bileşen ataması | src/cluster_erp/modules/production/component_allocations/models.py:14 |
| routing scaffold | RoutingScaffolder |
The wizard that derives a routing from the BOM and asks for missing facts. | Rota iskeleti | src/cluster_erp/modules/production/routings/scaffold.py:167 |
| cut technology rule | CutTechnologyRule |
A rule that maps material type and stock form to a cut operation type. | Kesim teknolojisi kuralı | src/cluster_erp/modules/production/routing_templates/models.py:107 |
Related pages¶
Verified against commit 92f8051 on 2026-11-13.