Files
invyone/backend-spring/src/main/java/com/erp/service/CascadingMutualExclusionService.java
T

176 lines
7.7 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 CascadingMutualExclusionService extends BaseService {
private static final String NS = "cascadingMutualExclusion.";
private final CommonService commonService;
private final JdbcTemplate jdbcTemplate;
public Map<String, Object> getCascadingMutualExclusionList(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
commonService.applyPagination(params);
int totalCount = sqlSession.selectOne(NS + "getCascadingMutualExclusionListCnt", params);
List<Map<String, Object>> list = sqlSession.selectList(NS + "getCascadingMutualExclusionList", params);
return commonService.buildListResponse(list, totalCount, params);
}
public Map<String, Object> getCascadingMutualExclusionInfo(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
return sqlSession.selectOne(NS + "getCascadingMutualExclusionInfo", params);
}
@Transactional
public Map<String, Object> insertCascadingMutualExclusion(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
if (params.get("exclusion_type") == null) params.put("exclusion_type", "SAME_VALUE");
if (params.get("error_message") == null) params.put("error_message", "동일한 값을 선택할 수 없습니다");
// 배제 코드 자동 생성: EX_XXXX_NNN
String companyCode = (String) params.get("company_code");
Map<String, Object> countParams = new LinkedHashMap<>();
countParams.put("company_code", companyCode);
int count = sqlSession.selectOne(NS + "getCascadingMutualExclusionCount", countParams);
String ts = Long.toString(System.currentTimeMillis(), 36).toUpperCase();
ts = ts.substring(Math.max(0, ts.length() - 4));
params.put("exclusion_code", String.format("EX_%s_%03d", ts, count + 1));
sqlSession.insert(NS + "insertCascadingMutualExclusion", params);
return params;
}
@Transactional
public Map<String, Object> updateCascadingMutualExclusion(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
sqlSession.update(NS + "updateCascadingMutualExclusion", params);
return params;
}
@Transactional
public Map<String, Object> deleteCascadingMutualExclusion(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
sqlSession.delete(NS + "deleteCascadingMutualExclusion", params);
return params;
}
/**
* 상호 배제 검증: 선택한 값들 간 충돌 여부 확인 (SAME_VALUE 타입)
*/
public Map<String, Object> validateCascadingMutualExclusion(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
Map<String, Object> exclusion = sqlSession.selectOne(NS + "getCascadingMutualExclusionByCode", params);
if (exclusion == null) throw new NoSuchElementException("상호 배제 규칙을 찾을 수 없습니다.");
@SuppressWarnings("unchecked")
Map<String, Object> fieldValues = (Map<String, Object>) params.getOrDefault("field_values", Collections.emptyMap());
String fieldNamesStr = (String) exclusion.get("field_names");
String[] fields = fieldNamesStr != null ? fieldNamesStr.split(",") : new String[0];
List<String> values = new ArrayList<>();
for (String field : fields) {
Object v = fieldValues.get(field.trim());
if (v != null) values.add(v.toString());
}
boolean isValid = true;
String errorMessage = null;
List<String> conflictingFields = new ArrayList<>();
String exclusionType = (String) exclusion.getOrDefault("exclusion_type", "SAME_VALUE");
if ("SAME_VALUE".equals(exclusionType)) {
Set<String> seen = new LinkedHashSet<>();
boolean hasDuplicate = false;
for (String v : values) {
if (!seen.add(v)) { hasDuplicate = true; break; }
}
if (hasDuplicate) {
isValid = false;
errorMessage = (String) exclusion.get("error_message");
Map<String, List<String>> valueCounts = new LinkedHashMap<>();
for (String field : fields) {
Object v = fieldValues.get(field.trim());
if (v != null) {
valueCounts.computeIfAbsent(v.toString(), k -> new ArrayList<>()).add(field.trim());
}
}
for (List<String> fl : valueCounts.values()) {
if (fl.size() > 1) { conflictingFields = fl; break; }
}
}
}
Map<String, Object> result = new LinkedHashMap<>();
result.put("is_valid", isValid);
result.put("error_message", isValid ? null : errorMessage);
result.put("conflicting_fields", conflictingFields);
return result;
}
/**
* 배제 옵션 조회: source_table에서 이미 선택된 값을 제외한 목록 반환
*/
public List<Map<String, Object>> getExcludedOptions(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
String companyCode = (String) params.get("company_code");
Map<String, Object> exclusion = sqlSession.selectOne(NS + "getCascadingMutualExclusionByCode", params);
if (exclusion == null) throw new NoSuchElementException("상호 배제 규칙을 찾을 수 없습니다.");
String sourceTable = (String) exclusion.get("source_table");
String valueColumn = (String) exclusion.get("value_column");
String labelColumn = (String) exclusion.get("label_column");
if (labelColumn == null || labelColumn.isEmpty()) labelColumn = valueColumn;
boolean hasCompanyCode = hasColumn(sourceTable, "company_code");
List<Object> queryParams = new ArrayList<>();
StringBuilder sql = new StringBuilder();
sql.append("SELECT ")
.append(valueColumn).append(" AS value, ")
.append(labelColumn).append(" AS label")
.append(" FROM ").append(sourceTable)
.append(" WHERE 1=1");
if (hasCompanyCode && !"*".equals(companyCode)) {
sql.append(" AND company_code = ?");
queryParams.add(companyCode);
}
Object selectedValuesParam = params.get("selected_values");
if (selectedValuesParam != null) {
List<String> excludeValues = new ArrayList<>();
for (String v : selectedValuesParam.toString().split(",")) {
String trimmed = v.trim();
if (!trimmed.isEmpty()) excludeValues.add(trimmed);
}
if (!excludeValues.isEmpty()) {
String placeholders = String.join(", ", Collections.nCopies(excludeValues.size(), "?"));
sql.append(" AND ").append(valueColumn).append(" NOT IN (").append(placeholders).append(")");
queryParams.addAll(excludeValues);
}
}
sql.append(" ORDER BY ").append(labelColumn);
return jdbcTemplate.queryForList(sql.toString(), queryParams.toArray());
}
private boolean hasColumn(String tableName, String columnName) {
String sql = "SELECT COUNT(*) FROM information_schema.columns WHERE table_name = ? AND column_name = ?";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class, tableName, columnName);
return count != null && count > 0;
}
}