146 lines
5.0 KiB
TypeScript
146 lines
5.0 KiB
TypeScript
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
import type { Prisma } from '@prisma/client';
|
|
import type { Response } from 'express';
|
|
import { PrismaService } from '../../prisma/prisma.service';
|
|
import { getFirst, setListHeaders, toArray, toDateValue, toDecimalValue, toNumberValue } from '../shared/query-utils';
|
|
import { CreateEmployeeDto } from './dto/create-employee.dto';
|
|
import { UpdateEmployeeDto } from './dto/update-employee.dto';
|
|
|
|
@Injectable()
|
|
export class EmployeeService {
|
|
constructor(private readonly prisma: PrismaService) {}
|
|
|
|
private toNested(item: any): Record<string, unknown> {
|
|
return {
|
|
id: item.code,
|
|
code: item.code,
|
|
fullName: item.fullName,
|
|
role: item.role,
|
|
position: item.position,
|
|
bossCode: item.bossCode,
|
|
price: item.price,
|
|
phoneNumber: item.phoneNumber,
|
|
};
|
|
}
|
|
|
|
private toRecord(item: any): Record<string, unknown> {
|
|
return {
|
|
id: item.code,
|
|
code: item.code,
|
|
fullName: item.fullName,
|
|
role: item.role,
|
|
position: item.position,
|
|
bossCode: item.bossCode,
|
|
boss: item.boss ? this.toNested(item.boss) : null,
|
|
subordinates: Array.isArray(item.subordinates) ? item.subordinates.map((subordinate: any) => this.toNested(subordinate)) : [],
|
|
price: item.price,
|
|
phoneNumber: item.phoneNumber,
|
|
};
|
|
}
|
|
async findAll(query: Record<string, string | string[] | undefined>, response: Response): Promise<Record<string, unknown>[]> {
|
|
const start = Number(getFirst(query._start) ?? 0);
|
|
const end = Number(getFirst(query._end) ?? start + 25);
|
|
const take = Math.max(end - start, 0) || 25;
|
|
const where: Record<string, unknown> = {};
|
|
const q = getFirst(query.q);
|
|
if (q) {
|
|
where.OR = [
|
|
{ code: { contains: q, mode: 'insensitive' } },
|
|
{ fullName: { contains: q, mode: 'insensitive' } },
|
|
{ position: { contains: q, mode: 'insensitive' } },
|
|
];
|
|
}
|
|
const code = getFirst(query.code);
|
|
if (code) where.code = { contains: code, mode: 'insensitive' };
|
|
const fullName = getFirst(query.fullName);
|
|
if (fullName) where.fullName = { contains: fullName, mode: 'insensitive' };
|
|
const position = getFirst(query.position);
|
|
if (position) where.position = { contains: position, mode: 'insensitive' };
|
|
const roleValues = toArray(query.role);
|
|
if (roleValues.length > 0) where.role = { in: Array.from(new Set(roleValues)) };
|
|
const boss = getFirst(query.boss);
|
|
if (boss) where.bossCode = boss;
|
|
const sortField = getFirst(query._sort) ?? 'code';
|
|
const prismaSortField = sortField === 'id' ? 'code' : sortField;
|
|
const sortOrder = (String(getFirst(query._order) ?? 'ASC').toLowerCase() === 'desc' ? 'desc' : 'asc') as Prisma.SortOrder;
|
|
|
|
const [items, total] = await this.prisma.$transaction([
|
|
this.prisma.employee.findMany({
|
|
where,
|
|
skip: start,
|
|
take,
|
|
orderBy: { [prismaSortField]: sortOrder },
|
|
include: {
|
|
boss: true,
|
|
subordinates: true,
|
|
},
|
|
}),
|
|
this.prisma.employee.count({ where }),
|
|
]);
|
|
|
|
setListHeaders(response, total, start, end, 'employees');
|
|
return items.map((item) => this.toRecord(item));
|
|
}
|
|
|
|
async findOne(code: string): Promise<Record<string, unknown>> {
|
|
const item = await this.prisma.employee.findUnique({ where: { code },
|
|
include: {
|
|
boss: true,
|
|
subordinates: true,
|
|
}, });
|
|
if (!item) throw new NotFoundException('Employee not found');
|
|
return this.toRecord(item);
|
|
}
|
|
|
|
async create(dto: CreateEmployeeDto): Promise<Record<string, unknown>> {
|
|
const created = await this.prisma.employee.create({ data: this.prepareCreateData(dto) as any,
|
|
include: {
|
|
boss: true,
|
|
subordinates: true,
|
|
}, });
|
|
return this.toRecord(created);
|
|
}
|
|
|
|
async update(code: string, dto: UpdateEmployeeDto): Promise<Record<string, unknown>> {
|
|
const updated = await this.prisma.employee.update({ where: { code }, data: this.prepareUpdateData(dto) as any,
|
|
include: {
|
|
boss: true,
|
|
subordinates: true,
|
|
}, });
|
|
return this.toRecord(updated);
|
|
}
|
|
|
|
async remove(code: string): Promise<Record<string, unknown>> {
|
|
const deleted = await this.prisma.employee.delete({ where: { code },
|
|
include: {
|
|
boss: true,
|
|
subordinates: true,
|
|
}, });
|
|
return this.toRecord(deleted);
|
|
}
|
|
|
|
private prepareCreateData(dto: CreateEmployeeDto): Record<string, unknown> {
|
|
return {
|
|
code: dto.code,
|
|
fullName: dto.fullName,
|
|
role: dto.role,
|
|
position: dto.position,
|
|
bossCode: dto.boss ?? null,
|
|
price: toNumberValue(dto.price),
|
|
phoneNumber: toNumberValue(dto.phoneNumber),
|
|
};
|
|
}
|
|
|
|
private prepareUpdateData(dto: UpdateEmployeeDto): Record<string, unknown> {
|
|
const { id, code: _pk, ...rest } = dto as Record<string, unknown> & { id?: string; code?: string };
|
|
return {
|
|
fullName: rest.fullName,
|
|
role: rest.role,
|
|
position: rest.position,
|
|
bossCode: rest.boss ?? null,
|
|
price: toNumberValue(rest.price),
|
|
phoneNumber: toNumberValue(rest.phoneNumber),
|
|
};
|
|
}
|
|
}
|