-- FASE 2: DB Performance Optimizations -- Applies to: master DB (nexus_autoparts) and all tenant DBs -- ─── MASTER DB ───────────────────────────────── -- Index for parts name lookups (used by get_part_types, shop supplies) CREATE INDEX IF NOT EXISTS idx_parts_name_part ON parts(name_part); CREATE INDEX IF NOT EXISTS idx_parts_name_part_pattern ON parts(name_part text_pattern_ops); -- Partial index for warehouse_inventory stock lookups (already created in Fase 1, -- kept here for completeness on fresh installs) CREATE INDEX IF NOT EXISTS idx_wi_part_stock_positive ON warehouse_inventory(part_id) WHERE stock_quantity > 0; -- ─── TENANT DB (run on each tenant) ──────────── -- O(1) stock summary table with trigger-based updates CREATE TABLE IF NOT EXISTS inventory_stock_summary ( inventory_id INT PRIMARY KEY REFERENCES inventory(id) ON DELETE CASCADE, branch_id INT REFERENCES branches(id), stock INT NOT NULL DEFAULT 0, last_updated TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_iss_branch ON inventory_stock_summary(branch_id); -- Trigger function: recalculates stock for an item after every operation insert CREATE OR REPLACE FUNCTION update_stock_summary() RETURNS TRIGGER AS $$ BEGIN INSERT INTO inventory_stock_summary (inventory_id, branch_id, stock) SELECT i.id, i.branch_id, COALESCE(SUM(io.quantity), 0) FROM inventory i LEFT JOIN inventory_operations io ON io.inventory_id = i.id WHERE i.id = NEW.inventory_id GROUP BY i.id, i.branch_id ON CONFLICT (inventory_id) DO UPDATE SET stock = EXCLUDED.stock, branch_id = EXCLUDED.branch_id, last_updated = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS trg_update_stock_summary ON inventory_operations; CREATE TRIGGER trg_update_stock_summary AFTER INSERT ON inventory_operations FOR EACH ROW EXECUTE FUNCTION update_stock_summary(); -- Composite index for inventory_operations (used by stock + history queries) CREATE INDEX IF NOT EXISTS idx_inv_ops_inventory_branch_created ON inventory_operations(inventory_id, branch_id, created_at DESC); -- Initial population of summary table (idempotent) INSERT INTO inventory_stock_summary (inventory_id, branch_id, stock) SELECT i.id, i.branch_id, COALESCE(SUM(io.quantity), 0) FROM inventory i LEFT JOIN inventory_operations io ON io.inventory_id = i.id GROUP BY i.id, i.branch_id ON CONFLICT (inventory_id) DO UPDATE SET stock = EXCLUDED.stock, branch_id = EXCLUDED.branch_id, last_updated = NOW();