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

Module

Purchasing quotations module (purchasing_quotations)

Module page for purchasing_quotations, the supplier quotation register with lines, pricing conditions, scales, versions, award, comparison, and follow-on documents.

The purchasing_quotations module in src/cluster_erp/modules/purchasing_quotations/ is the register of supplier quotations. A supplier quotation (PurchasingQuotation) records an offer from a vendor, with or without a purchasing RFQ, priced per line with discount, surcharge, and freight conditions. Awarding a quotation can create a purchase order or a purchase contract in procurement and updates the purchasing info records. The register also lists the vendor quotations kept inside the purchasing RFQ sub-module.

At a glance

Item Value Source
Package src/cluster_erp/modules/purchasing_quotations/ folder
Module class Module src/cluster_erp/modules/purchasing_quotations/module.py:15
name / version purchasing_quotations / 0.1.0 src/cluster_erp/modules/purchasing_quotations/module.py:20-26
API prefix /api/v1/purchasing_quotations (ModuleBase.api_prefix) src/cluster_erp/core/module_base.py:37-38
Sub-modules 1: quotations folder listing
Tables 4: purq_quotations, purq_quotation_lines, purq_quotation_conditions, purq_quotation_scales __tablename__ in quotations/models.py
Entities in metadata 6 keys in entities src/cluster_erp/modules/purchasing_quotations/module.py:173-184
Routes 27 route decorators in the package grep for @...router.get/post/put/patch/delete
Actions 7 ActionMeta entries grep "ActionMeta(" in the package
Migrations 8 files files in migrations/versions/ whose text contains one of the four table names
Web app presence Catalogue app purchasing-quotations src/cluster_erp/modules/app_store/catalog.json (entry purchasing-quotations)
Desktop presence src/cluster_erp/desktop/modules/purchasing_quotations/ holds only __init__.py; screens use the generic widgets folder

What the module does

  • Records supplier quotations with four source values: rfq, unsolicited (default), spot, and price_list (src/cluster_erp/modules/purchasing_quotations/quotations/models.py:40-46, src/cluster_erp/modules/purchasing_quotations/quotations/schemas.py:16).
  • Prices each line through a sequence of conditions into an effective unit price (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:797-831).
  • Keeps revisions: revise clones a quotation into a new version and marks the old one superseded (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:509-594).
  • Awards lines and, on request, creates a purchase order or contract through the EventBus (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:285-346).
  • Compares all live quotation lines for one product by effective price, and lists a register of native and RFQ quotations (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:990-1116).

Sub-modules

Sub-module Purpose Main entities Router Source
quotations Quotations, lines, conditions, scales, compare, register PurchasingQuotation, PurchasingQuotationLine, PurchasingQuotationCondition, PurchasingQuotationScale /purchasing-quotations and line, condition, and scale paths src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:39-61

The router is mounted under the module prefix with require_app("purchasing_quotations") (src/cluster_erp/modules/purchasing_quotations/module.py:39-49).

Data model

Entity Table Key fields Notes Source
PurchasingQuotation purq_quotations code, source, purchase_rfq_id, vendor_party_id, status, version_no, superseded_by_id, vendor_quotation_no, currency, valid_from, valid_until, binding_until, total_amount, project_id, follow_on_type, follow_on_id, follow_on_code lifecycle stamps for submit, award, reject, complete, cancel src/cluster_erp/modules/purchasing_quotations/quotations/models.py:24-104
PurchasingQuotationLine purq_quotation_lines line_no, product breakdown, description, qty, net_unit_price, effective_unit_price, line_total, lead_time_days, moq, rejection_indicator, is_awarded free-text lines have no product src/cluster_erp/modules/purchasing_quotations/quotations/models.py:107-151
PurchasingQuotationCondition purq_quotation_conditions condition_type, calc_type, value, base, sequence, label src/cluster_erp/modules/purchasing_quotations/quotations/models.py:154-186
PurchasingQuotationScale purq_quotation_scales from_qty, unit_price src/cluster_erp/modules/purchasing_quotations/quotations/models.py:189-205

