bmc_hub/migrations/181_fedex_shipments.sql

97 lines
3.8 KiB
MySQL
Raw Permalink Normal View History

-- Migration 181: FedEx shipments foundation (case-linked)
CREATE TABLE IF NOT EXISTS fedex_shipments (
id SERIAL PRIMARY KEY,
booking_ref VARCHAR(64) NOT NULL UNIQUE,
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,
service_type VARCHAR(32) NOT NULL,
shipment_status VARCHAR(32) NOT NULL DEFAULT 'draft',
pickup_window_start TIMESTAMP NOT NULL,
pickup_window_end TIMESTAMP NOT NULL,
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(64),
label_url TEXT,
cancel_reason TEXT,
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 fedex_shipments_service_type_check CHECK (service_type IN ('PRIORITY', 'ECONOMY')),
CONSTRAINT fedex_shipments_status_check CHECK (
shipment_status IN ('draft', 'submitted', 'booked', 'in_transit', 'delivered', 'cancelled', 'failed')
),
CONSTRAINT fedex_shipments_pickup_window_check CHECK (pickup_window_end > pickup_window_start)
);
CREATE TABLE IF NOT EXISTS fedex_shipment_packages (
id SERIAL PRIMARY KEY,
shipment_id INTEGER NOT NULL REFERENCES fedex_shipments(id) ON DELETE CASCADE,
weight_kg NUMERIC(10,3) NOT NULL,
length_cm NUMERIC(10,2) NOT NULL,
width_cm NUMERIC(10,2) NOT NULL,
height_cm NUMERIC(10,2) NOT NULL,
description VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fedex_package_weight_positive CHECK (weight_kg > 0),
CONSTRAINT fedex_package_length_positive CHECK (length_cm > 0),
CONSTRAINT fedex_package_width_positive CHECK (width_cm > 0),
CONSTRAINT fedex_package_height_positive CHECK (height_cm > 0)
);
CREATE TABLE IF NOT EXISTS fedex_tracking_events (
id SERIAL PRIMARY KEY,
shipment_id INTEGER NOT NULL REFERENCES fedex_shipments(id) ON DELETE CASCADE,
status VARCHAR(64) NOT NULL,
description TEXT,
event_timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
location_city VARCHAR(120),
location_country VARCHAR(2),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_fedex_shipments_case_id ON fedex_shipments(case_id);
CREATE INDEX IF NOT EXISTS idx_fedex_shipments_status ON fedex_shipments(shipment_status);
CREATE INDEX IF NOT EXISTS idx_fedex_shipments_tracking_number ON fedex_shipments(tracking_number);
CREATE INDEX IF NOT EXISTS idx_fedex_shipments_created_at ON fedex_shipments(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_fedex_packages_shipment_id ON fedex_shipment_packages(shipment_id);
CREATE INDEX IF NOT EXISTS idx_fedex_tracking_shipment_id ON fedex_tracking_events(shipment_id);
CREATE INDEX IF NOT EXISTS idx_fedex_tracking_event_timestamp ON fedex_tracking_events(event_timestamp DESC);
CREATE OR REPLACE FUNCTION update_fedex_shipments_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS fedex_shipments_updated_at_trigger ON fedex_shipments;
CREATE TRIGGER fedex_shipments_updated_at_trigger
BEFORE UPDATE ON fedex_shipments
FOR EACH ROW
EXECUTE FUNCTION update_fedex_shipments_updated_at();