-- ============================================================================
-- Database Schema for SCM Microservice
-- Includes: Trans Schema, SCM Tables, and Sales Order Tables
-- ============================================================================

-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- Create Role if not exists
DO $$
BEGIN
  IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'trans_owner') THEN
    CREATE ROLE trans_owner WITH LOGIN PASSWORD 'trans_password'; -- Set a default password or leave it nologin
  END IF;
END
$$;

-- Create Schema
CREATE SCHEMA IF NOT EXISTS trans;
ALTER SCHEMA trans OWNER TO trans_owner;

-- ============================================================================
-- Core Reference Tables
-- ============================================================================

-- Catalogue Reference
CREATE TABLE IF NOT EXISTS trans.catalogue_ref (
    catalogue_id TEXT PRIMARY KEY,
    catalogue_code TEXT,
    catalogue_type TEXT NOT NULL,
    catalogue_name TEXT NOT NULL,
    sku TEXT,
    barcode_number TEXT,
    hsn_code TEXT,
    gst_rate NUMERIC(5,2),
    mrp NUMERIC(12,2),
    base_price NUMERIC(12,2),
    track_inventory BOOLEAN DEFAULT FALSE,
    batch_managed BOOLEAN DEFAULT FALSE,
    status TEXT NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    merchant_id TEXT[],
    pricing_levels JSON
);

CREATE INDEX IF NOT EXISTS idx_catalogue_ref_catalogue_code ON trans.catalogue_ref (catalogue_code);
CREATE INDEX IF NOT EXISTS idx_catalogue_ref_catalogue_type ON trans.catalogue_ref (catalogue_type);
CREATE INDEX IF NOT EXISTS idx_catalogue_ref_sku ON trans.catalogue_ref (sku);
CREATE INDEX IF NOT EXISTS idx_catalogue_ref_status ON trans.catalogue_ref (status);
CREATE INDEX IF NOT EXISTS idx_catalogue_ref_pricing_levels_currency ON trans.catalogue_ref USING GIN ((pricing_levels->>'currency'));

-- UOM Groups
CREATE TABLE IF NOT EXISTS trans.scm_uom_group_ref (
    uom_group_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    uom_group_code VARCHAR(50) UNIQUE,
    name VARCHAR(100) NOT NULL,
    base_unit VARCHAR(50) NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'inactive')),
    units JSON NOT NULL DEFAULT '[]',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_uom_group_code ON trans.scm_uom_group_ref (uom_group_code);
CREATE INDEX IF NOT EXISTS idx_uom_group_name ON trans.scm_uom_group_ref (name);

-- Stored Objects (Documents)
CREATE TABLE IF NOT EXISTS trans.stored_objects (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    tenant_id TEXT NOT NULL,
    domain TEXT NOT NULL,
    entity_id TEXT NOT NULL,
    bucket_name TEXT NOT NULL,
    object_key TEXT NOT NULL,
    category TEXT NOT NULL,
    file_name TEXT NOT NULL,
    mime_type TEXT NOT NULL,
    file_size BIGINT,
    checksum_sha256 TEXT,
    visibility VARCHAR(16) NOT NULL DEFAULT 'private',
    created_by TEXT NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP,
    legal_hold BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT uq_stored_object_active_key UNIQUE (tenant_id, domain, entity_id, object_key, deleted_at)
);

CREATE INDEX IF NOT EXISTS ix_stored_objects_active ON trans.stored_objects (tenant_id, domain, entity_id) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS ix_stored_objects_checksum ON trans.stored_objects (tenant_id, checksum_sha256) WHERE deleted_at IS NULL;

