/** * Contract DTOs - Data Transfer Objects para Contratos * * Contratos con clientes y subcontratistas. * * @module Contracts (MAI-012) */ import { IsString, IsUUID, IsOptional, IsEnum, IsNumber, IsDateString, MinLength, MaxLength, Min, Max, } from 'class-validator'; /** * Tipo de contrato */ export enum ContractTypeEnum { CLIENT = 'client', SUBCONTRACTOR = 'subcontractor', } /** * Estado del contrato */ export enum ContractStatusEnum { DRAFT = 'draft', REVIEW = 'review', APPROVED = 'approved', ACTIVE = 'active', COMPLETED = 'completed', TERMINATED = 'terminated', } /** * Tipo de contrato cliente */ export enum ClientContractTypeEnum { DESARROLLO = 'desarrollo', LLAVE_EN_MANO = 'llave_en_mano', ADMINISTRACION = 'administracion', } /** * DTO para crear un nuevo contrato */ export class CreateContractDto { @IsString() @MinLength(3) @MaxLength(50) contractNumber: string; @IsEnum(ContractTypeEnum) type: ContractTypeEnum; @IsString() @MinLength(5) @MaxLength(255) title: string; @IsOptional() @IsString() description?: string; @IsOptional() @IsUUID() partnerId?: string; @IsOptional() @IsUUID() fraccionamientoId?: string; @IsOptional() @IsUUID() projectId?: string; @IsOptional() @IsUUID() subcontractorId?: string; @IsDateString() startDate: string; @IsOptional() @IsDateString() endDate?: string; @IsNumber() @Min(0) contractAmount: number; @IsOptional() @IsString() @MaxLength(3) currency?: string; @IsOptional() @IsEnum(ClientContractTypeEnum) clientContractType?: ClientContractTypeEnum; @IsOptional() @IsString() @MaxLength(255) clientName?: string; @IsOptional() @IsString() @MaxLength(13) clientRfc?: string; @IsOptional() @IsString() clientAddress?: string; @IsOptional() @IsString() @MaxLength(50) specialty?: string; @IsOptional() @IsString() paymentTerms?: string; @IsOptional() @IsNumber() @Min(0) @Max(100) retentionPercentage?: number; @IsOptional() @IsNumber() @Min(0) @Max(100) advancePercentage?: number; @IsOptional() @IsString() notes?: string; } /** * DTO para actualizar un contrato existente */ export class UpdateContractDto { @IsOptional() @IsString() @MinLength(3) @MaxLength(50) contractNumber?: string; @IsOptional() @IsEnum(ContractTypeEnum) type?: ContractTypeEnum; @IsOptional() @IsString() @MinLength(5) @MaxLength(255) title?: string; @IsOptional() @IsString() description?: string; @IsOptional() @IsUUID() partnerId?: string; @IsOptional() @IsUUID() fraccionamientoId?: string; @IsOptional() @IsUUID() projectId?: string; @IsOptional() @IsUUID() subcontractorId?: string; @IsOptional() @IsDateString() startDate?: string; @IsOptional() @IsDateString() endDate?: string; @IsOptional() @IsNumber() @Min(0) contractAmount?: number; @IsOptional() @IsString() @MaxLength(3) currency?: string; @IsOptional() @IsEnum(ClientContractTypeEnum) clientContractType?: ClientContractTypeEnum; @IsOptional() @IsString() @MaxLength(255) clientName?: string; @IsOptional() @IsString() @MaxLength(13) clientRfc?: string; @IsOptional() @IsString() clientAddress?: string; @IsOptional() @IsString() @MaxLength(50) specialty?: string; @IsOptional() @IsString() paymentTerms?: string; @IsOptional() @IsNumber() @Min(0) @Max(100) retentionPercentage?: number; @IsOptional() @IsNumber() @Min(0) @Max(100) advancePercentage?: number; @IsOptional() @IsEnum(ContractStatusEnum) status?: ContractStatusEnum; @IsOptional() @IsString() @MaxLength(500) documentUrl?: string; @IsOptional() @IsString() @MaxLength(500) signedDocumentUrl?: string; @IsOptional() @IsString() notes?: string; @IsOptional() @IsString() terminationReason?: string; } /** * DTO para filtrar contratos en listados */ export class ContractFiltersDto { @IsOptional() @IsEnum(ContractTypeEnum) type?: ContractTypeEnum; @IsOptional() @IsEnum(ContractStatusEnum) status?: ContractStatusEnum; @IsOptional() @IsUUID() partnerId?: string; @IsOptional() @IsUUID() fraccionamientoId?: string; @IsOptional() @IsUUID() projectId?: string; @IsOptional() @IsUUID() subcontractorId?: string; @IsOptional() @IsDateString() dateFrom?: string; @IsOptional() @IsDateString() dateTo?: string; @IsOptional() @IsDateString() startDateFrom?: string; @IsOptional() @IsDateString() startDateTo?: string; @IsOptional() @IsDateString() endDateFrom?: string; @IsOptional() @IsDateString() endDateTo?: string; @IsOptional() @IsNumber() @Min(0) amountMin?: number; @IsOptional() @IsNumber() @Min(0) amountMax?: number; @IsOptional() @IsString() search?: string; @IsOptional() @IsNumber() @Min(1) page?: number; @IsOptional() @IsNumber() @Min(1) limit?: number; @IsOptional() @IsString() sortBy?: string; @IsOptional() @IsEnum(['ASC', 'DESC']) sortOrder?: 'ASC' | 'DESC'; } /** * DTO para aprobar un contrato */ export class ApproveContractDto { @IsOptional() @IsString() notes?: string; @IsOptional() @IsDateString() approvalDate?: string; } /** * DTO para aprobacion legal del contrato */ export class LegalApproveContractDto { @IsOptional() @IsString() notes?: string; } /** * DTO para terminar un contrato */ export class TerminateContractDto { @IsString() @MinLength(10) reason: string; @IsOptional() @IsDateString() terminationDate?: string; } /** * DTO para firmar un contrato */ export class SignContractDto { @IsOptional() @IsString() @MaxLength(500) signedDocumentUrl?: string; @IsOptional() @IsDateString() signedDate?: string; } /** * DTO de respuesta para un contrato */ export class ContractResponseDto { id: string; tenantId: string; projectId?: string; project?: { id: string; code: string; name: string; }; fraccionamientoId?: string; fraccionamiento?: { id: string; code: string; name: string; }; contractNumber: string; contractType: ContractTypeEnum; clientContractType?: ClientContractTypeEnum; name: string; description?: string; clientName?: string; clientRfc?: string; clientAddress?: string; subcontractorId?: string; subcontractor?: { id: string; code: string; businessName: string; }; specialty?: string; startDate: Date; endDate: Date; contractAmount: string; currency: string; paymentTerms?: string; retentionPercentage: string; advancePercentage: string; status: ContractStatusEnum; submittedAt?: Date; legalApprovedAt?: Date; approvedAt?: Date; signedAt?: Date; terminatedAt?: Date; terminationReason?: string; documentUrl?: string; signedDocumentUrl?: string; progressPercentage: string; invoicedAmount: string; paidAmount: string; remainingAmount?: string; isExpiring?: boolean; notes?: string; addendumsCount?: number; createdAt: Date; createdById?: string; createdBy?: { id: string; firstName: string; lastName: string; }; updatedAt: Date; }