# DOMAIN MODEL: Finance Context

**Version:** 1.0.0
**Fecha:** 2025-12-05
**Modulos:** MAE-014

---

## Descripcion

El contexto de Finance gestiona toda la contabilidad y control financiero integrado con proyectos de construccion. Incluye libro mayor, cuentas por pagar/cobrar, flujo de efectivo y conciliacion bancaria.

---

## Agregados

### 1. Accounting Aggregate

```
AccountingEntry (Aggregate Root)
|
+-- EntryLine (Entity)
|   +-- Account (Reference)
|   +-- CostCenter (Reference)
|
+-- EntryStatus (Value Object)
```

#### AccountingEntry (Root)
```typescript
interface AccountingEntry {
  id: UUID;
  tenantId: UUID;

  entryNumber: string;
  entryType: EntryType;
  entryDate: Date;

  description: string;
  reference?: string;

  // Source
  sourceModule?: string;  // purchases, estimations, payroll
  sourceId?: UUID;
  sourceReference?: string;

  // Project link
  projectId?: UUID;
  costCenterId?: UUID;

  // Totals
  totalDebit: Money;
  totalCredit: Money;
  isBalanced: boolean;

  // Status
  status: EntryStatus;
  postedAt?: Timestamp;
  postedBy?: UUID;

  // Period
  fiscalYear: number;
  fiscalPeriod: number;

  lines: EntryLine[];
}

enum EntryType {
  INCOME = 'income',
  EXPENSE = 'expense',
  JOURNAL = 'journal',
  TRANSFER = 'transfer',
  ADJUSTMENT = 'adjustment',
  OPENING = 'opening',
  CLOSING = 'closing'
}

enum EntryStatus {
  DRAFT = 'draft',
  PENDING = 'pending',
  POSTED = 'posted',
  CANCELLED = 'cancelled'
}
```

#### EntryLine (Entity)
```typescript
interface EntryLine {
  id: UUID;
  entryId: UUID;
  lineNumber: number;

  // Account
  accountId: UUID;
  accountCode: string;

  description?: string;

  // Amounts
  debitAmount: Money;
  creditAmount: Money;

  // Attribution
  costCenterId?: UUID;
  projectId?: UUID;

  // Partner
  partnerId?: UUID;
  partnerName?: string;
}
```

---

### 2. AccountsPayable Aggregate

```
AccountPayable (Aggregate Root)
|
+-- APPayment (Entity)
|
+-- PaymentSchedule (Value Object)
```

#### AccountPayable (Root)
```typescript
interface AccountPayable {
  id: UUID;
  tenantId: UUID;

  documentNumber: string;
  documentType: DocumentType;

  // Supplier
  supplierId: UUID;
  supplierName: string;
  supplierRfc?: string;

  // Source
  purchaseOrderId?: UUID;
  contractId?: UUID;

  // Amounts
  subtotal: Money;
  taxAmount: Money;
  retentionAmount: Money;
  totalAmount: Money;
  paidAmount: Money;
  balance: Money;  // totalAmount - paidAmount

  // Dates
  documentDate: Date;
  dueDate: Date;
  receivedDate?: Date;

  // Project
  projectId?: UUID;
  costCenterId?: UUID;

  // Status
  status: PaymentStatus;

  // Linked entry
  accountingEntryId?: UUID;

  payments: APPayment[];
}

enum PaymentStatus {
  PENDING = 'pending',
  PARTIAL = 'partial',
  PAID = 'paid',
  OVERDUE = 'overdue',
  CANCELLED = 'cancelled'
}
```

#### APPayment (Entity)
```typescript
interface APPayment {
  id: UUID;
  payableId: UUID;

  paymentNumber: string;
  paymentDate: Date;
  amount: Money;

  paymentMethod: PaymentMethod;
  bankAccountId?: UUID;
  reference?: string;

  status: string;
  accountingEntryId?: UUID;
}

enum PaymentMethod {
  CASH = 'cash',
  CHECK = 'check',
  TRANSFER = 'transfer',
  CARD = 'card',
  DEPOSIT = 'deposit',
  OTHER = 'other'
}
```

---

### 3. AccountsReceivable Aggregate

```
AccountReceivable (Aggregate Root)
|
+-- ARCollection (Entity)
|
+-- CollectionReminder (Value Object)
```

