Factorizer/Cluster ERP WikiCluster ERP Türkçe
Home / Business modules

Module

Procurement module (procurement)

Module page for procurement, with suppliers, purchase requests, purchasing RFQs, purchase orders, contracts, info records, critical materials, substitution, and MRP.

The procurement module in src/cluster_erp/modules/procurement/ covers buying. It holds the supplier facet of a party, purchase requests, purchasing RFQs with vendor quotations and scoring, purchase orders with goods receipt, purchase contracts, and purchasing info records. It also runs material requirements planning (MRP) and keeps critical materials and substitution groups. This page is the overview; each sub-module has its own reference page, and MRP has an explanation page.

At a glance

Item Value Source
Package src/cluster_erp/modules/procurement/ folder
Module class Module src/cluster_erp/modules/procurement/module.py:18
name / version procurement / 0.1.0 src/cluster_erp/modules/procurement/module.py:20-25
API prefix /api/v1/procurement (ModuleBase.api_prefix) src/cluster_erp/core/module_base.py:37-38
Sub-modules 9: suppliers, purchase_requests, purchase_rfqs, purchase_orders, purchase_contracts, info_records, critical_materials, substitution_groups, mrp folder listing
Tables 27 __tablename__ in the nine models.py files
Entities in metadata 22 keys in entities src/cluster_erp/modules/procurement/module.py:1419-1442
Routes 155 route decorators in the package grep for @...router.get/post/put/patch/delete
Actions 21 ActionMeta entries grep "ActionMeta(" in the package
Migrations 47 files files in migrations/versions/ whose text contains one of the 27 table names
Web app presence Catalogue app procurement; eight custom widgets from a gated bundle src/cluster_erp/modules/app_store/catalog.json (entry procurement), gated_apps/procurement/app.js:1647-1656
Desktop presence src/cluster_erp/desktop/modules/procurement/mrp/ (dashboard, exception workbench, planned orders, stock requirements, time-phased, pegging) folder

What the module does

  • Keeps a supplier facet per party, with identity fields derived from the party (src/cluster_erp/modules/procurement/suppliers/services.py:80-145).
  • Collects material needs in purchase requests that move through approval to an order (src/cluster_erp/modules/procurement/purchase_requests/services.py:76-83).
  • Sends purchasing RFQs to several vendors, records and scores their quotations, and awards lines, which creates one purchase order per awarded vendor (src/cluster_erp/modules/procurement/purchase_rfqs/services.py:1215-1292).
  • Places purchase orders, receives goods per line, and posts the receipt to inventory (src/cluster_erp/modules/procurement/purchase_orders/services.py:695-837).
  • Keeps quantity and value contracts and a price master per vendor and product breakdown (src/cluster_erp/modules/procurement/purchase_contracts/models.py:23-109, src/cluster_erp/modules/procurement/info_records/models.py:25-121).
  • Runs MRP in seven phases and turns its proposals into requests or orders (src/cluster_erp/modules/procurement/mrp/engine.py:1-19).
  • Flags critical materials and groups materials that can replace each other (src/cluster_erp/modules/procurement/critical_materials/models.py:12-65, src/cluster_erp/modules/procurement/substitution_groups/models.py:24-127).

Sub-modules

Sub-module Purpose Main entities Router Source
suppliers Supplier facet of a party Supplier /suppliers src/cluster_erp/modules/procurement/suppliers/routes.py:28-37
purchase_requests Purchase requests and items PurchaseRequest, PurchaseRequestItem /purchase-requests src/cluster_erp/modules/procurement/purchase_requests/routes.py:33
purchase_rfqs Purchasing RFQs, vendors, quotations, criteria, scores, vendor portal PurchaseRfq and six child entities /purchase-rfqs, /portal/rfqs src/cluster_erp/modules/procurement/purchase_rfqs/routes.py:44-45, src/cluster_erp/modules/procurement/purchase_rfqs/portal_routes.py:26-27
purchase_orders Purchase orders, items, receipt PurchaseOrder, PurchaseOrderItem /purchase-orders src/cluster_erp/modules/procurement/purchase_orders/routes.py:35
purchase_contracts Outline agreements PurchaseContract, PurchaseContractItem /purchase-contracts src/cluster_erp/modules/procurement/purchase_contracts/routes.py:33-34
info_records Vendor price master and price history PurchasingInfoRecord, PurchasingInfoRecordPrice /info-records src/cluster_erp/modules/procurement/info_records/routes.py:24-25
critical_materials Materials that must not run short CriticalMaterial /critical-materials src/cluster_erp/modules/procurement/critical_materials/routes.py:24
substitution_groups Interchangeable materials MaterialSubstitutionGroup, MaterialSubstitutionMember /substitution-groups src/cluster_erp/modules/procurement/substitution_groups/routes.py:27
mrp Planning runs, run items, PIRs, safety time, quotas, netting groups, ATP MrpRun, MrpRunItem and five more /mrp src/cluster_erp/modules/procurement/mrp/routes.py:54

