feat(inventory): implement inter-project material transfer backend

- Add ProjectTransfer database model and migration
- Implement project transfer service with immediate stock deduction on creation
- Support 100% full delivery receipt logic across destination warehouses
- Enforce canonical_specs_hash matching for cross-project stock merge
- Add RBAC guards and status lock on received transfers (409 Conflict)
- Register API router for transfers with on-the-way integration
This commit is contained in:
2026-09-23 22:30:31 +03:30
parent da883a28c0
commit b326cf64bf
9 changed files with 868 additions and 0 deletions
+33
View File
@@ -551,6 +551,35 @@ CREATE TABLE standard_conversions (
CONSTRAINT uq_standard_conversion UNIQUE (from_unit, to_unit)
);
-- Inter-project material transfers
CREATE TABLE project_transfers (
id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
from_project_id UUID NOT NULL REFERENCES projects(id) ON DELETE RESTRICT,
from_warehouse_id UUID NOT NULL REFERENCES warehouses(id) ON DELETE RESTRICT,
to_project_id UUID NOT NULL REFERENCES projects(id) ON DELETE RESTRICT,
material_id UUID NOT NULL REFERENCES materials(id) ON DELETE RESTRICT,
brand_id UUID REFERENCES brands(id) ON DELETE SET NULL,
unit_id INTEGER NOT NULL REFERENCES units(id) ON DELETE RESTRICT,
quantity NUMERIC(18,6) NOT NULL CHECK (quantity > 0),
specs JSONB NOT NULL DEFAULT '{}'::jsonb,
specs_hash TEXT NOT NULL DEFAULT 'default',
note TEXT,
status TEXT NOT NULL DEFAULT 'in_transit' CHECK (status IN ('in_transit', 'received', 'cancelled')),
out_transaction_id UUID REFERENCES inventory_transactions(id) ON DELETE SET NULL,
transfer_date TIMESTAMPTZ NOT NULL DEFAULT now(),
transferred_by TEXT,
received_at TIMESTAMPTZ,
received_by TEXT,
to_warehouse_id UUID REFERENCES warehouses(id) ON DELETE SET NULL,
receipt_allocations JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_project_transfers_from ON project_transfers(from_project_id, status);
CREATE INDEX idx_project_transfers_to ON project_transfers(to_project_id, status);
-- ============================================================================
-- UPDATED_AT TRIGGER (auto-set updated_at on row modification)
-- ============================================================================
@@ -579,6 +608,10 @@ CREATE TRIGGER trg_quote_attachments_updated_at
BEFORE UPDATE ON quote_attachments
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
CREATE TRIGGER trg_project_transfers_updated_at
BEFORE UPDATE ON project_transfers
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
-- ============================================================================
-- AUTOMATION TRIGGERS (v2.5 + v2.6)
-- ============================================================================