Screens

Every screen below was generated from this object by OODS Foundry 0.10.1, in React and Vue, and shows the calls that made it and its content hash. Each runs as its generated app runs, in this site's brand, Aquex, in the theme you choose, with the sample records this object's own file carries. A value no record gives shows as a neutral one, such as an empty value or "Not recorded"; OODS Foundry invents none.

React app · sample recordsMaturity: betasha256:cf7934100633…Open full size: Invoice detail screen generated by OODS Foundry in React

What design_compose reported for every screen here:

  • OODS-V121 Object 'Invoice' has maturity 'beta' — composed output may change.
The calls that made the Invoice detail apps, in React and Vue
3 calls, as the pipeline sent them
design_compose {
  "object": "Invoice",
  "context": "detail",
  "preferences": {
    "brand": "Aquex",
    "theme": "light"
  }
}

code_generate {
  "schemaRef": "compose-98b33491",
  "framework": "react",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}

code_generate {
  "schemaRef": "compose-98b33491",
  "framework": "vue",
  "profile": "build",
  "options": {
    "output": "application",
    "brand": "Aquex",
    "theme": "light",
    "payloadMode": "file"
  }
}

The React app's content hash: sha256:cf79341006331fe509c72fcfdd33524098062f0a029c6664c4c4875f824e6a81. Its src/ folder: App.tsx, GeneratedUI.tsx, app.css, charts/, main.tsx, oods-brand-aquex.css

The Vue app's content hash: sha256:f824c0c1f74b29f6dec3f284ecf9df32af8dbd04ede28fe38db2061ef135a5cf. Its src/ folder: App.vue, GeneratedUI.vue, app.css, charts/, main.ts, oods-brand-aquex.css

Fields

FieldTypeDescription
invoice_numberrequired string Human readable invoice identifier presented to customers.
statusrequired string Canonical invoice status after provider mapping.
provider_status string Original provider reported status or badge.
issued_atrequired datetime Timestamp when the invoice was finalized or posted.
due_at datetime Payment due timestamp derived from payment terms.
paid_at datetime Timestamp when full payment cleared.
total_minorrequired integer Total amount due expressed in minor currency units.
balance_minor integer Remaining amount outstanding in minor units.
currencyrequired string ISO 4217 currency for the invoice.
payment_terms string Payment term label describing when payment is expected.
collection_state string Dunning phase or retry program detail presented to success teams.
last_reminder_at datetime Timestamp of most recent payment reminder issued to customer.
aging_bucket_days integer Number of days outstanding grouped for aging reports.
attempt_count integer Number of automatic payment attempts made on this invoice (Stripe smart-retries attempt_count).
More

Increments on each retry in the dunning window. Source: docs.stripe.com/billing/revenue-recovery/smart-retries.

next_payment_attempt datetime When the next automatic payment retry is scheduled (Stripe smart-retries next_payment_attempt).
More

Defines the open end of the retry window — modeled on the Refundable.refundable_until datetime-window precedent. Absent/null when no further attempts are scheduled (retries exhausted → invoice goes uncollectible, mirroring the subscription `unpaid` state). Source: docs.stripe.com/billing/revenue-recovery/smart-retries.

memo string Internal finance note or customer visible memo.
refundable_until datetime Date when refund eligibility window ends for this record.
refund_policy_url string Link to customer facing refund or cancellation policy.
total_refunded_minor integer Cumulative amount refunded in minor currency units.
credit_memo_balance_minor integer Remaining credit memo balance that can be applied to invoices.
credit_memo_type string Category of credit memo tied to business justification.
last_refund_at datetime Timestamp when the most recent refund was issued.
requires_manager_approval boolean Indicates if finance manager approval is required before issuing refund.
notes string Internal commentary about refund actions or policy exceptions.
created_atrequired datetime Timestamp recording when the entity was first created.
updated_at datetime Timestamp for the most recent modification, when available.
last_eventrequired string Lifecycle event associated with the most recent timestamp mutation.
last_event_at datetime Timestamp for the lifecycle event captured in last_event.
invoice_idrequired string Primary identifier for the invoice inside the billing domain.
subscription_idrequired string Subscription identifier this invoice is associated with.
providerrequired string Source system providing invoice data.
provider_invoice_id string Native provider identifier retained for audit trails.
billing_contact_name string Customer billing contact receiving the invoice.
billing_contact_email email Email address for the billing contact.
tax_minor integer Tax amount collected on the invoice in minor currency units.
discount_minor integer Total discounts applied to the invoice in minor units.
subtotal_minor integer Subtotal before discounts and tax in minor units.
line_items InvoiceLineItem[] Normalized line items with quantity, amount_minor, and description fields.
attachments AssetReference[] Supporting documents or credit memos associated with the invoice.
portal_url string Link to the hosted invoice or customer billing portal.
dunning_step string Current dunning playbook step label (ex: reminder_1, reminder_final, collections).
More

