-- ============================================================================
-- INVENTORY EXTENSION Schema DDL - Extensiones de Inventario para Construcción
-- Modulos: MAI-004 (Compras e Inventarios)
-- Version: 1.0.0
-- Fecha: 2025-12-08
-- ============================================================================
-- TIPO: Extensión del ERP Core (MGN-005 Inventory)
-- NOTA: Contiene SOLO extensiones específicas de construcción.
--       Las tablas base están en el ERP Core.
-- ============================================================================
-- PREREQUISITOS:
--   1. ERP-Core instalado (auth.tenants, auth.users)
--   2. Schema construction instalado (fraccionamientos, conceptos, lotes, departamentos)
--   3. Schema inventory de ERP-Core instalado (opcional, para FKs)
-- ============================================================================

-- Verificar prerequisitos
DO $$
BEGIN
    IF NOT EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = 'auth') THEN
        RAISE EXCEPTION 'Schema auth no existe. Ejecutar primero ERP-Core DDL';
    END IF;
    IF NOT EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = 'construction') THEN
        RAISE EXCEPTION 'Schema construction no existe. Ejecutar primero construction DDL';
    END IF;
END $$;

-- Crear schema si no existe (puede ya existir desde ERP-Core)
CREATE SCHEMA IF NOT EXISTS inventory;

-- ============================================================================
-- TYPES (ENUMs) ADICIONALES
-- ============================================================================

DO $$ BEGIN
    CREATE TYPE inventory.warehouse_type_construction AS ENUM (
        'central', 'obra', 'temporal', 'transito'
    );
EXCEPTION WHEN duplicate_object THEN NULL; END $$;

DO $$ BEGIN
    CREATE TYPE inventory.requisition_status AS ENUM (
        'draft', 'submitted', 'approved', 'partially_served', 'served', 'cancelled'
    );
EXCEPTION WHEN duplicate_object THEN NULL; END $$;

-- ============================================================================
-- TABLES - EXTENSIONES CONSTRUCCIÓN
-- ============================================================================

-- Tabla: almacenes_proyecto (almacén por proyecto/obra)
-- Extiende: inventory.warehouses (ERP Core)
CREATE TABLE IF NOT EXISTS inventory.almacenes_proyecto (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
    warehouse_id UUID NOT NULL,  -- FK a inventory.warehouses (ERP Core)
    fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
    warehouse_type inventory.warehouse_type_construction NOT NULL DEFAULT 'obra',
    location_description TEXT,
    location GEOMETRY(POINT, 4326),
    responsible_id UUID REFERENCES auth.users(id),
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    created_by UUID REFERENCES auth.users(id),
    updated_at TIMESTAMPTZ,
    updated_by UUID REFERENCES auth.users(id),
    deleted_at TIMESTAMPTZ,
    deleted_by UUID REFERENCES auth.users(id),
    CONSTRAINT uq_almacenes_proyecto_warehouse UNIQUE (warehouse_id)
);

-- Tabla: requisiciones_obra (requisiciones desde obra)
CREATE TABLE IF NOT EXISTS inventory.requisiciones_obra (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
    fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
    requisition_number VARCHAR(30) NOT NULL,
    requisition_date DATE NOT NULL,
    required_date DATE NOT NULL,
    status inventory.requisition_status NOT NULL DEFAULT 'draft',
    priority VARCHAR(20) DEFAULT 'medium',
    requested_by UUID NOT NULL REFERENCES auth.users(id),
    destination_warehouse_id UUID,  -- FK a inventory.warehouses (ERP Core)
    approved_by UUID REFERENCES auth.users(id),
    approved_at TIMESTAMPTZ,
    rejection_reason TEXT,
    purchase_order_id UUID,  -- FK a purchase.purchase_orders (ERP Core)
    notes TEXT,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    created_by UUID REFERENCES auth.users(id),
    updated_at TIMESTAMPTZ,
    updated_by UUID REFERENCES auth.users(id),
    deleted_at TIMESTAMPTZ,
    deleted_by UUID REFERENCES auth.users(id),
    CONSTRAINT uq_requisiciones_obra_number UNIQUE (tenant_id, requisition_number)
);

-- Tabla: requisicion_lineas (líneas de requisición)
CREATE TABLE IF NOT EXISTS inventory.requisicion_lineas (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
    requisicion_id UUID NOT NULL REFERENCES inventory.requisiciones_obra(id) ON DELETE CASCADE,
    product_id UUID NOT NULL,  -- FK a inventory.products (ERP Core)
    concepto_id UUID REFERENCES construction.conceptos(id),
    lote_id UUID REFERENCES construction.lotes(id),
    quantity_requested DECIMAL(12,4) NOT NULL,
    quantity_approved DECIMAL(12,4),
    quantity_served DECIMAL(12,4) DEFAULT 0,
    unit_id UUID,  -- FK a core.uom (ERP Core)
    notes TEXT,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    created_by UUID REFERENCES auth.users(id),
    updated_at TIMESTAMPTZ,
    updated_by UUID REFERENCES auth.users(id),
    deleted_at TIMESTAMPTZ,
    deleted_by UUID REFERENCES auth.users(id)
);

