Focus mode active/Press Alt+Shift+R to toggle/Esc to exit
Build CoreOrdered learning track

Charge and Invoice Model

Model charge dan invoice untuk enterprise quote-to-cash systems, termasuk recurring charge, one-time charge, usage charge, tax, discount, credit, debit, invoice, invoice line, billing period, due date, payment status, reconciliation, auditability, and production correctness.

14 min read2681 words
PrevNext
Lesson 3582 lesson track16–45 Build Core
#enterprise-data-modelling#charge#invoice#billing+6 more

Charge and Invoice Model

1. Core Idea

Charge and invoice modelling adalah bagian dari quote-to-cash yang mengubah commercial price dan fulfilled order menjadi financial billing artifact.

Quote price menjawab:

Berapa harga yang ditawarkan dan disetujui?

Order/fulfillment menjawab:

Apa yang benar-benar dieksekusi dan diaktifkan?

Charge menjawab:

Apa yang harus ditagihkan, untuk periode apa, kepada billing account mana, berdasarkan produk/order/usage apa?

Invoice menjawab:

Dokumen tagihan resmi apa yang dikirim ke payer, berisi line apa saja, total berapa, due date kapan, dan payment status apa?

Mental model:

Price is commercial intent, charge is billable obligation, invoice is customer-facing billing document.


2. Why Charge and Invoice Modelling Matters

Banyak bug quote-to-cash terjadi karena sistem mencampur price, charge, invoice line, dan payment.

Contoh kesalahan:

  • quote price dianggap invoice line,
  • recurring charge dibuat sebelum activation,
  • tax dihitung dari address yang salah,
  • discount diterapkan dua kali,
  • usage charge duplicate karena event retry,
  • invoice line tidak bisa ditrace ke order item,
  • payment status disimpan di order status,
  • invoice total tidak sama dengan sum invoice lines,
  • billing correction dilakukan tanpa credit/debit note,
  • one-time charge muncul setiap billing cycle,
  • cancelled order tetap menghasilkan invoice.

Charge and invoice model harus menjaga financial correctness, auditability, and reconciliation.


3. Price vs Charge vs Invoice Line

ConceptMeaningLifecycle
PriceCommercial value defined in catalog/pricing/quote.Before order/billing.
ChargeBillable obligation generated from product/order/usage.Billing lifecycle.
Invoice lineLine item on a generated invoice.Invoice document lifecycle.
PaymentSettlement against invoice/account.Finance/payment lifecycle.

Example:

Catalog price:
  Business Internet recurring price = $100/month

Quote price snapshot:
  Customer accepted $90/month after discount

Charge:
  Recurring charge $90/month for product instance P-123, billing account BA-001

Invoice line:
  Invoice INV-001 line: $90 for 2026-08-01 to 2026-08-31

Payment:
  Customer paid invoice INV-001 on 2026-09-05

Do not collapse these into one table unless your domain is extremely simple.


4. Charge Types

Common charge types:

Charge typeMeaning
One-time chargeNon-recurring charge, e.g. setup fee, installation fee.
Recurring chargePeriodic charge, e.g. monthly subscription.
Usage chargeCharge based on metered usage.
Tax chargeTax/VAT/GST/SST/etc.
Discount chargeDiscount as separate negative line or adjustment.
CreditAmount reducing customer balance.
DebitAdditional amount increasing customer balance.
Penalty/feeEarly termination fee, late fee, service fee.
AdjustmentManual/system correction.

Charges should be typed because billing behavior differs.


5. Charge Lifecycle

Conceptual lifecycle:

stateDiagram-v2 [*] --> PLANNED PLANNED --> PENDING_ACTIVATION: orderAccepted PENDING_ACTIVATION --> ACTIVE: productActivated ACTIVE --> BILLED: includedInInvoice ACTIVE --> SUSPENDED: billingSuspended SUSPENDED --> ACTIVE: billingResumed ACTIVE --> TERMINATED: productTerminated BILLED --> ADJUSTED: correction BILLED --> CREDITED: creditIssued TERMINATED --> [*] CANCELLED --> [*] PLANNED --> CANCELLED: orderCancelled PENDING_ACTIVATION --> CANCELLED: activationCancelled