Money is Numeric: total and line total Numeric(19, 4), prices and condition values Numeric(18, 4) (src/cluster_erp/modules/purchasing_quotations/quotations/models.py:81, src/cluster_erp/modules/purchasing_quotations/quotations/models.py:127-131, src/cluster_erp/modules/purchasing_quotations/quotations/models.py:172). Line breakdowns are checked with ensure_product_breakdown (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:713, src/cluster_erp/modules/purchasing_quotations/quotations/services.py:745).

Screens and metadata

get_metadata declares a sidebar group Supplier Quotations (Turkish Tedarikçi Teklifleri) with three list sections: Supplier Quotations, All Quotations (Register), and Compare Supplier Quotations (src/cluster_erp/modules/purchasing_quotations/module.py:130-170). The register and compare views are their own entities, purchasing_quotation_register and purchasing_quotation_compare (src/cluster_erp/modules/purchasing_quotations/module.py:173-184). See generic list.

Status and actions

Statuses are in_preparation (default), submitted, awarded, completed, rejected, and cancelled (src/cluster_erp/modules/purchasing_quotations/quotations/models.py:54-62). The service maps each action to a target status and allowed source statuses (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:57-64).

stateDiagram-v2
 [*] --> in_preparation
 in_preparation --> submitted: submit
 submitted --> awarded: award
 in_preparation --> rejected: reject
 submitted --> rejected: reject
 awarded --> completed: complete
 in_preparation --> cancelled: cancel
 submitted --> cancelled: cancel
 awarded --> cancelled: cancel
 rejected --> in_preparation: reopen
 cancelled --> in_preparation: reopen

In prose: a quotation is prepared and submitted, then awarded or rejected. An awarded quotation is completed or cancelled. A rejected or cancelled quotation can be reopened. revise works from submitted, rejected, or cancelled and starts a new in_preparation version (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:509-525).

Action Label Condition Endpoint Permission Source
submit Submit status is in_preparation POST /purchasing-quotations/{id}/submit purchasing_quotation.submit src/cluster_erp/modules/purchasing_quotations/quotations/metadata.py:636-643, src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:178
award Award status is submitted POST /purchasing-quotations/{id}/award purchasing_quotation.award src/cluster_erp/modules/purchasing_quotations/quotations/metadata.py:644-695, src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:192
reject Reject status is in_preparation or submitted POST /purchasing-quotations/{id}/reject purchasing_quotation.reject src/cluster_erp/modules/purchasing_quotations/quotations/metadata.py:696-712, src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:214
complete Complete status is awarded POST /purchasing-quotations/{id}/complete purchasing_quotation.complete src/cluster_erp/modules/purchasing_quotations/quotations/metadata.py:713-720, src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:231
cancel Cancel status is in_preparation, submitted, or awarded POST /purchasing-quotations/{id}/cancel purchasing_quotation.update src/cluster_erp/modules/purchasing_quotations/quotations/metadata.py:721-737, src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:245
reopen Reopen status is rejected or cancelled POST /purchasing-quotations/{id}/reopen purchasing_quotation.update src/cluster_erp/modules/purchasing_quotations/quotations/metadata.py:738-745, src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:262
revise Revise (new version) status is submitted, rejected, or cancelled POST /purchasing-quotations/{id}/revise purchasing_quotation.revise src/cluster_erp/modules/purchasing_quotations/quotations/metadata.py:746-753, src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:276

Business rules

  • A quotation can be edited only in in_preparation or submitted (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:54, src/cluster_erp/modules/purchasing_quotations/quotations/services.py:634-640).
  • Only in_preparation, cancelled, or rejected quotations can be deleted; delete sets deleted_at (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:224-238).
  • Submitting needs at least one line, at least one line that is not rejected, a currency, and a validity date (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:599-633).
  • The effective unit price walks the conditions in sequence order. A percent applies to the running subtotal or to the net price; per_unit adds a fixed amount per unit; absolute spreads a fixed amount over the quantity. Discounts subtract, surcharges and freight add, and the result is floored at zero (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:797-831).
  • The line total is quantity times effective price, rounded to four places; the header total is recomputed on every line or condition change (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:848-874).
  • Award stores the decision first, then creates a follow-on purchase order or contract when asked, and skips this if a follow-on already exists (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:321-339, src/cluster_erp/modules/purchasing_quotations/quotations/services.py:389-449).
  • code comes from the yearly sequence purchasing_quotation; a revision gets a new code and version_no plus one (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:168, src/cluster_erp/modules/purchasing_quotations/quotations/services.py:522).
  • Scales are stored per line and copied on revision; the effective price calculation does not read them (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:580-582, src/cluster_erp/modules/purchasing_quotations/quotations/services.py:848-851).

