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

700 lines
13 KiB
Markdown

# DOMAIN MODEL: Documents Context (DMS)
**Version:** 1.0.0
**Fecha:** 2025-12-05
**Modulos:** MAE-016
---
## Descripcion
El contexto de Documents gestiona el sistema de gestion documental (DMS) enterprise. Incluye repositorio centralizado, versionado de planos, flujos de aprobacion, anotaciones y control de acceso granular.
---
## Agregados
### 1. Document Aggregate
```
Document (Aggregate Root)
|
+-- DocumentVersion (Entity)
| +-- VersionMetadata (Value Object)
|
+-- DocumentShare (Entity)
|
+-- AccessLog (Entity)
```
#### Document (Root)
```typescript
interface Document {
id: UUID;
tenantId: UUID;
folderId?: UUID;
documentNumber?: string;
title: string;
description?: string;
documentType: DocumentType;
subcategory?: string;
// Project link
projectId?: UUID;
housingUnitId?: UUID;
// Current version
currentVersionId?: UUID;
currentVersionNumber: string;
totalVersions: number;
// File info
fileUrl: string;
fileName: string;
fileSize?: number;
mimeType?: string;
fileExtension?: string;
thumbnailUrl?: string;
previewUrl?: string;
// Metadata
tags?: string[];
customFields?: Record<string, any>;
status: DocumentStatus;
accessLevel: AccessLevel;
// Dates
documentDate?: Date;
expiryDate?: Date;
// OCR
ocrText?: string;
isOcrProcessed: boolean;
ocrProcessedAt?: Timestamp;
versions: DocumentVersion[];
shares: DocumentShare[];
}
enum DocumentType {
PLAN = 'plan',
SPECIFICATION = 'specification',
CONTRACT = 'contract',
PERMIT = 'permit',
INVOICE = 'invoice',
REPORT = 'report',
PHOTO = 'photo',
DRAWING = 'drawing',
MANUAL = 'manual',
CERTIFICATE = 'certificate',
OTHER = 'other'
}
enum DocumentStatus {
DRAFT = 'draft',
IN_REVIEW = 'in_review',
APPROVED = 'approved',
REJECTED = 'rejected',
OBSOLETE = 'obsolete',
ARCHIVED = 'archived'
}
enum AccessLevel {
PUBLIC = 'public',
RESTRICTED = 'restricted',
CONFIDENTIAL = 'confidential',
PRIVATE = 'private'
}
```
#### DocumentVersion (Entity)
```typescript
interface DocumentVersion {
id: UUID;
documentId: UUID;
versionNumber: string; // 1.0, Rev. A, etc.
versionSequence: number;
fileUrl: string;
fileName: string;
fileSize?: number;
mimeType?: string;
thumbnailUrl?: string;
previewUrl?: string;
changeSummary?: string;
changeType?: ChangeType;
status: DocumentStatus;
isCurrent: boolean;
approvedBy?: UUID;
approvedAt?: Timestamp;
}
enum ChangeType {
MINOR = 'minor',
MAJOR = 'major',
REVISION = 'revision'
}
```
#### DocumentShare (Entity)
```typescript
interface DocumentShare {
id: UUID;
documentId: UUID;
shareType: ShareType;
sharedWithUserId?: UUID;
sharedWithRole?: string;
sharedWithEmail?: string;
// Permissions
canView: boolean;
canDownload: boolean;
canAnnotate: boolean;
canShare: boolean;
expiresAt?: Timestamp;
accessToken?: string; // For external links
isActive: boolean;
}
enum ShareType {
USER = 'user',
ROLE = 'role',
EXTERNAL = 'external'
}
```
---
### 2. Folder Aggregate
```
Folder (Aggregate Root)
|
+-- FolderPath (Value Object)
+-- AccessControl (Value Object)
```
#### Folder (Root)
```typescript
interface Folder {
id: UUID;
tenantId: UUID;
name: string;
description?: string;
parentId?: UUID;
fullPath: string;
level: number;
projectId?: UUID;
folderType?: FolderType;
accessLevel: AccessLevel;
allowedRoles?: string[];
sortOrder: number;
isActive: boolean;
children: Folder[];
documents: Document[];
}
enum FolderType {
PLANS = 'plans',
CONTRACTS = 'contracts',
PERMITS = 'permits',
SPECIFICATIONS = 'specifications',
REPORTS = 'reports',
PHOTOS = 'photos',
GENERAL = 'general'
}
```
---
### 3. Plan Aggregate (Extended Document)
```
Plan (Aggregate Root - extends Document)
|
+-- PlanAnnotation (Entity)
| +-- AnnotationShape (Value Object)
|
+-- PlanRevision (Value Object)
```
#### Plan (Root)
```typescript
interface Plan extends Document {
id: UUID;
documentId: UUID;
planType: PlanType;
discipline?: string;
planNumber: string;
sheetNumber?: string;
totalSheets?: number;
scale?: string;
// Dimensions
format?: string; // A0, A1, A2, A3, A4
widthMm?: number;
heightMm?: number;
// Georeferencing
northCoordinate?: number;
eastCoordinate?: number;
coordinateSystem?: string;
// Source
sourceSoftware?: string; // AutoCAD, Revit
sourceFileUrl?: string; // .dwg, .rvt
currentRevision: string;
isForConstruction: boolean;
isAsBuilt: boolean;
annotations: PlanAnnotation[];
}
enum PlanType {
ARCHITECTURAL = 'architectural',
STRUCTURAL = 'structural',
ELECTRICAL = 'electrical',
PLUMBING = 'plumbing',
HVAC = 'hvac',
LANDSCAPE = 'landscape',
CIVIL = 'civil',
DETAIL = 'detail',
AS_BUILT = 'as_built'
}
```
#### PlanAnnotation (Entity)
```typescript
interface PlanAnnotation {
id: UUID;
planId: UUID;
versionId?: UUID;
annotationType: AnnotationType;
// Position
xPosition: number;
yPosition: number;
width?: number;
height?: number;
rotation?: number;
content?: string;
color?: string;
style?: Record<string, any>;
// Shape (for markups)
shapeType?: ShapeType;
shapePoints?: Point[];
isResolved: boolean;
resolvedBy?: UUID;
resolvedAt?: Timestamp;
}
enum AnnotationType {
COMMENT = 'comment',
MARKUP = 'markup',
MEASUREMENT = 'measurement',
SYMBOL = 'symbol'
}
enum ShapeType {
RECTANGLE = 'rectangle',
CIRCLE = 'circle',
ARROW = 'arrow',
FREEHAND = 'freehand',
POLYGON = 'polygon',
LINE = 'line'
}
interface Point {
x: number;
y: number;
}
```
---
### 4. Approval Aggregate
```
ApprovalWorkflow (Aggregate Root)
|
+-- WorkflowLevel (Entity)
|
+-- ApproverConfig (Value Object)
DocumentApproval (Aggregate Root)
|
+-- ApprovalAction (Entity)
|
+-- ApprovalResult (Value Object)
```
#### ApprovalWorkflow (Root)
```typescript
interface ApprovalWorkflow {
id: UUID;
tenantId: UUID;
name: string;
description?: string;
documentTypes: DocumentType[];
totalLevels: number;
isActive: boolean;
levels: WorkflowLevel[];
}
```
#### WorkflowLevel (Entity)
```typescript
interface WorkflowLevel {
id: UUID;
workflowId: UUID;
levelNumber: number;
levelName: string;
approverType: ApproverType;
approverIds?: UUID[];
approverRoles?: string[];
requiresAll: boolean; // true = all must approve
canSkip: boolean;
sortOrder: number;
}
enum ApproverType {
USER = 'user',
ROLE = 'role',
DEPARTMENT = 'department'
}
```
#### DocumentApproval (Root)
```typescript
interface DocumentApproval {
id: UUID;
tenantId: UUID;
documentId: UUID;
versionId?: UUID;
workflowId?: UUID;
currentLevel: number;
status: ApprovalStatus;
submittedAt?: Timestamp;
submittedBy?: UUID;
completedAt?: Timestamp;
finalAction?: ApprovalAction;
finalComments?: string;
actions: ApprovalActionRecord[];
}
enum ApprovalStatus {
PENDING = 'pending',
IN_PROGRESS = 'in_progress',
APPROVED = 'approved',
REJECTED = 'rejected'
}
```
#### ApprovalActionRecord (Entity)
```typescript
interface ApprovalActionRecord {
id: UUID;
approvalId: UUID;
levelNumber: number;
action: ApprovalAction;
actionBy: UUID;
actionAt: Timestamp;
comments?: string;
}
enum ApprovalAction {
SUBMIT = 'submit',
APPROVE = 'approve',
REJECT = 'reject',
REQUEST_CHANGES = 'request_changes',
WITHDRAW = 'withdraw'
}
```
---
## Value Objects
### FileInfo
```typescript
interface FileInfo {
url: string;
name: string;
size: number;
mimeType: string;
extension: string;
checksum?: string;
}
```
### FolderPath
```typescript
interface FolderPath {
path: string;
segments: string[];
depth: number;
static fromString(path: string): FolderPath;
static join(parent: FolderPath, name: string): FolderPath;
getParent(): FolderPath;
}
```
### VersionNumber
```typescript
interface VersionNumber {
major: number;
minor: number;
revision?: string;
static parse(str: string): VersionNumber;
static next(current: VersionNumber, changeType: ChangeType): VersionNumber;
toString(): string;
}
```
### Dimensions
```typescript
interface Dimensions {
width: number;
height: number;
unit: 'mm' | 'cm' | 'in';
}
```
---
## Domain Events
### Document Events
```typescript
interface DocumentUploaded {
documentId: UUID;
fileName: string;
fileSize: number;
documentType: DocumentType;
uploadedBy: UUID;
timestamp: Timestamp;
}
interface DocumentVersionCreated {
documentId: UUID;
versionId: UUID;
versionNumber: string;
changeType: ChangeType;
createdBy: UUID;
timestamp: Timestamp;
}
interface DocumentStatusChanged {
documentId: UUID;
previousStatus: DocumentStatus;
newStatus: DocumentStatus;
changedBy: UUID;
timestamp: Timestamp;
}
interface DocumentShared {
documentId: UUID;
shareId: UUID;
shareType: ShareType;
sharedWith: string;
permissions: string[];
sharedBy: UUID;
timestamp: Timestamp;
}
```
### Plan Events
```typescript
interface PlanRevisionCreated {
planId: UUID;
versionId: UUID;
revision: string;
createdBy: UUID;
timestamp: Timestamp;
}
interface AnnotationAdded {
planId: UUID;
annotationId: UUID;
annotationType: AnnotationType;
createdBy: UUID;
timestamp: Timestamp;
}
interface AnnotationResolved {
annotationId: UUID;
planId: UUID;
resolvedBy: UUID;
timestamp: Timestamp;
}
```
### Approval Events
```typescript
interface ApprovalSubmitted {
approvalId: UUID;
documentId: UUID;
workflowId: UUID;
submittedBy: UUID;
timestamp: Timestamp;
}
interface ApprovalLevelCompleted {
approvalId: UUID;
documentId: UUID;
levelNumber: number;
action: ApprovalAction;
actionBy: UUID;
timestamp: Timestamp;
}
interface ApprovalCompleted {
approvalId: UUID;
documentId: UUID;
finalAction: ApprovalAction;
completedBy: UUID;
timestamp: Timestamp;
}
```
### Access Events
```typescript
interface DocumentAccessed {
documentId: UUID;
action: AccessAction;
userId: UUID;
versionId?: UUID;
timestamp: Timestamp;
}
enum AccessAction {
VIEW = 'view',
DOWNLOAD = 'download',
PRINT = 'print',
ANNOTATE = 'annotate',
SHARE = 'share'
}
```
---
## Business Rules
### Document Rules
1. Los documentos requieren al menos un archivo
2. El numero de documento debe ser unico por proyecto
3. Solo la version actual puede modificarse
4. Documentos archivados son de solo lectura
### Version Rules
1. Cada nueva version incrementa secuencia automaticamente
2. Solo puede haber una version 'current' a la vez
3. El historial de versiones es inmutable
4. Los cambios mayores requieren nueva revision
### Plan Rules
1. Los planos deben tener numero de plano unico
2. Las revisiones siguen secuencia (A, B, C... o 1, 2, 3...)
3. Los planos 'for construction' requieren aprobacion
4. Las anotaciones no resueltas bloquean nueva revision
### Approval Rules
1. El flujo de aprobacion respeta niveles en orden
2. 'requiresAll' exige aprobacion de todos los aprobadores del nivel
3. Rechazo en cualquier nivel rechaza todo el documento
4. 'request_changes' regresa al nivel anterior
### Access Rules
1. 'private' solo visible por propietario
2. 'confidential' requiere permiso explicito
3. 'restricted' limita por roles
4. Links externos expiran automaticamente
---
## Invariantes
1. `Document.currentVersionId = MAX(versions.versionSequence).id WHERE isCurrent = true`
2. `Document.totalVersions = COUNT(versions)`
3. `Folder.fullPath = parent.fullPath + '/' + name`
4. `Folder.level = parent.level + 1`
5. `DocumentApproval.currentLevel <= workflow.totalLevels`
---
## Integraciones
### Con Project Context
- Documentos asociados a proyectos
- Planos vinculados a viviendas/conceptos
- Fotos de avance como documentos
### Con Compliance Context
- Evidencias almacenadas como documentos
- Reportes de auditoria
- Certificaciones
### Con Finance Context
- Facturas digitales
- Polizas exportadas
- Contratos
### Con Storage (Externo)
- S3/Azure Blob para archivos
- CDN para previews
- OCR externo para busqueda
---
## Referencias
- [DDL-SPEC-documents.md](../database-design/schemas/DDL-SPEC-documents.md)
---
*Ultima actualizacion: 2025-12-05*