13 KiB
13 KiB
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)
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)
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)
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)
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)
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)
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)
interface ApprovalWorkflow {
id: UUID;
tenantId: UUID;
name: string;
description?: string;
documentTypes: DocumentType[];
totalLevels: number;
isActive: boolean;
levels: WorkflowLevel[];
}
WorkflowLevel (Entity)
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)
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)
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
interface FileInfo {
url: string;
name: string;
size: number;
mimeType: string;
extension: string;
checksum?: string;
}
FolderPath
interface FolderPath {
path: string;
segments: string[];
depth: number;
static fromString(path: string): FolderPath;
static join(parent: FolderPath, name: string): FolderPath;
getParent(): FolderPath;
}
VersionNumber
interface VersionNumber {
major: number;
minor: number;
revision?: string;
static parse(str: string): VersionNumber;
static next(current: VersionNumber, changeType: ChangeType): VersionNumber;
toString(): string;
}
Dimensions
interface Dimensions {
width: number;
height: number;
unit: 'mm' | 'cm' | 'in';
}
Domain Events
Document Events
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
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
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
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
- Los documentos requieren al menos un archivo
- El numero de documento debe ser unico por proyecto
- Solo la version actual puede modificarse
- Documentos archivados son de solo lectura
Version Rules
- Cada nueva version incrementa secuencia automaticamente
- Solo puede haber una version 'current' a la vez
- El historial de versiones es inmutable
- Los cambios mayores requieren nueva revision
Plan Rules
- Los planos deben tener numero de plano unico
- Las revisiones siguen secuencia (A, B, C... o 1, 2, 3...)
- Los planos 'for construction' requieren aprobacion
- Las anotaciones no resueltas bloquean nueva revision
Approval Rules
- El flujo de aprobacion respeta niveles en orden
- 'requiresAll' exige aprobacion de todos los aprobadores del nivel
- Rechazo en cualquier nivel rechaza todo el documento
- 'request_changes' regresa al nivel anterior
Access Rules
- 'private' solo visible por propietario
- 'confidential' requiere permiso explicito
- 'restricted' limita por roles
- Links externos expiran automaticamente
Invariantes
Document.currentVersionId = MAX(versions.versionSequence).id WHERE isCurrent = trueDocument.totalVersions = COUNT(versions)Folder.fullPath = parent.fullPath + '/' + nameFolder.level = parent.level + 1DocumentApproval.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
Ultima actualizacion: 2025-12-05