import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { ArrayNotEmpty, IsArray, IsIn, IsNotEmpty, IsOptional, IsString, IsUUID, Matches, MaxLength, ValidateIf, } from 'class-validator'; import { PaginationQueryDto, UserRelationDto, } from '../../../../common/http/response'; import { CORE_STATUSES } from '../../../../common/value-objects/status/status'; import { EMPLOYEE_CODE_MAX_LENGTH, EMPLOYEE_CODE_PATTERN, EMPLOYEE_NAME_MAX_LENGTH, EMPLOYEE_NAME_PATTERN, EMPLOYEE_POSITIONS, } from '../employee-fields'; export class CreateEmployeeDto { @ApiProperty({ example: 'EMP_01', maxLength: EMPLOYEE_CODE_MAX_LENGTH }) @IsString() @IsNotEmpty() @MaxLength(EMPLOYEE_CODE_MAX_LENGTH) @Matches(EMPLOYEE_CODE_PATTERN, { message: 'code must contain only letters, numbers, and underscores', }) code!: string; @ApiProperty({ example: 'Ada Lovelace', maxLength: EMPLOYEE_NAME_MAX_LENGTH, }) @IsString() @IsNotEmpty() @MaxLength(EMPLOYEE_NAME_MAX_LENGTH) @Matches(EMPLOYEE_NAME_PATTERN, { message: 'name must contain only letters and spaces', }) name!: string; @ApiProperty({ example: '+6281234567890' }) @IsString() @IsNotEmpty() phone!: string; @ApiProperty({ enum: EMPLOYEE_POSITIONS, example: 'sales' }) @IsIn([...EMPLOYEE_POSITIONS]) position!: string; @ApiPropertyOptional({ enum: CORE_STATUSES }) @IsOptional() @IsIn([...CORE_STATUSES]) status?: string; @ApiPropertyOptional({ format: 'uuid' }) @IsOptional() @IsUUID('4') userId?: string; } export class UpdateEmployeeDto { @ApiPropertyOptional({ example: 'EMP_01' }) @IsOptional() @IsString() @IsNotEmpty() @MaxLength(EMPLOYEE_CODE_MAX_LENGTH) @Matches(EMPLOYEE_CODE_PATTERN, { message: 'code must contain only letters, numbers, and underscores', }) code?: string; @ApiPropertyOptional({ example: 'Ada Lovelace' }) @IsOptional() @IsString() @IsNotEmpty() @MaxLength(EMPLOYEE_NAME_MAX_LENGTH) @Matches(EMPLOYEE_NAME_PATTERN, { message: 'name must contain only letters and spaces', }) name?: string; @ApiPropertyOptional({ example: '+6281234567890' }) @IsOptional() @IsString() @IsNotEmpty() phone?: string; @ApiPropertyOptional({ enum: EMPLOYEE_POSITIONS }) @IsOptional() @IsIn([...EMPLOYEE_POSITIONS]) position?: string; @ApiPropertyOptional({ format: 'uuid', nullable: true }) @ValidateIf((_, value) => value !== undefined) @IsUUID('4') userId?: string | null; } export class UpdateEmployeeStatusDto { @ApiProperty({ enum: CORE_STATUSES }) @IsIn([...CORE_STATUSES]) status!: string; } export class BulkIdsDto { @ApiProperty({ type: [String], format: 'uuid' }) @IsArray() @ArrayNotEmpty() @IsUUID('4', { each: true }) ids!: string[]; } export class BulkStatusDto { @ApiProperty({ type: [String], format: 'uuid' }) @IsArray() @ArrayNotEmpty() @IsUUID('4', { each: true }) ids!: string[]; @ApiProperty({ enum: CORE_STATUSES }) @IsIn([...CORE_STATUSES]) status!: string; } export class ListEmployeesQueryDto extends PaginationQueryDto { @ApiPropertyOptional() @IsOptional() @IsString() code?: string; @ApiPropertyOptional() @IsOptional() @IsString() name?: string; @ApiPropertyOptional() @IsOptional() @IsString() phone?: string; @ApiPropertyOptional({ enum: EMPLOYEE_POSITIONS }) @IsOptional() @IsIn([...EMPLOYEE_POSITIONS]) position?: string; @ApiPropertyOptional({ enum: CORE_STATUSES }) @IsOptional() @IsIn([...CORE_STATUSES]) status?: string; @ApiPropertyOptional({ format: 'uuid' }) @IsOptional() @IsUUID('4') userId?: string; @ApiPropertyOptional({ description: 'Case-insensitive match on code or name', }) @IsOptional() @IsString() search?: string; } export class EmployeeDto { @ApiProperty({ format: 'uuid' }) id!: string; @ApiProperty() code!: string; @ApiProperty() name!: string; @ApiProperty({ example: '+6281234567890' }) phone!: string; @ApiProperty({ enum: EMPLOYEE_POSITIONS }) position!: string; @ApiProperty({ enum: CORE_STATUSES }) status!: string; @ApiProperty({ description: 'Unix ms' }) createdAt!: number; @ApiProperty({ description: 'Unix ms' }) updatedAt!: number; @ApiProperty({ format: 'uuid' }) createdBy!: string; @ApiProperty({ format: 'uuid' }) updatedBy!: string; @ApiPropertyOptional({ type: UserRelationDto, nullable: true }) user!: UserRelationDto | null; }