The structured retry window (attempt_count + next_payment_attempt) is provided by the composed SaaSBillingPayable trait; this field is the human-readable step name.

payment_source string Payment method used or expected (card, ach, wire).

Traits

Each trait adds fields and behaviour. Every object with the trait gets the same.

Relationships

These arrows show declared relationships between object types. They don't join live records.

Relationships: Invoice2 object types and 1 declared associations. Arrows point from source to target. Labels state source-relative cardinality and the via field; they do not assert live referential integrity. Invoice to Subscription: Subscription, many-to-one, via subscription_id.Subscriptionmany-to-onevia subscription_idCanonical SaaS invoice object normalizing payment terms, status, and refund posture.InvoiceTraits: SaaSBillingPayable,SaaSBillingRefundable, Timestampable,MarkBarKey fields (6 of 42)invoice_id: string *invoice_number: string *subscription_id: string *provider: string *attachments: AssetReference[]billing_contact_email: emailCanonical subscription record composing lifecycle, billing, and cancellation semantics.SubscriptionTraits: Stateful, Cancellable,Timestampable, Billable, Archivable,MarkBarKey fields (6 of 37)subscription_id: string *plan_name: string *plan_code: stringamount: integer *cancel_at_period_end: boolean *currency: string *

The object file

The Invoice object definition in YAML: domains/saas-billing/objects/Invoice.object.yaml
object:
  name: Invoice
  version: 1.0.0
  domain: saas.billing
  description: Canonical SaaS invoice object normalizing payment terms, status, and refund posture.
  tags:
    - billing
    - invoice
    - finance

traits:
  - name: SaaSBillingPayable
    alias: InvoiceTerms
  - name: SaaSBillingRefundable
    alias: CreditWindow
  - name: lifecycle/Timestampable
    alias: AuditTrail
    parameters:
      recordedEvents:
        - created
        - posted
        - payment_initiated
        - payment_cleared
        - payment_failed
        - voided
        - written_off
      timezone: UTC
      allowNullUpdatedAt: true
  # s223-m01 (#2527 ruling 2): line items are money, so the chart plots major units in the invoice's currency
  # (amount_minor / 100, the y axis reading $12,000, £1,234 or €19), not minor units.
  - name: viz/MarkBar
    parameters:
      title: Invoice line item amounts
      description: Line-item amounts in the invoice's currency; line items with the same description are summed.
      chart:
        chartType: bar
        source: record-array
        dataField: line_items
        encodings:
          x: {field: description, title: Line item}
          y: {field: amount_minor, aggregate: sum, title: Amount}
        minorUnits: 100
        currencyField: currency
        # Copied from domains/saas-billing/examples/stripe.json invoice.line_items.
        sampleRows:
          - description: Scale plan
            quantity: 1
            amount_minor: 284000
            unit_amount_minor: 284000

schema:
  invoice_id:
    type: string
    required: true
    description: Primary identifier for the invoice inside the billing domain.
  subscription_id:
    type: string
    required: true
    description: Subscription identifier this invoice is associated with.
  provider:
    type: string
    required: true
    description: Source system providing invoice data.
  provider_invoice_id:
    type: string
    required: false
    description: Native provider identifier retained for audit trails.
  billing_contact_name:
    type: string
    required: false
    description: Customer billing contact receiving the invoice.
  billing_contact_email:
    type: email
    required: false
    description: Email address for the billing contact.
  tax_minor:
    type: integer
    required: false
    description: Tax amount collected on the invoice in minor currency units.
  discount_minor:
    type: integer
    required: false
    description: Total discounts applied to the invoice in minor units.
  subtotal_minor:
    type: integer
    required: false
    description: Subtotal before discounts and tax in minor units.
  line_items:
    type: InvoiceLineItem[]
    required: false
    description: Normalized line items with quantity, amount_minor, and description fields.
    default: []
  attachments:
    type: AssetReference[]
    required: false
    description: Supporting documents or credit memos associated with the invoice.
    default: []
  portal_url:
    type: string
    required: false
    description: Link to the hosted invoice or customer billing portal.
  dunning_step:
    type: string
    required: false
    description: >-
      Current dunning playbook step label (ex: reminder_1, reminder_final, collections).
      The structured retry window (attempt_count + next_payment_attempt) is provided by
      the composed SaaSBillingPayable trait; this field is the human-readable step name.
  payment_source:
    type: string
    required: false
    description: Payment method used or expected (card, ach, wire).