#### AccountReceivable (Root)
```typescript
interface AccountReceivable {
  id: UUID;
  tenantId: UUID;

  documentNumber: string;
  documentType: string;

  // Customer
  customerId: UUID;
  customerName: string;
  customerRfc?: string;

  // Source
  estimationId?: UUID;
  saleOrderId?: UUID;
  contractId?: UUID;

  // Amounts
  subtotal: Money;
  taxAmount: Money;
  retentionAmount: Money;
  totalAmount: Money;
  collectedAmount: Money;
  balance: Money;  // totalAmount - collectedAmount

  // Dates
  documentDate: Date;
  dueDate: Date;

  // Project
  projectId?: UUID;

  // Status
  status: PaymentStatus;

  accountingEntryId?: UUID;

  collections: ARCollection[];
}
```

#### ARCollection (Entity)
```typescript
interface ARCollection {
  id: UUID;
  receivableId: UUID;

  collectionNumber: string;
  collectionDate: Date;
  amount: Money;

  paymentMethod: PaymentMethod;
  bankAccountId?: UUID;
  reference?: string;

  status: string;
  accountingEntryId?: UUID;
}
```

---

### 4. CashFlow Aggregate

```
CashFlowProjection (Aggregate Root)
|
+-- CashFlowItem (Entity)
|
+-- Variance (Value Object)
```

#### CashFlowProjection (Root)
```typescript
interface CashFlowProjection {
  id: UUID;
  tenantId: UUID;
  projectId?: UUID;

  periodDate: Date;
  periodType: PeriodType;

  // Projected Income
  projectedIncome: Money;
  projectedCollections: Money;

  // Projected Expenses
  projectedExpenses: Money;
  projectedPayments: Money;

  // Actual
  actualIncome: Money;
  actualExpenses: Money;

  // Balances
  openingBalance: Money;
  projectedClosing: Money;
  actualClosing?: Money;

  cashFlowType: CashFlowType;

  items: CashFlowItem[];
}

enum PeriodType {
  DAILY = 'daily',
  WEEKLY = 'weekly',
  MONTHLY = 'monthly'
}

enum CashFlowType {
  OPERATING = 'operating',
  INVESTING = 'investing',
  FINANCING = 'financing'
}
```

#### CashFlowItem (Entity)
```typescript
interface CashFlowItem {
  id: UUID;
  projectionId: UUID;

  itemType: 'income' | 'expense';
  category?: string;

  description: string;

  sourceType?: string;  // estimation, purchase_order, contract, payroll
  sourceId?: UUID;

  projectedAmount: Money;
  actualAmount?: Money;

  expectedDate?: Date;
  actualDate?: Date;
}
```

---

### 5. BankReconciliation Aggregate

```
BankAccount (Aggregate Root)
|
+-- BankMovement (Entity)
|
+-- BankReconciliation (Entity)
```

#### BankAccount (Root)
```typescript
interface BankAccount {
  id: UUID;
  tenantId: UUID;

  accountNumber: string;
  clabe?: string;
  name: string;

  bankName: string;
  bankCode?: string;

  accountType?: string;  // checking, savings, credit
  currency: string;

  currentBalance: Money;
  availableBalance: Money;
  lastReconciledBalance?: Money;
  lastReconciledDate?: Date;

  ledgerAccountId?: UUID;
  projectId?: UUID;

  isActive: boolean;

  movements: BankMovement[];
}
```

#### BankMovement (Entity)
```typescript
interface BankMovement {
  id: UUID;
  bankAccountId: UUID;

  movementDate: Date;
  valueDate?: Date;
  reference?: string;
  description?: string;

  debitAmount: Money;
  creditAmount: Money;
  balanceAfter?: Money;

  // Bank source
  bankReference?: string;
  importBatchId?: UUID;

  // Reconciliation
  reconciliationStatus: ReconciliationStatus;
  reconciledWithId?: UUID;
  reconciledWithType?: string;  // ap_payment, ar_collection, entry_line
  reconciledAt?: Timestamp;
  reconciledBy?: UUID;
}

enum ReconciliationStatus {
  PENDING = 'pending',
  MATCHED = 'matched',
  PARTIAL = 'partial',
  UNMATCHED = 'unmatched'
}
```

---

## Value Objects

