Skip to main content

Billing Schema

Purpose

Lumie has two billing models with different data boundaries. Platform billing tracks Lumie charging academies for the SaaS product. Tuition billing tracks an academy charging guardians or students. The ERDs separate those models so schema changes do not accidentally mix platform control-plane records with tenant-owned tuition records.

Source Paths

PathRole
lumie-backend/app/src/main/resources/db/migration/public/V28__billing_platform_tables.sqlPlatform billing tables and the initial payment_transactions audit table
lumie-backend/app/src/main/resources/db/migration/public/V29__tuition_tenant_tables.sqlTuition billing tables, JSON columns, and tenant RLS
lumie-backend/app/src/main/resources/db/migration/public/V31__billing_add_missing_columns.sqlSyncs payment_transactions.type comments to the current enum names
lumie-backend/app/src/main/resources/db/migration/public/V33__billing_keys_add_customer_key.sqlToss customer key support
lumie-backend/app/src/main/resources/db/migration/public/V34__seed_plans.sqlInitial plan data
lumie-backend/app/src/main/resources/db/migration/public/V35__backfill_free_subscriptions.sqlDefault subscription backfill
lumie-backend/app/src/main/resources/db/migration/public/V37__subscription_scheduled_changes.sqlScheduled subscription changes
lumie-backend/app/src/main/resources/db/migration/public/V38__create_billing_operation_locks.sqlBilling operation lock table
lumie-backend/modules/billing/src/main/java/com/lumie/billing/domain/entity/PaymentTransaction.javaCurrent JPA mapping for audit rows
lumie-backend/modules/tuition/src/main/java/com/lumie/tuition/domain/entity/TuitionInvoice.javaCurrent JPA mapping for tuition invoices

Platform Billing ERD

Platform billing tables are cross-tenant Lumie records. They reference tenants, but they are not tenant RLS tables. Access control belongs to backend authorization and billing workflows.

Tenant Tuition ERD

Tuition tables are tenant-owned academy records. They must keep tenant_id, tenant-safe indexes, and RLS. Some relations are semantic rather than strict database FKs when hard coupling would cross module ownership boundaries.

Audit And Idempotency

payment_transactions is append-only audit data. Normal billing code should add audit rows for requests, responses, and webhooks rather than mutating history.

Verification

cd /path/to/Lumie
rg -n "total_amount|items|idempotency_key|order_id|pg_payload|billing_operation_locks" \
lumie-backend/app/src/main/resources/db/migration/public/V28__billing_platform_tables.sql \
lumie-backend/app/src/main/resources/db/migration/public/V29__tuition_tenant_tables.sql \
lumie-backend/app/src/main/resources/db/migration/public/V38__create_billing_operation_locks.sql

Expected success signal: tuition_invoices exposes items, total_amount, status, and idempotency_key; payment_transactions exposes pg_payload and idempotency_key; billing_operation_locks exposes its per-tenant lock state.

cd /path/to/Lumie
rg -n "SUBSCRIPTION_CHARGE|SUBSCRIPTION_REFUND|ALIMTALK_RECHARGE|BILLING_KEY_ISSUE|BILLING_KEY_REVOKE" \
lumie-backend/app/src/main/resources/db/migration/public/V31__billing_add_missing_columns.sql \
lumie-backend/modules/billing/src/main/java/com/lumie/billing/domain/vo/TransactionType.java

Expected success signal: the search shows the live contract drift explicitly. V31 mentions TAX_INVOICE_ISSUE, while the checked-in Java enum does not.

Change Checklist

  1. Decide whether the change is platform billing or tenant tuition.
  2. Use RLS only for tenant tuition tables, not platform subscription tables.
  3. Preserve idempotency for external payment calls.
  4. Add or update audit writes when a new PG interaction is introduced.
  5. Keep tenant tuition references tenant-safe even when using soft references.