All routers are mounted under the module prefix with require_app("procurement") (src/cluster_erp/modules/procurement/module.py:70-82). The shared helper delivery_address.py resolves the structured delivery address of orders and RFQs through GetAddressById and stores a text snapshot (src/cluster_erp/modules/procurement/delivery_address.py:1-13, src/cluster_erp/modules/procurement/delivery_address.py:78).

Data model

Each sub-module page lists its fields. All material lines carry product_id, product_model_id, and product_version_id; order lines may also be text items without a product (src/cluster_erp/modules/procurement/purchase_orders/schemas.py:20-37). Money columns are Numeric, for example the order total Numeric(19, 4) and the unit price Numeric(18, 4) (src/cluster_erp/modules/procurement/purchase_orders/models.py:81-82, src/cluster_erp/modules/procurement/purchase_orders/models.py:195-200). Line totals are rounded with ROUND_HALF_EVEN before storage (src/cluster_erp/modules/procurement/purchase_orders/services.py:307-312).

Screens and metadata

get_metadata declares a sidebar group Procurement (Turkish Satın Alma) with 19 sections (src/cluster_erp/modules/procurement/module.py:1072-1418). Seven sections are custom widgets of the gated bundle: MRP Dashboard, Exception Workbench, Planned Orders, Stock Requirements, Segmentation (XYZ), DDMRP Buffers, and ATP/CTP. The others are lists: Forecast (PIR), MRP Runs, Safety Time Periods, Quota Arrangements, Purchase Requests, Purchasing RFQs, Purchase Orders, Purchase Contracts, Info Records, Critical Materials, and Substitution Groups. The RFQ comparison is the eighth widget, purchase_rfq_comparison (gated_apps/procurement/app.js:1647-1656). See gated app bundles and desktop module screens.

Status and actions

Statuses and actions are listed on each sub-module page. The diagram shows the main path from a requirement to stock.

flowchart LR
 MRP["MrpRun items"] --> PR["PurchaseRequest"]
 PR --> RFQ["PurchaseRfq"]
 RFQ --> Q["PurchaseRfqQuotation"]
 Q --> AW["award"]
 AW --> PO["PurchaseOrder"]
 PR --> PO
 PO --> GR["receive_item"]
 GR --> INV["PostGoodsReceipt to inventory"]
 AW --> IR["PurchasingInfoRecord via SupplierQuotationAwarded"]

In prose: an MRP run creates purchase requests from its items (src/cluster_erp/modules/procurement/mrp/services.py:331). A request can go to an RFQ through purchase_request_id (src/cluster_erp/modules/procurement/purchase_rfqs/models.py:49), or straight to an order with POST /purchase-orders/from-pr/{pr_id} once approved (src/cluster_erp/modules/procurement/purchase_orders/services.py:349-413). Awarding RFQ lines creates one order per awarded vendor (src/cluster_erp/modules/procurement/purchase_rfqs/services.py:1281-1286). Receiving an order line posts a goods receipt to inventory with PostGoodsReceipt (src/cluster_erp/modules/procurement/purchase_orders/services.py:799-836). An award of a supplier quotation in the purchasing_quotations module updates the info records (src/cluster_erp/modules/procurement/module.py:813-862).

Business rules

The rules of each sub-module are on its page. Two rules apply across the module:

  • Every material line is checked with ensure_product_breakdown through the EventBus (src/cluster_erp/modules/procurement/purchase_orders/services.py:279, src/cluster_erp/modules/procurement/purchase_requests/services.py:233).
  • Documents use yearly sequences: supplier, purchase_request, purchase_order, purchase_contract, info_record, substitution_group, and mrp_pir (src/cluster_erp/modules/procurement/suppliers/services.py:130, src/cluster_erp/modules/procurement/purchase_requests/services.py:208, src/cluster_erp/modules/procurement/purchase_orders/services.py:245).

Events and queries

The module consumes 31 contracts and produces 48, counted as on the parties module page. The full list is on the contracts reference.

