The sales_orders module in src/cluster_erp/modules/sales_orders/ turns a customer purchase order into a sales order and follows it to delivery. It checks the customer PO against the sent quote, freezes each PO revision, copies quote lines into order lines, tracks individual units (assets), ships them in shipments with packages and transport data, and generates the packing list and the delivery note. This page is the overview; the sub-topics have their own pages.
At a glance¶
| Item | Value | Source |
|---|---|---|
| Package | src/cluster_erp/modules/sales_orders/ |
folder |
| Module class | Module |
src/cluster_erp/modules/sales_orders/module.py:18 |
name / version |
sales_orders / 0.1.0 |
src/cluster_erp/modules/sales_orders/module.py:20-25 |
| API prefix | /api/v1/sales_orders (ModuleBase.api_prefix) |
src/cluster_erp/core/module_base.py:37-38 |
| Sub-modules | 6: orders, order_lines, shipments, trade_documents, units, settings |
folder listing |
| Tables | 14 | __tablename__ in the six models.py files |
| Entities in metadata | 13 keys in entities |
src/cluster_erp/modules/sales_orders/module.py:371-385 |
| Routes | 68 route decorators in the package | grep for @...router.get/post/put/patch/delete |
| Actions | 21 ActionMeta entries |
grep "ActionMeta(" in the package |
| Migrations | 16 files | files in migrations/versions/ whose text contains one of the 14 table names |
| Web app presence | Catalogue app sales-orders |
src/cluster_erp/modules/app_store/catalog.json (entry sales-orders) |
| Desktop presence | generic widgets only | src/cluster_erp/desktop/modules/ has no sales_orders folder |
What the module does¶
- Creates an order from a customer PO that references a sent or won quote, and copies the quote's open lines (
src/cluster_erp/modules/sales_orders/orders/services.py:174-341). - Compares the PO with the quote field by field and records each attempt (
src/cluster_erp/modules/sales_orders/orders/services.py:342-463). - Freezes each PO version as a snapshot revision (
src/cluster_erp/modules/sales_orders/orders/services.py:871-939). - Tracks individual units of an order line with customer asset numbers and serial numbers (
src/cluster_erp/modules/sales_orders/units/models.py:14-40). - Ships lines and units in shipments with packages, transport data, events, and proof of delivery, and rolls the order status up from shipped quantities (
src/cluster_erp/modules/sales_orders/shipments/services.py:1253-1392). - Generates the packing list and the delivery note as PDF from a frozen snapshot (
src/cluster_erp/modules/sales_orders/trade_documents/services.py:169-278).
Sub-modules¶
| Sub-module | Purpose | Main entities | Router | Source |
|---|---|---|---|---|
orders |
Orders, PO checks, PO revisions, milestones | SalesOrder, PoCheck, PoCheckLine, PoRevision, SalesOrderMilestone |
/sales-orders |
src/cluster_erp/modules/sales_orders/orders/routes.py:33-52 |
order_lines |
Order lines and the BOM action | SalesOrderLine |
/sales-orders/.../lines |
src/cluster_erp/modules/sales_orders/order_lines/routes.py:24-27 |
units |
Units (assets) per line | SalesOrderUnit |
/sales-orders/units, /sales-orders/lines/{line_id}/units |
src/cluster_erp/modules/sales_orders/units/routes.py:21-24 |
shipments |
Shipments, lines, units, packages, events | SalesOrderShipment, ShipmentLine, ShipmentUnit, ShipmentPackage, ShipmentEvent |
/sales-orders/shipments and child paths |
src/cluster_erp/modules/sales_orders/shipments/routes.py:40-85 |
trade_documents |
Packing list and delivery note | TradeDocument |
/sales-orders/trade-documents |
src/cluster_erp/modules/sales_orders/trade_documents/routes.py:24-37 |
settings |
One settings row per tenant | SalesOrderSettings |
/settings/chain |
src/cluster_erp/modules/sales_orders/settings/routes.py:16-19 |
All routers are mounted under the module prefix with require_app("sales_orders") (src/cluster_erp/modules/sales_orders/module.py:64-71).
Data model¶
Fields are listed on orders and lines, shipments, trade documents, and units and settings. Order lines carry part_id, part_model_id, and part_version_id; a catalogue line always carries its model and version (src/cluster_erp/modules/sales_orders/order_lines/models.py:22-62). Money is Numeric: order total Numeric(19, 4), line price and total Numeric(18, 4) (src/cluster_erp/modules/sales_orders/orders/models.py:81-84, src/cluster_erp/modules/sales_orders/order_lines/models.py:71-79).
Screens and metadata¶
get_metadata declares a sidebar group Order Management (Turkish Sipariş Yönetimi) with the sections Sales Orders, Shipments, Units (Assets), Export Documents, and Settings (src/cluster_erp/modules/sales_orders/module.py:321-368). See generic list and actions and action sheet.
Status and actions¶
Order statuses and actions are on orders and lines; shipment statuses on shipments. The diagram shows the path from a customer PO to the documents.
flowchart LR Q["Quote sent"] --> SO["SalesOrder po_received"] SO --> CHK["run_po_check: matched or mismatch"] CHK --> ACC["accept: opened"] ACC --> SH["SalesOrderShipment planned"] SH --> RDY["ready"] RDY --> SHIP["ship: shipped"] SHIP --> DEL["deliver with POD: delivered"] SH --> TD["generate-documents"] TD --> PL["TradeDocument packing_list"] TD --> DN["TradeDocument delivery_note"] SHIP --> ROLL["_advance_order_status on the order"] DEL --> ROLL
In prose: an order created from a PO starts as po_received (src/cluster_erp/modules/sales_orders/orders/models.py:72-77, src/cluster_erp/modules/sales_orders/orders/services.py:41-55). The PO check sets matched or mismatch, and accept opens a matched order (src/cluster_erp/modules/sales_orders/orders/services.py:342-463, src/cluster_erp/modules/sales_orders/orders/services.py:588-648). A shipment of the order is readied, dispatched, and delivered; each step rolls the order up from shipped quantities (src/cluster_erp/modules/sales_orders/shipments/services.py:1085-1191, src/cluster_erp/modules/sales_orders/shipments/services.py:1253-1392). Documents are generated per shipment (src/cluster_erp/modules/sales_orders/trade_documents/routes.py:102).
Business rules¶
Each sub-topic page lists its rules. Across the module, foreign data such as customers, parties, products, units of measure, and countries is read through EventBus queries, and the module imports no other module (src/cluster_erp/modules/sales_orders/trade_documents/builder.py:1-5).
Events and queries¶
The module consumes 7 contracts and produces 33, counted as on the parties module page. The full list is on the contracts reference.
| Direction | Contract class | Handler or emitter | Source |
|---|---|---|---|
| emits | SalesOrderPoReceived, SalesOrderMatched, SalesOrderMismatchDetected, SalesOrderRevisionRequested, SalesOrderOpened, SalesOrderCancelled, SalesOrderClosed |
SalesOrderService |
src/cluster_erp/modules/sales_orders/orders/services.py:174-750 |
| emits | SalesOrderShipped, SalesOrderPartiallyShipped, SalesOrderDelivered |
order roll-up from shipments | src/cluster_erp/modules/sales_orders/shipments/services.py:1253-1392 |
| queries | GetQuoteById, GetQuoteLineItems, ReferenceQuoteLines, ReleaseQuoteLineReferences, GetRfqById, GetCustomerById, GetOwnerWorkingDays, CreateBomForProduct |
order and line services | src/cluster_erp/modules/sales_orders/orders/services.py:78-115, src/cluster_erp/modules/sales_orders/orders/services.py:174-341 |
| answers query | GetSalesOrderById, GetProjectSalesDelivery, GetOpenSalesOrderDemand |
handlers in module.py |
src/cluster_erp/modules/sales_orders/module.py:90-101 |
| subscribes | ProjectCreated |
_on_project_created, which writes the project back on the order |
src/cluster_erp/modules/sales_orders/module.py:102-106, src/cluster_erp/modules/sales_orders/module.py:123-140 |
| subscribes | DescribeFieldConsumers, DescribeAnalyticsFacts, DescribeDisplaySwitches |
tenant fields, analytics, display switches | src/cluster_erp/modules/sales_orders/module.py:77, src/cluster_erp/modules/sales_orders/module.py:93, src/cluster_erp/modules/sales_orders/module.py:110 |
Permissions¶
The module checks the families sales_order.*, po_revision.read, shipment.*, shipment_line.*, shipment_unit.*, shipment_package.*, shipment_event.*, trade_document.*, sales_order_unit.*, and sales_order_settings.*. The order line BOM route uses the permission named by the contract CreateBomForProduct.REQUIRED_PERMISSION (src/cluster_erp/modules/sales_orders/order_lines/routes.py:104-114). Each sub-topic page lists the keys per route.
Privacy, retention, and history¶
The module has no privacy_handlers.py. Records are soft-deleted; issued documents are superseded, not removed (src/cluster_erp/modules/sales_orders/trade_documents/services.py:262-263). Changes are captured by change history.
Analytics facts¶
analytics_facts.py contributes the fact set sales_order over so_sales_orders with the measures order_count, total_value, average_value, median_value, and total_quantity, read with sales_order.read (src/cluster_erp/modules/sales_orders/analytics_facts.py:22-126). See analytics facts.
Settings and reference data¶
One settings row per tenant controls the internal order number, document number templates, the proof-of-delivery rule, the dispatch check level, default units and package type, and the document language; see units and settings.
Tests¶
Found by a grep for modules.sales_orders in tests/ and for the path /sales_orders/ in web-client/_e2e_*.mjs.
| Kind | File | Covers |
|---|---|---|
| pytest | tests/test_order_shipment_chain.py |
order to shipment to document chain |
| pytest | tests/test_sales_delivery_day_party.py |
delivery date on a working day of the customer's party calendar |
| e2e | web-client/_e2e_sales_orders_app.mjs |
the sales orders app |
| e2e | web-client/_e2e_order_shipment_chain.mjs |
the chain in a browser |
| e2e | web-client/_e2e_soline_bom_action.mjs |
the order line BOM action |
| e2e | web-client/_e2e_quote_line_bom.mjs, web-client/_e2e_project_otd.mjs |
quote references and on-time delivery |
Terms introduced¶
| Term | Code identifier | Definition | Turkish term | Source |
|---|---|---|---|---|
| sales order | SalesOrder |
The order created from a customer purchase order that references a quote. | Satış siparişi | src/cluster_erp/modules/sales_orders/orders/models.py:23 |
| shipment | SalesOrderShipment |
One dispatch of order lines and units, with packages and transport data. | Sevkiyat | src/cluster_erp/modules/sales_orders/shipments/models.py:24 |
| trade document | TradeDocument |
A generated packing list or delivery note with its frozen snapshot. | İhracat belgesi | src/cluster_erp/modules/sales_orders/trade_documents/models.py:19 |
Related pages¶
- Modules index
- Orders and lines
- Shipments
- Trade documents
- Units and settings
- Quotations module
- API reference for this module
Verified against commit 92f8051 on 2026-11-13.