erp-construccion-backend-v2/src/modules/contracts/dto/contract.dto.ts
Adrian Flores Cortes 598c3215e1 feat(FASE-4A): Complete vertical modules for construction
- MAI-018 Bidding module: entities, services, controllers, DTOs
  - Opportunity, Tender, Proposal, Vendor management
  - Bid calendar, documents, analytics
- Earned Value Management: Curva S, SPI/CPI reports
  - earned-value.service.ts with EV, PV, AC calculations
  - earned-value.controller.ts with 9 endpoints
- DTOs for modules: assets, contracts, documents, purchase, quality
  - 28 new DTO files with class-validator decorators
- Storage module: service and controller implementation
  - Multi-provider support (local, S3, GCS, Azure)
  - File management, upload/download URLs
- Multiple entity and service fixes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 07:00:18 -06:00

467 lines
7.1 KiB
TypeScript

/**
* 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;
}