semantics:
  invoice_id:
    semantic_type: billing.invoice.id
    token_mapping: tokenMap(billing.invoice.id)
  subscription_id:
    semantic_type: billing.invoice.subscription_id
    token_mapping: tokenMap(billing.invoice.subscription_id)
  provider:
    semantic_type: billing.invoice.provider
    token_mapping: tokenMap(billing.invoice.provider)
  provider_invoice_id:
    semantic_type: billing.invoice.provider_id
    token_mapping: tokenMap(billing.invoice.provider_id)
  # The one-line summary under the invoice number in lists: who is billed.
  billing_contact_name:
    semantic_type: text.summary
    token_mapping: tokenMap(billing.invoice.billing_contact_name)
  billing_contact_email:
    semantic_type: billing.invoice.billing_contact_email
    token_mapping: tokenMap(billing.invoice.billing_contact_email)
  tax_minor:
    semantic_type: billing.invoice.tax_minor
    token_mapping: tokenMap(billing.invoice.tax_minor)
    ui_hints:
      component: CurrencyAmount
      currencyField: currency
      minorUnits: 100
  discount_minor:
    semantic_type: billing.invoice.discount_minor
    token_mapping: tokenMap(billing.invoice.discount_minor)
    ui_hints:
      component: CurrencyAmount
      currencyField: currency
      minorUnits: 100
  subtotal_minor:
    semantic_type: billing.invoice.subtotal_minor
    token_mapping: tokenMap(billing.invoice.subtotal_minor)
    ui_hints:
      component: CurrencyAmount
      currencyField: currency
      minorUnits: 100
  line_items:
    semantic_type: billing.invoice.line_items
    token_mapping: tokenMap(billing.invoice.line_items)
  attachments:
    semantic_type: billing.invoice.attachments
    token_mapping: tokenMap(billing.invoice.attachments)
  portal_url:
    semantic_type: billing.invoice.portal_url
    token_mapping: tokenMap(billing.invoice.portal_url)
  dunning_step:
    semantic_type: billing.invoice.dunning_step
    token_mapping: tokenMap(billing.invoice.dunning_step)
  payment_source:
    semantic_type: billing.invoice.payment_source
    token_mapping: tokenMap(billing.invoice.payment_source)

tokens:
  billing.invoice.id: "var(--cmp-text-strong)"
  billing.invoice.billing_contact_name: "var(--cmp-text-body-strong)"
  billing.invoice.payment_source: "var(--cmp-text-subtle)"
  billing.invoice.dunning_step: "var(--cmp-badge-text-warning)"

metadata:
  owners:
    - revenue-ops@oods.systems
    - finance@oods.systems
  maturity: beta
  references:
    - R13.5 Canonical Model: Subscription and Invoice
    - R4.5 SaaS Enum-to-Token Mapping Schema

# Authored type associations; no record join or referential-integrity claim.
relationships:
  - target: Subscription
    via: subscription_id
    cardinality: many-to-one
    label: Subscription

