971 lines
34 KiB
PL/PgSQL
971 lines
34 KiB
PL/PgSQL
-- =====================================================
|
|
-- SCHEMA: financial
|
|
-- PROPÓSITO: Contabilidad, facturas, pagos, finanzas
|
|
-- MÓDULOS: MGN-004 (Financiero Básico)
|
|
-- FECHA: 2025-11-24
|
|
-- =====================================================
|
|
|
|
-- Crear schema
|
|
CREATE SCHEMA IF NOT EXISTS financial;
|
|
|
|
-- =====================================================
|
|
-- TYPES (ENUMs)
|
|
-- =====================================================
|
|
|
|
CREATE TYPE financial.account_type AS ENUM (
|
|
'asset',
|
|
'liability',
|
|
'equity',
|
|
'revenue',
|
|
'expense'
|
|
);
|
|
|
|
CREATE TYPE financial.journal_type AS ENUM (
|
|
'sale',
|
|
'purchase',
|
|
'bank',
|
|
'cash',
|
|
'general'
|
|
);
|
|
|
|
CREATE TYPE financial.entry_status AS ENUM (
|
|
'draft',
|
|
'posted',
|
|
'cancelled'
|
|
);
|
|
|
|
CREATE TYPE financial.invoice_type AS ENUM (
|
|
'customer',
|
|
'supplier'
|
|
);
|
|
|
|
CREATE TYPE financial.invoice_status AS ENUM (
|
|
'draft',
|
|
'open',
|
|
'paid',
|
|
'cancelled'
|
|
);
|
|
|
|
CREATE TYPE financial.payment_type AS ENUM (
|
|
'inbound',
|
|
'outbound'
|
|
);
|
|
|
|
CREATE TYPE financial.payment_method AS ENUM (
|
|
'cash',
|
|
'bank_transfer',
|
|
'check',
|
|
'card',
|
|
'other'
|
|
);
|
|
|
|
CREATE TYPE financial.payment_status AS ENUM (
|
|
'draft',
|
|
'posted',
|
|
'reconciled',
|
|
'cancelled'
|
|
);
|
|
|
|
CREATE TYPE financial.tax_type AS ENUM (
|
|
'sales',
|
|
'purchase',
|
|
'all'
|
|
);
|
|
|
|
CREATE TYPE financial.fiscal_period_status AS ENUM (
|
|
'open',
|
|
'closed'
|
|
);
|
|
|
|
-- =====================================================
|
|
-- TABLES
|
|
-- =====================================================
|
|
|
|
-- Tabla: account_types (Tipos de cuenta contable)
|
|
CREATE TABLE financial.account_types (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
code VARCHAR(20) NOT NULL UNIQUE,
|
|
name VARCHAR(100) NOT NULL,
|
|
account_type financial.account_type NOT NULL,
|
|
description TEXT,
|
|
|
|
-- Sin tenant_id: catálogo global
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Tabla: accounts (Plan de cuentas)
|
|
CREATE TABLE financial.accounts (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
company_id UUID NOT NULL REFERENCES auth.companies(id) ON DELETE CASCADE,
|
|
|
|
code VARCHAR(50) NOT NULL,
|
|
name VARCHAR(255) NOT NULL,
|
|
account_type_id UUID NOT NULL REFERENCES financial.account_types(id),
|
|
parent_id UUID REFERENCES financial.accounts(id),
|
|
|
|
-- Configuración
|
|
currency_id UUID REFERENCES core.currencies(id),
|
|
is_reconcilable BOOLEAN DEFAULT FALSE, -- ¿Permite conciliación?
|
|
is_deprecated BOOLEAN DEFAULT FALSE,
|
|
|
|
-- Notas
|
|
notes TEXT,
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
updated_by UUID REFERENCES auth.users(id),
|
|
deleted_at TIMESTAMP,
|
|
deleted_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT uq_accounts_code_company UNIQUE (company_id, code),
|
|
CONSTRAINT chk_accounts_no_self_parent CHECK (id != parent_id)
|
|
);
|
|
|
|
-- Tabla: journals (Diarios contables)
|
|
CREATE TABLE financial.journals (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
company_id UUID NOT NULL REFERENCES auth.companies(id) ON DELETE CASCADE,
|
|
|
|
name VARCHAR(255) NOT NULL,
|
|
code VARCHAR(20) NOT NULL,
|
|
journal_type financial.journal_type NOT NULL,
|
|
|
|
-- Configuración
|
|
default_account_id UUID REFERENCES financial.accounts(id),
|
|
sequence_id UUID REFERENCES core.sequences(id),
|
|
currency_id UUID REFERENCES core.currencies(id),
|
|
|
|
-- Control
|
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
updated_by UUID REFERENCES auth.users(id),
|
|
deleted_at TIMESTAMP,
|
|
deleted_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT uq_journals_code_company UNIQUE (company_id, code)
|
|
);
|
|
|
|
-- Tabla: fiscal_years (Años fiscales)
|
|
CREATE TABLE financial.fiscal_years (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
company_id UUID NOT NULL REFERENCES auth.companies(id) ON DELETE CASCADE,
|
|
|
|
name VARCHAR(100) NOT NULL,
|
|
code VARCHAR(20) NOT NULL,
|
|
start_date DATE NOT NULL,
|
|
end_date DATE NOT NULL,
|
|
status financial.fiscal_period_status NOT NULL DEFAULT 'open',
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
updated_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT uq_fiscal_years_code_company UNIQUE (company_id, code),
|
|
CONSTRAINT chk_fiscal_years_dates CHECK (end_date > start_date)
|
|
);
|
|
|
|
-- Tabla: fiscal_periods (Períodos fiscales - meses)
|
|
CREATE TABLE financial.fiscal_periods (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
fiscal_year_id UUID NOT NULL REFERENCES financial.fiscal_years(id) ON DELETE CASCADE,
|
|
|
|
name VARCHAR(100) NOT NULL,
|
|
code VARCHAR(20) NOT NULL,
|
|
start_date DATE NOT NULL,
|
|
end_date DATE NOT NULL,
|
|
status financial.fiscal_period_status NOT NULL DEFAULT 'open',
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
updated_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT uq_fiscal_periods_code_year UNIQUE (fiscal_year_id, code),
|
|
CONSTRAINT chk_fiscal_periods_dates CHECK (end_date > start_date)
|
|
);
|
|
|
|
-- Tabla: journal_entries (Asientos contables)
|
|
CREATE TABLE financial.journal_entries (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
company_id UUID NOT NULL REFERENCES auth.companies(id) ON DELETE CASCADE,
|
|
|
|
journal_id UUID NOT NULL REFERENCES financial.journals(id),
|
|
name VARCHAR(100) NOT NULL, -- Número de asiento
|
|
ref VARCHAR(255), -- Referencia externa
|
|
date DATE NOT NULL,
|
|
status financial.entry_status NOT NULL DEFAULT 'draft',
|
|
|
|
-- Metadatos
|
|
notes TEXT,
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
updated_by UUID REFERENCES auth.users(id),
|
|
posted_at TIMESTAMP,
|
|
posted_by UUID REFERENCES auth.users(id),
|
|
cancelled_at TIMESTAMP,
|
|
cancelled_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT uq_journal_entries_name_journal UNIQUE (journal_id, name)
|
|
);
|
|
|
|
-- Tabla: journal_entry_lines (Líneas de asiento contable)
|
|
CREATE TABLE financial.journal_entry_lines (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
entry_id UUID NOT NULL REFERENCES financial.journal_entries(id) ON DELETE CASCADE,
|
|
|
|
account_id UUID NOT NULL REFERENCES financial.accounts(id),
|
|
partner_id UUID REFERENCES core.partners(id),
|
|
|
|
-- Montos
|
|
debit DECIMAL(15, 2) NOT NULL DEFAULT 0,
|
|
credit DECIMAL(15, 2) NOT NULL DEFAULT 0,
|
|
|
|
-- Analítica
|
|
analytic_account_id UUID, -- FK a analytics.analytic_accounts (se crea después)
|
|
|
|
-- Descripción
|
|
description TEXT,
|
|
ref VARCHAR(255),
|
|
|
|
-- Multi-moneda
|
|
currency_id UUID REFERENCES core.currencies(id),
|
|
amount_currency DECIMAL(15, 2),
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT chk_journal_lines_debit_positive CHECK (debit >= 0),
|
|
CONSTRAINT chk_journal_lines_credit_positive CHECK (credit >= 0),
|
|
CONSTRAINT chk_journal_lines_not_both CHECK (
|
|
(debit > 0 AND credit = 0) OR (credit > 0 AND debit = 0)
|
|
)
|
|
);
|
|
|
|
-- Índices para journal_entry_lines
|
|
CREATE INDEX idx_journal_entry_lines_tenant_id ON financial.journal_entry_lines(tenant_id);
|
|
CREATE INDEX idx_journal_entry_lines_entry_id ON financial.journal_entry_lines(entry_id);
|
|
CREATE INDEX idx_journal_entry_lines_account_id ON financial.journal_entry_lines(account_id);
|
|
|
|
-- RLS para journal_entry_lines
|
|
ALTER TABLE financial.journal_entry_lines ENABLE ROW LEVEL SECURITY;
|
|
CREATE POLICY tenant_isolation_journal_entry_lines ON financial.journal_entry_lines
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
-- Tabla: taxes (Impuestos)
|
|
CREATE TABLE financial.taxes (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
company_id UUID NOT NULL REFERENCES auth.companies(id) ON DELETE CASCADE,
|
|
|
|
name VARCHAR(100) NOT NULL,
|
|
code VARCHAR(20) NOT NULL,
|
|
rate DECIMAL(5, 4) NOT NULL, -- 0.1600 para 16%
|
|
tax_type financial.tax_type NOT NULL,
|
|
|
|
-- Configuración contable
|
|
account_id UUID REFERENCES financial.accounts(id),
|
|
|
|
-- Control
|
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
updated_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT uq_taxes_code_company UNIQUE (company_id, code),
|
|
CONSTRAINT chk_taxes_rate CHECK (rate >= 0 AND rate <= 1)
|
|
);
|
|
|
|
-- Tabla: payment_terms (Términos de pago)
|
|
CREATE TABLE financial.payment_terms (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
company_id UUID NOT NULL REFERENCES auth.companies(id) ON DELETE CASCADE,
|
|
|
|
name VARCHAR(100) NOT NULL,
|
|
code VARCHAR(20) NOT NULL,
|
|
|
|
-- Configuración de términos (JSON)
|
|
-- Ejemplo: [{"days": 0, "percent": 100}] = Pago inmediato
|
|
-- Ejemplo: [{"days": 30, "percent": 100}] = 30 días
|
|
-- Ejemplo: [{"days": 15, "percent": 50}, {"days": 30, "percent": 50}] = 50% a 15 días, 50% a 30 días
|
|
terms JSONB NOT NULL DEFAULT '[]',
|
|
|
|
-- Control
|
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
updated_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT uq_payment_terms_code_company UNIQUE (company_id, code)
|
|
);
|
|
|
|
-- Tabla: invoices (Facturas)
|
|
CREATE TABLE financial.invoices (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
company_id UUID NOT NULL REFERENCES auth.companies(id) ON DELETE CASCADE,
|
|
|
|
partner_id UUID NOT NULL REFERENCES core.partners(id),
|
|
invoice_type financial.invoice_type NOT NULL,
|
|
|
|
-- Numeración
|
|
number VARCHAR(100), -- Número de factura (generado al validar)
|
|
ref VARCHAR(100), -- Referencia del partner
|
|
|
|
-- Fechas
|
|
invoice_date DATE NOT NULL,
|
|
due_date DATE,
|
|
|
|
-- Montos
|
|
currency_id UUID NOT NULL REFERENCES core.currencies(id),
|
|
amount_untaxed DECIMAL(15, 2) NOT NULL DEFAULT 0,
|
|
amount_tax DECIMAL(15, 2) NOT NULL DEFAULT 0,
|
|
amount_total DECIMAL(15, 2) NOT NULL DEFAULT 0,
|
|
amount_paid DECIMAL(15, 2) NOT NULL DEFAULT 0,
|
|
amount_residual DECIMAL(15, 2) NOT NULL DEFAULT 0,
|
|
|
|
-- Estado
|
|
status financial.invoice_status NOT NULL DEFAULT 'draft',
|
|
|
|
-- Configuración
|
|
payment_term_id UUID REFERENCES financial.payment_terms(id),
|
|
journal_id UUID REFERENCES financial.journals(id),
|
|
|
|
-- Asiento contable (generado al validar)
|
|
journal_entry_id UUID REFERENCES financial.journal_entries(id),
|
|
|
|
-- Notas
|
|
notes TEXT,
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
updated_by UUID REFERENCES auth.users(id),
|
|
validated_at TIMESTAMP,
|
|
validated_by UUID REFERENCES auth.users(id),
|
|
cancelled_at TIMESTAMP,
|
|
cancelled_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT uq_invoices_number_company UNIQUE (company_id, number),
|
|
CONSTRAINT chk_invoices_amounts CHECK (
|
|
amount_total = amount_untaxed + amount_tax
|
|
),
|
|
CONSTRAINT chk_invoices_residual CHECK (
|
|
amount_residual = amount_total - amount_paid
|
|
)
|
|
);
|
|
|
|
-- Tabla: invoice_lines (Líneas de factura)
|
|
CREATE TABLE financial.invoice_lines (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
invoice_id UUID NOT NULL REFERENCES financial.invoices(id) ON DELETE CASCADE,
|
|
|
|
product_id UUID, -- FK a inventory.products (se crea después)
|
|
description TEXT NOT NULL,
|
|
|
|
-- Cantidades y precios
|
|
quantity DECIMAL(12, 4) NOT NULL DEFAULT 1,
|
|
uom_id UUID REFERENCES core.uom(id),
|
|
price_unit DECIMAL(15, 4) NOT NULL,
|
|
|
|
-- Impuestos (array de tax_ids)
|
|
tax_ids UUID[] DEFAULT '{}',
|
|
|
|
-- Montos calculados
|
|
amount_untaxed DECIMAL(15, 2) NOT NULL,
|
|
amount_tax DECIMAL(15, 2) NOT NULL,
|
|
amount_total DECIMAL(15, 2) NOT NULL,
|
|
|
|
-- Contabilidad
|
|
account_id UUID REFERENCES financial.accounts(id),
|
|
analytic_account_id UUID, -- FK a analytics.analytic_accounts
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP,
|
|
|
|
CONSTRAINT chk_invoice_lines_quantity CHECK (quantity > 0),
|
|
CONSTRAINT chk_invoice_lines_amounts CHECK (
|
|
amount_total = amount_untaxed + amount_tax
|
|
)
|
|
);
|
|
|
|
-- Índices para invoice_lines
|
|
CREATE INDEX idx_invoice_lines_tenant_id ON financial.invoice_lines(tenant_id);
|
|
CREATE INDEX idx_invoice_lines_invoice_id ON financial.invoice_lines(invoice_id);
|
|
CREATE INDEX idx_invoice_lines_product_id ON financial.invoice_lines(product_id);
|
|
|
|
-- RLS para invoice_lines
|
|
ALTER TABLE financial.invoice_lines ENABLE ROW LEVEL SECURITY;
|
|
CREATE POLICY tenant_isolation_invoice_lines ON financial.invoice_lines
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);
|
|
|
|
-- Tabla: payments (Pagos)
|
|
CREATE TABLE financial.payments (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
company_id UUID NOT NULL REFERENCES auth.companies(id) ON DELETE CASCADE,
|
|
|
|
partner_id UUID NOT NULL REFERENCES core.partners(id),
|
|
payment_type financial.payment_type NOT NULL,
|
|
payment_method financial.payment_method NOT NULL,
|
|
|
|
-- Monto
|
|
amount DECIMAL(15, 2) NOT NULL,
|
|
currency_id UUID NOT NULL REFERENCES core.currencies(id),
|
|
|
|
-- Fecha y referencia
|
|
payment_date DATE NOT NULL,
|
|
ref VARCHAR(255),
|
|
|
|
-- Estado
|
|
status financial.payment_status NOT NULL DEFAULT 'draft',
|
|
|
|
-- Configuración
|
|
journal_id UUID NOT NULL REFERENCES financial.journals(id),
|
|
|
|
-- Asiento contable (generado al validar)
|
|
journal_entry_id UUID REFERENCES financial.journal_entries(id),
|
|
|
|
-- Notas
|
|
notes TEXT,
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
updated_by UUID REFERENCES auth.users(id),
|
|
posted_at TIMESTAMP,
|
|
posted_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT chk_payments_amount CHECK (amount > 0)
|
|
);
|
|
|
|
-- Tabla: payment_invoice (Conciliación pagos-facturas)
|
|
CREATE TABLE financial.payment_invoice (
|
|
payment_id UUID NOT NULL REFERENCES financial.payments(id) ON DELETE CASCADE,
|
|
invoice_id UUID NOT NULL REFERENCES financial.invoices(id) ON DELETE CASCADE,
|
|
amount DECIMAL(15, 2) NOT NULL,
|
|
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
PRIMARY KEY (payment_id, invoice_id),
|
|
CONSTRAINT chk_payment_invoice_amount CHECK (amount > 0)
|
|
);
|
|
|
|
-- Tabla: bank_accounts (Cuentas bancarias)
|
|
CREATE TABLE financial.bank_accounts (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
company_id UUID REFERENCES auth.companies(id),
|
|
|
|
partner_id UUID REFERENCES core.partners(id), -- Puede ser de la empresa o de un partner
|
|
|
|
bank_name VARCHAR(255) NOT NULL,
|
|
account_number VARCHAR(50) NOT NULL,
|
|
account_holder VARCHAR(255),
|
|
|
|
-- Configuración
|
|
currency_id UUID REFERENCES core.currencies(id),
|
|
journal_id UUID REFERENCES financial.journals(id), -- Diario asociado (si es cuenta de la empresa)
|
|
|
|
-- Control
|
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
updated_by UUID REFERENCES auth.users(id)
|
|
);
|
|
|
|
-- Tabla: reconciliations (Conciliaciones bancarias)
|
|
CREATE TABLE financial.reconciliations (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
|
|
company_id UUID NOT NULL REFERENCES auth.companies(id) ON DELETE CASCADE,
|
|
|
|
bank_account_id UUID NOT NULL REFERENCES financial.bank_accounts(id),
|
|
|
|
-- Período de conciliación
|
|
start_date DATE NOT NULL,
|
|
end_date DATE NOT NULL,
|
|
|
|
-- Saldos
|
|
balance_start DECIMAL(15, 2) NOT NULL,
|
|
balance_end_real DECIMAL(15, 2) NOT NULL, -- Saldo real del banco
|
|
balance_end_computed DECIMAL(15, 2) NOT NULL, -- Saldo calculado
|
|
|
|
-- Líneas conciliadas (array de journal_entry_line_ids)
|
|
reconciled_line_ids UUID[] DEFAULT '{}',
|
|
|
|
-- Estado
|
|
status financial.entry_status NOT NULL DEFAULT 'draft',
|
|
|
|
-- Auditoría
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
created_by UUID REFERENCES auth.users(id),
|
|
updated_at TIMESTAMP,
|
|
updated_by UUID REFERENCES auth.users(id),
|
|
validated_at TIMESTAMP,
|
|
validated_by UUID REFERENCES auth.users(id),
|
|
|
|
CONSTRAINT chk_reconciliations_dates CHECK (end_date >= start_date)
|
|
);
|
|
|
|
-- =====================================================
|
|
-- INDICES
|
|
-- =====================================================
|
|
|
|
-- Account Types
|
|
CREATE INDEX idx_account_types_code ON financial.account_types(code);
|
|
|
|
-- Accounts
|
|
CREATE INDEX idx_accounts_tenant_id ON financial.accounts(tenant_id);
|
|
CREATE INDEX idx_accounts_company_id ON financial.accounts(company_id);
|
|
CREATE INDEX idx_accounts_code ON financial.accounts(code);
|
|
CREATE INDEX idx_accounts_parent_id ON financial.accounts(parent_id);
|
|
CREATE INDEX idx_accounts_type_id ON financial.accounts(account_type_id);
|
|
|
|
-- Journals
|
|
CREATE INDEX idx_journals_tenant_id ON financial.journals(tenant_id);
|
|
CREATE INDEX idx_journals_company_id ON financial.journals(company_id);
|
|
CREATE INDEX idx_journals_code ON financial.journals(code);
|
|
CREATE INDEX idx_journals_type ON financial.journals(journal_type);
|
|
|
|
-- Fiscal Years
|
|
CREATE INDEX idx_fiscal_years_tenant_id ON financial.fiscal_years(tenant_id);
|
|
CREATE INDEX idx_fiscal_years_company_id ON financial.fiscal_years(company_id);
|
|
CREATE INDEX idx_fiscal_years_dates ON financial.fiscal_years(start_date, end_date);
|
|
|
|
-- Fiscal Periods
|
|
CREATE INDEX idx_fiscal_periods_tenant_id ON financial.fiscal_periods(tenant_id);
|
|
CREATE INDEX idx_fiscal_periods_year_id ON financial.fiscal_periods(fiscal_year_id);
|
|
CREATE INDEX idx_fiscal_periods_dates ON financial.fiscal_periods(start_date, end_date);
|
|
|
|
-- Journal Entries
|
|
CREATE INDEX idx_journal_entries_tenant_id ON financial.journal_entries(tenant_id);
|
|
CREATE INDEX idx_journal_entries_company_id ON financial.journal_entries(company_id);
|
|
CREATE INDEX idx_journal_entries_journal_id ON financial.journal_entries(journal_id);
|
|
CREATE INDEX idx_journal_entries_date ON financial.journal_entries(date);
|
|
CREATE INDEX idx_journal_entries_status ON financial.journal_entries(status);
|
|
|
|
-- Journal Entry Lines
|
|
CREATE INDEX idx_journal_entry_lines_entry_id ON financial.journal_entry_lines(entry_id);
|
|
CREATE INDEX idx_journal_entry_lines_account_id ON financial.journal_entry_lines(account_id);
|
|
CREATE INDEX idx_journal_entry_lines_partner_id ON financial.journal_entry_lines(partner_id);
|
|
CREATE INDEX idx_journal_entry_lines_analytic ON financial.journal_entry_lines(analytic_account_id);
|
|
|
|
-- Taxes
|
|
CREATE INDEX idx_taxes_tenant_id ON financial.taxes(tenant_id);
|
|
CREATE INDEX idx_taxes_company_id ON financial.taxes(company_id);
|
|
CREATE INDEX idx_taxes_code ON financial.taxes(code);
|
|
CREATE INDEX idx_taxes_type ON financial.taxes(tax_type);
|
|
CREATE INDEX idx_taxes_active ON financial.taxes(active) WHERE active = TRUE;
|
|
|
|
-- Payment Terms
|
|
CREATE INDEX idx_payment_terms_tenant_id ON financial.payment_terms(tenant_id);
|
|
CREATE INDEX idx_payment_terms_company_id ON financial.payment_terms(company_id);
|
|
|
|
-- Invoices
|
|
CREATE INDEX idx_invoices_tenant_id ON financial.invoices(tenant_id);
|
|
CREATE INDEX idx_invoices_company_id ON financial.invoices(company_id);
|
|
CREATE INDEX idx_invoices_partner_id ON financial.invoices(partner_id);
|
|
CREATE INDEX idx_invoices_type ON financial.invoices(invoice_type);
|
|
CREATE INDEX idx_invoices_status ON financial.invoices(status);
|
|
CREATE INDEX idx_invoices_number ON financial.invoices(number);
|
|
CREATE INDEX idx_invoices_date ON financial.invoices(invoice_date);
|
|
CREATE INDEX idx_invoices_due_date ON financial.invoices(due_date);
|
|
|
|
-- Invoice Lines
|
|
CREATE INDEX idx_invoice_lines_invoice_id ON financial.invoice_lines(invoice_id);
|
|
CREATE INDEX idx_invoice_lines_product_id ON financial.invoice_lines(product_id);
|
|
CREATE INDEX idx_invoice_lines_account_id ON financial.invoice_lines(account_id);
|
|
|
|
-- Payments
|
|
CREATE INDEX idx_payments_tenant_id ON financial.payments(tenant_id);
|
|
CREATE INDEX idx_payments_company_id ON financial.payments(company_id);
|
|
CREATE INDEX idx_payments_partner_id ON financial.payments(partner_id);
|
|
CREATE INDEX idx_payments_type ON financial.payments(payment_type);
|
|
CREATE INDEX idx_payments_status ON financial.payments(status);
|
|
CREATE INDEX idx_payments_date ON financial.payments(payment_date);
|
|
|
|
-- Payment Invoice
|
|
CREATE INDEX idx_payment_invoice_payment_id ON financial.payment_invoice(payment_id);
|
|
CREATE INDEX idx_payment_invoice_invoice_id ON financial.payment_invoice(invoice_id);
|
|
|
|
-- Bank Accounts
|
|
CREATE INDEX idx_bank_accounts_tenant_id ON financial.bank_accounts(tenant_id);
|
|
CREATE INDEX idx_bank_accounts_company_id ON financial.bank_accounts(company_id);
|
|
CREATE INDEX idx_bank_accounts_partner_id ON financial.bank_accounts(partner_id);
|
|
|
|
-- Reconciliations
|
|
CREATE INDEX idx_reconciliations_tenant_id ON financial.reconciliations(tenant_id);
|
|
CREATE INDEX idx_reconciliations_company_id ON financial.reconciliations(company_id);
|
|
CREATE INDEX idx_reconciliations_bank_account_id ON financial.reconciliations(bank_account_id);
|
|
CREATE INDEX idx_reconciliations_dates ON financial.reconciliations(start_date, end_date);
|
|
|
|
-- =====================================================
|
|
-- FUNCTIONS
|
|
-- =====================================================
|
|
|
|
-- Función: validate_entry_balance
|
|
-- Valida que un asiento esté balanceado (debit = credit)
|
|
CREATE OR REPLACE FUNCTION financial.validate_entry_balance(p_entry_id UUID)
|
|
RETURNS BOOLEAN AS $$
|
|
DECLARE
|
|
v_total_debit DECIMAL;
|
|
v_total_credit DECIMAL;
|
|
BEGIN
|
|
SELECT
|
|
COALESCE(SUM(debit), 0),
|
|
COALESCE(SUM(credit), 0)
|
|
INTO v_total_debit, v_total_credit
|
|
FROM financial.journal_entry_lines
|
|
WHERE entry_id = p_entry_id;
|
|
|
|
IF v_total_debit != v_total_credit THEN
|
|
RAISE EXCEPTION 'Journal entry % is not balanced: debit=% credit=%',
|
|
p_entry_id, v_total_debit, v_total_credit;
|
|
END IF;
|
|
|
|
RETURN TRUE;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION financial.validate_entry_balance IS 'Valida que un asiento contable esté balanceado (debit = credit)';
|
|
|
|
-- Función: post_journal_entry
|
|
-- Contabiliza un asiento (cambiar estado a posted)
|
|
CREATE OR REPLACE FUNCTION financial.post_journal_entry(p_entry_id UUID)
|
|
RETURNS VOID AS $$
|
|
BEGIN
|
|
-- Validar balance
|
|
PERFORM financial.validate_entry_balance(p_entry_id);
|
|
|
|
-- Actualizar estado
|
|
UPDATE financial.journal_entries
|
|
SET status = 'posted',
|
|
posted_at = CURRENT_TIMESTAMP,
|
|
posted_by = get_current_user_id()
|
|
WHERE id = p_entry_id
|
|
AND status = 'draft';
|
|
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION 'Journal entry % not found or already posted', p_entry_id;
|
|
END IF;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION financial.post_journal_entry IS 'Contabiliza un asiento contable después de validar su balance';
|
|
|
|
-- Función: calculate_invoice_totals
|
|
-- Calcula los totales de una factura a partir de sus líneas
|
|
CREATE OR REPLACE FUNCTION financial.calculate_invoice_totals(p_invoice_id UUID)
|
|
RETURNS VOID AS $$
|
|
DECLARE
|
|
v_amount_untaxed DECIMAL;
|
|
v_amount_tax DECIMAL;
|
|
v_amount_total DECIMAL;
|
|
BEGIN
|
|
SELECT
|
|
COALESCE(SUM(amount_untaxed), 0),
|
|
COALESCE(SUM(amount_tax), 0),
|
|
COALESCE(SUM(amount_total), 0)
|
|
INTO v_amount_untaxed, v_amount_tax, v_amount_total
|
|
FROM financial.invoice_lines
|
|
WHERE invoice_id = p_invoice_id;
|
|
|
|
UPDATE financial.invoices
|
|
SET amount_untaxed = v_amount_untaxed,
|
|
amount_tax = v_amount_tax,
|
|
amount_total = v_amount_total,
|
|
amount_residual = v_amount_total - amount_paid,
|
|
updated_at = CURRENT_TIMESTAMP,
|
|
updated_by = get_current_user_id()
|
|
WHERE id = p_invoice_id;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION financial.calculate_invoice_totals IS 'Calcula los totales de una factura a partir de sus líneas';
|
|
|
|
-- Función: update_invoice_paid_amount
|
|
-- Actualiza el monto pagado de una factura
|
|
CREATE OR REPLACE FUNCTION financial.update_invoice_paid_amount(p_invoice_id UUID)
|
|
RETURNS VOID AS $$
|
|
DECLARE
|
|
v_amount_paid DECIMAL;
|
|
BEGIN
|
|
SELECT COALESCE(SUM(amount), 0)
|
|
INTO v_amount_paid
|
|
FROM financial.payment_invoice
|
|
WHERE invoice_id = p_invoice_id;
|
|
|
|
UPDATE financial.invoices
|
|
SET amount_paid = v_amount_paid,
|
|
amount_residual = amount_total - v_amount_paid,
|
|
status = CASE
|
|
WHEN v_amount_paid >= amount_total THEN 'paid'::financial.invoice_status
|
|
WHEN v_amount_paid > 0 THEN 'open'::financial.invoice_status
|
|
ELSE status
|
|
END
|
|
WHERE id = p_invoice_id;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
COMMENT ON FUNCTION financial.update_invoice_paid_amount IS 'Actualiza el monto pagado y estado de una factura';
|
|
|
|
-- =====================================================
|
|
-- TRIGGERS
|
|
-- =====================================================
|
|
|
|
-- Trigger: Actualizar updated_at
|
|
CREATE TRIGGER trg_accounts_updated_at
|
|
BEFORE UPDATE ON financial.accounts
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auth.update_updated_at_column();
|
|
|
|
CREATE TRIGGER trg_journals_updated_at
|
|
BEFORE UPDATE ON financial.journals
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auth.update_updated_at_column();
|
|
|
|
CREATE TRIGGER trg_fiscal_years_updated_at
|
|
BEFORE UPDATE ON financial.fiscal_years
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auth.update_updated_at_column();
|
|
|
|
CREATE TRIGGER trg_fiscal_periods_updated_at
|
|
BEFORE UPDATE ON financial.fiscal_periods
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auth.update_updated_at_column();
|
|
|
|
CREATE TRIGGER trg_journal_entries_updated_at
|
|
BEFORE UPDATE ON financial.journal_entries
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auth.update_updated_at_column();
|
|
|
|
CREATE TRIGGER trg_taxes_updated_at
|
|
BEFORE UPDATE ON financial.taxes
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auth.update_updated_at_column();
|
|
|
|
CREATE TRIGGER trg_payment_terms_updated_at
|
|
BEFORE UPDATE ON financial.payment_terms
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auth.update_updated_at_column();
|
|
|
|
CREATE TRIGGER trg_invoices_updated_at
|
|
BEFORE UPDATE ON financial.invoices
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auth.update_updated_at_column();
|
|
|
|
CREATE TRIGGER trg_payments_updated_at
|
|
BEFORE UPDATE ON financial.payments
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auth.update_updated_at_column();
|
|
|
|
CREATE TRIGGER trg_bank_accounts_updated_at
|
|
BEFORE UPDATE ON financial.bank_accounts
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auth.update_updated_at_column();
|
|
|
|
CREATE TRIGGER trg_reconciliations_updated_at
|
|
BEFORE UPDATE ON financial.reconciliations
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION auth.update_updated_at_column();
|
|
|
|
-- Trigger: Validar balance antes de contabilizar
|
|
CREATE OR REPLACE FUNCTION financial.trg_validate_entry_before_post()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
IF NEW.status = 'posted' AND OLD.status = 'draft' THEN
|
|
PERFORM financial.validate_entry_balance(NEW.id);
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER trg_journal_entries_validate_balance
|
|
BEFORE UPDATE OF status ON financial.journal_entries
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION financial.trg_validate_entry_before_post();
|
|
|
|
-- Trigger: Actualizar totales de factura al cambiar líneas
|
|
CREATE OR REPLACE FUNCTION financial.trg_update_invoice_totals()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
IF TG_OP = 'DELETE' THEN
|
|
PERFORM financial.calculate_invoice_totals(OLD.invoice_id);
|
|
ELSE
|
|
PERFORM financial.calculate_invoice_totals(NEW.invoice_id);
|
|
END IF;
|
|
RETURN NULL;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER trg_invoice_lines_update_totals
|
|
AFTER INSERT OR UPDATE OR DELETE ON financial.invoice_lines
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION financial.trg_update_invoice_totals();
|
|
|
|
-- Trigger: Actualizar monto pagado al conciliar
|
|
CREATE OR REPLACE FUNCTION financial.trg_update_invoice_paid()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
IF TG_OP = 'DELETE' THEN
|
|
PERFORM financial.update_invoice_paid_amount(OLD.invoice_id);
|
|
ELSE
|
|
PERFORM financial.update_invoice_paid_amount(NEW.invoice_id);
|
|
END IF;
|
|
RETURN NULL;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER trg_payment_invoice_update_paid
|
|
AFTER INSERT OR UPDATE OR DELETE ON financial.payment_invoice
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION financial.trg_update_invoice_paid();
|
|
|
|
-- =====================================================
|
|
-- TRACKING AUTOMÁTICO (mail.thread pattern)
|
|
-- =====================================================
|
|
|
|
-- Trigger: Tracking automático para facturas
|
|
CREATE TRIGGER track_invoice_changes
|
|
AFTER INSERT OR UPDATE OR DELETE ON financial.invoices
|
|
FOR EACH ROW EXECUTE FUNCTION system.track_field_changes();
|
|
|
|
COMMENT ON TRIGGER track_invoice_changes ON financial.invoices IS
|
|
'Registra automáticamente cambios en facturas (estado, monto, cliente, fechas)';
|
|
|
|
-- Trigger: Tracking automático para asientos contables
|
|
CREATE TRIGGER track_journal_entry_changes
|
|
AFTER INSERT OR UPDATE OR DELETE ON financial.journal_entries
|
|
FOR EACH ROW EXECUTE FUNCTION system.track_field_changes();
|
|
|
|
COMMENT ON TRIGGER track_journal_entry_changes ON financial.journal_entries IS
|
|
'Registra automáticamente cambios en asientos contables (estado, fecha, diario)';
|
|
|
|
-- =====================================================
|
|
-- ROW LEVEL SECURITY (RLS)
|
|
-- =====================================================
|
|
|
|
ALTER TABLE financial.accounts ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE financial.journals ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE financial.fiscal_years ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE financial.fiscal_periods ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE financial.journal_entries ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE financial.taxes ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE financial.payment_terms ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE financial.invoices ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE financial.payments ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE financial.bank_accounts ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE financial.reconciliations ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY tenant_isolation_accounts ON financial.accounts
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
CREATE POLICY tenant_isolation_journals ON financial.journals
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
CREATE POLICY tenant_isolation_fiscal_years ON financial.fiscal_years
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
CREATE POLICY tenant_isolation_fiscal_periods ON financial.fiscal_periods
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
CREATE POLICY tenant_isolation_journal_entries ON financial.journal_entries
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
CREATE POLICY tenant_isolation_taxes ON financial.taxes
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
CREATE POLICY tenant_isolation_payment_terms ON financial.payment_terms
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
CREATE POLICY tenant_isolation_invoices ON financial.invoices
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
CREATE POLICY tenant_isolation_payments ON financial.payments
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
CREATE POLICY tenant_isolation_bank_accounts ON financial.bank_accounts
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
CREATE POLICY tenant_isolation_reconciliations ON financial.reconciliations
|
|
USING (tenant_id = get_current_tenant_id());
|
|
|
|
-- =====================================================
|
|
-- SEED DATA
|
|
-- =====================================================
|
|
|
|
-- Tipos de cuenta estándar
|
|
INSERT INTO financial.account_types (code, name, account_type, description) VALUES
|
|
('ASSET_CASH', 'Cash and Cash Equivalents', 'asset', 'Efectivo y equivalentes'),
|
|
('ASSET_RECEIVABLE', 'Accounts Receivable', 'asset', 'Cuentas por cobrar'),
|
|
('ASSET_CURRENT', 'Current Assets', 'asset', 'Activos circulantes'),
|
|
('ASSET_FIXED', 'Fixed Assets', 'asset', 'Activos fijos'),
|
|
('LIABILITY_PAYABLE', 'Accounts Payable', 'liability', 'Cuentas por pagar'),
|
|
('LIABILITY_CURRENT', 'Current Liabilities', 'liability', 'Pasivos circulantes'),
|
|
('LIABILITY_LONG', 'Long-term Liabilities', 'liability', 'Pasivos a largo plazo'),
|
|
('EQUITY_CAPITAL', 'Capital', 'equity', 'Capital social'),
|
|
('EQUITY_RETAINED', 'Retained Earnings', 'equity', 'Utilidades retenidas'),
|
|
('REVENUE_SALES', 'Sales Revenue', 'revenue', 'Ingresos por ventas'),
|
|
('REVENUE_OTHER', 'Other Revenue', 'revenue', 'Otros ingresos'),
|
|
('EXPENSE_COGS', 'Cost of Goods Sold', 'expense', 'Costo de ventas'),
|
|
('EXPENSE_OPERATING', 'Operating Expenses', 'expense', 'Gastos operativos'),
|
|
('EXPENSE_ADMIN', 'Administrative Expenses', 'expense', 'Gastos administrativos')
|
|
ON CONFLICT (code) DO NOTHING;
|
|
|
|
-- =====================================================
|
|
-- COMENTARIOS
|
|
-- =====================================================
|
|
|
|
COMMENT ON SCHEMA financial IS 'Schema de contabilidad, facturas, pagos y finanzas';
|
|
COMMENT ON TABLE financial.account_types IS 'Tipos de cuentas contables (asset, liability, equity, revenue, expense)';
|
|
COMMENT ON TABLE financial.accounts IS 'Plan de cuentas contables';
|
|
COMMENT ON TABLE financial.journals IS 'Diarios contables (ventas, compras, bancos, etc.)';
|
|
COMMENT ON TABLE financial.fiscal_years IS 'Años fiscales';
|
|
COMMENT ON TABLE financial.fiscal_periods IS 'Períodos fiscales (meses)';
|
|
COMMENT ON TABLE financial.journal_entries IS 'Asientos contables';
|
|
COMMENT ON TABLE financial.journal_entry_lines IS 'Líneas de asientos contables (partida doble)';
|
|
COMMENT ON TABLE financial.taxes IS 'Impuestos (IVA, retenciones, etc.)';
|
|
COMMENT ON TABLE financial.payment_terms IS 'Términos de pago (inmediato, 30 días, etc.)';
|
|
COMMENT ON TABLE financial.invoices IS 'Facturas de cliente y proveedor';
|
|
COMMENT ON TABLE financial.invoice_lines IS 'Líneas de factura';
|
|
COMMENT ON TABLE financial.payments IS 'Pagos y cobros';
|
|
COMMENT ON TABLE financial.payment_invoice IS 'Conciliación de pagos con facturas';
|
|
COMMENT ON TABLE financial.bank_accounts IS 'Cuentas bancarias de la empresa y partners';
|
|
COMMENT ON TABLE financial.reconciliations IS 'Conciliaciones bancarias';
|
|
|
|
-- =====================================================
|
|
-- FIN DEL SCHEMA FINANCIAL
|
|
-- =====================================================
|