erp-core-database-v2/ddl/51-financial-accounts.sql
rckrdmrd 4b6240311d [TASK-2026-01-20-003] feat: Add financial DDL and matching tables
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>
2026-01-20 03:47:04 -06:00

144 lines
6.0 KiB
SQL

-- =============================================================
-- ARCHIVO: 51-financial-accounts.sql
-- DESCRIPCION: Plan de cuentas, tipos de cuenta y mapeos
-- VERSION: 1.0.0
-- PROYECTO: ERP-Core V2
-- FECHA: 2026-01-20
-- DEPENDE DE: 50-financial-schema.sql
-- =============================================================
-- =====================
-- TABLA: account_types
-- Catalogo de tipos de cuenta contable
-- =====================
CREATE TABLE IF NOT EXISTS financial.account_types (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- Identificacion
code VARCHAR(20) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL,
-- Clasificacion
account_type financial.account_type_enum NOT NULL,
-- Descripcion
description TEXT,
-- Metadata
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
-- Indices para account_types
CREATE INDEX IF NOT EXISTS idx_financial_account_types_code ON financial.account_types(code);
CREATE INDEX IF NOT EXISTS idx_financial_account_types_type ON financial.account_types(account_type);
-- =====================
-- TABLA: accounts
-- Plan de cuentas contables
-- =====================
CREATE TABLE IF NOT EXISTS financial.accounts (
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, -- FK a company si existe multi-company
-- Identificacion
code VARCHAR(50) NOT NULL,
name VARCHAR(255) NOT NULL,
-- Clasificacion
account_type_id UUID NOT NULL REFERENCES financial.account_types(id) ON DELETE RESTRICT,
-- Jerarquia (cuenta padre para estructura arborea)
parent_id UUID REFERENCES financial.accounts(id) ON DELETE SET NULL,
-- Moneda preferida
currency_id UUID, -- FK a catalogo de monedas si existe
-- Configuracion
is_reconcilable BOOLEAN DEFAULT FALSE, -- Permite conciliacion bancaria
is_deprecated BOOLEAN DEFAULT FALSE, -- Cuenta obsoleta (no usar en nuevos movimientos)
-- 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),
deleted_at TIMESTAMPTZ,
-- Constraint de unicidad por tenant
UNIQUE(tenant_id, code)
);
-- Indices para accounts
CREATE INDEX IF NOT EXISTS idx_financial_accounts_tenant ON financial.accounts(tenant_id);
CREATE INDEX IF NOT EXISTS idx_financial_accounts_company ON financial.accounts(company_id);
CREATE INDEX IF NOT EXISTS idx_financial_accounts_code ON financial.accounts(code);
CREATE INDEX IF NOT EXISTS idx_financial_accounts_type ON financial.accounts(account_type_id);
CREATE INDEX IF NOT EXISTS idx_financial_accounts_parent ON financial.accounts(parent_id);
CREATE INDEX IF NOT EXISTS idx_financial_accounts_active ON financial.accounts(tenant_id) WHERE deleted_at IS NULL AND is_deprecated = FALSE;
CREATE INDEX IF NOT EXISTS idx_financial_accounts_reconcilable ON financial.accounts(tenant_id, is_reconcilable) WHERE is_reconcilable = TRUE;
-- =====================
-- TABLA: account_mappings
-- Mapeos de cuentas para automatizaciones
-- Ej: cuenta_ingreso_default, cuenta_iva_16, cuenta_banco_principal
-- =====================
CREATE TABLE IF NOT EXISTS financial.account_mappings (
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 del mapeo
mapping_type VARCHAR(50) NOT NULL, -- Ej: default_income, default_expense, vat_16, bank_main
-- Cuenta mapeada
account_id UUID NOT NULL REFERENCES financial.accounts(id) ON DELETE CASCADE,
-- Descripcion
description TEXT,
-- Estado
is_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),
-- Un solo mapeo activo por tipo por tenant/company
UNIQUE(tenant_id, company_id, mapping_type)
);
-- Indices para account_mappings
CREATE INDEX IF NOT EXISTS idx_financial_account_mappings_tenant ON financial.account_mappings(tenant_id);
CREATE INDEX IF NOT EXISTS idx_financial_account_mappings_company ON financial.account_mappings(company_id);
CREATE INDEX IF NOT EXISTS idx_financial_account_mappings_type ON financial.account_mappings(mapping_type);
CREATE INDEX IF NOT EXISTS idx_financial_account_mappings_account ON financial.account_mappings(account_id);
CREATE INDEX IF NOT EXISTS idx_financial_account_mappings_active ON financial.account_mappings(tenant_id, is_active) WHERE is_active = TRUE;
-- =====================
-- COMENTARIOS
-- =====================
COMMENT ON TABLE financial.account_types IS 'Catalogo de tipos de cuenta contable (activo, pasivo, capital, ingreso, gasto)';
COMMENT ON COLUMN financial.account_types.code IS 'Codigo unico del tipo (ej: ASSET_CURRENT, LIABILITY_LONG)';
COMMENT ON COLUMN financial.account_types.account_type IS 'Clasificacion principal: asset, liability, equity, income, expense';
COMMENT ON TABLE financial.accounts IS 'Plan de cuentas contables con estructura jerarquica';
COMMENT ON COLUMN financial.accounts.code IS 'Codigo de cuenta (ej: 1100, 1100.01)';
COMMENT ON COLUMN financial.accounts.parent_id IS 'Referencia a cuenta padre para estructura de arbol';
COMMENT ON COLUMN financial.accounts.is_reconcilable IS 'TRUE si la cuenta permite conciliacion bancaria';
COMMENT ON COLUMN financial.accounts.is_deprecated IS 'TRUE si la cuenta esta obsoleta (no usar en nuevos movimientos)';
COMMENT ON TABLE financial.account_mappings IS 'Mapeos de cuentas para automatizaciones contables';
COMMENT ON COLUMN financial.account_mappings.mapping_type IS 'Tipo de mapeo (ej: default_income, vat_16, bank_main)';
COMMENT ON COLUMN financial.account_mappings.account_id IS 'Cuenta contable asociada al mapeo';