Files
orion/app/modules/orders/docs/data-model.md
Samir Boulahtit f141cc4e6a docs: migrate module documentation to single source of truth
Move 39 documentation files from top-level docs/ into each module's
docs/ folder, accessible via symlinks from docs/modules/. Create
data-model.md files for 10 modules with full schema documentation.
Replace originals with redirect stubs. Remove empty guide stubs.

Modules migrated: tenancy, billing, loyalty, marketplace, orders,
messaging, cms, catalog, inventory, hosting, prospecting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 23:38:37 +01:00

12 KiB

Orders Data Model

Entity relationships and database schema for the orders module.

Entity Relationship Overview

Store 1──* Order 1──* OrderItem *──1 Product
                 │          │
                 │          └──? OrderItemException
                 │
                 └──* Invoice

Store 1──1 StoreInvoiceSettings
Store 1──* CustomerOrderStats *──1 Customer

Models

Order

Unified order model for all sales channels (direct store orders and marketplace orders). Stores customer and address data as snapshots at order time. All monetary amounts are stored as integer cents (e.g., €105.91 = 10591).

Field Type Constraints Description
id Integer PK Primary key
store_id Integer FK, not null, indexed Reference to store
customer_id Integer FK, not null, indexed Reference to customer
order_number String(100) not null, indexed Unique order identifier
channel String(50) default "direct", indexed Order source: "direct" or "letzshop"
external_order_id String(100) nullable, indexed Marketplace order ID
external_shipment_id String(100) nullable, indexed Marketplace shipment ID
external_order_number String(100) nullable Marketplace order number
external_data JSON nullable Raw marketplace data for debugging
status String(50) default "pending", indexed pending, processing, shipped, delivered, cancelled, refunded
subtotal_cents Integer nullable Subtotal in cents
tax_amount_cents Integer nullable Tax in cents
shipping_amount_cents Integer nullable Shipping cost in cents
discount_amount_cents Integer nullable Discount in cents
total_amount_cents Integer not null Total in cents
currency String(10) default "EUR" Currency code
vat_regime String(20) nullable domestic, oss, reverse_charge, origin, exempt
vat_rate Numeric(5,2) nullable VAT rate percentage
vat_rate_label String(100) nullable Human-readable VAT label
vat_destination_country String(2) nullable Destination country ISO code
customer_first_name String(100) not null Customer first name snapshot
customer_last_name String(100) not null Customer last name snapshot
customer_email String(255) not null Customer email snapshot
customer_phone String(50) nullable Customer phone
customer_locale String(10) nullable Customer locale (en, fr, de, lb)
ship_* Various not null Shipping address fields (first_name, last_name, company, address_line_1/2, city, postal_code, country_iso)
bill_* Various not null Billing address fields (same structure as shipping)
shipping_method String(100) nullable Shipping method
tracking_number String(100) nullable Tracking number
tracking_provider String(100) nullable Tracking provider
tracking_url String(500) nullable Full tracking URL
shipment_number String(100) nullable Carrier shipment number
shipping_carrier String(50) nullable Carrier code (greco, colissimo, etc.)
customer_notes Text nullable Notes from customer
internal_notes Text nullable Internal notes
order_date DateTime not null, tz-aware When customer placed order
confirmed_at DateTime nullable, tz-aware When order was confirmed
shipped_at DateTime nullable, tz-aware When order was shipped
delivered_at DateTime nullable, tz-aware When order was delivered
cancelled_at DateTime nullable, tz-aware When order was cancelled
created_at DateTime tz-aware Record creation time
updated_at DateTime tz-aware Record update time

Composite Indexes: (store_id, status), (store_id, channel), (store_id, order_date)

OrderItem

Individual line items in an order with product snapshot at order time.

Field Type Constraints Description
id Integer PK Primary key
order_id Integer FK, not null, indexed Reference to order
product_id Integer FK, not null Reference to product
product_name String(255) not null Product name snapshot
product_sku String(100) nullable Product SKU snapshot
gtin String(50) nullable EAN/UPC/ISBN code
gtin_type String(20) nullable GTIN type (ean13, upc, isbn, etc.)
quantity Integer not null Units ordered
unit_price_cents Integer not null Price per unit in cents
total_price_cents Integer not null Total price for line in cents
external_item_id String(100) nullable Marketplace inventory unit ID
external_variant_id String(100) nullable Marketplace variant ID
item_state String(50) nullable confirmed_available or confirmed_unavailable
inventory_reserved Boolean default False Whether inventory is reserved
inventory_fulfilled Boolean default False Whether inventory is fulfilled
shipped_quantity Integer default 0, not null Units shipped so far
needs_product_match Boolean default False, indexed Product not found by GTIN during import
created_at DateTime tz-aware Record creation time
updated_at DateTime tz-aware Record update time

OrderItemException

Tracks unmatched order items requiring admin/store resolution. Created when a marketplace order contains a GTIN that doesn't match any product in the store's catalog.

