duckil_plm/plm-api/src/services/department.service.js

208 lines
5.3 KiB
JavaScript
Raw Normal View History

2024-12-12 18:31:36 +09:00
// src/services/department.service.js
const { Department, Company, Branch, User } = require("../models");
const alertService = require("./alert.service");
class DepartmentService {
async findByCompanyId(companyId) {
const departments = await Department.findAll({
where: { companyId },
include: [
{
model: User,
attributes: ["id", "name", "email"],
},
],
});
const buildHierarchy = (items) => {
const map = new Map();
const roots = [];
items.forEach((item) => {
map.set(item.id, { ...item.get({ plain: true }), children: [] });
});
items.forEach((item) => {
if (item.parentId) {
const parent = map.get(item.parentId);
if (parent) {
parent.children.push(map.get(item.id));
}
} else {
roots.push(map.get(item.id));
}
});
return roots;
};
return buildHierarchy(departments);
}
async findById(id) {
return await Department.findByPk(id, {
include: [
{
model: Department,
as: "parent",
attributes: ["id", "name"],
},
{
model: Department,
as: "children",
attributes: ["id", "name"],
},
{
model: User,
attributes: ["id", "name", "email"],
},
],
});
}
// 추가: 앱에서 사용할 부서 목록 조회 메서드
async findAll(currentUser, format = "flat", includeInactive = false) {
let where = {};
// company_admin은 자신의 회사 부서만 조회 가능
if (currentUser.role === "company_admin") {
where.companyId = currentUser.companyId;
}
// 활성 상태 필터링
if (!includeInactive) {
where.isActive = true;
}
const departments = await Department.findAll({
where,
include: [
{
model: Company,
attributes: ["id", "name"],
},
{
model: Branch,
attributes: ["id", "name"],
},
{
model: Department,
as: "parent",
attributes: ["id", "name"],
},
{
model: User,
attributes: ["id", "name"],
},
],
order: [
["parentId", "ASC NULLS FIRST"],
["name", "ASC"],
],
});
// 트리 구조로 반환
if (format === "tree") {
const buildHierarchy = (items, parentId = null) => {
return items
.filter((item) => item.parentId === parentId)
.map((item) => ({
...item.get({ plain: true }),
children: buildHierarchy(items, item.id),
// 추가 정보 계산
userCount: item.Users ? item.Users.length : 0,
path: this.getDepartmentPath(items, item),
}));
};
return buildHierarchy(departments);
}
// 평면 구조로 반환
return departments.map((dept) => {
const json = dept.get({ plain: true });
// 추가 정보 계산
json.path = this.getDepartmentPath(departments, dept);
json.childCount = departments.filter(
(d) => d.parentId === dept.id
).length;
json.userCount = dept.Users ? dept.Users.length : 0;
return json;
});
}
// 부서 경로 생성 헬퍼 메서드
getDepartmentPath(departments, department) {
const path = [];
let current = department;
while (current) {
path.unshift(current.name);
current = departments.find((d) => d.id === current.parentId);
}
return path.join(" > ");
}
async hasChildren(id) {
const childCount = await Department.count({
where: { parentId: id },
});
return childCount > 0;
}
async createDepartment(departmentData, user) {
const department = await Department.create(departmentData);
await alertService.createAlert({
type: "info",
message: `부서 ${department.name}이(가) ${user.name}에 의해 생성되었습니다.`,
companyId: department.companyId,
});
return department;
}
async updateDepartment(id, updateData, user) {
const department = await Department.findByPk(id);
if (!department) throw new Error("Department not found");
// parentId가 undefined이면 업데이트에서 제외, 명확히 null일 경우만 null로 설정
if (updateData.parentId === undefined) {
delete updateData.parentId;
} else if (updateData.parentId === null) {
updateData.parentId = null;
}
const updatedDepartment = await department.update(updateData);
await alertService.createAlert({
type: "info",
message: `부서 ${department.name}이(가) ${user.name}에 의해 수정되었습니다.`,
companyId: department.companyId,
});
return updatedDepartment;
}
async deleteDepartment(id, user) {
const department = await Department.findByPk(id);
if (!department) throw new Error("Department not found");
const departmentName = department.name;
const companyId = department.companyId;
await department.destroy();
await alertService.createAlert({
type: "info",
message: `부서 ${departmentName}이(가) ${user.name}에 의해 삭제되었습니다.`,
companyId: companyId,
});
return true;
}
}
module.exports = new DepartmentService();