Focus mode active/Press Alt+Shift+R to toggle/Esc to exit
Start HereOrdered learning track

TMF648 Quote Management Data Model

Quote, quote item, related party, product offering, product configuration, price, agreement reference, validity period, quote state, quote item action, approval, authorization, dan quote-to-order conversion dalam CPQ dan quote-to-cash systems.

22 min read4308 words
PrevNext
Lesson 0882 lesson track01–15 Start Here
#enterprise-data-modelling#tmf648#quote-management#quote+4 more

TMF648 Quote Management Data Model

TMF648 Quote Management API memberi reference shape untuk customer quote management.

Tetapi untuk senior backend engineer, quote bukan hanya REST resource.

Quote adalah commercial proposal state yang mengikat customer context, product selection, configuration, price, discount, approval, validity, dan eventual conversion ke order.

Mindset yang benar:

Quote is the commercial decision record before order execution.

TMF648 membantu menyamakan vocabulary dan API shape, tetapi internal system tetap harus mendesain:

  • quote aggregate boundary,
  • quote item structure,
  • price snapshot,
  • configuration snapshot,
  • approval trace,
  • lifecycle state machine,
  • version/revision,
  • quote expiry,
  • quote-to-order mapping,
  • idempotent conversion,
  • auditability,
  • event contract,
  • reporting model,
  • dan production failure recovery.

1. Core Mental Model

Quote menjawab pertanyaan:

For this customer/account/context, what are we proposing to sell, at what configuration, price, terms, validity, and approval state?

Quote berada di antara product catalog dan product order.

graph LR A[Product Catalog / TMF620] --> B[Configuration] B --> C[Pricing] C --> D[Quote / TMF648] D --> E[Approval] E --> F[Accepted Quote] F --> G[Product Order / TMF622] G --> H[Fulfillment] H --> I[Billing]

Quote bukan sekadar shopping cart.

Quote adalah evidence untuk:

  • apa yang ditawarkan,
  • kapan ditawarkan,
  • siapa customer/account/party-nya,
  • harga dan discount yang disetujui,
  • catalog version yang digunakan,
  • configuration yang valid saat itu,
  • approval yang diperlukan,
  • expiry dan acceptance,
  • dan dasar order creation.

Quote as stateful commercial artifact

Quote biasanya melalui lifecycle:

Draft -> Configured -> Priced -> Submitted -> Approved -> Accepted -> ConvertedToOrder

Dengan alternate path:

Rejected, Cancelled, Expired, Revised

Hal yang harus dijaga:

A quote must remain explainable after catalog, price, customer, or rules have changed.

2. TMF648 Position in the Model Stack

TMF648 biasanya muncul sebagai API/reference model di boundary pre-ordering.

graph TD A[Internal Quote Domain Model] --> B[Quote Persistence Model] A --> C[TMF648-aligned API DTO] A --> D[Quote Events] A --> E[Quote Read Model] A --> F[Approval Workflow] A --> G[Quote-to-Order Mapping] H[Product Catalog / TMF620] --> A I[Customer / TMF629] --> A J[Agreement / Contract] --> A K[Pricing Service] --> A

Pemisahan penting:

ModelPurpose
Quote Domain ModelInvariant, lifecycle, command handling
Quote Persistence ModelTables, constraints, history, indexes
TMF648 API DTOExternal/internal API contract shape
Quote Event ModelIntegration and projection changes
Quote Snapshot ModelFrozen evidence for acceptance/conversion
Quote Read ModelSearch, dashboard, approval queue, reporting
Quote-to-Order Mapping ModelConversion traceability

Jangan memaksakan TMF648 response object menjadi database entity.


3. Quote Header

Quote header adalah container utama.

Quote header menyimpan data yang berlaku untuk seluruh quote.

Contoh conceptual fields:

FieldPurposeCorrectness Concern
quote_idInternal stable IDInternal reference
quote_numberBusiness/public identifierUnique, human-readable
customer_refCustomer contextMust be stable/snapshotted if needed
account_refAccount/billing/service account contextAvoid ambiguity
related_partyRoles involvedBuyer, seller, approver, contact
sales_channelChannel sourcePricing/eligibility impact
owner_user_idSales ownerAccess/approval routing
currencyQuote currencyPrice consistency
validity_periodQuote expiryAcceptance guard
quote_stateLifecycle stateTransition correctness
approval_statusCommercial approval stateMust not be conflated with quote state
version/revisionRevision controlImmutability and diff
source_opportunityCRM/opportunity referenceExternal traceability
catalog_versionCatalog contextHistorical correctness
price_summaryDerived totalRecalculation/snapshot policy
created/updated metadataAuditActor/source/correlation

