The procurement module serves suppliers, substitution groups, critical materials, purchase requests, purchase RFQs with a supplier portal, purchase orders with goods receipt, purchase contracts, purchasing info records, and MRP. All 155 endpoints sit under /api/v1/procurement. For business meaning see the Procurement module page. Because the full table exceeds the page length limit, each sub-module has its own page.
Group facts¶
| Item | Value | Source |
|---|---|---|
| Base path | /api/v1/procurement |
src/cluster_erp/core/module_base.py:37-38, src/cluster_erp/modules/procurement/module.py:70 |
| Routers | 10 router objects in 10 files; listed in the section Endpoint summary | src/cluster_erp/modules/procurement/module.py:35 |
| Endpoints | 155, counted from the route decorators and add_api_route calls of the routers that register_routes mounts |
src/cluster_erp/modules/procurement/critical_materials/routes.py, src/cluster_erp/modules/procurement/info_records/routes.py, src/cluster_erp/modules/procurement/mrp/routes.py ... |
| Authentication | Bearer header or session cookie, resolved by get_current_user; see Authentication and headers |
src/cluster_erp/modules/auth/guards.py:85-167 |
| Permission guard | 152 of 155 routes declare require_permission; the other routes show their guard in the tables |
src/cluster_erp/modules/auth/guards.py:205-240 |
| App entitlement gate | require_app("procurement") on every mounted router |
src/cluster_erp/modules/procurement/module.py:82 |
| Error format | JSON body {"error": {...}}; see Errors |
src/cluster_erp/server/error_handler.py:33-46 |
Endpoint summary¶
One row per sub-module folder. The router prefix is added to the base path. The page column links the endpoint table.
| Sub-module | Routers | Endpoints | Router source | Page |
|---|---|---|---|---|
suppliers |
router |
6 | src/cluster_erp/modules/procurement/suppliers/routes.py:28 |
Suppliers |
substitution_groups |
router (/substitution-groups) |
10 | src/cluster_erp/modules/procurement/substitution_groups/routes.py:27 |
Substitution groups |
critical_materials |
router (/critical-materials) |
6 | src/cluster_erp/modules/procurement/critical_materials/routes.py:24 |
Critical materials |
purchase_requests |
router (/purchase-requests) |
12 | src/cluster_erp/modules/procurement/purchase_requests/routes.py:33 |
Purchase requests |
purchase_rfqs |
router, router |
35 | src/cluster_erp/modules/procurement/purchase_rfqs/routes.py:44, src/cluster_erp/modules/procurement/purchase_rfqs/portal_routes.py:26 |
Purchase RFQs |
purchase_orders |
router (/purchase-orders) |
18 | src/cluster_erp/modules/procurement/purchase_orders/routes.py:35 |
Purchase orders |
purchase_contracts |
router |
16 | src/cluster_erp/modules/procurement/purchase_contracts/routes.py:33 |
Purchase contracts |
info_records |
router |
8 | src/cluster_erp/modules/procurement/info_records/routes.py:24 |
Purchasing info records |
mrp |
router (/mrp) |
44 | src/cluster_erp/modules/procurement/mrp/routes.py:54 |
MRP |
Error codes¶
The table lists the error codes that code under src/cluster_erp/modules/procurement/ raises, found by a syntax-tree scan for AppError(...), the factories in src/cluster_erp/core/errors.py (not_found, conflict, protected, permission_denied, privilege_escalation, check_version), and HTTPException(...). A status of 400 is the AppError default (src/cluster_erp/core/errors.py:23). Guard errors (401, 403), the entitlement codes, and validation errors (422) apply to every route and are listed on Errors.
| Code | HTTP status | Raised in | First site |
|---|---|---|---|
CONCURRENCY_VERSION_CONFLICT |
409 |
critical_materials, info_records, mrp, purchase_contracts, purchase_orders, purchase_requests, purchase_rfqs, substitution_groups, suppliers |
src/cluster_erp/modules/procurement/critical_materials/services.py:127 |
CRITICAL_MATERIAL_ALREADY_EXISTS |
409 |
critical_materials |
src/cluster_erp/modules/procurement/critical_materials/services.py:86 |
DELIVERY_ADDRESS_INVALID |
422 |
delivery_address |
src/cluster_erp/modules/procurement/delivery_address.py:97 |
INFO_RECORD_EXISTS |
409 |
info_records |
src/cluster_erp/modules/procurement/info_records/services.py:169 |
MRP_ITEMS_ALREADY_ACTIONED |
409 |
mrp |
src/cluster_erp/modules/procurement/mrp/services.py:370 |
MRP_ITEMS_ALREADY_FIRMED |
409 |
mrp |
src/cluster_erp/modules/procurement/mrp/services.py:1314 |
MRP_ITEM_OUTSIDE_OPENING_PERIOD |
422 |
mrp |
src/cluster_erp/modules/procurement/mrp/routes.py:399 |
MRP_RUN_FAILED |
400, 500 |
mrp |
src/cluster_erp/modules/procurement/mrp/engine.py:3931 |
MRP_RUN_IN_PROGRESS |
409 |
mrp |
src/cluster_erp/modules/procurement/mrp/services.py:172 |
MRP_RUN_NOT_COMPLETED |
409 |
mrp |
src/cluster_erp/modules/procurement/mrp/services.py:341 |
MRP_RUN_STALE |
409 |
mrp |
src/cluster_erp/modules/procurement/mrp/services.py:347 |
PCON_INCOMPLETE |
409 |
purchase_contracts |
src/cluster_erp/modules/procurement/purchase_contracts/services.py:246 |
PCON_INVALID_STATUS |
409 |
purchase_contracts |
src/cluster_erp/modules/procurement/purchase_contracts/services.py:203 |
PO_GOODS_RECEIPT_FAILED |
400 |
purchase_orders |
src/cluster_erp/modules/procurement/purchase_orders/services.py:821 |
PO_INVALID_STATUS |
400, 409 |
purchase_orders |
src/cluster_erp/modules/procurement/purchase_orders/services.py:86 |
PO_ITEM_ALREADY_RECEIVED |
400 |
purchase_orders |
src/cluster_erp/modules/procurement/purchase_orders/services.py:735 |
PO_NO_ORDER_DATE |
400 |
purchase_orders |
src/cluster_erp/modules/procurement/purchase_orders/services.py:630 |
PO_NO_TECHNICAL_ATTACHMENT |
400 |
purchase_orders |
src/cluster_erp/modules/procurement/purchase_orders/services.py:637 |
PO_RECEIVE_QTY_EXCEEDS |
400 |
purchase_orders |
src/cluster_erp/modules/procurement/purchase_orders/services.py:743 |
PO_VENDOR_BLACKLISTED |
400 |
purchase_orders |
src/cluster_erp/modules/procurement/purchase_orders/services.py:233 |
PRFQ_AWARD_INVALID |
422 |
purchase_rfqs |
src/cluster_erp/modules/procurement/purchase_rfqs/services.py:778 |
PRFQ_INCOMPLETE |
409 |
purchase_rfqs |
src/cluster_erp/modules/procurement/purchase_rfqs/services.py:299 |
PRFQ_INVALID_STATUS |
409 |
purchase_rfqs |
src/cluster_erp/modules/procurement/purchase_rfqs/services.py:188 |
PR_INVALID_STATUS |
400 |
purchase_requests |
src/cluster_erp/modules/procurement/purchase_requests/services.py:115 |
PR_NO_ITEMS |
400 |
purchase_requests |
src/cluster_erp/modules/procurement/purchase_requests/services.py:469 |
RESOURCE_NOT_FOUND |
404 |
critical_materials, info_records, mrp, purchase_contracts, purchase_orders, purchase_requests, purchase_rfqs, substitution_groups, suppliers |
src/cluster_erp/modules/procurement/critical_materials/routes.py:75 |
SUBSTITUTION_GROUP_DUPLICATE_PRODUCT |
409 |
substitution_groups |
src/cluster_erp/modules/procurement/substitution_groups/services.py:221 |
SUBSTITUTION_GROUP_SINGLE_MEMBER |
400 |
substitution_groups |
src/cluster_erp/modules/procurement/substitution_groups/services.py:317 |
VALIDATION_ERROR |
409, 422 |
mrp, suppliers |
src/cluster_erp/modules/procurement/mrp/routes.py:386 |
Events emitted¶
The table lists the contract classes that code under src/cluster_erp/modules/procurement/ passes directly to EventBus.emit, found by a syntax-tree scan. Events built in a variable first are not counted. The contracts are described in Contracts reference.
| Contract | Sites | First site |
|---|---|---|
CriticalMaterialAlert |
1 | src/cluster_erp/modules/procurement/mrp/engine.py:4105 |
MrpRunCompleted |
1 | src/cluster_erp/modules/procurement/mrp/engine.py:4072 |
MrpRunFailed |
1 | src/cluster_erp/modules/procurement/mrp/services.py:283 |
PartyRoleSet |
3 | src/cluster_erp/modules/procurement/suppliers/services.py:138 |
PoAcknowledged |
1 | src/cluster_erp/modules/procurement/purchase_orders/services.py:673 |
PoCancelled |
1 | src/cluster_erp/modules/procurement/purchase_orders/services.py:922 |
PoCreated |
1 | src/cluster_erp/modules/procurement/purchase_orders/services.py:339 |
PoReceivedFull |
1 | src/cluster_erp/modules/procurement/purchase_orders/services.py:780 |
PoReceivedPartial |
1 | src/cluster_erp/modules/procurement/purchase_orders/services.py:789 |
PoSent |
1 | src/cluster_erp/modules/procurement/purchase_orders/services.py:649 |
PrApproved |
1 | src/cluster_erp/modules/procurement/purchase_requests/services.py:522 |
PrCancelled |
1 | src/cluster_erp/modules/procurement/purchase_requests/services.py:547 |
PrCreated |
3 | src/cluster_erp/modules/procurement/mrp/services.py:445 |
Related pages¶
- Suppliers
- Substitution groups
- Critical materials
- Purchase requests
- Purchase RFQs
- Purchase orders
- Purchase contracts
- Purchasing info records
- MRP
- API reference
- Procurement module
- API conventions
- Errors
- Authentication and headers
Verified against commit 92f8051 on 2026-11-13.