-- =============================================================
-- ARCHIVO: 54-financial-invoices.sql
-- DESCRIPCION: Facturas contables (cliente/proveedor) y lineas de factura
-- VERSION: 1.0.0
-- PROYECTO: ERP-Core V2
-- FECHA: 2026-01-20
-- DEPENDE DE: 50-financial-schema.sql, 51-financial-accounts.sql, 52-financial-journals.sql, 53-financial-entries.sql
-- NOTA: Este modulo es para facturas desde perspectiva CONTABLE.
--       Para facturacion operativa ver 24-invoices.sql (schema billing)
-- =============================================================

-- =====================
-- TABLA: invoices
-- Facturas contables (cliente y proveedor)
-- =====================
CREATE TABLE IF NOT EXISTS financial.invoices (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),

    -- Multi-tenant
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
    company_id UUID,

    -- Partner (cliente o proveedor)
    partner_id UUID NOT NULL,  -- FK a partners.partners

    -- Tipo de factura
    invoice_type financial.invoice_type_enum NOT NULL,

    -- Identificacion
    number VARCHAR(100) NOT NULL,  -- Numero de factura
    ref VARCHAR(255),               -- Referencia externa

    -- Fechas
    invoice_date DATE NOT NULL,
    due_date DATE,

    -- Moneda
    currency_id UUID,  -- FK a catalogo de monedas

    -- Montos
    amount_untaxed DECIMAL(15, 2) DEFAULT 0,    -- Subtotal sin impuestos
    amount_tax DECIMAL(15, 2) DEFAULT 0,         -- Total impuestos
    amount_total DECIMAL(15, 2) DEFAULT 0,       -- Total de la factura
    amount_paid DECIMAL(15, 2) DEFAULT 0,        -- Monto pagado
    amount_residual DECIMAL(15, 2) GENERATED ALWAYS AS (amount_total - COALESCE(amount_paid, 0)) STORED,  -- Saldo pendiente

    -- Estado
    status financial.invoice_status_enum DEFAULT 'draft',

    -- Terminos de pago
    payment_term_id UUID,  -- FK a terminos de pago si existe

    -- Relacion con contabilidad
    journal_id UUID REFERENCES financial.journals(id) ON DELETE RESTRICT,
    journal_entry_id UUID REFERENCES financial.journal_entries(id) ON DELETE SET NULL,

    -- Notas
    notes TEXT,

    -- Audit columns
    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),

    -- Validacion
    validated_at TIMESTAMPTZ,
    validated_by UUID REFERENCES auth.users(id),

    -- Cancelacion
    cancelled_at TIMESTAMPTZ,
    cancelled_by UUID REFERENCES auth.users(id),

    -- Unicidad
    UNIQUE(tenant_id, number, invoice_type)
);

-- Indices para invoices
CREATE INDEX IF NOT EXISTS idx_financial_invoices_tenant ON financial.invoices(tenant_id);
CREATE INDEX IF NOT EXISTS idx_financial_invoices_company ON financial.invoices(company_id);
CREATE INDEX IF NOT EXISTS idx_financial_invoices_partner ON financial.invoices(partner_id);
CREATE INDEX IF NOT EXISTS idx_financial_invoices_type ON financial.invoices(invoice_type);
CREATE INDEX IF NOT EXISTS idx_financial_invoices_number ON financial.invoices(number);
CREATE INDEX IF NOT EXISTS idx_financial_invoices_date ON financial.invoices(invoice_date);
CREATE INDEX IF NOT EXISTS idx_financial_invoices_due_date ON financial.invoices(due_date);
CREATE INDEX IF NOT EXISTS idx_financial_invoices_status ON financial.invoices(status);
CREATE INDEX IF NOT EXISTS idx_financial_invoices_journal ON financial.invoices(journal_id);
CREATE INDEX IF NOT EXISTS idx_financial_invoices_entry ON financial.invoices(journal_entry_id);
CREATE INDEX IF NOT EXISTS idx_financial_invoices_open ON financial.invoices(tenant_id, status) WHERE status = 'open';
CREATE INDEX IF NOT EXISTS idx_financial_invoices_unpaid ON financial.invoices(tenant_id, due_date) WHERE status = 'open' AND amount_paid < amount_total;
CREATE INDEX IF NOT EXISTS idx_financial_invoices_customer ON financial.invoices(tenant_id, partner_id, invoice_type) WHERE invoice_type = 'customer';
CREATE INDEX IF NOT EXISTS idx_financial_invoices_supplier ON financial.invoices(tenant_id, partner_id, invoice_type) WHERE invoice_type = 'supplier';

