Financial Schema (50-57): - 50-financial-schema.sql: Schema + 10 ENUMs - 51-financial-accounts.sql: account_types, accounts, account_mappings - 52-financial-journals.sql: fiscal_years, fiscal_periods, journals - 53-financial-entries.sql: journal_entries, journal_entry_lines - 54-financial-invoices.sql: invoices, invoice_lines - 55-financial-payments.sql: payments, payment_invoice_allocations - 56-financial-taxes.sql: taxes, tax_groups - 57-financial-bank-reconciliation.sql: bank_statements, bank_statement_lines, rules Purchases Matching (46): - 46-purchases-matching.sql: purchase_order_matching, purchase_matching_lines, matching_exceptions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
156 lines
6.7 KiB
PL/PgSQL
156 lines
6.7 KiB
PL/PgSQL
-- =============================================================
|
|
-- ARCHIVO: 56-financial-taxes.sql
|
|
-- DESCRIPCION: Impuestos contables (IVA, retenciones, etc.)
|
|
-- VERSION: 1.0.0
|
|
-- PROYECTO: ERP-Core V2
|
|
-- FECHA: 2026-01-20
|
|
-- DEPENDE DE: 50-financial-schema.sql, 51-financial-accounts.sql
|
|
-- =============================================================
|
|
|
|
-- =====================
|
|
-- TABLA: taxes
|
|
-- Catalogo de impuestos
|
|
-- =====================
|
|
CREATE TABLE IF NOT EXISTS financial.taxes (
|
|
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,
|
|
|
|
-- Identificacion
|
|
name VARCHAR(100) NOT NULL, -- Ej: "IVA 16%", "Retencion ISR 10%"
|
|
code VARCHAR(20) NOT NULL, -- Ej: "IVA16", "RET_ISR10"
|
|
|
|
-- Tipo de impuesto
|
|
tax_type financial.tax_type_enum NOT NULL DEFAULT 'all',
|
|
|
|
-- Tasa
|
|
amount DECIMAL(5, 2) NOT NULL, -- Porcentaje (ej: 16.00 para 16%)
|
|
|
|
-- Configuracion
|
|
included_in_price BOOLEAN DEFAULT FALSE, -- TRUE si el precio ya incluye el impuesto
|
|
|
|
-- Estado
|
|
active BOOLEAN DEFAULT TRUE,
|
|
|
|
-- Cuentas contables asociadas (opcional)
|
|
account_id UUID REFERENCES financial.accounts(id) ON DELETE SET NULL, -- Cuenta de impuesto
|
|
refund_account_id UUID REFERENCES financial.accounts(id) ON DELETE SET NULL, -- Cuenta para devoluciones
|
|
|
|
-- 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),
|
|
|
|
-- Unicidad por tenant
|
|
UNIQUE(tenant_id, code)
|
|
);
|
|
|
|
-- Indices para taxes
|
|
CREATE INDEX IF NOT EXISTS idx_financial_taxes_tenant ON financial.taxes(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_financial_taxes_company ON financial.taxes(company_id);
|
|
CREATE INDEX IF NOT EXISTS idx_financial_taxes_code ON financial.taxes(code);
|
|
CREATE INDEX IF NOT EXISTS idx_financial_taxes_type ON financial.taxes(tax_type);
|
|
CREATE INDEX IF NOT EXISTS idx_financial_taxes_active ON financial.taxes(tenant_id) WHERE active = TRUE;
|
|
CREATE INDEX IF NOT EXISTS idx_financial_taxes_sales ON financial.taxes(tenant_id, tax_type) WHERE tax_type IN ('sales', 'all') AND active = TRUE;
|
|
CREATE INDEX IF NOT EXISTS idx_financial_taxes_purchase ON financial.taxes(tenant_id, tax_type) WHERE tax_type IN ('purchase', 'all') AND active = TRUE;
|
|
CREATE INDEX IF NOT EXISTS idx_financial_taxes_account ON financial.taxes(account_id) WHERE account_id IS NOT NULL;
|
|
|
|
-- =====================
|
|
-- TABLA: tax_groups (opcional, para agrupar impuestos)
|
|
-- Grupos de impuestos para aplicacion conjunta
|
|
-- =====================
|
|
CREATE TABLE IF NOT EXISTS financial.tax_groups (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
|
|
-- Multi-tenant
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
|
|
-- Identificacion
|
|
name VARCHAR(100) NOT NULL,
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
-- Descripcion
|
|
description TEXT,
|
|
|
|
-- Impuestos en el grupo (array de IDs)
|
|
tax_ids UUID[] DEFAULT '{}',
|
|
|
|
-- Estado
|
|
active BOOLEAN DEFAULT TRUE,
|
|
|
|
-- 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),
|
|
|
|
UNIQUE(tenant_id, code)
|
|
);
|
|
|
|
-- Indices para tax_groups
|
|
CREATE INDEX IF NOT EXISTS idx_financial_tax_groups_tenant ON financial.tax_groups(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_financial_tax_groups_code ON financial.tax_groups(code);
|
|
CREATE INDEX IF NOT EXISTS idx_financial_tax_groups_active ON financial.tax_groups(tenant_id) WHERE active = TRUE;
|
|
CREATE INDEX IF NOT EXISTS idx_financial_tax_groups_tax_ids ON financial.tax_groups USING GIN(tax_ids);
|
|
|
|
-- =====================
|
|
-- DATOS SEMILLA: Impuestos comunes de Mexico
|
|
-- =====================
|
|
-- Nota: Estos se insertan condicionalmente. En produccion, los impuestos
|
|
-- se crean por tenant desde la aplicacion.
|
|
|
|
-- Funcion para insertar impuestos semilla
|
|
CREATE OR REPLACE FUNCTION financial.seed_default_taxes(p_tenant_id UUID)
|
|
RETURNS void AS $$
|
|
BEGIN
|
|
-- IVA 16% (tasa general)
|
|
INSERT INTO financial.taxes (tenant_id, code, name, tax_type, amount, included_in_price, active)
|
|
VALUES (p_tenant_id, 'IVA16', 'IVA 16%', 'all', 16.00, FALSE, TRUE)
|
|
ON CONFLICT (tenant_id, code) DO NOTHING;
|
|
|
|
-- IVA 8% (frontera)
|
|
INSERT INTO financial.taxes (tenant_id, code, name, tax_type, amount, included_in_price, active)
|
|
VALUES (p_tenant_id, 'IVA8', 'IVA 8% (Frontera)', 'all', 8.00, FALSE, TRUE)
|
|
ON CONFLICT (tenant_id, code) DO NOTHING;
|
|
|
|
-- IVA 0% (tasa cero)
|
|
INSERT INTO financial.taxes (tenant_id, code, name, tax_type, amount, included_in_price, active)
|
|
VALUES (p_tenant_id, 'IVA0', 'IVA 0%', 'all', 0.00, FALSE, TRUE)
|
|
ON CONFLICT (tenant_id, code) DO NOTHING;
|
|
|
|
-- IVA Exento
|
|
INSERT INTO financial.taxes (tenant_id, code, name, tax_type, amount, included_in_price, active)
|
|
VALUES (p_tenant_id, 'EXENTO', 'Exento de IVA', 'all', 0.00, FALSE, TRUE)
|
|
ON CONFLICT (tenant_id, code) DO NOTHING;
|
|
|
|
-- Retencion ISR 10%
|
|
INSERT INTO financial.taxes (tenant_id, code, name, tax_type, amount, included_in_price, active)
|
|
VALUES (p_tenant_id, 'RET_ISR10', 'Retencion ISR 10%', 'purchase', -10.00, FALSE, TRUE)
|
|
ON CONFLICT (tenant_id, code) DO NOTHING;
|
|
|
|
-- Retencion IVA 10.67%
|
|
INSERT INTO financial.taxes (tenant_id, code, name, tax_type, amount, included_in_price, active)
|
|
VALUES (p_tenant_id, 'RET_IVA', 'Retencion IVA 2/3', 'purchase', -10.67, FALSE, TRUE)
|
|
ON CONFLICT (tenant_id, code) DO NOTHING;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- =====================
|
|
-- COMENTARIOS
|
|
-- =====================
|
|
COMMENT ON TABLE financial.taxes IS 'Catalogo de impuestos (IVA, retenciones, etc.)';
|
|
COMMENT ON COLUMN financial.taxes.code IS 'Codigo unico del impuesto (ej: IVA16, RET_ISR10)';
|
|
COMMENT ON COLUMN financial.taxes.tax_type IS 'Aplicacion: sales (solo ventas), purchase (solo compras), all (ambos)';
|
|
COMMENT ON COLUMN financial.taxes.amount IS 'Tasa del impuesto en porcentaje (ej: 16.00 para 16%). Negativo para retenciones.';
|
|
COMMENT ON COLUMN financial.taxes.included_in_price IS 'TRUE si el precio del producto ya incluye este impuesto';
|
|
COMMENT ON COLUMN financial.taxes.account_id IS 'Cuenta contable donde se registra el impuesto';
|
|
COMMENT ON COLUMN financial.taxes.refund_account_id IS 'Cuenta contable para devoluciones/notas de credito';
|
|
|
|
COMMENT ON TABLE financial.tax_groups IS 'Grupos de impuestos para aplicacion conjunta (ej: IVA + Retenciones)';
|
|
COMMENT ON COLUMN financial.tax_groups.tax_ids IS 'Array de IDs de impuestos que componen el grupo';
|
|
|
|
COMMENT ON FUNCTION financial.seed_default_taxes(UUID) IS 'Inserta impuestos predeterminados de Mexico para un tenant';
|