/** * Document Entity - Registro Principal de Documentos * Sistema de gestion documental. * * @module Documents (MAE-016) */ import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToOne, OneToMany, JoinColumn, Index, } from 'typeorm'; import { DocumentCategory, AccessLevel } from './document-category.entity'; import { DocumentVersion } from './document-version.entity'; import { Annotation } from './annotation.entity'; export type DocumentType = | 'plan' | 'specification' | 'contract' | 'permit' | 'report' | 'photograph' | 'drawing' | 'manual' | 'procedure' | 'form' | 'correspondence' | 'invoice' | 'estimate' | 'other'; export type DocumentStatus = | 'draft' | 'pending_review' | 'in_review' | 'approved' | 'rejected' | 'obsolete' | 'archived'; @Entity('documents', { schema: 'documents' }) @Index(['tenantId', 'documentCode'], { unique: true }) @Index(['tenantId', 'categoryId']) @Index(['tenantId', 'documentType']) @Index(['tenantId', 'status']) @Index(['tenantId', 'projectId']) export class Document { @PrimaryGeneratedColumn('uuid') id!: string; @Column({ name: 'tenant_id', type: 'uuid' }) @Index() tenantId!: string; // Identificacion @Column({ name: 'document_code', length: 100 }) documentCode!: string; @Column({ length: 500 }) title!: string; @Column({ type: 'text', nullable: true }) description?: string; // Clasificacion @Column({ name: 'category_id', type: 'uuid', nullable: true }) categoryId?: string; @ManyToOne(() => DocumentCategory, { nullable: true }) @JoinColumn({ name: 'category_id' }) category?: DocumentCategory; @Column({ name: 'document_type', type: 'enum', enum: ['plan', 'specification', 'contract', 'permit', 'report', 'photograph', 'drawing', 'manual', 'procedure', 'form', 'correspondence', 'invoice', 'estimate', 'other'], enumName: 'document_type', }) documentType!: DocumentType; @Column({ type: 'enum', enum: ['draft', 'pending_review', 'in_review', 'approved', 'rejected', 'obsolete', 'archived'], enumName: 'document_status', default: 'draft', }) status!: DocumentStatus; @Column({ name: 'access_level', type: 'enum', enum: ['public', 'internal', 'confidential', 'restricted'], enumName: 'access_level', default: 'internal', }) accessLevel!: AccessLevel; // Version actual @Column({ name: 'current_version_id', type: 'uuid', nullable: true }) currentVersionId?: string; @Column({ name: 'current_version_number', length: 20, default: '1.0' }) currentVersionNumber!: string; // Proyecto/Contexto @Column({ name: 'project_id', type: 'uuid', nullable: true }) projectId?: string; @Column({ name: 'project_code', length: 50, nullable: true }) projectCode?: string; @Column({ name: 'project_name', length: 255, nullable: true }) projectName?: string; // Metadatos del documento @Column({ length: 255, nullable: true }) author?: string; @Column({ type: 'varchar', array: true, nullable: true }) keywords?: string[]; @Column({ type: 'varchar', array: true, nullable: true }) tags?: string[]; // Fechas importantes @Column({ name: 'document_date', type: 'date', nullable: true }) documentDate?: Date; @Column({ name: 'effective_date', type: 'date', nullable: true }) effectiveDate?: Date; @Column({ name: 'expiry_date', type: 'date', nullable: true }) expiryDate?: Date; @Column({ name: 'review_date', type: 'date', nullable: true }) reviewDate?: Date; // Origen @Column({ length: 100, nullable: true }) source?: string; @Column({ name: 'external_reference', length: 255, nullable: true }) externalReference?: string; @Column({ name: 'original_filename', length: 500, nullable: true }) originalFilename?: string; // Relaciones de documentos @Column({ name: 'parent_document_id', type: 'uuid', nullable: true }) parentDocumentId?: string; @ManyToOne(() => Document, { nullable: true }) @JoinColumn({ name: 'parent_document_id' }) parentDocument?: Document; @Column({ name: 'related_documents', type: 'uuid', array: true, nullable: true }) relatedDocuments?: string[]; // Flujo de aprobacion @Column({ name: 'requires_approval', type: 'boolean', default: false }) requiresApproval!: boolean; @Column({ name: 'current_workflow_id', type: 'uuid', nullable: true }) currentWorkflowId?: string; @Column({ name: 'approved_by_id', type: 'uuid', nullable: true }) approvedById?: string; @Column({ name: 'approved_at', type: 'timestamptz', nullable: true }) approvedAt?: Date; // Estadisticas @Column({ name: 'view_count', type: 'int', default: 0 }) viewCount!: number; @Column({ name: 'download_count', type: 'int', default: 0 }) downloadCount!: number; @Column({ name: 'last_accessed_at', type: 'timestamptz', nullable: true }) lastAccessedAt?: Date; // Flags @Column({ name: 'is_template', type: 'boolean', default: false }) isTemplate!: boolean; @Column({ name: 'is_locked', type: 'boolean', default: false }) isLocked!: boolean; @Column({ name: 'locked_by_id', type: 'uuid', nullable: true }) lockedById?: string; @Column({ name: 'locked_at', type: 'timestamptz', nullable: true }) lockedAt?: Date; // Notas y metadatos @Column({ type: 'text', nullable: true }) notes?: string; @Column({ name: 'custom_fields', type: 'jsonb', nullable: true }) customFields?: Record; @Column({ type: 'jsonb', nullable: true }) metadata?: Record; // Relaciones @OneToMany(() => DocumentVersion, (version) => version.document) versions?: DocumentVersion[]; @OneToMany(() => Annotation, (annotation) => annotation.document) annotations?: Annotation[]; // Auditoria @Column({ name: 'created_by', type: 'uuid', nullable: true }) createdBy?: string; @Column({ name: 'updated_by', type: 'uuid', nullable: true }) updatedBy?: string; @CreateDateColumn({ name: 'created_at', type: 'timestamptz' }) createdAt!: Date; @UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' }) updatedAt!: Date; @Column({ name: 'deleted_at', type: 'timestamptz', nullable: true }) deletedAt?: Date; }