[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 <noreply@anthropic.com>
This commit is contained in:
Adrian Flores Cortes 2026-02-03 17:23:09 -06:00
parent ff7fc41449
commit c4262498ee
10 changed files with 364 additions and 364 deletions

View File

@ -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<string, any>;
}
@ -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;
}

View File

@ -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;
}

View File

@ -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' })

View File

@ -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' })

View File

@ -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[];
}

View File

@ -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;
}

View File

@ -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<string, any>;
}
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<string, any>;
}
export class UpdateProductStatusDto {
@IsEnum(ProductStatus)
@IsEnum(ProductStatus, { message: 'El estado del producto debe ser un valor valido' })
status: ProductStatus;
}

View File

@ -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<string, any>;
}
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<string, any>;
}
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;

View File

@ -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<string, any>;
}
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<string, any>;
}
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;
}

View File

@ -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<string, string>;
}
// 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<string, string>;
@IsBoolean()
@IsBoolean({ message: 'Activo debe ser verdadero o falso' })
@IsOptional()
isActive?: boolean;
}