- Introduced new columns `status`, `created_by`, and `updated_by` in the `users` table to track user status and ownership. - Updated the `employees` table to include a foreign key reference to the `users` table via `user_id`. - Created migration script `0012_users_primary.sql` to apply these changes to the database schema. - Enhanced the `EmployeesService` and `EmployeesRepository` to support user assignments and related data retrieval. - Updated DTOs and service methods to reflect the new user and employee relationships. - Added unit tests to validate the new functionality and ensure data integrity. - Modified existing controllers to accommodate the new fields and relationships in user and employee management.
206 lines
4.4 KiB
TypeScript
206 lines
4.4 KiB
TypeScript
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;
|
|
}
|