### Money
```typescript
interface Money {
  amount: number;
  currency: string;
}

class Money {
  static add(a: Money, b: Money): Money;
  static subtract(a: Money, b: Money): Money;
  static multiply(a: Money, factor: number): Money;
  static isPositive(m: Money): boolean;
  static isNegative(m: Money): boolean;
  static equals(a: Money, b: Money): boolean;
}
```

### AccountCode
```typescript
interface AccountCode {
  code: string;
  type: AccountType;
  nature: AccountNature;
  level: number;
}

enum AccountType {
  ASSET = 'asset',
  LIABILITY = 'liability',
  EQUITY = 'equity',
  INCOME = 'income',
  EXPENSE = 'expense'
}

enum AccountNature {
  DEBIT = 'debit',
  CREDIT = 'credit'
}
```

### FiscalPeriod
```typescript
interface FiscalPeriod {
  year: number;
  period: number;  // 1-12 for monthly
  isClosed: boolean;
}
```

---

## Domain Events

### Accounting Events
```typescript
interface EntryPosted {
  entryId: UUID;
  entryNumber: string;
  entryType: EntryType;
  totalAmount: Money;
  postedBy: UUID;
  timestamp: Timestamp;
}

interface PeriodClosed {
  fiscalYear: number;
  fiscalPeriod: number;
  closedBy: UUID;
  timestamp: Timestamp;
}
```

### AP/AR Events
```typescript
interface PayableCreated {
  payableId: UUID;
  supplierId: UUID;
  totalAmount: Money;
  dueDate: Date;
  timestamp: Timestamp;
}

interface PaymentMade {
  paymentId: UUID;
  payableId: UUID;
  amount: Money;
  remainingBalance: Money;
  timestamp: Timestamp;
}

interface CollectionReceived {
  collectionId: UUID;
  receivableId: UUID;
  amount: Money;
  remainingBalance: Money;
  timestamp: Timestamp;
}
```

### Bank Events
```typescript
interface MovementsImported {
  bankAccountId: UUID;
  batchId: UUID;
  movementsCount: number;
  totalDebits: Money;
  totalCredits: Money;
  timestamp: Timestamp;
}

interface ReconciliationCompleted {
  reconciliationId: UUID;
  bankAccountId: UUID;
  periodEnd: Date;
  isBalanced: boolean;
  difference: Money;
  timestamp: Timestamp;
}
```

---

## Business Rules

### Accounting Rules
1. Toda poliza debe estar balanceada (debitos = creditos)
2. No se puede modificar una poliza en status 'posted'
3. Los periodos cerrados no permiten nuevas polizas
4. Las cuentas de nivel 1 no permiten movimientos directos

### AP/AR Rules
1. El saldo no puede ser negativo
2. Un pago no puede exceder el saldo pendiente
3. Las CxP vencidas deben generar alertas automaticas
4. Los pagos parciales cambian status a 'partial'

### Cash Flow Rules
1. La proyeccion debe coincidir con CxP/CxC pendientes
2. Varianza > 10% requiere justificacion
3. Proyecciones semanales son obligatorias

### Bank Rules
1. Solo movimientos conciliados afectan el libro
2. La conciliacion requiere diferencia = 0
3. Importacion de estados de cuenta es idempotente

---

## Invariantes

1. `Entry.totalDebit = Entry.totalCredit` (siempre)
2. `AccountPayable.balance = totalAmount - paidAmount`
3. `AccountReceivable.balance = totalAmount - collectedAmount`
4. `BankAccount.currentBalance = SUM(movements.credits) - SUM(movements.debits)`
5. `CashFlow.projectedClosing = openingBalance + income - expenses`

---

## Integraciones

### Con Project Context
- Estimaciones aprobadas -> CxC
- Ordenes de compra -> CxP
- Costos de proyecto -> Polizas

### Con Assets Context
- Depreciacion -> Polizas automaticas
- Mantenimiento -> CxP

### Con Documents Context
- Facturas digitales almacenadas
- Polizas exportadas a PDF

### Con ERP Externos
- SAP: Sincronizacion de polizas via RFC
- CONTPAQi: Export XML de polizas
- ASPEL: Export archivo plano

---

## Referencias

- [DDL-SPEC-finance.md](../database-design/schemas/DDL-SPEC-finance.md)
- [EPIC-MAE-014](../../08-epicas/EPIC-MAE-014-finanzas.md)

---

*Ultima actualizacion: 2025-12-05*
