diff --git a/backend-spring/src/main/java/com/erp/controller/DepartmentController.java b/backend-spring/src/main/java/com/erp/controller/DepartmentController.java index 7ee10c98..48d90235 100644 --- a/backend-spring/src/main/java/com/erp/controller/DepartmentController.java +++ b/backend-spring/src/main/java/com/erp/controller/DepartmentController.java @@ -21,20 +21,22 @@ public class DepartmentController { /** * 부서 목록 조회 (회사별). * 기본은 active 부서만. ?include_deleted=true 시 soft-delete 된 부서도 포함. - * GET /api/departments/companies/{companyCode}/departments[?include_deleted=true] + * ?base_date=YYYY-MM-DD 시 해당 시점에 active 했던 부서만 반환. + * GET /api/departments/companies/{companyCode}/departments[?include_deleted=true][&base_date=YYYY-MM-DD] */ @GetMapping("/companies/{companyCode}/departments") public ResponseEntity>>> getDepartments( @PathVariable String companyCode, @RequestAttribute("company_code") String userCompanyCode, - @RequestParam(value = "include_deleted", required = false, defaultValue = "false") boolean includeDeleted) { + @RequestParam(value = "include_deleted", required = false, defaultValue = "false") boolean includeDeleted, + @RequestParam(value = "base_date", required = false) String baseDate) { if (!isSuperAdmin(userCompanyCode) && !userCompanyCode.equals(companyCode)) { return ResponseEntity.status(403) .body(ApiResponse.error("해당 회사의 부서를 조회할 권한이 없습니다.")); } - List> departments = departmentService.getDepartments(companyCode, includeDeleted); + List> departments = departmentService.getDepartments(companyCode, includeDeleted, baseDate); return ResponseEntity.ok(ApiResponse.success(departments, "부서 목록 조회 성공")); } diff --git a/backend-spring/src/main/java/com/erp/service/DepartmentService.java b/backend-spring/src/main/java/com/erp/service/DepartmentService.java index e774d84c..57e993f8 100644 --- a/backend-spring/src/main/java/com/erp/service/DepartmentService.java +++ b/backend-spring/src/main/java/com/erp/service/DepartmentService.java @@ -20,17 +20,22 @@ public class DepartmentService extends BaseService { // ────────────────────────────────────────────────── public List> getDepartments(String companyCode) { - return getDepartments(companyCode, false); + return getDepartments(companyCode, false, null); } /** soft-delete 대응 — includeDeleted=true 면 DELETED_AT 부서도 포함 */ public List> getDepartments(String companyCode, boolean includeDeleted) { + return getDepartments(companyCode, includeDeleted, null); + } + + /** 기준일 필터 — baseDate 가 있으면 해당 시점에 active 한 부서만 반환 (start_date ≤ baseDate ≤ end_date OR end_date IS NULL) */ + public List> getDepartments(String companyCode, boolean includeDeleted, String baseDate) { Map params = new HashMap<>(); params.put("company_code", companyCode); params.put("include_deleted", includeDeleted); + params.put("base_date", baseDate); // null/빈문자면 XML if 가 skip List> departments = sqlSession.selectList("department.selectDepartments", params); - // member_count를 int로 변환 for (Map dept : departments) { Object cnt = dept.get("member_count"); if (cnt != null) { diff --git a/backend-spring/src/main/resources/mapper/department.xml b/backend-spring/src/main/resources/mapper/department.xml index be469617..1c492644 100644 --- a/backend-spring/src/main/resources/mapper/department.xml +++ b/backend-spring/src/main/resources/mapper/department.xml @@ -30,6 +30,10 @@ AND D.DELETED_AT IS NULL + + AND D.START_DATE <= #{base_date}::date + AND (D.END_DATE IS NULL OR D.END_DATE >= #{base_date}::date) + GROUP BY D.DEPT_CODE, D.DEPT_NAME, D.COMPANY_CODE, D.PARENT_DEPT_CODE, D.SHORT_NAME, D.DEPT_TYPE, D.ORG_SYSTEM, D.APPROVAL_MANAGER, D.DEPT_MANAGER, diff --git a/frontend/app/(main)/admin/userMng/deptMngList/page.tsx b/frontend/app/(main)/admin/userMng/deptMngList/page.tsx index 5df0b9b2..df7da3f3 100644 --- a/frontend/app/(main)/admin/userMng/deptMngList/page.tsx +++ b/frontend/app/(main)/admin/userMng/deptMngList/page.tsx @@ -201,7 +201,10 @@ export default function DeptMngListPage() { if (!selectedCompanyCode) return; setIsTreeLoading(true); try { - const res = await departmentAPI.getDepartments(selectedCompanyCode, { includeDeleted: showDeleted }); + const res = await departmentAPI.getDepartments(selectedCompanyCode, { + includeDeleted: showDeleted, + baseDate: periodMode === "date" ? baseDate : undefined, + }); if (res.success && (res as any).data) { setDepartments((res as any).data); } else { @@ -210,7 +213,7 @@ export default function DeptMngListPage() { } finally { setIsTreeLoading(false); } - }, [selectedCompanyCode, showDeleted]); + }, [selectedCompanyCode, showDeleted, periodMode, baseDate]); useEffect(() => { loadDepartments(); @@ -645,33 +648,30 @@ export default function DeptMngListPage() {