001-inventory-init.xml 4.26 KB
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                                       https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.27.xsd">

    <!--
        pbc-inventory initial schema (P5.3).

        Owns: inventory__location, inventory__stock_balance.

        vibe_erp is single-tenant per instance — no tenant_id columns,
        no Row-Level Security policies.

        StockBalance does NOT have a foreign key to catalog__item, by
        design. The link to "is this item in the catalog?" is enforced
        at the application layer through the cross-PBC api.v1 facade
        (CatalogApi). A database FK across PBCs would couple their
        schemas at the storage level, defeating the bounded-context
        rule.

        StockBalance HAS a foreign key to inventory__location because
        the relationship is intra-PBC and the framework's "PBCs own
        their own tables" guarantee makes the FK safe.

        Conventions enforced for every business table in vibe_erp:
          • UUID primary key
          • Audit columns: created_at, created_by, updated_at, updated_by
          • Optimistic-locking version column
          • ext jsonb NOT NULL DEFAULT '{}' on aggregate roots only
            (Location has it; StockBalance doesn't — it's a fact, not
            a master record, and Tier 1 customisation belongs on the
            facts that hold the data, not the cells that count it)
          • GIN index on ext for fast custom-field queries
    -->

    <changeSet id="inventory-init-001" author="vibe_erp">
        <comment>Create inventory__location table</comment>
        <sql>
            CREATE TABLE inventory__location (
                id           uuid PRIMARY KEY,
                code         varchar(64)  NOT NULL,
                name         varchar(256) NOT NULL,
                type         varchar(16)  NOT NULL,
                active       boolean      NOT NULL DEFAULT true,
                ext          jsonb        NOT NULL DEFAULT '{}'::jsonb,
                created_at   timestamptz  NOT NULL,
                created_by   varchar(128) NOT NULL,
                updated_at   timestamptz  NOT NULL,
                updated_by   varchar(128) NOT NULL,
                version      bigint       NOT NULL DEFAULT 0
            );
            CREATE UNIQUE INDEX inventory__location_code_uk ON inventory__location (code);
            CREATE INDEX inventory__location_type_idx ON inventory__location (type);
            CREATE INDEX inventory__location_active_idx ON inventory__location (active);
            CREATE INDEX inventory__location_ext_gin ON inventory__location USING GIN (ext jsonb_path_ops);
        </sql>
        <rollback>
            DROP TABLE inventory__location;
        </rollback>
    </changeSet>

    <changeSet id="inventory-init-002" author="vibe_erp">
        <comment>Create inventory__stock_balance table (FK to inventory__location, no FK to catalog__item)</comment>
        <sql>
            CREATE TABLE inventory__stock_balance (
                id           uuid PRIMARY KEY,
                item_code    varchar(64)    NOT NULL,
                location_id  uuid           NOT NULL REFERENCES inventory__location(id),
                quantity     numeric(18,4)  NOT NULL,
                created_at   timestamptz    NOT NULL,
                created_by   varchar(128)   NOT NULL,
                updated_at   timestamptz    NOT NULL,
                updated_by   varchar(128)   NOT NULL,
                version      bigint         NOT NULL DEFAULT 0,
                CONSTRAINT inventory__stock_balance_nonneg CHECK (quantity &gt;= 0)
            );
            CREATE UNIQUE INDEX inventory__stock_balance_item_loc_uk
                ON inventory__stock_balance (item_code, location_id);
            CREATE INDEX inventory__stock_balance_item_idx ON inventory__stock_balance (item_code);
            CREATE INDEX inventory__stock_balance_loc_idx ON inventory__stock_balance (location_id);
        </sql>
        <rollback>
            DROP TABLE inventory__stock_balance;
        </rollback>
    </changeSet>

</databaseChangeLog>