259 lines
6.0 KiB
TypeScript
Executable File
259 lines
6.0 KiB
TypeScript
Executable File
import { Injectable } from '@nestjs/common';
|
|
import {
|
|
db,
|
|
StaffMethodSchema,
|
|
ObjectType,
|
|
UserProfile,
|
|
Prisma,
|
|
} from '@nice/common';
|
|
import { DepartmentService } from '../department/department.service';
|
|
import { z } from 'zod';
|
|
import { BaseService } from '../base/base.service';
|
|
import * as argon2 from 'argon2';
|
|
import EventBus, { CrudOperation } from '@server/utils/event-bus';
|
|
|
|
@Injectable()
|
|
export class StaffService extends BaseService<Prisma.StaffDelegate> {
|
|
constructor(private readonly departmentService: DepartmentService) {
|
|
super(db, ObjectType.STAFF, true);
|
|
}
|
|
|
|
/**
|
|
* 获取某一单位下所有staff的记录
|
|
* @param deptId 单位的id
|
|
* @returns 查到的staff记录
|
|
*/
|
|
async findByDept(data: z.infer<typeof StaffMethodSchema.findByDept>) {
|
|
const { deptId, domainId } = data;
|
|
const childDepts = await this.departmentService.getDescendantIds(
|
|
deptId,
|
|
true,
|
|
);
|
|
const result = await db.staff.findMany({
|
|
where: {
|
|
deptId: { in: childDepts },
|
|
domainId,
|
|
},
|
|
});
|
|
return result;
|
|
}
|
|
|
|
async create(args: Prisma.StaffCreateArgs) {
|
|
const { data, select } = args;
|
|
const { fieldValues, ...staffData } = data as any;
|
|
|
|
// 创建员工基本信息
|
|
const staff = await super.create({
|
|
...args,
|
|
data: {
|
|
...staffData,
|
|
password: await argon2.hash((staffData.password || '123456') as string),
|
|
},
|
|
});
|
|
|
|
// 如果有自定义字段值,创建它们
|
|
if (fieldValues) {
|
|
await db.staffFieldValue.createMany({
|
|
data: Object.entries(fieldValues).map(([fieldId, value]) => ({
|
|
staffId: staff.id,
|
|
fieldId,
|
|
value: String(value),
|
|
})),
|
|
});
|
|
}
|
|
|
|
this.emitDataChangedEvent(staff, CrudOperation.CREATED);
|
|
return staff;
|
|
}
|
|
|
|
async update(args: Prisma.StaffUpdateArgs) {
|
|
const { data, where } = args;
|
|
const { fieldValues, ...staffData } = data as any;
|
|
|
|
// 更新员工基本信息
|
|
const staff = await super.update({
|
|
...args,
|
|
data: {
|
|
...staffData,
|
|
...(staffData.password && {
|
|
password: await argon2.hash(staffData.password as string),
|
|
}),
|
|
},
|
|
});
|
|
|
|
// 如果有自定义字段值,更新它们
|
|
if (fieldValues) {
|
|
await Promise.all(
|
|
Object.entries(fieldValues).map(([fieldId, value]) =>
|
|
db.staffFieldValue.upsert({
|
|
where: {
|
|
staffId_fieldId: {
|
|
staffId: staff.id,
|
|
fieldId,
|
|
},
|
|
},
|
|
create: {
|
|
staffId: staff.id,
|
|
fieldId,
|
|
value: String(value),
|
|
},
|
|
update: {
|
|
value: String(value),
|
|
},
|
|
}),
|
|
),
|
|
);
|
|
}
|
|
|
|
this.emitDataChangedEvent(staff, CrudOperation.UPDATED);
|
|
return staff;
|
|
}
|
|
|
|
private async validateUniqueFields(data: any, excludeId?: string) {
|
|
const uniqueFields = [
|
|
{
|
|
field: 'officerId',
|
|
errorMsg: (val: string) => `证件号为${val}的用户已存在`,
|
|
},
|
|
{
|
|
field: 'phoneNumber',
|
|
errorMsg: (val: string) => `手机号为${val}的用户已存在`,
|
|
},
|
|
{
|
|
field: 'username',
|
|
errorMsg: (val: string) => `帐号为${val}的用户已存在`,
|
|
},
|
|
];
|
|
for (const { field, errorMsg } of uniqueFields) {
|
|
if (data[field]) {
|
|
const count = await db.staff.count({
|
|
where: {
|
|
[field]: data[field],
|
|
...(excludeId && { id: { not: excludeId } }),
|
|
},
|
|
});
|
|
if (count > 0) {
|
|
throw new Error(errorMsg(data[field]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private emitDataChangedEvent(data: any, operation: CrudOperation) {
|
|
EventBus.emit('dataChanged', {
|
|
type: this.objectType,
|
|
operation,
|
|
data,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 更新员工DomainId
|
|
* @param data 包含domainId对象
|
|
* @returns 更新后的员工记录
|
|
*/
|
|
async updateUserDomain(data: { domainId?: string }, staff?: UserProfile) {
|
|
const { domainId } = data;
|
|
if (staff.domainId !== domainId) {
|
|
const result = await this.update({
|
|
where: { id: staff.id },
|
|
data: {
|
|
domainId,
|
|
deptId: null,
|
|
},
|
|
});
|
|
return result;
|
|
} else {
|
|
return staff;
|
|
}
|
|
}
|
|
|
|
async findUnique(args: Prisma.StaffFindUniqueArgs) {
|
|
const staff = await super.findUnique(args);
|
|
if (!staff) return null;
|
|
|
|
// 获取自定义字段值
|
|
const fieldValues = await db.staffFieldValue.findMany({
|
|
where: { staffId: staff.id },
|
|
include: { field: true },
|
|
});
|
|
|
|
return {
|
|
...staff,
|
|
fieldValues: fieldValues.reduce((acc, { field, value }) => ({
|
|
...acc,
|
|
[field.name]: value,
|
|
}), {}),
|
|
};
|
|
}
|
|
|
|
async addCustomField(data: {
|
|
name: string;
|
|
label?: string;
|
|
type: string;
|
|
required?: boolean;
|
|
order?: number;
|
|
options?: any;
|
|
group?: string;
|
|
}) {
|
|
return this.prisma.staffField.create({
|
|
data: {
|
|
...data,
|
|
},
|
|
});
|
|
}
|
|
|
|
async updateCustomField(data: {
|
|
id: string;
|
|
name?: string;
|
|
label?: string;
|
|
type?: string;
|
|
required?: boolean;
|
|
order?: number;
|
|
options?: any;
|
|
group?: string;
|
|
}) {
|
|
const { id, ...updateData } = data;
|
|
return this.prisma.staffField.update({
|
|
where: { id },
|
|
data: updateData,
|
|
});
|
|
}
|
|
|
|
async deleteCustomField(id: string) {
|
|
return this.prisma.staffField.delete({
|
|
where: { id },
|
|
});
|
|
}
|
|
|
|
async getCustomFields() {
|
|
return this.prisma.staffField.findMany({
|
|
orderBy: { order: 'asc' },
|
|
});
|
|
}
|
|
|
|
async setCustomFieldValue(data: {
|
|
staffId: string;
|
|
fieldId: string;
|
|
value?: string;
|
|
}) {
|
|
const { staffId, fieldId, value } = data;
|
|
return this.prisma.staffFieldValue.upsert({
|
|
where: {
|
|
staffId_fieldId: {
|
|
staffId,
|
|
fieldId,
|
|
}
|
|
},
|
|
create: {
|
|
staffId,
|
|
fieldId,
|
|
value,
|
|
},
|
|
update: {
|
|
value,
|
|
},
|
|
});
|
|
}
|
|
}
|