-- ============================================================================
-- SCM Purchase Orders
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.scm_po (
    po_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    po_no VARCHAR(50) UNIQUE NOT NULL,
    buyer_id UUID NOT NULL,
    buyer_type VARCHAR(20) NOT NULL,
    supplier_id UUID NOT NULL,
    supplier_type VARCHAR(20) NOT NULL,
    po_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    exp_delivery_dt DATE,
    currency VARCHAR(3) NOT NULL DEFAULT 'INR',
    total_amt NUMERIC(14, 2) NOT NULL,
    tax_amt NUMERIC(14, 2) DEFAULT 0,
    net_amt NUMERIC(14, 2) NOT NULL,
    status VARCHAR(20) NOT NULL,
    remarks TEXT,
    created_by VARCHAR(64) NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS trans.scm_po_item (
    po_item_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    po_id UUID NOT NULL REFERENCES trans.scm_po(po_id) ON DELETE CASCADE,
    catalogue_id UUID NOT NULL,
    sku VARCHAR(64) NOT NULL,
    batch_managed BOOLEAN,
    ord_qty NUMERIC(12, 3) NOT NULL,
    ord_uom_qty NUMERIC(12, 3) NOT NULL,
    rcvd_qty NUMERIC(12, 3) DEFAULT 0,
    invoiced_qty NUMERIC(12, 3) DEFAULT 0,
    returned_qty NUMERIC(12, 3) DEFAULT 0,
    dispatched_qty NUMERIC(12, 3) DEFAULT 0,
    rejected_qty NUMERIC(12, 3) DEFAULT 0,
    uom VARCHAR(10) NOT NULL,
    ord_uom VARCHAR(10) NOT NULL,
    unit_price NUMERIC(12, 2) NOT NULL,
    line_amt NUMERIC(14, 2) NOT NULL,
    tax_rate NUMERIC(5, 2) DEFAULT 0,
    tax_amt NUMERIC(12, 2) DEFAULT 0,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS trans.scm_po_status_log (
    log_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    po_id UUID NOT NULL REFERENCES trans.scm_po(po_id),
    status VARCHAR(20) NOT NULL,
    changed_by VARCHAR(64),
    changed_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    remarks TEXT
);

-- ============================================================================
-- SCM PO Returns
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.scm_po_return (
    po_return_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    po_return_no VARCHAR(40) UNIQUE NOT NULL,
    po_id UUID NOT NULL,
    supplier_id VARCHAR(64) NOT NULL,
    client_id VARCHAR(64) NOT NULL,
    warehouse_id VARCHAR(64),
    return_date TIMESTAMP NOT NULL,
    status VARCHAR(20) NOT NULL,
    reason_code VARCHAR(50),
    remarks TEXT,
    created_by VARCHAR(64),
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_po_return_po_id ON trans.scm_po_return(po_id);
CREATE INDEX IF NOT EXISTS idx_po_return_supplier_id ON trans.scm_po_return(supplier_id);
CREATE INDEX IF NOT EXISTS idx_po_return_client_id ON trans.scm_po_return(client_id);

CREATE TABLE IF NOT EXISTS trans.scm_po_return_item (
    po_return_item_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    po_return_id UUID NOT NULL REFERENCES trans.scm_po_return(po_return_id) ON DELETE CASCADE,
    po_item_id UUID NOT NULL,
    catalogue_id UUID NOT NULL,
    batch_no VARCHAR(50) NOT NULL,
    expiry_date TIMESTAMP,
    return_qty NUMERIC(12, 3) NOT NULL,
    uom VARCHAR(20) NOT NULL DEFAULT 'PCS',
    cost_price NUMERIC(12, 2) NOT NULL,
    return_value NUMERIC(14, 2) GENERATED ALWAYS AS (return_qty * cost_price) STORED,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_po_return_item_po_item_id ON trans.scm_po_return_item(po_item_id);

-- ============================================================================
-- SCM Goods Receipt Notes (GRN)
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.scm_grn (
    grn_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    grn_no VARCHAR(50) UNIQUE NOT NULL,
    po_id UUID REFERENCES trans.scm_po(po_id),
    shipment_id UUID,
    receiver_id VARCHAR(64),
    supplier_id UUID NOT NULL,
    received_by VARCHAR(64),
    transporter VARCHAR(64),
    recv_dt TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    wh_location VARCHAR(64),
    status VARCHAR(20) NOT NULL,
    total_qty NUMERIC(14, 3),
    remarks TEXT,
    created_by VARCHAR(64),
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS trans.scm_grn_item (
    grn_item_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    grn_id UUID NOT NULL REFERENCES trans.scm_grn(grn_id) ON DELETE CASCADE,
    po_item_id UUID REFERENCES trans.scm_po_item(po_item_id),
    catalogue_id UUID,
    sku VARCHAR(64) NOT NULL,
    recv_qty NUMERIC(12, 3) NOT NULL,
    acc_qty NUMERIC(12, 3) NOT NULL,
    rej_qty NUMERIC(12, 3) DEFAULT 0,
    uom VARCHAR(10) NOT NULL,
    batch_no VARCHAR(50),
    mfg_dt DATE,
    exp_dt DATE,
    qc_status VARCHAR(20) DEFAULT 'accepted',
    remarks TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS trans.scm_grn_issue (
    issue_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    grn_item_id UUID NOT NULL REFERENCES trans.scm_grn_item(grn_item_id),
    issue_type VARCHAR(50) NOT NULL,
    description TEXT,
    status VARCHAR(20) NOT NULL,
    created_by VARCHAR(64),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- ============================================================================
-- SCM Inventory / Stock
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.scm_stock_ledger (
    ledger_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    merchant_id VARCHAR(64) NOT NULL,
    warehouse_id VARCHAR(64) NOT NULL,
    catalogue_id VARCHAR(64),
    sku VARCHAR(64) NOT NULL,
    batch_no VARCHAR(50),
    txn_type VARCHAR(20) NOT NULL,
    qty NUMERIC(12, 3) NOT NULL,
    uom VARCHAR(20),
    ref_type VARCHAR(20) NOT NULL,
    ref_id UUID NOT NULL,
    ref_no VARCHAR(50),
    remarks TEXT,
    created_by VARCHAR(64) NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS trans.scm_stock (
    stock_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    merchant_id VARCHAR(64) NOT NULL,
    warehouse_id VARCHAR(64) NOT NULL,
    sku VARCHAR(64) NOT NULL,
    batch_no VARCHAR(50),
    catalogue_id VARCHAR(64),
    uom VARCHAR(20) DEFAULT 'PCS',
    qty_on_hand NUMERIC(12, 3) DEFAULT 0 CHECK (qty_on_hand >= 0),
    qty_reserved NUMERIC(12, 3) DEFAULT 0 CHECK (qty_reserved >= 0),
    qty_available NUMERIC(12, 3) DEFAULT 0 CHECK (qty_available >= 0),
    cost_price NUMERIC(12, 2),
    expiry_date DATE,
    ledger_id UUID,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT uq_scm_stock_sku_batch UNIQUE (merchant_id, warehouse_id, catalogue_id, batch_no)
);

-- Stock Adjustment (Master/Detail)
CREATE TABLE IF NOT EXISTS trans.scm_stock_adjustment_master (
    adjustment_master_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    adjustment_number VARCHAR(50) NOT NULL,
    merchant_id VARCHAR(64) NOT NULL,
    warehouse_id VARCHAR(64) NOT NULL,
    adjustment_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    description TEXT,
    additional_notes TEXT,
    status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'pending', 'approved', 'rejected', 'applied', 'cancelled')),
    total_items INTEGER DEFAULT 0,
    total_adjustment_value NUMERIC(15, 2) DEFAULT 0,
    requires_approval BOOLEAN DEFAULT TRUE,
    approval_threshold NUMERIC(15, 2),
    created_by VARCHAR(64) NOT NULL,
    approved_by VARCHAR(64),
    rejected_by VARCHAR(64),
    applied_by VARCHAR(64),
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    approved_at TIMESTAMP WITH TIME ZONE,
    rejected_at TIMESTAMP WITH TIME ZONE,
    applied_at TIMESTAMP WITH TIME ZONE,
    rejection_reason TEXT
);

CREATE TABLE IF NOT EXISTS trans.scm_stock_adjustment_details (
    adjustment_detail_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    adjustment_master_id UUID NOT NULL REFERENCES trans.scm_stock_adjustment_master(adjustment_master_id),
    sku VARCHAR(64) NOT NULL,
    batch_no VARCHAR(50),
    adj_type VARCHAR(20) NOT NULL CHECK (adj_type IN ('damage', 'expired', 'shrinkage', 'cycle_count')),
    qty NUMERIC(12, 3) NOT NULL CHECK (qty > 0),
    system_qty NUMERIC(12, 3) NOT NULL DEFAULT 0 CHECK (system_qty >= 0),
    direction VARCHAR(10) NOT NULL DEFAULT 'OUT' CHECK (direction IN ('IN', 'OUT')),
    reason TEXT NOT NULL,
    unit_cost NUMERIC(12, 4),
    adjustment_value NUMERIC(15, 2),
    line_status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (line_status IN ('pending', 'approved', 'rejected', 'applied')),
    ledger_id UUID,
    remarks TEXT,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Stock Take (Master/Detail)
CREATE TABLE IF NOT EXISTS trans.scm_stock_take_master (
    stock_take_master_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    stock_take_number VARCHAR(50) NOT NULL,
    merchant_id VARCHAR(64) NOT NULL,
    warehouse_id VARCHAR(64) NOT NULL,
    stock_take_date TIMESTAMP WITH TIME ZONE NOT NULL,
    description TEXT,
    additional_notes TEXT,
    status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'in_progress', 'completed', 'submitted', 'approved', 'rejected', 'cancelled')),
    total_items INTEGER DEFAULT 0,
    total_variance_value NUMERIC(15, 2) DEFAULT 0,
    created_by VARCHAR(64) NOT NULL,
    approved_by VARCHAR(64),
    rejected_by VARCHAR(64),
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    approved_at TIMESTAMP WITH TIME ZONE,
    rejected_at TIMESTAMP WITH TIME ZONE,
    rejection_reason TEXT
);

CREATE TABLE IF NOT EXISTS trans.scm_stock_take_details (
    stock_take_detail_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    stock_take_master_id UUID NOT NULL REFERENCES trans.scm_stock_take_master(stock_take_master_id),
    sku VARCHAR(64) NOT NULL,
    batch_no VARCHAR(50),
    system_qty NUMERIC(12, 3) NOT NULL CHECK (system_qty >= 0),
    physical_qty NUMERIC(12, 3) NOT NULL CHECK (physical_qty >= 0),
    variance_qty NUMERIC(12, 3) NOT NULL,
    unit_cost NUMERIC(12, 4),
    variance_value NUMERIC(15, 2),
    line_status VARCHAR(20) NOT NULL DEFAULT 'counted' CHECK (line_status IN ('counted', 'verified', 'adjusted')),
    adjustment_id UUID,
    remarks TEXT,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS trans.scm_stock_take_status_log (
    log_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    stock_take_master_id UUID NOT NULL REFERENCES trans.scm_stock_take_master(stock_take_master_id) ON DELETE CASCADE,
    status VARCHAR(50) NOT NULL,
    changed_by VARCHAR(255),
    changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    remarks TEXT
);

-- ============================================================================
-- Trade Relationships
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.scm_trade_relationship (
    relationship_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    from_merchant_id UUID NOT NULL,
    to_merchant_id UUID NOT NULL,
    relationship_type VARCHAR(30) NOT NULL DEFAULT 'procurement',
    status VARCHAR(20) NOT NULL DEFAULT 'draft',
    valid_from DATE NOT NULL DEFAULT CURRENT_DATE,
    valid_to DATE,
    credit_allowed BOOLEAN DEFAULT FALSE,
    credit_limit NUMERIC(14, 2),
    payment_terms VARCHAR(50),
    price_list_id VARCHAR(50),
    allowed_regions TEXT[],
    allowed_categories TEXT[],
    created_by VARCHAR(64),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT chk_different_merchants CHECK (from_merchant_id != to_merchant_id),
    CONSTRAINT chk_validity_range CHECK (valid_to IS NULL OR valid_to >= valid_from),
    CONSTRAINT chk_credit_configuration CHECK (credit_allowed = false OR (credit_allowed = true AND credit_limit IS NOT NULL AND credit_limit > 0))
);

CREATE UNIQUE INDEX IF NOT EXISTS idx_unique_relationship ON trans.scm_trade_relationship (from_merchant_id, to_merchant_id);
CREATE INDEX IF NOT EXISTS idx_trade_from_merchant ON trans.scm_trade_relationship (from_merchant_id);
CREATE INDEX IF NOT EXISTS idx_trade_to_merchant ON trans.scm_trade_relationship (to_merchant_id);

-- ============================================================================
-- Trade Schemes
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.trade_schemes (
    scheme_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    scheme_code VARCHAR(50) UNIQUE NOT NULL,
    scheme_name VARCHAR(200) NOT NULL,
    description TEXT,
    scheme_type VARCHAR(20) NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'DRAFT',
    applicable_level VARCHAR(20) NOT NULL,
    merchant_id UUID,
    valid_from DATE NOT NULL,
    valid_to DATE NOT NULL,
    settlement_type VARCHAR(20) NOT NULL,
    settlement_frequency VARCHAR(20) NOT NULL,
    inherit_to_children BOOLEAN DEFAULT TRUE,
    allow_child_override BOOLEAN DEFAULT TRUE,
    allow_better_only BOOLEAN DEFAULT TRUE,
    currency VARCHAR(3) DEFAULT 'INR',
    created_by VARCHAR(100),
    approved_by VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    approved_at TIMESTAMP,
    version INTEGER DEFAULT 1
);

CREATE INDEX IF NOT EXISTS idx_trade_schemes_type_status ON trans.trade_schemes (scheme_type, status);
CREATE INDEX IF NOT EXISTS idx_trade_schemes_validity ON trans.trade_schemes (valid_from, valid_to);

CREATE TABLE IF NOT EXISTS trans.trade_scheme_conditions (
    condition_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    scheme_id UUID NOT NULL REFERENCES trans.trade_schemes(scheme_id),
    min_quantity NUMERIC(15, 3),
    max_quantity NUMERIC(15, 3),
    qualifying_sku VARCHAR(50),
    min_order_value NUMERIC(15, 2),
    max_order_value NUMERIC(15, 2),
    sku_list JSON,
    category_list JSON,
    brand_list JSON,
    excluded_skus JSON,
    excluded_categories JSON,
    channel VARCHAR(20),
    aggregate_basis VARCHAR(20),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS trans.trade_scheme_benefits (
    benefit_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    scheme_id UUID NOT NULL REFERENCES trans.trade_schemes(scheme_id),
    discount_type VARCHAR(20),
    discount_percentage NUMERIC(5, 2),
    discount_amount NUMERIC(15, 2),
    free_sku VARCHAR(50),
    free_quantity NUMERIC(15, 3),
    rebate_type VARCHAR(20),
    rebate_percentage NUMERIC(5, 2),
    rebate_amount NUMERIC(15, 2),
    apply_on VARCHAR(20) DEFAULT 'TOTAL',
    max_benefit_amount NUMERIC(15, 2),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS trans.trade_scheme_accruals (
    accrual_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    scheme_id UUID NOT NULL REFERENCES trans.trade_schemes(scheme_id),
    merchant_id UUID NOT NULL,
    invoice_id VARCHAR(50),
    invoice_date DATE,
    accrual_amount NUMERIC(15, 2) NOT NULL,
    currency VARCHAR(3) DEFAULT 'INR',
    settlement_period VARCHAR(20),
    status VARCHAR(20) DEFAULT 'PENDING',
    credit_note_id VARCHAR(50),
    settled_at TIMESTAMP,
    settled_amount NUMERIC(15, 2),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_accruals_scheme_merchant ON trans.trade_scheme_accruals (scheme_id, merchant_id);

CREATE TABLE IF NOT EXISTS trans.trade_scheme_applications (
    application_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    scheme_id UUID NOT NULL REFERENCES trans.trade_schemes(scheme_id),
    merchant_id UUID NOT NULL,
    invoice_id UUID NOT NULL,
    applied_amount NUMERIC(15, 2) NOT NULL,
    benefit_type VARCHAR(20),
    status VARCHAR(20) DEFAULT 'APPLIED',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_applications_invoice ON trans.trade_scheme_applications (invoice_id);

-- ============================================================================
-- Trade Shipment (Sales)
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.scm_trade_shipment (
    shipment_id     UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    shipment_no     VARCHAR(40) UNIQUE NOT NULL,
    order_id        UUID NOT NULL REFERENCES trans.scm_po(po_id),
    supplier_id     UUID NOT NULL,
    client_id       UUID NOT NULL,
    warehouse_id    UUID NOT NULL,
    status          VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'shipped', 'closed')),
    shipment_date   DATE NOT NULL,
    transporter     VARCHAR(100),
    lr_no           VARCHAR(50),
    vehicle_no      VARCHAR(20),
    created_by      VARCHAR(64),
    created_at      TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    total_amt       NUMERIC(14, 2) NOT NULL DEFAULT 0.00,
    tax_amt         NUMERIC(14, 2) NOT NULL DEFAULT 0.00,
    net_amt         NUMERIC(14, 2) NOT NULL DEFAULT 0.00
);

CREATE INDEX IF NOT EXISTS idx_trade_shipment_order_id ON trans.scm_trade_shipment(order_id);
CREATE INDEX IF NOT EXISTS idx_trade_shipment_supplier_id ON trans.scm_trade_shipment(supplier_id);
CREATE INDEX IF NOT EXISTS idx_trade_shipment_client_id ON trans.scm_trade_shipment(client_id);
CREATE INDEX IF NOT EXISTS idx_trade_shipment_date ON trans.scm_trade_shipment(shipment_date);
CREATE INDEX IF NOT EXISTS idx_trade_shipment_status ON trans.scm_trade_shipment(status);

CREATE TABLE IF NOT EXISTS trans.scm_trade_shipment_item (
    item_id         UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    shipment_id     UUID NOT NULL REFERENCES trans.scm_trade_shipment(shipment_id) ON DELETE CASCADE,
    po_item_id      UUID NOT NULL REFERENCES trans.scm_po_item(po_item_id),
    sku             VARCHAR(64) NOT NULL,
    batch_no        VARCHAR(50),
    ordered_qty     NUMERIC(12,3) NOT NULL,
    shipped_qty     NUMERIC(12,3) NOT NULL,
    balance_qty     NUMERIC(12,3) NOT NULL,
    created_at      TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    catalogue_id    UUID,
    exp_dt          DATE,
    unit_price      NUMERIC(14, 2) NOT NULL,
    line_amt        NUMERIC(14, 2) NOT NULL,
    tax_amt         NUMERIC(14, 2),
    tax_rate        NUMERIC(5, 2),
    CONSTRAINT chk_trade_shipment_item_qty CHECK (
        shipped_qty >= 0 AND 
        ordered_qty >= 0 AND 
        balance_qty >= 0 AND
        shipped_qty <= ordered_qty
    )
);

CREATE INDEX IF NOT EXISTS idx_trade_shipment_item_shipment_id ON trans.scm_trade_shipment_item(shipment_id);
CREATE INDEX IF NOT EXISTS idx_trade_shipment_item_po_item_id ON trans.scm_trade_shipment_item(po_item_id);
CREATE INDEX IF NOT EXISTS idx_trade_shipment_item_sku ON trans.scm_trade_shipment_item(sku);

-- ============================================================================
-- Trade Invoices
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.scm_invoice (
    invoice_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    invoice_no VARCHAR(50) UNIQUE NOT NULL,
    po_id UUID NOT NULL,
    supplier_id UUID NOT NULL,
    buyer_id UUID NOT NULL,
    invoice_date DATE NOT NULL,
    payment_terms VARCHAR(30),
    due_date DATE,
    currency VARCHAR(3) NOT NULL DEFAULT 'INR',
    subtotal_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    discount_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    taxable_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    cgst_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    sgst_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    igst_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    total_tax_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    grand_total_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    status VARCHAR(30) NOT NULL DEFAULT 'draft',
    reverse_charge BOOLEAN NOT NULL DEFAULT FALSE,
    remarks TEXT,
    freight_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    packing_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    other_charges_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    round_off_amt NUMERIC(14, 2) NOT NULL DEFAULT 0,
    created_by VARCHAR(64),
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_scm_invoice_supplier_id ON trans.scm_invoice(supplier_id);
CREATE INDEX IF NOT EXISTS idx_scm_invoice_buyer_id ON trans.scm_invoice(buyer_id);
CREATE INDEX IF NOT EXISTS idx_scm_invoice_po_id ON trans.scm_invoice(po_id);
CREATE INDEX IF NOT EXISTS idx_scm_invoice_status ON trans.scm_invoice(status);
CREATE INDEX IF NOT EXISTS idx_scm_invoice_date ON trans.scm_invoice(invoice_date);

CREATE TABLE IF NOT EXISTS trans.scm_invoice_item (
    invoice_item_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    invoice_id UUID NOT NULL REFERENCES trans.scm_invoice(invoice_id) ON DELETE CASCADE,
    po_item_id UUID NOT NULL,
    catalogue_id UUID NOT NULL,
    sku VARCHAR(64) NOT NULL,
    hsn_code VARCHAR(10),
    invoice_qty NUMERIC(12, 3) NOT NULL,
    unit_price NUMERIC(12, 2) NOT NULL,
    discount_pct NUMERIC(5, 2),
    discount_amt NUMERIC(12, 2),
    tax_rate NUMERIC(5, 2),
    tax_amt NUMERIC(12, 2),
    line_total NUMERIC(14, 2) NOT NULL
);

CREATE INDEX IF NOT EXISTS idx_scm_invoice_item_invoice_id ON trans.scm_invoice_item(invoice_id);
CREATE INDEX IF NOT EXISTS idx_scm_invoice_item_po_item_id ON trans.scm_invoice_item(po_item_id);

CREATE TABLE IF NOT EXISTS trans.scm_invoice_status_log (
    log_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    invoice_id UUID NOT NULL REFERENCES trans.scm_invoice(invoice_id) ON DELETE CASCADE,
    action VARCHAR(20),
    from_status VARCHAR(20),
    to_status VARCHAR(20),
    remarks TEXT,
    performed_by VARCHAR(64),
    performed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- ============================================================================
-- Credit/Debit Notes (Invoice Adjustments)
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.scm_invoice_adjustment_note (
    note_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    note_no VARCHAR(50) UNIQUE NOT NULL,
    invoice_id UUID NOT NULL,
    supplier_id UUID NOT NULL,
    buyer_id UUID NOT NULL,
    category_code VARCHAR(30) NOT NULL,
    reason_code VARCHAR(50) NOT NULL,
    note_type VARCHAR(10) NOT NULL,
    note_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    original_amount NUMERIC(14, 2),
    revised_amount NUMERIC(14, 2),
    adjustment_amount NUMERIC(14, 2),
    taxable_amount NUMERIC(14, 2),
    original_tax_rate NUMERIC(5, 2),
    correct_tax_rate NUMERIC(5, 2),
    tax_adjustment_amt NUMERIC(14, 2),
    description TEXT NOT NULL,
    remarks TEXT,
    status VARCHAR(20) NOT NULL DEFAULT 'draft',
    created_by VARCHAR(64),
    created_by_username VARCHAR(64),
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_by VARCHAR(64),
    updated_by_username VARCHAR(64),
    submitted_by VARCHAR(64),
    submitted_at TIMESTAMP WITH TIME ZONE,
    approved_by VARCHAR(64),
    approved_at TIMESTAMP WITH TIME ZONE,
    rejected_by VARCHAR(64),
    rejected_at TIMESTAMP WITH TIME ZONE,
    applied_by VARCHAR(64),
    applied_at TIMESTAMP WITH TIME ZONE
);

CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_invoice_id ON trans.scm_invoice_adjustment_note(invoice_id);
CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_supplier_id ON trans.scm_invoice_adjustment_note(supplier_id);
CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_buyer_id ON trans.scm_invoice_adjustment_note(buyer_id);

CREATE TABLE IF NOT EXISTS trans.scm_invoice_adjustment_status_log (
    log_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    note_id UUID NOT NULL REFERENCES trans.scm_invoice_adjustment_note(note_id) ON DELETE CASCADE,
    action VARCHAR(20),
    from_status VARCHAR(20),
    to_status VARCHAR(20),
    remarks TEXT,
    performed_by VARCHAR(64),
    performed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- ============================================================================
-- Spa Partner Orders
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.spa_partner_orders (
    order_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    order_number VARCHAR(50) UNIQUE NOT NULL,
    partner_id VARCHAR(50) NOT NULL,
    merchant_id VARCHAR(50) NOT NULL,
    order_status VARCHAR(30) NOT NULL,
    total_amount NUMERIC(12, 2) NOT NULL,
    tax_amount NUMERIC(12, 2),
    discount_amount NUMERIC(12, 2),
    net_amount NUMERIC(12, 2),
    payment_status VARCHAR(30),
    payment_mode VARCHAR(30),
    delivery_address TEXT,
    city VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS trans.spa_partner_order_items (
    id SERIAL PRIMARY KEY,
    order_id UUID NOT NULL REFERENCES trans.spa_partner_orders(order_id),
    product_id VARCHAR(50) NOT NULL,
    product_name VARCHAR(200),
    quantity INTEGER NOT NULL,
    unit_price NUMERIC(10, 2) NOT NULL,
    tax_percent NUMERIC(5, 2),
    total_price NUMERIC(12, 2)
);

-- ============================================================================
-- Trade Returns
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.scm_return (
    return_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    return_no VARCHAR(50) UNIQUE NOT NULL,
    return_type VARCHAR(20) NOT NULL CHECK (return_type IN ('PURCHASE', 'SALES')),
    status VARCHAR(20) NOT NULL DEFAULT 'DRAFT' CHECK (status IN ('DRAFT', 'SUBMITTED', 'APPROVED', 'COMPLETED', 'REJECTED')),
    invoice_id UUID NOT NULL,
    invoice_no VARCHAR(50) NOT NULL,
    buyer_id VARCHAR(64) NOT NULL,
    buyer_name VARCHAR(200) NOT NULL,
    supplier_id VARCHAR(64) NOT NULL,
    supplier_name VARCHAR(200) NOT NULL,
    reason_code VARCHAR(50) NOT NULL CHECK (reason_code IN ('DAMAGED_GOODS', 'EXPIRED_STOCK', 'QUALITY_ISSUE', 'WRONG_ITEM', 'EXCESS_STOCK', 'DEFECTIVE', 'RECALL', 'OTHER')),
    remarks TEXT,
    dispatch_date TIMESTAMP WITH TIME ZONE,
    dispatch_reference VARCHAR(100),
    received_date TIMESTAMP WITH TIME ZONE,
    received_by VARCHAR(100),
    qc_completed_date TIMESTAMP WITH TIME ZONE,
    qc_performed_by VARCHAR(100),
    created_by VARCHAR(64) NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_by VARCHAR(64),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_scm_return_invoice_id ON trans.scm_return(invoice_id);
CREATE INDEX IF NOT EXISTS idx_scm_return_buyer_id ON trans.scm_return(buyer_id);
CREATE INDEX IF NOT EXISTS idx_scm_return_supplier_id ON trans.scm_return(supplier_id);
CREATE INDEX IF NOT EXISTS idx_scm_return_status ON trans.scm_return(status);

CREATE TABLE IF NOT EXISTS trans.scm_return_item (
    return_item_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    return_id UUID NOT NULL REFERENCES trans.scm_return(return_id) ON DELETE CASCADE,
    invoice_item_id UUID NOT NULL,
    catalogue_id UUID NOT NULL,
    sku VARCHAR(64) NOT NULL,
    description VARCHAR(500) NOT NULL,
    batch_no VARCHAR(50) NOT NULL,
    expiry_date TIMESTAMP WITH TIME ZONE,
    return_qty NUMERIC(12, 3) NOT NULL,
    qc_status VARCHAR(20) NOT NULL DEFAULT 'PENDING' CHECK (qc_status IN ('PENDING', 'ACCEPTED', 'REJECTED')),
    qc_qty NUMERIC(12, 3),
    qc_rejected_qty NUMERIC(12, 3),
    qc_remarks TEXT,
    qc_performed_by VARCHAR(100),
    qc_performed_at TIMESTAMP WITH TIME ZONE,
    unit_price NUMERIC(10, 2),
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_scm_return_item_return_id ON trans.scm_return_item(return_id);
CREATE INDEX IF NOT EXISTS idx_scm_return_item_invoice_item_id ON trans.scm_return_item(invoice_item_id);
CREATE INDEX IF NOT EXISTS idx_scm_return_item_sku ON trans.scm_return_item(sku);

CREATE TABLE IF NOT EXISTS trans.scm_return_status_log (
    log_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    return_id UUID NOT NULL REFERENCES trans.scm_return(return_id) ON DELETE CASCADE,
    action VARCHAR(20) NOT NULL,
    from_status VARCHAR(20),
    to_status VARCHAR(20) NOT NULL,
    performed_by VARCHAR(64) NOT NULL,
    performed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    remarks TEXT,
    reference_no VARCHAR(100)
);

CREATE INDEX IF NOT EXISTS idx_scm_return_status_log_return_id ON trans.scm_return_status_log(return_id);

-- ============================================================================
-- Legacy Sales Orders (B2C)
-- ============================================================================

CREATE TABLE IF NOT EXISTS trans.branches (
    branch_id VARCHAR(26) PRIMARY KEY
);

CREATE TABLE IF NOT EXISTS trans.merchants (
    merchant_id VARCHAR(26) PRIMARY KEY
);

CREATE TABLE IF NOT EXISTS trans.customers (
    customer_id VARCHAR(26) PRIMARY KEY
);

CREATE TABLE IF NOT EXISTS trans.users (
    user_id VARCHAR(26) PRIMARY KEY
);

CREATE TABLE IF NOT EXISTS trans.catalogues (
    catalogue_id VARCHAR(26) PRIMARY KEY
);

CREATE TABLE IF NOT EXISTS trans.sales_orders (
    sales_order_id VARCHAR(26) PRIMARY KEY,
    order_number VARCHAR(50) UNIQUE NOT NULL,
    branch_id VARCHAR(26) NOT NULL,
    merchant_id VARCHAR(26) NOT NULL,
    order_date TIMESTAMP WITH TIME ZONE NOT NULL,
    status VARCHAR(20) NOT NULL CHECK (status IN ('draft', 'confirmed', 'processing', 'fulfilled', 'partially_fulfilled', 'cancelled', 'on_hold')),
    customer_id VARCHAR(26) NOT NULL,
    customer_name VARCHAR(255) NOT NULL,
    customer_type VARCHAR(10) NOT NULL CHECK (customer_type IN ('b2b', 'b2c')),
    customer_phone VARCHAR(20),
    customer_email VARCHAR(255),
    customer_gstin VARCHAR(15),
    subtotal DECIMAL(12,2) NOT NULL DEFAULT 0,
    total_discount DECIMAL(12,2) NOT NULL DEFAULT 0,
    total_tax DECIMAL(12,2) NOT NULL DEFAULT 0,
    shipping_charges DECIMAL(12,2) NOT NULL DEFAULT 0,
    grand_total DECIMAL(12,2) NOT NULL DEFAULT 0,
    cgst DECIMAL(12,2) DEFAULT 0,
    sgst DECIMAL(12,2) DEFAULT 0,
    igst DECIMAL(12,2) DEFAULT 0,
    payment_type VARCHAR(20) NOT NULL CHECK (payment_type IN ('prepaid', 'cod', 'credit', 'partial')),
    payment_status VARCHAR(20) NOT NULL CHECK (payment_status IN ('unpaid', 'partial', 'paid', 'refunded', 'overdue')),
    payment_method VARCHAR(50),
    payment_date TIMESTAMP WITH TIME ZONE,
    payment_reference VARCHAR(100),
    amount_paid DECIMAL(12,2) NOT NULL DEFAULT 0,
    amount_due DECIMAL(12,2) NOT NULL DEFAULT 0,
    credit_terms VARCHAR(50),
    credit_limit DECIMAL(12,2),
    fulfillment_status VARCHAR(20) NOT NULL CHECK (fulfillment_status IN ('pending', 'allocated', 'picked', 'packed', 'shipped', 'delivered')),
    expected_delivery_date DATE,
    actual_delivery_date DATE,
    invoice_id VARCHAR(26),
    invoice_number VARCHAR(50),
    invoice_date TIMESTAMP WITH TIME ZONE,
    invoice_pdf_url TEXT,
    notes TEXT,
    internal_notes TEXT,
    created_by VARCHAR(26) NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    approved_by VARCHAR(26),
    approved_at TIMESTAMP WITH TIME ZONE,
    source VARCHAR(20) DEFAULT 'web',
    channel VARCHAR(50),
    tags TEXT[],
    version INTEGER NOT NULL DEFAULT 1,
    CONSTRAINT fk_sales_order_branch FOREIGN KEY (branch_id) REFERENCES trans.branches(branch_id),
    CONSTRAINT fk_sales_order_merchant FOREIGN KEY (merchant_id) REFERENCES trans.merchants(merchant_id),
    CONSTRAINT fk_sales_order_customer FOREIGN KEY (customer_id) REFERENCES trans.customers(customer_id),
    CONSTRAINT fk_sales_order_created_by FOREIGN KEY (created_by) REFERENCES trans.users(user_id)
);

CREATE TABLE IF NOT EXISTS trans.sales_order_items (
    id VARCHAR(26) PRIMARY KEY,
    sales_order_id VARCHAR(26) NOT NULL,
    sku VARCHAR(50) NOT NULL,
    product_id VARCHAR(26) NOT NULL,
    product_name VARCHAR(255) NOT NULL,
    item_type VARCHAR(20) NOT NULL CHECK (item_type IN ('product', 'service')),
    quantity INTEGER NOT NULL CHECK (quantity > 0),
    unit_price DECIMAL(10,2) NOT NULL,
    tax_percent DECIMAL(5,2) NOT NULL DEFAULT 0,
    discount_percent DECIMAL(5,2) NOT NULL DEFAULT 0,
    line_total DECIMAL(12,2) NOT NULL,
    hsn_code VARCHAR(10),
    uom VARCHAR(20) NOT NULL,
    batch_no VARCHAR(50),
    serials TEXT[],
    staff_id VARCHAR(26),
    staff_name VARCHAR(255),
    remarks TEXT,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_sales_order_item_order FOREIGN KEY (sales_order_id) REFERENCES trans.sales_orders(sales_order_id) ON DELETE CASCADE,
    CONSTRAINT fk_sales_order_item_product FOREIGN KEY (product_id) REFERENCES trans.catalogues(catalogue_id)
);

CREATE TABLE IF NOT EXISTS trans.sales_order_addresses (
    id VARCHAR(26) PRIMARY KEY,
    sales_order_id VARCHAR(26) NOT NULL,
    address_type VARCHAR(20) NOT NULL CHECK (address_type IN ('billing', 'shipping')),
    line1 VARCHAR(255) NOT NULL,
    line2 VARCHAR(255),
    city VARCHAR(100) NOT NULL,
    state VARCHAR(100) NOT NULL,
    postal_code VARCHAR(20) NOT NULL,
    country VARCHAR(100) NOT NULL DEFAULT 'India',
    landmark VARCHAR(255),
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_sales_order_address FOREIGN KEY (sales_order_id) REFERENCES trans.sales_orders(sales_order_id) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS trans.sales_order_shipments (
    shipment_id VARCHAR(26) PRIMARY KEY,
    sales_order_id VARCHAR(26) NOT NULL,
    carrier VARCHAR(100),
    tracking_number VARCHAR(100),
    awb_number VARCHAR(100),
    shipping_method VARCHAR(50),
    dispatch_date TIMESTAMP WITH TIME ZONE,
    expected_delivery_date DATE,
    actual_delivery_date DATE,
    status VARCHAR(20) CHECK (status IN ('pending', 'picked', 'in_transit', 'out_for_delivery', 'delivered', 'failed')),
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_sales_order_shipment FOREIGN KEY (sales_order_id) REFERENCES trans.sales_orders(sales_order_id) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS trans.sales_order_documents (
    id VARCHAR(26) PRIMARY KEY,
    sales_order_id VARCHAR(26) NOT NULL,
    filename VARCHAR(255) NOT NULL,
    file_url TEXT NOT NULL,
    document_type VARCHAR(50) NOT NULL,
    file_size INTEGER,
    mime_type VARCHAR(100),
    uploaded_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    uploaded_by VARCHAR(26),
    CONSTRAINT fk_sales_order_document FOREIGN KEY (sales_order_id) REFERENCES trans.sales_orders(sales_order_id) ON DELETE CASCADE
);

-- ============================================================================
-- Additional Indexes for Performance Optimization
-- ============================================================================

-- Invoice Adjustment Note Indexes
CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_status ON trans.scm_invoice_adjustment_note(status);
CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_type ON trans.scm_invoice_adjustment_note(note_type);
CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_category ON trans.scm_invoice_adjustment_note(category_code);
CREATE INDEX IF NOT EXISTS idx_scm_adjustment_note_date ON trans.scm_invoice_adjustment_note(note_date);

-- Trade Return Composite Indexes
CREATE INDEX IF NOT EXISTS idx_returns_type_status ON trans.scm_return (return_type, status);
CREATE INDEX IF NOT EXISTS idx_returns_buyer_status ON trans.scm_return (buyer_id, status);
CREATE INDEX IF NOT EXISTS idx_returns_supplier_status ON trans.scm_return (supplier_id, status);
CREATE INDEX IF NOT EXISTS idx_returns_invoice_type ON trans.scm_return (invoice_id, return_type);
CREATE INDEX IF NOT EXISTS idx_returns_created_status ON trans.scm_return (created_at, status);

-- Trade Return Item Indexes
CREATE INDEX IF NOT EXISTS idx_return_items_sku_batch ON trans.scm_return_item (sku, batch_no);
CREATE INDEX IF NOT EXISTS idx_return_items_qc_status ON trans.scm_return_item (qc_status);
CREATE INDEX IF NOT EXISTS idx_return_items_catalogue_batch ON trans.scm_return_item (catalogue_id, batch_no);

-- Trade Return Log Indexes
CREATE INDEX IF NOT EXISTS idx_return_logs_action_date ON trans.scm_return_status_log (action, performed_at);
CREATE INDEX IF NOT EXISTS idx_return_logs_status_date ON trans.scm_return_status_log (to_status, performed_at);
