# 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)
