2f398ae0b3
- 제어모드 IDE: ControlCardPanel, control/ide/* (Canvas/LeftRail/RightRail/PanZoomStage/V3RuleNode 등), schemas, lib/api/control - 레지스트리 정리: aggregation-widget, status-count, section-card/paper, table-list(legacy/v2), tabs-widget 폐기 → table/_shared/ 로 통합 - InvLegacyButtonConfigPanel cp 마이그레이션 - canonical data view cleanup 후속 노트
1458 lines
76 KiB
Java
1458 lines
76 KiB
Java
package com.erp.service;
|
|
|
|
import com.erp.common.BaseService;
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
|
|
@Service
|
|
@RequiredArgsConstructor
|
|
@Slf4j
|
|
public class ScreenGroupService extends BaseService {
|
|
|
|
private static final String NS = "screenGroup.";
|
|
|
|
/**
|
|
* canonical table / legacy table-list / hidden v2-table-list 위젯 카운트 합산.
|
|
* screen type inference 시 셋 모두 grid 화면으로 인식해야 한다 (frontend
|
|
* isTableLikeComponentType 와 동일 정책 — 2026-05-19 canonical cleanup follow-up).
|
|
*/
|
|
private static int countTableLikeWidgets(Map<String, Integer> widgetCounts) {
|
|
if (widgetCounts == null) return 0;
|
|
return widgetCounts.getOrDefault("table", 0)
|
|
+ widgetCounts.getOrDefault("table-list", 0)
|
|
+ widgetCounts.getOrDefault("v2-table-list", 0);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Screen Groups
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
public Map<String, Object> getScreenGroups(Map<String, Object> params) {
|
|
int page = toInt(params.getOrDefault("page", 1));
|
|
int size = toInt(params.getOrDefault("size", 20));
|
|
params.put("limit", size);
|
|
params.put("offset", (page - 1) * size);
|
|
|
|
int total = sqlSession.selectOne(NS + "countScreenGroups", params);
|
|
List<Map<String, Object>> groups = sqlSession.selectList(NS + "selectScreenGroups", params);
|
|
|
|
// screens 조립 (별도 쿼리)
|
|
if (!groups.isEmpty()) {
|
|
List<Object> groupIds = groups.stream()
|
|
.map(g -> g.get("id"))
|
|
.collect(Collectors.toList());
|
|
Map<String, Object> screenParams = new HashMap<>();
|
|
screenParams.put("group_ids", groupIds);
|
|
List<Map<String, Object>> allScreens = sqlSession.selectList(NS + "selectGroupScreensByGroupIds", screenParams);
|
|
Map<Object, List<Map<String, Object>>> byGroup = allScreens.stream()
|
|
.collect(Collectors.groupingBy(s -> s.get("group_id")));
|
|
for (Map<String, Object> g : groups) {
|
|
g.put("screens", byGroup.getOrDefault(g.get("id"), Collections.emptyList()));
|
|
}
|
|
}
|
|
|
|
Map<String, Object> result = new LinkedHashMap<>();
|
|
result.put("success", true);
|
|
result.put("data", groups);
|
|
result.put("total", total);
|
|
result.put("page", page);
|
|
result.put("size", size);
|
|
result.put("total_pages", (int) Math.ceil((double) total / size));
|
|
return result;
|
|
}
|
|
|
|
public Map<String, Object> getScreenGroup(Map<String, Object> params) {
|
|
Map<String, Object> group = sqlSession.selectOne(NS + "selectScreenGroupById", params);
|
|
if (group == null) return null;
|
|
|
|
List<Object> groupIds = Collections.singletonList(group.get("id"));
|
|
Map<String, Object> sp = new HashMap<>();
|
|
sp.put("group_ids", groupIds);
|
|
List<Map<String, Object>> screens = sqlSession.selectList(NS + "selectGroupScreensByGroupIds", sp);
|
|
group.put("screens", screens);
|
|
return group;
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> createScreenGroup(Map<String, Object> params) {
|
|
// 부모 그룹 계층 계산
|
|
Object parentGroupId = params.get("parent_group_id");
|
|
int groupLevel = 0;
|
|
String parentHierarchyPath = "";
|
|
if (parentGroupId != null) {
|
|
Map<String, Object> pp = new HashMap<>();
|
|
pp.put("parent_group_id", parentGroupId);
|
|
Map<String, Object> parent = sqlSession.selectOne(NS + "selectParentGroupById", pp);
|
|
if (parent != null) {
|
|
groupLevel = toInt(parent.getOrDefault("group_level", 0)) + 1;
|
|
parentHierarchyPath = (String) parent.getOrDefault("hierarchy_path",
|
|
"/" + parentGroupId + "/");
|
|
}
|
|
}
|
|
params.put("group_level", groupLevel);
|
|
|
|
sqlSession.insert(NS + "insertScreenGroup", params);
|
|
Object newId = params.get("id");
|
|
|
|
// hierarchy_path 업데이트
|
|
String hierarchyPath;
|
|
if (parentGroupId != null && !parentHierarchyPath.isEmpty()) {
|
|
hierarchyPath = (parentHierarchyPath + newId + "/").replace("//", "/");
|
|
} else {
|
|
hierarchyPath = "/" + newId + "/";
|
|
}
|
|
Map<String, Object> hp = new HashMap<>();
|
|
hp.put("id", newId);
|
|
hp.put("hierarchy_path", hierarchyPath);
|
|
sqlSession.update(NS + "updateScreenGroupHierarchyPath", hp);
|
|
|
|
Map<String, Object> sp = new HashMap<>();
|
|
sp.put("id", newId);
|
|
return sqlSession.selectOne(NS + "selectScreenGroupById", sp);
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> updateScreenGroup(Map<String, Object> params) {
|
|
Object id = params.get("id");
|
|
String userCompanyCode = (String) params.get("company_code");
|
|
Object parentGroupId = params.get("parent_group_id");
|
|
|
|
// 자기 자신을 부모로 지정하는 것 방지
|
|
if (parentGroupId != null && toInt(parentGroupId) == toInt(id)) {
|
|
throw new IllegalArgumentException("자기 자신을 상위 그룹으로 지정할 수 없습니다.");
|
|
}
|
|
|
|
// 부모 그룹 계층 재계산
|
|
int groupLevel = 0;
|
|
String hierarchyPath = "/" + id + "/";
|
|
if (parentGroupId != null) {
|
|
Map<String, Object> pp = new HashMap<>();
|
|
pp.put("parent_group_id", parentGroupId);
|
|
Map<String, Object> parent = sqlSession.selectOne(NS + "selectParentGroupById", pp);
|
|
if (parent != null) {
|
|
String parentPath = (String) parent.getOrDefault("hierarchy_path",
|
|
"/" + parentGroupId + "/");
|
|
// 순환 참조 방지
|
|
if (parentPath != null && parentPath.contains("/" + id + "/")) {
|
|
throw new IllegalArgumentException("하위 그룹을 상위 그룹으로 지정할 수 없습니다.");
|
|
}
|
|
groupLevel = toInt(parent.getOrDefault("group_level", 0)) + 1;
|
|
hierarchyPath = (parentPath + id + "/").replace("//", "/");
|
|
}
|
|
}
|
|
params.put("group_level", groupLevel);
|
|
params.put("hierarchy_path", hierarchyPath);
|
|
|
|
// 최고관리자가 회사 변경하는 경우
|
|
Object targetCompanyCode = params.get("target_company_code");
|
|
int rows;
|
|
if ("*".equals(userCompanyCode) && targetCompanyCode != null) {
|
|
rows = sqlSession.update(NS + "updateScreenGroupWithCompany", params);
|
|
} else {
|
|
rows = sqlSession.update(NS + "updateScreenGroup", params);
|
|
}
|
|
if (rows == 0) {
|
|
throw new NoSuchElementException("화면 그룹을 찾을 수 없거나 권한이 없습니다.");
|
|
}
|
|
Map<String, Object> sp = new HashMap<>();
|
|
sp.put("id", id);
|
|
return sqlSession.selectOne(NS + "selectScreenGroupById", sp);
|
|
}
|
|
|
|
@Transactional
|
|
public void deleteScreenGroup(Map<String, Object> params) {
|
|
Object id = params.get("id");
|
|
String companyCode = (String) params.get("company_code");
|
|
boolean deleteNumberingRules = Boolean.TRUE.equals(params.get("delete_numbering_rules"));
|
|
|
|
// 대상 그룹의 company_code 확인
|
|
Map<String, Object> target = sqlSession.selectOne(NS + "selectScreenGroupForDelete", params);
|
|
if (target == null) {
|
|
throw new NoSuchElementException("화면 그룹을 찾을 수 없습니다.");
|
|
}
|
|
String targetCompanyCode = (String) target.get("company_code");
|
|
|
|
// 권한 체크
|
|
if (!"*".equals(companyCode) && !companyCode.equals(targetCompanyCode)) {
|
|
throw new SecurityException("권한이 없습니다.");
|
|
}
|
|
|
|
// 하위 그룹 ID 수집 (재귀)
|
|
Map<String, Object> cp = new HashMap<>();
|
|
cp.put("id", id);
|
|
cp.put("target_company_code", targetCompanyCode);
|
|
List<Map<String, Object>> children = sqlSession.selectList(NS + "selectAllChildGroupIds", cp);
|
|
List<Object> groupIds = children.stream().map(c -> c.get("id")).collect(Collectors.toList());
|
|
|
|
if (!groupIds.isEmpty()) {
|
|
// 연결된 메뉴 조회 및 삭제
|
|
Map<String, Object> mp = new HashMap<>();
|
|
mp.put("group_ids", groupIds);
|
|
mp.put("target_company_code", targetCompanyCode);
|
|
List<Map<String, Object>> menus = sqlSession.selectList(NS + "selectMenusByGroupIds", mp);
|
|
List<Object> menuObjids = menus.stream().map(m -> m.get("objid")).collect(Collectors.toList());
|
|
|
|
if (!menuObjids.isEmpty()) {
|
|
Map<String, Object> delp = new HashMap<>();
|
|
delp.put("menu_objids", menuObjids);
|
|
delp.put("target_company_code", targetCompanyCode);
|
|
sqlSession.delete(NS + "deleteScreenMenuAssignmentsByMenuObjids", delp);
|
|
sqlSession.delete(NS + "deleteMenusByGroupIds", mp);
|
|
}
|
|
|
|
// 채번 규칙 삭제 (최상위 그룹 + 명시 요청)
|
|
if (deleteNumberingRules) {
|
|
Map<String, Object> rp = new HashMap<>();
|
|
rp.put("id", id);
|
|
int isRoot = sqlSession.selectOne(NS + "isRootGroupById", rp);
|
|
if (isRoot > 0) {
|
|
Map<String, Object> nrp = new HashMap<>();
|
|
nrp.put("target_company_code", targetCompanyCode);
|
|
sqlSession.delete(NS + "deleteNumberingRuleParts", nrp);
|
|
sqlSession.delete(NS + "deleteNumberingRules", nrp);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 그룹 삭제
|
|
int deleted = sqlSession.delete(NS + "deleteScreenGroupById", cp);
|
|
if (deleted == 0) {
|
|
throw new NoSuchElementException("화면 그룹을 찾을 수 없거나 권한이 없습니다.");
|
|
}
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Screen Group Screens
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
@Transactional
|
|
public Map<String, Object> addScreenToGroup(Map<String, Object> params) {
|
|
sqlSession.insert(NS + "insertGroupScreen", params);
|
|
// 삽입 후 조회
|
|
List<Object> ids = Collections.singletonList(params.get("group_id"));
|
|
Map<String, Object> sp = new HashMap<>();
|
|
sp.put("group_ids", ids);
|
|
List<Map<String, Object>> screens = sqlSession.selectList(NS + "selectGroupScreensByGroupIds", sp);
|
|
return screens.stream()
|
|
.filter(s -> Objects.equals(s.get("screen_id"), params.get("screen_id")))
|
|
.findFirst()
|
|
.orElse(params);
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> updateScreenInGroup(Map<String, Object> params) {
|
|
int rows = sqlSession.update(NS + "updateGroupScreen", params);
|
|
if (rows == 0) throw new NoSuchElementException("연결을 찾을 수 없거나 권한이 없습니다.");
|
|
return params;
|
|
}
|
|
|
|
@Transactional
|
|
public void removeScreenFromGroup(Map<String, Object> params) {
|
|
int rows = sqlSession.delete(NS + "deleteGroupScreen", params);
|
|
if (rows == 0) throw new NoSuchElementException("연결을 찾을 수 없거나 권한이 없습니다.");
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Field Joins
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
public List<Map<String, Object>> getFieldJoins(Map<String, Object> params) {
|
|
return sqlSession.selectList(NS + "selectFieldJoins", params);
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> createFieldJoin(Map<String, Object> params) {
|
|
sqlSession.insert(NS + "insertFieldJoin", params);
|
|
return params;
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> updateFieldJoin(Map<String, Object> params) {
|
|
int rows = sqlSession.update(NS + "updateFieldJoin", params);
|
|
if (rows == 0) throw new NoSuchElementException("필드 조인을 찾을 수 없거나 권한이 없습니다.");
|
|
return params;
|
|
}
|
|
|
|
@Transactional
|
|
public void deleteFieldJoin(Map<String, Object> params) {
|
|
int rows = sqlSession.delete(NS + "deleteFieldJoin", params);
|
|
if (rows == 0) throw new NoSuchElementException("필드 조인을 찾을 수 없거나 권한이 없습니다.");
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Data Flows
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
public List<Map<String, Object>> getDataFlows(Map<String, Object> params) {
|
|
return sqlSession.selectList(NS + "selectDataFlows", params);
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> createDataFlow(Map<String, Object> params) {
|
|
// data_mapping을 JSON 문자열로 변환
|
|
convertToJsonString(params, "data_mapping");
|
|
sqlSession.insert(NS + "insertDataFlow", params);
|
|
return params;
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> updateDataFlow(Map<String, Object> params) {
|
|
convertToJsonString(params, "data_mapping");
|
|
int rows = sqlSession.update(NS + "updateDataFlow", params);
|
|
if (rows == 0) throw new NoSuchElementException("데이터 흐름을 찾을 수 없거나 권한이 없습니다.");
|
|
return params;
|
|
}
|
|
|
|
@Transactional
|
|
public void deleteDataFlow(Map<String, Object> params) {
|
|
int rows = sqlSession.delete(NS + "deleteDataFlow", params);
|
|
if (rows == 0) throw new NoSuchElementException("데이터 흐름을 찾을 수 없거나 권한이 없습니다.");
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Table Relations
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
public List<Map<String, Object>> getTableRelations(Map<String, Object> params) {
|
|
return sqlSession.selectList(NS + "selectTableRelations", params);
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> createTableRelation(Map<String, Object> params) {
|
|
sqlSession.insert(NS + "insertTableRelation", params);
|
|
return params;
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> updateTableRelation(Map<String, Object> params) {
|
|
int rows = sqlSession.update(NS + "updateTableRelation", params);
|
|
if (rows == 0) throw new NoSuchElementException("화면-테이블 관계를 찾을 수 없거나 권한이 없습니다.");
|
|
return params;
|
|
}
|
|
|
|
@Transactional
|
|
public void deleteTableRelation(Map<String, Object> params) {
|
|
int rows = sqlSession.delete(NS + "deleteTableRelation", params);
|
|
if (rows == 0) throw new NoSuchElementException("화면-테이블 관계를 찾을 수 없거나 권한이 없습니다.");
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Layout Summary
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
public Map<String, Object> getScreenLayoutSummary(Map<String, Object> params) {
|
|
List<Map<String, Object>> rows = sqlSession.selectList(NS + "selectLayoutComponents", params);
|
|
|
|
Map<String, Integer> widgetCounts = new LinkedHashMap<>();
|
|
List<String> labels = new ArrayList<>();
|
|
List<Map<String, Object>> fields = new ArrayList<>();
|
|
|
|
for (Map<String, Object> row : rows) {
|
|
String widgetType = row.get("widget_type") != null ? (String) row.get("widget_type") : "text";
|
|
widgetCounts.merge(widgetType, 1, Integer::sum);
|
|
|
|
String label = (String) row.get("label");
|
|
if (label != null && !label.equals("기본 버튼")) {
|
|
labels.add(label);
|
|
Map<String, Object> field = new LinkedHashMap<>();
|
|
field.put("label", label);
|
|
field.put("widget_type", widgetType);
|
|
field.put("field_name", row.get("field_name"));
|
|
fields.add(field);
|
|
}
|
|
}
|
|
|
|
// 화면 타입 추론
|
|
// table-like (canonical 'table' / legacy 'table-list' / hidden 'v2-table-list')
|
|
// 어느 것이든 있으면 grid 로 본다.
|
|
String screenType = "form";
|
|
if (countTableLikeWidgets(widgetCounts) > 0) {
|
|
screenType = "grid";
|
|
} else if (widgetCounts.getOrDefault("custom", 0) > 2) {
|
|
screenType = "dashboard";
|
|
} else if (widgetCounts.size() <= 2 && widgetCounts.getOrDefault("button", 0) > 0) {
|
|
screenType = "action";
|
|
}
|
|
|
|
Map<String, Object> data = new LinkedHashMap<>();
|
|
data.put("screen_id", toInt(params.get("screen_id")));
|
|
data.put("screen_type", screenType);
|
|
data.put("widget_counts", widgetCounts);
|
|
data.put("total_components", rows.size());
|
|
data.put("fields", fields.subList(0, Math.min(fields.size(), 10)));
|
|
data.put("labels", labels.subList(0, Math.min(labels.size(), 8)));
|
|
return data;
|
|
}
|
|
|
|
public Map<String, Object> getMultipleScreenLayoutSummary(List<Integer> screenIds) {
|
|
if (screenIds == null || screenIds.isEmpty()) return new LinkedHashMap<>();
|
|
|
|
Map<String, Object> params = new HashMap<>();
|
|
params.put("screen_ids", screenIds);
|
|
List<Map<String, Object>> rows = sqlSession.selectList(NS + "selectMultipleLayoutComponents", params);
|
|
|
|
// 화면별 summary 초기화
|
|
Map<Integer, Map<String, Object>> summaryMap = new LinkedHashMap<>();
|
|
for (Integer sid : screenIds) {
|
|
Map<String, Object> s = new LinkedHashMap<>();
|
|
s.put("screen_id", sid);
|
|
s.put("screen_type", "form");
|
|
s.put("widget_counts", new LinkedHashMap<String, Integer>());
|
|
s.put("total_components", 0);
|
|
s.put("layout_items", new ArrayList<Map<String, Object>>());
|
|
s.put("canvas_width", 0);
|
|
s.put("canvas_height", 0);
|
|
summaryMap.put(sid, s);
|
|
}
|
|
|
|
for (Map<String, Object> row : rows) {
|
|
int sid = toInt(row.get("screen_id"));
|
|
Map<String, Object> summary = summaryMap.get(sid);
|
|
if (summary == null) continue;
|
|
|
|
String componentKind = row.get("component_kind") != null
|
|
? (String) row.get("component_kind")
|
|
: (row.get("widget_type") != null ? (String) row.get("widget_type") : "text");
|
|
String widgetType = row.get("widget_type") != null ? (String) row.get("widget_type") : "text";
|
|
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, Integer> wc = (Map<String, Integer>) summary.get("widget_counts");
|
|
wc.merge(componentKind, 1, Integer::sum);
|
|
summary.put("total_components", toInt(summary.get("total_components")) + 1);
|
|
|
|
Map<String, Object> item = new LinkedHashMap<>();
|
|
item.put("x", row.getOrDefault("position_x", 0));
|
|
item.put("y", row.getOrDefault("position_y", 0));
|
|
item.put("width", row.getOrDefault("width", 100));
|
|
item.put("height", row.getOrDefault("height", 30));
|
|
item.put("component_kind", componentKind);
|
|
item.put("widget_type", widgetType);
|
|
item.put("label", row.get("label"));
|
|
item.put("bind_field", row.get("bind_field"));
|
|
item.put("used_columns", new ArrayList<>());
|
|
item.put("join_columns", new ArrayList<>());
|
|
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> layoutItems = (List<Map<String, Object>>) summary.get("layout_items");
|
|
layoutItems.add(item);
|
|
|
|
int rightEdge = toInt(row.getOrDefault("position_x", 0)) + toInt(row.getOrDefault("width", 100));
|
|
int bottomEdge = toInt(row.getOrDefault("position_y", 0)) + toInt(row.getOrDefault("height", 30));
|
|
if (rightEdge > toInt(summary.get("canvas_width"))) summary.put("canvas_width", rightEdge);
|
|
if (bottomEdge > toInt(summary.get("canvas_height"))) summary.put("canvas_height", bottomEdge);
|
|
}
|
|
|
|
// 화면 타입 추론 — canonical / legacy / hidden v2 모두 grid 로 인식
|
|
summaryMap.values().forEach(summary -> {
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, Integer> wc = (Map<String, Integer>) summary.get("widget_counts");
|
|
if (countTableLikeWidgets(wc) > 0) {
|
|
summary.put("screen_type", "grid");
|
|
} else if (wc.getOrDefault("table-search-widget", 0) > 1) {
|
|
summary.put("screen_type", "dashboard");
|
|
} else if (toInt(summary.get("total_components")) <= 5 && wc.getOrDefault("button-primary", 0) > 0) {
|
|
summary.put("screen_type", "action");
|
|
}
|
|
});
|
|
|
|
Map<String, Object> result = new LinkedHashMap<>();
|
|
summaryMap.forEach((k, v) -> result.put(String.valueOf(k), v));
|
|
return result;
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Sub Tables
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
public Map<String, Object> getScreenSubTables(List<Integer> screenIds) {
|
|
if (screenIds == null || screenIds.isEmpty()) return new LinkedHashMap<>();
|
|
|
|
Map<String, Object> p = new HashMap<>();
|
|
p.put("screen_ids", screenIds);
|
|
|
|
// ── 1. 컴포넌트 config 기반 서브 테이블 수집 ─────────────────
|
|
List<Map<String, Object>> compRows = sqlSession.selectList(NS + "selectSubTableComponentConfigs", p);
|
|
|
|
// column label lookup 수집
|
|
List<Map<String, Object>> columnPairs = new ArrayList<>();
|
|
compRows.forEach(row -> {
|
|
Object fms = row.get("field_mappings");
|
|
if (fms instanceof List) {
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> fieldMappings = (List<Map<String, Object>>) fms;
|
|
String mainTable = (String) row.get("main_table");
|
|
String subTable = (String) row.get("sub_table");
|
|
fieldMappings.forEach(fm -> {
|
|
if (fm.get("source_field") != null && subTable != null) {
|
|
columnPairs.add(pairOf(subTable, (String) fm.get("source_field")));
|
|
}
|
|
if (fm.get("target_field") != null && mainTable != null) {
|
|
columnPairs.add(pairOf(mainTable, (String) fm.get("target_field")));
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// column labels 조회
|
|
Map<String, String> colLabelMap = new HashMap<>();
|
|
if (!columnPairs.isEmpty()) {
|
|
Map<String, Object> lp = new HashMap<>();
|
|
lp.put("pairs", columnPairs);
|
|
sqlSession.<Map<String, Object>>selectList(NS + "selectColumnLabelsByPairs", lp)
|
|
.forEach(r -> colLabelMap.put(r.get("table_name") + "." + r.get("column_name"),
|
|
(String) r.get("column_label")));
|
|
}
|
|
|
|
// screenSubTables 조립
|
|
Map<Integer, Map<String, Object>> screenSubTables = new LinkedHashMap<>();
|
|
compRows.forEach(row -> {
|
|
int sid = toInt(row.get("screen_id"));
|
|
String mainTable = (String) row.get("main_table");
|
|
String subTable = (String) row.get("sub_table");
|
|
if (subTable == null || subTable.equals(mainTable)) return;
|
|
|
|
ensureScreenEntry(screenSubTables, sid, (String) row.get("screen_name"), mainTable);
|
|
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> subTables = (List<Map<String, Object>>)
|
|
screenSubTables.get(sid).get("sub_tables");
|
|
boolean exists = subTables.stream().anyMatch(st -> subTable.equals(st.get("table_name")));
|
|
if (exists) return;
|
|
|
|
String componentType = (String) row.get("component_type");
|
|
String relationType = inferRelationType(componentType);
|
|
List<Map<String, Object>> fieldMappings = buildFieldMappings(row, subTable, mainTable, colLabelMap);
|
|
|
|
Map<String, Object> stEntry = new LinkedHashMap<>();
|
|
stEntry.put("table_name", subTable);
|
|
stEntry.put("component_type", componentType);
|
|
stEntry.put("relation_type", relationType);
|
|
if (fieldMappings != null) stEntry.put("field_mappings", fieldMappings);
|
|
subTables.add(stEntry);
|
|
});
|
|
|
|
// ── 2. reference_table 기반 참조 서브 테이블 ──────────────────
|
|
sqlSession.<Map<String, Object>>selectList(NS + "selectReferenceColumns", p).forEach(row -> {
|
|
int sid = toInt(row.get("screen_id"));
|
|
String mainTable = (String) row.get("main_table");
|
|
String refTable = (String) row.get("reference_table");
|
|
if (refTable == null || refTable.equals(mainTable)) return;
|
|
|
|
ensureScreenEntry(screenSubTables, sid, (String) row.get("screen_name"), mainTable);
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> subTables = (List<Map<String, Object>>)
|
|
screenSubTables.get(sid).get("sub_tables");
|
|
|
|
Map<String, Object> existing = subTables.stream()
|
|
.filter(st -> refTable.equals(st.get("table_name"))).findFirst().orElse(null);
|
|
|
|
Map<String, Object> mapping = new LinkedHashMap<>();
|
|
mapping.put("source_field", row.get("column_name"));
|
|
mapping.put("target_field", row.getOrDefault("reference_column", "id"));
|
|
mapping.put("source_display_name", row.getOrDefault("source_display_name", row.get("column_name")));
|
|
mapping.put("target_display_name", row.getOrDefault("target_display_name", row.getOrDefault("reference_column", "id")));
|
|
|
|
if (existing != null) {
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> fms = (List<Map<String, Object>>) existing.get("field_mappings");
|
|
if (fms != null && fms.stream().noneMatch(fm -> row.get("column_name").equals(fm.get("source_field")))) {
|
|
fms.add(mapping);
|
|
}
|
|
} else {
|
|
Map<String, Object> stEntry = new LinkedHashMap<>();
|
|
stEntry.put("table_name", refTable);
|
|
stEntry.put("component_type", "column_reference");
|
|
stEntry.put("relation_type", "reference");
|
|
List<Map<String, Object>> fms = new ArrayList<>();
|
|
fms.add(mapping);
|
|
stEntry.put("field_mappings", fms);
|
|
subTables.add(stEntry);
|
|
}
|
|
});
|
|
|
|
// ── 3. parentDataMapping ───────────────────────────────────
|
|
sqlSession.<Map<String, Object>>selectList(NS + "selectParentDataMappingConfigs", p).forEach(row -> {
|
|
int sid = toInt(row.get("screen_id"));
|
|
String mainTable = (String) row.get("main_table");
|
|
String compType = (String) row.get("component_type");
|
|
Object pdm = row.get("parent_data_mapping");
|
|
if (!(pdm instanceof List)) return;
|
|
|
|
ensureScreenEntry(screenSubTables, sid, (String) row.get("screen_name"), mainTable);
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> subTables = (List<Map<String, Object>>)
|
|
screenSubTables.get(sid).get("sub_tables");
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> mappings = (List<Map<String, Object>>) pdm;
|
|
|
|
mappings.forEach(mapping -> {
|
|
String sourceTable = (String) mapping.get("source_table");
|
|
if (sourceTable == null || sourceTable.equals(mainTable)) return;
|
|
|
|
Map<String, Object> newMapping = new LinkedHashMap<>();
|
|
newMapping.put("source_table", sourceTable);
|
|
newMapping.put("source_field", mapping.getOrDefault("source_field", ""));
|
|
newMapping.put("target_field", mapping.getOrDefault("target_field", ""));
|
|
newMapping.put("source_display_name", mapping.getOrDefault("source_field", ""));
|
|
newMapping.put("target_display_name", mapping.getOrDefault("target_field", ""));
|
|
|
|
Map<String, Object> existing = subTables.stream()
|
|
.filter(st -> sourceTable.equals(st.get("table_name"))).findFirst().orElse(null);
|
|
if (existing != null) {
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> fms = (List<Map<String, Object>>) existing.computeIfAbsent("field_mappings", k -> new ArrayList<>());
|
|
String sf = (String) newMapping.get("source_field");
|
|
String tf = (String) newMapping.get("target_field");
|
|
boolean exists = fms.stream().anyMatch(fm ->
|
|
sf.equals(fm.get("source_field")) && tf.equals(fm.get("target_field")));
|
|
if (!exists) fms.add(newMapping);
|
|
} else {
|
|
Map<String, Object> stEntry = new LinkedHashMap<>();
|
|
stEntry.put("table_name", sourceTable);
|
|
stEntry.put("component_type", compType);
|
|
stEntry.put("relation_type", "parent_mapping");
|
|
List<Map<String, Object>> fms = new ArrayList<>();
|
|
fms.add(newMapping);
|
|
stEntry.put("field_mappings", fms);
|
|
subTables.add(stEntry);
|
|
}
|
|
});
|
|
});
|
|
|
|
// ── 4. rightPanel.relation ─────────────────────────────────
|
|
List<Map<String, Object>> rpRows = sqlSession.selectList(NS + "selectRightPanelRelations", p);
|
|
// rightPanel columns에서 dot-notation 참조 테이블 수집
|
|
Map<String, Set<String>> rpJoinedTables = new HashMap<>();
|
|
rpRows.forEach(row -> {
|
|
Object cols = row.get("right_panel_columns");
|
|
String rpTable = (String) row.get("right_panel_table");
|
|
if (cols instanceof List && rpTable != null) {
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> columns = (List<Map<String, Object>>) cols;
|
|
int sid = toInt(row.get("screen_id"));
|
|
String key = sid + "_" + rpTable;
|
|
columns.forEach(col -> {
|
|
String colName = (String) col.getOrDefault("name",
|
|
col.getOrDefault("column_name", col.get("field")));
|
|
if (colName != null && colName.contains(".")) {
|
|
rpJoinedTables.computeIfAbsent(key, k -> new HashSet<>()).add(colName.split("\\.")[0]);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
rpRows.forEach(row -> {
|
|
int sid = toInt(row.get("screen_id"));
|
|
String mainTable = (String) row.get("main_table");
|
|
String compType = (String) row.get("component_type");
|
|
Object relation = row.get("right_panel_relation");
|
|
String rpTable = (String) row.get("right_panel_table");
|
|
|
|
String subTable = rpTable;
|
|
if (subTable == null && relation instanceof Map) {
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, Object> rel = (Map<String, Object>) relation;
|
|
subTable = (String) rel.getOrDefault("target_table", rel.get("table_name"));
|
|
}
|
|
if (subTable == null || subTable.equals(mainTable)) return;
|
|
|
|
ensureScreenEntry(screenSubTables, sid, (String) row.get("screen_name"), mainTable);
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> subTables = (List<Map<String, Object>>)
|
|
screenSubTables.get(sid).get("sub_tables");
|
|
|
|
String key = sid + "_" + subTable;
|
|
List<String> joinedTables = rpJoinedTables.containsKey(key)
|
|
? new ArrayList<>(rpJoinedTables.get(key)) : new ArrayList<>();
|
|
|
|
List<Map<String, Object>> fieldMappings = new ArrayList<>();
|
|
if (relation instanceof Map) {
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, Object> rel = (Map<String, Object>) relation;
|
|
if (rel.get("source_field") != null && rel.get("target_field") != null) {
|
|
Map<String, Object> fm = new LinkedHashMap<>();
|
|
fm.put("source_field", rel.get("source_field"));
|
|
fm.put("target_field", rel.get("target_field"));
|
|
fm.put("source_display_name", rel.get("source_field"));
|
|
fm.put("target_display_name", rel.get("target_field"));
|
|
fieldMappings.add(fm);
|
|
}
|
|
if (rel.get("field_mappings") instanceof List) {
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> rfms = (List<Map<String, Object>>) rel.get("field_mappings");
|
|
rfms.forEach(rfm -> {
|
|
Map<String, Object> fm = new LinkedHashMap<>();
|
|
fm.put("source_field", rfm.getOrDefault("source_field", rfm.get("source_field")));
|
|
fm.put("target_field", rfm.getOrDefault("target_field", rfm.get("target_field")));
|
|
fm.put("source_display_name", fm.get("source_field"));
|
|
fm.put("target_display_name", fm.get("target_field"));
|
|
fieldMappings.add(fm);
|
|
});
|
|
}
|
|
}
|
|
|
|
final String subTableFinal = subTable;
|
|
Map<String, Object> existing = subTables.stream()
|
|
.filter(st -> subTableFinal.equals(st.get("table_name"))).findFirst().orElse(null);
|
|
if (existing != null) {
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> fms = (List<Map<String, Object>>)
|
|
existing.computeIfAbsent("field_mappings", k -> new ArrayList<>());
|
|
fieldMappings.forEach(fm -> {
|
|
boolean dup = fms.stream().anyMatch(e ->
|
|
Objects.equals(fm.get("source_field"), e.get("source_field")) &&
|
|
Objects.equals(fm.get("target_field"), e.get("target_field")));
|
|
if (!dup) fms.add(fm);
|
|
});
|
|
} else {
|
|
Map<String, Object> stEntry = new LinkedHashMap<>();
|
|
stEntry.put("table_name", subTable);
|
|
stEntry.put("component_type", compType);
|
|
stEntry.put("relation_type", "right_panel_relation");
|
|
if (!joinedTables.isEmpty()) stEntry.put("joined_tables", joinedTables);
|
|
if (!fieldMappings.isEmpty()) stEntry.put("field_mappings", fieldMappings);
|
|
if (relation instanceof Map) {
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, Object> rel = (Map<String, Object>) relation;
|
|
if (rel.get("type") != null) stEntry.put("original_relation_type", rel.get("type"));
|
|
if (rel.get("foreign_key") != null) stEntry.put("foreign_key", rel.get("foreign_key"));
|
|
if (rel.get("left_column") != null) stEntry.put("left_column", rel.get("left_column"));
|
|
}
|
|
subTables.add(stEntry);
|
|
}
|
|
});
|
|
|
|
// ── 5. FK 컬럼 조회 ───────────────────────────────────────
|
|
Set<String> subTableNamesSet = new HashSet<>();
|
|
Set<String> refTableNamesSet = new HashSet<>();
|
|
screenSubTables.values().forEach(sd -> {
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> sts = (List<Map<String, Object>>) sd.get("sub_tables");
|
|
sts.forEach(st -> {
|
|
Object jt = st.get("joined_tables");
|
|
if (jt instanceof List) {
|
|
@SuppressWarnings("unchecked")
|
|
List<String> joinedList = (List<String>) jt;
|
|
subTableNamesSet.add((String) st.get("table_name"));
|
|
refTableNamesSet.addAll(joinedList);
|
|
}
|
|
});
|
|
});
|
|
if (!subTableNamesSet.isEmpty() && !refTableNamesSet.isEmpty()) {
|
|
Map<String, Object> fkp = new HashMap<>();
|
|
fkp.put("sub_table_names", new ArrayList<>(subTableNamesSet));
|
|
fkp.put("ref_table_names", new ArrayList<>(refTableNamesSet));
|
|
Map<String, List<Map<String, Object>>> joinColRefs = new HashMap<>();
|
|
sqlSession.<Map<String, Object>>selectList(NS + "selectFkColumnsForJoinedTables", fkp).forEach(row -> {
|
|
String tbl = (String) row.get("table_name");
|
|
joinColRefs.computeIfAbsent(tbl, k -> new ArrayList<>());
|
|
String col = (String) row.get("column_name");
|
|
String ref = (String) row.get("reference_table");
|
|
boolean dup = joinColRefs.get(tbl).stream().anyMatch(r ->
|
|
col.equals(r.get("column")) && ref.equals(r.get("ref_table")));
|
|
if (!dup) {
|
|
Map<String, Object> ref2 = new LinkedHashMap<>();
|
|
ref2.put("column", col);
|
|
ref2.put("column_label", row.getOrDefault("column_label", col));
|
|
ref2.put("ref_table", ref);
|
|
ref2.put("ref_table_label", row.getOrDefault("reference_table_label", ref));
|
|
ref2.put("ref_column", row.getOrDefault("reference_column", "id"));
|
|
joinColRefs.get(tbl).add(ref2);
|
|
}
|
|
});
|
|
screenSubTables.values().forEach(sd -> {
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> sts = (List<Map<String, Object>>) sd.get("sub_tables");
|
|
sts.forEach(st -> {
|
|
List<Map<String, Object>> refs = joinColRefs.get(st.get("table_name"));
|
|
if (refs != null) {
|
|
st.put("join_columns", refs.stream().map(r -> r.get("column")).collect(Collectors.toList()));
|
|
st.put("join_column_refs", refs);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// ── 6. v2-repeater ────────────────────────────────────────
|
|
sqlSession.<Map<String, Object>>selectList(NS + "selectV2Repeaters", p).forEach(row -> {
|
|
int sid = toInt(row.get("screen_id"));
|
|
String mainTable = (String) row.get("main_table");
|
|
String subTable = (String) row.get("sub_table");
|
|
String fk = (String) row.get("foreign_key");
|
|
if (subTable == null || subTable.equals(mainTable)) return;
|
|
|
|
ensureScreenEntry(screenSubTables, sid, (String) row.get("screen_name"), mainTable);
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> sts = (List<Map<String, Object>>)
|
|
screenSubTables.get(sid).get("sub_tables");
|
|
if (sts.stream().noneMatch(st -> subTable.equals(st.get("table_name")))) {
|
|
Map<String, Object> stEntry = new LinkedHashMap<>();
|
|
stEntry.put("table_name", subTable);
|
|
stEntry.put("component_type", "v2-repeater");
|
|
stEntry.put("relation_type", "right_panel_relation");
|
|
if (fk != null) {
|
|
Map<String, Object> fm = new LinkedHashMap<>();
|
|
fm.put("source_field", "id");
|
|
fm.put("target_field", fk);
|
|
fm.put("source_display_name", "ID");
|
|
fm.put("target_display_name", fk);
|
|
stEntry.put("field_mappings", Collections.singletonList(fm));
|
|
}
|
|
sts.add(stEntry);
|
|
}
|
|
});
|
|
|
|
// ── 7. v2-bom-tree detailTable ────────────────────────────
|
|
sqlSession.<Map<String, Object>>selectList(NS + "selectV2DetailTables", p).forEach(row -> {
|
|
int sid = toInt(row.get("screen_id"));
|
|
String mainTable = (String) row.get("main_table");
|
|
String subTable = (String) row.get("sub_table");
|
|
String fk = (String) row.get("foreign_key");
|
|
if (subTable == null || subTable.equals(mainTable)) return;
|
|
|
|
ensureScreenEntry(screenSubTables, sid, (String) row.get("screen_name"), mainTable);
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> sts = (List<Map<String, Object>>)
|
|
screenSubTables.get(sid).get("sub_tables");
|
|
if (sts.stream().noneMatch(st -> subTable.equals(st.get("table_name")))) {
|
|
Map<String, Object> stEntry = new LinkedHashMap<>();
|
|
stEntry.put("table_name", subTable);
|
|
stEntry.put("component_type", row.getOrDefault("component_type", "v2-bom-tree"));
|
|
stEntry.put("relation_type", "right_panel_relation");
|
|
if (fk != null) {
|
|
Map<String, Object> fm = new LinkedHashMap<>();
|
|
fm.put("source_field", "id");
|
|
fm.put("target_field", fk);
|
|
fm.put("source_display_name", "ID");
|
|
fm.put("target_display_name", fk);
|
|
stEntry.put("field_mappings", Collections.singletonList(fm));
|
|
}
|
|
sts.add(stEntry);
|
|
}
|
|
});
|
|
|
|
// ── 8. Save Tables ────────────────────────────────────────
|
|
sqlSession.<Map<String, Object>>selectList(NS + "selectSaveTableActions", p).forEach(row -> {
|
|
int sid = toInt(row.get("screen_id"));
|
|
String mainTable = (String) row.get("main_table");
|
|
String actionType = (String) row.get("action_type");
|
|
String compType = (String) row.getOrDefault("component_type", "component");
|
|
String targetTable = row.get("target_table") != null
|
|
? (String) row.get("target_table")
|
|
: (row.get("transfer_target_table") != null
|
|
? (String) row.get("transfer_target_table") : mainTable);
|
|
if (targetTable == null) return;
|
|
|
|
ensureScreenEntry(screenSubTables, sid, (String) row.get("screen_name"), mainTable);
|
|
Map<String, Object> sd = screenSubTables.get(sid);
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> saveTables = (List<Map<String, Object>>)
|
|
sd.computeIfAbsent("save_tables", k -> new ArrayList<>());
|
|
|
|
boolean dup = saveTables.stream().anyMatch(st ->
|
|
targetTable.equals(st.get("table_name")) && actionType.equals(st.get("save_type")));
|
|
if (!dup) {
|
|
Map<String, Object> stEntry = new LinkedHashMap<>();
|
|
stEntry.put("table_name", targetTable);
|
|
stEntry.put("save_type", actionType);
|
|
stEntry.put("component_type", compType);
|
|
stEntry.put("is_main_table", targetTable.equals(mainTable));
|
|
saveTables.add(stEntry);
|
|
}
|
|
});
|
|
|
|
// ── 9. 전역 메인 테이블 목록 ──────────────────────────────
|
|
List<String> globalMainTables = sqlSession.<Map<String, Object>>selectList(NS + "selectGlobalMainTables", p).stream()
|
|
.map(r -> (String) r.get("main_table"))
|
|
.filter(t -> t != null && !t.isEmpty())
|
|
.collect(Collectors.toList());
|
|
|
|
Map<String, Object> result = new LinkedHashMap<>();
|
|
result.put("data", screenSubTables);
|
|
result.put("global_main_tables", globalMainTables);
|
|
return result;
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// POP Groups
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
public List<Map<String, Object>> getPopScreenGroups(Map<String, Object> params) {
|
|
List<Map<String, Object>> groups = sqlSession.selectList(NS + "selectPopScreenGroups", params);
|
|
if (!groups.isEmpty()) {
|
|
List<Object> groupIds = groups.stream().map(g -> g.get("id")).collect(Collectors.toList());
|
|
Map<String, Object> sp = new HashMap<>();
|
|
sp.put("group_ids", groupIds);
|
|
List<Map<String, Object>> allScreens = sqlSession.selectList(NS + "selectPopGroupScreens", sp);
|
|
Map<Object, List<Map<String, Object>>> byGroup = allScreens.stream()
|
|
.collect(Collectors.groupingBy(s -> s.get("group_id")));
|
|
groups.forEach(g -> g.put("screens", byGroup.getOrDefault(g.get("id"), Collections.emptyList())));
|
|
}
|
|
return groups;
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> createPopScreenGroup(Map<String, Object> params) {
|
|
String userCompanyCode = (String) params.get("user_company_code");
|
|
String effectiveCompanyCode = (String) params.getOrDefault("target_company_code", userCompanyCode);
|
|
if (!"*".equals(userCompanyCode) && !effectiveCompanyCode.equals(userCompanyCode)) {
|
|
throw new SecurityException("다른 회사의 그룹을 생성할 권한이 없습니다.");
|
|
}
|
|
params.put("company_code", effectiveCompanyCode);
|
|
|
|
// hierarchy_path 계산
|
|
Object parentGroupId = params.get("parent_group_id");
|
|
String hierarchyPath;
|
|
if (parentGroupId != null) {
|
|
Map<String, Object> pp = new HashMap<>();
|
|
pp.put("parent_group_id", parentGroupId);
|
|
Map<String, Object> parent = sqlSession.selectOne(NS + "selectParentGroupById", pp);
|
|
if (parent != null) {
|
|
hierarchyPath = parent.get("hierarchy_path") + "/" + params.get("group_code");
|
|
} else {
|
|
hierarchyPath = "POP/" + params.get("group_code");
|
|
}
|
|
} else {
|
|
hierarchyPath = "POP/" + params.get("group_code");
|
|
}
|
|
params.put("hierarchy_path", hierarchyPath);
|
|
|
|
// 중복 체크
|
|
int dupCount = sqlSession.selectOne(NS + "countGroupByCode", params);
|
|
if (dupCount > 0) {
|
|
throw new IllegalArgumentException("동일한 그룹코드가 이미 존재합니다.");
|
|
}
|
|
|
|
sqlSession.insert(NS + "insertPopScreenGroup", params);
|
|
Map<String, Object> sp = new HashMap<>();
|
|
sp.put("id", params.get("id"));
|
|
return sqlSession.selectOne(NS + "selectScreenGroupById", sp);
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> updatePopScreenGroup(Map<String, Object> params) {
|
|
Map<String, Object> existing = sqlSession.selectOne(NS + "selectScreenGroupForUpdate", params);
|
|
if (existing == null) throw new NoSuchElementException("그룹을 찾을 수 없습니다.");
|
|
|
|
String hierarchyPath = (String) existing.get("hierarchy_path");
|
|
if (hierarchyPath == null || !hierarchyPath.startsWith("POP")) {
|
|
throw new IllegalArgumentException("POP 그룹만 수정할 수 있습니다.");
|
|
}
|
|
sqlSession.update(NS + "updatePopScreenGroup", params);
|
|
Map<String, Object> sp = new HashMap<>();
|
|
sp.put("id", params.get("id"));
|
|
return sqlSession.selectOne(NS + "selectScreenGroupById", sp);
|
|
}
|
|
|
|
@Transactional
|
|
public void deletePopScreenGroup(Map<String, Object> params) {
|
|
Map<String, Object> existing = sqlSession.selectOne(NS + "selectScreenGroupForUpdate", params);
|
|
if (existing == null) {
|
|
Map<String, Object> any = sqlSession.selectOne(NS + "selectAnyScreenGroupById", params);
|
|
if (any != null) {
|
|
String ownerCode = (String) any.get("company_code");
|
|
throw new SecurityException("이 그룹은 " + ("*".equals(ownerCode) ? "최고관리자" : ownerCode)
|
|
+ " 소속이라 삭제할 수 없습니다.");
|
|
}
|
|
throw new NoSuchElementException("그룹을 찾을 수 없습니다.");
|
|
}
|
|
String hierarchyPath = (String) existing.get("hierarchy_path");
|
|
if (hierarchyPath == null || !hierarchyPath.startsWith("POP")) {
|
|
throw new IllegalArgumentException("POP 그룹만 삭제할 수 있습니다.");
|
|
}
|
|
int childCount = sqlSession.selectOne(NS + "countChildGroupsByParentId", params);
|
|
if (childCount > 0) throw new IllegalArgumentException("하위 그룹이 " + childCount + "개 있어 삭제할 수 없습니다. 하위 그룹을 먼저 삭제해주세요.");
|
|
int screenCount = sqlSession.selectOne(NS + "countGroupScreensByGroupId", params);
|
|
if (screenCount > 0) throw new IllegalArgumentException("그룹에 연결된 화면이 " + screenCount + "개 있어 삭제할 수 없습니다. 화면을 먼저 제거해주세요.");
|
|
|
|
Map<String, Object> dp = new HashMap<>();
|
|
dp.put("id", params.get("id"));
|
|
dp.put("target_company_code", existing.get("company_code"));
|
|
sqlSession.delete(NS + "deleteScreenGroupById", dp);
|
|
}
|
|
|
|
public Map<String, Object> ensurePopRootGroup(Map<String, Object> params) {
|
|
String companyCode = (String) params.get("company_code");
|
|
Map<String, Object> existing = sqlSession.selectOne(NS + "selectPopRootGroup", params);
|
|
if (existing != null) return existing;
|
|
|
|
if (!"*".equals(companyCode)) return null;
|
|
|
|
sqlSession.insert(NS + "insertPopRootGroup", params);
|
|
return sqlSession.selectOne(NS + "selectPopRootGroup", params);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Sync: Screen Groups → Menu
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
@Transactional
|
|
public Map<String, Object> syncScreenGroupsToMenu(String companyCode, String userId) {
|
|
int created = 0, linked = 0, skipped = 0;
|
|
List<String> errors = new ArrayList<>();
|
|
List<Map<String, Object>> details = new ArrayList<>();
|
|
|
|
try {
|
|
Map<String, Object> p = new HashMap<>();
|
|
p.put("company_code", companyCode);
|
|
List<Map<String, Object>> groups = sqlSession.selectList(NS + "selectScreenGroupsForSync", p);
|
|
List<Map<String, Object>> existingMenus = sqlSession.selectList(NS + "selectExistingMenusForSync", p);
|
|
|
|
// path/name → menu 매핑 (screen_group_id 없는 것만)
|
|
Map<String, Map<String, Object>> menuByPath = new LinkedHashMap<>();
|
|
Map<String, Map<String, Object>> menuByName = new LinkedHashMap<>();
|
|
Set<Long> existingMenuObjids = new HashSet<>();
|
|
existingMenus.forEach(m -> {
|
|
existingMenuObjids.add(toLong(m.get("objid")));
|
|
if (m.get("screen_group_id") == null) {
|
|
String mName = toStr(m.get("menu_name_kor")).trim().toLowerCase();
|
|
String pName = toStr(m.get("parent_name")).trim().toLowerCase();
|
|
String pathKey = !pName.isEmpty() ? pName + ">" + mName : mName;
|
|
menuByPath.put(pathKey, m);
|
|
menuByName.putIfAbsent(mName, m);
|
|
}
|
|
});
|
|
|
|
// 사용자 메뉴 루트 확보
|
|
Map<String, Object> rootMenu = sqlSession.selectOne(NS + "selectUserMenuRoot", p);
|
|
long userMenuRootObjid;
|
|
if (rootMenu != null) {
|
|
userMenuRootObjid = toLong(rootMenu.get("objid"));
|
|
} else {
|
|
long rootObjid = System.currentTimeMillis();
|
|
Map<String, Object> rp = new HashMap<>();
|
|
rp.put("objid", rootObjid);
|
|
rp.put("company_code", companyCode);
|
|
rp.put("user_id", userId);
|
|
sqlSession.insert(NS + "insertUserMenuRoot", rp);
|
|
userMenuRootObjid = rootObjid;
|
|
}
|
|
|
|
// 최상위 회사 폴더 (level=0) 매핑
|
|
Map<Integer, Long> groupToMenuMap = new LinkedHashMap<>();
|
|
Map<Integer, String> groupIdToName = new LinkedHashMap<>();
|
|
Set<Integer> topLevelFolderIds = new HashSet<>();
|
|
groups.forEach(g -> groupIdToName.put(toInt(g.get("id")), toStr(g.get("group_name")).trim().toLowerCase()));
|
|
groups.forEach(g -> {
|
|
if (toInt(g.get("group_level")) == 0 && g.get("parent_group_id") == null) {
|
|
topLevelFolderIds.add(toInt(g.get("id")));
|
|
groupToMenuMap.put(toInt(g.get("id")), userMenuRootObjid);
|
|
}
|
|
});
|
|
|
|
long nextObjid = System.currentTimeMillis();
|
|
|
|
for (Map<String, Object> group : groups) {
|
|
int gid = toInt(group.get("id"));
|
|
String gName = toStr(group.get("group_name")).trim();
|
|
|
|
if (topLevelFolderIds.contains(gid)) {
|
|
skipped++;
|
|
details.add(detail("skipped", gName, gid, null, "최상위 회사 폴더 (메뉴 생성 스킵)"));
|
|
continue;
|
|
}
|
|
|
|
// 이미 연결된 경우
|
|
Object menuObjidObj = group.get("menu_objid");
|
|
if (menuObjidObj != null) {
|
|
if (existingMenuObjids.contains(toLong(menuObjidObj))) {
|
|
skipped++;
|
|
details.add(detail("skipped", gName, gid, toLong(menuObjidObj), "이미 메뉴와 연결됨"));
|
|
groupToMenuMap.put(gid, toLong(menuObjidObj));
|
|
continue;
|
|
} else {
|
|
Map<String, Object> cp = new HashMap<>(); cp.put("id", gid);
|
|
sqlSession.update(NS + "clearScreenGroupMenuObjid", cp);
|
|
}
|
|
}
|
|
|
|
// 경로 기반 매칭
|
|
String parentName = group.get("parent_group_id") != null
|
|
? groupIdToName.getOrDefault(toInt(group.get("parent_group_id")), "") : "";
|
|
String gNameLower = gName.toLowerCase();
|
|
String pathKey = !parentName.isEmpty() ? parentName + ">" + gNameLower : gNameLower;
|
|
|
|
Map<String, Object> matchedMenu = menuByPath.getOrDefault(pathKey, menuByName.get(gNameLower));
|
|
|
|
if (matchedMenu != null) {
|
|
long mObjid = toLong(matchedMenu.get("objid"));
|
|
Map<String, Object> up = new HashMap<>(); up.put("menu_objid", mObjid); up.put("id", gid);
|
|
sqlSession.update(NS + "updateScreenGroupMenuObjid", up);
|
|
Map<String, Object> up2 = new HashMap<>(); up2.put("group_id", gid); up2.put("objid", mObjid);
|
|
sqlSession.update(NS + "updateMenuScreenGroupId", up2);
|
|
// URL 업데이트
|
|
Map<String, Object> dp = new HashMap<>(); dp.put("group_id", gid); dp.put("company_code", companyCode);
|
|
Map<String, Object> defaultScreen = sqlSession.selectOne(NS + "selectDefaultScreenForGroup", dp);
|
|
if (defaultScreen != null) {
|
|
Map<String, Object> urlp = new HashMap<>();
|
|
urlp.put("menu_url", "/screens/" + defaultScreen.get("screen_id"));
|
|
urlp.put("screen_code", defaultScreen.get("screen_code"));
|
|
urlp.put("objid", mObjid);
|
|
sqlSession.update(NS + "updateMenuUrlAndScreenCode", urlp);
|
|
}
|
|
groupToMenuMap.put(gid, mObjid);
|
|
linked++;
|
|
details.add(detail("linked", gName, gid, mObjid, null));
|
|
menuByPath.remove(pathKey);
|
|
menuByName.remove(gNameLower);
|
|
} else {
|
|
// 새 메뉴 생성
|
|
long newObjid = nextObjid++;
|
|
long parentMenuObjid = userMenuRootObjid;
|
|
if (group.get("parent_group_id") != null) {
|
|
int pgid = toInt(group.get("parent_group_id"));
|
|
if (groupToMenuMap.containsKey(pgid)) parentMenuObjid = groupToMenuMap.get(pgid);
|
|
else if (group.get("parent_menu_objid") != null
|
|
&& existingMenuObjids.contains(toLong(group.get("parent_menu_objid")))) {
|
|
parentMenuObjid = toLong(group.get("parent_menu_objid"));
|
|
}
|
|
}
|
|
Map<String, Object> seqp = new HashMap<>();
|
|
seqp.put("parent_objid", parentMenuObjid);
|
|
seqp.put("company_code", companyCode);
|
|
int seq = sqlSession.selectOne(NS + "getNextMenuSeqUnderParent", seqp);
|
|
|
|
Map<String, Object> dp = new HashMap<>(); dp.put("group_id", gid); dp.put("company_code", companyCode);
|
|
Map<String, Object> defScreen = sqlSession.selectOne(NS + "selectDefaultScreenForGroup", dp);
|
|
String menuUrl = defScreen != null ? "/screens/" + defScreen.get("screen_id") : null;
|
|
String screenCode = defScreen != null ? (String) defScreen.get("screen_code") : null;
|
|
|
|
Map<String, Object> ins = new HashMap<>();
|
|
ins.put("objid", newObjid); ins.put("parent_objid", parentMenuObjid);
|
|
ins.put("group_name", gName); ins.put("group_code", group.getOrDefault("group_code", gName));
|
|
ins.put("seq", seq); ins.put("company_code", companyCode); ins.put("user_id", userId);
|
|
ins.put("group_id", gid); ins.put("description", group.get("description"));
|
|
ins.put("menu_url", menuUrl); ins.put("screen_code", screenCode); ins.put("icon", group.get("icon"));
|
|
sqlSession.insert(NS + "insertMenuForGroup", ins);
|
|
|
|
Map<String, Object> up = new HashMap<>(); up.put("menu_objid", newObjid); up.put("id", gid);
|
|
sqlSession.update(NS + "updateScreenGroupMenuObjid", up);
|
|
|
|
groupToMenuMap.put(gid, newObjid);
|
|
created++;
|
|
details.add(detail("created", gName, gid, newObjid, null));
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
log.error("화면관리 → 메뉴 동기화 실패", e);
|
|
errors.add(e.getMessage());
|
|
Map<String, Object> r = new LinkedHashMap<>();
|
|
r.put("success", false); r.put("created", created); r.put("linked", linked);
|
|
r.put("skipped", skipped); r.put("errors", errors); r.put("details", details);
|
|
return r;
|
|
}
|
|
|
|
Map<String, Object> r = new LinkedHashMap<>();
|
|
r.put("success", true); r.put("created", created); r.put("linked", linked);
|
|
r.put("skipped", skipped); r.put("errors", errors); r.put("details", details);
|
|
return r;
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Sync: Menu → Screen Groups
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
@Transactional
|
|
public Map<String, Object> syncMenuToScreenGroups(String companyCode, String userId) {
|
|
int created = 0, linked = 0, skipped = 0;
|
|
List<String> errors = new ArrayList<>();
|
|
List<Map<String, Object>> details = new ArrayList<>();
|
|
|
|
try {
|
|
Map<String, Object> p = new HashMap<>();
|
|
p.put("company_code", companyCode);
|
|
|
|
// 회사명 조회
|
|
Map<String, Object> companyRow = sqlSession.selectOne(NS + "selectCompanyName", p);
|
|
String companyName = companyRow != null ? toStr(companyRow.get("company_name")) : companyCode;
|
|
|
|
List<Map<String, Object>> menus = sqlSession.selectList(NS + "selectMenusForSync", p);
|
|
List<Map<String, Object>> groups = sqlSession.selectList(NS + "selectGroupsForSync", p);
|
|
|
|
// path/name → group 매핑 (menu_objid 없는 것만)
|
|
Map<String, Map<String, Object>> groupByPath = new LinkedHashMap<>();
|
|
Map<String, Map<String, Object>> groupByName = new LinkedHashMap<>();
|
|
Set<Integer> existingGroupIds = new HashSet<>();
|
|
groups.forEach(g -> {
|
|
existingGroupIds.add(toInt(g.get("id")));
|
|
if (g.get("menu_objid") == null) {
|
|
String gn = toStr(g.get("group_name")).trim().toLowerCase();
|
|
String pn = toStr(g.get("parent_name")).trim().toLowerCase();
|
|
String pk = !pn.isEmpty() ? pn + ">" + gn : gn;
|
|
groupByPath.put(pk, g);
|
|
groupByName.putIfAbsent(gn, g);
|
|
}
|
|
});
|
|
|
|
// 회사 폴더 확보
|
|
Map<String, Object> folderRow = sqlSession.selectOne(NS + "selectRootCompanyFolder", p);
|
|
int companyFolderId;
|
|
if (folderRow != null) {
|
|
companyFolderId = toInt(folderRow.get("id"));
|
|
} else {
|
|
int maxOrder = sqlSession.selectOne(NS + "getMaxRootDisplayOrder", null);
|
|
Map<String, Object> fp = new HashMap<>();
|
|
fp.put("company_name", companyName);
|
|
fp.put("group_code", companyCode.toLowerCase());
|
|
fp.put("display_order", maxOrder);
|
|
fp.put("company_code", companyCode);
|
|
fp.put("user_id", userId);
|
|
sqlSession.insert(NS + "insertCompanyFolder", fp);
|
|
companyFolderId = toInt(fp.get("id"));
|
|
Map<String, Object> hp = new HashMap<>();
|
|
hp.put("id", companyFolderId);
|
|
hp.put("hierarchy_path", "/" + companyFolderId + "/");
|
|
sqlSession.update(NS + "updateGroupHierarchyPathById", hp);
|
|
}
|
|
|
|
Map<Long, Integer> menuToGroupMap = new LinkedHashMap<>();
|
|
menuToGroupMap.put(0L, companyFolderId);
|
|
|
|
for (Map<String, Object> menu : menus) {
|
|
long mObjid = toLong(menu.get("objid"));
|
|
String mName = toStr(menu.get("menu_name_kor")).trim();
|
|
|
|
// 이미 연결된 경우
|
|
Object sgId = menu.get("screen_group_id");
|
|
if (sgId != null && existingGroupIds.contains(toInt(sgId))) {
|
|
skipped++;
|
|
details.add(detail("skipped", mName, mObjid, toInt(sgId), "이미 그룹과 연결됨"));
|
|
menuToGroupMap.put(mObjid, toInt(sgId));
|
|
continue;
|
|
}
|
|
|
|
// 경로 기반 매칭
|
|
String mNameLower = mName.toLowerCase();
|
|
String pathKey = mNameLower;
|
|
|
|
Map<String, Object> matchedGroup = groupByPath.getOrDefault(pathKey, groupByName.get(mNameLower));
|
|
|
|
if (matchedGroup != null) {
|
|
int gid = toInt(matchedGroup.get("id"));
|
|
Map<String, Object> up = new HashMap<>(); up.put("menu_objid", mObjid); up.put("id", gid);
|
|
sqlSession.update(NS + "updateScreenGroupForMenuSync", up);
|
|
Map<String, Object> up2 = new HashMap<>(); up2.put("group_id", gid); up2.put("objid", mObjid);
|
|
sqlSession.update(NS + "updateMenuScreenGroupId", up2);
|
|
menuToGroupMap.put(mObjid, gid);
|
|
linked++;
|
|
details.add(detail("linked", mName, mObjid, gid, null));
|
|
groupByPath.remove(pathKey);
|
|
groupByName.remove(mNameLower);
|
|
} else {
|
|
// 새 그룹 생성
|
|
long parentObjid = toLong(menu.get("parent_obj_id"));
|
|
int parentGid = menuToGroupMap.getOrDefault(parentObjid, companyFolderId);
|
|
// 부모 그룹 level + hierarchy_path 조회
|
|
Map<String, Object> pp = new HashMap<>();
|
|
pp.put("parent_group_id", parentGid);
|
|
Map<String, Object> parentGroup = sqlSession.selectOne(NS + "selectParentGroupById", pp);
|
|
int parentLevel = parentGroup != null ? toInt(parentGroup.getOrDefault("group_level", 0)) : 0;
|
|
String parentPath = parentGroup != null ? toStr(parentGroup.get("hierarchy_path")) : "/" + parentGid + "/";
|
|
|
|
Map<String, Object> ins = new HashMap<>();
|
|
ins.put("group_name", mName);
|
|
ins.put("group_code", mNameLower.replaceAll("\\s+", "_"));
|
|
ins.put("parent_group_id", parentGid);
|
|
ins.put("group_level", parentLevel + 1);
|
|
ins.put("display_order", toInt(menu.getOrDefault("seq", 0)));
|
|
ins.put("company_code", companyCode);
|
|
ins.put("user_id", userId);
|
|
ins.put("hierarchy_path", parentPath + "0/");
|
|
ins.put("menu_objid", mObjid);
|
|
ins.put("description", menu.get("menu_desc"));
|
|
sqlSession.insert(NS + "insertScreenGroupForSync", ins);
|
|
|
|
int newGid = toInt(ins.get("id"));
|
|
String hp = (parentPath + newGid + "/").replace("//", "/");
|
|
Map<String, Object> hpu = new HashMap<>();
|
|
hpu.put("id", newGid);
|
|
hpu.put("hierarchy_path", hp);
|
|
sqlSession.update(NS + "updateGroupHierarchyPathById", hpu);
|
|
|
|
Map<String, Object> up2 = new HashMap<>(); up2.put("group_id", newGid); up2.put("objid", mObjid);
|
|
sqlSession.update(NS + "updateMenuScreenGroupId", up2);
|
|
|
|
menuToGroupMap.put(mObjid, newGid);
|
|
existingGroupIds.add(newGid);
|
|
created++;
|
|
details.add(detail("created", mName, mObjid, newGid, null));
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
log.error("메뉴 → 화면관리 동기화 실패", e);
|
|
errors.add(e.getMessage());
|
|
Map<String, Object> r = new LinkedHashMap<>();
|
|
r.put("success", false); r.put("created", created); r.put("linked", linked);
|
|
r.put("skipped", skipped); r.put("errors", errors); r.put("details", details);
|
|
return r;
|
|
}
|
|
|
|
Map<String, Object> r = new LinkedHashMap<>();
|
|
r.put("success", true); r.put("created", created); r.put("linked", linked);
|
|
r.put("skipped", skipped); r.put("errors", errors); r.put("details", details);
|
|
return r;
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Sync: Status
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
public Map<String, Object> getSyncStatus(String companyCode) {
|
|
Map<String, Object> p = new HashMap<>();
|
|
p.put("company_code", companyCode);
|
|
List<Map<String, Object>> groupStats = sqlSession.selectList(NS + "selectSyncStatusGroups", p);
|
|
List<Map<String, Object>> menuStats = sqlSession.selectList(NS + "selectSyncStatusMenus", p);
|
|
Map<String, Object> status = new LinkedHashMap<>();
|
|
status.put("company_code", companyCode);
|
|
status.put("groups", groupStats);
|
|
status.put("menus", menuStats);
|
|
return status;
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Sync: All Companies
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
public Map<String, Object> syncAllCompanies(String userId) {
|
|
List<Map<String, Object>> companies = sqlSession.selectList(NS + "selectAllCompanyCodes", null);
|
|
List<Map<String, Object>> results = new ArrayList<>();
|
|
int successCount = 0, failedCount = 0;
|
|
|
|
for (Map<String, Object> company : companies) {
|
|
String code = (String) company.get("company_code");
|
|
try {
|
|
Map<String, Object> r = syncScreenGroupsToMenu(code, userId);
|
|
r.put("company_code", code);
|
|
results.add(r);
|
|
if (Boolean.TRUE.equals(r.get("success"))) successCount++;
|
|
else failedCount++;
|
|
} catch (Exception e) {
|
|
failedCount++;
|
|
Map<String, Object> r = new LinkedHashMap<>();
|
|
r.put("company_code", code); r.put("success", false);
|
|
r.put("error", e.getMessage());
|
|
results.add(r);
|
|
}
|
|
}
|
|
|
|
Map<String, Object> res = new LinkedHashMap<>();
|
|
res.put("success", failedCount == 0);
|
|
res.put("total_companies", companies.size());
|
|
res.put("success_count", successCount);
|
|
res.put("failed_count", failedCount);
|
|
res.put("results", results);
|
|
return res;
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════
|
|
// Helpers
|
|
// ══════════════════════════════════════════════════════════════
|
|
|
|
private void ensureScreenEntry(Map<Integer, Map<String, Object>> map, int sid,
|
|
String screenName, String mainTable) {
|
|
if (!map.containsKey(sid)) {
|
|
Map<String, Object> entry = new LinkedHashMap<>();
|
|
entry.put("screen_id", sid);
|
|
entry.put("screen_name", screenName);
|
|
entry.put("main_table", mainTable != null ? mainTable : "");
|
|
entry.put("sub_tables", new ArrayList<Map<String, Object>>());
|
|
map.put(sid, entry);
|
|
}
|
|
}
|
|
|
|
private String inferRelationType(String componentType) {
|
|
if (componentType == null) return "lookup";
|
|
if (componentType.contains("autocomplete") || componentType.contains("entity-search")) return "lookup";
|
|
if (componentType.contains("modal-repeater") || componentType.contains("selected-items")) return "source";
|
|
if (componentType.contains("table")) return "join";
|
|
return "lookup";
|
|
}
|
|
|
|
private List<Map<String, Object>> buildFieldMappings(Map<String, Object> row, String subTable,
|
|
String mainTable, Map<String, String> colLabelMap) {
|
|
Object fmsObj = row.get("field_mappings");
|
|
Object colsObj = row.get("columns_config");
|
|
List<Map<String, Object>> result = new ArrayList<>();
|
|
|
|
if (fmsObj instanceof List) {
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> fms = (List<Map<String, Object>>) fmsObj;
|
|
fms.forEach(fm -> {
|
|
String sf = toStr(fm.getOrDefault("source_field", fm.get("source_field")));
|
|
String tf = toStr(fm.getOrDefault("target_field", fm.get("target_field")));
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
m.put("source_field", sf);
|
|
m.put("target_field", tf);
|
|
m.put("source_display_name", colLabelMap.getOrDefault(subTable + "." + sf, sf));
|
|
m.put("target_display_name", colLabelMap.getOrDefault(mainTable + "." + tf, tf));
|
|
result.add(m);
|
|
});
|
|
} else if (colsObj instanceof List) {
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> cols = (List<Map<String, Object>>) colsObj;
|
|
cols.forEach(col -> {
|
|
Object mapping = col.get("mapping");
|
|
if (mapping instanceof Map) {
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, Object> mp = (Map<String, Object>) mapping;
|
|
if ("source".equals(mp.get("type")) && mp.get("source_field") != null) {
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
m.put("source_field", col.getOrDefault("field", ""));
|
|
m.put("target_field", mp.get("source_field"));
|
|
m.put("source_display_name", col.getOrDefault("label", col.getOrDefault("field", "")));
|
|
m.put("target_display_name", mp.get("source_field"));
|
|
result.add(m);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
return result.isEmpty() ? null : result;
|
|
}
|
|
|
|
private Map<String, Object> pairOf(String tableName, String columnName) {
|
|
Map<String, Object> m = new HashMap<>();
|
|
m.put("table_name", tableName);
|
|
m.put("column_name", columnName);
|
|
return m;
|
|
}
|
|
|
|
private Map<String, Object> detail(String action, String name, Object sourceId,
|
|
Object targetId, String reason) {
|
|
Map<String, Object> d = new LinkedHashMap<>();
|
|
d.put("action", action);
|
|
d.put("source_name", name);
|
|
d.put("source_id", sourceId);
|
|
if (targetId != null) d.put("target_id", targetId);
|
|
if (reason != null) d.put("reason", reason);
|
|
return d;
|
|
}
|
|
|
|
private void convertToJsonString(Map<String, Object> params, String key) {
|
|
Object val = params.get(key);
|
|
if (val != null && !(val instanceof String)) {
|
|
params.put(key, val.toString());
|
|
}
|
|
}
|
|
|
|
private int toInt(Object val) {
|
|
if (val == null) return 0;
|
|
if (val instanceof Number) return ((Number) val).intValue();
|
|
try { return Integer.parseInt(val.toString()); } catch (NumberFormatException e) { return 0; }
|
|
}
|
|
|
|
private long toLong(Object val) {
|
|
if (val == null) return 0L;
|
|
if (val instanceof Number) return ((Number) val).longValue();
|
|
try { return Long.parseLong(val.toString()); } catch (NumberFormatException e) { return 0L; }
|
|
}
|
|
|
|
private String toStr(Object val) {
|
|
return val != null ? val.toString() : "";
|
|
}
|
|
}
|