Field Type Constraints Description
id Integer PK Primary key
order_item_id Integer FK, unique, not null Reference to order item (cascade delete)
store_id Integer FK, not null, indexed Denormalized store reference
original_gtin String(50) nullable, indexed Original GTIN from marketplace
original_product_name String(500) nullable Original product name from marketplace
original_sku String(100) nullable Original SKU from marketplace
exception_type String(50) default "product_not_found", not null product_not_found, gtin_mismatch, duplicate_gtin
status String(50) default "pending", not null, indexed pending, resolved, ignored
resolved_product_id Integer FK, nullable Assigned product after resolution
resolved_at DateTime nullable, tz-aware When exception was resolved
resolved_by Integer FK, nullable Who resolved it
resolution_notes Text nullable Notes about the resolution
created_at DateTime tz-aware Record creation time
updated_at DateTime tz-aware Record update time

Composite Indexes: (store_id, status), (store_id, original_gtin)

Invoice

Invoice record with snapshots of seller/buyer details. Stores complete invoice data including snapshots at creation time for audit.

Field Type Constraints Description
id Integer PK Primary key
store_id Integer FK, not null, indexed Reference to store
order_id Integer FK, nullable, indexed Reference to order
invoice_number String(50) not null Invoice identifier
invoice_date DateTime not null, tz-aware Date of invoice
status String(20) default "draft", not null draft, issued, paid, cancelled
seller_details JSON not null Snapshot: {merchant_name, address, city, postal_code, country, vat_number}
buyer_details JSON not null Snapshot: {name, email, address, city, postal_code, country, vat_number}
line_items JSON not null Snapshot: [{description, quantity, unit_price_cents, total_cents, sku, ean}]
vat_regime String(20) default "domestic", not null domestic, oss, reverse_charge, origin, exempt
destination_country String(2) nullable Destination country ISO for OSS
vat_rate Numeric(5,2) not null VAT rate percentage
vat_rate_label String(50) nullable Human-readable VAT rate label
currency String(3) default "EUR", not null Currency code
subtotal_cents Integer not null Subtotal before VAT in cents
vat_amount_cents Integer not null VAT amount in cents
total_cents Integer not null Total after VAT in cents
payment_terms Text nullable Payment terms description
bank_details JSON nullable IBAN and BIC snapshot
footer_text Text nullable Custom footer text
pdf_generated_at DateTime nullable, tz-aware When PDF was generated
pdf_path String(500) nullable Path to stored PDF
notes Text nullable Internal notes
created_at DateTime tz-aware Record creation time
updated_at DateTime tz-aware Record update time

Unique Constraint: (store_id, invoice_number) Composite Indexes: (store_id, invoice_date), (store_id, status)

StoreInvoiceSettings

Per-store invoice configuration including merchant details, VAT number, invoice numbering, and payment information.

Field Type Constraints Description
id Integer PK Primary key
store_id Integer FK, unique, not null One-to-one with store
merchant_name String(255) not null Legal merchant name
merchant_address String(255) nullable Street address
merchant_city String(100) nullable City
merchant_postal_code String(20) nullable Postal code
merchant_country String(2) default "LU", not null ISO country code
vat_number String(50) nullable VAT number (e.g., "LU12345678")
is_vat_registered Boolean default True, not null VAT registration status
is_oss_registered Boolean default False, not null OSS registration status
oss_registration_country String(2) nullable OSS registration country
invoice_prefix String(20) default "INV", not null Invoice number prefix
invoice_next_number Integer default 1, not null Next invoice number counter
invoice_number_padding Integer default 5, not null Zero-padding width
payment_terms Text nullable Payment terms description
bank_name String(255) nullable Bank name
bank_iban String(50) nullable IBAN
bank_bic String(20) nullable BIC
footer_text Text nullable Custom footer text
default_vat_rate Numeric(5,2) default 17.00, not null Default VAT rate
created_at DateTime tz-aware Record creation time
updated_at DateTime tz-aware Record update time

CustomerOrderStats

Aggregated order statistics per customer per store. Separates order stats from customer profile data.

Field Type Constraints Description
id Integer PK Primary key
store_id Integer FK, not null, indexed Reference to store
customer_id Integer FK, not null, indexed Reference to customer
total_orders Integer default 0, not null Total number of orders
total_spent_cents Integer default 0, not null Total amount spent in cents
last_order_date DateTime nullable, tz-aware Date of most recent order
first_order_date DateTime nullable, tz-aware Date of first order
created_at DateTime tz-aware Record creation time
updated_at DateTime tz-aware Record update time

Unique Constraint: (store_id, customer_id)

Enums

InvoiceStatus

Value Description
draft Invoice created but not finalized
issued Invoice sent to customer
paid Payment received
cancelled Invoice cancelled

VATRegime

Value Description
domestic Same country as seller
oss EU cross-border with OSS registration
reverse_charge B2B with valid VAT number
origin Cross-border without OSS (use origin VAT)
exempt VAT exempt

Design Patterns

  • Money as cents: All monetary values stored as integer cents for precision
  • Snapshots: Customer, address, seller, and product data captured at order/invoice time
  • Marketplace support: External reference fields for marketplace-specific IDs and data
  • Timezone-aware dates: All DateTime fields include timezone info
  • Composite indexes: Optimized for common query patterns (store + status, store + date)