-- =============================================================
-- ARCHIVO: 17-products.sql
-- DESCRIPCION: Productos, categorias y precios
-- VERSION: 1.0.0
-- PROYECTO: ERP-Core V2
-- FECHA: 2026-01-13
-- =============================================================

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

-- =====================
-- TABLA: product_categories
-- Categorias jerarquicas de productos
-- =====================
CREATE TABLE IF NOT EXISTS products.product_categories (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
    parent_id UUID REFERENCES products.product_categories(id) ON DELETE SET NULL,

    -- Identificacion
    code VARCHAR(30) NOT NULL,
    name VARCHAR(100) NOT NULL,
    description TEXT,

    -- Jerarquia
    hierarchy_path TEXT,         -- /root/electronics/phones
    hierarchy_level INTEGER DEFAULT 0,

    -- Imagen/icono
    image_url VARCHAR(500),
    icon VARCHAR(50),
    color VARCHAR(20),

    -- Estado
    is_active BOOLEAN DEFAULT TRUE,
    display_order INTEGER DEFAULT 0,

    -- 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, code)
);

-- Indices para product_categories
CREATE INDEX IF NOT EXISTS idx_product_categories_tenant ON products.product_categories(tenant_id);
CREATE INDEX IF NOT EXISTS idx_product_categories_parent ON products.product_categories(parent_id);
CREATE INDEX IF NOT EXISTS idx_product_categories_code ON products.product_categories(code);
CREATE INDEX IF NOT EXISTS idx_product_categories_hierarchy ON products.product_categories(hierarchy_path);
CREATE INDEX IF NOT EXISTS idx_product_categories_active ON products.product_categories(is_active) WHERE is_active = TRUE;

-- =====================
-- TABLA: products
-- Productos y servicios
-- =====================
CREATE TABLE IF NOT EXISTS products.products (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
    category_id UUID REFERENCES products.product_categories(id) ON DELETE SET NULL,

    -- Identificacion
    sku VARCHAR(50) NOT NULL,    -- Stock Keeping Unit
    barcode VARCHAR(50),         -- EAN, UPC, etc.
    name VARCHAR(200) NOT NULL,
    description TEXT,
    short_description VARCHAR(500),

    -- Tipo
    product_type VARCHAR(20) NOT NULL DEFAULT 'product', -- product, service, consumable, kit

    -- Precios
    price DECIMAL(15, 4) NOT NULL DEFAULT 0,
    cost DECIMAL(15, 4) DEFAULT 0,
    currency VARCHAR(3) DEFAULT 'MXN',
    tax_included BOOLEAN DEFAULT TRUE,

    -- Impuestos
    tax_rate DECIMAL(5, 2) DEFAULT 16.00,   -- IVA en Mexico
    tax_code VARCHAR(20),        -- Codigo SAT para facturacion

    -- Unidad de medida
    uom VARCHAR(20) DEFAULT 'PZA', -- Unidad de medida principal
    uom_purchase VARCHAR(20),     -- Unidad de medida para compras
    uom_conversion DECIMAL(10, 4) DEFAULT 1, -- Factor de conversion

    -- Inventario
    track_inventory BOOLEAN DEFAULT TRUE,
    min_stock DECIMAL(15, 4) DEFAULT 0,
    max_stock DECIMAL(15, 4),
    reorder_point DECIMAL(15, 4),
    lead_time_days INTEGER DEFAULT 0,

    -- Caracteristicas fisicas
    weight DECIMAL(10, 4),       -- Peso en kg
    length DECIMAL(10, 4),       -- Dimensiones en cm
    width DECIMAL(10, 4),
    height DECIMAL(10, 4),
    volume DECIMAL(10, 4),       -- Volumen en m3

    -- Imagenes
    image_url VARCHAR(500),
    images JSONB DEFAULT '[]',   -- Array de URLs de imagenes

    -- Atributos
    attributes JSONB DEFAULT '{}',
    -- Ejemplo: {"color": "red", "size": "XL", "material": "cotton"}

    -- Estado
    is_active BOOLEAN DEFAULT TRUE,
    is_sellable BOOLEAN DEFAULT TRUE,
    is_purchasable BOOLEAN DEFAULT TRUE,

    -- 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, sku)
);

