002-inventory-movement-ledger.xml 3.04 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 movement ledger (P5.3 follow-up).

        Adds: inventory__stock_movement.

        The ledger is the source of truth: inventory__stock_balance is
        a materialised view whose `quantity` equals the SUM of every
        `delta` for the same (item_code, location_id). The framework
        writes the movement row and the balance update in the SAME
        database transaction so the two cannot drift.

        This changeset is in its own file (002-...) instead of being
        appended to 001-inventory-init.xml because Liquibase tracks
        applied changesets by (file, id, author) tuple — once an
        environment has run 001 it will not pick up new changesets
        added inside that file (unless you increment the runOnChange
        attribute, which is fragile). The convention this codebase
        follows: each new schema cut goes in a new XML file in the
        PBC's changelog directory, registered in master.xml.
    -->

    <changeSet id="inventory-movement-ledger-001" author="vibe_erp">
        <comment>Create inventory__stock_movement append-only ledger table</comment>
        <sql>
            CREATE TABLE inventory__stock_movement (
                id           uuid PRIMARY KEY,
                item_code    varchar(64)    NOT NULL,
                location_id  uuid           NOT NULL REFERENCES inventory__location(id),
                delta        numeric(18,4)  NOT NULL,
                reason       varchar(32)    NOT NULL,
                reference    varchar(128),
                occurred_at  timestamptz    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_movement_nonzero CHECK (delta &lt;&gt; 0)
            );
            CREATE INDEX inventory__stock_movement_item_idx
                ON inventory__stock_movement (item_code);
            CREATE INDEX inventory__stock_movement_loc_idx
                ON inventory__stock_movement (location_id);
            CREATE INDEX inventory__stock_movement_item_loc_idx
                ON inventory__stock_movement (item_code, location_id);
            CREATE INDEX inventory__stock_movement_reference_idx
                ON inventory__stock_movement (reference);
            CREATE INDEX inventory__stock_movement_occurred_idx
                ON inventory__stock_movement (occurred_at);
        </sql>
        <rollback>
            DROP TABLE inventory__stock_movement;
        </rollback>
    </changeSet>

</databaseChangeLog>