Charge lifecycle must reflect product/order/billing lifecycle.

Important distinction:

  • charge definition can be active over time,
  • invoice line is a generated occurrence,
  • payment is settlement after invoice.

6. Invoice Lifecycle

Conceptual invoice lifecycle:

stateDiagram-v2 [*] --> DRAFT DRAFT --> GENERATED: generate GENERATED --> ISSUED: issueToCustomer ISSUED --> PARTIALLY_PAID: partialPayment ISSUED --> PAID: fullPayment PARTIALLY_PAID --> PAID: fullPayment ISSUED --> OVERDUE: dueDatePassed PARTIALLY_PAID --> OVERDUE: dueDatePassed ISSUED --> VOIDED: void GENERATED --> CANCELLED: cancelBeforeIssue OVERDUE --> PAID: paymentReceived ISSUED --> DISPUTED: disputeRaised DISPUTED --> ISSUED: disputeResolved PAID --> CLOSED: close VOIDED --> [*] CLOSED --> [*]

Actual invoice lifecycle may be owned by external billing system. Internal system may only store references/status snapshots.


7. Core Charge Fields

Common fields:

FieldPurpose
idInternal charge ID.
charge_numberBusiness reference if needed.
charge_typeOne-time, recurring, usage, tax, adjustment, etc.
billing_account_idPayer responsibility.
customer_idCustomer context.
product_instance_idInstalled product related to charge.
order_id / order_item_idSource order trace.
quote_id / quote_item_idAccepted commercial trace if needed.
price_snapshot_idSource price evidence.
amountCharge amount.
currencyBilling currency.
tax_profile_idTax context.
billing_period_start/endPeriod covered by charge.
effective_from/toValidity of charge.
statusPlanned, active, billed, cancelled, etc.
external_charge_idBilling system reference.
created_at / updated_atTechnical timestamps.

8. Core Invoice Fields

Common fields:

FieldPurpose
idInternal invoice ID.
invoice_numberCustomer-facing invoice reference.
billing_account_idPayer.
customer_idCustomer context.
invoice_dateDate invoice generated/issued.
due_datePayment due date.
billing_period_start/endPeriod covered.
currencyInvoice currency.
subtotal_amountAmount before tax/adjustments depending semantics.
tax_amountTotal tax.
discount_amountTotal discount.
total_amountInvoice total.
amount_paidSettled amount.
balance_dueOutstanding amount.
statusDraft, issued, paid, overdue, voided, etc.
external_invoice_idBilling system reference.

Invoice total must be derived/reconciled from invoice lines. Avoid arbitrary manual total without line evidence.


9. Core Invoice Line Fields

Invoice line connects invoice to charge.

invoice_line
- id
- invoice_id
- charge_id
- line_type
- description
- product_instance_id
- order_id
- order_item_id
- quantity
- unit_amount
- amount
- tax_amount
- discount_amount
- billing_period_start
- billing_period_end
- currency

Invoice line should support traceability:

invoice line -> charge -> product instance -> order item -> quote item -> price snapshot

This trace is critical for disputes and reconciliation.


10. Conceptual ERD