-- Indices para products
CREATE INDEX IF NOT EXISTS idx_products_tenant ON products.products(tenant_id);
CREATE INDEX IF NOT EXISTS idx_products_category ON products.products(category_id);
CREATE INDEX IF NOT EXISTS idx_products_sku ON products.products(sku);
CREATE INDEX IF NOT EXISTS idx_products_barcode ON products.products(barcode);
CREATE INDEX IF NOT EXISTS idx_products_type ON products.products(product_type);
CREATE INDEX IF NOT EXISTS idx_products_active ON products.products(is_active) WHERE is_active = TRUE;
CREATE INDEX IF NOT EXISTS idx_products_name ON products.products USING gin(to_tsvector('spanish', name));
CREATE INDEX IF NOT EXISTS idx_products_sellable ON products.products(is_sellable) WHERE is_sellable = TRUE;
CREATE INDEX IF NOT EXISTS idx_products_purchasable ON products.products(is_purchasable) WHERE is_purchasable = TRUE;

-- =====================
-- TABLA: product_prices
-- Listas de precios y precios especiales
-- =====================
CREATE TABLE IF NOT EXISTS products.product_prices (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    product_id UUID NOT NULL REFERENCES products.products(id) ON DELETE CASCADE,

    -- Tipo de precio
    price_type VARCHAR(30) NOT NULL DEFAULT 'standard', -- standard, wholesale, retail, promo
    price_list_name VARCHAR(100),

    -- Precio
    price DECIMAL(15, 4) NOT NULL,
    currency VARCHAR(3) DEFAULT 'MXN',

    -- Cantidad minima para este precio
    min_quantity DECIMAL(15, 4) DEFAULT 1,

    -- Vigencia
    valid_from TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    valid_to TIMESTAMPTZ,

    -- Estado
    is_active BOOLEAN DEFAULT TRUE,

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

-- Indices para product_prices
CREATE INDEX IF NOT EXISTS idx_product_prices_product ON products.product_prices(product_id);
CREATE INDEX IF NOT EXISTS idx_product_prices_type ON products.product_prices(price_type);
CREATE INDEX IF NOT EXISTS idx_product_prices_active ON products.product_prices(is_active) WHERE is_active = TRUE;
CREATE INDEX IF NOT EXISTS idx_product_prices_validity ON products.product_prices(valid_from, valid_to);

-- =====================
-- TABLA: product_suppliers
-- Proveedores de productos
-- =====================
CREATE TABLE IF NOT EXISTS products.product_suppliers (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    product_id UUID NOT NULL REFERENCES products.products(id) ON DELETE CASCADE,
    supplier_id UUID NOT NULL REFERENCES partners.partners(id) ON DELETE CASCADE,

    -- Datos del proveedor
    supplier_sku VARCHAR(50),    -- SKU del proveedor
    supplier_name VARCHAR(200),  -- Nombre del producto del proveedor

    -- Precios de compra
    purchase_price DECIMAL(15, 4),
    currency VARCHAR(3) DEFAULT 'MXN',
    min_order_qty DECIMAL(15, 4) DEFAULT 1,

    -- Tiempos
    lead_time_days INTEGER DEFAULT 0,

    -- Estado
    is_preferred BOOLEAN DEFAULT FALSE,
    is_active BOOLEAN DEFAULT TRUE,

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

    UNIQUE(product_id, supplier_id)
);

-- Indices para product_suppliers
CREATE INDEX IF NOT EXISTS idx_product_suppliers_product ON products.product_suppliers(product_id);
CREATE INDEX IF NOT EXISTS idx_product_suppliers_supplier ON products.product_suppliers(supplier_id);
CREATE INDEX IF NOT EXISTS idx_product_suppliers_preferred ON products.product_suppliers(product_id, is_preferred) WHERE is_preferred = TRUE;

-- =====================
-- COMENTARIOS
-- =====================
COMMENT ON TABLE products.product_categories IS 'Categorias jerarquicas para organizar productos';
COMMENT ON COLUMN products.product_categories.hierarchy_path IS 'Path materializado para consultas eficientes de jerarquia';

COMMENT ON TABLE products.products IS 'Catalogo de productos y servicios';
COMMENT ON COLUMN products.products.product_type IS 'Tipo: product (fisico), service (servicio), consumable (consumible), kit (combo)';
COMMENT ON COLUMN products.products.sku IS 'Stock Keeping Unit - identificador unico del producto';
COMMENT ON COLUMN products.products.tax_code IS 'Codigo SAT para facturacion electronica en Mexico';
COMMENT ON COLUMN products.products.track_inventory IS 'Si se debe llevar control de inventario';

COMMENT ON TABLE products.product_prices IS 'Listas de precios y precios especiales por cantidad';
COMMENT ON COLUMN products.product_prices.price_type IS 'Tipo: standard, wholesale (mayoreo), retail (menudeo), promo (promocional)';

COMMENT ON TABLE products.product_suppliers IS 'Relacion de productos con sus proveedores';
COMMENT ON COLUMN products.product_suppliers.is_preferred IS 'Proveedor preferido para este producto';
