# DOMAIN MODEL: Compliance Context (INFONAVIT)

**Version:** 1.0.0
**Fecha:** 2025-12-05
**Modulos:** MAI-011

---

## Descripcion

El contexto de Compliance gestiona el cumplimiento normativo para proyectos de vivienda bajo programas INFONAVIT. Incluye registro de proyectos en programas, checklists de requisitos, evidencias y auditorias.

---

## Agregados

### 1. Program Aggregate

```
InfonavitProgram (Aggregate Root)
|
+-- ProgramRequirement (Entity)
|   +-- EvidenceType (Value Object)
|
+-- RequirementCategory (Value Object)
```

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

  code: string;
  name: string;
  description?: string;
  programType: ProgramType;

  validFrom?: Date;
  validTo?: Date;

  isActive: boolean;
  requirementsCount: number;

  requirements: ProgramRequirement[];
}

enum ProgramType {
  EVC = 'evc',                    // Esquemas de Valor Compartido
  TRADITIONAL = 'traditional',    // Credito tradicional
  COFINAVIT = 'cofinavit',        // Credito mixto
  INFONAVIT_TOTAL = 'infonavit_total',  // Con subsidio
  APOYO_INFONAVIT = 'apoyo_infonavit',  // Solo subsidio
  MEJORAVIT = 'mejoravit',        // Mejora de vivienda
  UNAMOS_CREDITOS = 'unamos_creditos'   // Creditos combinados
}
```

#### ProgramRequirement (Entity)
```typescript
interface ProgramRequirement {
  id: UUID;
  programId: UUID;

  code: string;
  name: string;
  description?: string;

  category: RequirementCategory;
  subcategory?: string;

  // Evidence required
  evidenceRequired: string[];
  evidenceDescription?: string;

  sortOrder: number;
  parentId?: UUID;

  isMandatory: boolean;
  isActive: boolean;

  children: ProgramRequirement[];
}

enum RequirementCategory {
  TECHNICAL = 'technical',       // Requisitos tecnicos
  URBAN = 'urban',               // Requisitos urbanos
  SERVICES = 'services',         // Requisitos de servicios
  LEGAL = 'legal',               // Requisitos legales
  ENVIRONMENTAL = 'environmental' // Requisitos ambientales
}
```

---

### 2. ProjectCompliance Aggregate

```
ProjectProgram (Aggregate Root)
|
+-- ComplianceItem (Entity)
|   +-- ComplianceEvidence (Entity)
|
+-- ComplianceStatus (Value Object)
```

#### ProjectProgram (Root)
```typescript
interface ProjectProgram {
  id: UUID;
  tenantId: UUID;
  projectId: UUID;
  programId: UUID;

  registrationNumber?: string;
  registrationDate?: Date;

  validFrom?: Date;
  validTo?: Date;

  // Compliance statistics
  compliancePercentage: Percentage;
  totalRequirements: number;
  compliantCount: number;
  nonCompliantCount: number;
  pendingCount: number;

  status: string;

  items: ComplianceItem[];
}
```

#### ComplianceItem (Entity)
```typescript
interface ComplianceItem {
  id: UUID;
  projectProgramId: UUID;
  requirementId: UUID;

  status: RequirementStatus;
  previousStatus?: RequirementStatus;

  // Verification
  verifiedBy?: UUID;
  verifiedAt?: Timestamp;
  verificationNotes?: string;

  // Dates
  dueDate?: Date;
  completedDate?: Date;

  notes?: string;
  isNotApplicable: boolean;
  naReason?: string;

  evidence: ComplianceEvidence[];
}

enum RequirementStatus {
  PENDING = 'pending',
  IN_PROGRESS = 'in_progress',
  COMPLIANT = 'compliant',
  NON_COMPLIANT = 'non_compliant',
  NOT_APPLICABLE = 'not_applicable'
}
```

#### ComplianceEvidence (Entity)
```typescript
interface ComplianceEvidence {
  id: UUID;
  complianceItemId: UUID;

  fileUrl: string;
  fileName: string;
  fileSize?: number;
  mimeType?: string;
  thumbnailUrl?: string;

  evidenceType: EvidenceType;
  description?: string;

  takenAt?: Timestamp;
  location?: Location;
  metadata?: Record<string, any>;

  status: EvidenceStatus;

