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