252 lines
12 KiB
Java
252 lines
12 KiB
Java
package com.erp.service;
|
|
|
|
import com.erp.common.BaseService;
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.*;
|
|
|
|
@Service
|
|
@RequiredArgsConstructor
|
|
@Slf4j
|
|
public class CascadingHierarchyService extends BaseService {
|
|
|
|
private static final String NS = "cascadingHierarchy.";
|
|
|
|
private final CommonService commonService;
|
|
private final JdbcTemplate jdbcTemplate;
|
|
|
|
public Map<String, Object> getCascadingHierarchyGroupList(Map<String, Object> params) {
|
|
commonService.applyCompanyCodeFilter(params);
|
|
commonService.applyPagination(params);
|
|
int totalCount = sqlSession.selectOne(NS + "getCascadingHierarchyGroupListCnt", params);
|
|
List<Map<String, Object>> list = sqlSession.selectList(NS + "getCascadingHierarchyGroupList", params);
|
|
return commonService.buildListResponse(list, totalCount, params);
|
|
}
|
|
|
|
public Map<String, Object> getCascadingHierarchyGroupDetail(Map<String, Object> params) {
|
|
commonService.applyCompanyCodeFilter(params);
|
|
Map<String, Object> group = sqlSession.selectOne(NS + "getCascadingHierarchyGroupByCode", params);
|
|
if (group == null) return null;
|
|
|
|
Map<String, Object> levelParams = new HashMap<>();
|
|
levelParams.put("group_code", params.get("group_code"));
|
|
levelParams.put("company_code", group.get("company_code"));
|
|
List<Map<String, Object>> levels = sqlSession.selectList(NS + "getCascadingHierarchyLevelList", levelParams);
|
|
|
|
Map<String, Object> result = new HashMap<>(group);
|
|
result.put("levels", levels);
|
|
return result;
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> insertCascadingHierarchyGroup(Map<String, Object> params) {
|
|
commonService.applyCompanyCodeFilter(params);
|
|
String companyCode = (String) params.get("company_code");
|
|
String userId = (String) params.getOrDefault("user_id", "system");
|
|
|
|
// Generate group code: HG_{timestamp_base36}_{count:03d}
|
|
Map<String, Object> countParams = new HashMap<>();
|
|
countParams.put("company_code", companyCode);
|
|
Number cntNum = sqlSession.selectOne(NS + "getCascadingHierarchyGroupCount", countParams);
|
|
int count = (cntNum != null ? cntNum.intValue() : 0) + 1;
|
|
String timestamp = Long.toString(System.currentTimeMillis(), 36).toUpperCase();
|
|
String suffix = timestamp.substring(Math.max(0, timestamp.length() - 4));
|
|
String groupCode = "HG_" + suffix + "_" + String.format("%03d", count);
|
|
|
|
params.put("group_code", groupCode);
|
|
params.put("created_by", userId);
|
|
|
|
if (params.get("hierarchy_type") == null) params.put("hierarchy_type", "MULTI_TABLE");
|
|
if (params.get("is_fixed_levels") == null) params.put("is_fixed_levels", "Y");
|
|
if (params.get("empty_message") == null) params.put("empty_message", "선택해주세요");
|
|
if (params.get("no_options_message") == null) params.put("no_options_message", "옵션이 없습니다");
|
|
if (params.get("loading_message") == null) params.put("loading_message", "로딩 중...");
|
|
|
|
sqlSession.insert(NS + "insertCascadingHierarchyGroup", params);
|
|
|
|
// Insert levels for MULTI_TABLE type
|
|
Object levelsObj = params.get("levels");
|
|
if ("MULTI_TABLE".equals(params.get("hierarchy_type")) && levelsObj instanceof List) {
|
|
List<?> levels = (List<?>) levelsObj;
|
|
for (Object l : levels) {
|
|
if (l instanceof Map) {
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, Object> level = (Map<String, Object>) l;
|
|
Map<String, Object> lp = new HashMap<>(level);
|
|
lp.put("group_code", groupCode);
|
|
lp.put("company_code", companyCode);
|
|
if (lp.get("order_direction") == null) lp.put("order_direction", "ASC");
|
|
if (lp.get("is_required") == null) lp.put("is_required", "Y");
|
|
if (lp.get("is_searchable") == null) lp.put("is_searchable", "N");
|
|
if (lp.get("placeholder") == null && lp.get("level_name") != null) {
|
|
lp.put("placeholder", lp.get("level_name") + " 선택");
|
|
}
|
|
sqlSession.insert(NS + "insertCascadingHierarchyLevel", lp);
|
|
}
|
|
}
|
|
}
|
|
return params;
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> updateCascadingHierarchyGroup(Map<String, Object> params) {
|
|
commonService.applyCompanyCodeFilter(params);
|
|
params.put("updated_by", params.getOrDefault("user_id", "system"));
|
|
|
|
Map<String, Object> existing = sqlSession.selectOne(NS + "getCascadingHierarchyGroupByCode", params);
|
|
if (existing == null) return null;
|
|
|
|
params.put("company_code", existing.get("company_code"));
|
|
sqlSession.update(NS + "updateCascadingHierarchyGroup", params);
|
|
return params;
|
|
}
|
|
|
|
@Transactional
|
|
public boolean deleteCascadingHierarchyGroup(Map<String, Object> params) {
|
|
commonService.applyCompanyCodeFilter(params);
|
|
Map<String, Object> existing = sqlSession.selectOne(NS + "getCascadingHierarchyGroupByCode", params);
|
|
if (existing == null) return false;
|
|
|
|
String groupCode = (String) params.get("group_code");
|
|
String companyCode = (String) existing.get("company_code");
|
|
|
|
Map<String, Object> delParams = new HashMap<>();
|
|
delParams.put("group_code", groupCode);
|
|
delParams.put("company_code", companyCode);
|
|
sqlSession.delete(NS + "deleteCascadingHierarchyLevels", delParams);
|
|
sqlSession.delete(NS + "deleteCascadingHierarchyGroup", delParams);
|
|
return true;
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> addCascadingHierarchyLevel(Map<String, Object> params) {
|
|
commonService.applyCompanyCodeFilter(params);
|
|
String groupCode = (String) params.get("group_code");
|
|
|
|
Map<String, Object> groupParams = new HashMap<>();
|
|
groupParams.put("group_code", groupCode);
|
|
groupParams.put("company_code", params.get("company_code"));
|
|
Map<String, Object> group = sqlSession.selectOne(NS + "getCascadingHierarchyGroupByCode", groupParams);
|
|
if (group == null) return null;
|
|
|
|
params.put("company_code", group.get("company_code"));
|
|
if (params.get("order_direction") == null) params.put("order_direction", "ASC");
|
|
if (params.get("is_required") == null) params.put("is_required", "Y");
|
|
if (params.get("is_searchable") == null) params.put("is_searchable", "N");
|
|
if (params.get("placeholder") == null && params.get("level_name") != null) {
|
|
params.put("placeholder", params.get("level_name") + " 선택");
|
|
}
|
|
|
|
sqlSession.insert(NS + "insertCascadingHierarchyLevel", params);
|
|
return params;
|
|
}
|
|
|
|
@Transactional
|
|
public Map<String, Object> updateCascadingHierarchyLevel(Map<String, Object> params) {
|
|
commonService.applyCompanyCodeFilter(params);
|
|
Map<String, Object> existing = sqlSession.selectOne(NS + "getCascadingHierarchyLevelInfo", params);
|
|
if (existing == null) return null;
|
|
|
|
sqlSession.update(NS + "updateCascadingHierarchyLevel", params);
|
|
return params;
|
|
}
|
|
|
|
@Transactional
|
|
public boolean deleteCascadingHierarchyLevel(Map<String, Object> params) {
|
|
commonService.applyCompanyCodeFilter(params);
|
|
Map<String, Object> existing = sqlSession.selectOne(NS + "getCascadingHierarchyLevelInfo", params);
|
|
if (existing == null) return false;
|
|
|
|
sqlSession.delete(NS + "deleteCascadingHierarchyLevel", params);
|
|
return true;
|
|
}
|
|
|
|
public Map<String, Object> getLevelOptions(Map<String, Object> params) {
|
|
commonService.applyCompanyCodeFilter(params);
|
|
String companyCode = (String) params.get("company_code");
|
|
|
|
Map<String, Object> level = sqlSession.selectOne(NS + "getCascadingHierarchyLevelForOptions", params);
|
|
if (level == null) return null;
|
|
|
|
String tableName = sanitizeIdentifier((String) level.get("table_name"));
|
|
String valueColumn = sanitizeIdentifier((String) level.get("value_column"));
|
|
String labelColumn = sanitizeIdentifier((String) level.get("label_column"));
|
|
|
|
StringBuilder sql = new StringBuilder();
|
|
sql.append("SELECT ").append(valueColumn).append(" AS value, ")
|
|
.append(labelColumn).append(" AS label")
|
|
.append(" FROM ").append(tableName)
|
|
.append(" WHERE 1=1");
|
|
|
|
List<Object> sqlParams = new ArrayList<>();
|
|
|
|
// Parent value filter (level 2+)
|
|
Object parentValue = params.get("parent_value");
|
|
Object parentKeyColumn = level.get("parent_key_column");
|
|
if (parentKeyColumn != null && !parentKeyColumn.toString().isEmpty() && parentValue != null) {
|
|
sql.append(" AND ").append(sanitizeIdentifier(parentKeyColumn.toString())).append(" = ?");
|
|
sqlParams.add(parentValue);
|
|
}
|
|
|
|
// Fixed filter
|
|
Object filterColumn = level.get("filter_column");
|
|
Object filterValue = level.get("filter_value");
|
|
if (filterColumn != null && !filterColumn.toString().isEmpty()
|
|
&& filterValue != null && !filterValue.toString().isEmpty()) {
|
|
sql.append(" AND ").append(sanitizeIdentifier(filterColumn.toString())).append(" = ?");
|
|
sqlParams.add(filterValue.toString());
|
|
}
|
|
|
|
// Multi-tenancy
|
|
if (!"*".equals(companyCode) && hasColumn(tableName, "company_code")) {
|
|
sql.append(" AND company_code = ?");
|
|
sqlParams.add(companyCode);
|
|
}
|
|
|
|
// Order
|
|
Object orderColumn = level.get("order_column");
|
|
if (orderColumn != null && !orderColumn.toString().isEmpty()) {
|
|
Object orderDir = level.get("order_direction");
|
|
String dir = (orderDir != null && "DESC".equalsIgnoreCase(orderDir.toString())) ? "DESC" : "ASC";
|
|
sql.append(" ORDER BY ").append(sanitizeIdentifier(orderColumn.toString())).append(" ").append(dir);
|
|
} else {
|
|
sql.append(" ORDER BY ").append(labelColumn);
|
|
}
|
|
|
|
List<Map<String, Object>> options = jdbcTemplate.queryForList(sql.toString(), sqlParams.toArray());
|
|
|
|
Map<String, Object> levelInfo = new LinkedHashMap<>();
|
|
levelInfo.put("level_id", level.get("level_id"));
|
|
levelInfo.put("level_name", level.get("level_name"));
|
|
levelInfo.put("placeholder", level.get("placeholder"));
|
|
levelInfo.put("is_required", level.get("is_required"));
|
|
levelInfo.put("is_searchable", level.get("is_searchable"));
|
|
|
|
Map<String, Object> result = new HashMap<>();
|
|
result.put("data", options);
|
|
result.put("level_info", levelInfo);
|
|
return result;
|
|
}
|
|
|
|
private String sanitizeIdentifier(String identifier) {
|
|
if (identifier == null || !identifier.matches("[a-zA-Z0-9_.]+")) {
|
|
throw new IllegalArgumentException("Invalid SQL identifier: " + identifier);
|
|
}
|
|
return identifier;
|
|
}
|
|
|
|
private boolean hasColumn(String tableName, String columnName) {
|
|
try {
|
|
Integer count = jdbcTemplate.queryForObject(
|
|
"SELECT COUNT(*) FROM information_schema.columns WHERE table_name = ? AND column_name = ?",
|
|
Integer.class, tableName, columnName);
|
|
return count != null && count > 0;
|
|
} catch (Exception e) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|