erp-core/docs/04-modelado/domain-models/financial-domain.md

349 lines
9.2 KiB
Markdown

# MODELO DE DOMINIO: Financiero
**Módulos:** MGN-004 (Financiero Básico)
**Fecha:** 2025-11-24
**Referencia Odoo:** account
**Referencia Gamilit:** financial_management schema
---
## Diagrama de Entidades (Texto UML)
```
[Account]
- id: UUID (PK)
- tenant_id: UUID (FK)
- company_id: UUID (FK)
- code: String
- name: String
- account_type: ENUM (asset, liability, equity, income, expense)
- parent_id: UUID (FK self)
- currency_id: UUID (FK)
1 <----> * [JournalEntry]
[Journal]
- id: UUID (PK)
- tenant_id: UUID (FK)
- company_id: UUID (FK)
- name: String
- code: String
- type: ENUM (sales, purchase, bank, cash, general)
1 <----> * [JournalEntry]
[JournalEntry]
- id: UUID (PK)
- tenant_id: UUID (FK)
- company_id: UUID (FK)
- journal_id: UUID (FK)
- name: String
- date: Date
- status: ENUM (draft, posted, cancelled)
1 <----> * [JournalLine]
[JournalLine]
- id: UUID (PK)
- entry_id: UUID (FK)
- account_id: UUID (FK)
- partner_id: UUID (FK)
- debit: Decimal
- credit: Decimal
- analytic_account_id: UUID (FK)
- description: String
[Invoice]
- id: UUID (PK)
- tenant_id: UUID (FK)
- company_id: UUID (FK)
- partner_id: UUID (FK)
- invoice_type: ENUM (customer, vendor)
- number: String
- date: Date
- due_date: Date
- status: ENUM (draft, open, paid, cancelled)
- amount_total: Decimal
- amount_paid: Decimal
- journal_entry_id: UUID (FK)
1 <----> * [InvoiceLine]
* <----> * [Payment] (through PaymentInvoice)
[InvoiceLine]
- id: UUID (PK)
- invoice_id: UUID (FK)
- product_id: UUID (FK)
- description: String
- quantity: Decimal
- price_unit: Decimal
- tax_ids: UUID[] (FK array)
- subtotal: Decimal
- total: Decimal
- analytic_account_id: UUID (FK)
[Payment]
- id: UUID (PK)
- tenant_id: UUID (FK)
- company_id: UUID (FK)
- partner_id: UUID (FK)
- payment_type: ENUM (inbound, outbound)
- amount: Decimal
- date: Date
- payment_method: ENUM (cash, bank_transfer, check, card)
- journal_entry_id: UUID (FK)
* <----> * [Invoice] (through PaymentInvoice)
[PaymentInvoice] (many-to-many)
- payment_id: UUID (FK)
- invoice_id: UUID (FK)
- amount: Decimal
[Tax]
- id: UUID (PK)
- tenant_id: UUID (FK)
- company_id: UUID (FK)
- name: String
- code: String
- rate: Decimal
- type: ENUM (sales, purchase, all)
- account_id: UUID (FK)
```
## Entidades Principales
### 1. Account (Cuenta Contable)
**Descripción:** Cuenta del plan de cuentas contables.
**Atributos:**
- `id`: UUID
- `code`: Código de cuenta (ej: "110.01.001")
- `name`: Nombre (ej: "Bancos - BBVA")
- `account_type`: Tipo (asset, liability, equity, income, expense)
- `parent_id`: Cuenta padre (jerarquía)
- `currency_id`: Moneda
**Relaciones:**
- 1 Account → N Journal Lines
- N Accounts → 1 Company
**Patrón Odoo:** account.account
**Validaciones:**
- code único por company
- Cuentas tipo 'view' no pueden tener movimientos
### 2. Journal (Diario Contable)
**Descripción:** Diario para agrupar asientos contables por tipo.
**Atributos:**
- `id`: UUID
- `name`: Nombre del diario
- `code`: Código (ej: "SALES", "BANK")
- `type`: Tipo (sales, purchase, bank, cash, general)
**Relaciones:**
- 1 Journal → N Journal Entries
**Patrón Odoo:** account.journal
**Diarios estándar:**
- Sales Journal (facturas de cliente)
- Purchase Journal (facturas de proveedor)
- Bank Journal (movimientos bancarios)
- Cash Journal (efectivo)
- Miscellaneous Journal (asientos manuales)
### 3. JournalEntry (Asiento Contable)
**Descripción:** Asiento contable con múltiples líneas (débito/crédito).
**Atributos:**
- `id`: UUID
- `journal_id`: Diario asociado
- `name`: Número de asiento
- `date`: Fecha del asiento
- `status`: draft, posted, cancelled
**Relaciones:**
- 1 JournalEntry → N JournalLines
- N JournalEntries → 1 Journal
**Patrón Odoo:** account.move
**Regla fundamental:** SUM(debit) = SUM(credit)
### 4. JournalLine (Línea de Asiento)
**Descripción:** Línea individual de un asiento (débito o crédito).
**Atributos:**
- `id`: UUID
- `entry_id`: Asiento propietario
- `account_id`: Cuenta contable
- `partner_id`: Partner (cliente/proveedor)
- `debit`: Monto débito
- `credit`: Monto crédito
- `analytic_account_id`: Cuenta analítica (opcional)
**Relaciones:**
- N JournalLines → 1 JournalEntry
- N JournalLines → 1 Account
**Patrón Odoo:** account.move.line
**Validación:** En cada línea, debit XOR credit (no ambos)
### 5. Invoice (Factura)
**Descripción:** Factura de cliente o proveedor.
**Atributos:**
- `id`: UUID
- `partner_id`: Cliente/Proveedor
- `invoice_type`: customer, vendor
- `number`: Número de factura
- `date`: Fecha de emisión
- `due_date`: Fecha de vencimiento
- `status`: draft, open, paid, cancelled
- `amount_total`: Monto total
- `amount_paid`: Monto pagado
**Relaciones:**
- 1 Invoice → N InvoiceLines
- 1 Invoice → 1 JournalEntry (al validar)
- N Invoices ←→ N Payments
**Patrón Odoo:** account.move (type=invoice)
**Estados:**
- draft: Borrador (editable)
- open: Validada (genera asiento)
- paid: Pagada completamente
- cancelled: Cancelada
### 6. InvoiceLine (Línea de Factura)
**Descripción:** Línea de producto/servicio en factura.
**Atributos:**
- `id`: UUID
- `invoice_id`: Factura propietaria
- `product_id`: Producto/servicio
- `description`: Descripción
- `quantity`: Cantidad
- `price_unit`: Precio unitario
- `tax_ids`: Impuestos aplicados
- `subtotal`: Subtotal sin impuestos
- `total`: Total con impuestos
**Relaciones:**
- N InvoiceLines → 1 Invoice
**Patrón Odoo:** account.move.line (con invoice_line_id)
**Cálculo:** total = (quantity * price_unit) + taxes
### 7. Payment (Pago)
**Descripción:** Registro de pago de cliente o a proveedor.
**Atributos:**
- `id`: UUID
- `partner_id`: Cliente/Proveedor
- `payment_type`: inbound (cliente), outbound (proveedor)
- `amount`: Monto del pago
- `date`: Fecha del pago
- `payment_method`: cash, bank_transfer, check, card
- `journal_entry_id`: Asiento generado
**Relaciones:**
- N Payments ←→ N Invoices (reconciliación)
- 1 Payment → 1 JournalEntry
**Patrón Odoo:** account.payment
**Flujo:**
1. Crear payment
2. Validar payment → genera journal entry
3. Reconciliar payment con invoice(s)
### 8. Tax (Impuesto)
**Descripción:** Configuración de impuestos (IVA, retenciones).
**Atributos:**
- `id`: UUID
- `name`: Nombre (ej: "IVA 16%")
- `code`: Código (ej: "IVA16")
- `rate`: Tasa (0.16 para 16%)
- `type`: sales, purchase, all
- `account_id`: Cuenta contable para impuesto
**Relaciones:**
- N Taxes → N InvoiceLines
**Patrón Odoo:** account.tax
**Impuestos comunes México:**
- IVA 16% (ventas y compras)
- IVA 8% (zona frontera)
- Retención IVA 10.67%
- Retención ISR 10%
## Reglas de Negocio
### RN-FIN-001: Balance de Asientos
- TODO asiento debe cumplir: SUM(debit) = SUM(credit)
- Validación obligatoria antes de posted
### RN-FIN-002: Asientos Inmutables
- Asientos con status=posted NO pueden editarse
- Para corregir: crear asiento de reversa
### RN-FIN-003: Generación Automática de Asientos
- Validar factura → genera journal entry automáticamente
- Validar pago → genera journal entry automáticamente
### RN-FIN-004: Multi-Moneda
- Transacciones en moneda extranjera se convierten a moneda de company
- Usar tasa de cambio del día de la transacción
- Gain/Loss se registra en cuenta especial
### RN-FIN-005: Conciliación de Pagos
- Payment puede aplicarse a múltiples invoices (parcial)
- Invoice puede recibir múltiples payments
- amount_paid se actualiza automáticamente
## Casos de Uso Principales
1. **UC-FIN-001:** Contador crea asiento contable manual
2. **UC-FIN-002:** Usuario crea factura de cliente
3. **UC-FIN-003:** Sistema genera asiento al validar factura
4. **UC-FIN-004:** Usuario registra pago de cliente
5. **UC-FIN-005:** Usuario concilia pago con facturas
6. **UC-FIN-006:** Contador genera Balance General
7. **UC-FIN-007:** Contador genera Estado de Resultados
8. **UC-FIN-008:** Usuario crea factura en USD (empresa en MXN)
## Validaciones y Constraints
```sql
-- Asiento balanceado
CHECK (SUM(debit) = SUM(credit) per entry_id)
-- Debit XOR Credit (no ambos)
CHECK ((debit > 0 AND credit = 0) OR (credit > 0 AND debit = 0))
-- Invoice number único por company y tipo
UNIQUE (tenant_id, company_id, invoice_type, number)
-- Status transitions válidos
-- (implementar con state machine)
```
## Índices Requeridos
```sql
CREATE INDEX idx_accounts_company_id ON financial.accounts(company_id);
CREATE INDEX idx_accounts_code ON financial.accounts(code);
CREATE INDEX idx_journal_entries_company_id ON financial.journal_entries(company_id);
CREATE INDEX idx_journal_entries_date ON financial.journal_entries(date);
CREATE INDEX idx_journal_lines_account_id ON financial.journal_lines(account_id);
CREATE INDEX idx_invoices_partner_id ON financial.invoices(partner_id);
CREATE INDEX idx_invoices_status ON financial.invoices(status);
CREATE INDEX idx_payments_partner_id ON financial.payments(partner_id);
```
## Referencias
- [ALCANCE-POR-MODULO.md - MGN-004](../../01-definicion-modulos/ALCANCE-POR-MODULO.md#mgn-004)
- [ADR-007: Database Design](../../adr/ADR-007-database-design.md)
- [odoo-account-analysis.md](../../00-analisis-referencias/odoo/odoo-account-analysis.md)