package com.erp.controller; import com.erp.dto.ApiResponse; import com.erp.service.AdminService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping("/api/admin") @RequiredArgsConstructor @Slf4j public class AdminController { private final AdminService adminService; // ── 메뉴 관리 ────────────────────────────────────────────────────────── /** * GET /api/admin/menus * 관리자 메뉴 목록 조회 */ @GetMapping("/menus") public ResponseEntity>>> getAdminMenus( @RequestAttribute("company_code") String companyCode, @RequestAttribute("role") String role, @RequestAttribute("user_id") String userId, @RequestParam Map params) { params.put("company_code", companyCode); params.put("user_type", role); params.put("user_id", userId); params.putIfAbsent("user_lang", "ko"); params.put("is_management_screen", params.get("menu_type") == null || "true".equals(params.get("include_inactive"))); return ResponseEntity.ok(ApiResponse.success(adminService.getAdminMenuList(params), "관리자 메뉴 목록 조회 성공")); } /** * GET /api/admin/user-menus * 사용자 메뉴 목록 조회 (사이드바) */ @GetMapping("/user-menus") public ResponseEntity>>> getUserMenus( @RequestAttribute("company_code") String companyCode, @RequestAttribute("role") String role, @RequestAttribute("user_id") String userId, @RequestParam Map params) { params.put("company_code", companyCode); params.put("user_type", role); params.put("user_id", userId); params.putIfAbsent("user_lang", "ko"); return ResponseEntity.ok(ApiResponse.success(adminService.getUserMenuList(params), "사용자 메뉴 목록 조회 성공")); } /** * GET /api/admin/pop-menus * POP 메뉴 목록 조회 */ @GetMapping("/pop-menus") public ResponseEntity>> getPopMenus( @RequestAttribute("company_code") String companyCode, @RequestAttribute("role") String role) { Map params = new HashMap<>(); params.put("company_code", companyCode); params.put("user_type", role); return ResponseEntity.ok(ApiResponse.success(adminService.getPopMenuList(params), "POP 메뉴 목록 조회 성공")); } /** * GET /api/admin/menus/{menuId} * 메뉴 단건 조회 */ @GetMapping("/menus/{menuId}") public ResponseEntity>> getMenuInfo(@PathVariable String menuId) { Map menu = adminService.getMenuInfo(menuId); if (menu == null) { return ResponseEntity.status(404).body(ApiResponse.error("메뉴를 찾을 수 없습니다.")); } return ResponseEntity.ok(ApiResponse.success(menu, "메뉴 정보 조회 성공")); } /** * POST /api/admin/menus * 메뉴 등록 */ @PostMapping("/menus") public ResponseEntity>> saveMenu( @RequestAttribute("company_code") String companyCode, @RequestBody Map body) { body.put("company_code", companyCode); return ResponseEntity.ok(ApiResponse.success(adminService.saveMenu(body), "메뉴 등록 성공")); } /** * PUT /api/admin/menus/{menuId} * 메뉴 수정 */ @PutMapping("/menus/{menuId}") public ResponseEntity>> updateMenu( @PathVariable String menuId, @RequestBody Map body) { return ResponseEntity.ok(ApiResponse.success(adminService.updateMenu(menuId, body), "메뉴 수정 성공")); } /** * DELETE /api/admin/menus/{menuId} * 메뉴 삭제 */ @DeleteMapping("/menus/{menuId}") public ResponseEntity> deleteMenu(@PathVariable String menuId) { adminService.deleteMenu(menuId); return ResponseEntity.ok(ApiResponse.success(null, "메뉴 삭제 성공")); } /** * PUT /api/admin/menus/{menuId}/toggle * 메뉴 상태 토글 */ @PutMapping("/menus/{menuId}/toggle") public ResponseEntity>> toggleMenuStatus(@PathVariable String menuId) { return ResponseEntity.ok(ApiResponse.success(adminService.toggleMenuStatus(menuId), "메뉴 상태 변경 성공")); } /** * DELETE /api/admin/menus/batch * 메뉴 일괄 삭제 */ @DeleteMapping("/menus/batch") public ResponseEntity> deleteMenusBatch(@RequestBody Map body) { @SuppressWarnings("unchecked") List menuIds = (List) body.get("menu_ids"); if (menuIds != null) { menuIds.forEach(adminService::deleteMenu); } return ResponseEntity.ok(ApiResponse.success(null, "메뉴 일괄 삭제 성공")); } // ── 사용자 관리 ──────────────────────────────────────────────────────── /** * GET /api/admin/users * 사용자 목록 조회 */ @GetMapping("/users") public ResponseEntity getUserList( @RequestAttribute("company_code") String companyCode, @RequestAttribute("role") String role, @RequestParam Map params) { // SUPER_ADMIN이 아닌 경우 자사 필터 적용 if (!"SUPER_ADMIN".equals(role)) { params.put("company_code", companyCode); } else { params.put("company_code", "*"); } params.putIfAbsent("page", "1"); params.putIfAbsent("limit", "20"); Map result = adminService.getUserList(params); // Node.js 응답 형식: success, data, total, searchType, pagination, message Map response = new HashMap<>(result); response.put("success", true); response.put("message", "사용자 목록 조회 성공"); return ResponseEntity.ok(response); } /** * GET /api/admin/users/{userId} * 사용자 단건 조회 */ @GetMapping("/users/{userId}") public ResponseEntity>> getUserInfo(@PathVariable String userId) { Map user = adminService.getUserInfo(userId); if (user == null) { return ResponseEntity.status(404).body(ApiResponse.error("사용자를 찾을 수 없습니다.")); } return ResponseEntity.ok(ApiResponse.success(user, "사용자 정보 조회 성공")); } /** * GET /api/admin/users/{userId}/history * 사용자 변경이력 조회 */ @GetMapping("/users/{userId}/history") public ResponseEntity>>> getUserHistory( @PathVariable String userId, @RequestParam Map params) { return ResponseEntity.ok(ApiResponse.success(adminService.getUserHistory(userId, params), "사용자 변경이력 조회 성공")); } /** * GET /api/admin/users/{userId}/with-dept * 사원 + 부서 정보 조회 (수정 모달용) */ @GetMapping("/users/{userId}/with-dept") public ResponseEntity>> getUserWithDept( @RequestAttribute("company_code") String companyCode, @PathVariable String userId) { Map params = new HashMap<>(); params.put("company_code", companyCode); params.put("user_id", userId); Map result = adminService.getUserWithDept(params); if (result == null) { return ResponseEntity.status(404).body(ApiResponse.error("사용자를 찾을 수 없습니다.")); } return ResponseEntity.ok(ApiResponse.success(result)); } /** * POST /api/admin/users/with-dept * 사원 + 부서 통합 저장 */ @PostMapping("/users/with-dept") public ResponseEntity>> saveUserWithDept( @RequestAttribute("company_code") String companyCode, @RequestBody Map body) { body.put("company_code", companyCode); return ResponseEntity.ok(ApiResponse.success(adminService.saveUserWithDept(body))); } /** * POST /api/admin/users * 사용자 등록/수정 */ @PostMapping("/users") public ResponseEntity>> saveUser( @RequestAttribute("company_code") String companyCode, @RequestBody Map body) { body.put("company_code", companyCode); return ResponseEntity.ok(ApiResponse.success(adminService.saveUser(body), "사용자 저장 성공")); } /** * PUT /api/admin/users/{userId} * 사용자 수정 (REST) */ @PutMapping("/users/{userId}") public ResponseEntity>> updateUser( @PathVariable String userId, @RequestAttribute("company_code") String companyCode, @RequestBody Map body) { body.put("user_id", userId); body.put("company_code", companyCode); return ResponseEntity.ok(ApiResponse.success(adminService.saveUser(body), "사용자 수정 성공")); } /** * DELETE /api/admin/users/{userId} * 사용자 삭제 (비활성화) */ @DeleteMapping("/users/{userId}") public ResponseEntity> deleteUser( @PathVariable String userId) { Map existing = adminService.getUserInfo(userId); if (existing == null) { return ResponseEntity.status(404).body(ApiResponse.error("사용자를 찾을 수 없습니다.")); } adminService.changeUserStatus(userId, "inactive"); return ResponseEntity.ok(ApiResponse.success(null, "사용자 삭제 성공")); } /** * PATCH /api/admin/users/{userId}/status * 사용자 상태 변경 */ @PatchMapping("/users/{userId}/status") public ResponseEntity> changeUserStatus( @PathVariable String userId, @RequestBody Map body) { String status = (String) body.get("status"); adminService.changeUserStatus(userId, status); return ResponseEntity.ok(ApiResponse.success(null, "사용자 상태 변경 성공")); } /** * POST /api/admin/users/reset-password * 비밀번호 초기화 */ @PostMapping("/users/reset-password") public ResponseEntity> resetUserPassword(@RequestBody Map body) { String userId = (String) body.get("user_id"); adminService.resetUserPassword(userId); return ResponseEntity.ok(ApiResponse.success(null, "비밀번호 초기화 성공")); } /** * POST /api/admin/users/check-duplicate * 사용자 ID 중복 확인 */ @PostMapping("/users/check-duplicate") public ResponseEntity>> checkDuplicateUserId( @RequestBody Map body) { String userId = (String) body.get("user_id"); Map existing = adminService.getUserInfo(userId); Map result = new HashMap<>(); result.put("is_duplicate", existing != null); return ResponseEntity.ok(ApiResponse.success(result, "아이디 중복 확인 완료")); } // ── 프로필 수정 ──────────────────────────────────────────────────────── /** * PUT /api/admin/profile * 프로필 수정 (본인) */ @PutMapping("/profile") public ResponseEntity>> updateProfile( @RequestAttribute("user_id") String userId, @RequestBody Map body) { body.put("user_id", userId); return ResponseEntity.ok(ApiResponse.success(adminService.saveUser(body), "프로필 수정 성공")); } // ── 부서 관리 ────────────────────────────────────────────────────────── /** * GET /api/admin/departments * 부서 목록 조회 */ @GetMapping("/departments") public ResponseEntity getDepartmentList( @RequestAttribute("company_code") String companyCode, @RequestParam Map params) { params.put("company_code", companyCode); Map serviceResult = adminService.getDepartmentList(params); int total = ((Number) serviceResult.get("total")).intValue(); Map data = new HashMap<>(); data.put("departments", serviceResult.get("departments")); data.put("flat_list", serviceResult.get("flat_list")); Map response = new HashMap<>(); response.put("success", true); response.put("data", data); response.put("message", "부서 목록 조회 성공"); response.put("total", total); response.put("total_count", total); return ResponseEntity.ok(response); } // ── 회사 관리 ────────────────────────────────────────────────────────── /** * GET /api/admin/companies * 회사 목록 조회 */ @GetMapping("/companies") public ResponseEntity>>> getCompanyList() { return ResponseEntity.ok(ApiResponse.success(adminService.getCompanyList(), "회사 목록 조회 성공")); } /** * GET /api/admin/companies/db * 실제 DB에서 회사 목록 조회 */ @GetMapping("/companies/db") public ResponseEntity>>> getCompanyListFromDB() { return ResponseEntity.ok(ApiResponse.success(adminService.getCompanyList(), "회사 목록 조회 성공")); } /** * GET /api/admin/companies/{companyCode} * 회사 단건 조회 */ @GetMapping("/companies/{companyCode}") public ResponseEntity>> getCompanyByCode( @PathVariable String companyCode) { Map company = adminService.getCompanyByCode(companyCode); if (company == null) { return ResponseEntity.status(404).body(ApiResponse.error("회사를 찾을 수 없습니다.")); } return ResponseEntity.ok(ApiResponse.success(company, "회사 조회 성공")); } /** * POST /api/admin/companies * 회사 등록 */ @PostMapping("/companies") public ResponseEntity>> createCompany( @RequestBody Map body) { return ResponseEntity.ok(ApiResponse.success(adminService.createCompany(body), "회사 등록 성공")); } /** * PUT /api/admin/companies/{companyCode} * 회사 수정 */ @PutMapping("/companies/{companyCode}") public ResponseEntity>> updateCompany( @PathVariable String companyCode, @RequestBody Map body) { return ResponseEntity.ok(ApiResponse.success(adminService.updateCompanyInfo(companyCode, body), "회사 수정 성공")); } /** * DELETE /api/admin/companies/{companyCode} * 회사 삭제 (비활성화) */ @DeleteMapping("/companies/{companyCode}") public ResponseEntity> deleteCompany(@PathVariable String companyCode) { adminService.deleteCompany(companyCode); return ResponseEntity.ok(ApiResponse.success(null, "회사 삭제 성공")); } // ── 로케일 관리 ──────────────────────────────────────────────────────── /** * GET /api/admin/user-locale * 사용자 로케일 조회 */ @GetMapping("/user-locale") public ResponseEntity> getUserLocale( @RequestAttribute("user_id") String userId) { Map row = adminService.getUserLocale(userId); Object locale = row.getOrDefault("locale", "KR"); return ResponseEntity.ok(ApiResponse.success(locale, "사용자 로케일 조회 성공")); } /** * POST /api/admin/user-locale * 사용자 로케일 설정 */ @PostMapping("/user-locale") public ResponseEntity> setUserLocale( @RequestAttribute("user_id") String userId, @RequestBody Map body) { String locale = (String) body.get("locale"); if (locale == null || locale.isBlank()) { return ResponseEntity.badRequest().body(ApiResponse.error("로케일이 필요합니다.")); } try { adminService.setUserLocale(userId, locale); return ResponseEntity.ok(ApiResponse.success(locale, "사용자 로케일 설정 성공")); } catch (IllegalArgumentException e) { return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage())); } } // ── 테이블 스키마 ────────────────────────────────────────────────────── /** * GET /api/admin/tables/{tableName}/schema * 테이블 스키마 조회 */ @GetMapping("/tables/{tableName}/schema") public ResponseEntity>>> getTableSchema( @PathVariable String tableName) { return ResponseEntity.ok(ApiResponse.success(adminService.getTableSchema(tableName), "테이블 스키마 조회 성공")); } }