This page describes two sub-modules of src/cluster_erp/modules/procurement/: purchase_contracts/, the outline agreements with a vendor for a period, and info_records/, the price master per vendor and product breakdown with its price history. Supplier quotations that feed both are described on the purchasing quotations module.
Scope and source¶
- Defined in:
models.py,services.py,routes.py, andmetadata.pyofpurchase_contractsandinfo_records. - Count: 4 tables; 16 contract routes and 8 info record routes (
@router.decorators); 5ActionMetaentries, all on contracts.
Contract fields¶
| Name | Meaning | Source |
|---|---|---|
code |
Business key from the yearly sequence purchase_contract |
src/cluster_erp/modules/procurement/purchase_contracts/models.py:35, src/cluster_erp/modules/procurement/purchase_contracts/services.py:145 |
contract_type |
quantity (default) or value |
src/cluster_erp/modules/procurement/purchase_contracts/models.py:37-42, src/cluster_erp/modules/procurement/purchase_contracts/schemas.py:10 |
vendor_id, vendor_name_cache |
Vendor party and cached name | src/cluster_erp/modules/procurement/purchase_contracts/models.py:43-44 |
source_quotation_id, purchase_rfq_id |
Origin of the contract | src/cluster_erp/modules/procurement/purchase_contracts/models.py:46-49 |
status |
Default draft |
src/cluster_erp/modules/procurement/purchase_contracts/models.py:51-57 |
valid_from, valid_to, currency, incoterm, payment_terms |
Validity and terms | src/cluster_erp/modules/procurement/purchase_contracts/models.py:58-62 |
target_value, released_value |
Value target and released value, Numeric(19, 4) |
src/cluster_erp/modules/procurement/purchase_contracts/models.py:64-67 |
activated_at, activated_by, closed_at, cancelled_at, cancelled_by, cancel_reason |
Lifecycle record | src/cluster_erp/modules/procurement/purchase_contracts/models.py:71-76 |
Contract items (PurchaseContractItem, table procurement_purchase_contract_items) carry line_no, the product breakdown, description, target_qty, released_qty, net_unit_price, and unit_id (src/cluster_erp/modules/procurement/purchase_contracts/models.py:83-109).
Contract statuses and actions¶
The service maps each action to a target status and the allowed source statuses (src/cluster_erp/modules/procurement/purchase_contracts/services.py:39-45).
stateDiagram-v2 [*] --> draft draft --> active: activate active --> closed: close active --> expired: expire draft --> cancelled: cancel active --> cancelled: cancel cancelled --> draft: reopen
In prose: activate needs a complete draft: at least one item, a validity period with from not after to, and a target value for a value contract (src/cluster_erp/modules/procurement/purchase_contracts/services.py:234-256, src/cluster_erp/modules/procurement/purchase_contracts/services.py:308-346). Every transition checks the record version for concurrent edits (src/cluster_erp/modules/procurement/purchase_contracts/services.py:213-232).
| Action | Label | Condition | Endpoint | Permission | Source |
|---|---|---|---|---|---|
activate |
Activate | status is draft |
POST /purchase-contracts/{id}/activate |
purchase_contract.activate |
src/cluster_erp/modules/procurement/purchase_contracts/metadata.py:242-255, src/cluster_erp/modules/procurement/purchase_contracts/routes.py:170 |
close |
Close | status is active |
POST /purchase-contracts/{id}/close |
purchase_contract.update |
src/cluster_erp/modules/procurement/purchase_contracts/metadata.py:256-267, src/cluster_erp/modules/procurement/purchase_contracts/routes.py:184 |
expire |
Expire | status is active |
POST /purchase-contracts/{id}/expire |
purchase_contract.update |
src/cluster_erp/modules/procurement/purchase_contracts/metadata.py:268-281, src/cluster_erp/modules/procurement/purchase_contracts/routes.py:196 |
cancel |
Cancel | status is draft or active |
POST /purchase-contracts/{id}/cancel |
purchase_contract.cancel |
src/cluster_erp/modules/procurement/purchase_contracts/metadata.py:282-308, src/cluster_erp/modules/procurement/purchase_contracts/routes.py:210 |
reopen |
Reopen | status is cancelled |
POST /purchase-contracts/{id}/reopen |
purchase_contract.update |
src/cluster_erp/modules/procurement/purchase_contracts/metadata.py:309-320, src/cluster_erp/modules/procurement/purchase_contracts/routes.py:227 |
Contract routes¶
| Method and path | Permission | Source |
|---|---|---|
GET, POST /purchase-contracts/; GET, PUT, DELETE /purchase-contracts/{contract_id}; POST /purchase-contracts/bulk-delete |
purchase_contract.read, .create, .update, .delete |
src/cluster_erp/modules/procurement/purchase_contracts/routes.py:55-140 |
GET /purchase-contracts/{contract_id}/completeness |
purchase_contract.read |
src/cluster_erp/modules/procurement/purchase_contracts/routes.py:155 |
Items: GET, POST /purchase-contracts/{contract_id}/items; PUT, DELETE /purchase-contract-items/{item_id} |
purchase_contract.read, purchase_contract.update |
src/cluster_erp/modules/procurement/purchase_contracts/routes.py:242-290 |
Info record fields¶
| Name | Meaning | Source |
|---|---|---|
code |
Business key from the yearly sequence info_record |
src/cluster_erp/modules/procurement/info_records/models.py:44, src/cluster_erp/modules/procurement/info_records/services.py:175 |
vendor_party_id, vendor_name_cache |
Vendor | src/cluster_erp/modules/procurement/info_records/models.py:45-48 |
product_id, product_model_id, product_version_id |
Product breakdown | src/cluster_erp/modules/procurement/info_records/models.py:51-59 |
currency, net_unit_price |
Current price Numeric(18, 4) |
src/cluster_erp/modules/procurement/info_records/models.py:62-64 |
lead_time_days, min_order_qty, incoterm, payment_terms |
Supply terms | src/cluster_erp/modules/procurement/info_records/models.py:66-71 |
source, source_ref_id, source_ref_code |
Where the price came from: manual or quotation |
src/cluster_erp/modules/procurement/info_records/models.py:73-79, src/cluster_erp/modules/procurement/info_records/services.py:179 |
valid_from, valid_to, is_active, notes |
Validity | src/cluster_erp/modules/procurement/info_records/models.py:82-87 |
Price history rows (PurchasingInfoRecordPrice, table procurement_info_record_prices) keep unit_price, currency, valid_from, source, source_ref_code, and recorded_at (src/cluster_erp/modules/procurement/info_records/models.py:94-121).
Info record routes¶
| Method and path | Permission | Source |
|---|---|---|
GET, POST /info-records/; GET, PUT, DELETE /info-records/{record_id}; POST /info-records/bulk-delete |
info_record.read, .create, .update, .delete |
src/cluster_erp/modules/procurement/info_records/routes.py:32-110 |
GET /info-records/{record_id}/prices |
info_record.read |
src/cluster_erp/modules/procurement/info_records/routes.py:125 |
GET /info-record-lookup |
info_record.read |
src/cluster_erp/modules/procurement/info_records/routes.py:140-149 |
Constraints and validation¶
- A contract changes only in
draft; onlydraftorcancelledcontracts can be deleted (src/cluster_erp/modules/procurement/purchase_contracts/services.py:36,src/cluster_erp/modules/procurement/purchase_contracts/services.py:198-210). - One live info record exists per vendor and product breakdown; a manual duplicate is refused (
src/cluster_erp/modules/procurement/info_records/models.py:33-41,src/cluster_erp/modules/procurement/info_records/services.py:160-173). upsertcreates a record or updates the price, reactivates the record, and appends a history row when the price changed (src/cluster_erp/modules/procurement/info_records/services.py:229-292).- On
SupplierQuotationAwarded, the module upserts one info record per awarded line that carries a full breakdown, each line in its own savepoint (src/cluster_erp/modules/procurement/module.py:813-862). CreateFollowOnFromSupplierQuotationcreates a purchase order or a contract from an awarded supplier quotation; text lines become text items (src/cluster_erp/modules/procurement/module.py:711-810).- Purchase order items take their default unit price from
lookup_pricewith the full breakdown (src/cluster_erp/modules/procurement/purchase_orders/services.py:297-303).
Discrepancies¶
Terms introduced¶
| Term | Code identifier | Definition | Turkish term | Source |
|---|---|---|---|---|
| purchase contract | PurchaseContract |
An outline agreement with a vendor for a period, by quantity or value. | Satın alma sözleşmesi | src/cluster_erp/modules/procurement/purchase_contracts/models.py:23 |
| info record | PurchasingInfoRecord |
The current price and terms of one product breakdown from one vendor. | Info kaydı | src/cluster_erp/modules/procurement/info_records/models.py:25 |
Related pages¶
Verified against commit 92f8051 on 2026-11-13.