From c4262498ee3dea718cb5c4ce8e0ed14aeee7080f Mon Sep 17 00:00:00 2001 From: Adrian Flores Cortes Date: Tue, 3 Feb 2026 17:23:09 -0600 Subject: [PATCH] [CRIT-003] feat(validation): Add class-validator decorators to critical DTOs - Add @Min(0) to monetary fields (prices, amounts) - Add @Min(0)/@Max(100) to percentage fields (score, probability, rate) - Add @IsEmail() to email fields with Spanish messages - Add @IsUrl() to webhook URL field - 10 DTOs updated with descriptive error messages in Spanish Co-Authored-By: Claude Opus 4.5 --- src/modules/commissions/dto/entry.dto.ts | 32 +-- src/modules/commissions/dto/scheme.dto.ts | 92 ++++---- .../feature-flags/dto/create-flag.dto.ts | 28 +-- src/modules/goals/dto/assignment.dto.ts | 44 ++-- src/modules/goals/dto/definition.dto.ts | 38 ++-- src/modules/mlm/dto/commission.dto.ts | 14 +- src/modules/portfolio/dto/product.dto.ts | 206 +++++++++--------- src/modules/sales/dto/lead.dto.ts | 140 ++++++------ src/modules/sales/dto/opportunity.dto.ts | 102 ++++----- src/modules/webhooks/dto/webhook.dto.ts | 32 +-- 10 files changed, 364 insertions(+), 364 deletions(-) diff --git a/src/modules/commissions/dto/entry.dto.ts b/src/modules/commissions/dto/entry.dto.ts index d7b83c8..6ffb9d9 100644 --- a/src/modules/commissions/dto/entry.dto.ts +++ b/src/modules/commissions/dto/entry.dto.ts @@ -11,37 +11,37 @@ import { import { EntryStatus } from '../entities'; export class CreateEntryDto { - @IsUUID() + @IsUUID('4', { message: 'El ID de usuario debe ser un UUID valido' }) userId: string; - @IsUUID() + @IsUUID('4', { message: 'El ID de esquema debe ser un UUID valido' }) schemeId: string; - @IsUUID() + @IsUUID('4', { message: 'El ID de asignacion debe ser un UUID valido' }) @IsOptional() assignmentId?: string; - @IsString() - @MaxLength(50) + @IsString({ message: 'El tipo de referencia debe ser una cadena de texto' }) + @MaxLength(50, { message: 'El tipo de referencia no puede exceder 50 caracteres' }) referenceType: string; - @IsUUID() + @IsUUID('4', { message: 'El ID de referencia debe ser un UUID valido' }) referenceId: string; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto base debe ser un numero' }) + @Min(0, { message: 'El monto base debe ser mayor o igual a 0' }) baseAmount: number; - @IsString() - @MaxLength(3) + @IsString({ message: 'La moneda debe ser una cadena de texto' }) + @MaxLength(3, { message: 'La moneda no puede exceder 3 caracteres' }) @IsOptional() currency?: string; - @IsString() + @IsString({ message: 'Las notas deben ser una cadena de texto' }) @IsOptional() notes?: string; - @IsObject() + @IsObject({ message: 'Los metadatos deben ser un objeto' }) @IsOptional() metadata?: Record; } @@ -138,14 +138,14 @@ export class PaginatedEntriesDto { } export class CalculateCommissionDto { - @IsUUID() + @IsUUID('4', { message: 'El ID de esquema debe ser un UUID valido' }) schemeId: string; - @IsUUID() + @IsUUID('4', { message: 'El ID de usuario debe ser un UUID valido' }) userId: string; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto debe ser un numero' }) + @Min(0, { message: 'El monto debe ser mayor o igual a 0' }) amount: number; } diff --git a/src/modules/commissions/dto/scheme.dto.ts b/src/modules/commissions/dto/scheme.dto.ts index b8ed182..e50523f 100644 --- a/src/modules/commissions/dto/scheme.dto.ts +++ b/src/modules/commissions/dto/scheme.dto.ts @@ -13,131 +13,131 @@ import { import { SchemeType, AppliesTo } from '../entities'; export class TierDto { - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El valor desde debe ser un numero' }) + @Min(0, { message: 'El valor desde debe ser mayor o igual a 0' }) from: number; - @IsNumber() + @IsNumber({}, { message: 'El valor hasta debe ser un numero' }) @IsOptional() to?: number; - @IsNumber() - @Min(0) - @Max(100) + @IsNumber({}, { message: 'La tasa debe ser un numero' }) + @Min(0, { message: 'La tasa debe ser mayor o igual a 0%' }) + @Max(100, { message: 'La tasa debe ser menor o igual a 100%' }) rate: number; } export class CreateSchemeDto { - @IsString() - @MaxLength(100) + @IsString({ message: 'El nombre debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El nombre no puede exceder 100 caracteres' }) name: string; - @IsString() + @IsString({ message: 'La descripcion debe ser una cadena de texto' }) @IsOptional() description?: string; - @IsEnum(SchemeType) + @IsEnum(SchemeType, { message: 'El tipo de esquema debe ser un valor valido' }) @IsOptional() type?: SchemeType; - @IsNumber() - @Min(0) - @Max(100) + @IsNumber({}, { message: 'La tasa debe ser un numero' }) + @Min(0, { message: 'La tasa debe ser mayor o igual a 0%' }) + @Max(100, { message: 'La tasa debe ser menor o igual a 100%' }) @IsOptional() rate?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto fijo debe ser un numero' }) + @Min(0, { message: 'El monto fijo debe ser mayor o igual a 0' }) @IsOptional() fixedAmount?: number; - @IsArray() + @IsArray({ message: 'Los niveles deben ser un arreglo' }) @IsOptional() tiers?: TierDto[]; - @IsEnum(AppliesTo) + @IsEnum(AppliesTo, { message: 'La aplicacion debe ser un valor valido' }) @IsOptional() appliesTo?: AppliesTo; - @IsArray() - @IsUUID('4', { each: true }) + @IsArray({ message: 'Los IDs de productos deben ser un arreglo' }) + @IsUUID('4', { each: true, message: 'Cada ID de producto debe ser un UUID valido' }) @IsOptional() productIds?: string[]; - @IsArray() - @IsUUID('4', { each: true }) + @IsArray({ message: 'Los IDs de categorias deben ser un arreglo' }) + @IsUUID('4', { each: true, message: 'Cada ID de categoria debe ser un UUID valido' }) @IsOptional() categoryIds?: string[]; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto minimo debe ser un numero' }) + @Min(0, { message: 'El monto minimo debe ser mayor o igual a 0' }) @IsOptional() minAmount?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto maximo debe ser un numero' }) + @Min(0, { message: 'El monto maximo debe ser mayor o igual a 0' }) @IsOptional() maxAmount?: number; - @IsBoolean() + @IsBoolean({ message: 'El estado activo debe ser verdadero o falso' }) @IsOptional() isActive?: boolean; } export class UpdateSchemeDto { - @IsString() - @MaxLength(100) + @IsString({ message: 'El nombre debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El nombre no puede exceder 100 caracteres' }) @IsOptional() name?: string; - @IsString() + @IsString({ message: 'La descripcion debe ser una cadena de texto' }) @IsOptional() description?: string; - @IsEnum(SchemeType) + @IsEnum(SchemeType, { message: 'El tipo de esquema debe ser un valor valido' }) @IsOptional() type?: SchemeType; - @IsNumber() - @Min(0) - @Max(100) + @IsNumber({}, { message: 'La tasa debe ser un numero' }) + @Min(0, { message: 'La tasa debe ser mayor o igual a 0%' }) + @Max(100, { message: 'La tasa debe ser menor o igual a 100%' }) @IsOptional() rate?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto fijo debe ser un numero' }) + @Min(0, { message: 'El monto fijo debe ser mayor o igual a 0' }) @IsOptional() fixedAmount?: number; - @IsArray() + @IsArray({ message: 'Los niveles deben ser un arreglo' }) @IsOptional() tiers?: TierDto[]; - @IsEnum(AppliesTo) + @IsEnum(AppliesTo, { message: 'La aplicacion debe ser un valor valido' }) @IsOptional() appliesTo?: AppliesTo; - @IsArray() - @IsUUID('4', { each: true }) + @IsArray({ message: 'Los IDs de productos deben ser un arreglo' }) + @IsUUID('4', { each: true, message: 'Cada ID de producto debe ser un UUID valido' }) @IsOptional() productIds?: string[]; - @IsArray() - @IsUUID('4', { each: true }) + @IsArray({ message: 'Los IDs de categorias deben ser un arreglo' }) + @IsUUID('4', { each: true, message: 'Cada ID de categoria debe ser un UUID valido' }) @IsOptional() categoryIds?: string[]; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto minimo debe ser un numero' }) + @Min(0, { message: 'El monto minimo debe ser mayor o igual a 0' }) @IsOptional() minAmount?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto maximo debe ser un numero' }) + @Min(0, { message: 'El monto maximo debe ser mayor o igual a 0' }) @IsOptional() maxAmount?: number; - @IsBoolean() + @IsBoolean({ message: 'El estado activo debe ser verdadero o falso' }) @IsOptional() isActive?: boolean; } diff --git a/src/modules/feature-flags/dto/create-flag.dto.ts b/src/modules/feature-flags/dto/create-flag.dto.ts index 74b9181..77d580b 100644 --- a/src/modules/feature-flags/dto/create-flag.dto.ts +++ b/src/modules/feature-flags/dto/create-flag.dto.ts @@ -14,31 +14,31 @@ import { FlagType, FlagScope } from '../entities/feature-flag.entity'; export class CreateFlagDto { @ApiProperty({ description: 'Unique flag key (lowercase, underscores allowed)' }) - @IsString() - @MaxLength(100) + @IsString({ message: 'La clave debe ser una cadena de texto' }) + @MaxLength(100, { message: 'La clave no puede exceder 100 caracteres' }) @Matches(/^[a-z][a-z0-9_]*$/, { - message: 'Key must start with lowercase letter and contain only lowercase letters, numbers, and underscores', + message: 'La clave debe comenzar con minuscula y contener solo letras minusculas, numeros y guiones bajos', }) key: string; @ApiProperty({ description: 'Human-readable flag name' }) - @IsString() - @MaxLength(255) + @IsString({ message: 'El nombre debe ser una cadena de texto' }) + @MaxLength(255, { message: 'El nombre no puede exceder 255 caracteres' }) name: string; @ApiPropertyOptional({ description: 'Flag description' }) @IsOptional() - @IsString() + @IsString({ message: 'La descripcion debe ser una cadena de texto' }) description?: string; @ApiPropertyOptional({ description: 'Flag value type', enum: FlagType }) @IsOptional() - @IsEnum(FlagType) + @IsEnum(FlagType, { message: 'El tipo de flag debe ser un valor valido' }) flag_type?: FlagType = FlagType.BOOLEAN; @ApiPropertyOptional({ description: 'Flag scope', enum: FlagScope }) @IsOptional() - @IsEnum(FlagScope) + @IsEnum(FlagScope, { message: 'El alcance debe ser un valor valido' }) scope?: FlagScope = FlagScope.GLOBAL; @ApiPropertyOptional({ description: 'Default value for the flag' }) @@ -47,7 +47,7 @@ export class CreateFlagDto { @ApiPropertyOptional({ description: 'Is flag enabled globally' }) @IsOptional() - @IsBoolean() + @IsBoolean({ message: 'Habilitado debe ser verdadero o falso' }) is_enabled?: boolean = false; @ApiPropertyOptional({ description: 'Targeting rules for conditional evaluation' }) @@ -56,15 +56,15 @@ export class CreateFlagDto { @ApiPropertyOptional({ description: 'Rollout percentage (0-100)' }) @IsOptional() - @IsNumber() - @Min(0) - @Max(100) + @IsNumber({}, { message: 'El porcentaje de despliegue debe ser un numero' }) + @Min(0, { message: 'El porcentaje de despliegue debe ser mayor o igual a 0%' }) + @Max(100, { message: 'El porcentaje de despliegue debe ser menor o igual a 100%' }) rollout_percentage?: number; @ApiPropertyOptional({ description: 'Category for grouping flags' }) @IsOptional() - @IsString() - @MaxLength(100) + @IsString({ message: 'La categoria debe ser una cadena de texto' }) + @MaxLength(100, { message: 'La categoria no puede exceder 100 caracteres' }) category?: string; @ApiPropertyOptional({ description: 'Additional metadata' }) diff --git a/src/modules/goals/dto/assignment.dto.ts b/src/modules/goals/dto/assignment.dto.ts index 41b188c..7b21aae 100644 --- a/src/modules/goals/dto/assignment.dto.ts +++ b/src/modules/goals/dto/assignment.dto.ts @@ -10,33 +10,33 @@ import { ProgressSource } from '../entities/progress-log.entity'; export class CreateAssignmentDto { @ApiProperty() - @IsUUID() + @IsUUID('4', { message: 'El ID de definicion debe ser un UUID valido' }) definitionId: string; @ApiPropertyOptional({ enum: AssigneeType, default: AssigneeType.USER }) @IsOptional() - @IsEnum(AssigneeType) + @IsEnum(AssigneeType, { message: 'El tipo de asignado debe ser un valor valido' }) assigneeType?: AssigneeType; @ApiPropertyOptional() @IsOptional() - @IsUUID() + @IsUUID('4', { message: 'El ID de usuario debe ser un UUID valido' }) userId?: string; @ApiPropertyOptional() @IsOptional() - @IsUUID() + @IsUUID('4', { message: 'El ID de equipo debe ser un UUID valido' }) teamId?: string; @ApiPropertyOptional({ example: 50000 }) @IsOptional() - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El objetivo personalizado debe ser un numero' }) + @Min(0, { message: 'El objetivo personalizado debe ser mayor o igual a 0' }) customTarget?: number; @ApiPropertyOptional() @IsOptional() - @IsString() + @IsString({ message: 'Las notas deben ser una cadena de texto' }) notes?: string; } @@ -62,23 +62,23 @@ export class UpdateAssignmentStatusDto { export class UpdateProgressDto { @ApiProperty({ example: 25000 }) - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El valor debe ser un numero' }) + @Min(0, { message: 'El valor debe ser mayor o igual a 0' }) value: number; @ApiPropertyOptional({ enum: ProgressSource, default: ProgressSource.MANUAL }) @IsOptional() - @IsEnum(ProgressSource) + @IsEnum(ProgressSource, { message: 'La fuente de progreso debe ser un valor valido' }) source?: ProgressSource; @ApiPropertyOptional() @IsOptional() - @IsString() + @IsString({ message: 'La referencia de fuente debe ser una cadena de texto' }) sourceReference?: string; @ApiPropertyOptional() @IsOptional() - @IsString() + @IsString({ message: 'Las notas deben ser una cadena de texto' }) notes?: string; } @@ -159,38 +159,38 @@ export class AssignmentResponseDto { export class AssignmentFiltersDto { @ApiPropertyOptional() @IsOptional() - @IsUUID() + @IsUUID('4', { message: 'El ID de definicion debe ser un UUID valido' }) definitionId?: string; @ApiPropertyOptional() @IsOptional() - @IsUUID() + @IsUUID('4', { message: 'El ID de usuario debe ser un UUID valido' }) userId?: string; @ApiPropertyOptional({ enum: AssignmentStatus }) @IsOptional() - @IsEnum(AssignmentStatus) + @IsEnum(AssignmentStatus, { message: 'El estado debe ser un valor valido' }) status?: AssignmentStatus; @ApiPropertyOptional({ enum: AssigneeType }) @IsOptional() - @IsEnum(AssigneeType) + @IsEnum(AssigneeType, { message: 'El tipo de asignado debe ser un valor valido' }) assigneeType?: AssigneeType; @ApiPropertyOptional({ description: 'Minimum progress percentage' }) @IsOptional() @Type(() => Number) - @IsNumber() - @Min(0) - @Max(100) + @IsNumber({}, { message: 'El progreso minimo debe ser un numero' }) + @Min(0, { message: 'El progreso minimo debe ser mayor o igual a 0%' }) + @Max(100, { message: 'El progreso minimo debe ser menor o igual a 100%' }) minProgress?: number; @ApiPropertyOptional({ description: 'Maximum progress percentage' }) @IsOptional() @Type(() => Number) - @IsNumber() - @Min(0) - @Max(100) + @IsNumber({}, { message: 'El progreso maximo debe ser un numero' }) + @Min(0, { message: 'El progreso maximo debe ser mayor o igual a 0%' }) + @Max(100, { message: 'El progreso maximo debe ser menor o igual a 100%' }) maxProgress?: number; @ApiPropertyOptional({ example: 'progressPercentage' }) diff --git a/src/modules/goals/dto/definition.dto.ts b/src/modules/goals/dto/definition.dto.ts index e6e35b3..11870bd 100644 --- a/src/modules/goals/dto/definition.dto.ts +++ b/src/modules/goals/dto/definition.dto.ts @@ -9,12 +9,12 @@ import { GoalType, MetricType, PeriodType, DataSource, GoalStatus, SourceConfig, export class MilestoneDto { @ApiProperty({ example: 50 }) - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El porcentaje debe ser un numero' }) + @Min(0, { message: 'El porcentaje debe ser mayor o igual a 0' }) percentage: number; @ApiProperty({ example: true }) - @IsBoolean() + @IsBoolean({ message: 'Notificar debe ser verdadero o falso' }) notify: boolean; } @@ -55,57 +55,57 @@ export class SourceConfigDto { export class CreateDefinitionDto { @ApiProperty({ example: 'Q1 Sales Target' }) - @IsString() + @IsString({ message: 'El nombre debe ser una cadena de texto' }) name: string; @ApiPropertyOptional({ example: 'Achieve $100,000 in closed deals' }) @IsOptional() - @IsString() + @IsString({ message: 'La descripcion debe ser una cadena de texto' }) description?: string; @ApiPropertyOptional({ example: 'sales' }) @IsOptional() - @IsString() + @IsString({ message: 'La categoria debe ser una cadena de texto' }) category?: string; @ApiPropertyOptional({ enum: GoalType, default: GoalType.TARGET }) @IsOptional() - @IsEnum(GoalType) + @IsEnum(GoalType, { message: 'El tipo de meta debe ser un valor valido' }) type?: GoalType; @ApiPropertyOptional({ enum: MetricType, default: MetricType.NUMBER }) @IsOptional() - @IsEnum(MetricType) + @IsEnum(MetricType, { message: 'El tipo de metrica debe ser un valor valido' }) metric?: MetricType; @ApiProperty({ example: 100000 }) - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El valor objetivo debe ser un numero' }) + @Min(0, { message: 'El valor objetivo debe ser mayor o igual a 0' }) targetValue: number; @ApiPropertyOptional({ example: 'USD' }) @IsOptional() - @IsString() + @IsString({ message: 'La unidad debe ser una cadena de texto' }) unit?: string; @ApiPropertyOptional({ enum: PeriodType, default: PeriodType.MONTHLY }) @IsOptional() - @IsEnum(PeriodType) + @IsEnum(PeriodType, { message: 'El tipo de periodo debe ser un valor valido' }) period?: PeriodType; @ApiProperty({ example: '2026-01-01' }) @Type(() => Date) - @IsDate() + @IsDate({ message: 'La fecha de inicio debe ser una fecha valida' }) startsAt: Date; @ApiProperty({ example: '2026-03-31' }) @Type(() => Date) - @IsDate() + @IsDate({ message: 'La fecha de fin debe ser una fecha valida' }) endsAt: Date; @ApiPropertyOptional({ enum: DataSource, default: DataSource.MANUAL }) @IsOptional() - @IsEnum(DataSource) + @IsEnum(DataSource, { message: 'La fuente de datos debe ser un valor valido' }) source?: DataSource; @ApiPropertyOptional({ type: SourceConfigDto }) @@ -116,20 +116,20 @@ export class CreateDefinitionDto { @ApiPropertyOptional({ type: [MilestoneDto] }) @IsOptional() - @IsArray() + @IsArray({ message: 'Los hitos deben ser un arreglo' }) @ValidateNested({ each: true }) @Type(() => MilestoneDto) milestones?: MilestoneDto[]; @ApiPropertyOptional({ enum: GoalStatus, default: GoalStatus.DRAFT }) @IsOptional() - @IsEnum(GoalStatus) + @IsEnum(GoalStatus, { message: 'El estado de la meta debe ser un valor valido' }) status?: GoalStatus; @ApiPropertyOptional({ type: [String], example: ['sales', 'q1'] }) @IsOptional() - @IsArray() - @IsString({ each: true }) + @IsArray({ message: 'Las etiquetas deben ser un arreglo' }) + @IsString({ each: true, message: 'Cada etiqueta debe ser una cadena de texto' }) tags?: string[]; } diff --git a/src/modules/mlm/dto/commission.dto.ts b/src/modules/mlm/dto/commission.dto.ts index 3fdaaed..6d3b4aa 100644 --- a/src/modules/mlm/dto/commission.dto.ts +++ b/src/modules/mlm/dto/commission.dto.ts @@ -14,33 +14,33 @@ import { BonusType } from '../entities/bonus.entity'; export class CalculateCommissionsDto { @ApiProperty({ description: 'Source node ID (who generated the sale)' }) - @IsUUID() + @IsUUID('4', { message: 'El ID del nodo origen debe ser un UUID valido' }) sourceNodeId: string; @ApiProperty({ description: 'Amount to calculate commissions on' }) - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto debe ser un numero' }) + @Min(0, { message: 'El monto debe ser mayor o igual a 0' }) amount: number; @ApiPropertyOptional({ description: 'Currency', default: 'USD' }) @IsOptional() - @IsString() + @IsString({ message: 'La moneda debe ser una cadena de texto' }) currency?: string; @ApiPropertyOptional({ description: 'Source reference (sale ID, etc.)' }) @IsOptional() - @IsString() + @IsString({ message: 'La referencia origen debe ser una cadena de texto' }) sourceReference?: string; @ApiPropertyOptional({ description: 'Period ID' }) @IsOptional() - @IsUUID() + @IsUUID('4', { message: 'El ID del periodo debe ser un UUID valido' }) periodId?: string; } export class UpdateCommissionStatusDto { @ApiProperty({ description: 'New status', enum: CommissionStatus }) - @IsEnum(CommissionStatus) + @IsEnum(CommissionStatus, { message: 'El estado debe ser un valor valido' }) status: CommissionStatus; } diff --git a/src/modules/portfolio/dto/product.dto.ts b/src/modules/portfolio/dto/product.dto.ts index d78114c..ef98339 100644 --- a/src/modules/portfolio/dto/product.dto.ts +++ b/src/modules/portfolio/dto/product.dto.ts @@ -19,57 +19,57 @@ import { PriceType } from '../entities/price.entity'; // ============================================ export class CreateProductDto { - @IsString() - @MaxLength(255) + @IsString({ message: 'El nombre debe ser una cadena de texto' }) + @MaxLength(255, { message: 'El nombre no puede exceder 255 caracteres' }) name: string; - @IsString() - @MaxLength(280) + @IsString({ message: 'El slug debe ser una cadena de texto' }) + @MaxLength(280, { message: 'El slug no puede exceder 280 caracteres' }) slug: string; - @IsUUID() + @IsUUID('4', { message: 'El ID de categoria debe ser un UUID valido' }) @IsOptional() categoryId?: string; - @IsString() - @MaxLength(100) + @IsString({ message: 'El SKU debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El SKU no puede exceder 100 caracteres' }) @IsOptional() sku?: string; - @IsString() - @MaxLength(100) + @IsString({ message: 'El codigo de barras debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El codigo de barras no puede exceder 100 caracteres' }) @IsOptional() barcode?: string; - @IsString() + @IsString({ message: 'La descripcion debe ser una cadena de texto' }) @IsOptional() description?: string; - @IsString() - @MaxLength(500) + @IsString({ message: 'La descripcion corta debe ser una cadena de texto' }) + @MaxLength(500, { message: 'La descripcion corta no puede exceder 500 caracteres' }) @IsOptional() shortDescription?: string; - @IsEnum(ProductType) + @IsEnum(ProductType, { message: 'El tipo de producto debe ser un valor valido' }) @IsOptional() productType?: ProductType; - @IsEnum(ProductStatus) + @IsEnum(ProductStatus, { message: 'El estado del producto debe ser un valor valido' }) @IsOptional() status?: ProductStatus; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El precio base debe ser un numero' }) + @Min(0, { message: 'El precio base debe ser mayor o igual a 0' }) @IsOptional() basePrice?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El precio de costo debe ser un numero' }) + @Min(0, { message: 'El precio de costo debe ser mayor o igual a 0' }) @IsOptional() costPrice?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El precio de comparacion debe ser un numero' }) + @Min(0, { message: 'El precio de comparacion debe ser mayor o igual a 0' }) @IsOptional() compareAtPrice?: number; @@ -78,252 +78,252 @@ export class CreateProductDto { @IsOptional() currency?: string; - @IsBoolean() + @IsBoolean({ message: 'Seguir inventario debe ser verdadero o falso' }) @IsOptional() trackInventory?: boolean; - @IsInt() - @Min(0) + @IsInt({ message: 'La cantidad en stock debe ser un numero entero' }) + @Min(0, { message: 'La cantidad en stock debe ser mayor o igual a 0' }) @IsOptional() stockQuantity?: number; - @IsInt() - @Min(0) + @IsInt({ message: 'El umbral de stock bajo debe ser un numero entero' }) + @Min(0, { message: 'El umbral de stock bajo debe ser mayor o igual a 0' }) @IsOptional() lowStockThreshold?: number; - @IsBoolean() + @IsBoolean({ message: 'Permitir backorder debe ser verdadero o falso' }) @IsOptional() allowBackorder?: boolean; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El peso debe ser un numero' }) + @Min(0, { message: 'El peso debe ser mayor o igual a 0' }) @IsOptional() weight?: number; - @IsString() - @MaxLength(10) + @IsString({ message: 'La unidad de peso debe ser una cadena de texto' }) + @MaxLength(10, { message: 'La unidad de peso no puede exceder 10 caracteres' }) @IsOptional() weightUnit?: string; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'La longitud debe ser un numero' }) + @Min(0, { message: 'La longitud debe ser mayor o igual a 0' }) @IsOptional() length?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El ancho debe ser un numero' }) + @Min(0, { message: 'El ancho debe ser mayor o igual a 0' }) @IsOptional() width?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'La altura debe ser un numero' }) + @Min(0, { message: 'La altura debe ser mayor o igual a 0' }) @IsOptional() height?: number; - @IsString() - @MaxLength(10) + @IsString({ message: 'La unidad de dimension debe ser una cadena de texto' }) + @MaxLength(10, { message: 'La unidad de dimension no puede exceder 10 caracteres' }) @IsOptional() dimensionUnit?: string; - @IsArray() + @IsArray({ message: 'Las imagenes deben ser un arreglo' }) @IsOptional() images?: string[]; - @IsString() - @MaxLength(500) + @IsString({ message: 'La URL de imagen destacada debe ser una cadena de texto' }) + @MaxLength(500, { message: 'La URL de imagen destacada no puede exceder 500 caracteres' }) @IsOptional() featuredImageUrl?: string; - @IsString() - @MaxLength(200) + @IsString({ message: 'El titulo meta debe ser una cadena de texto' }) + @MaxLength(200, { message: 'El titulo meta no puede exceder 200 caracteres' }) @IsOptional() metaTitle?: string; - @IsString() + @IsString({ message: 'La descripcion meta debe ser una cadena de texto' }) @IsOptional() metaDescription?: string; - @IsArray() + @IsArray({ message: 'Las etiquetas deben ser un arreglo' }) @IsOptional() tags?: string[]; - @IsBoolean() + @IsBoolean({ message: 'Visibilidad debe ser verdadero o falso' }) @IsOptional() isVisible?: boolean; - @IsBoolean() + @IsBoolean({ message: 'Destacado debe ser verdadero o falso' }) @IsOptional() isFeatured?: boolean; - @IsBoolean() + @IsBoolean({ message: 'Tiene variantes debe ser verdadero o falso' }) @IsOptional() hasVariants?: boolean; - @IsArray() + @IsArray({ message: 'Los atributos de variantes deben ser un arreglo' }) @IsOptional() variantAttributes?: string[]; - @IsObject() + @IsObject({ message: 'Los campos personalizados deben ser un objeto' }) @IsOptional() customFields?: Record; } export class UpdateProductDto { - @IsString() - @MaxLength(255) + @IsString({ message: 'El nombre debe ser una cadena de texto' }) + @MaxLength(255, { message: 'El nombre no puede exceder 255 caracteres' }) @IsOptional() name?: string; - @IsString() - @MaxLength(280) + @IsString({ message: 'El slug debe ser una cadena de texto' }) + @MaxLength(280, { message: 'El slug no puede exceder 280 caracteres' }) @IsOptional() slug?: string; - @IsUUID() + @IsUUID('4', { message: 'El ID de categoria debe ser un UUID valido' }) @IsOptional() categoryId?: string | null; - @IsString() - @MaxLength(100) + @IsString({ message: 'El SKU debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El SKU no puede exceder 100 caracteres' }) @IsOptional() sku?: string; - @IsString() - @MaxLength(100) + @IsString({ message: 'El codigo de barras debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El codigo de barras no puede exceder 100 caracteres' }) @IsOptional() barcode?: string; - @IsString() + @IsString({ message: 'La descripcion debe ser una cadena de texto' }) @IsOptional() description?: string; - @IsString() - @MaxLength(500) + @IsString({ message: 'La descripcion corta debe ser una cadena de texto' }) + @MaxLength(500, { message: 'La descripcion corta no puede exceder 500 caracteres' }) @IsOptional() shortDescription?: string; - @IsEnum(ProductType) + @IsEnum(ProductType, { message: 'El tipo de producto debe ser un valor valido' }) @IsOptional() productType?: ProductType; - @IsEnum(ProductStatus) + @IsEnum(ProductStatus, { message: 'El estado del producto debe ser un valor valido' }) @IsOptional() status?: ProductStatus; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El precio base debe ser un numero' }) + @Min(0, { message: 'El precio base debe ser mayor o igual a 0' }) @IsOptional() basePrice?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El precio de costo debe ser un numero' }) + @Min(0, { message: 'El precio de costo debe ser mayor o igual a 0' }) @IsOptional() costPrice?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El precio de comparacion debe ser un numero' }) + @Min(0, { message: 'El precio de comparacion debe ser mayor o igual a 0' }) @IsOptional() compareAtPrice?: number; - @IsString() - @MaxLength(3) + @IsString({ message: 'La moneda debe ser una cadena de texto' }) + @MaxLength(3, { message: 'La moneda no puede exceder 3 caracteres' }) @IsOptional() currency?: string; - @IsBoolean() + @IsBoolean({ message: 'Seguir inventario debe ser verdadero o falso' }) @IsOptional() trackInventory?: boolean; - @IsInt() - @Min(0) + @IsInt({ message: 'La cantidad en stock debe ser un numero entero' }) + @Min(0, { message: 'La cantidad en stock debe ser mayor o igual a 0' }) @IsOptional() stockQuantity?: number; - @IsInt() - @Min(0) + @IsInt({ message: 'El umbral de stock bajo debe ser un numero entero' }) + @Min(0, { message: 'El umbral de stock bajo debe ser mayor o igual a 0' }) @IsOptional() lowStockThreshold?: number; - @IsBoolean() + @IsBoolean({ message: 'Permitir backorder debe ser verdadero o falso' }) @IsOptional() allowBackorder?: boolean; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El peso debe ser un numero' }) + @Min(0, { message: 'El peso debe ser mayor o igual a 0' }) @IsOptional() weight?: number; - @IsString() - @MaxLength(10) + @IsString({ message: 'La unidad de peso debe ser una cadena de texto' }) + @MaxLength(10, { message: 'La unidad de peso no puede exceder 10 caracteres' }) @IsOptional() weightUnit?: string; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'La longitud debe ser un numero' }) + @Min(0, { message: 'La longitud debe ser mayor o igual a 0' }) @IsOptional() length?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El ancho debe ser un numero' }) + @Min(0, { message: 'El ancho debe ser mayor o igual a 0' }) @IsOptional() width?: number; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'La altura debe ser un numero' }) + @Min(0, { message: 'La altura debe ser mayor o igual a 0' }) @IsOptional() height?: number; - @IsString() - @MaxLength(10) + @IsString({ message: 'La unidad de dimension debe ser una cadena de texto' }) + @MaxLength(10, { message: 'La unidad de dimension no puede exceder 10 caracteres' }) @IsOptional() dimensionUnit?: string; - @IsArray() + @IsArray({ message: 'Las imagenes deben ser un arreglo' }) @IsOptional() images?: string[]; - @IsString() - @MaxLength(500) + @IsString({ message: 'La URL de imagen destacada debe ser una cadena de texto' }) + @MaxLength(500, { message: 'La URL de imagen destacada no puede exceder 500 caracteres' }) @IsOptional() featuredImageUrl?: string; - @IsString() - @MaxLength(200) + @IsString({ message: 'El titulo meta debe ser una cadena de texto' }) + @MaxLength(200, { message: 'El titulo meta no puede exceder 200 caracteres' }) @IsOptional() metaTitle?: string; - @IsString() + @IsString({ message: 'La descripcion meta debe ser una cadena de texto' }) @IsOptional() metaDescription?: string; - @IsArray() + @IsArray({ message: 'Las etiquetas deben ser un arreglo' }) @IsOptional() tags?: string[]; - @IsBoolean() + @IsBoolean({ message: 'Visibilidad debe ser verdadero o falso' }) @IsOptional() isVisible?: boolean; - @IsBoolean() + @IsBoolean({ message: 'Destacado debe ser verdadero o falso' }) @IsOptional() isFeatured?: boolean; - @IsBoolean() + @IsBoolean({ message: 'Tiene variantes debe ser verdadero o falso' }) @IsOptional() hasVariants?: boolean; - @IsArray() + @IsArray({ message: 'Los atributos de variantes deben ser un arreglo' }) @IsOptional() variantAttributes?: string[]; - @IsObject() + @IsObject({ message: 'Los campos personalizados deben ser un objeto' }) @IsOptional() customFields?: Record; } export class UpdateProductStatusDto { - @IsEnum(ProductStatus) + @IsEnum(ProductStatus, { message: 'El estado del producto debe ser un valor valido' }) status: ProductStatus; } diff --git a/src/modules/sales/dto/lead.dto.ts b/src/modules/sales/dto/lead.dto.ts index fa6d7b9..8e196af 100644 --- a/src/modules/sales/dto/lead.dto.ts +++ b/src/modules/sales/dto/lead.dto.ts @@ -14,195 +14,195 @@ import { import { LeadStatus, LeadSource } from '../entities'; export class CreateLeadDto { - @IsString() - @MaxLength(100) + @IsString({ message: 'El nombre debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El nombre no puede exceder 100 caracteres' }) firstName: string; - @IsString() - @MaxLength(100) + @IsString({ message: 'El apellido debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El apellido no puede exceder 100 caracteres' }) lastName: string; - @IsEmail() + @IsEmail({}, { message: 'El email debe tener un formato valido' }) @IsOptional() email?: string; - @IsString() - @MaxLength(50) + @IsString({ message: 'El telefono debe ser una cadena de texto' }) + @MaxLength(50, { message: 'El telefono no puede exceder 50 caracteres' }) @IsOptional() phone?: string; - @IsString() - @MaxLength(200) + @IsString({ message: 'La empresa debe ser una cadena de texto' }) + @MaxLength(200, { message: 'La empresa no puede exceder 200 caracteres' }) @IsOptional() company?: string; - @IsString() - @MaxLength(150) + @IsString({ message: 'El puesto debe ser una cadena de texto' }) + @MaxLength(150, { message: 'El puesto no puede exceder 150 caracteres' }) @IsOptional() jobTitle?: string; - @IsString() - @MaxLength(255) + @IsString({ message: 'El sitio web debe ser una cadena de texto' }) + @MaxLength(255, { message: 'El sitio web no puede exceder 255 caracteres' }) @IsOptional() website?: string; - @IsEnum(LeadSource) + @IsEnum(LeadSource, { message: 'El origen del lead debe ser un valor valido' }) @IsOptional() source?: LeadSource; - @IsEnum(LeadStatus) + @IsEnum(LeadStatus, { message: 'El estado del lead debe ser un valor valido' }) @IsOptional() status?: LeadStatus; - @IsInt() - @Min(0) - @Max(100) + @IsInt({ message: 'El score debe ser un numero entero' }) + @Min(0, { message: 'El score debe ser mayor o igual a 0' }) + @Max(100, { message: 'El score debe ser menor o igual a 100' }) @IsOptional() score?: number; - @IsUUID() + @IsUUID('4', { message: 'El ID del asignado debe ser un UUID valido' }) @IsOptional() assignedTo?: string; - @IsString() + @IsString({ message: 'Las notas deben ser una cadena de texto' }) @IsOptional() notes?: string; - @IsString() - @MaxLength(255) + @IsString({ message: 'La direccion linea 1 debe ser una cadena de texto' }) + @MaxLength(255, { message: 'La direccion linea 1 no puede exceder 255 caracteres' }) @IsOptional() addressLine1?: string; - @IsString() - @MaxLength(255) + @IsString({ message: 'La direccion linea 2 debe ser una cadena de texto' }) + @MaxLength(255, { message: 'La direccion linea 2 no puede exceder 255 caracteres' }) @IsOptional() addressLine2?: string; - @IsString() - @MaxLength(100) + @IsString({ message: 'La ciudad debe ser una cadena de texto' }) + @MaxLength(100, { message: 'La ciudad no puede exceder 100 caracteres' }) @IsOptional() city?: string; - @IsString() - @MaxLength(100) + @IsString({ message: 'El estado/provincia debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El estado/provincia no puede exceder 100 caracteres' }) @IsOptional() state?: string; - @IsString() - @MaxLength(20) + @IsString({ message: 'El codigo postal debe ser una cadena de texto' }) + @MaxLength(20, { message: 'El codigo postal no puede exceder 20 caracteres' }) @IsOptional() postalCode?: string; - @IsString() - @MaxLength(100) + @IsString({ message: 'El pais debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El pais no puede exceder 100 caracteres' }) @IsOptional() country?: string; - @IsObject() + @IsObject({ message: 'Los campos personalizados deben ser un objeto' }) @IsOptional() customFields?: Record; } export class UpdateLeadDto { - @IsString() - @MaxLength(100) + @IsString({ message: 'El nombre debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El nombre no puede exceder 100 caracteres' }) @IsOptional() firstName?: string; - @IsString() - @MaxLength(100) + @IsString({ message: 'El apellido debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El apellido no puede exceder 100 caracteres' }) @IsOptional() lastName?: string; - @IsEmail() + @IsEmail({}, { message: 'El email debe tener un formato valido' }) @IsOptional() email?: string; - @IsString() - @MaxLength(50) + @IsString({ message: 'El telefono debe ser una cadena de texto' }) + @MaxLength(50, { message: 'El telefono no puede exceder 50 caracteres' }) @IsOptional() phone?: string; - @IsString() - @MaxLength(200) + @IsString({ message: 'La empresa debe ser una cadena de texto' }) + @MaxLength(200, { message: 'La empresa no puede exceder 200 caracteres' }) @IsOptional() company?: string; - @IsString() - @MaxLength(150) + @IsString({ message: 'El puesto debe ser una cadena de texto' }) + @MaxLength(150, { message: 'El puesto no puede exceder 150 caracteres' }) @IsOptional() jobTitle?: string; - @IsString() - @MaxLength(255) + @IsString({ message: 'El sitio web debe ser una cadena de texto' }) + @MaxLength(255, { message: 'El sitio web no puede exceder 255 caracteres' }) @IsOptional() website?: string; - @IsEnum(LeadSource) + @IsEnum(LeadSource, { message: 'El origen del lead debe ser un valor valido' }) @IsOptional() source?: LeadSource; - @IsEnum(LeadStatus) + @IsEnum(LeadStatus, { message: 'El estado del lead debe ser un valor valido' }) @IsOptional() status?: LeadStatus; - @IsInt() - @Min(0) - @Max(100) + @IsInt({ message: 'El score debe ser un numero entero' }) + @Min(0, { message: 'El score debe ser mayor o igual a 0' }) + @Max(100, { message: 'El score debe ser menor o igual a 100' }) @IsOptional() score?: number; - @IsUUID() + @IsUUID('4', { message: 'El ID del asignado debe ser un UUID valido' }) @IsOptional() assignedTo?: string; - @IsString() + @IsString({ message: 'Las notas deben ser una cadena de texto' }) @IsOptional() notes?: string; - @IsString() - @MaxLength(255) + @IsString({ message: 'La direccion linea 1 debe ser una cadena de texto' }) + @MaxLength(255, { message: 'La direccion linea 1 no puede exceder 255 caracteres' }) @IsOptional() addressLine1?: string; - @IsString() - @MaxLength(255) + @IsString({ message: 'La direccion linea 2 debe ser una cadena de texto' }) + @MaxLength(255, { message: 'La direccion linea 2 no puede exceder 255 caracteres' }) @IsOptional() addressLine2?: string; - @IsString() - @MaxLength(100) + @IsString({ message: 'La ciudad debe ser una cadena de texto' }) + @MaxLength(100, { message: 'La ciudad no puede exceder 100 caracteres' }) @IsOptional() city?: string; - @IsString() - @MaxLength(100) + @IsString({ message: 'El estado/provincia debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El estado/provincia no puede exceder 100 caracteres' }) @IsOptional() state?: string; - @IsString() - @MaxLength(20) + @IsString({ message: 'El codigo postal debe ser una cadena de texto' }) + @MaxLength(20, { message: 'El codigo postal no puede exceder 20 caracteres' }) @IsOptional() postalCode?: string; - @IsString() - @MaxLength(100) + @IsString({ message: 'El pais debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El pais no puede exceder 100 caracteres' }) @IsOptional() country?: string; - @IsObject() + @IsObject({ message: 'Los campos personalizados deben ser un objeto' }) @IsOptional() customFields?: Record; } export class ConvertLeadDto { - @IsString() - @MaxLength(255) + @IsString({ message: 'El nombre de oportunidad debe ser una cadena de texto' }) + @MaxLength(255, { message: 'El nombre de oportunidad no puede exceder 255 caracteres' }) @IsOptional() opportunityName?: string; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto debe ser un numero' }) + @Min(0, { message: 'El monto debe ser mayor o igual a 0' }) @IsOptional() amount?: number; diff --git a/src/modules/sales/dto/opportunity.dto.ts b/src/modules/sales/dto/opportunity.dto.ts index b4c498c..dfa34f2 100644 --- a/src/modules/sales/dto/opportunity.dto.ts +++ b/src/modules/sales/dto/opportunity.dto.ts @@ -15,158 +15,158 @@ import { import { OpportunityStage } from '../entities'; export class CreateOpportunityDto { - @IsString() - @MaxLength(255) + @IsString({ message: 'El nombre debe ser una cadena de texto' }) + @MaxLength(255, { message: 'El nombre no puede exceder 255 caracteres' }) name: string; - @IsString() + @IsString({ message: 'La descripcion debe ser una cadena de texto' }) @IsOptional() description?: string; - @IsUUID() + @IsUUID('4', { message: 'El ID del lead debe ser un UUID valido' }) @IsOptional() leadId?: string; - @IsEnum(OpportunityStage) + @IsEnum(OpportunityStage, { message: 'La etapa debe ser un valor valido' }) @IsOptional() stage?: OpportunityStage; - @IsUUID() + @IsUUID('4', { message: 'El ID de etapa debe ser un UUID valido' }) @IsOptional() stageId?: string; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto debe ser un numero' }) + @Min(0, { message: 'El monto debe ser mayor o igual a 0' }) @IsOptional() amount?: number; - @IsString() - @MaxLength(3) + @IsString({ message: 'La moneda debe ser una cadena de texto' }) + @MaxLength(3, { message: 'La moneda no puede exceder 3 caracteres' }) @IsOptional() currency?: string; - @IsInt() - @Min(0) - @Max(100) + @IsInt({ message: 'La probabilidad debe ser un numero entero' }) + @Min(0, { message: 'La probabilidad debe ser mayor o igual a 0%' }) + @Max(100, { message: 'La probabilidad debe ser menor o igual a 100%' }) @IsOptional() probability?: number; - @IsDateString() + @IsDateString({}, { message: 'La fecha esperada de cierre debe ser una fecha valida' }) @IsOptional() expectedCloseDate?: string; - @IsUUID() + @IsUUID('4', { message: 'El ID del asignado debe ser un UUID valido' }) @IsOptional() assignedTo?: string; - @IsString() - @MaxLength(200) + @IsString({ message: 'El nombre del contacto debe ser una cadena de texto' }) + @MaxLength(200, { message: 'El nombre del contacto no puede exceder 200 caracteres' }) @IsOptional() contactName?: string; - @IsEmail() + @IsEmail({}, { message: 'El email del contacto debe tener un formato valido' }) @IsOptional() contactEmail?: string; - @IsString() - @MaxLength(50) + @IsString({ message: 'El telefono del contacto debe ser una cadena de texto' }) + @MaxLength(50, { message: 'El telefono del contacto no puede exceder 50 caracteres' }) @IsOptional() contactPhone?: string; - @IsString() - @MaxLength(200) + @IsString({ message: 'El nombre de la empresa debe ser una cadena de texto' }) + @MaxLength(200, { message: 'El nombre de la empresa no puede exceder 200 caracteres' }) @IsOptional() companyName?: string; - @IsString() + @IsString({ message: 'Las notas deben ser una cadena de texto' }) @IsOptional() notes?: string; - @IsObject() + @IsObject({ message: 'Los campos personalizados deben ser un objeto' }) @IsOptional() customFields?: Record; } export class UpdateOpportunityDto { - @IsString() - @MaxLength(255) + @IsString({ message: 'El nombre debe ser una cadena de texto' }) + @MaxLength(255, { message: 'El nombre no puede exceder 255 caracteres' }) @IsOptional() name?: string; - @IsString() + @IsString({ message: 'La descripcion debe ser una cadena de texto' }) @IsOptional() description?: string; - @IsEnum(OpportunityStage) + @IsEnum(OpportunityStage, { message: 'La etapa debe ser un valor valido' }) @IsOptional() stage?: OpportunityStage; - @IsUUID() + @IsUUID('4', { message: 'El ID de etapa debe ser un UUID valido' }) @IsOptional() stageId?: string; - @IsNumber() - @Min(0) + @IsNumber({}, { message: 'El monto debe ser un numero' }) + @Min(0, { message: 'El monto debe ser mayor o igual a 0' }) @IsOptional() amount?: number; - @IsString() - @MaxLength(3) + @IsString({ message: 'La moneda debe ser una cadena de texto' }) + @MaxLength(3, { message: 'La moneda no puede exceder 3 caracteres' }) @IsOptional() currency?: string; - @IsInt() - @Min(0) - @Max(100) + @IsInt({ message: 'La probabilidad debe ser un numero entero' }) + @Min(0, { message: 'La probabilidad debe ser mayor o igual a 0%' }) + @Max(100, { message: 'La probabilidad debe ser menor o igual a 100%' }) @IsOptional() probability?: number; - @IsDateString() + @IsDateString({}, { message: 'La fecha esperada de cierre debe ser una fecha valida' }) @IsOptional() expectedCloseDate?: string; - @IsUUID() + @IsUUID('4', { message: 'El ID del asignado debe ser un UUID valido' }) @IsOptional() assignedTo?: string; - @IsString() - @MaxLength(500) + @IsString({ message: 'La razon de perdida debe ser una cadena de texto' }) + @MaxLength(500, { message: 'La razon de perdida no puede exceder 500 caracteres' }) @IsOptional() lostReason?: string; - @IsString() - @MaxLength(200) + @IsString({ message: 'El nombre del contacto debe ser una cadena de texto' }) + @MaxLength(200, { message: 'El nombre del contacto no puede exceder 200 caracteres' }) @IsOptional() contactName?: string; - @IsEmail() + @IsEmail({}, { message: 'El email del contacto debe tener un formato valido' }) @IsOptional() contactEmail?: string; - @IsString() - @MaxLength(50) + @IsString({ message: 'El telefono del contacto debe ser una cadena de texto' }) + @MaxLength(50, { message: 'El telefono del contacto no puede exceder 50 caracteres' }) @IsOptional() contactPhone?: string; - @IsString() - @MaxLength(200) + @IsString({ message: 'El nombre de la empresa debe ser una cadena de texto' }) + @MaxLength(200, { message: 'El nombre de la empresa no puede exceder 200 caracteres' }) @IsOptional() companyName?: string; - @IsString() + @IsString({ message: 'Las notas deben ser una cadena de texto' }) @IsOptional() notes?: string; - @IsObject() + @IsObject({ message: 'Los campos personalizados deben ser un objeto' }) @IsOptional() customFields?: Record; } export class UpdateOpportunityStageDto { - @IsEnum(OpportunityStage) + @IsEnum(OpportunityStage, { message: 'La etapa debe ser un valor valido' }) stage: OpportunityStage; - @IsString() + @IsString({ message: 'Las notas deben ser una cadena de texto' }) @IsOptional() notes?: string; } diff --git a/src/modules/webhooks/dto/webhook.dto.ts b/src/modules/webhooks/dto/webhook.dto.ts index 708541a..7679e5e 100644 --- a/src/modules/webhooks/dto/webhook.dto.ts +++ b/src/modules/webhooks/dto/webhook.dto.ts @@ -31,52 +31,52 @@ export type WebhookEvent = (typeof WEBHOOK_EVENTS)[number]; // Create webhook DTO export class CreateWebhookDto { - @IsString() - @MaxLength(100) + @IsString({ message: 'El nombre debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El nombre no puede exceder 100 caracteres' }) name: string; - @IsString() + @IsString({ message: 'La descripcion debe ser una cadena de texto' }) @IsOptional() description?: string; - @IsUrl({ protocols: ['https'], require_protocol: true }) + @IsUrl({ protocols: ['https'], require_protocol: true }, { message: 'La URL debe ser HTTPS valida' }) url: string; - @IsArray() - @ArrayMinSize(1) - @IsString({ each: true }) + @IsArray({ message: 'Los eventos deben ser un arreglo' }) + @ArrayMinSize(1, { message: 'Debe seleccionar al menos un evento' }) + @IsString({ each: true, message: 'Cada evento debe ser una cadena de texto' }) events: string[]; - @IsObject() + @IsObject({ message: 'Los headers deben ser un objeto' }) @IsOptional() headers?: Record; } // Update webhook DTO export class UpdateWebhookDto { - @IsString() - @MaxLength(100) + @IsString({ message: 'El nombre debe ser una cadena de texto' }) + @MaxLength(100, { message: 'El nombre no puede exceder 100 caracteres' }) @IsOptional() name?: string; - @IsString() + @IsString({ message: 'La descripcion debe ser una cadena de texto' }) @IsOptional() description?: string; - @IsUrl({ protocols: ['https'], require_protocol: true }) + @IsUrl({ protocols: ['https'], require_protocol: true }, { message: 'La URL debe ser HTTPS valida' }) @IsOptional() url?: string; - @IsArray() - @IsString({ each: true }) + @IsArray({ message: 'Los eventos deben ser un arreglo' }) + @IsString({ each: true, message: 'Cada evento debe ser una cadena de texto' }) @IsOptional() events?: string[]; - @IsObject() + @IsObject({ message: 'Los headers deben ser un objeto' }) @IsOptional() headers?: Record; - @IsBoolean() + @IsBoolean({ message: 'Activo debe ser verdadero o falso' }) @IsOptional() isActive?: boolean; }