diff --git a/backend-spring/src/main/java/com/erp/controller/AdminController.java b/backend-spring/src/main/java/com/erp/controller/AdminController.java index 434c5c7a..a038a4f0 100644 --- a/backend-spring/src/main/java/com/erp/controller/AdminController.java +++ b/backend-spring/src/main/java/com/erp/controller/AdminController.java @@ -308,11 +308,25 @@ public class AdminController { * 부서 목록 조회 */ @GetMapping("/departments") - public ResponseEntity>> getDepartmentList( + public ResponseEntity getDepartmentList( @RequestAttribute("companyCode") String companyCode, @RequestParam Map params) { params.put("companyCode", companyCode); - return ResponseEntity.ok(ApiResponse.success(adminService.getDepartmentList(params), "부서 목록 조회 성공")); + Map serviceResult = adminService.getDepartmentList(params); + + int total = ((Number) serviceResult.get("total")).intValue(); + + Map data = new HashMap<>(); + data.put("departments", serviceResult.get("departments")); + data.put("flatList", serviceResult.get("flatList")); + + Map response = new HashMap<>(); + response.put("success", true); + response.put("data", data); + response.put("message", "부서 목록 조회 성공"); + response.put("total", total); + response.put("totalCount", total); + return ResponseEntity.ok(response); } // ── 회사 관리 ────────────────────────────────────────────────────────── diff --git a/backend-spring/src/main/java/com/erp/controller/ScreenManagementController.java b/backend-spring/src/main/java/com/erp/controller/ScreenManagementController.java index b5d7285a..8151e712 100644 --- a/backend-spring/src/main/java/com/erp/controller/ScreenManagementController.java +++ b/backend-spring/src/main/java/com/erp/controller/ScreenManagementController.java @@ -217,11 +217,14 @@ public class ScreenManagementController { // ─── 휴지통 ──────────────────────────────────────────────── @GetMapping("/screens/trash/list") - public ResponseEntity>> getDeletedScreens( + public ResponseEntity>>> getDeletedScreens( @RequestAttribute("companyCode") String companyCode, @RequestParam Map params) { params.put("companyCode", companyCode); - return ResponseEntity.ok(ApiResponse.success(service.getDeletedScreens(params))); + Map result = service.getDeletedScreens(params); + @SuppressWarnings("unchecked") + List> list = (List>) result.get("data"); + return ResponseEntity.ok(ApiResponse.success(list)); } @PostMapping("/screens/{id}/restore") diff --git a/backend-spring/src/main/java/com/erp/service/AdminService.java b/backend-spring/src/main/java/com/erp/service/AdminService.java index 002e6ed4..dc601495 100644 --- a/backend-spring/src/main/java/com/erp/service/AdminService.java +++ b/backend-spring/src/main/java/com/erp/service/AdminService.java @@ -340,8 +340,44 @@ public class AdminService extends BaseService { public Map getDepartmentList(Map params) { commonService.applyCompanyCodeFilter(params); - List> list = sqlSession.selectList("admin.selectDepartmentList", params); - return commonService.buildListResponse(list, list.size(), params); + List> rawList = sqlSession.selectList("admin.selectDepartmentList", params); + + // 평탄 목록 (camelCase 변환) + List> flatList = rawList.stream() + .map(commonService::toCamelCaseKeys) + .collect(Collectors.toList()); + + // 트리 구조 빌드 — 1차: camelCase 변환 + children 초기화 + java.util.LinkedHashMap> deptTreeMap = new java.util.LinkedHashMap<>(); + List> rootDepts = new java.util.ArrayList<>(); + + for (Map raw : rawList) { + Map node = commonService.toCamelCaseKeys(raw); + node.put("children", new java.util.ArrayList<>()); + deptTreeMap.put((String) raw.get("dept_code"), node); + } + + // 2차: parent_dept_code 기준 트리 연결 + for (Map raw : rawList) { + String deptCode = (String) raw.get("dept_code"); + String parentDeptCode = (String) raw.get("parent_dept_code"); + Map node = deptTreeMap.get(deptCode); + + if (parentDeptCode != null && deptTreeMap.containsKey(parentDeptCode)) { + @SuppressWarnings("unchecked") + List> children = (List>) deptTreeMap.get(parentDeptCode).get("children"); + children.add(node); + } else { + rootDepts.add(node); + } + } + + Map result = new HashMap<>(); + result.put("departments", rootDepts); + result.put("flatList", flatList); + result.put("total", rawList.size()); + result.put("totalCount", rawList.size()); + return result; } // ── 회사 관리 ────────────────────────────────────────────────────────── diff --git a/backend-spring/src/main/java/com/erp/service/ScheduleService.java b/backend-spring/src/main/java/com/erp/service/ScheduleService.java index 7e120d23..50aeb2d2 100644 --- a/backend-spring/src/main/java/com/erp/service/ScheduleService.java +++ b/backend-spring/src/main/java/com/erp/service/ScheduleService.java @@ -21,13 +21,10 @@ public class ScheduleService extends BaseService { public Map getScheduleList(Map params) { commonService.applyCompanyCodeFilter(params); - commonService.applyPagination(params); - Integer totalObj = sqlSession.selectOne(NS + "getScheduleListCnt", params); - int totalCount = totalObj != null ? totalObj : 0; List> list = sqlSession.selectList(NS + "getScheduleList", params); Map result = new LinkedHashMap<>(); result.put("data", list); - result.put("total", totalCount); + result.put("total", list.size()); return result; } diff --git a/backend-spring/src/main/java/com/erp/service/ScreenManagementService.java b/backend-spring/src/main/java/com/erp/service/ScreenManagementService.java index 14a7bf42..b450a361 100644 --- a/backend-spring/src/main/java/com/erp/service/ScreenManagementService.java +++ b/backend-spring/src/main/java/com/erp/service/ScreenManagementService.java @@ -499,16 +499,57 @@ public class ScreenManagementService extends BaseService { } /** GET /layout — V2 우선 조회 (layer_id=1), 없으면 V1을 { components: [...] } 로 감싸서 반환 */ + @SuppressWarnings("unchecked") public Map getLayout(Integer screenId, String companyCode) { Map v2 = getLayoutV2(screenId, companyCode, 1); - if (v2 != null) return v2; + if (v2 != null) { + if (!v2.containsKey("gridSettings") || v2.get("gridSettings") == null) { + v2.put("gridSettings", buildDefaultGridSettings()); + } + if (!v2.containsKey("screenResolution") || v2.get("screenResolution") == null) { + Object compsObj = v2.get("components"); + if (compsObj instanceof List && !((List) compsObj).isEmpty()) { + List> comps = (List>) compsObj; + int maxRight = 0, maxBottom = 0; + for (Map comp : comps) { + Object posObj = comp.get("position"); + Object szObj = comp.get("size"); + if (posObj instanceof Map && szObj instanceof Map) { + Map pos = (Map) posObj; + Map sz = (Map) szObj; + int right = toInt(pos.getOrDefault("x", 0), 0) + toInt(sz.getOrDefault("width", 200), 200); + int bottom = toInt(pos.getOrDefault("y", 0), 0) + toInt(sz.getOrDefault("height", 100), 100); + maxRight = Math.max(maxRight, right); + maxBottom = Math.max(maxBottom, bottom); + } + } + Map res = new LinkedHashMap<>(); + res.put("width", Math.max(1200, maxRight + 100)); + res.put("height", Math.max(800, maxBottom + 100)); + v2.put("screenResolution", res); + } + } + return v2; + } List> v1 = getLayoutV1(screenId); Map result = new LinkedHashMap<>(); - result.put("components", v1 != null ? v1 : Collections.emptyList()); + result.put("components", v1 != null ? v1 : Collections.emptyList()); + result.put("gridSettings", buildDefaultGridSettings()); + result.put("screenResolution", null); return result; } + private Map buildDefaultGridSettings() { + Map gs = new LinkedHashMap<>(); + gs.put("columns", 12); + gs.put("gap", 16); + gs.put("padding", 16); + gs.put("snapToGrid", true); + gs.put("showGrid", true); + return gs; + } + // ═══════════════════════════════════════════════════════════ // Layout V2 // ═══════════════════════════════════════════════════════════ diff --git a/backend-spring/src/main/java/com/erp/service/TableManagementService.java b/backend-spring/src/main/java/com/erp/service/TableManagementService.java index 424dbd92..fcd29d4d 100644 --- a/backend-spring/src/main/java/com/erp/service/TableManagementService.java +++ b/backend-spring/src/main/java/com/erp/service/TableManagementService.java @@ -32,13 +32,11 @@ public class TableManagementService extends BaseService { public List> getTableList() { List> tables = sqlSession.selectList(NS + "getTableList"); - // column_count BigInt → Integer 변환 + camelCase 키 추가 (Node 호환) + // columnCount Long → Integer 변환 (Node 호환) for (Map t : tables) { - Object cnt = t.get("column_count"); + Object cnt = t.get("columnCount"); if (cnt instanceof Number) { - int intVal = ((Number) cnt).intValue(); - t.put("column_count", intVal); - t.put("columnCount", intVal); + t.put("columnCount", ((Number) cnt).intValue()); } } return tables; diff --git a/backend-spring/src/main/resources/mapper/admin.xml b/backend-spring/src/main/resources/mapper/admin.xml index 49ed0445..fe8aca10 100644 --- a/backend-spring/src/main/resources/mapper/admin.xml +++ b/backend-spring/src/main/resources/mapper/admin.xml @@ -47,6 +47,18 @@ AND MENU.MENU_TYPE = CAST(#{menuType} AS NUMERIC) + + AND EXISTS ( + SELECT 1 + FROM REL_MENU_AUTH RMA + JOIN AUTHORITY_MASTER AM ON RMA.AUTH_OBJID = AM.OBJID + JOIN AUTHORITY_SUB_USER ASU ON AM.OBJID = ASU.MASTER_OBJID + WHERE RMA.MENU_OBJID = MENU.OBJID + AND ASU.USER_ID = #{userId} + AND AM.STATUS = 'active' + AND RMA.READ_YN = 'Y' + ) + UNION ALL @@ -82,6 +94,18 @@ AND (S.COMPANY_CODE = #{companyCode} OR S.COMPANY_CODE = '*') + + AND EXISTS ( + SELECT 1 + FROM REL_MENU_AUTH RMA + JOIN AUTHORITY_MASTER AM ON RMA.AUTH_OBJID = AM.OBJID + JOIN AUTHORITY_SUB_USER ASU ON AM.OBJID = ASU.MASTER_OBJID + WHERE RMA.MENU_OBJID = S.OBJID + AND ASU.USER_ID = #{userId} + AND AM.STATUS = 'active' + AND RMA.READ_YN = 'Y' + ) + ) SELECT V.LEV @@ -90,16 +114,16 @@ , CAST(V.PARENT_OBJ_ID AS TEXT) AS PARENT_OBJ_ID , V.MENU_NAME_KOR , LPAD(' ', 3 * (V.LEV - 1)) || V.MENU_NAME_KOR AS LPAD_MENU_NAME_KOR - , V.MENU_URL - , V.MENU_DESC + , COALESCE(V.MENU_URL, '') AS MENU_URL + , COALESCE(V.MENU_DESC, '') AS MENU_DESC , CAST(V.SEQ AS TEXT) AS SEQ , V.WRITER , TO_CHAR(V.REGDATE, 'YYYY-MM-DD') AS REGDATE , V.STATUS , V.COMPANY_CODE - , V.LANG_KEY - , V.LANG_KEY_DESC - , V.MENU_ICON + , COALESCE(V.LANG_KEY, '') AS LANG_KEY + , COALESCE(V.LANG_KEY_DESC, '') AS LANG_KEY_DESC + , COALESCE(V.MENU_ICON, '') AS MENU_ICON , COALESCE(CM.COMPANY_NAME, '미지정') AS COMPANY_NAME , COALESCE( (SELECT MLT.LANG_TEXT @@ -119,7 +143,7 @@ WHERE MLKM.LANG_KEY = V.LANG_KEY_DESC AND MLT.LANG_CODE = #{userLang} LIMIT 1), - V.MENU_DESC + COALESCE(V.MENU_DESC, '') ) AS TRANSLATED_DESC , CASE UPPER(V.STATUS) WHEN 'ACTIVE' THEN '활성화' @@ -153,8 +177,8 @@ , MENU.MENU_ICON , ARRAY[MENU.OBJID] AS PATH FROM MENU_INFO MENU - WHERE MENU.PARENT_OBJ_ID = 0 - AND MENU.MENU_TYPE = 1 + WHERE MENU.PARENT_OBJ_ID = '0' + AND MENU.MENU_TYPE = '1' AND MENU.STATUS = 'active' @@ -192,21 +216,21 @@ ) SELECT V.LEV - , CASE V.MENU_TYPE WHEN 0 THEN 'admin' WHEN 1 THEN 'user' ELSE '' END AS MENU_TYPE + , CASE V.MENU_TYPE WHEN '0' THEN 'admin' WHEN '1' THEN 'user' ELSE '' END AS MENU_TYPE , CAST(V.OBJID AS TEXT) AS OBJID , CAST(V.PARENT_OBJ_ID AS TEXT) AS PARENT_OBJ_ID , V.MENU_NAME_KOR , LPAD(' ', 3 * (V.LEV - 1)) || V.MENU_NAME_KOR AS LPAD_MENU_NAME_KOR - , V.MENU_URL - , V.MENU_DESC + , COALESCE(V.MENU_URL, '') AS MENU_URL + , COALESCE(V.MENU_DESC, '') AS MENU_DESC , CAST(V.SEQ AS TEXT) AS SEQ , V.WRITER , TO_CHAR(V.REGDATE, 'YYYY-MM-DD') AS REGDATE , V.STATUS , V.COMPANY_CODE - , V.LANG_KEY - , V.LANG_KEY_DESC - , V.MENU_ICON + , COALESCE(V.LANG_KEY, '') AS LANG_KEY + , COALESCE(V.LANG_KEY_DESC, '') AS LANG_KEY_DESC + , COALESCE(V.MENU_ICON, '') AS MENU_ICON , COALESCE(CM.COMPANY_NAME, '미지정') AS COMPANY_NAME , COALESCE( (SELECT MLT.LANG_TEXT @@ -226,7 +250,7 @@ WHERE MLKM.LANG_KEY = V.LANG_KEY_DESC AND MLT.LANG_CODE = #{userLang} LIMIT 1), - V.MENU_DESC + COALESCE(V.MENU_DESC, '') ) AS TRANSLATED_DESC , CASE UPPER(V.STATUS) WHEN 'ACTIVE' THEN '활성화' @@ -250,8 +274,8 @@ , COMPANY_CODE , STATUS FROM MENU_INFO - WHERE PARENT_OBJ_ID = 0 - AND MENU_TYPE = 1 + WHERE PARENT_OBJ_ID = '0' + AND MENU_TYPE = '1' AND (MENU_DESC LIKE '%[POP]%' OR UPPER(MENU_NAME_KOR) LIKE '%POP%') @@ -381,16 +405,15 @@ FROM USER_INFO WHERE 1=1 - AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*') - AND COMPANY_CODE != '*' - - - AND COMPANY_CODE != '*' + AND COMPANY_CODE = #{companyCode} AND (USER_ID ILIKE #{search} OR USER_NAME ILIKE #{search} OR DEPT_NAME ILIKE #{search} + OR POSITION_NAME ILIKE #{search} + OR USER_TYPE_NAME ILIKE #{search} + OR SABUN ILIKE #{search} OR EMAIL ILIKE #{search} OR TEL ILIKE #{search} OR CELL_PHONE ILIKE #{search}) @@ -411,16 +434,15 @@ FROM USER_INFO WHERE 1=1 - AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*') - AND COMPANY_CODE != '*' - - - AND COMPANY_CODE != '*' + AND COMPANY_CODE = #{companyCode} AND (USER_ID ILIKE #{search} OR USER_NAME ILIKE #{search} OR DEPT_NAME ILIKE #{search} + OR POSITION_NAME ILIKE #{search} + OR USER_TYPE_NAME ILIKE #{search} + OR SABUN ILIKE #{search} OR EMAIL ILIKE #{search} OR TEL ILIKE #{search} OR CELL_PHONE ILIKE #{search}) @@ -561,14 +583,32 @@ ================================================================ -->