-- Migration 1017: Shipmondo shipments linked to cases CREATE TABLE IF NOT EXISTS shipmondo_shipments ( id SERIAL PRIMARY KEY, booking_ref VARCHAR(64) NOT NULL UNIQUE, shipmondo_id VARCHAR(64), case_id INTEGER NOT NULL REFERENCES sag_sager(id) ON DELETE CASCADE, customer_id INTEGER REFERENCES customers(id) ON DELETE SET NULL, contact_id INTEGER REFERENCES contacts(id) ON DELETE SET NULL, product_code VARCHAR(80) NOT NULL, product_name VARCHAR(180), carrier_code VARCHAR(80), carrier_name VARCHAR(120), service_codes JSONB NOT NULL DEFAULT '[]'::jsonb, shipment_status VARCHAR(32) NOT NULL DEFAULT 'draft', own_agreement BOOLEAN NOT NULL DEFAULT FALSE, automatic_select_service_point BOOLEAN NOT NULL DEFAULT FALSE, recipient_name VARCHAR(150) NOT NULL, company_name VARCHAR(150), address_line1 VARCHAR(200) NOT NULL, address_line2 VARCHAR(200), postal_code VARCHAR(20) NOT NULL, city VARCHAR(120) NOT NULL, country_code VARCHAR(2) NOT NULL, phone VARCHAR(50), email VARCHAR(150), tracking_number VARCHAR(128), tracking_url TEXT, total_amount NUMERIC(12,2), currency VARCHAR(8), dry_run BOOLEAN NOT NULL DEFAULT FALSE, submitted_at TIMESTAMP, api_payload JSONB, api_response JSONB, created_by_user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL, updated_by_user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, deleted_at TIMESTAMP, CONSTRAINT shipmondo_shipments_status_check CHECK ( shipment_status IN ('draft', 'submitted', 'booked', 'in_transit', 'delivered', 'cancelled', 'failed') ) ); CREATE TABLE IF NOT EXISTS shipmondo_shipment_parcels ( id SERIAL PRIMARY KEY, shipment_id INTEGER NOT NULL REFERENCES shipmondo_shipments(id) ON DELETE CASCADE, weight_kg NUMERIC(10,3) NOT NULL, length_cm NUMERIC(10,2), width_cm NUMERIC(10,2), height_cm NUMERIC(10,2), description VARCHAR(255) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT shipmondo_parcel_weight_positive CHECK (weight_kg > 0) ); CREATE INDEX IF NOT EXISTS idx_shipmondo_shipments_case_id ON shipmondo_shipments(case_id); CREATE INDEX IF NOT EXISTS idx_shipmondo_shipments_status ON shipmondo_shipments(shipment_status); CREATE INDEX IF NOT EXISTS idx_shipmondo_shipments_created_at ON shipmondo_shipments(created_at DESC); CREATE INDEX IF NOT EXISTS idx_shipmondo_parcels_shipment_id ON shipmondo_shipment_parcels(shipment_id); CREATE OR REPLACE FUNCTION update_shipmondo_shipments_updated_at() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = CURRENT_TIMESTAMP; RETURN NEW; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS shipmondo_shipments_updated_at_trigger ON shipmondo_shipments; CREATE TRIGGER shipmondo_shipments_updated_at_trigger BEFORE UPDATE ON shipmondo_shipments FOR EACH ROW EXECUTE FUNCTION update_shipmondo_shipments_updated_at();