  // Review
  reviewedBy?: UUID;
  reviewedAt?: Timestamp;
  reviewNotes?: string;
}

enum EvidenceType {
  DOCUMENT = 'document',
  PHOTO = 'photo',
  VIDEO = 'video',
  CERTIFICATE = 'certificate'
}

enum EvidenceStatus {
  ACTIVE = 'active',
  REPLACED = 'replaced',
  REJECTED = 'rejected'
}
```

---

### 3. Audit Aggregate

```
Audit (Aggregate Root)
|
+-- AuditFinding (Entity)
|   +-- CorrectiveAction (Entity)
|
+-- AuditResult (Value Object)
```

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

  auditNumber: string;
  auditType: AuditType;

  // Schedule
  scheduledDate: Date;
  scheduledTime?: Time;
  actualDate?: Date;

  // Auditor
  auditorName?: string;
  auditorCompany?: string;
  auditorContact?: string;

  status: AuditStatus;

  // Results
  overallCompliancePercentage?: Percentage;
  findingsCount: number;
  criticalFindings: number;
  majorFindings: number;
  minorFindings: number;

  reportUrl?: string;
  notes?: string;

  closedAt?: Timestamp;
  closedBy?: UUID;

  findings: AuditFinding[];
}

enum AuditType {
  INITIAL = 'initial',
  PROGRESS = 'progress',
  FINAL = 'final',
  SPECIAL = 'special',
  RANDOM = 'random'
}

enum AuditStatus {
  SCHEDULED = 'scheduled',
  IN_PROGRESS = 'in_progress',
  COMPLETED = 'completed',
  FOLLOW_UP = 'follow_up',
  CANCELLED = 'cancelled'
}
```

#### AuditFinding (Entity)
```typescript
interface AuditFinding {
  id: UUID;
  auditId: UUID;
  complianceItemId?: UUID;

  findingNumber: string;
  severity: FindingSeverity;

  title: string;
  description: string;
  evidenceRefs?: string[];

  // Failed requirement
  requirementCode?: string;
  requirementName?: string;

  // Responsible
  responsibleName?: string;
  responsibleArea?: string;

  dueDate: Date;
  resolutionDate?: Date;

  status: FindingStatus;

  correctiveActions: CorrectiveAction[];
}

enum FindingSeverity {
  MINOR = 'minor',      // 30 days to correct
  MAJOR = 'major',      // 15 days to correct
  CRITICAL = 'critical' // 7 days to correct
}

enum FindingStatus {
  OPEN = 'open',
  IN_PROGRESS = 'in_progress',
  RESOLVED = 'resolved',
  VERIFIED = 'verified',
  CLOSED = 'closed'
}
```

#### CorrectiveAction (Entity)
```typescript
interface CorrectiveAction {
  id: UUID;
  findingId: UUID;

  actionNumber: string;
  description: string;
  actionType: ActionType;

  // Assignment
  assignedTo?: UUID;
  assignedToName?: string;
  assignedAt?: Timestamp;

  dueDate: Date;
  completedDate?: Date;

  status: ActionStatus;

  // Verification
  verifiedBy?: UUID;
  verifiedAt?: Timestamp;
  verificationNotes?: string;
}

enum ActionType {
  CORRECTION = 'correction',
  PREVENTION = 'prevention',
  IMPROVEMENT = 'improvement'
}

enum ActionStatus {
  PENDING = 'pending',
  IN_PROGRESS = 'in_progress',
  COMPLETED = 'completed',
  VERIFIED = 'verified'
}
```

---

## Value Objects

### Percentage
```typescript
interface Percentage {
  value: number;  // 0-100

  static fromDecimal(decimal: number): Percentage;
  static toDecimal(percentage: Percentage): number;
  static isAboveThreshold(p: Percentage, threshold: number): boolean;
}
```

### Location
```typescript
interface Location {
  latitude: number;
  longitude: number;
  accuracy?: number;
  timestamp?: Timestamp;
}
```

### ComplianceSummary
```typescript
interface ComplianceSummary {
  totalRequirements: number;
  compliantCount: number;
  pendingCount: number;
  nonCompliantCount: number;
  notApplicableCount: number;

  byCategory: Record<RequirementCategory, {
    total: number;
    compliant: number;
    percentage: Percentage;
  }>;
}
```

---

## Domain Events

