Proposed data model

Entity-relationship overview supporting every screen in the prototype. Money fields are stored as integer JPY (_jpy); balances are always derived, never stored. The ledger is append-only — corrections are new rows, not edits.

← Back to home
erDiagram LOCATION ||--o{ UNIT : "contains" LOCATION ||--o| BILLING_CYCLE : "uses" UNIT_TYPE ||--o{ UNIT : "typed as" UNIT ||--o{ RENTAL : "assigned to" CUSTOMER ||--o{ RENTAL : "holds" CUSTOMER ||--o{ PAYMENT_METHOD : "has" CUSTOMER ||--o{ INVOICE : "billed to" INVOICE ||--o{ INVOICE_LINE : "contains" INVOICE ||--o{ PAYMENT : "paid by" CUSTOMER ||--o{ PAYMENT : "makes" BILLING_CYCLE ||--o{ BILLING_RULE : "defines" BILLING_RULE ||--o{ RULE_EXECUTION : "logged as" CUSTOMER ||--o{ RULE_EXECUTION : "against" PROCESSING_RUN ||--o{ RULE_EXECUTION : "triggers" CUSTOMER ||--o{ COMMUNICATION : "notified" CUSTOMER ||--o{ DOCUMENT : "has files" USER ||--o{ AUDIT_LOG : "performs" LOCATION { uuid id PK string name string code "A, B, C ..." string address string phone enum status "active|inactive" uuid billing_cycle_id FK } UNIT_TYPE { uuid id PK string name "1.0 畳, Container, Parking 1" int standard_rate_jpy enum climate "ac|non_ac" int deposit_jpy int size_w_cm int size_l_cm int size_h_cm int sort_order } UNIT { uuid id PK uuid location_id FK uuid unit_type_id FK string unit_number "A-001" enum status "vacant|rented|maintenance" } CUSTOMER { uuid id PK string name_last string name_first string phone string email jsonb secondary_contact int day_to_bill "1..31" uuid billing_cycle_id FK "optional override" timestamp created_at } RENTAL { uuid id PK uuid customer_id FK uuid unit_id FK int contract_rent_jpy int discount_jpy date move_in_date date move_out_date "nullable" enum status "active|moved_out" } PAYMENT_METHOD { uuid id PK uuid customer_id FK string stripe_pm_id string brand "visa|mc|jcb|amex" string last4 string exp "MM/YYYY" bool is_default } INVOICE { uuid id PK uuid customer_id FK uuid rental_id FK "nullable for ad-hoc" date issue_date date due_date int subtotal_jpy int tax_jpy int total_jpy enum status "open|paid|void" enum kind "rent|late_fee|adjustment|other" string billing_period "YYYY-MM" } INVOICE_LINE { uuid id PK uuid invoice_id FK string description int amount_jpy int tax_jpy enum kind } PAYMENT { uuid id PK uuid customer_id FK uuid invoice_id FK "nullable for credit" int amount_jpy enum method "card|cash|bank|other" enum type "autopay|manual|offline|retry|refund" enum status "success|failed|pending|refunded|partial_refund" string failure_reason string stripe_pi_id string external_ref uuid created_by FK "user id or null=system" timestamp created_at } BILLING_CYCLE { uuid id PK string code "BC01" string description int rent_due_day "1..31" int billing_start_day } BILLING_RULE { uuid id PK uuid billing_cycle_id FK int day_offset "days past due" enum trigger "invoice_due|payment_failed|unpaid|still_unpaid" jsonb condition jsonb actions "create_invoice|add_charge|attempt_payment|restrict_access|mark_eviction" jsonb notices "email|late_fee|lockout|eviction|final" int sort_order } RULE_EXECUTION { uuid id PK uuid customer_id FK uuid rule_id FK uuid processing_run_id FK string billing_period "YYYY-MM" timestamp executed_at jsonb actions_log } PROCESSING_RUN { uuid id PK date run_date UK timestamp started_at timestamp completed_at enum status "running|completed|failed" jsonb summary } COMMUNICATION { uuid id PK uuid customer_id FK enum kind "email" string template string to_address timestamp sent_at string provider_ref } DOCUMENT { uuid id PK uuid customer_id FK string filename string blob_key string mime int size_bytes timestamp uploaded_at } USER { uuid id PK string email UK string name enum role "staff|manager|admin" bool mfa_enabled timestamp last_login_at } AUDIT_LOG { uuid id PK uuid actor_id FK string action string entity uuid entity_id jsonb diff string ip timestamp at }

Invariants

How the model maps to screens

Units & Customers joins UNIT · RENTAL · CUSTOMER · INVOICE for balance/status.
Customer Details aggregates every entity rooted at CUSTOMER.
Daily Processing writes to PROCESSING_RUN · RULE_EXECUTION · INVOICE · PAYMENT · COMMUNICATION.
Payments is a read over PAYMENT with customer/unit joins.
Billing Cycle Rules edits BILLING_CYCLE · BILLING_RULE.
Locations / Unit Types are configuration tables read by every screen.