-- =============================================================
-- ARCHIVO: 22-sales.sql
-- DESCRIPCION: Cotizaciones y ordenes de venta
-- VERSION: 1.0.0
-- PROYECTO: ERP-Core V2
-- FECHA: 2026-01-13
-- DEPENDE DE: 16-partners.sql, 17-products.sql
-- =============================================================

-- =====================
-- SCHEMA: sales
-- =====================
CREATE SCHEMA IF NOT EXISTS sales;

-- =====================
-- TABLA: quotations
-- Cotizaciones de venta
-- =====================
CREATE TABLE IF NOT EXISTS sales.quotations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

    -- Identificacion
    quotation_number VARCHAR(30) NOT NULL,

    -- Cliente
    partner_id UUID NOT NULL REFERENCES partners.partners(id) ON DELETE RESTRICT,
    partner_name VARCHAR(200),         -- Snapshot del nombre
    partner_email VARCHAR(255),

    -- Direcciones
    billing_address JSONB,
    shipping_address JSONB,

    -- Fechas
    quotation_date DATE NOT NULL DEFAULT CURRENT_DATE,
    valid_until DATE,
    expected_close_date DATE,

    -- Vendedor
    sales_rep_id UUID REFERENCES auth.users(id),

    -- Totales
    currency VARCHAR(3) DEFAULT 'MXN',
    subtotal DECIMAL(15, 2) NOT NULL DEFAULT 0,
    tax_amount DECIMAL(15, 2) NOT NULL DEFAULT 0,
    discount_amount DECIMAL(15, 2) NOT NULL DEFAULT 0,
    total DECIMAL(15, 2) NOT NULL DEFAULT 0,

    -- Terminos
    payment_term_days INTEGER DEFAULT 0,
    payment_method VARCHAR(50),

    -- Estado
    status VARCHAR(20) NOT NULL DEFAULT 'draft', -- draft, sent, accepted, rejected, expired, converted

    -- Conversion
    converted_to_order BOOLEAN DEFAULT FALSE,
    order_id UUID,
    converted_at TIMESTAMPTZ,

    -- Notas
    notes TEXT,
    internal_notes TEXT,
    terms_and_conditions TEXT,

    -- Metadata
    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    created_by UUID REFERENCES auth.users(id),
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_by UUID REFERENCES auth.users(id),
    deleted_at TIMESTAMPTZ,

    UNIQUE(tenant_id, quotation_number)
);

-- Indices para quotations
CREATE INDEX IF NOT EXISTS idx_quotations_tenant ON sales.quotations(tenant_id);
CREATE INDEX IF NOT EXISTS idx_quotations_number ON sales.quotations(quotation_number);
CREATE INDEX IF NOT EXISTS idx_quotations_partner ON sales.quotations(partner_id);
CREATE INDEX IF NOT EXISTS idx_quotations_status ON sales.quotations(status);
CREATE INDEX IF NOT EXISTS idx_quotations_date ON sales.quotations(quotation_date);
CREATE INDEX IF NOT EXISTS idx_quotations_valid_until ON sales.quotations(valid_until);
CREATE INDEX IF NOT EXISTS idx_quotations_sales_rep ON sales.quotations(sales_rep_id);