### Program Events
```typescript
interface ProjectRegisteredInProgram {
  projectProgramId: UUID;
  projectId: UUID;
  programId: UUID;
  registrationNumber?: string;
  timestamp: Timestamp;
}
```

### Compliance Events
```typescript
interface ComplianceItemStatusChanged {
  complianceItemId: UUID;
  projectProgramId: UUID;
  previousStatus: RequirementStatus;
  newStatus: RequirementStatus;
  changedBy: UUID;
  timestamp: Timestamp;
}

interface EvidenceUploaded {
  evidenceId: UUID;
  complianceItemId: UUID;
  evidenceType: EvidenceType;
  fileName: string;
  uploadedBy: UUID;
  timestamp: Timestamp;
}

interface ComplianceThresholdReached {
  projectProgramId: UUID;
  projectId: UUID;
  compliancePercentage: Percentage;
  threshold: Percentage;
  timestamp: Timestamp;
}
```

### Audit Events
```typescript
interface AuditScheduled {
  auditId: UUID;
  projectId: UUID;
  auditType: AuditType;
  scheduledDate: Date;
  timestamp: Timestamp;
}

interface AuditCompleted {
  auditId: UUID;
  projectId: UUID;
  overallCompliance: Percentage;
  findingsCount: number;
  criticalCount: number;
  timestamp: Timestamp;
}

interface FindingCreated {
  findingId: UUID;
  auditId: UUID;
  severity: FindingSeverity;
  dueDate: Date;
  timestamp: Timestamp;
}

interface CorrectiveActionCompleted {
  actionId: UUID;
  findingId: UUID;
  completedBy: UUID;
  timestamp: Timestamp;
}
```

### Alert Events
```typescript
interface RequirementDueSoon {
  complianceItemId: UUID;
  projectId: UUID;
  dueDate: Date;
  daysRemaining: number;
  timestamp: Timestamp;
}

interface FindingOverdue {
  findingId: UUID;
  auditId: UUID;
  severity: FindingSeverity;
  dueDate: Date;
  daysOverdue: number;
  timestamp: Timestamp;
}
```

---

## Business Rules

### Program Rules
1. Un proyecto solo puede registrarse una vez por programa
2. Los requisitos obligatorios no pueden marcarse como N/A sin justificacion
3. El registro en programa requiere al menos datos basicos del proyecto

### Compliance Rules
1. El status solo puede avanzar: pending -> in_progress -> compliant
2. Marcar como compliant requiere al menos una evidencia
3. El porcentaje de cumplimiento excluye items N/A del calculo
4. Cambios de status deben registrar historial

### Audit Rules
1. No se puede cerrar auditoria con hallazgos criticos abiertos
2. Los hallazgos tienen plazos segun severidad (7/15/30 dias)
3. Las acciones correctivas requieren verificacion antes de cerrar
4. Una auditoria de seguimiento requiere auditoria previa completada

### Evidence Rules
1. Fotografias deben incluir metadata de fecha y ubicacion
2. Documentos PDF deben ser legibles (no escaneados de baja calidad)
3. Evidencias reemplazadas mantienen historial
4. El tamaño maximo de archivo es 50MB

---

## Invariantes

1. `ProjectProgram.compliancePercentage = (compliantCount / (total - notApplicable)) * 100`
2. `ProjectProgram.totalRequirements = compliantCount + nonCompliantCount + pendingCount`
3. `Audit.findingsCount = criticalFindings + majorFindings + minorFindings`
4. `Finding.dueDate <= Finding.createdAt + severityDays`
5. `CorrectiveAction.dueDate <= Finding.dueDate`

---

## Integraciones

### Con Project Context
- Proyectos se registran en programas
- Avances de obra se usan como evidencia
- Viviendas se vinculan a requisitos

### Con Documents Context
- Evidencias se almacenan en DMS
- Reportes de auditoria como documentos
- Planos como evidencia tecnica

### Con INFONAVIT (Externo)
- Sincronizacion de programas vigentes
- Reporte de cumplimiento
- Notificacion de auditorias

---

## Referencias

- [DDL-SPEC-compliance.md](../database-design/schemas/DDL-SPEC-compliance.md)
- [EPIC-MAI-011](../../08-epicas/EPIC-MAI-011-infonavit.md)

---

*Ultima actualizacion: 2025-12-05*