Events and queries

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

Direction Contract class Handler or emitter Source
emits SupplierQuotationAwarded _emit_awarded_event, for awarded lines with a product src/cluster_erp/modules/purchasing_quotations/quotations/services.py:347-388
queries CreateFollowOnFromSupplierQuotation _create_follow_on src/cluster_erp/modules/purchasing_quotations/quotations/services.py:389-449
queries GetPurchaseRfqQuotations register, for the RFQ quotations src/cluster_erp/modules/purchasing_quotations/quotations/services.py:1048-1116
answers query GetPurchasingQuotationById _handle_get_quotation src/cluster_erp/modules/purchasing_quotations/module.py:51-102
subscribes DescribeAnalyticsFacts describe_analytics_facts src/cluster_erp/modules/purchasing_quotations/module.py:60-66

The procurement module handles SupplierQuotationAwarded and CreateFollowOnFromSupplierQuotation; see purchase contracts and info records.

Permissions

Permission key Used by Source
purchasing_quotation.read lists, detail, completeness, lines, conditions, scales, compare, register src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:61-473
purchasing_quotation.create, .update, .delete, .bulk_delete record and child changes, cancel, reopen src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:99-436
purchasing_quotation.submit, .award, .reject, .complete, .revise lifecycle routes src/cluster_erp/modules/purchasing_quotations/quotations/routes.py:178-276

Privacy, retention, and history

The module has no privacy_handlers.py. Quotations are soft-deleted (src/cluster_erp/modules/purchasing_quotations/quotations/services.py:236). Pricing conditions and scales are child rows that are replaced together with their line; they are removed through the ORM so that each removal is recorded (see Notes below). Changes are captured by change history.

Analytics facts

analytics_facts.py contributes the fact set purchasing_quotation with the measures quotation_count, total_amount, median_amount, and average_lead_time_days, read with purchasing_quotation.read (src/cluster_erp/modules/purchasing_quotations/analytics_facts.py:17-117). See analytics facts.

Settings and reference data

The module has no settings section. Not determined from code: whether the condition types are meant to come from reference data; they are a fixed Literal in the schema (src/cluster_erp/modules/purchasing_quotations/quotations/schemas.py:16-19).

Tests

Found by a grep for modules.purchasing_quotations in tests/ (no hit) and by file name and the path /purchasing_quotations/ in web-client/.

Kind File Covers
e2e web-client/_e2e_purchasing_quotations_app.mjs the purchasing quotations app
e2e web-client/_e2e_tenant_fields_phase4b.mjs tenant fields on the quotation

Discrepancies

Terms introduced

Term Code identifier Definition Turkish term Source
supplier quotation PurchasingQuotation An offer from a vendor recorded in the register, with or without an RFQ. Tedarikçi teklifi src/cluster_erp/modules/purchasing_quotations/quotations/models.py:24
pricing condition PurchasingQuotationCondition A discount, surcharge, freight, or cash discount applied to a line price. Fiyat koşulu src/cluster_erp/modules/purchasing_quotations/quotations/models.py:154
effective unit price effective_unit_price The line price after all conditions in sequence. Etkin birim fiyat src/cluster_erp/modules/purchasing_quotations/quotations/models.py:130
follow-on document follow_on_type, follow_on_id The purchase order or contract created from an awarded quotation. İzleyen belge src/cluster_erp/modules/purchasing_quotations/quotations/models.py:91-93

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

Verified against commit 92f8051 · 2026-11-13