Direction Contract class Handler or emitter Source
emits PrCreated, PrApproved, PrCancelled purchase request service src/cluster_erp/modules/procurement/purchase_requests/services.py:279, src/cluster_erp/modules/procurement/purchase_requests/services.py:522, src/cluster_erp/modules/procurement/purchase_requests/services.py:547
emits PoCreated, PoSent, PoAcknowledged, PoReceivedFull, PoReceivedPartial, PoCancelled purchase order service src/cluster_erp/modules/procurement/purchase_orders/services.py:338, src/cluster_erp/modules/procurement/purchase_orders/services.py:648-921
emits PartyRoleSet supplier create and delete src/cluster_erp/modules/procurement/suppliers/services.py:138, src/cluster_erp/modules/procurement/suppliers/services.py:195
emits MrpRunCompleted, CriticalMaterialAlert MRP engine src/cluster_erp/modules/procurement/mrp/engine.py:4073, src/cluster_erp/modules/procurement/mrp/engine.py:4106
answers query GetPurchaseOrderById, GetPurchaseRequestById, GetOpenPosForProduct, GetOpenPoLinesForReceipt, GetPlannedOrdersForCapacity, GetBulkOpenPos, GetCriticalMaterials, GetSubstitutesForProduct, GetPurchaseRfqQuotations, CreateFollowOnFromSupplierQuotation, ReconcilePoReceiptReversal handlers in module.py src/cluster_erp/modules/procurement/module.py:139-202
subscribes PartyUpdated, PartyDeleted supplier facet sync src/cluster_erp/modules/procurement/module.py:122-125
subscribes SalesOrderOpened, ProductionOrderCreated, BomActivated, GoodsReceived, GoodsIssued, StockTransferred, StockAdjusted, GoodsMovementReversed, StockCategoryTransferred, ProductionOrderCompleted, BomItemAdded, BomItemChanged, ProductUpdated MRP staleness and planning file src/cluster_erp/modules/procurement/module.py:182-207
subscribes SupplierQuotationAwarded info record upsert src/cluster_erp/modules/procurement/module.py:208
subscribes CollectSubjectData, AnonymiseSubject, DescribeAnalyticsFacts, DescribeFieldConsumers privacy, analytics, tenant fields src/cluster_erp/modules/procurement/module.py:88, src/cluster_erp/modules/procurement/module.py:136-137, src/cluster_erp/modules/procurement/module.py:218-219

Permissions

Each sub-module page lists its keys. The module checks the families supplier.*, purchase_request.*, purchase_rfq.*, purchase_order.*, purchase_contract.*, info_record.*, critical_material.*, substitution_group.*, and mrp_run.* with require_permission in the route files.

Privacy, retention, and history

privacy_handlers.py answers data-subject requests for supplier facets of individual parties: CollectSubjectData returns the rows, and AnonymiseSubject overwrites the identifying values and deactivates the rows (src/cluster_erp/modules/procurement/privacy_handlers.py:1-11). Deletes set deleted_at (src/cluster_erp/modules/procurement/suppliers/services.py:185-191). See privacy and data-subject requests and change history.

Analytics facts

analytics_facts.py contributes two fact sets. purchase_order over procurement_purchase_orders has the measures order_count, total_amount, average_amount, and median_amount, with currency as the currency field. purchase_request over procurement_purchase_requests has request_count and total_estimated_cost (src/cluster_erp/modules/procurement/analytics_facts.py:19-179). See analytics facts.

Settings and reference data

The module has no settings section. MRP reads lot-sizing defaults per ABC class from Settings (src/cluster_erp/modules/procurement/mrp/engine.py:3037-3048); see settings reference.

Tests

Found by a grep for modules.procurement in tests/ and for the path /procurement/ in web-client/_e2e_*.mjs.

Kind File Covers
pytest tests/test_procurement_descriptions.py action descriptions in procurement metadata
pytest tests/test_data_map_package3.py, tests/test_party_form_contract.py supplier facet and party form contracts
e2e web-client/_e2e_procurement_app.mjs the procurement app
e2e web-client/_e2e_procurement_audit_high.mjs, _medium, _low, _deferred audit findings across requests, RFQs, and orders
e2e web-client/_e2e_procurement_gr.mjs goods receipt
e2e web-client/_e2e_rfq_portal_token.mjs the vendor portal
e2e web-client/_e2e_mrp_hygiene_faz0.mjs to web-client/_e2e_mrp_atp_faz8.mjs (nine suites) MRP

Discrepancies

Terms introduced

Term Code identifier Definition Turkish term Source
supplier facet Supplier The supplier role record of a party, with commercial defaults. Tedarikçi rolü src/cluster_erp/modules/procurement/suppliers/models.py:13
delivery snapshot resolve_delivery_snapshot The address text copied onto an order or RFQ when it is set. Teslimat adresi anlık görüntüsü src/cluster_erp/modules/procurement/delivery_address.py:78

Verified against commit 92f8051 on 2026-11-13.

Verified against commit 92f8051 · 2026-11-13