Skip to content

Database model

Every shop owns a full Solidus schema; this page shows the lean core plus each shop's custom tables. Update this page in the same PR that adds a migration.

Solidus core (shared shape, one database per shop)

erDiagram
    ORDER ||--o{ LINE_ITEM : contains
    LINE_ITEM }o--|| VARIANT : of
    VARIANT }o--|| PRODUCT : belongs_to
    PRODUCT }o--o{ TAXON : classified
    ORDER ||--o{ SHIPMENT : ships_as
    SHIPMENT }o--|| STOCK_LOCATION : from
    ORDER ||--o{ PAYMENT : paid_by
    PAYMENT }o--|| PAYMENT_METHOD : via
    ORDER }o--|| USER : placed_by
    ORDER }o--o| PROMOTION : discounted_by
    USER ||--o{ ADDRESS : has

Custom tables per shop

erDiagram
    USER ||--o{ PET : "wagwhisker: profiles"
    PET {
        string name
        date birthday "immutable, drives birthday baskets"
        string species
        jsonb feeding_data
    }
    PRODUCT ||--o{ PRICE_CHECK : "wagwhisker: best price crawls"
    PRICE_CHECK {
        string competitor
        string country
        datetime checked_at
    }
    USER ||--o{ ASSISTANT_CONVERSATION : "all shops: AI finder"
    ASSISTANT_CONVERSATION {
        text summary "feeds FAQ statistics"
    }
    NEWSLETTER_VOUCHER {
        string code
        datetime expires_at
    }
    DEMO_EVENT {
        string kind "showcase analytics"
    }

    USER ||--o| PILOT_PROFILE : "flugschule"
    PILOT_PROFILE {
        string licence_level
        date licence_since
        int logged_hours
    }
    COURSE ||--o{ COURSE_DAY : "flugschule: weather gated"
    COURSE_DAY ||--o{ PARTICIPATION : validated
    PARTICIPATION }o--|| USER : by
    PARTICIPATION {
        bool validated "attendance drives progression"
    }
    USER ||--o{ FLIGHT_LOG : "IGC uploads"
    FLIGHT_LOG {
        string igc_file
        float distance_km "B licence XC check"
    }
    LINE_ITEM {
        int deposit_pence "flugschule instalments"
    }

The flight school's licence engine derives progression from validated participations and flight logs (Uebungshang days unlock Hoehenfluege; 40 Hoehenfluege plus theory unlock the A licence test; the B licence checks a cross country flight of at least 10 km straight from the uploaded IGC file). State is always derived from evidence rows, never stored as a mutable flag.