[agent-pipeline] pipe-20260328092322-vevu round-1

This commit is contained in:
DDD1542
2026-03-28 18:38:49 +09:00
parent a7c9ba2982
commit dc035667e8
15 changed files with 229 additions and 69 deletions
@@ -308,11 +308,25 @@ public class AdminController {
* 부서 목록 조회
*/
@GetMapping("/departments")
public ResponseEntity<ApiResponse<Map<String, Object>>> getDepartmentList(
public ResponseEntity<?> getDepartmentList(
@RequestAttribute("companyCode") String companyCode,
@RequestParam Map<String, Object> params) {
params.put("companyCode", companyCode);
return ResponseEntity.ok(ApiResponse.success(adminService.getDepartmentList(params), "부서 목록 조회 성공"));
Map<String, Object> serviceResult = adminService.getDepartmentList(params);
int total = ((Number) serviceResult.get("total")).intValue();
Map<String, Object> data = new HashMap<>();
data.put("departments", serviceResult.get("departments"));
data.put("flatList", serviceResult.get("flatList"));
Map<String, Object> 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);
}
// ── 회사 관리 ──────────────────────────────────────────────────────────
@@ -217,11 +217,14 @@ public class ScreenManagementController {
// ─── 휴지통 ────────────────────────────────────────────────
@GetMapping("/screens/trash/list")
public ResponseEntity<ApiResponse<Map<String, Object>>> getDeletedScreens(
public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getDeletedScreens(
@RequestAttribute("companyCode") String companyCode,
@RequestParam Map<String, Object> params) {
params.put("companyCode", companyCode);
return ResponseEntity.ok(ApiResponse.success(service.getDeletedScreens(params)));
Map<String, Object> result = service.getDeletedScreens(params);
@SuppressWarnings("unchecked")
List<Map<String, Object>> list = (List<Map<String, Object>>) result.get("data");
return ResponseEntity.ok(ApiResponse.success(list));
}
@PostMapping("/screens/{id}/restore")
@@ -340,8 +340,44 @@ public class AdminService extends BaseService {
public Map<String, Object> getDepartmentList(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
List<Map<String, Object>> list = sqlSession.selectList("admin.selectDepartmentList", params);
return commonService.buildListResponse(list, list.size(), params);
List<Map<String, Object>> rawList = sqlSession.selectList("admin.selectDepartmentList", params);
// 평탄 목록 (camelCase 변환)
List<Map<String, Object>> flatList = rawList.stream()
.map(commonService::toCamelCaseKeys)
.collect(Collectors.toList());
// 트리 구조 빌드 — 1차: camelCase 변환 + children 초기화
java.util.LinkedHashMap<String, Map<String, Object>> deptTreeMap = new java.util.LinkedHashMap<>();
List<Map<String, Object>> rootDepts = new java.util.ArrayList<>();
for (Map<String, Object> raw : rawList) {
Map<String, Object> 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<String, Object> raw : rawList) {
String deptCode = (String) raw.get("dept_code");
String parentDeptCode = (String) raw.get("parent_dept_code");
Map<String, Object> node = deptTreeMap.get(deptCode);
if (parentDeptCode != null && deptTreeMap.containsKey(parentDeptCode)) {
@SuppressWarnings("unchecked")
List<Map<String, Object>> children = (List<Map<String, Object>>) deptTreeMap.get(parentDeptCode).get("children");
children.add(node);
} else {
rootDepts.add(node);
}
}
Map<String, Object> result = new HashMap<>();
result.put("departments", rootDepts);
result.put("flatList", flatList);
result.put("total", rawList.size());
result.put("totalCount", rawList.size());
return result;
}
// ── 회사 관리 ──────────────────────────────────────────────────────────
@@ -21,13 +21,10 @@ public class ScheduleService extends BaseService {
public Map<String, Object> getScheduleList(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
commonService.applyPagination(params);
Integer totalObj = sqlSession.selectOne(NS + "getScheduleListCnt", params);
int totalCount = totalObj != null ? totalObj : 0;
List<Map<String, Object>> list = sqlSession.selectList(NS + "getScheduleList", params);
Map<String, Object> result = new LinkedHashMap<>();
result.put("data", list);
result.put("total", totalCount);
result.put("total", list.size());
return result;
}
@@ -499,16 +499,57 @@ public class ScreenManagementService extends BaseService {
}
/** GET /layout — V2 우선 조회 (layer_id=1), 없으면 V1을 { components: [...] } 로 감싸서 반환 */
@SuppressWarnings("unchecked")
public Map<String, Object> getLayout(Integer screenId, String companyCode) {
Map<String, Object> 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<Map<String, Object>> comps = (List<Map<String, Object>>) compsObj;
int maxRight = 0, maxBottom = 0;
for (Map<String, Object> comp : comps) {
Object posObj = comp.get("position");
Object szObj = comp.get("size");
if (posObj instanceof Map && szObj instanceof Map) {
Map<String, Object> pos = (Map<String, Object>) posObj;
Map<String, Object> sz = (Map<String, Object>) 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<String, Object> 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<Map<String, Object>> v1 = getLayoutV1(screenId);
Map<String, Object> result = new LinkedHashMap<>();
result.put("components", v1 != null ? v1 : Collections.emptyList());
result.put("gridSettings", buildDefaultGridSettings());
result.put("screenResolution", null);
return result;
}
private Map<String, Object> buildDefaultGridSettings() {
Map<String, Object> 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
// ═══════════════════════════════════════════════════════════
@@ -32,13 +32,11 @@ public class TableManagementService extends BaseService {
public List<Map<String, Object>> getTableList() {
List<Map<String, Object>> tables = sqlSession.selectList(NS + "getTableList");
// column_count BigInt → Integer 변환 + camelCase 키 추가 (Node 호환)
// columnCount Long → Integer 변환 (Node 호환)
for (Map<String, Object> 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;
@@ -47,6 +47,18 @@
<if test="menuType != null">
AND MENU.MENU_TYPE = CAST(#{menuType} AS NUMERIC)
</if>
<if test='userId != null and userType != null and userType != "SUPER_ADMIN" and !isManagementScreen'>
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'
)
</if>
UNION ALL
@@ -82,6 +94,18 @@
AND (S.COMPANY_CODE = #{companyCode} OR S.COMPANY_CODE = '*')
</when>
</choose>
<if test='userId != null and userType != null and userType != "SUPER_ADMIN" and !isManagementScreen'>
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'
)
</if>
)
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'
<choose>
<when test='userType == "SUPER_ADMIN" and companyCode == "*"'>
@@ -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%')
<choose>
<when test='userType == "SUPER_ADMIN" and companyCode == "*"'>
@@ -381,16 +405,15 @@
FROM USER_INFO
WHERE 1=1
<if test='companyCode != null and companyCode != "*"'>
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
AND COMPANY_CODE != '*'
</if>
<if test='companyCode == "*"'>
AND COMPANY_CODE != '*'
AND COMPANY_CODE = #{companyCode}
</if>
<if test="search != null and search != ''">
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
<if test='companyCode != null and companyCode != "*"'>
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
AND COMPANY_CODE != '*'
</if>
<if test='companyCode == "*"'>
AND COMPANY_CODE != '*'
AND COMPANY_CODE = #{companyCode}
</if>
<if test="search != null and search != ''">
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 @@
================================================================ -->
<select id="selectDepartmentList" parameterType="map" resultType="map">
SELECT DISTINCT
SELECT
DEPT_CODE
, PARENT_DEPT_CODE
, DEPT_NAME
, MASTER_SABUN
, MASTER_USER_ID
, LOCATION
, LOCATION_NAME
, CASE WHEN REGDATE IS NOT NULL THEN TO_CHAR(REGDATE, 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') ELSE NULL END AS REGDATE
, DATA_TYPE
, STATUS
, SALES_YN
, COMPANY_CODE
FROM USER_INFO
WHERE DEPT_CODE IS NOT NULL
, COMPANY_NAME
FROM DEPT_INFO
WHERE 1=1
<include refid="common.companyCodeFilter"/>
ORDER BY DEPT_NAME ASC
<if test="status != null and status != ''">
AND STATUS = #{status}
</if>
<if test="search != null and search != ''">
AND (DEPT_NAME ILIKE '%' || #{search} || '%'
OR DEPT_CODE ILIKE '%' || #{search} || '%'
OR LOCATION_NAME ILIKE '%' || #{search} || '%')
</if>
ORDER BY PARENT_DEPT_CODE ASC NULLS FIRST, DEPT_NAME ASC
</select>
<!-- ================================================================
@@ -90,7 +90,7 @@
ON T.DEFINITION_ID = D.DEFINITION_ID AND T.COMPANY_CODE = D.COMPANY_CODE
WHERE 1=1
<if test='companyCode != null and companyCode != "*"'>
AND (T.COMPANY_CODE = #{companyCode} OR T.COMPANY_CODE = '*')
AND T.COMPANY_CODE = #{companyCode}
</if>
<if test="definition_id != null">
AND T.DEFINITION_ID = #{definition_id}
@@ -28,14 +28,24 @@
FROM batch_execution_logs bel
LEFT JOIN batch_configs bc ON bel.batch_config_id = bc.id
LEFT JOIN batch_configs bc ON bel.batch_config_id::INTEGER = bc.id
WHERE 1=1
<if test="companyCode != null and companyCode != &quot;*&quot;">
AND (bel.company_code = #{companyCode} OR bel.company_code = '*')
</if>
<include refid="batchExecutionLogSearchCondition"/>
<include refid="common.dynamicOrderBy"/>
<choose>
<when test="sortColumn != null and sortColumn != ''">
ORDER BY ${sortColumn}
<if test="sortDirection != null and sortDirection != ''">
${sortDirection}
</if>
</when>
<otherwise>
ORDER BY bel.start_time DESC
</otherwise>
</choose>
<include refid="common.pagination"/>
</select>
@@ -44,7 +54,7 @@
FROM batch_execution_logs bel
LEFT JOIN batch_configs bc ON bel.batch_config_id = bc.id
LEFT JOIN batch_configs bc ON bel.batch_config_id::INTEGER = bc.id
WHERE 1=1
<if test="companyCode != null and companyCode != &quot;*&quot;">
@@ -63,7 +73,7 @@
FROM batch_execution_logs bel
LEFT JOIN batch_configs bc ON bel.batch_config_id = bc.id
LEFT JOIN batch_configs bc ON bel.batch_config_id::INTEGER = bc.id
WHERE bel.id = #{id}
<if test="companyCode != null and companyCode != &quot;*&quot;">
@@ -163,7 +163,7 @@
<update id="updateCurrentSequenceInRule" parameterType="map">
UPDATE numbering_rules
SET current_sequence = GREATEST(COALESCE(current_sequence, 0), #{currentSequence}),
SET current_sequence = GREATEST(COALESCE(current_sequence, '0'), #{currentSequence}),
updated_at = NOW()
WHERE rule_id = #{ruleId}
@@ -901,15 +901,15 @@
FROM MENU_INFO M
LEFT JOIN MENU_INFO P ON M.PARENT_OBJ_ID = P.OBJID
WHERE (M.COMPANY_CODE = #{companyCode} OR M.COMPANY_CODE = '*')
AND M.MENU_TYPE = 1
AND M.MENU_TYPE = '1'
</select>
<select id="selectUserMenuRoot" parameterType="map" resultType="map">
SELECT OBJID
FROM MENU_INFO
WHERE (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
AND MENU_TYPE = 1
AND PARENT_OBJ_ID = 0
AND MENU_TYPE = '1'
AND PARENT_OBJ_ID = '0'
ORDER BY SEQ ASC
LIMIT 1
</select>
@@ -946,7 +946,7 @@
FROM MENU_INFO
WHERE PARENT_OBJ_ID = #{parentObjid}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
AND MENU_TYPE = 1
AND MENU_TYPE = '1'
</select>
<insert id="insertMenuForGroup" parameterType="map">
@@ -1004,9 +1004,9 @@
FROM MENU_INFO M
LEFT JOIN MENU_INFO PARENT ON M.PARENT_OBJ_ID = PARENT.OBJID
WHERE (M.COMPANY_CODE = #{companyCode} OR M.COMPANY_CODE = '*')
AND M.MENU_TYPE = 1
AND M.MENU_TYPE = '1'
ORDER BY
CASE WHEN M.PARENT_OBJ_ID = 0 THEN 0 ELSE 1 END,
CASE WHEN M.PARENT_OBJ_ID = '0' THEN 0 ELSE 1 END,
M.PARENT_OBJ_ID,
M.SEQ
</select>
@@ -1028,7 +1028,7 @@
FROM SCREEN_GROUPS
WHERE (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
AND PARENT_GROUP_ID IS NULL
AND GROUP_LEVEL = 0
AND GROUP_LEVEL = '0'
ORDER BY ID ASC
LIMIT 1
</select>
@@ -1094,7 +1094,7 @@
COUNT(CASE WHEN SCREEN_GROUP_ID IS NULL THEN 1 END) AS UNLINKED_MENUS
FROM MENU_INFO
WHERE (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
AND MENU_TYPE = 1
AND MENU_TYPE = '1'
</select>
<!-- ══════════════════════════════════════════════════════════════
@@ -107,9 +107,30 @@
<select id="selectScreenById" parameterType="map" resultType="map">
SELECT
*
FROM SCREEN_DEFINITIONS
WHERE SCREEN_ID = #{screenId}
SD.SCREEN_ID
, SD.SCREEN_NAME
, SD.SCREEN_CODE
, SD.TABLE_NAME
, SD.COMPANY_CODE
, SD.DESCRIPTION
, SD.IS_ACTIVE
, SD.CREATED_DATE
, SD.CREATED_BY
, SD.UPDATED_DATE
, SD.UPDATED_BY
, SD.DB_SOURCE_TYPE
, SD.DB_CONNECTION_ID
, SD.DATA_SOURCE_TYPE
, SD.REST_API_CONNECTION_ID
, SD.REST_API_ENDPOINT
, COALESCE(SD.REST_API_JSON_PATH, 'data') AS REST_API_JSON_PATH
, SD.DELETED_DATE
, SD.DELETED_BY
, SD.DELETE_REASON
, COALESCE(TL.TABLE_LABEL, SD.TABLE_NAME) AS TABLE_LABEL
FROM SCREEN_DEFINITIONS SD
LEFT JOIN TABLE_LABELS TL ON SD.TABLE_NAME = TL.TABLE_NAME
WHERE SD.SCREEN_ID = #{screenId}
LIMIT 1
</select>
@@ -457,9 +457,9 @@
INNER JOIN menu_info m0 ON m1.parent_obj_id = m0.objid
WHERE m1.menu_type = 1
WHERE m1.menu_type = '1'
AND m1.status = 'active'
AND m0.parent_obj_id = 0
AND m0.parent_obj_id = '0'
<if test='hasCompanyCode and companyCode != null and companyCode != "*"'>
AND (m1.company_code = #{companyCode} OR m1.company_code = '*')
</if>
@@ -12,7 +12,7 @@
, COALESCE(TL.TABLE_LABEL, T.TABLE_NAME) AS "displayName"
, COALESCE(TL.DESCRIPTION, '') AS "description"
, (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = T.TABLE_NAME AND TABLE_SCHEMA = 'public') AS column_count
WHERE TABLE_NAME = T.TABLE_NAME AND TABLE_SCHEMA = 'public') AS "columnCount"
FROM INFORMATION_SCHEMA.TABLES T
LEFT JOIN TABLE_LABELS TL
ON T.TABLE_NAME = TL.TABLE_NAME
@@ -245,7 +245,7 @@
UPDATE vehicle_trip_summary
SET
location_count = COALESCE(location_count, 0) + 1
location_count = COALESCE(location_count, '0')::INT + 1
WHERE trip_id = #{tripId}
</update>