The purchasing_quotations module serves the supplier quotation register: quotations with their lifecycle, lines, pricing conditions, quantity scales, a comparison, and a register read. All 27 endpoints sit under /api/v1/purchasing_quotations. For business meaning see the Purchasing quotations module page.
Group facts¶
| Item | Value | Source |
|---|---|---|
| Base path | /api/v1/purchasing_quotations |
src/cluster_erp/core/module_base.py:37-38, src/cluster_erp/modules/purchasing_quotations/module.py:47 |
| Routers | 1 router objects in 1 files; listed in the section Endpoint summary | src/cluster_erp/modules/purchasing_quotations/module.py:39 |
| Endpoints | 27, counted from the route decorators and add_api_route calls of the routers that register_routes mounts |
src/cluster_erp/modules/purchasing_quotations/quotations/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 | 27 of 27 routes declare require_permission |
src/cluster_erp/modules/auth/guards.py:205-240 |
| App entitlement gate | require_app("purchasing_quotations") on every mounted router |
src/cluster_erp/modules/purchasing_quotations/module.py:49 |
| 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.
| Sub-module | Routers | Endpoints | Router source |
|---|---|---|---|
quotations |
router |
27 | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:39 |
Supplier quotations endpoints¶
Quotation records, completeness, submit, award, reject, complete, cancel, reopen, revise, lines, conditions, scales, compare, and register. Conditions and scales are removed physically through the ORM (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:932-936, src/cluster_erp/modules/purchasing_quotations/quotations/services.py:985); the project's written engineering rules name these rows as a deliberate exception.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
GET |
/api/v1/purchasing_quotations/purchasing-quotations/ |
list_quotations |
purchasing_quotation.read |
none | search, status, source, vendor_party_id, limit, offset |
dict |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:61 |
POST |
/api/v1/purchasing_quotations/purchasing-quotations/ |
create_quotation |
purchasing_quotation.create |
PurchasingQuotationCreate |
none | PurchasingQuotationRead |
201 |
src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:99 |
GET |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id} |
get_quotation |
purchasing_quotation.read |
none | none | PurchasingQuotationRead |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:110 |
PUT |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id} |
update_quotation |
purchasing_quotation.update |
PurchasingQuotationUpdate |
none | PurchasingQuotationRead |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:123 |
DELETE |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id} |
delete_quotation |
purchasing_quotation.delete |
none | none | none | 204 |
src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:137 |
POST |
/api/v1/purchasing_quotations/purchasing-quotations/bulk-delete |
bulk_delete |
purchasing_quotation.bulk_delete |
BulkDeleteRequest |
none | BulkDeleteResponse |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:148 |
GET |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id}/completeness |
get_completeness |
purchasing_quotation.read |
none | none | dict |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:163 |
POST |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id}/submit |
submit |
purchasing_quotation.submit |
PurqTransition |
none | PurchasingQuotationRead |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:178 |
POST |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id}/award |
award |
purchasing_quotation.award |
PurchasingQuotationAwardRequest |
none | PurchasingQuotationRead |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:192 |
POST |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id}/reject |
reject |
purchasing_quotation.reject |
PurqReasonTransition |
none | PurchasingQuotationRead |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:214 |
POST |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id}/complete |
complete |
purchasing_quotation.complete |
PurqTransition |
none | PurchasingQuotationRead |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:231 |
POST |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id}/cancel |
cancel |
purchasing_quotation.update |
PurqReasonTransition |
none | PurchasingQuotationRead |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:245 |
POST |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id}/reopen |
reopen |
purchasing_quotation.update |
PurqTransition |
none | PurchasingQuotationRead |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:262 |
POST |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id}/revise |
revise |
purchasing_quotation.revise |
none | none | PurchasingQuotationRead |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:276 |
GET |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id}/lines |
list_lines |
purchasing_quotation.read |
none | none | list[PurchasingQuotationLineRead] |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:288 |
POST |
/api/v1/purchasing_quotations/purchasing-quotations/{quotation_id}/lines |
add_line |
purchasing_quotation.update |
PurchasingQuotationLineCreate |
none | PurchasingQuotationLineRead |
201 |
src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:302 |
PUT |
/api/v1/purchasing_quotations/purchasing-quotation-lines/{line_id} |
update_line |
purchasing_quotation.update |
PurchasingQuotationLineUpdate |
none | PurchasingQuotationLineRead |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:318 |
DELETE |
/api/v1/purchasing_quotations/purchasing-quotation-lines/{line_id} |
delete_line |
purchasing_quotation.update |
none | none | none | 204 |
src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:335 |
GET |
/api/v1/purchasing_quotations/purchasing-quotation-lines/{line_id}/conditions |
list_conditions |
purchasing_quotation.read |
none | none | list[PurchasingQuotationConditionRead] |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:347 |
POST |
/api/v1/purchasing_quotations/purchasing-quotation-lines/{line_id}/conditions |
add_condition |
purchasing_quotation.update |
PurchasingQuotationConditionCreate |
none | PurchasingQuotationConditionRead |
201 |
src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:361 |
PUT |
/api/v1/purchasing_quotations/purchasing-quotation-conditions/{condition_id} |
update_condition |
purchasing_quotation.update |
PurchasingQuotationConditionUpdate |
none | PurchasingQuotationConditionRead |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:377 |
DELETE |
/api/v1/purchasing_quotations/purchasing-quotation-conditions/{condition_id} |
delete_condition |
purchasing_quotation.update |
none | none | none | 204 |
src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:394 |
GET |
/api/v1/purchasing_quotations/purchasing-quotation-lines/{line_id}/scales |
list_scales |
purchasing_quotation.read |
none | none | list[PurchasingQuotationScaleRead] |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:406 |
POST |
/api/v1/purchasing_quotations/purchasing-quotation-lines/{line_id}/scales |
add_scale |
purchasing_quotation.update |
PurchasingQuotationScaleCreate |
none | PurchasingQuotationScaleRead |
201 |
src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:420 |
DELETE |
/api/v1/purchasing_quotations/purchasing-quotation-scales/{scale_id} |
delete_scale |
purchasing_quotation.update |
none | none | none | 204 |
src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:436 |
GET |
/api/v1/purchasing_quotations/purchasing-quotation-compare |
compare |
purchasing_quotation.read |
none | product_id, search, limit, offset |
dict |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:450 |
GET |
/api/v1/purchasing_quotations/purchasing-quotation-register |
register |
purchasing_quotation.read |
none | origin, vendor_party_id, search, limit, offset |
dict |
200 (default) | src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:473 |
Error codes¶
The table lists the error codes that code under src/cluster_erp/modules/purchasing_quotations/ 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 |
quotations |
src/cluster_erp/modules/purchasing_quotations/quotations/services.py:201 |
PURQ_AWARD_INVALID |
422 |
quotations |
src/cluster_erp/modules/purchasing_quotations/quotations/services.py:302 |
PURQ_INCOMPLETE |
409 |
quotations |
src/cluster_erp/modules/purchasing_quotations/quotations/services.py:273 |
PURQ_INVALID_STATUS |
409 |
quotations |
src/cluster_erp/modules/purchasing_quotations/quotations/services.py:230 |
RESOURCE_NOT_FOUND |
404 |
quotations |
src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:119 |
Events emitted¶
The table lists the contract classes that code under src/cluster_erp/modules/purchasing_quotations/ 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 |
|---|---|---|
SupplierQuotationAwarded |
1 | src/cluster_erp/modules/purchasing_quotations/quotations/services.py:376 |
Related pages¶
Verified against commit 92f8051 on 2026-11-13.