-- =====================
-- TABLA: quotation_items
-- Lineas de cotizacion
-- =====================
CREATE TABLE IF NOT EXISTS sales.quotation_items (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    quotation_id UUID NOT NULL REFERENCES sales.quotations(id) ON DELETE CASCADE,
    product_id UUID REFERENCES products.products(id) ON DELETE SET NULL,

    -- Linea
    line_number INTEGER NOT NULL DEFAULT 1,

    -- Producto
    product_sku VARCHAR(50),
    product_name VARCHAR(200) NOT NULL,
    description TEXT,

    -- Cantidad y precio
    quantity DECIMAL(15, 4) NOT NULL DEFAULT 1,
    uom VARCHAR(20) DEFAULT 'PZA',
    unit_price DECIMAL(15, 4) NOT NULL DEFAULT 0,

    -- Descuentos
    discount_percent DECIMAL(5, 2) DEFAULT 0,
    discount_amount DECIMAL(15, 2) DEFAULT 0,

    -- Impuestos
    tax_rate DECIMAL(5, 2) DEFAULT 16.00,
    tax_amount DECIMAL(15, 2) DEFAULT 0,

    -- Totales
    subtotal DECIMAL(15, 2) NOT NULL DEFAULT 0,
    total DECIMAL(15, 2) NOT NULL DEFAULT 0,

    -- Metadata
    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

-- Indices para quotation_items
CREATE INDEX IF NOT EXISTS idx_quotation_items_quotation ON sales.quotation_items(quotation_id);
CREATE INDEX IF NOT EXISTS idx_quotation_items_product ON sales.quotation_items(product_id);
CREATE INDEX IF NOT EXISTS idx_quotation_items_line ON sales.quotation_items(quotation_id, line_number);

-- =====================
-- TABLA: sales_orders
-- Ordenes de venta
-- =====================
CREATE TABLE IF NOT EXISTS sales.sales_orders (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

    -- Identificacion
    order_number VARCHAR(30) NOT NULL,

    -- Origen
    quotation_id UUID REFERENCES sales.quotations(id),

    -- Cliente
    partner_id UUID NOT NULL REFERENCES partners.partners(id) ON DELETE RESTRICT,
    partner_name VARCHAR(200),
    partner_email VARCHAR(255),

    -- Direcciones
    billing_address JSONB,
    shipping_address JSONB,

    -- Fechas
    order_date DATE NOT NULL DEFAULT CURRENT_DATE,
    requested_date DATE,           -- Fecha solicitada por cliente
    promised_date DATE,            -- Fecha prometida
    shipped_date DATE,
    delivered_date DATE,

    -- Vendedor
    sales_rep_id UUID REFERENCES auth.users(id),

    -- Almacen
    warehouse_id UUID REFERENCES inventory.warehouses(id),

    -- Totales
    currency VARCHAR(3) DEFAULT 'MXN',
    subtotal DECIMAL(15, 2) NOT NULL DEFAULT 0,
    tax_amount DECIMAL(15, 2) NOT NULL DEFAULT 0,
    discount_amount DECIMAL(15, 2) NOT NULL DEFAULT 0,
    shipping_amount DECIMAL(15, 2) DEFAULT 0,
    total DECIMAL(15, 2) NOT NULL DEFAULT 0,

    -- Terminos
    payment_term_days INTEGER DEFAULT 0,
    payment_method VARCHAR(50),

    -- Estado
    status VARCHAR(20) NOT NULL DEFAULT 'draft', -- draft, confirmed, processing, shipped, delivered, cancelled

    -- Envio
    shipping_method VARCHAR(50),
    tracking_number VARCHAR(100),
    carrier VARCHAR(100),

    -- Notas
    notes TEXT,
    internal_notes TEXT,

    -- Metadata
    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    created_by UUID REFERENCES auth.users(id),
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_by UUID REFERENCES auth.users(id),
    deleted_at TIMESTAMPTZ,

    UNIQUE(tenant_id, order_number)
);

-- Indices para sales_orders
CREATE INDEX IF NOT EXISTS idx_sales_orders_tenant ON sales.sales_orders(tenant_id);
CREATE INDEX IF NOT EXISTS idx_sales_orders_number ON sales.sales_orders(order_number);
CREATE INDEX IF NOT EXISTS idx_sales_orders_quotation ON sales.sales_orders(quotation_id);
CREATE INDEX IF NOT EXISTS idx_sales_orders_partner ON sales.sales_orders(partner_id);
CREATE INDEX IF NOT EXISTS idx_sales_orders_status ON sales.sales_orders(status);
CREATE INDEX IF NOT EXISTS idx_sales_orders_date ON sales.sales_orders(order_date);
CREATE INDEX IF NOT EXISTS idx_sales_orders_warehouse ON sales.sales_orders(warehouse_id);
CREATE INDEX IF NOT EXISTS idx_sales_orders_sales_rep ON sales.sales_orders(sales_rep_id);

-- =====================
-- TABLA: sales_order_items
-- Lineas de orden de venta
-- =====================
CREATE TABLE IF NOT EXISTS sales.sales_order_items (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    order_id UUID NOT NULL REFERENCES sales.sales_orders(id) ON DELETE CASCADE,
    product_id UUID REFERENCES products.products(id) ON DELETE SET NULL,

    -- Linea
    line_number INTEGER NOT NULL DEFAULT 1,

    -- Producto
    product_sku VARCHAR(50),
    product_name VARCHAR(200) NOT NULL,
    description TEXT,

    -- Cantidad
    quantity DECIMAL(15, 4) NOT NULL DEFAULT 1,
    quantity_reserved DECIMAL(15, 4) DEFAULT 0,
    quantity_shipped DECIMAL(15, 4) DEFAULT 0,
    quantity_delivered DECIMAL(15, 4) DEFAULT 0,
    quantity_returned DECIMAL(15, 4) DEFAULT 0,
    uom VARCHAR(20) DEFAULT 'PZA',

    -- Precio
    unit_price DECIMAL(15, 4) NOT NULL DEFAULT 0,
    unit_cost DECIMAL(15, 4) DEFAULT 0,

    -- Descuentos
    discount_percent DECIMAL(5, 2) DEFAULT 0,
    discount_amount DECIMAL(15, 2) DEFAULT 0,

    -- Impuestos
    tax_rate DECIMAL(5, 2) DEFAULT 16.00,
    tax_amount DECIMAL(15, 2) DEFAULT 0,

    -- Totales
    subtotal DECIMAL(15, 2) NOT NULL DEFAULT 0,
    total DECIMAL(15, 2) NOT NULL DEFAULT 0,

    -- Lote/Serie
    lot_number VARCHAR(50),
    serial_number VARCHAR(50),

    -- Estado
    status VARCHAR(20) DEFAULT 'pending', -- pending, reserved, shipped, delivered, cancelled

    -- Metadata
    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

-- Indices para sales_order_items
CREATE INDEX IF NOT EXISTS idx_sales_order_items_order ON sales.sales_order_items(order_id);
CREATE INDEX IF NOT EXISTS idx_sales_order_items_product ON sales.sales_order_items(product_id);
CREATE INDEX IF NOT EXISTS idx_sales_order_items_line ON sales.sales_order_items(order_id, line_number);
CREATE INDEX IF NOT EXISTS idx_sales_order_items_status ON sales.sales_order_items(status);

-- =====================
-- COMENTARIOS
-- =====================
COMMENT ON TABLE sales.quotations IS 'Cotizaciones de venta a clientes';
COMMENT ON COLUMN sales.quotations.status IS 'Estado: draft, sent, accepted, rejected, expired, converted';
COMMENT ON COLUMN sales.quotations.converted_to_order IS 'Indica si la cotizacion fue convertida a orden de venta';

COMMENT ON TABLE sales.quotation_items IS 'Lineas de detalle de cotizaciones';

COMMENT ON TABLE sales.sales_orders IS 'Ordenes de venta confirmadas';
COMMENT ON COLUMN sales.sales_orders.status IS 'Estado: draft, confirmed, processing, shipped, delivered, cancelled';
COMMENT ON COLUMN sales.sales_orders.quotation_id IS 'Referencia a la cotizacion origen (si aplica)';

COMMENT ON TABLE sales.sales_order_items IS 'Lineas de detalle de ordenes de venta';
COMMENT ON COLUMN sales.sales_order_items.quantity_reserved IS 'Cantidad reservada en inventario';
COMMENT ON COLUMN sales.sales_order_items.quantity_shipped IS 'Cantidad enviada';
COMMENT ON COLUMN sales.sales_order_items.quantity_delivered IS 'Cantidad entregada al cliente';