-- Tabla: consumos_obra (consumos de materiales por obra/lote)
CREATE TABLE IF NOT EXISTS inventory.consumos_obra (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
    stock_move_id UUID,  -- FK a inventory.stock_moves (ERP Core)
    fraccionamiento_id UUID NOT NULL REFERENCES construction.fraccionamientos(id),
    lote_id UUID REFERENCES construction.lotes(id),
    departamento_id UUID REFERENCES construction.departamentos(id),
    concepto_id UUID REFERENCES construction.conceptos(id),
    product_id UUID NOT NULL,  -- FK a inventory.products (ERP Core)
    quantity DECIMAL(12,4) NOT NULL,
    unit_cost DECIMAL(12,4),
    total_cost DECIMAL(14,2) GENERATED ALWAYS AS (quantity * unit_cost) STORED,
    consumption_date DATE NOT NULL,
    registered_by UUID NOT NULL REFERENCES auth.users(id),
    notes TEXT,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    created_by UUID REFERENCES auth.users(id),
    updated_at TIMESTAMPTZ,
    updated_by UUID REFERENCES auth.users(id),
    deleted_at TIMESTAMPTZ,
    deleted_by UUID REFERENCES auth.users(id)
);

-- ============================================================================
-- INDICES
-- ============================================================================

CREATE INDEX IF NOT EXISTS idx_almacenes_proyecto_tenant_id ON inventory.almacenes_proyecto(tenant_id);
CREATE INDEX IF NOT EXISTS idx_almacenes_proyecto_warehouse_id ON inventory.almacenes_proyecto(warehouse_id);
CREATE INDEX IF NOT EXISTS idx_almacenes_proyecto_fraccionamiento_id ON inventory.almacenes_proyecto(fraccionamiento_id);

CREATE INDEX IF NOT EXISTS idx_requisiciones_obra_tenant_id ON inventory.requisiciones_obra(tenant_id);
CREATE INDEX IF NOT EXISTS idx_requisiciones_obra_fraccionamiento_id ON inventory.requisiciones_obra(fraccionamiento_id);
CREATE INDEX IF NOT EXISTS idx_requisiciones_obra_status ON inventory.requisiciones_obra(status);
CREATE INDEX IF NOT EXISTS idx_requisiciones_obra_date ON inventory.requisiciones_obra(requisition_date);
CREATE INDEX IF NOT EXISTS idx_requisiciones_obra_required_date ON inventory.requisiciones_obra(required_date);

CREATE INDEX IF NOT EXISTS idx_requisicion_lineas_tenant_id ON inventory.requisicion_lineas(tenant_id);
CREATE INDEX IF NOT EXISTS idx_requisicion_lineas_requisicion_id ON inventory.requisicion_lineas(requisicion_id);
CREATE INDEX IF NOT EXISTS idx_requisicion_lineas_product_id ON inventory.requisicion_lineas(product_id);

CREATE INDEX IF NOT EXISTS idx_consumos_obra_tenant_id ON inventory.consumos_obra(tenant_id);
CREATE INDEX IF NOT EXISTS idx_consumos_obra_fraccionamiento_id ON inventory.consumos_obra(fraccionamiento_id);
CREATE INDEX IF NOT EXISTS idx_consumos_obra_lote_id ON inventory.consumos_obra(lote_id);
CREATE INDEX IF NOT EXISTS idx_consumos_obra_concepto_id ON inventory.consumos_obra(concepto_id);
CREATE INDEX IF NOT EXISTS idx_consumos_obra_product_id ON inventory.consumos_obra(product_id);
CREATE INDEX IF NOT EXISTS idx_consumos_obra_date ON inventory.consumos_obra(consumption_date);

-- ============================================================================
-- ROW LEVEL SECURITY (RLS)
-- ============================================================================

ALTER TABLE inventory.almacenes_proyecto ENABLE ROW LEVEL SECURITY;
ALTER TABLE inventory.requisiciones_obra ENABLE ROW LEVEL SECURITY;
ALTER TABLE inventory.requisicion_lineas ENABLE ROW LEVEL SECURITY;
ALTER TABLE inventory.consumos_obra ENABLE ROW LEVEL SECURITY;

DO $$ BEGIN
    DROP POLICY IF EXISTS tenant_isolation_almacenes_proyecto ON inventory.almacenes_proyecto;
    CREATE POLICY tenant_isolation_almacenes_proyecto ON inventory.almacenes_proyecto
        FOR ALL USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
EXCEPTION WHEN undefined_object THEN NULL; END $$;

DO $$ BEGIN
    DROP POLICY IF EXISTS tenant_isolation_requisiciones_obra ON inventory.requisiciones_obra;
    CREATE POLICY tenant_isolation_requisiciones_obra ON inventory.requisiciones_obra
        FOR ALL USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
EXCEPTION WHEN undefined_object THEN NULL; END $$;

DO $$ BEGIN
    DROP POLICY IF EXISTS tenant_isolation_requisicion_lineas ON inventory.requisicion_lineas;
    CREATE POLICY tenant_isolation_requisicion_lineas ON inventory.requisicion_lineas
        FOR ALL USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
EXCEPTION WHEN undefined_object THEN NULL; END $$;

DO $$ BEGIN
    DROP POLICY IF EXISTS tenant_isolation_consumos_obra ON inventory.consumos_obra;
    CREATE POLICY tenant_isolation_consumos_obra ON inventory.consumos_obra
        FOR ALL USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
EXCEPTION WHEN undefined_object THEN NULL; END $$;

-- ============================================================================
-- COMENTARIOS
-- ============================================================================

COMMENT ON TABLE inventory.almacenes_proyecto IS 'Extensión: almacenes por proyecto de construcción';
COMMENT ON TABLE inventory.requisiciones_obra IS 'Extensión: requisiciones de material desde obra';
COMMENT ON TABLE inventory.requisicion_lineas IS 'Extensión: líneas de requisición de obra';
COMMENT ON TABLE inventory.consumos_obra IS 'Extensión: consumos de materiales por obra/lote';

-- ============================================================================
-- FIN DE EXTENSIONES INVENTORY
-- Total tablas: 4
-- ============================================================================