Quote header invariant examples

A quote must have exactly one primary customer context.
A quote must have a currency before pricing is finalized.
An accepted quote must not be mutable except through revision/amendment process.
An expired quote cannot be accepted unless explicitly revived/revised.
A quote converted to order must retain source order mapping.

Internal verification checklist

  • Apakah quote punya internal ID dan business quote number?
  • Apakah quote number unique per tenant/customer/channel atau global?
  • Apakah customer/account distinction jelas?
  • Apakah currency wajib sebelum pricing?
  • Apakah quote state dan approval state dipisahkan?
  • Apakah quote expiry enforced?
  • Apakah quote revision/version ada?
  • Apakah accepted quote immutable?
  • Apakah quote punya source opportunity/CRM reference?

4. Quote Item

Quote item adalah unit komersial yang ditawarkan.

Quote item biasanya mereferensikan product offering dari catalog.

Quote item membawa:

  • selected product offering,
  • quantity,
  • configuration,
  • price,
  • discount,
  • tax estimate,
  • action,
  • site/location,
  • parent-child relation,
  • validation state,
  • approval impact,
  • order item mapping.

Conceptual model

erDiagram QUOTE ||--o{ QUOTE_ITEM : contains QUOTE_ITEM ||--o{ QUOTE_ITEM : parent_child QUOTE_ITEM ||--o{ QUOTE_ITEM_CHARACTERISTIC_VALUE : configured_by QUOTE_ITEM ||--o{ QUOTE_ITEM_PRICE : priced_by QUOTE_ITEM ||--o{ QUOTE_ITEM_DISCOUNT : discounted_by QUOTE_ITEM ||--o{ QUOTE_ITEM_RELATIONSHIP : relates_to

Quote item fields

FieldPurpose
quote_item_idInternal item ID
quote_idParent quote
parent_quote_item_idBundle/component hierarchy
item_sequenceDisplay/order sequence
product_offering_refCatalog offering reference
product_offering_versionStable version reference
product_specification_refOptional derived reference
actionAdd/modify/disconnect/etc.
quantityQuantity
site/location_refSite-specific quote context
stateItem lifecycle/validation state
validation_statusConfig/pricing validation
price_summaryItem-level summary

Quote item vs quote line

Terminology differs across systems.

Possible interpretation:

TermCommon Meaning
Quote ItemDomain unit that maps to product/order item
Quote LineUI/commercial line; sometimes same as item, sometimes price line/detail
Price ItemComponent of item price
Discount ItemApplied discount component
Tax ItemEstimated tax component

Internal verification is mandatory because teams often use these terms differently.

Internal verification checklist

  • Apakah quote item dan quote line istilahnya sama atau berbeda?
  • Apakah parent-child quote item mendukung bundle?
  • Apakah item action ada?
  • Apakah quote item menyimpan offering version/snapshot?
  • Apakah quantity dan site/location dimodelkan?
  • Apakah validation status item-level ada?
  • Apakah item-level price breakdown ada?
  • Apakah quote item mapping ke order item disimpan?

Related party menunjukkan pihak-pihak yang berperan dalam quote.

Contoh role:

  • customer,
  • buyer,
  • account owner,
  • sales representative,
  • reseller/partner,
  • approver,
  • billing contact,
  • technical contact,
  • legal contact,
  • contracting party.

Related party memengaruhi:

  • authority to request quote,
  • approval routing,
  • legal/commercial responsibility,
  • contact notification,
  • billing profile,
  • order ownership,
  • audit evidence.

Party vs Customer vs Account

Party = real-world individual or organization.
Customer = party in commercial customer role.
Account = financial/service relationship container.
RelatedParty = party reference with a role in this quote context.

Common failure modes

  • billing contact dipakai sebagai buyer,
  • legal entity tidak sama dengan service user,
  • approver disimpan sebagai free text,
  • partner/reseller ownership hilang saat conversion,
  • related party tidak versioned/snapshotted,
  • old quote rusak saat contact/customer data berubah.

Internal verification checklist

  • Apakah related party role punya controlled vocabulary?
  • Apakah quote customer, buyer, billing contact, legal contact dipisahkan?
  • Apakah related party snapshot disimpan?
  • Apakah quote approval routing memakai related party?
  • Apakah related party ikut dibawa ke order?
  • Apakah CRM/customer master update mengubah historical quote meaning?

6. Product Offering Reference

Quote item biasanya dibuat berdasarkan product offering.

Critical question:

Does quote item reference current offering or a specific offering version/snapshot?

Untuk production correctness, quote item perlu stable reference.

Reference patterns

PatternMeaningRisk
offering_id onlyReferences current offering rowMutable meaning risk
offering_id + versionStable version referenceNeed version lookup
deep snapshotFull frozen product detailsStorage and mapping complexity
mixed reference + snapshotPractical compromiseNeeds clear rules
Quote item should retain enough product/catalog data to explain the quote without relying on mutable current catalog state.

At minimum, consider storing:

  • product offering ID/code,
  • product offering name at quote time,
  • product offering version,
  • catalog version/release,
  • product specification reference,
  • selected characteristics,
  • price version/reference,
  • effective date used.

Internal verification checklist

  • Apakah quote item punya offering ID, code, dan version?
  • Apakah offering name disnapshot?
  • Apakah catalog release/version disimpan?
  • Apakah product offering deletion/retirement aman untuk old quote?
  • Apakah quote display memakai snapshot atau current catalog?
  • Apakah conversion ke order memakai snapshot atau latest catalog?

7. Product Configuration

Product configuration adalah selected options dan characteristic values untuk quote item.

Configuration berasal dari catalog-driven rules tetapi quote harus menyimpan hasilnya.

Definition vs selected value

Catalog characteristic definition: Bandwidth allowed values = 500Mbps, 1Gbps, 10Gbps.
Quote configuration value: Bandwidth selected = 1Gbps.

Configuration model

erDiagram QUOTE_ITEM ||--o{ QUOTE_ITEM_CHARACTERISTIC_VALUE : has QUOTE_ITEM_CHARACTERISTIC_VALUE { string characteristic_code string value_type string string_value numeric numeric_value boolean boolean_value string unit_of_measure string source string validation_status }

Configuration snapshot

Quote should preserve:

  • characteristic code/name,
  • selected value,
  • value type,
  • unit of measure,
  • catalog characteristic version,
  • validation result,
  • rule trace if needed,
  • configuration errors/warnings.

Failure modes

  • selected value no longer allowed after catalog update,
  • quote display changes because characteristic name changed,
  • order decomposition lacks required technical characteristic,
  • billing cannot map configurable option to charge,
  • modify order cannot compare old vs new configuration.

Internal verification checklist

  • Apakah configuration disimpan structured atau JSONB?
  • Apakah characteristic value typed?
  • Apakah catalog characteristic version/reference disimpan?
  • Apakah validation error/warning disimpan?
  • Apakah configuration snapshot immutable setelah quote accepted?
  • Apakah order receives configuration snapshot?
  • Apakah billing/provisioning membutuhkan subset field tertentu?

8. Quote Price Model

Quote price adalah harga yang dihitung untuk quote context.

Quote price bukan sekadar copy product offering price.

Quote price dipengaruhi oleh:

  • catalog price,
  • customer segment,
  • contract/agreement,
  • selected configuration,
  • quantity,
  • site/location,
  • term,
  • discount,
  • promotion,
  • tax estimate,
  • currency,
  • effective date,
  • approval policy.

Price layers

LayerMeaning
Catalog PriceList/reference price from catalog
Calculated PriceResult of pricing engine
Quote PricePrice proposed to customer, possibly with discount
Approved PricePrice after approval decision
Order PricePrice carried into order
Billing ChargeBillable financial component
Invoice LineActual invoice record

Quote price breakdown

A robust quote item price model should capture:

  • base/list price,
  • recurring charge,
  • one-time charge,
  • usage charge estimate,
  • discount amount/percentage,
  • promotion reference,
  • tax estimate,
  • currency,
  • price version,
  • calculation timestamp,
  • pricing rule trace,
  • manual override indicator,
  • approval requirement indicator.

Price snapshot invariant

Accepted quote price must be explainable without recalculating from current pricing rules.

Internal verification checklist

  • Apakah quote price dipisahkan dari catalog price?
  • Apakah price breakdown disimpan?
  • Apakah discount dan tax estimate dipisahkan?
  • Apakah pricing rule trace ada?
  • Apakah manual override ditandai?
  • Apakah accepted quote price immutable?
  • Apakah order carries quote price?
  • Apakah billing receives quote/order price snapshot?

9. Agreement Reference

Quote dapat merujuk agreement/contract.

Agreement memengaruhi:

  • eligible products,
  • negotiated pricing,
  • discount entitlement,
  • contract term,
  • renewal condition,
  • SLA,
  • billing terms,
  • legal entity,
  • termination fee,
  • special commercial terms.

Agreement modelling in quote

Quote tidak selalu perlu menyimpan full agreement copy, tetapi harus menyimpan reference/snapshot cukup untuk traceability.

Possible fields:

FieldPurpose
agreement_idInternal agreement reference
agreement_numberBusiness/legal reference
agreement_versionStable version
agreement_term_refSpecific term reference
commercial_term_snapshotRelevant terms used in quote
discount_agreement_refDiscount entitlement
contract_validityValidity period

Invariant examples

A quote cannot use an expired agreement unless business explicitly allows renewal/revision flow.
A quote using agreement-based discount must record the agreement version/term used.
An accepted quote must remain explainable even if the agreement is later amended.

Internal verification checklist

  • Apakah quote punya agreement reference?
  • Apakah agreement version disimpan?
  • Apakah agreement term/discount entitlement disnapshot?
  • Apakah agreement validity dicek saat submit/accept?
  • Apakah quote-to-order membawa agreement reference?
  • Apakah billing memakai agreement terms?

10. Validity Period and Expiry

Quote validity period adalah batas waktu commercial offer berlaku.

Ini berbeda dari:

  • catalog validity,
  • price validity,
  • contract term,
  • subscription period,
  • order requested date,
  • billing period.

Validity semantics

Quote validity defines until when the customer may accept this commercial proposal.

Common fields:

  • valid_from,
  • valid_to,
  • expiry_reason,
  • expiry_policy,
  • expired_at,
  • expiry_job_id,
  • extended_from_quote_id,
  • extension_approval_ref.

Expiry state flow

stateDiagram-v2 Draft --> Submitted Submitted --> Approved Approved --> Accepted Approved --> Expired Submitted --> Expired Draft --> Cancelled Expired --> Revised Accepted --> ConvertedToOrder

Correctness concerns

  • quote accepted after expiry,
  • timezone boundary issue,
  • expiry job misses quote,
  • quote valid_to changed without audit,
  • extension bypasses approval,
  • expired quote converted to order.

Internal verification checklist

  • Apakah valid_from/valid_to timezone policy jelas?
  • Apakah expiry enforced by API and job?
  • Apakah expired quote cannot be accepted?
  • Apakah extension flow ada?
  • Apakah expiry transition diaudit?
  • Apakah conversion checks expiry?

11. Quote State

Quote state merepresentasikan lifecycle commercial artifact.

Jangan campur quote state dengan:

  • approval status,
  • pricing status,
  • validation status,
  • payment status,
  • order status,
  • fulfillment status.

Example state model

stateDiagram-v2 [*] --> Draft Draft --> Configured Configured --> Priced Priced --> Submitted Submitted --> Approved Submitted --> Rejected Approved --> Accepted Approved --> Expired Draft --> Cancelled Priced --> Revised Rejected --> Revised Expired --> Revised Accepted --> ConvertedToOrder ConvertedToOrder --> [*]

State transition table example

FromToGuardSide Effect
DraftConfiguredRequired items validSave configuration snapshot
ConfiguredPricedPricing input completeCreate price snapshot
PricedSubmittedQuote completeStart approval if needed
SubmittedApprovedApproval passedFreeze approved price
ApprovedAcceptedNot expiredFreeze accepted quote
AcceptedConvertedToOrderIdempotency check passedCreate order + mapping

Internal verification checklist

  • Apakah state transition eksplisit?
  • Apakah illegal transition dicegah?
  • Apakah state history disimpan?
  • Apakah side effect transition jelas?
  • Apakah concurrent transition ditangani?
  • Apakah quote state dan approval state tidak dicampur?

12. Quote Item Action

Quote item action menjelaskan apa yang ingin dilakukan terhadap product.

Common actions:

  • add,
  • modify,
  • disconnect,
  • suspend,
  • resume,
  • change plan,
  • upgrade,
  • downgrade,
  • move,
  • renew.

Why action matters

Action menentukan:

  • required reference ke installed product,
  • pricing behavior,
  • eligibility rule,
  • order item action,
  • fulfillment task,
  • billing trigger,
  • inventory update.

Add vs Modify vs Disconnect

ActionRequires Product Inventory?Typical Effect
AddNoCreate new product instance
ModifyYesChange existing product instance
DisconnectYesTerminate product instance
SuspendYesTemporarily disable service
ResumeYesReactivate suspended service
Change PlanYesReplace/modify offering/configuration

Invariant examples

Modify/disconnect action must reference an existing active/suspendable product instance.
Add action must not reference existing product instance as target unless explicitly modelling replacement.
Action must be compatible with offering and current inventory state.

Internal verification checklist

  • Apakah quote item action ada?
  • Apakah action enum aligned dengan order item action?
  • Apakah modify/disconnect reference installed product?
  • Apakah action compatibility divalidasi?
  • Apakah pricing berbeda per action?
  • Apakah action dibawa ke order item?

13. Quote Authorization and Approval

Quote approval adalah commercial governance process.

Approval biasanya dipicu oleh:

  • discount melebihi threshold,
  • margin rendah,
  • non-standard term,
  • special price override,
  • risky customer segment,
  • contract exception,
  • product exception,
  • channel-specific rule.

Approval is not quote state

Quote state = lifecycle of the quote.
Approval status = governance decision state.

Quote bisa Submitted dengan approval status Pending. Quote bisa Approved setelah semua approval selesai.

Approval data model

erDiagram QUOTE ||--o{ APPROVAL_REQUEST : requires APPROVAL_REQUEST ||--o{ APPROVAL_STEP : contains APPROVAL_STEP ||--o{ APPROVAL_DECISION : records APPROVAL_STEP }o--|| APPROVER : assigned_to

Approval trace should capture

  • approval rule that triggered,
  • threshold exceeded,
  • requested discount/margin,
  • approver role/group,
  • assigned approver,
  • delegation if any,
  • decision,
  • comment/reason,
  • timestamp,
  • actor,
  • correlation ID,
  • before/after quote price.

Internal verification checklist

  • Apakah approval request dipisahkan dari quote?
  • Apakah approval rule trace disimpan?
  • Apakah approval decision immutable?
  • Apakah delegation didukung?
  • Apakah approval history cukup untuk audit?
  • Apakah quote can be accepted only after required approvals?
  • Apakah approval re-triggered after quote revision?

14. Quote-to-Order Conversion

Quote-to-order conversion adalah transformasi dari accepted quote menjadi executable order.

Ini harus idempotent dan auditable.

Conversion mapping

graph TD A[Quote] --> B[Product Order] A1[Quote Item 1] --> B1[Order Item 1] A2[Quote Item 2] --> B2[Order Item 2] A3[Quote Item 3] --> B3[Order Item 3] C[Quote Price Snapshot] --> D[Order Price / Billing Trigger] E[Quote Configuration Snapshot] --> F[Order Configuration] G[Quote Agreement Ref] --> H[Order Agreement Ref]

Conversion record

A robust model stores:

FieldPurpose
conversion_idUnique conversion attempt/reference
quote_idSource quote
quote_versionAccepted version
order_idCreated order
idempotency_keyDuplicate prevention
conversion_statusSuccess/failed/partial
failure_reasonDebugging
started_at/completed_atOperational tracking
correlation_idTraceability

Invariant examples

Only accepted quote can be converted.
Expired/cancelled/rejected quote cannot be converted.
A quote version should not create duplicate orders for the same idempotency key.
Order item must be traceable back to quote item.

Internal verification checklist

  • Apakah conversion punya idempotency key?
  • Apakah quote-to-order mapping table ada?
  • Apakah duplicate order dicegah?
  • Apakah conversion failure disimpan?
  • Apakah partial conversion mungkin?
  • Apakah order item punya source quote item reference?
  • Apakah conversion event diterbitkan?

15. API Model Mapping

TMF648-aligned API DTO harus dipisahkan dari internal persistence.

Possible mapping:

TMF648-like ResourceInternal Model
Quotequote_header + summary + related refs
QuoteItemquote_item + config + price summary
RelatedPartyrelated_party table/snapshot
ProductOfferingRefoffering version/snapshot reference
Productconfigured product representation
QuotePricequote item/header price breakdown
AgreementRefagreement reference/snapshot
Statequote lifecycle state mapping

API contract concerns

  • field names may follow TMF reference,
  • internal field names may differ,
  • extension fields must be intentional,
  • nullability must be stable,
  • enum values must be mapped carefully,
  • pagination/search must not expose inefficient query pattern,
  • PATCH semantics must preserve invariants.

Java/JAX-RS implication

Recommended structure:

QuoteResource
  -> QuoteApplicationService
      -> QuoteCommandHandler / QuoteDomainService
          -> QuoteRepository
          -> PricingClient
          -> CatalogClient
          -> ApprovalClient
          -> OrderClient

Avoid:

QuoteResource directly manipulates quote tables and returns persistence entity.

Internal verification checklist

  • Apakah TMF648 DTO dipisahkan dari quote entity/table?
  • Apakah enum mapping terdokumentasi?
  • Apakah PATCH/update menjaga invariant?
  • Apakah API response memakai snapshot atau current reference?
  • Apakah API backward compatibility diuji?
  • Apakah API extension fields jelas owner-nya?

16. Event Model Mapping

Quote lifecycle menghasilkan events.

Event umum:

  • QuoteCreated,
  • QuoteConfigured,
  • QuotePriced,
  • QuoteSubmitted,
  • QuoteApprovalRequested,
  • QuoteApproved,
  • QuoteRejected,
  • QuoteAccepted,
  • QuoteExpired,
  • QuoteCancelled,
  • QuoteRevised,
  • QuoteConvertedToOrder,
  • QuoteConversionFailed.

Event payload principles

Quote event harus membawa:

  • event ID,
  • event version,
  • quote ID,
  • quote number,
  • quote version/revision,
  • state before/after if lifecycle event,
  • customer/account reference,
  • correlation ID,
  • causation ID,
  • occurred at,
  • source system,
  • minimal business summary.

Event example

{
  "eventId": "...",
  "eventType": "QuoteAccepted",
  "eventVersion": 1,
  "quoteId": "...",
  "quoteNumber": "Q-2026-000123",
  "quoteRevision": 3,
  "customerId": "...",
  "accountId": "...",
  "acceptedAt": "2026-07-11T10:15:30Z",
  "validTo": "2026-07-31T23:59:59Z",
  "correlationId": "...",
  "causationId": "..."
}

Event correctness concerns

  • QuoteAccepted emitted before DB commit,
  • QuoteConvertedToOrder emitted twice,
  • event lacks quote revision,
  • out-of-order QuoteRevised arrives after QuoteAccepted,
  • consumer assumes event payload is full snapshot,
  • event schema changes break consumers,
  • quote projection stale.

Internal verification checklist

  • Apakah quote events ada?
  • Apakah event emitted via outbox?
  • Apakah event punya quote version/revision?
  • Apakah state before/after disimpan?
  • Apakah consumer idempotent?
  • Apakah event schema versioned?
  • Apakah event digunakan untuk reporting/read model?

17. PostgreSQL Implementation Considerations

Possible physical model:

quote
quote_version
quote_item
quote_item_characteristic_value
quote_item_price
quote_item_discount
quote_item_tax
quote_related_party
quote_agreement_ref
quote_state_history
quote_approval_ref
quote_conversion
quote_order_mapping
quote_audit_event
quote_outbox_event

Constraint examples

-- Example only. Verify against actual internal schema conventions.
unique (tenant_id, quote_number)
check (valid_to is null or valid_to > valid_from)
unique (quote_id, revision)
unique (quote_id, idempotency_key) -- for conversion if scoped this way

Index candidates

Query PatternIndex Candidate
quote by number(tenant_id, quote_number)
quotes by customer(tenant_id, customer_id, created_at desc)
approval queue(tenant_id, approval_status, updated_at)
expiry job(quote_state, valid_to)
quote search by owner/status(tenant_id, owner_user_id, quote_state, updated_at)
conversion lookup(quote_id, quote_revision, conversion_status)
audit by correlation(correlation_id)

Snapshot storage

Snapshot can be stored as:

  • normalized version tables,
  • immutable quote revision tables,
  • JSONB snapshot for external references,
  • audit/change-history tables,
  • hybrid normalized + JSONB evidence.

Principle:

Core fields that drive lifecycle/query/reporting should not be hidden only in JSONB.

Internal verification checklist

  • Apakah quote table terlalu wide?
  • Apakah quote item/price/config normalized?
  • Apakah snapshot versioning jelas?
  • Apakah expiry query indexed?
  • Apakah approval queue query indexed?
  • Apakah conversion idempotency constrained?
  • Apakah audit/event tables partitioned jika besar?

18. MyBatis/JPA/JDBC Implications

Quote model sering kompleks karena nested item, price breakdown, config values, related parties, dan approval references.

Common traps

TrapImpact
Loading full quote graph for every searchSlow list/search API
Updating quote item tree by replace-allAccidental data loss
No optimistic locking on quote revisionLost update
Entity reused as DTOContract coupling
Price recalculated on readHistorical inconsistency
JSONB config with no validationInvalid order payload

Safer patterns

  • command-based update,
  • explicit quote aggregate loading for write use cases,
  • projection/read model for list/search,
  • optimistic locking on quote revision,
  • immutable accepted quote snapshot,
  • dedicated mapper for TMF648 DTO,
  • separate queries for price/config/approval when needed,
  • transactional outbox for lifecycle events.

Internal verification checklist

  • Apakah repository membedakan write aggregate dan read projection?
  • Apakah quote revision memakai optimistic lock?
  • Apakah update quote item tree aman?
  • Apakah price dihitung saat command, bukan diam-diam saat read?
  • Apakah mapper memisahkan entity dan DTO?
  • Apakah MyBatis/JPA query menyebabkan N+1?

19. Reporting and Read Model Implications

Quote reporting umum:

  • quote pipeline,
  • quote conversion rate,
  • average quote value,
  • discount by approver/product/customer,
  • quote aging,
  • quote expiry risk,
  • approval SLA,
  • win/loss analysis,
  • quote-to-order fallout,
  • price override frequency.

Read model examples

quote_search_view
quote_pipeline_projection
approval_queue_projection
quote_item_product_projection
quote_conversion_fact

Reporting fields to preserve

  • quote number,
  • customer/account,
  • owner,
  • channel,
  • quote state,
  • approval status,
  • created/submitted/approved/accepted/expired timestamps,
  • total one-time charge,
  • total recurring charge,
  • discount amount/percentage,
  • catalog version,
  • product family/category,
  • converted order reference.

Internal verification checklist

  • Apakah quote lifecycle timestamps disimpan?
  • Apakah quote state history tersedia untuk funnel metrics?
  • Apakah quote item product dimension versioned?
  • Apakah quote value snapshot digunakan untuk reporting?
  • Apakah approval aging dapat dihitung?
  • Apakah quote-to-order conversion metric tersedia?

20. Auditability and Change History

Quote adalah commercial evidence. Audit trail harus kuat.

Audit harus menjawab:

Who changed what, when, why, under what business action, from what source, with what approval, and what price/configuration was affected?

Audit event examples

  • quote created,
  • item added/removed,
  • configuration changed,
  • price recalculated,
  • discount overridden,
  • submitted for approval,
  • approved/rejected,
  • validity extended,
  • quote accepted,
  • quote revised,
  • quote converted to order.

Audit record should include

  • actor,
  • action,
  • target entity,
  • before/after values,
  • reason/comment,
  • source system,
  • correlation ID,
  • causation ID,
  • timestamp,
  • quote revision,
  • approval reference.

Internal verification checklist

  • Apakah quote audit event ada?
  • Apakah before/after value disimpan untuk critical fields?
  • Apakah price/discount changes audited?
  • Apakah approval trace linked ke quote revision?
  • Apakah correlation ID tersedia end-to-end?
  • Apakah audit immutable?

21. Security and Privacy Concerns

Quote mengandung data sensitif:

  • customer identity,
  • commercial price,
  • discount,
  • margin/profitability,
  • contract/agreement reference,
  • contact information,
  • site/location,
  • internal approval comments,
  • competitive pricing notes,
  • credit/commercial risk signals.

Access model

Quote access bisa bergantung pada:

  • tenant,
  • sales team,
  • owner,
  • customer/account assignment,
  • role/permission,
  • approval authority,
  • commercial sensitivity,
  • geographic/business unit boundary.

Security failure modes

  • sales rep melihat quote customer lain,
  • approver melihat margin tanpa authority,
  • exported quote membuka internal cost,
  • API response exposes approval comments,
  • search index tidak menerapkan tenant/security filter,
  • audit log menyimpan PII tanpa retention/masking.

Internal verification checklist

  • Apakah quote access tenant-aware?
  • Apakah owner/team-based visibility diterapkan?
  • Apakah margin/cost fields protected?
  • Apakah export/print quote berbeda dari internal API?
  • Apakah search index aman?
  • Apakah PII retention/masking policy jelas?

22. Failure Modes

Common quote data failure modes:

Failure ModeCauseDetection
Duplicate quoteRetry without idempotencyDuplicate external/opportunity/request key
Accepted expired quoteMissing expiry guardaccepted_at > valid_to query
Price mismatchRecalculation from latest priceCompare quote snapshot vs price version
Catalog mismatchMutable catalog referenceQuote offering version missing
Invalid configurationRule not enforced or stale configValidation status/error query
Approval bypassState transition without approval guardApproved/accepted with missing approval decision
Duplicate orderConversion retry unsafeMultiple orders for same quote revision
Lost updateConcurrent edits without revision lockRevision conflict/audit gap
Audit gapDirect DB update/no auditCritical changes without audit event
Stale read modelProjection lagRead model freshness metric

23. Debugging Quote Data Issues

When debugging quote issue, use lifecycle trace.

Diagnostic questions

Which quote revision is relevant?
Which catalog version was used?
Which product offering version was selected?
Which configuration values were selected?
Which price version/rules were used?
Was the quote expired when accepted?
Was approval required and completed?
Was the quote revised after approval?
Was the accepted quote converted more than once?
Did read model/search show stale state?

Diagnostic data trail

Follow this order:

  1. quote header,
  2. quote revision/version,
  3. quote state history,
  4. quote item tree,
  5. configuration snapshot,
  6. price snapshot,
  7. discount/approval trace,
  8. agreement reference,
  9. conversion record,
  10. order mapping,
  11. outbox/event log,
  12. read model projection.

24. PR Review Checklist

When reviewing a quote data model PR, ask:

Entity and lifecycle

  • Is this quote header, item, price, configuration, approval, or conversion data?
  • Is the lifecycle state impacted?
  • Are illegal transitions prevented?
  • Is quote revision/version handled?

Snapshot and correctness

  • Does accepted quote remain immutable?
  • Does the change preserve historical catalog/price/config meaning?
  • Does quote-to-order mapping remain traceable?
  • Does expiry still work?

API/event

  • Does TMF648 DTO contract change?
  • Is backward compatibility preserved?
  • Are event schemas updated/versioned?
  • Are consumers affected?

Persistence and performance

  • Are constraints sufficient?
  • Are indexes aligned with search/queue/expiry patterns?
  • Is migration safe for existing quotes?
  • Is JSONB used responsibly?

Operations and audit

  • Is audit trail updated?
  • Is read model projection updated?
  • Is cache invalidation needed?
  • Is reporting impacted?
  • Is data repair/reconciliation possible?

25. Internal Verification Checklist

Gunakan checklist ini untuk mempelajari quote model internal.

Codebase

  • Temukan quote service/module.
  • Temukan quote aggregate/domain classes.
  • Temukan quote JAX-RS resources/controllers.
  • Temukan quote command handlers.
  • Temukan pricing/catalog/customer/agreement clients.
  • Temukan quote-to-order conversion code.

Database schema

  • Temukan quote header table.
  • Temukan quote item table.
  • Temukan quote price/discount/tax tables.
  • Temukan configuration value storage.
  • Temukan quote state history.
  • Temukan quote approval references.
  • Temukan quote conversion/order mapping.
  • Temukan audit/history/outbox tables.

API contract

  • Cek apakah API TMF648-aligned.
  • Cek enum state mapping.
  • Cek update/PATCH semantics.
  • Cek extension fields.
  • Cek API versioning and contract tests.

Events

  • Cek QuoteCreated/Submitted/Approved/Accepted/Converted events.
  • Cek event versioning.
  • Cek outbox pattern.
  • Cek projection consumers.
  • Cek idempotency handling.

Business/process

  • Tanya BA/PO: quote lifecycle business semantics.
  • Tanya senior engineer: accepted quote immutability policy.
  • Tanya solution architect: TMF648 alignment level.
  • Tanya DBA: quote query hotspots.
  • Tanya support/ops: frequent quote production issues.

26. Summary

TMF648 membantu memberi reference model untuk quote management, tetapi production-grade quote model harus lebih dalam daripada API shape.

Quote data model harus menjaga:

  • customer/account context,
  • product offering reference,
  • configuration snapshot,
  • price snapshot,
  • discount and approval trace,
  • validity and expiry,
  • lifecycle state machine,
  • version/revision,
  • quote-to-order mapping,
  • auditability,
  • security,
  • reporting readiness,
  • dan failure recovery.

Core takeaway:

A quote is not just a proposal document.
It is a versioned, stateful, auditable commercial evidence object that becomes the source for order execution.
Lesson Recap

You just completed lesson 08 in start here. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.