erp-construccion/docs/04-modelado/domain-models/FINANCE-CONTEXT.md

628 lines
11 KiB
Markdown

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