-- =====================
-- TABLA: invoice_lines
-- Lineas de factura contable
-- =====================
CREATE TABLE IF NOT EXISTS financial.invoice_lines (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),

    -- Relacion con factura (cascade delete)
    invoice_id UUID NOT NULL REFERENCES financial.invoices(id) ON DELETE CASCADE,

    -- Multi-tenant (denormalizado para queries rapidas)
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

    -- Producto (opcional)
    product_id UUID,  -- FK a products.products

    -- Descripcion
    description TEXT,

    -- Cantidad y unidad
    quantity DECIMAL(15, 4) NOT NULL DEFAULT 1,
    uom_id UUID,  -- FK a unidades de medida

    -- Precio
    price_unit DECIMAL(15, 2) NOT NULL DEFAULT 0,

    -- Impuestos aplicables (array de UUIDs de taxes)
    tax_ids UUID[] DEFAULT '{}',

    -- Montos calculados
    amount_untaxed DECIMAL(15, 2) DEFAULT 0,  -- subtotal linea
    amount_tax DECIMAL(15, 2) DEFAULT 0,       -- impuestos linea
    amount_total DECIMAL(15, 2) DEFAULT 0,     -- total linea

    -- Cuenta contable
    account_id UUID REFERENCES financial.accounts(id) ON DELETE RESTRICT,

    -- Audit columns
    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)
);

-- Indices para invoice_lines
CREATE INDEX IF NOT EXISTS idx_financial_invoice_lines_invoice ON financial.invoice_lines(invoice_id);
CREATE INDEX IF NOT EXISTS idx_financial_invoice_lines_tenant ON financial.invoice_lines(tenant_id);
CREATE INDEX IF NOT EXISTS idx_financial_invoice_lines_product ON financial.invoice_lines(product_id) WHERE product_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_financial_invoice_lines_account ON financial.invoice_lines(account_id);
CREATE INDEX IF NOT EXISTS idx_financial_invoice_lines_tax_ids ON financial.invoice_lines USING GIN(tax_ids);

-- =====================
-- COMENTARIOS
-- =====================
COMMENT ON TABLE financial.invoices IS 'Facturas contables (perspectiva financiera)';
COMMENT ON COLUMN financial.invoices.invoice_type IS 'Tipo: customer (venta a cliente), supplier (compra a proveedor)';
COMMENT ON COLUMN financial.invoices.number IS 'Numero unico de factura';
COMMENT ON COLUMN financial.invoices.ref IS 'Referencia externa (numero de factura del proveedor, etc.)';
COMMENT ON COLUMN financial.invoices.amount_untaxed IS 'Subtotal sin impuestos';
COMMENT ON COLUMN financial.invoices.amount_tax IS 'Total de impuestos';
COMMENT ON COLUMN financial.invoices.amount_total IS 'Total de la factura (subtotal + impuestos)';
COMMENT ON COLUMN financial.invoices.amount_paid IS 'Monto pagado hasta el momento';
COMMENT ON COLUMN financial.invoices.amount_residual IS 'Saldo pendiente de pago (calculado)';
COMMENT ON COLUMN financial.invoices.status IS 'Estado: draft, open (validada), paid, cancelled';
COMMENT ON COLUMN financial.invoices.journal_entry_id IS 'Asiento contable generado al validar la factura';
COMMENT ON COLUMN financial.invoices.validated_at IS 'Fecha y hora de validacion/apertura';
COMMENT ON COLUMN financial.invoices.cancelled_at IS 'Fecha y hora de cancelacion';

COMMENT ON TABLE financial.invoice_lines IS 'Lineas de detalle de facturas contables';
COMMENT ON COLUMN financial.invoice_lines.product_id IS 'Producto asociado (opcional)';
COMMENT ON COLUMN financial.invoice_lines.quantity IS 'Cantidad facturada';
COMMENT ON COLUMN financial.invoice_lines.price_unit IS 'Precio unitario';
COMMENT ON COLUMN financial.invoice_lines.tax_ids IS 'Array de IDs de impuestos aplicables';
COMMENT ON COLUMN financial.invoice_lines.account_id IS 'Cuenta contable para el asiento';
