origin/apps/server/src/models/department/department.service.ts

365 lines
11 KiB
TypeScript
Raw Normal View History

2024-09-03 20:19:33 +08:00
import { Injectable } from '@nestjs/common';
import { db, z, DepartmentSchema } from '@nicestack/common';
@Injectable()
export class DepartmentService {
/**
*
* @param deptId -
* @returns deptId则返回undefined
*/
async getFlatChildDepts(deptId: string) {
if (!deptId) return undefined;
return await db.deptAncestry.findMany({
where: { ancestorId: deptId },
});
}
/**
* DOM下的对应name的单位
* @param domId
* @param name
* @returns
*
*
*/
async findByNameInDom(domId: string, name: string) {
const subDepts = await db.deptAncestry.findMany({
where: {
ancestorId: domId,
},
include: {
descendant: true,
},
});
const dept = subDepts.find((item) => item.descendant.name === name);
return dept?.descendant;
}
/**
*
* @param deptId -
* @returns deptId则返回undefined
*/
async getFlatParentDepts(deptId: string) {
if (!deptId) return undefined;
return await db.deptAncestry.findMany({
where: { descendantId: deptId },
});
}
/**
* ID
* @param deptId -
* @returns ID的数组
*/
async getAllChildDeptIds(deptId: string) {
const res = await this.getFlatChildDepts(deptId);
return res?.map((dept) => dept.descendantId) || [];
}
/**
* ID
* @param deptId -
* @returns ID的数组
*/
async getAllParentDeptIds(deptId: string) {
const res = await this.getFlatParentDepts(deptId);
return res?.map((dept) => dept.ancestorId) || [];
}
/**
*
* @param deptId -
* @returns
*/
async getDepartmentDetails(deptId: string) {
const department = await db.department.findUnique({
where: { id: deptId },
include: { children: true, deptStaffs: true },
});
const childrenData = await db.deptAncestry.findMany({
where: { ancestorId: deptId, relDepth: 1 },
include: { descendant: { include: { children: true } } },
});
const children = childrenData.map(({ descendant }) => ({
id: descendant.id,
name: descendant.name,
order: descendant.order,
parentId: descendant.parentId,
hasChildren: Boolean(descendant.children?.length),
childrenCount: descendant.children?.length || 0,
}));
return {
id: department?.id,
name: department?.name,
order: department?.order,
parentId: department?.parentId,
children,
staffs: department?.deptStaffs,
hasChildren: !!children.length,
};
}
/**
*
* @param parentId -
* @returns
*/
async getChildren(parentId?: string) {
const departments = await db.department.findMany({
where: { parentId: parentId ?? null },
include: { children: true, deptStaffs: true },
});
return departments.map((dept) => ({
...dept,
hasChildren: dept.children.length > 0,
staffs: dept.deptStaffs,
}));
}
async paginate(data: z.infer<typeof DepartmentSchema.paginate>) {
const { page, pageSize, ids } = data;
const [items, totalCount] = await Promise.all([
db.department.findMany({
skip: (page - 1) * pageSize,
take: pageSize,
where: {
deletedAt: null,
OR: [{ id: { in: ids } }],
},
include: { deptStaffs: true, parent: true },
orderBy: { order: 'asc' },
}),
db.department.count({
where: {
deletedAt: null,
OR: [{ id: { in: ids } }],
},
}),
]);
return { items, totalCount };
}
async findMany(data: z.infer<typeof DepartmentSchema.findMany>) {
const { keyword = '', ids } = data;
const departments = await db.department.findMany({
where: {
deletedAt: null,
OR: [{ name: { contains: keyword! } }, ids ? { id: { in: ids } } : {}],
},
include: { deptStaffs: true },
orderBy: { order: 'asc' },
take: 20,
});
return departments.map((dept) => ({
...dept,
staffs: dept.deptStaffs,
}));
}
/**
*
* @param query -
* @returns
*/
async getDomainDepartments(query?: string) {
return await db.department.findMany({
where: { isDomain: true, name: { contains: query } },
take: 10,
});
}
async getDeptIdsByStaffIds(ids: string[]) {
const staffs = await db.staff.findMany({
where: { id: { in: ids } },
});
return staffs.map((staff) => staff.deptId);
}
/**
* DeptAncestry关系
* @param data -
* @returns
*/
async create(data: z.infer<typeof DepartmentSchema.create>) {
let newOrder = 0;
// 确定新单位的顺序
const siblingDepartments = await db.department.findMany({
where: { parentId: data.parentId ?? null },
orderBy: { order: 'desc' },
take: 1,
});
if (siblingDepartments.length > 0) {
newOrder = siblingDepartments[0].order + 1;
}
// 根据计算的顺序创建新单位
const newDepartment = await db.department.create({
data: { ...data, order: newOrder },
});
// 如果存在parentId则更新DeptAncestry关系
if (data.parentId) {
const parentAncestries = await db.deptAncestry.findMany({
where: { descendantId: data.parentId },
orderBy: { relDepth: 'asc' },
});
// 为新单位创建新的祖先记录
const newAncestries = parentAncestries.map((ancestry) => ({
ancestorId: ancestry.ancestorId,
descendantId: newDepartment.id,
relDepth: ancestry.relDepth + 1,
}));
newAncestries.push({
ancestorId: data.parentId,
descendantId: newDepartment.id,
relDepth: 1,
});
await db.deptAncestry.createMany({ data: newAncestries });
}
return newDepartment;
}
/**
* parentId更改时管理DeptAncestry关系
* @param data -
* @returns
*/
async update(data: z.infer<typeof DepartmentSchema.update>) {
return await db.$transaction(async (transaction) => {
const currentDepartment = await transaction.department.findUnique({
where: { id: data.id },
});
if (!currentDepartment) throw new Error('Department not found');
const updatedDepartment = await transaction.department.update({
where: { id: data.id },
data: data,
});
if (data.parentId !== currentDepartment.parentId) {
await transaction.deptAncestry.deleteMany({
where: { descendantId: data.id },
});
if (data.parentId) {
const parentAncestries = await transaction.deptAncestry.findMany({
where: { descendantId: data.parentId },
});
const newAncestries = parentAncestries.map((ancestry) => ({
ancestorId: ancestry.ancestorId,
descendantId: data.id,
relDepth: ancestry.relDepth + 1,
}));
newAncestries.push({
ancestorId: data.parentId,
descendantId: data.id,
relDepth: 1,
});
await transaction.deptAncestry.createMany({ data: newAncestries });
}
}
return updatedDepartment;
});
}
/**
* DeptAncestry关系
* @param data -
* @returns
*/
async delete(data: z.infer<typeof DepartmentSchema.delete>) {
const deletedDepartment = await db.department.update({
where: { id: data.id },
data: { deletedAt: new Date() },
});
await db.deptAncestry.deleteMany({
where: { OR: [{ ancestorId: data.id }, { descendantId: data.id }] },
});
return deletedDepartment;
}
async getStaffsByDeptIds(ids: string[]) {
const depts = await db.department.findMany({
where: { id: { in: ids } },
include: { deptStaffs: true },
});
return depts.flatMap((dept) => dept.deptStaffs);
}
/**
*
* @param deptIds - ID的部门ID数组
* @returns ID的数组
*/
async getAllStaffsByDepts(deptIds: string[]) {
const allDeptIds = new Set(deptIds);
for (const deptId of deptIds) {
const childDeptIds = await this.getAllChildDeptIds(deptId);
childDeptIds.forEach((id) => allDeptIds.add(id));
}
return await this.getStaffsByDeptIds(Array.from(allDeptIds));
}
/**
* ID获取部门ID
*
* @param {string} name -
* @param {string} domainId -
* @returns {Promise<string | null>} - IDnull
*/
async getDeptIdByName(name: string, domainId: string): Promise<string | null> {
const dept = await db.department.findFirst({
where: {
name,
ancestors: {
some: {
ancestorId: domainId
}
}
}
});
return dept ? dept.id : null;
}
/**
* ID获取多个部门的ID
*
* @param {string[]} names -
* @param {string} domainId -
* @returns {Promise<Record<string, string | null>>} - ID或null的记录
*/
async getDeptIdsByNames(names: string[], domainId: string): Promise<Record<string, string | null>> {
const result: Record<string, string | null> = {};
// 遍历每个部门名称并获取对应的部门ID
for (const name of names) {
// 使用之前定义的函数根据名称获取部门ID
const deptId = await this.getDeptIdByName(name, domainId);
result[name] = deptId;
}
return result;
}
}