erDiagram BILLING_ACCOUNT { uuid id PK string billing_account_number } CHARGE { uuid id PK string charge_type uuid billing_account_id FK uuid product_instance_id uuid order_id uuid order_item_id decimal amount string currency string status date billing_period_start date billing_period_end } INVOICE { uuid id PK string invoice_number uuid billing_account_id FK date invoice_date date due_date string status decimal total_amount decimal balance_due string currency } INVOICE_LINE { uuid id PK uuid invoice_id FK uuid charge_id FK string line_type decimal amount decimal tax_amount decimal discount_amount date billing_period_start date billing_period_end } PAYMENT { uuid id PK uuid invoice_id FK decimal amount string status timestamp paid_at } BILLING_ACCOUNT ||--o{ CHARGE : has BILLING_ACCOUNT ||--o{ INVOICE : receives CHARGE ||--o{ INVOICE_LINE : appears_as INVOICE ||--o{ INVOICE_LINE : contains INVOICE ||--o{ PAYMENT : settled_by

11. One-Time Charge

One-time charge examples:

  • setup fee,
  • installation fee,
  • activation fee,
  • equipment fee,
  • migration fee,
  • cancellation fee,
  • early termination fee.

Important fields:

  • source order item,
  • trigger event,
  • effective date,
  • bill once flag,
  • external charge reference,
  • billing account,
  • tax category,
  • status.

Critical invariant:

A one-time charge must not be billed more than once for the same source event unless explicitly adjusted.

Use idempotency key:

one_time_charge_key = order_item_id + charge_type + trigger_event

12. Recurring Charge

Recurring charge examples:

  • monthly subscription fee,
  • annual license fee,
  • managed service fee,
  • recurring add-on fee.

Recurring charge needs:

  • start date,
  • end date,
  • billing frequency,
  • billing cycle,
  • proration policy,
  • amount,
  • currency,
  • product instance,
  • billing account,
  • suspension behavior,
  • cancellation behavior,
  • renewal behavior.

A recurring charge is not the same as each invoice line. One recurring charge can generate many invoice lines over time.


13. Usage Charge

Usage charge is based on metered usage.

Data flow:

Usage event -> mediation/aggregation -> rating -> rated usage -> usage charge -> invoice line

Usage charge needs:

  • usage event reference,
  • usage period,
  • meter type,
  • quantity/units,
  • rating rule,
  • rated amount,
  • allowance/overage,
  • aggregation key,
  • duplicate detection key.

Usage is covered deeply in part 037, but charge model must reserve a place for usage charges.


14. Tax Modelling

Tax can be modelled as:

  1. included in charge amount,
  2. separate tax charge,
  3. tax fields on invoice line,
  4. tax summary table,
  5. external tax engine reference.

Tax depends on:

  • billing account,
  • billing address,
  • service address,
  • product tax category,
  • customer tax profile,
  • jurisdiction,
  • invoice date,
  • tax exemption,
  • legal entity.

Do not hard-code tax as a simple percent field unless domain guarantees it.

Tax evidence should be auditable.


15. Discount on Invoice

Discount can appear as:

  • price already net of discount,
  • separate negative charge,
  • invoice line discount amount,
  • promotion adjustment,
  • credit note,
  • billing system adjustment.

Important question:

Is discount applied during quote pricing, charge generation, invoice generation, or payment settlement?

For traceability, preserve:

  • discount reason,
  • approval reference,
  • promotion/agreement reference,
  • quote price snapshot,
  • charge discount,
  • invoice line discount.

Avoid double discount.


16. Credit and Debit

Credit and debit are financial adjustments.

Credit examples:

  • billing error refund,
  • service outage credit,
  • goodwill credit,
  • overpayment adjustment,
  • cancellation credit.

Debit examples:

  • underbilling correction,
  • late fee,
  • penalty,
  • manual adjustment.

Model:

billing_adjustment
- id
- adjustment_type = CREDIT / DEBIT
- billing_account_id
- invoice_id nullable
- charge_id nullable
- amount
- currency
- reason_code
- approval_reference
- status
- created_at

Do not edit old invoice lines silently to correct financial outcome. Use adjustment/credit/debit where required by billing policy.


17. Billing Period

Billing period must be explicit.

Fields:

billing_period_start
billing_period_end

Define:

  • inclusive or exclusive end,
  • timezone,
  • date vs timestamp,
  • proration rule,
  • partial period handling,
  • first invoice period,
  • final invoice period,
  • usage period vs invoice period.

Common rule:

[start, end)

Meaning start inclusive, end exclusive. But verify internally.

Failure mode:

Customer billed for one extra day due to inclusive/exclusive ambiguity.

18. Due Date and Payment Terms

Due date is derived from invoice date and payment terms.

Examples:

  • due on receipt,
  • net 15,
  • net 30,
  • net 45,
  • custom enterprise term,
  • due by fixed day of month.

Payment term may come from:

  • billing profile,
  • agreement,
  • customer segment,
  • invoice preference,
  • external billing system.

Do not hard-code due date calculation in multiple services.


19. Payment Status

Payment status belongs to invoice/payment model, not order lifecycle.

Common statuses:

  • unpaid,
  • partially paid,
  • paid,
  • overdue,
  • disputed,
  • written off,
  • refunded,
  • voided.

Payment record fields:

payment
- id
- invoice_id
- billing_account_id
- amount
- currency
- payment_method_reference
- status
- paid_at
- external_payment_id

If payment is owned by external billing/finance system, internal model may only store status snapshot/reference.


20. Charge Generation from Order

Charge generation should be linked to order fulfillment and product inventory.

Possible triggers:

  • order item fulfilled,
  • product instance activated,
  • service activated,
  • billing readiness event,
  • manual billing trigger,
  • billing cycle job,
  • usage rating completion.

Charge generation must know:

  • billing account,
  • product instance,
  • source order item,
  • charge type,
  • accepted price snapshot,
  • tax context,
  • billing period,
  • effective date.

Do not generate charges only because quote was accepted unless business supports pre-billing.


21. Charge and Product Inventory

Charge should usually reference product instance for recurring service.

Why:

  • customer modifies product,
  • customer disconnects product,
  • recurring billing stops,
  • invoice dispute references active product,
  • revenue by installed product,
  • reconciliation active product vs active charge.

Potential invariant:

Active recurring charge must reference an active or billable product instance unless it is a non-product account-level charge.

22. External Billing System Ownership

In many enterprise systems, invoice and payment are owned by external billing system.

Internal application may store:

  • billing request,
  • charge instruction,
  • billing activation event,
  • external charge ID,
  • external invoice ID,
  • invoice status snapshot,
  • payment status snapshot,
  • last sync time,
  • reconciliation result.

Be clear on ownership:

DataPossible owner
Accepted priceCPQ/quote service.
Billing instructionOrder/billing integration service.
Charge masterBilling system.
InvoiceBilling system.
PaymentFinance/payment system.
Billing accountBilling system or customer/account service.

Do not pretend internal system owns invoice if it only mirrors it.


23. Event Model

Events:

  • ChargePlanned
  • ChargeActivated
  • ChargeSuspended
  • ChargeTerminated
  • ChargeBilled
  • InvoiceGenerated
  • InvoiceIssued
  • InvoicePaid
  • InvoiceOverdue
  • CreditIssued
  • DebitIssued
  • BillingMismatchDetected

Event payload example:

{
  "eventId": "uuid",
  "eventType": "ChargeActivated",
  "eventVersion": 1,
  "occurredAt": "2026-07-12T10:00:00Z",
  "chargeId": "charge-id",
  "billingAccountId": "billing-account-id",
  "productInstanceId": "product-instance-id",
  "orderId": "order-id",
  "orderItemId": "order-item-id",
  "chargeType": "RECURRING",
  "amount": "90.00",
  "currency": "USD",
  "effectiveFrom": "2026-08-01",
  "correlationId": "corr-123"
}

Be careful with financial/PII data in events. Publish only what consumers need.


24. PostgreSQL Physical Design

Conceptual charge table:

create table charge (
  id uuid primary key,
  charge_number text,
  charge_type text not null,
  billing_account_id uuid not null,
  customer_id uuid,
  product_instance_id uuid,
  order_id uuid,
  order_item_id uuid,
  quote_id uuid,
  quote_item_id uuid,
  price_snapshot_id uuid,
  amount numeric(18, 4) not null,
  currency char(3) not null,
  status text not null,
  billing_period_start date,
  billing_period_end date,
  effective_from timestamptz,
  effective_to timestamptz,
  external_charge_id text,
  idempotency_key text,
  created_at timestamptz not null,
  updated_at timestamptz not null
);

Invoice table:

create table invoice (
  id uuid primary key,
  invoice_number text not null unique,
  billing_account_id uuid not null,
  customer_id uuid,
  invoice_date date not null,
  due_date date,
  billing_period_start date,
  billing_period_end date,
  currency char(3) not null,
  subtotal_amount numeric(18, 4) not null,
  tax_amount numeric(18, 4) not null default 0,
  discount_amount numeric(18, 4) not null default 0,
  total_amount numeric(18, 4) not null,
  amount_paid numeric(18, 4) not null default 0,
  balance_due numeric(18, 4) not null,
  status text not null,
  external_invoice_id text,
  created_at timestamptz not null,
  updated_at timestamptz not null
);

Invoice line:

create table invoice_line (
  id uuid primary key,
  invoice_id uuid not null references invoice(id),
  charge_id uuid,
  line_type text not null,
  description text,
  product_instance_id uuid,
  order_id uuid,
  order_item_id uuid,
  quantity numeric(18, 4),
  unit_amount numeric(18, 4),
  amount numeric(18, 4) not null,
  tax_amount numeric(18, 4) not null default 0,
  discount_amount numeric(18, 4) not null default 0,
  billing_period_start date,
  billing_period_end date,
  currency char(3) not null
);

Useful indexes:

create index idx_charge_billing_account_status
on charge (billing_account_id, status, updated_at);

create index idx_charge_product_instance
on charge (product_instance_id, status);

create index idx_charge_order_item
on charge (order_item_id);

create unique index uq_charge_idempotency
on charge (idempotency_key)
where idempotency_key is not null;

create index idx_invoice_billing_account_status
on invoice (billing_account_id, status, invoice_date desc);

create index idx_invoice_line_charge
on invoice_line (charge_id);

25. Java/JAX-RS Backend Implications

Billing/charge APIs should be command-oriented:

POST /charges
POST /charges/{id}/activate
POST /charges/{id}/terminate
POST /billing-triggers
GET /billing-accounts/{id}/charges
GET /billing-accounts/{id}/invoices
POST /billing-adjustments

Application service responsibilities:

  • validate billing account,
  • validate product/order linkage,
  • enforce idempotency,
  • compute or carry amount correctly,
  • preserve accepted price snapshot,
  • create charge/invoice references,
  • write audit,
  • publish events,
  • reconcile external billing system.

Do not let order service create invoice lines directly if billing system owns invoice generation.


26. MyBatis/JPA/JDBC Implications

MyBatis

Useful for:

  • billing reconciliation queries,
  • invoice line trace queries,
  • charge lookup by product instance,
  • billing account aging queries,
  • batch charge activation.

JPA

Be careful with:

  • money precision,
  • lazy loading invoice lines,
  • accidental update of issued invoice,
  • entity lifecycle callbacks generating financial side effects.

JDBC

Useful for deterministic financial/billing integration writes and reconciliation jobs.

General rule:

Financial data changes should be explicit commands with audit, not incidental entity mutation.


27. Reporting Impact

Charge/invoice model supports:

  • monthly recurring revenue,
  • one-time revenue,
  • usage revenue,
  • invoice aging,
  • unpaid balance,
  • overdue invoices,
  • revenue by product,
  • revenue by billing account,
  • charge activation lag,
  • billing error rate,
  • credit/debit adjustments,
  • tax reporting,
  • churn/disconnect revenue impact.

Define carefully:

  • booked vs billed vs collected revenue,
  • charge amount vs invoice amount,
  • net vs gross,
  • tax included vs excluded,
  • recurring vs one-time,
  • invoice date vs service period,
  • customer vs billing account revenue.

28. Reconciliation

Important reconciliations:

SourceTargetCheck
Fulfilled order itemChargeEvery billable fulfilled item has charge.
Active product instanceActive recurring chargeActive billable product is billed.
Terminated product instanceRecurring chargeCharge stopped at correct date.
ChargeInvoice lineBilled charges appear on invoice.
InvoicePaymentPayment status matches finance system.
Billing accountInvoiceInvoice assigned to correct payer.
Quote priceCharge amountAccepted price carried correctly.

Example query:

-- Active recurring product without active charge
select pi.id as product_instance_id
from product_instance pi
left join charge c
  on c.product_instance_id = pi.id
 and c.charge_type = 'RECURRING'
 and c.status = 'ACTIVE'
where pi.status = 'ACTIVE'
  and c.id is null;

Adjust table names internally.


29. Data Quality Checks

-- Invoice total mismatch
select i.id, i.invoice_number, i.total_amount, sum(il.amount + il.tax_amount - il.discount_amount) as line_total
from invoice i
join invoice_line il on il.invoice_id = i.id
group by i.id, i.invoice_number, i.total_amount
having i.total_amount <> sum(il.amount + il.tax_amount - il.discount_amount);

-- Charge without billing account
select id, charge_type, order_id, order_item_id
from charge
where billing_account_id is null;

-- One-time charge duplicate by idempotency
select idempotency_key, count(*)
from charge
where charge_type = 'ONE_TIME'
  and idempotency_key is not null
group by idempotency_key
having count(*) > 1;

30. Security and Privacy

Charge/invoice data can be sensitive:

  • customer billing information,
  • pricing,
  • discounts,
  • tax details,
  • payment references,
  • invoice documents,
  • billing address,
  • commercial terms.

Controls:

  • restrict access to invoice/charge APIs,
  • mask payment references,
  • avoid sensitive payload in events/logs,
  • encrypt document storage if needed,
  • audit invoice/adjustment access,
  • define retention,
  • handle legal hold.

31. Failure Modes

Failure modeSymptomLikely causePrevention
Duplicate chargeCustomer billed twiceRetry without idempotencyCharge idempotency key
Missing chargeFulfilled product not billedBilling trigger lostReconciliation active product vs charge
Wrong payerInvoice to wrong accountBilling account not carriedBilling account snapshot
Wrong amountCharge differs from accepted quoteRepricing or mapping errorPrice snapshot carry-over
Tax mismatchInvoice rejected/disputedWrong tax profile/addressTax profile snapshot/validation
Billing period errorOver/under billingInclusive/exclusive ambiguityPeriod semantics
Discount double appliedRevenue leakageDiscount applied at price and invoiceDiscount trace
Invoice total mismatchFinancial report errorLine/total inconsistencyDB checks/reconciliation
Payment status wrongCollection process wrongExternal sync issuePayment reconciliation
Silent correctionAudit gapManual update invoice/chargeCredit/debit/adjustment model

32. PR Review Checklist

When reviewing charge/invoice changes, ask:

  • Is this price, charge, invoice line, or payment?
  • What is the source order/order item/product instance?
  • What billing account owns the charge?
  • Is accepted price snapshot preserved?
  • Is charge type explicit?
  • Is billing period explicit?
  • Is charge idempotent?
  • Is tax profile/address clear?
  • Is discount applied once?
  • Is one-time charge protected from duplicate billing?
  • Is recurring charge lifecycle tied to product lifecycle?
  • Is invoice line traceable to charge?
  • Is payment status owned internally or externally?
  • Are financial corrections modelled as credit/debit?
  • Are events safe and versioned?
  • Are reconciliation queries possible?
  • Are money types and precision correct?
  • Are issued invoices immutable or correction-controlled?

33. Internal Verification Checklist

Verify these in the internal CSG/team context:

  • Whether charge, invoice, and payment are internally owned or external billing-owned.
  • Whether order service creates charges or only billing instructions.
  • Whether charge links to order item and product instance.
  • Whether accepted quote price snapshot is carried to charge.
  • Whether one-time/recurring/usage charge types are distinct.
  • Whether billing period semantics are documented.
  • Whether tax is calculated internally or externally.
  • Whether invoice line is stored internally or mirrored from billing system.
  • Whether invoice total reconciliation exists.
  • Whether payment status is synced and how often.
  • Whether credit/debit adjustments are modelled.
  • Whether billing account is copied from quote/order or recalculated.
  • Whether charge activation is triggered by fulfillment proof.
  • Whether duplicate charge idempotency exists.
  • Whether invoice/charge changes are audited.
  • Whether billing events are outbox-backed.
  • Whether incidents mention duplicate billing, missing charge, wrong tax, wrong payer, or invoice mismatch.

34. Summary

Charge and invoice modelling protects financial correctness.

A strong model must distinguish:

  • price,
  • charge,
  • invoice line,
  • payment,
  • credit/debit,
  • tax,
  • billing period,
  • billing account,
  • product/order source,
  • external billing ownership,
  • lifecycle state,
  • reconciliation evidence.

The key principle:

Do not treat invoice as just a formatted order. Billing needs its own traceable, auditable, period-aware, financially correct data model.

Lesson Recap

You just completed lesson 35 in build core. 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.