# Eight authored sample invoices for the sample subscriptions; each is billed to a sample Organization by name. Line
# items sum to the subtotal, the balance is what remains unpaid, and the last event is the latest recorded change (a
# refund is not a recorded event).
samples:
  - invoice_id: inv_2026_0142
    invoice_number: INV-2026-0142
    subscription_id: sub_northwind_business
    provider: Stripe
    provider_invoice_id: in_1RkT2nNw8aQ5bC01
    provider_status: paid
    billing_contact_name: Northwind Traders
    billing_contact_email: billing@northwind.example
    status: paid
    currency: USD
    payment_terms: due_upon_receipt
    line_items:
      - { description: Business plan, quantity: 1, unit_amount_minor: 14900, amount_minor: 14900 }
    subtotal_minor: 14900
    discount_minor: 0
    tax_minor: 0
    total_minor: 14900
    balance_minor: 0
    attempt_count: 1
    payment_source: card
    portal_url: https://pay.example/invoices/INV-2026-0142
    memo: Business plan, Sep 2 to Oct 2
    issued_at: '2026-09-02T15:00:00Z'
    due_at: '2026-09-02T15:00:00Z'
    paid_at: '2026-09-02T15:01:00Z'
    created_at: '2026-09-02T15:00:00Z'
    updated_at: '2026-09-02T15:01:00Z'
    last_event: payment_cleared
    last_event_at: '2026-09-02T15:01:00Z'
  - invoice_id: inv_2026_0118
    invoice_number: INV-2026-0118
    subscription_id: sub_marlow_starter
    provider: Stripe
    provider_invoice_id: in_1QwE8rMa2lYo9gV7
    provider_status: void
    billing_contact_name: Marlow Yoga
    billing_contact_email: studio@marlowyoga.example
    status: void
    currency: USD
    payment_terms: due_upon_receipt
    line_items:
      - { description: Starter plan, quantity: 1, unit_amount_minor: 1900, amount_minor: 1900 }
    subtotal_minor: 1900
    discount_minor: 0
    tax_minor: 0
    total_minor: 1900
    balance_minor: 0
    attempt_count: 0
    payment_source: card
    portal_url: https://pay.example/invoices/INV-2026-0118
    memo: Renewal issued before the cancellation took effect; voided
    issued_at: '2026-07-09T10:15:00Z'
    due_at: '2026-07-09T10:15:00Z'
    paid_at: null
    created_at: '2026-07-09T10:15:00Z'
    updated_at: '2026-07-09T10:20:00Z'
    last_event: voided
    last_event_at: '2026-07-09T10:20:00Z'
  - invoice_id: inv_2026_0155
    invoice_number: INV-2026-0155
    subscription_id: sub_tidewater_enterprise
    provider: Stripe
    provider_invoice_id: in_1SkV7cRx1nTd8qJ4
    provider_status: open
    billing_contact_name: Tidewater Co-op
    billing_contact_email: treasurer@tidewater.example
    status: processing
    currency: USD
    payment_terms: net_45
    line_items:
      - { description: Enterprise plan, quantity: 1, unit_amount_minor: 1080000, amount_minor: 1080000 }
      - { description: Premium support, quantity: 1, unit_amount_minor: 120000, amount_minor: 120000 }
    subtotal_minor: 1200000
    discount_minor: 0
    tax_minor: 0
    total_minor: 1200000
    balance_minor: 1200000
    attempt_count: 0
    payment_source: wire
    portal_url: https://pay.example/invoices/INV-2026-0155
    memo: Annual renewal, Oct 30 2026 to Oct 30 2027; bank transfer in progress
    issued_at: '2026-09-15T21:00:00Z'
    due_at: '2026-10-30T14:00:00Z'
    paid_at: null
    created_at: '2026-09-15T21:00:00Z'
    updated_at: '2026-09-28T21:00:00Z'
    last_event: payment_initiated
    last_event_at: '2026-09-28T21:00:00Z'
  - invoice_id: inv_2026_0139
    invoice_number: INV-2026-0139
    subscription_id: sub_kestrel_team
    provider: Stripe
    provider_invoice_id: in_1S8mQ2Kt5oPz4rN6
    provider_status: open
    billing_contact_name: Kestrel Print Co.
    billing_contact_email: hello@kestrelprint.example
    status: past_due
    currency: GBP
    payment_terms: due_upon_receipt
    line_items:
      - { description: Team plan, quantity: 1, unit_amount_minor: 4900, amount_minor: 4900 }
    subtotal_minor: 4900
    discount_minor: 0
    tax_minor: 0
    total_minor: 4900
    balance_minor: 4900
    collection_state: Automatic retries
    dunning_step: reminder_2
    last_reminder_at: '2026-09-24T09:00:00Z'
    aging_bucket_days: 27
    attempt_count: 3
    next_payment_attempt: '2026-10-01T10:00:00Z'
    payment_source: card
    portal_url: https://pay.example/invoices/INV-2026-0139
    memo: Team plan, Sep 3 to Oct 3; card declined three times
    issued_at: '2026-09-03T10:00:00Z'
    due_at: '2026-09-03T10:00:00Z'
    paid_at: null
    created_at: '2026-09-03T10:00:00Z'
    updated_at: '2026-09-24T09:00:00Z'
    last_event: payment_failed
    last_event_at: '2026-09-24T09:00:00Z'
  - invoice_id: inv_2026_0151
    invoice_number: INV-2026-0151
    subscription_id: sub_lindqvist_starter
    provider: Stripe
    provider_invoice_id: in_1SaP4dLq7uWe3hK2
    provider_status: paid
    billing_contact_name: Lindqvist Bakery
    billing_contact_email: finance@lindqvist.example
    status: paid
    currency: EUR
    payment_terms: due_upon_receipt
    line_items:
      - { description: Starter plan, quantity: 1, unit_amount_minor: 1900, amount_minor: 1900 }
    subtotal_minor: 1900
    discount_minor: 0
    tax_minor: 0
    total_minor: 1900
    balance_minor: 0
    attempt_count: 1
    payment_source: card
    portal_url: https://pay.example/invoices/INV-2026-0151
    memo: Starter plan, Sep 15 to Oct 15
    issued_at: '2026-09-15T08:00:00Z'
    due_at: '2026-09-15T08:00:00Z'
    paid_at: '2026-09-15T08:01:00Z'
    created_at: '2026-09-15T08:00:00Z'
    updated_at: '2026-09-15T08:01:00Z'
    last_event: payment_cleared
    last_event_at: '2026-09-15T08:01:00Z'
  - invoice_id: inv_2026_0133
    invoice_number: INV-2026-0133
    subscription_id: sub_lindqvist_starter
    provider: Stripe
    provider_invoice_id: in_1RzH6bJw3sXv2mE9
    provider_status: refunded
    billing_contact_name: Lindqvist Bakery
    billing_contact_email: finance@lindqvist.example
    status: refunded
    currency: EUR
    payment_terms: due_upon_receipt
    line_items:
      - { description: Starter plan, quantity: 1, unit_amount_minor: 1900, amount_minor: 1900 }
    subtotal_minor: 1900
    discount_minor: 0
    tax_minor: 0
    total_minor: 1900
    balance_minor: 0
    total_refunded_minor: 1900
    last_refund_at: '2026-08-19T11:30:00Z'
    refundable_until: '2026-09-15T08:00:00Z'
    notes: Duplicate of INV-2026-0132 for the same period; refunded in full.
    attempt_count: 1
    payment_source: card
    portal_url: https://pay.example/invoices/INV-2026-0133
    memo: Starter plan, Aug 15 to Sep 15 (charged twice)
    issued_at: '2026-08-16T08:00:00Z'
    due_at: '2026-08-16T08:00:00Z'
    paid_at: '2026-08-16T08:01:00Z'
    created_at: '2026-08-16T08:00:00Z'
    updated_at: '2026-08-19T11:30:00Z'
    last_event: payment_cleared
    last_event_at: '2026-08-16T08:01:00Z'
  - invoice_id: inv_2026_0149
    invoice_number: INV-2026-0149
    subscription_id: sub_summit_business
    provider: Stripe
    provider_invoice_id: in_1ScN9fTy6pRb1wL3
    provider_status: paid
    billing_contact_name: Summit Outfitters
    billing_contact_email: ap@summit.example
    status: paid
    currency: USD
    payment_terms: due_upon_receipt
    line_items:
      - { description: Business plan, quantity: 1, unit_amount_minor: 14900, amount_minor: 14900 }
    subtotal_minor: 14900
    discount_minor: 0
    tax_minor: 0
    total_minor: 14900
    balance_minor: 0
    attempt_count: 1
    payment_source: card
    portal_url: https://pay.example/invoices/INV-2026-0149
    memo: Business plan, Sep 7 to Oct 7
    issued_at: '2026-09-07T12:00:00Z'
    due_at: '2026-09-07T12:00:00Z'
    paid_at: '2026-09-07T12:01:00Z'
    created_at: '2026-09-07T12:00:00Z'
    updated_at: '2026-09-07T12:01:00Z'
    last_event: payment_cleared
    last_event_at: '2026-09-07T12:01:00Z'
  - invoice_id: inv_2026_0160
    invoice_number: INV-2026-0160
    subscription_id: sub_blueharbor_team
    provider: Stripe
    provider_invoice_id: in_1SmB3gUz8qNc5xP1
    provider_status: draft
    billing_contact_name: Blue Harbor Studio
    billing_contact_email: accounts@blueharbor.example
    status: draft
    currency: USD
    payment_terms: due_upon_receipt
    line_items:
      - { description: Team plan, quantity: 1, unit_amount_minor: 4900, amount_minor: 4900 }
    subtotal_minor: 4900
    discount_minor: 0
    tax_minor: 0
    total_minor: 4900
    balance_minor: 4900
    attempt_count: 0
    payment_source: card
    portal_url: https://pay.example/invoices/INV-2026-0160
    memo: First Team invoice; finalises when the trial ends on Oct 5
    issued_at: '2026-10-05T09:00:00Z'
    due_at: '2026-10-05T09:00:00Z'
    paid_at: null
    created_at: '2026-09-28T09:00:00Z'
    updated_at: '2026-09-28T09:00:00Z'
    last_event: created
    last_event_at: '2026-09-28T09:00:00Z'