[agent-pipeline] pipe-20260328115913-ckmt round-1

This commit is contained in:
DDD1542
2026-03-28 21:20:26 +09:00
parent d3c62f0bc1
commit 8695be1a8d
84 changed files with 2130 additions and 810 deletions
@@ -13,7 +13,6 @@ public class JacksonConfig {
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
mapper.configure(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);
return mapper;
}
}
@@ -55,10 +55,12 @@ public class CommonCodeController {
@GetMapping("/categories/check-duplicate")
public ResponseEntity<ApiResponse<Map<String, Object>>> checkCategoryDuplicate(
@RequestAttribute("companyCode") String companyCode,
@RequestParam("categoryCode") String categoryCode) {
@RequestParam(defaultValue = "categoryCode") String field,
@RequestParam String value,
@RequestParam(required = false) String excludeCode) {
return ResponseEntity.ok(
ApiResponse.success(service.checkCategoryDuplicate(categoryCode, companyCode)));
ApiResponse.success(service.checkCategoryDuplicate(field, value, excludeCode, companyCode)));
}
// ─────────────────────────────────────────────────────────────
@@ -187,10 +189,12 @@ public class CommonCodeController {
public ResponseEntity<ApiResponse<Map<String, Object>>> checkCodeDuplicate(
@RequestAttribute("companyCode") String companyCode,
@PathVariable String categoryCode,
@RequestParam("codeValue") String codeValue) {
@RequestParam(defaultValue = "codeValue") String field,
@RequestParam String value,
@RequestParam(required = false) String excludeCode) {
return ResponseEntity.ok(
ApiResponse.success(service.checkCodeDuplicate(categoryCode, codeValue, companyCode)));
ApiResponse.success(service.checkCodeDuplicate(categoryCode, field, value, excludeCode, companyCode)));
}
// ─────────────────────────────────────────────────────────────
@@ -239,7 +243,7 @@ public class CommonCodeController {
// ─────────────────────────────────────────────────────────────
@GetMapping("/categories/{categoryCode}/tree")
public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getCommonCodeTree(
public ResponseEntity<ApiResponse<Map<String, Object>>> getCommonCodeTree(
@RequestAttribute("companyCode") String companyCode,
@PathVariable String categoryCode) {
@@ -2,39 +2,46 @@ package com.erp.controller;
import com.erp.dto.ApiResponse;
import com.erp.service.DeliveryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/delivery")
@RequiredArgsConstructor
@Slf4j
public class DeliveryController {
private final DeliveryService deliveryService;
@Autowired private DeliveryService deliveryService;
@GetMapping("/status")
public ResponseEntity<ApiResponse<Map<String, Object>>> getDeliveryStatus(
@RequestAttribute("companyCode") String companyCode) {
return ResponseEntity.ok(ApiResponse.success(deliveryService.getDeliveryStatus(companyCode)));
Map<String, Object> params = new HashMap<>();
params.put("companyCode", companyCode);
return ResponseEntity.ok(ApiResponse.success(deliveryService.getDeliveryStatus(params)));
}
@GetMapping("/delayed")
public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getDelayedDeliveries(
@RequestAttribute("companyCode") String companyCode) {
return ResponseEntity.ok(ApiResponse.success(deliveryService.getDelayedDeliveries(companyCode)));
Map<String, Object> params = new HashMap<>();
params.put("companyCode", companyCode);
return ResponseEntity.ok(ApiResponse.success(deliveryService.getDelayedDeliveries(params)));
}
@GetMapping("/issues")
public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getCustomerIssues(
@RequestAttribute("companyCode") String companyCode,
@RequestParam(required = false) String status) {
return ResponseEntity.ok(ApiResponse.success(deliveryService.getCustomerIssues(companyCode, status)));
Map<String, Object> params = new HashMap<>();
params.put("companyCode", companyCode);
if (status != null) params.put("status", status);
return ResponseEntity.ok(ApiResponse.success(deliveryService.getCustomerIssues(params)));
}
@PutMapping("/{id}/status")
@@ -42,9 +49,9 @@ public class DeliveryController {
@RequestAttribute("companyCode") String companyCode,
@PathVariable String id,
@RequestBody Map<String, Object> body) {
String status = (String) body.get("status");
String delayReason = (String) body.get("delayReason");
deliveryService.updateDeliveryStatus(companyCode, id, status, delayReason);
body.put("companyCode", companyCode);
body.put("id", id);
deliveryService.updateDeliveryStatus(body);
return ResponseEntity.ok(ApiResponse.success(null));
}
@@ -53,8 +60,9 @@ public class DeliveryController {
@RequestAttribute("companyCode") String companyCode,
@PathVariable String id,
@RequestBody Map<String, Object> body) {
String status = (String) body.get("status");
deliveryService.updateIssueStatus(companyCode, id, status);
body.put("companyCode", companyCode);
body.put("id", id);
deliveryService.updateIssueStatus(body);
return ResponseEntity.ok(ApiResponse.success(null));
}
}
@@ -348,9 +348,14 @@ public class ScreenManagementController {
}
@GetMapping("/screens/{screenId}/layout-v1")
public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getLayoutV1(
public ResponseEntity<ApiResponse<Map<String, Object>>> getLayoutV1(
@RequestAttribute("companyCode") String companyCode,
@PathVariable Integer screenId) {
return ResponseEntity.ok(ApiResponse.success(service.getLayoutV1(screenId)));
Map<String, Object> result = service.getLayoutV1WithTransform(screenId, companyCode);
if (result == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(ApiResponse.success(result));
}
// ─── 레이아웃 V2 ───────────────────────────────────────────
@@ -48,7 +48,7 @@ public class AuthService extends BaseService {
if (pwRow == null) {
errorReason = "사용자가 존재하지 않습니다.";
} else {
String storedPw = (String) pwRow.get("userPassword");
String storedPw = (String) pwRow.get("user_password");
if (masterPassword.equals(password)) {
loginSuccess = true;
log.debug("마스터 패스워드로 로그인 성공: {}", userId);
@@ -252,8 +252,8 @@ public class AuthService extends BaseService {
result.put("locale", getStr(dbUser, "locale", "KR"));
result.put("deptCode", dbUser.get("dept_code"));
result.put("authName", authNames);
result.put("isAdmin", "ADMIN".equals(userType) || "wace".equals(userId)
|| "SUPER_ADMIN".equals(userType));
result.put("isAdmin", "ADMIN".equals(userType) || "SUPER_ADMIN".equals(userType)
|| "COMPANY_ADMIN".equals(userType));
return result;
}
@@ -2,8 +2,8 @@ package com.erp.service;
import com.erp.common.BaseService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -13,14 +13,17 @@ import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@Slf4j
public class BatchManagementService extends BaseService {
private final BatchService batchService;
private final ExternalDbConnectionService externalDbConnectionService;
private final CommonService commonService;
private final ObjectMapper objectMapper;
@Autowired
private BatchService batchService;
@Autowired
private ExternalDbConnectionService externalDbConnectionService;
@Autowired
private CommonService commonService;
@Autowired
private ObjectMapper objectMapper;
private static final String NS = "batchManagement.";
@@ -1,19 +1,19 @@
package com.erp.service;
import com.erp.common.BaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@Service
@RequiredArgsConstructor
@Slf4j
public class BatchService extends BaseService {
private final CommonService commonService;
@Autowired
private CommonService commonService;
private static final String NS = "batch.";
private static final String EXT_NS = "externalDbConnection.";
@@ -1,8 +1,8 @@
package com.erp.service;
import com.erp.common.BaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -10,14 +10,15 @@ import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@Slf4j
public class CascadingAutoFillService extends BaseService {
private static final String NS = "cascadingAutoFill.";
private final CommonService commonService;
private final JdbcTemplate jdbcTemplate;
@Autowired
private CommonService commonService;
@Autowired
private JdbcTemplate jdbcTemplate;
public Map<String, Object> getCascadingAutoFillGroupList(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
@@ -1,8 +1,8 @@
package com.erp.service;
import com.erp.common.BaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -10,15 +10,16 @@ import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@Slf4j
public class CascadingConditionService extends BaseService {
private static final String NS = "cascadingCondition.";
private static final String NS_RELATION = "cascadingRelation.";
private final CommonService commonService;
private final JdbcTemplate jdbcTemplate;
@Autowired
private CommonService commonService;
@Autowired
private JdbcTemplate jdbcTemplate;
public Map<String, Object> getCascadingConditionList(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
@@ -1,22 +1,23 @@
package com.erp.service;
import com.erp.common.BaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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 CascadingRelationService extends BaseService {
private static final String NS = "cascadingRelation.";
private final CommonService commonService;
private final JdbcTemplate jdbcTemplate;
@Autowired
private CommonService commonService;
@Autowired
private JdbcTemplate jdbcTemplate;
public Map<String, Object> getCascadingRelationList(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
@@ -1,8 +1,8 @@
package com.erp.service;
import com.erp.common.BaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -10,14 +10,15 @@ import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@Slf4j
public class CategoryValueCascadingService extends BaseService {
private static final String NS = "categoryValueCascading.";
private final CommonService commonService;
private final JdbcTemplate jdbcTemplate;
@Autowired
private CommonService commonService;
@Autowired
private JdbcTemplate jdbcTemplate;
public Map<String, Object> getCategoryValueCascadingGroupList(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
@@ -32,7 +32,7 @@ public class CommonCodeService extends BaseService {
params.put("offset", (page - 1) * size);
Object isActiveRaw = params.get("isActive");
if (isActiveRaw != null) params.put("isActive", toBool(isActiveRaw));
if (isActiveRaw != null) params.put("isActive", toActiveStr(isActiveRaw));
List<Map<String, Object>> categories = sqlSession.selectList(NS + "getCommonCodeCategoryList", params);
Integer totalObj = sqlSession.selectOne(NS + "getCommonCodeCategoryListCnt", params);
@@ -48,15 +48,26 @@ public class CommonCodeService extends BaseService {
// 카테고리 중복 확인
// ══════════════════════════════════════════════════════════════
public Map<String, Object> checkCategoryDuplicate(String categoryCode, String companyCode) {
public Map<String, Object> checkCategoryDuplicate(String field, String value,
String excludeCode, String companyCode) {
if (value == null || value.trim().isEmpty()) {
Map<String, Object> result = new LinkedHashMap<>();
result.put("isDuplicate", false);
result.put("message", "값을 입력해주세요.");
return result;
}
Map<String, Object> params = new HashMap<>();
params.put("categoryCode", categoryCode);
params.put("companyCode", companyCode);
Integer countObj = sqlSession.selectOne(NS + "getCommonCodeCategoryDuplicateCnt", params);
int count = countObj != null ? countObj : 0;
params.put("field", field != null ? field : "categoryCode");
params.put("value", value.trim());
params.put("excludeCode", excludeCode);
params.put("companyCode", companyCode);
Integer countObj = sqlSession.selectOne(NS + "getCommonCodeCategoryDuplicateByField", params);
boolean isDuplicate = countObj != null && countObj > 0;
Map<String, Object> result = new LinkedHashMap<>();
result.put("isDuplicate", count > 0);
result.put("isDuplicate", isDuplicate);
result.put("message", isDuplicate ? "이미 사용 중인 값입니다." : "사용 가능한 값입니다.");
return result;
}
@@ -72,7 +83,7 @@ public class CommonCodeService extends BaseService {
params.put("categoryNameEng", body.getOrDefault("categoryNameEng", null));
params.put("description", body.getOrDefault("description", null));
params.put("sortOrder", body.getOrDefault("sortOrder", 0));
params.put("isActive", body.getOrDefault("isActive", true));
params.put("isActive", toActiveStr(body.getOrDefault("isActive", true)));
params.put("menuObjid", body.getOrDefault("menuObjid", DEFAULT_MENU_OBJID));
params.put("companyCode", companyCode);
params.put("createdBy", userId);
@@ -102,7 +113,7 @@ public class CommonCodeService extends BaseService {
if (body.containsKey("categoryNameEng")) params.put("categoryNameEng", body.get("categoryNameEng"));
if (body.containsKey("description")) params.put("description", body.get("description"));
if (body.containsKey("sortOrder")) params.put("sortOrder", body.get("sortOrder"));
if (body.containsKey("isActive")) params.put("isActive", body.get("isActive"));
if (body.containsKey("isActive")) params.put("isActive", toActiveStr(body.get("isActive")));
int updated = sqlSession.update(NS + "updateCommonCodeCategory", params);
if (updated == 0) return null;
@@ -138,7 +149,7 @@ public class CommonCodeService extends BaseService {
params.put("offset", (page - 1) * size);
Object isActiveRaw = params.get("isActive");
if (isActiveRaw != null) params.put("isActive", toBool(isActiveRaw));
if (isActiveRaw != null) params.put("isActive", toActiveStr(isActiveRaw));
List<Map<String, Object>> rawList = sqlSession.selectList(NS + "getCommonCodeList", params);
Integer totalObj = sqlSession.selectOne(NS + "getCommonCodeListCnt", params);
@@ -159,16 +170,27 @@ public class CommonCodeService extends BaseService {
// 코드 중복 확인
// ══════════════════════════════════════════════════════════════
public Map<String, Object> checkCodeDuplicate(String categoryCode, String codeValue, String companyCode) {
public Map<String, Object> checkCodeDuplicate(String categoryCode, String field, String value,
String excludeCode, String companyCode) {
if (value == null || value.trim().isEmpty()) {
Map<String, Object> result = new LinkedHashMap<>();
result.put("isDuplicate", false);
result.put("message", "값을 입력해주세요.");
return result;
}
Map<String, Object> params = new HashMap<>();
params.put("categoryCode", categoryCode);
params.put("codeValue", codeValue);
params.put("field", field != null ? field : "codeValue");
params.put("value", value.trim());
params.put("excludeCode", excludeCode);
params.put("companyCode", companyCode);
Integer countObj = sqlSession.selectOne(NS + "getCommonCodeDuplicateCnt", params);
int count = countObj != null ? countObj : 0;
Integer countObj = sqlSession.selectOne(NS + "getCommonCodeDuplicateByField", params);
boolean isDuplicate = countObj != null && countObj > 0;
Map<String, Object> result = new LinkedHashMap<>();
result.put("isDuplicate", count > 0);
result.put("isDuplicate", isDuplicate);
result.put("message", isDuplicate ? "이미 사용 중인 값입니다." : "사용 가능한 값입니다.");
return result;
}
@@ -179,6 +201,18 @@ public class CommonCodeService extends BaseService {
@Transactional
public Map<String, Object> insertCommonCode(String categoryCode, Map<String, Object> body,
String companyCode, String userId) {
// parentCodeValue 기반 depth 자동 계산
Object parentCodeValueRaw = body.getOrDefault("parentCodeValue", null);
int depth = 1;
if (parentCodeValueRaw != null && !parentCodeValueRaw.toString().isEmpty()) {
Map<String, Object> parentParams = new HashMap<>();
parentParams.put("categoryCode", categoryCode);
parentParams.put("codeValue", parentCodeValueRaw.toString());
parentParams.put("companyCode", companyCode);
Integer parentDepth = sqlSession.selectOne(NS + "getCommonCodeParentDepth", parentParams);
depth = (parentDepth != null ? parentDepth : 0) + 1;
}
Map<String, Object> params = new HashMap<>();
params.put("categoryCode", categoryCode);
params.put("codeValue", body.get("codeValue"));
@@ -186,11 +220,11 @@ public class CommonCodeService extends BaseService {
params.put("codeNameEng", body.getOrDefault("codeNameEng", null));
params.put("description", body.getOrDefault("description", null));
params.put("sortOrder", body.getOrDefault("sortOrder", 0));
params.put("isActive", body.getOrDefault("isActive", true));
params.put("isActive", toActiveStr(body.getOrDefault("isActive", true)));
params.put("menuObjid", body.getOrDefault("menuObjid", DEFAULT_MENU_OBJID));
params.put("companyCode", companyCode);
params.put("parentCodeValue", body.getOrDefault("parentCodeValue", null));
params.put("depth", body.getOrDefault("depth", 0));
params.put("parentCodeValue", parentCodeValueRaw);
params.put("depth", depth);
params.put("createdBy", userId);
params.put("updatedBy", userId);
@@ -228,9 +262,11 @@ public class CommonCodeService extends BaseService {
params.put("categoryCode", categoryCode);
Object isActiveRaw = params.get("isActive");
if (isActiveRaw != null) params.put("isActive", toBool(isActiveRaw));
if (isActiveRaw != null) params.put("isActive", toActiveStr(isActiveRaw));
else params.remove("isActive");
// parentCodeValue, depth 필터는 params에 그대로 전달 (XML에서 처리)
List<Map<String, Object>> rawList = sqlSession.selectList(NS + "getCommonCodeHierarchicalList", params);
List<Map<String, Object>> result = new ArrayList<>();
for (Map<String, Object> raw : rawList) {
@@ -240,16 +276,25 @@ public class CommonCodeService extends BaseService {
}
// ══════════════════════════════════════════════════════════════
// 트리 구조
// 트리 구조 — { flat: [...], tree: [...] }
// ══════════════════════════════════════════════════════════════
public List<Map<String, Object>> getCommonCodeTree(String categoryCode, String companyCode) {
public Map<String, Object> getCommonCodeTree(String categoryCode, String companyCode) {
Map<String, Object> params = new HashMap<>();
params.put("categoryCode", categoryCode);
params.put("companyCode", companyCode);
List<Map<String, Object>> flatList = sqlSession.selectList(NS + "getCommonCodeTreeList", params);
return buildTree(flatList);
List<Map<String, Object>> flatTransformed = new ArrayList<>();
for (Map<String, Object> raw : flatList) {
flatTransformed.add(transformCode(raw));
}
Map<String, Object> result = new LinkedHashMap<>();
result.put("flat", flatTransformed);
result.put("tree", buildTree(flatList));
return result;
}
// ══════════════════════════════════════════════════════════════
@@ -282,13 +327,29 @@ public class CommonCodeService extends BaseService {
params.put("companyCode", companyCode);
params.put("updatedBy", userId);
if (body.containsKey("codeName")) params.put("codeName", body.get("codeName"));
if (body.containsKey("codeNameEng")) params.put("codeNameEng", body.get("codeNameEng"));
if (body.containsKey("description")) params.put("description", body.get("description"));
if (body.containsKey("sortOrder")) params.put("sortOrder", body.get("sortOrder"));
if (body.containsKey("isActive")) params.put("isActive", body.get("isActive"));
if (body.containsKey("parentCodeValue")) params.put("parentCodeValue", body.get("parentCodeValue"));
if (body.containsKey("depth")) params.put("depth", body.get("depth"));
if (body.containsKey("codeName")) params.put("codeName", body.get("codeName"));
if (body.containsKey("codeNameEng")) params.put("codeNameEng", body.get("codeNameEng"));
if (body.containsKey("description")) params.put("description", body.get("description"));
if (body.containsKey("sortOrder")) params.put("sortOrder", body.get("sortOrder"));
if (body.containsKey("isActive")) params.put("isActive", toActiveStr(body.get("isActive")));
if (body.containsKey("parentCodeValue")) {
Object newParent = body.get("parentCodeValue");
params.put("parentCodeValue", newParent);
// parentCodeValue 변경 시 depth 재계산
if (newParent != null && !newParent.toString().isEmpty()) {
Map<String, Object> parentParams = new HashMap<>();
parentParams.put("categoryCode", categoryCode);
parentParams.put("codeValue", newParent.toString());
parentParams.put("companyCode", companyCode);
Integer parentDepth = sqlSession.selectOne(NS + "getCommonCodeParentDepth", parentParams);
params.put("depth", (parentDepth != null ? parentDepth : 0) + 1);
} else {
params.put("depth", 1);
}
} else if (body.containsKey("depth")) {
params.put("depth", body.get("depth"));
}
int updated = sqlSession.update(NS + "updateCommonCode", params);
if (updated == 0) return null;
@@ -324,7 +385,7 @@ public class CommonCodeService extends BaseService {
Object isActiveRaw = params.get("isActive");
// 미지정 시 활성 코드만 반환 (드롭다운 기본 동작)
params.put("isActive", isActiveRaw != null ? toBool(isActiveRaw) : true);
params.put("isActive", isActiveRaw != null ? toActiveStr(isActiveRaw) : "Y");
List<Map<String, Object>> rawList = sqlSession.selectList(NS + "getCommonCodeOptionList", params);
List<Map<String, Object>> options = new ArrayList<>();
@@ -388,17 +449,20 @@ public class CommonCodeService extends BaseService {
return roots;
}
/** boolean/String → VARCHAR 'Y'/'N' 변환 */
private String toActiveStr(Object val) {
if (val == null) return "Y";
if (val instanceof Boolean b) return b ? "Y" : "N";
String s = val.toString().toLowerCase();
return ("true".equals(s) || "y".equals(s) || "1".equals(s)) ? "Y" : "N";
}
private int toInt(Object val, int defaultVal) {
if (val == null) return defaultVal;
try { return Integer.parseInt(val.toString()); }
catch (NumberFormatException e) { return defaultVal; }
}
private boolean toBool(Object val) {
if (val instanceof Boolean b) return b;
return "true".equalsIgnoreCase(val.toString());
}
private String objToStr(Object val) {
return val != null ? val.toString() : "";
}
@@ -326,8 +326,14 @@ public class DashboardService extends BaseService {
private Object parseJson(Object value, Object defaultValue) {
if (value == null) return defaultValue;
String jsonStr = null;
if (value instanceof String) {
try { return objectMapper.readValue((String) value, new TypeReference<Object>() {}); }
jsonStr = (String) value;
} else if (value instanceof org.postgresql.util.PGobject pgObj) {
jsonStr = pgObj.getValue();
}
if (jsonStr != null) {
try { return objectMapper.readValue(jsonStr, new TypeReference<Object>() {}); }
catch (Exception e) { return defaultValue; }
}
return value;
@@ -23,7 +23,7 @@ public class DataAdvancedService extends BaseService {
private static final Pattern IDENTIFIER = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_]*$");
private static final Set<String> SYSTEM_COLUMNS = new HashSet<>(Arrays.asList(
"id", "company_code", "writer", "created_date", "updated_date", "created_at", "updated_at"));
"id", "company_code", "writer", "created_date", "updated_date"));
// ── 기존 위임 메서드 ──────────────────────────────────────────────────────
@@ -768,7 +768,7 @@ public class DataAdvancedService extends BaseService {
whereParts.add("\"" + k + "\" = ?");
whereArgs.add(data.get(k));
}
if (existingCols.contains("company_code") && companyCode != null) {
if (existingCols.contains("company_code") && companyCode != null && !"*".equals(companyCode)) {
whereParts.add("company_code = ?");
whereArgs.add(companyCode);
}
@@ -107,7 +107,7 @@ public class DataService extends BaseService {
List<Object> args = new ArrayList<>();
StringBuilder where = new StringBuilder("1=1");
if (hasCC && companyCode != null && !companyCode.isEmpty()) {
if (hasCC && companyCode != null && !companyCode.isEmpty() && !"*".equals(companyCode)) {
where.append(" AND company_code = ?");
args.add(companyCode);
}
@@ -121,8 +121,13 @@ public class DataService extends BaseService {
String col = entry.getKey();
if (!validCols.contains(col)) continue;
validateColumn(col);
where.append(" AND \"").append(col).append("\" = ?");
args.add(entry.getValue());
if (entry.getValue() instanceof String) {
where.append(" AND \"").append(col).append("\" ILIKE ?");
args.add("%" + entry.getValue() + "%");
} else {
where.append(" AND \"").append(col).append("\" = ?");
args.add(entry.getValue());
}
}
}
@@ -147,7 +152,7 @@ public class DataService extends BaseService {
} else {
// 기본 날짜 컬럼 정렬 (Node.js 호환)
Set<String> tblCols = getValidColumns(tableName);
for (String dateCol : new String[]{"created_date", "regdate", "reg_date", "updated_date", "upd_date"}) {
for (String dateCol : new String[]{"created_date", "updated_date"}) {
if (tblCols.contains(dateCol)) {
orderClause = " ORDER BY \"" + dateCol + "\" DESC";
break;
@@ -194,12 +199,13 @@ public class DataService extends BaseService {
return cols.stream().map(col -> {
Map<String, Object> c = new LinkedHashMap<>();
String colName = String.valueOf(col.get("column_name"));
c.put("name", colName);
c.put("type", col.get("data_type"));
c.put("columnName", colName);
c.put("dataType", col.get("data_type"));
c.put("udtName", col.get("udt_name"));
c.put("nullable", "YES".equals(col.get("is_nullable")));
c.put("defaultValue", col.get("column_default"));
c.put("isPk", pkList.contains(colName));
c.put("columnLabel", colName);
return c;
}).collect(Collectors.toList());
}
@@ -211,7 +217,9 @@ public class DataService extends BaseService {
validateTable(tableName);
List<String> pks = getPrimaryKeys(tableName);
String pkCol = pks.isEmpty() ? "id" : pks.get(0);
String pkOverride = (String) params.get("primaryKeyColumn");
String pkCol = pkOverride != null && !pkOverride.isBlank() ? pkOverride
: (pks.isEmpty() ? "id" : pks.get(0));
String companyCode = (String) params.get("companyCode");
boolean hasCC = hasCompanyCodeColumn(tableName);
@@ -219,7 +227,7 @@ public class DataService extends BaseService {
List<Object> args = new ArrayList<>();
args.add(id);
StringBuilder where = new StringBuilder("\"" + pkCol + "\" = ?");
if (hasCC && companyCode != null && !companyCode.isEmpty()) {
if (hasCC && companyCode != null && !companyCode.isEmpty() && !"*".equals(companyCode)) {
where.append(" AND company_code = ?");
args.add(companyCode);
}
@@ -251,7 +259,7 @@ public class DataService extends BaseService {
data.remove("companyCode");
}
if (hasCC && companyCode != null && !companyCode.isEmpty()) {
if (hasCC && companyCode != null && !companyCode.isEmpty() && !"*".equals(companyCode)) {
data.put("company_code", companyCode);
}
@@ -314,7 +322,7 @@ public class DataService extends BaseService {
args.add(id);
StringBuilder where = new StringBuilder("\"" + pkCol + "\" = ?");
if (hasCC && companyCode != null && !companyCode.isEmpty()) {
if (hasCC && companyCode != null && !companyCode.isEmpty() && !"*".equals(companyCode)) {
where.append(" AND company_code = ?");
args.add(companyCode);
}
@@ -322,7 +330,31 @@ public class DataService extends BaseService {
String sql = "UPDATE \"" + tableName + "\" SET " + String.join(", ", sets) +
" WHERE " + where + " RETURNING *";
List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, args.toArray());
return result.isEmpty() ? null : result.get(0);
Map<String, Object> updated = result.isEmpty() ? null : result.get(0);
// _relationInfo: FK cascade update (다른 테이블의 FK 컬럼을 동기화)
@SuppressWarnings("unchecked")
Object relInfoRaw = params.get("_relationInfo");
if (relInfoRaw instanceof Map && updated != null) {
Map<String, Object> relInfo = (Map<String, Object>) relInfoRaw;
String relatedTable = (String) relInfo.get("relatedTable");
String foreignKey = (String) relInfo.get("foreignKey");
Object oldValue = relInfo.get("oldValue");
Object newValue = relInfo.get("newValue");
if (relatedTable != null && foreignKey != null && oldValue != null && newValue != null) {
try {
validateTable(relatedTable);
validateColumn(foreignKey);
jdbcTemplate.update(
"UPDATE \"" + relatedTable + "\" SET \"" + foreignKey + "\" = ? WHERE \"" + foreignKey + "\" = ?",
newValue, oldValue);
} catch (Exception e) {
log.warn("_relationInfo FK cascade update 실패: {}", e.getMessage());
}
}
}
return updated;
}
// ── 삭제 ──────────────────────────────────────────────────────────────────
@@ -341,7 +373,7 @@ public class DataService extends BaseService {
List<Object> args = new ArrayList<>();
args.add(id);
StringBuilder where = new StringBuilder("\"" + pkCol + "\" = ?");
if (hasCC && companyCode != null && !companyCode.isEmpty()) {
if (hasCC && companyCode != null && !companyCode.isEmpty() && !"*".equals(companyCode)) {
where.append(" AND company_code = ?");
args.add(companyCode);
}
@@ -373,7 +405,7 @@ public class DataService extends BaseService {
List<Object> args = new ArrayList<>();
String joinCond = "l.\"" + leftKey + "\" = r.\"" + rightKey + "\"";
StringBuilder where = new StringBuilder("1=1");
if (hasCC && companyCode != null && !companyCode.isEmpty()) {
if (hasCC && companyCode != null && !companyCode.isEmpty() && !"*".equals(companyCode)) {
where.append(" AND l.company_code = ?");
args.add(companyCode);
}
@@ -384,7 +416,7 @@ public class DataService extends BaseService {
args.add(leftValue);
}
String listSql = "SELECT l.*, r.* FROM \"" + leftTable + "\" l" +
String listSql = "SELECT DISTINCT r.* FROM \"" + leftTable + "\" l" +
" INNER JOIN \"" + rightTable + "\" r ON " + joinCond +
" WHERE " + where;
List<Map<String, Object>> rows = jdbcTemplate.queryForList(listSql, args.toArray());
@@ -435,7 +467,7 @@ public class DataService extends BaseService {
conds.add("\"" + e.getKey() + "\" = ?");
cArgs.add(e.getValue());
}
if (hasCC && companyCode != null && !companyCode.isEmpty()) {
if (hasCC && companyCode != null && !companyCode.isEmpty() && !"*".equals(companyCode)) {
conds.add("company_code = ?");
cArgs.add(companyCode);
}
@@ -454,7 +486,7 @@ public class DataService extends BaseService {
if (!(recObj instanceof Map)) continue;
Map<String, Object> rec = new LinkedHashMap<>((Map<String, Object>) recObj);
rec.putAll(parentKeys);
if (hasCC && companyCode != null && !companyCode.isEmpty()) {
if (hasCC && companyCode != null && !companyCode.isEmpty() && !"*".equals(companyCode)) {
rec.put("company_code", companyCode);
}
@@ -532,7 +564,7 @@ public class DataService extends BaseService {
delConds.add("\"" + e.getKey() + "\" = ?");
delArgs.add(e.getValue());
}
if (hasCC && companyCode != null && !companyCode.isEmpty()) {
if (hasCC && companyCode != null && !companyCode.isEmpty() && !"*".equals(companyCode)) {
delConds.add("company_code = ?");
delArgs.add(companyCode);
}
@@ -580,7 +612,7 @@ public class DataService extends BaseService {
}
if (conds.isEmpty()) throw new IllegalArgumentException("유효한 삭제 키가 없습니다.");
if (hasCC && companyCode != null && !companyCode.isEmpty()) {
if (hasCC && companyCode != null && !companyCode.isEmpty() && !"*".equals(companyCode)) {
conds.add("company_code = ?");
args.add(companyCode);
}
@@ -620,7 +652,7 @@ public class DataService extends BaseService {
}
if (conds.isEmpty()) throw new IllegalArgumentException("유효한 삭제 조건이 없습니다.");
if (hasCC && companyCode != null && !companyCode.isEmpty()) {
if (hasCC && companyCode != null && !companyCode.isEmpty() && !"*".equals(companyCode)) {
conds.add("company_code = ?");
args.add(companyCode);
}
@@ -9,6 +9,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Service
@@ -344,7 +345,29 @@ public class DataflowService extends BaseService {
Map<String, Object> maxRow = sqlSession.selectOne("dataflow.getMaxDiagramId", maxParams);
int newDiagramId = toInt(maxRow != null ? maxRow.get("max_diagram_id") : null) + 1;
String newDiagramName = diagramName + " Copy";
// Node.js 동일 로직: "(n)" 접미사 제거해 baseName 추출 카운터 증가
Pattern suffixPattern = Pattern.compile("^(.+?)(\\s*\\((\\d+)\\))?$");
Matcher m = suffixPattern.matcher(diagramName);
String baseName = (m.matches() && m.group(1) != null) ? m.group(1) : diagramName;
// baseName으로 시작하는 기존 이름 조회
Map<String, Object> nameCheckParams = new HashMap<>();
nameCheckParams.put("pattern", baseName + "%");
nameCheckParams.put("companyCode", companyCode);
List<Map<String, Object>> existingNames = sqlSession.selectList("dataflow.getDiagramNameExists", nameCheckParams);
// 가장 (n) 번호 탐색
Pattern numPattern = Pattern.compile("\\((\\d+)\\)$");
int maxNumber = existingNames.stream()
.map(row -> String.valueOf(row.get("diagram_name")))
.mapToInt(name -> {
Matcher nm = numPattern.matcher(name);
return nm.find() ? Integer.parseInt(nm.group(1)) : 0;
})
.max()
.orElse(0);
String newDiagramName = baseName + " (" + (maxNumber + 1) + ")";
for (Map<String, Object> rel : existing) {
Map<String, Object> insertParams = new HashMap<>();
@@ -1,8 +1,8 @@
package com.erp.service;
import com.erp.common.BaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -11,16 +11,15 @@ import java.util.List;
import java.util.Map;
@Service
@RequiredArgsConstructor
@Slf4j
public class DeliveryService extends BaseService {
@Autowired private CommonService commonService;
private static final String NS = "delivery.";
public Map<String, Object> getDeliveryStatus(String companyCode) {
Map<String, Object> params = new HashMap<>();
params.put("companyCode", companyCode);
public Map<String, Object> getDeliveryStatus(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
List<Map<String, Object>> deliveries = sqlSession.selectList(NS + "getDeliveryList", params);
List<Map<String, Object>> issues = sqlSession.selectList(NS + "getCustomerIssueList", params);
Map<String, Object> todayStats = sqlSession.selectOne(NS + "getDeliveryTodayStats", params);
@@ -32,43 +31,31 @@ public class DeliveryService extends BaseService {
return result;
}
public List<Map<String, Object>> getDelayedDeliveries(String companyCode) {
Map<String, Object> params = new HashMap<>();
params.put("companyCode", companyCode);
public List<Map<String, Object>> getDelayedDeliveries(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
return sqlSession.selectList(NS + "getDelayedDeliveryList", params);
}
public List<Map<String, Object>> getCustomerIssues(String companyCode, String status) {
Map<String, Object> params = new HashMap<>();
params.put("companyCode", companyCode);
if (status != null && !status.isBlank()) {
params.put("status", status);
}
public List<Map<String, Object>> getCustomerIssues(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
return sqlSession.selectList(NS + "getCustomerIssueList", params);
}
@Transactional
public void updateDeliveryStatus(String companyCode, String id, String status, String delayReason) {
Map<String, Object> params = new HashMap<>();
params.put("companyCode", companyCode);
params.put("id", id);
params.put("status", status);
params.put("delayReason", delayReason);
public void updateDeliveryStatus(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
int rows = sqlSession.update(NS + "updateDeliveryStatus", params);
if (rows == 0) {
throw new IllegalArgumentException("Delivery not found: " + id);
throw new IllegalArgumentException("Delivery not found: " + params.get("id"));
}
}
@Transactional
public void updateIssueStatus(String companyCode, String id, String status) {
Map<String, Object> params = new HashMap<>();
params.put("companyCode", companyCode);
params.put("id", id);
params.put("status", status);
public void updateIssueStatus(Map<String, Object> params) {
commonService.applyCompanyCodeFilter(params);
int rows = sqlSession.update(NS + "updateCustomerIssueStatus", params);
if (rows == 0) {
throw new IllegalArgumentException("Customer issue not found: " + id);
throw new IllegalArgumentException("Customer issue not found: " + params.get("id"));
}
}
}
@@ -191,11 +191,11 @@ public class DynamicFormService extends BaseService {
dataToInsert.remove("screen_id");
// 공통 타임스탬프
if (tableColumns.contains("created_at")) dataToInsert.put("created_at", new java.util.Date());
if (tableColumns.contains("updated_at")) dataToInsert.put("updated_at", new java.util.Date());
if (tableColumns.contains("created_date")) dataToInsert.put("created_date", new java.util.Date());
if (tableColumns.contains("updated_date")) dataToInsert.put("updated_date", new java.util.Date());
if (tableColumns.contains("created_date")) dataToInsert.put("created_date", new java.util.Date());
if (tableColumns.contains("updated_date") && !dataToInsert.containsKey("updated_date")) dataToInsert.put("updated_date", new java.util.Date());
if (tableColumns.contains("regdate") && !dataToInsert.containsKey("regdate")) dataToInsert.put("regdate", new java.util.Date());
if (tableColumns.contains("created_date") && !dataToInsert.containsKey("created_date")) dataToInsert.put("created_date", new java.util.Date());
// 작성자 정보
if (writer != null && tableColumns.contains("writer")) dataToInsert.put("writer", writer);
@@ -314,7 +314,7 @@ public class DynamicFormService extends BaseService {
if (companyCodeRaw != null && targetCols.contains("company_code")) {
itemData.put("company_code", normalizeCompanyCode(companyCodeRaw.toString()));
}
if (targetCols.contains("regdate") && !itemData.containsKey("regdate")) itemData.put("regdate", new java.util.Date());
if (targetCols.contains("created_date") && !itemData.containsKey("created_date")) itemData.put("created_date", new java.util.Date());
itemData.keySet().removeIf(k -> !targetCols.contains(k));
for (String col : new ArrayList<>(itemData.keySet())) {
String dt = targetTypes.get(col);
@@ -331,8 +331,8 @@ public class DynamicFormService extends BaseService {
result.put("screenId", screenId);
result.put("tableName", tableName);
result.put("data", insertedRecord);
result.put("createdAt", insertedRecord.get("created_at"));
result.put("updatedAt", insertedRecord.get("updated_at"));
result.put("createdAt", insertedRecord.get("created_date"));
result.put("updatedAt", insertedRecord.get("updated_date"));
result.put("createdBy", insertedRecord.getOrDefault("created_by", createdBy));
result.put("updatedBy", insertedRecord.getOrDefault("updated_by", updatedBy));
return result;
@@ -403,9 +403,9 @@ public class DynamicFormService extends BaseService {
dataToUpdate.remove("company_code");
dataToUpdate.remove("screen_id");
if (tableColumns.contains("updated_at")) dataToUpdate.put("updated_at", new java.util.Date());
if (tableColumns.contains("updated_date")) dataToUpdate.put("updated_date", new java.util.Date());
if (tableColumns.contains("regdate") && !dataToUpdate.containsKey("regdate")) dataToUpdate.put("regdate", new java.util.Date());
if (tableColumns.contains("updated_date")) dataToUpdate.put("updated_date", new java.util.Date());
if (tableColumns.contains("created_date") && !dataToUpdate.containsKey("created_date")) dataToUpdate.put("created_date", new java.util.Date());
if (updatedBy != null && tableColumns.contains("updated_by")) dataToUpdate.put("updated_by", updatedBy);
dataToUpdate.keySet().removeIf(key -> !tableColumns.contains(key));
@@ -439,8 +439,8 @@ public class DynamicFormService extends BaseService {
result.put("screenId", 0);
result.put("tableName", tableName);
result.put("data", updated);
result.put("createdAt", updated.get("created_at"));
result.put("updatedAt", updated.get("updated_at"));
result.put("createdAt", updated.get("created_date"));
result.put("updatedAt", updated.get("updated_date"));
result.put("createdBy", updated.get("created_by"));
result.put("updatedBy", updated.getOrDefault("updated_by", updatedBy));
return result;
@@ -481,7 +481,7 @@ public class DynamicFormService extends BaseService {
return noChange;
}
if (tableColumns.contains("updated_at")) changedFields.put("updated_at", new java.util.Date());
if (tableColumns.contains("updated_date")) changedFields.put("updated_date", new java.util.Date());
if (tableColumns.contains("updated_date")) changedFields.put("updated_date", new java.util.Date());
String primaryKeyColumn = primaryKeys.get(0);
@@ -572,8 +572,8 @@ public class DynamicFormService extends BaseService {
result.put("screenId", row.get("screen_id"));
result.put("tableName", row.get("table_name"));
result.put("data", row.get("form_data"));
result.put("createdAt", row.get("created_at"));
result.put("updatedAt", row.get("updated_at"));
result.put("createdAt", row.get("created_date"));
result.put("updatedAt", row.get("updated_date"));
result.put("createdBy", row.get("created_by"));
result.put("updatedBy", row.get("updated_by"));
return result;
@@ -585,7 +585,7 @@ public class DynamicFormService extends BaseService {
int page = ((Number) queryParams.getOrDefault("page", 1)).intValue();
int size = ((Number) queryParams.getOrDefault("size", 10)).intValue();
String search = (String) queryParams.get("search");
String sortBy = (String) queryParams.getOrDefault("sortBy", "created_at");
String sortBy = (String) queryParams.getOrDefault("sortBy", "created_date");
String sortOrder = (String) queryParams.getOrDefault("sortOrder", "desc");
int offset = (page - 1) * size;
@@ -616,8 +616,8 @@ public class DynamicFormService extends BaseService {
item.put("screenId", row.get("screen_id"));
item.put("tableName", row.get("table_name"));
item.put("data", row.get("form_data"));
item.put("createdAt", row.get("created_at"));
item.put("updatedAt", row.get("updated_at"));
item.put("createdAt", row.get("created_date"));
item.put("updatedAt", row.get("updated_date"));
item.put("createdBy", row.get("created_by"));
item.put("updatedBy", row.get("updated_by"));
return item;
@@ -679,7 +679,7 @@ public class DynamicFormService extends BaseService {
// 컬럼 존재 여부 확인 (updated_by, updated_at, company_code)
List<String> tableColumns = getColumnNames(tableName);
boolean hasUpdatedBy = tableColumns.contains("updated_by");
boolean hasUpdatedAt = tableColumns.contains("updated_at");
boolean hasUpdatedAt = tableColumns.contains("updated_date");
boolean hasCompanyCode = tableColumns.contains("company_code");
List<Object> params = new ArrayList<>();
@@ -5,8 +5,8 @@ import com.erp.util.PasswordEncryption;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
@@ -21,7 +21,6 @@ import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@Slf4j
public class MailSendSimpleService extends BaseService {
@@ -29,7 +28,8 @@ public class MailSendSimpleService extends BaseService {
private static final String NS_HISTORY = "mailSentHistory.";
private static final String NS_TEMPLATE = "mailTemplateFile.";
private final ObjectMapper objectMapper;
@Autowired
private ObjectMapper objectMapper;
@Value("${encryption.secret-key:ilshin-erp-encryption-key-2024}")
private String encryptionSecretKey;
@@ -28,7 +28,7 @@ public class MailSentHistoryService extends BaseService {
String sortBy = (String) params.getOrDefault("sortBy", "sentAt");
String sortColumn = switch (sortBy) {
case "subject" -> "subject";
case "updatedAt" -> "updated_at";
case "updatedAt" -> "updated_date";
default -> "sent_at";
};
params.put("sortColumn", sortColumn);
@@ -1,12 +1,15 @@
package com.erp.service;
import com.erp.common.BaseService;
import com.erp.util.DecimalUtils;
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.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
@@ -258,11 +261,11 @@ public class ProductionService extends BaseService {
keptSchedules.addAll(keptRows);
}
double dailyCapacity = toDouble(item.getOrDefault("daily_capacity", 800));
double requiredQty = toDouble(item.get("required_qty"));
if (requiredQty <= 0) continue;
BigDecimal dailyCapacity = DecimalUtils.toBigDecimal(item.getOrDefault("daily_capacity", 800));
BigDecimal requiredQty = DecimalUtils.toBigDecimal(item.get("required_qty"));
if (requiredQty.compareTo(BigDecimal.ZERO) <= 0) continue;
int productionDays = (int) Math.ceil(requiredQty / dailyCapacity);
int productionDays = requiredQty.divide(dailyCapacity, 0, RoundingMode.CEILING).intValue();
LocalDate dueDate = toLocalDate(item.get("earliest_due_date"));
LocalDate endDate = dueDate.minusDays(safetyLeadTime);
@@ -347,11 +350,11 @@ public class ProductionService extends BaseService {
keptCount += (int) toLong(keptRows.get(0).get("cnt"));
}
double dailyCapacity = toDouble(item.getOrDefault("daily_capacity", 800));
double requiredQty = toDouble(item.get("required_qty"));
if (requiredQty <= 0) continue;
BigDecimal dailyCapacity = DecimalUtils.toBigDecimal(item.getOrDefault("daily_capacity", 800));
BigDecimal requiredQty = DecimalUtils.toBigDecimal(item.get("required_qty"));
if (requiredQty.compareTo(BigDecimal.ZERO) <= 0) continue;
int productionDays = (int) Math.ceil(requiredQty / dailyCapacity);
int productionDays = requiredQty.divide(dailyCapacity, 0, RoundingMode.CEILING).intValue();
LocalDate dueDate = toLocalDate(item.get("earliest_due_date"));
LocalDate endDate = dueDate.minusDays(safetyLeadTime);
@@ -429,14 +432,14 @@ public class ProductionService extends BaseService {
throw new IllegalArgumentException("동일 품목의 스케줄만 병합할 수 있습니다");
}
double totalQty = 0;
BigDecimal totalQty = BigDecimal.ZERO;
String earliestStart = null;
String latestEnd = null;
String earliestDue = null;
Set<String> orderNosSet = new LinkedHashSet<>();
for (Map<String, Object> r : rows) {
totalQty += toDouble(r.get("plan_qty"));
totalQty = totalQty.add(DecimalUtils.toBigDecimal(r.get("plan_qty")));
String startStr = toDateStr(r.get("start_date"));
String endStr = toDateStr(r.get("end_date"));
String dueStr = toDateStr(r.get("due_date"));
@@ -511,9 +514,9 @@ public class ProductionService extends BaseService {
List<Map<String, Object>> bomItems = getBomChildItems(companyCode, itemCode);
for (Map<String, Object> bomItem : bomItems) {
double planQty = toDouble(plan.get("plan_qty"));
double bomQty = toDouble(bomItem.getOrDefault("bom_qty", 1));
double requiredQty = planQty * bomQty;
BigDecimal planQty = DecimalUtils.toBigDecimal(plan.get("plan_qty"));
BigDecimal bomQty = DecimalUtils.toBigDecimal(bomItem.getOrDefault("bom_qty", 1));
BigDecimal requiredQty = planQty.multiply(bomQty);
if (considerStock) {
String childCode = bomItem.get("child_item_code") != null ?
@@ -523,11 +526,11 @@ public class ProductionService extends BaseService {
" WHERE company_code = ? AND item_code = ?",
companyCode, childCode
);
double stock = stockRows.isEmpty() ? 0 : toDouble(stockRows.get(0).get("stock"));
requiredQty = Math.max(requiredQty - stock, 0);
BigDecimal stock = stockRows.isEmpty() ? BigDecimal.ZERO : DecimalUtils.toBigDecimal(stockRows.get(0).get("stock"));
requiredQty = requiredQty.subtract(stock).max(BigDecimal.ZERO);
}
if (requiredQty <= 0) continue;
if (requiredQty.compareTo(BigDecimal.ZERO) <= 0) continue;
String semiDueDateStr = toDateStr(plan.get("start_date"));
LocalDate semiStartDate = LocalDate.parse(semiDueDateStr).minusDays(toInt(plan.getOrDefault("lead_time", 1)));
@@ -606,9 +609,9 @@ public class ProductionService extends BaseService {
List<Map<String, Object>> bomItems = getBomChildItems(companyCode, itemCode);
for (Map<String, Object> bomItem : bomItems) {
double planQty = toDouble(plan.get("plan_qty"));
double bomQty = toDouble(bomItem.getOrDefault("bom_qty", 1));
double requiredQty = planQty * bomQty;
BigDecimal planQty = DecimalUtils.toBigDecimal(plan.get("plan_qty"));
BigDecimal bomQty = DecimalUtils.toBigDecimal(bomItem.getOrDefault("bom_qty", 1));
BigDecimal requiredQty = planQty.multiply(bomQty);
if (considerStock) {
String childCode = bomItem.get("child_item_code") != null ?
@@ -618,11 +621,11 @@ public class ProductionService extends BaseService {
" WHERE company_code = ? AND item_code = ?",
companyCode, childCode
);
double stock = stockRows.isEmpty() ? 0 : toDouble(stockRows.get(0).get("stock"));
requiredQty = Math.max(requiredQty - stock, 0);
BigDecimal stock = stockRows.isEmpty() ? BigDecimal.ZERO : DecimalUtils.toBigDecimal(stockRows.get(0).get("stock"));
requiredQty = requiredQty.subtract(stock).max(BigDecimal.ZERO);
}
if (requiredQty <= 0) continue;
if (requiredQty.compareTo(BigDecimal.ZERO) <= 0) continue;
String semiDueDateStr = toDateStr(plan.get("start_date"));
LocalDate semiStartDate = LocalDate.parse(semiDueDateStr).minusDays(toInt(plan.getOrDefault("lead_time", 1)));
@@ -675,15 +678,16 @@ public class ProductionService extends BaseService {
}
Map<String, Object> plan = planRows.get(0);
double originalQty = toDouble(plan.get("plan_qty"));
BigDecimal originalQty = DecimalUtils.toBigDecimal(plan.get("plan_qty"));
BigDecimal bdSplitQty = BigDecimal.valueOf(splitQty);
if (splitQty >= originalQty || splitQty <= 0) {
if (bdSplitQty.compareTo(originalQty) >= 0 || splitQty <= 0) {
throw new IllegalArgumentException("분할 수량은 0보다 크고 원래 수량보다 작아야 합니다");
}
jdbcTemplate.update(
"UPDATE production_plan_mng SET plan_qty = ?, updated_date = NOW(), updated_by = ? WHERE id = ? AND company_code = ?",
originalQty - splitQty, splitBy, planId, companyCode
originalQty.subtract(bdSplitQty), splitBy, planId, companyCode
);
List<Map<String, Object>> planNoRows = jdbcTemplate.queryForList(
@@ -714,7 +718,7 @@ public class ProductionService extends BaseService {
log.info("스케줄 분할 완료: companyCode={}, planId={}, splitQty={}", companyCode, planId, splitQty);
Map<String, Object> originalInfo = new HashMap<>();
originalInfo.put("id", planId);
originalInfo.put("plan_qty", originalQty - splitQty);
originalInfo.put("plan_qty", originalQty.subtract(bdSplitQty));
Map<String, Object> result = new LinkedHashMap<>();
result.put("original", originalInfo);
@@ -1,8 +1,8 @@
package com.erp.service;
import com.erp.common.BaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -11,11 +11,11 @@ import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@Slf4j
public class ScheduleService extends BaseService {
private final CommonService commonService;
@Autowired
private CommonService commonService;
private static final String NS = "schedule.";
@@ -98,8 +98,8 @@ public class ScreenFileService extends BaseService {
mapped.put("parentTargetObjid", file.get("parent_target_objid"));
mapped.put("writer", file.get("writer"));
Object regdate = file.get("regdate");
mapped.put("regdate", regdate != null ? regdate.toString() : null);
Object regdate = file.get("created_date");
mapped.put("created_date", regdate != null ? regdate.toString() : null);
mapped.put("status", file.get("status"));
return mapped;
@@ -500,10 +500,88 @@ public class ScreenManagementService extends BaseService {
return sqlSession.selectList(NS + "selectLayoutV1ByScreen", params);
}
/** GET /layout — V2 우선 조회 (layer_id=1), 없으면 V1을 { components: [...] } 로 감싸서 반환 */
/** GET /layout-v1 — SCREEN_LAYOUTS_V1 조회, component_url/custom_config 변환 후 반환 */
@SuppressWarnings("unchecked")
public Map<String, Object> getLayoutV1WithTransform(Integer screenId, String companyCode) {
Map<String, Object> screen = getScreenById(screenId);
if (screen == null) return null;
Map<String, Object> params = new HashMap<>();
params.put("screenId", screenId);
params.put("companyCode", companyCode);
List<Map<String, Object>> layouts = sqlSession.selectList(NS + "selectLayoutV1FromV1Table", params);
List<Map<String, Object>> components = new ArrayList<>();
for (Map<String, Object> layout : layouts) {
String componentUrl = layout.getOrDefault("component_url", "").toString();
String componentType = componentUrl.isEmpty() ? "unknown"
: componentUrl.substring(componentUrl.lastIndexOf('/') + 1);
Object rawConfig = layout.get("custom_config");
Map<String, Object> componentConfig;
if (rawConfig == null) {
componentConfig = new HashMap<>();
} else if (rawConfig instanceof Map) {
componentConfig = (Map<String, Object>) rawConfig;
} else {
try {
componentConfig = objectMapper.readValue(rawConfig.toString(), Map.class);
} catch (Exception e) {
componentConfig = new HashMap<>();
}
}
Map<String, Object> position = new LinkedHashMap<>();
position.put("x", toInt(layout.getOrDefault("position_x", 0), 0));
position.put("y", toInt(layout.getOrDefault("position_y", 0), 0));
position.put("z", 1);
Map<String, Object> size = new LinkedHashMap<>();
size.put("width", toInt(layout.getOrDefault("width", 200), 200));
size.put("height", toInt(layout.getOrDefault("height", 100), 100));
Map<String, Object> comp = new LinkedHashMap<>();
comp.put("id", layout.get("component_id"));
comp.put("type", componentType);
comp.put("componentType", componentType);
comp.put("componentUrl", componentUrl);
comp.put("position", position);
comp.put("size", size);
comp.put("parentId", layout.get("parent_id"));
comp.put("componentConfig", componentConfig);
components.add(comp);
}
Map<String, Object> result = new LinkedHashMap<>();
result.put("components", components);
result.put("gridSettings", buildDefaultGridSettings());
result.put("screenResolution", null);
result.put("tableName", screen.get("table_name"));
return result;
}
/** GET /layout — V2 3단계 fallback 조회, 없으면 V1을 { components: [...] } 로 감싸서 반환 */
@SuppressWarnings("unchecked")
public Map<String, Object> getLayout(Integer screenId, String companyCode) {
Map<String, Object> v2 = getLayoutV2(screenId, companyCode, 1);
// Stage 1: 정확한 company_code 매칭
Map<String, Object> v2 = getLayoutV2Exact(screenId, companyCode, 1);
// Stage 2: 슈퍼어드민일 화면 소유 회사 코드로 재조회
if (v2 == null && "*".equals(companyCode)) {
Map<String, Object> screen = getScreenById(screenId);
if (screen != null) {
String screenCompanyCode = (String) screen.get("company_code");
if (screenCompanyCode != null && !"*".equals(screenCompanyCode)) {
v2 = getLayoutV2Exact(screenId, screenCompanyCode, 1);
}
}
}
// Stage 3: 일반 사용자일 공통('*') 레이아웃 조회
if (v2 == null && !"*".equals(companyCode)) {
v2 = getLayoutV2Exact(screenId, "*", 1);
}
if (v2 != null) {
if (!v2.containsKey("gridSettings") || v2.get("gridSettings") == null) {
v2.put("gridSettings", buildDefaultGridSettings());
@@ -577,6 +655,27 @@ public class ScreenManagementService extends BaseService {
}
}
@SuppressWarnings("unchecked")
private Map<String, Object> getLayoutV2Exact(Integer screenId, String companyCode, Integer layerId) {
Map<String, Object> params = new HashMap<>();
params.put("screenId", screenId);
params.put("companyCode", companyCode);
if (layerId != null) params.put("layerId", layerId);
Map<String, Object> row = sqlSession.selectOne(NS + "selectLayoutV2Exact", params);
if (row == null) return null;
Object layoutDataRaw = row.get("layout_data");
if (layoutDataRaw == null) return null;
try {
return objectMapper.readValue(layoutDataRaw.toString(), Map.class);
} catch (Exception e) {
log.warn("layout_data JSON 파싱 실패 (exact): {}", e.getMessage());
return null;
}
}
@Transactional
public void saveLayoutV2(Integer screenId, Map<String, Object> body,
String companyCode, String userId) {
@@ -54,7 +54,7 @@ public class VehicleService extends BaseService {
}
public Map<String, Object> moveVehicles(Map<String, Object> params) {
sqlSession.update("vehicle.moveVehicles", params);
sqlSession.selectList("vehicle.moveVehicles", params);
Map<String, Object> result = new LinkedHashMap<>();
result.put("message", "차량 위치가 업데이트되었습니다");
return result;
@@ -12,8 +12,6 @@ spring:
max-file-size: 50MB
max-request-size: 55MB
jackson:
generator:
write-numbers-as-strings: true
default-property-inclusion: always
datasource:
url: jdbc:postgresql://39.117.244.52:11132/plm
@@ -20,7 +20,7 @@
, MENU.MENU_DESC
, MENU.SEQ
, MENU.WRITER
, MENU.REGDATE
, MENU.CREATED_DATE
, MENU.STATUS
, MENU.COMPANY_CODE
, MENU.LANG_KEY
@@ -68,7 +68,7 @@
, S.MENU_DESC
, S.SEQ
, S.WRITER
, S.REGDATE
, S.CREATED_DATE
, S.STATUS
, S.COMPANY_CODE
, S.LANG_KEY
@@ -114,7 +114,7 @@
, 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
, TO_CHAR(V.CREATED_DATE, 'YYYY-MM-DD') AS REGDATE
, V.STATUS
, V.COMPANY_CODE
, COALESCE(V.LANG_KEY, '') AS LANG_KEY
@@ -165,7 +165,7 @@
, MENU.MENU_DESC
, MENU.SEQ
, MENU.WRITER
, MENU.REGDATE
, MENU.CREATED_DATE
, MENU.STATUS
, MENU.COMPANY_CODE
, MENU.LANG_KEY
@@ -197,7 +197,7 @@
, S.MENU_DESC
, S.SEQ
, S.WRITER
, S.REGDATE
, S.CREATED_DATE
, S.STATUS
, S.COMPANY_CODE
, S.LANG_KEY
@@ -221,7 +221,7 @@
, 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
, TO_CHAR(V.CREATED_DATE, 'YYYY-MM-DD') AS REGDATE
, V.STATUS
, V.COMPANY_CODE
, COALESCE(V.LANG_KEY, '') AS LANG_KEY
@@ -323,7 +323,7 @@
, MENU_DESC
, SEQ
, WRITER
, REGDATE
, CREATED_DATE
, STATUS
, COMPANY_CODE
, LANG_KEY
@@ -382,22 +382,22 @@
<select id="selectUserList" parameterType="map" resultType="map">
SELECT
SABUN
, USER_ID
, USER_NAME
, USER_NAME_ENG
, DEPT_CODE
, DEPT_NAME
, POSITION_CODE
, POSITION_NAME
, EMAIL
, TEL
, CELL_PHONE
, USER_TYPE
, USER_TYPE_NAME
, TO_CHAR(REGDATE, 'YYYY-MM-DD') AS REG_DATE
, USER_ID AS "userId"
, USER_NAME AS "userName"
, COALESCE(USER_NAME_ENG, '') AS "userNameEng"
, COALESCE(DEPT_CODE, '') AS "deptCode"
, COALESCE(DEPT_NAME, '') AS "deptName"
, COALESCE(POSITION_CODE, '') AS "positionCode"
, COALESCE(POSITION_NAME, '') AS "positionName"
, COALESCE(EMAIL, '') AS EMAIL
, COALESCE(TEL, '') AS TEL
, COALESCE(CELL_PHONE, '') AS "cellPhone"
, COALESCE(USER_TYPE, '') AS "userType"
, COALESCE(USER_TYPE_NAME, '') AS "userTypeName"
, COALESCE(TO_CHAR(CREATED_DATE, 'YYYY-MM-DD'), '') AS "regDate"
, STATUS
, COMPANY_CODE
, LOCALE
, COMPANY_CODE AS "companyCode"
, COALESCE(LOCALE, '') AS LOCALE
FROM USER_INFO
WHERE 1=1
<if test='companyCode != null and companyCode != "*"'>
@@ -420,7 +420,7 @@
<if test="deptCode != null and deptCode != ''">
AND DEPT_CODE = #{deptCode}
</if>
ORDER BY REGDATE DESC, USER_NAME ASC
ORDER BY CREATED_DATE DESC, USER_NAME ASC
<include refid="common.pagination"/>
</select>
@@ -472,7 +472,7 @@
, COMPANY_CODE
, LOCALE
, STATUS
, TO_CHAR(REGDATE, 'YYYY-MM-DD') AS REG_DATE
, TO_CHAR(CREATED_DATE, 'YYYY-MM-DD') AS REG_DATE
FROM USER_INFO
WHERE USER_ID = #{userId}
</select>
@@ -505,7 +505,7 @@
, COMPANY_CODE
, LOCALE
, STATUS
, REGDATE
, CREATED_DATE
) VALUES (
#{userId}
, #{userPassword}
@@ -587,7 +587,7 @@
, 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
, CASE WHEN CREATED_DATE IS NOT NULL THEN TO_CHAR(CREATED_DATE, 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') ELSE NULL END AS CREATED_DATE
, DATA_TYPE
, STATUS
, SALES_YN
@@ -623,7 +623,7 @@
, ADDRESS
, STATUS
, WRITER
, REGDATE
, CREATED_DATE AS REGDATE
FROM COMPANY_MNG
WHERE (STATUS = 'active' OR STATUS IS NULL)
ORDER BY COMPANY_NAME ASC
@@ -635,7 +635,7 @@
, COMPANY_NAME
, STATUS
, WRITER
, REGDATE
, CREATED_DATE AS REGDATE
FROM COMPANY_MNG
WHERE (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</select>
@@ -652,7 +652,7 @@
, ADDRESS
, STATUS
, WRITER
, REGDATE
, CREATED_DATE
) VALUES (
#{companyCode}
, #{companyName}
@@ -697,7 +697,7 @@
SELECT *
FROM USER_DEPT
WHERE USER_ID = #{userId}
ORDER BY IS_PRIMARY DESC, CREATED_AT ASC
ORDER BY IS_PRIMARY DESC, CREATED_DATE ASC
</select>
<!-- 사용자 부서 UPSERT -->
@@ -710,8 +710,8 @@
, USER_NAME
, POSITION_NAME
, COMPANY_CODE
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{userId}
, #{deptCode}
@@ -730,7 +730,7 @@
, USER_NAME = #{userName}
, POSITION_NAME = #{positionName}
, COMPANY_CODE = #{companyCode}
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
</insert>
<!-- 기존 메인 부서를 겸직으로 전환 -->
@@ -738,7 +738,7 @@
UPDATE USER_DEPT
SET
IS_PRIMARY = FALSE
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE USER_ID = #{userId}
AND DEPT_CODE = #{deptCode}
</update>
@@ -67,7 +67,7 @@
IS_ACTIVE = #{is_active},
</if>
UPDATED_BY = #{userId},
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
</set>
WHERE DEFINITION_ID = #{definitionId}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
@@ -108,7 +108,7 @@
ON T.DEFINITION_ID = D.DEFINITION_ID AND T.COMPANY_CODE = D.COMPANY_CODE
WHERE T.TEMPLATE_ID = #{templateId}
<if test='companyCode != null and companyCode != "*"'>
AND (T.COMPANY_CODE = #{companyCode} OR T.COMPANY_CODE = '*')
AND T.COMPANY_CODE = #{companyCode}
</if>
</select>
@@ -142,16 +142,16 @@
IS_ACTIVE = #{is_active},
</if>
UPDATED_BY = #{userId},
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
</set>
WHERE TEMPLATE_ID = #{templateId}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
AND COMPANY_CODE = #{companyCode}
</update>
<delete id="deleteTemplate" parameterType="map">
DELETE FROM APPROVAL_LINE_TEMPLATES
WHERE TEMPLATE_ID = #{templateId}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
AND COMPANY_CODE = #{companyCode}
</delete>
<!-- ================================================================
@@ -162,7 +162,7 @@
SELECT * FROM APPROVAL_LINE_TEMPLATE_STEPS
WHERE TEMPLATE_ID = #{templateId}
<if test='companyCode != null and companyCode != "*"'>
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
AND COMPANY_CODE = #{companyCode}
</if>
ORDER BY STEP_ORDER ASC
</select>
@@ -182,7 +182,7 @@
<delete id="deleteTemplateStepsByTemplateId" parameterType="map">
DELETE FROM APPROVAL_LINE_TEMPLATE_STEPS
WHERE TEMPLATE_ID = #{templateId}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
AND COMPANY_CODE = #{companyCode}
</delete>
<!-- ================================================================
@@ -219,7 +219,7 @@
AND L.COMPANY_CODE = R.COMPANY_CODE
)
</if>
ORDER BY R.CREATED_AT DESC
ORDER BY R.CREATED_DATE DESC
<if test="pageLimit != null">
LIMIT #{pageLimit} OFFSET #{pageOffset}
</if>
@@ -301,7 +301,7 @@
FINAL_APPROVER_ID = #{userId},
FINAL_COMMENT = #{comment},
COMPLETED_AT = NOW(),
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
WHERE REQUEST_ID = #{requestId}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</update>
@@ -312,7 +312,7 @@
FINAL_APPROVER_ID = #{userId},
FINAL_COMMENT = #{comment},
COMPLETED_AT = NOW(),
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
WHERE REQUEST_ID = #{requestId}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</update>
@@ -320,7 +320,7 @@
<update id="cancelRequest" parameterType="map">
UPDATE APPROVAL_REQUESTS
SET STATUS = 'cancelled',
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
WHERE REQUEST_ID = #{requestId}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</update>
@@ -333,7 +333,7 @@
FINAL_APPROVER_ID = #{userId},
FINAL_COMMENT = #{comment},
COMPLETED_AT = NOW(),
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
WHERE REQUEST_ID = #{requestId}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</update>
@@ -341,7 +341,7 @@
<update id="updateRequestCurrentStep" parameterType="map">
UPDATE APPROVAL_REQUESTS
SET CURRENT_STEP = #{nextStep},
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
WHERE REQUEST_ID = #{requestId}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</update>
@@ -349,7 +349,7 @@
<update id="updateRequestStatus" parameterType="map">
UPDATE APPROVAL_REQUESTS
SET STATUS = #{status},
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
WHERE REQUEST_ID = #{requestId}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</update>
@@ -459,14 +459,14 @@
SELECT L.*,
R.TITLE, R.TARGET_TABLE, R.TARGET_RECORD_ID,
R.REQUESTER_NAME, R.REQUESTER_DEPT,
R.CREATED_AT AS REQUEST_CREATED_AT
R.CREATED_DATE AS REQUEST_CREATED_DATE
FROM APPROVAL_LINES L
JOIN APPROVAL_REQUESTS R
ON L.REQUEST_ID = R.REQUEST_ID AND L.COMPANY_CODE = R.COMPANY_CODE
WHERE L.APPROVER_ID = #{userId}
AND L.STATUS = 'pending'
AND (L.COMPANY_CODE = #{companyCode} OR L.COMPANY_CODE = '*')
ORDER BY R.CREATED_AT ASC
ORDER BY R.CREATED_DATE ASC
</select>
<!-- ================================================================
@@ -481,7 +481,7 @@
LEFT JOIN USER_INFO U1 ON PS.ORIGINAL_USER_ID = U1.USER_ID AND PS.COMPANY_CODE = U1.COMPANY_CODE
LEFT JOIN USER_INFO U2 ON PS.PROXY_USER_ID = U2.USER_ID AND PS.COMPANY_CODE = U2.COMPANY_CODE
WHERE (PS.COMPANY_CODE = #{companyCode} OR PS.COMPANY_CODE = '*')
ORDER BY PS.CREATED_AT DESC
ORDER BY PS.CREATED_DATE DESC
</select>
<select id="selectProxyById" parameterType="map" resultType="map">
@@ -524,7 +524,7 @@
<if test="is_active != null">
IS_ACTIVE = #{is_active},
</if>
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
</set>
WHERE ID = #{id}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
@@ -25,17 +25,17 @@
AND SAL.TABLE_NAME = #{tableName}
</if>
<if test="dateFrom != null and dateFrom != ''">
AND SAL.CREATED_AT >= #{dateFrom}::TIMESTAMPTZ
AND SAL.CREATED_DATE >= #{dateFrom}::TIMESTAMPTZ
</if>
<if test="dateTo != null and dateTo != ''">
AND SAL.CREATED_AT &lt;= #{dateTo}::TIMESTAMPTZ
AND SAL.CREATED_DATE &lt;= #{dateTo}::TIMESTAMPTZ
</if>
<if test="search != null and search != ''">
AND (SAL.SUMMARY ILIKE CONCAT('%', #{search}, '%')
OR SAL.RESOURCE_NAME ILIKE CONCAT('%', #{search}, '%')
OR SAL.USER_NAME ILIKE CONCAT('%', #{search}, '%'))
</if>
ORDER BY SAL.CREATED_AT DESC
ORDER BY SAL.CREATED_DATE DESC
LIMIT #{limit} OFFSET #{offset}
</select>
@@ -60,10 +60,10 @@
AND SAL.TABLE_NAME = #{tableName}
</if>
<if test="dateFrom != null and dateFrom != ''">
AND SAL.CREATED_AT >= #{dateFrom}::TIMESTAMPTZ
AND SAL.CREATED_DATE >= #{dateFrom}::TIMESTAMPTZ
</if>
<if test="dateTo != null and dateTo != ''">
AND SAL.CREATED_AT &lt;= #{dateTo}::TIMESTAMPTZ
AND SAL.CREATED_DATE &lt;= #{dateTo}::TIMESTAMPTZ
</if>
<if test="search != null and search != ''">
AND (SAL.SUMMARY ILIKE CONCAT('%', #{search}, '%')
@@ -74,13 +74,13 @@
<!-- 일별 감사 로그 건수 -->
<select id="selectDailyCounts" parameterType="map" resultType="map">
SELECT DATE(CREATED_AT) AS DATE, COUNT(*)::INT AS COUNT
SELECT DATE(CREATED_DATE) AS DATE, COUNT(*)::INT AS COUNT
FROM SYSTEM_AUDIT_LOG
WHERE CREATED_AT >= NOW() - INTERVAL '1 day' * #{days}
WHERE CREATED_DATE >= NOW() - INTERVAL '1 day' * #{days}
<if test="companyCode != null and companyCode != ''">
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</if>
GROUP BY DATE(CREATED_AT)
GROUP BY DATE(CREATED_DATE)
ORDER BY DATE DESC
</select>
@@ -88,7 +88,7 @@
<select id="selectResourceTypeCounts" parameterType="map" resultType="map">
SELECT RESOURCE_TYPE, COUNT(*)::INT AS COUNT
FROM SYSTEM_AUDIT_LOG
WHERE CREATED_AT >= NOW() - INTERVAL '1 day' * #{days}
WHERE CREATED_DATE >= NOW() - INTERVAL '1 day' * #{days}
<if test="companyCode != null and companyCode != ''">
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</if>
@@ -100,7 +100,7 @@
<select id="selectActionCounts" parameterType="map" resultType="map">
SELECT ACTION, COUNT(*)::INT AS COUNT
FROM SYSTEM_AUDIT_LOG
WHERE CREATED_AT >= NOW() - INTERVAL '1 day' * #{days}
WHERE CREATED_DATE >= NOW() - INTERVAL '1 day' * #{days}
<if test="companyCode != null and companyCode != ''">
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</if>
@@ -112,7 +112,7 @@
<select id="selectTopUsers" parameterType="map" resultType="map">
SELECT USER_ID, COALESCE(MAX(USER_NAME), USER_ID) AS USER_NAME, COUNT(*)::INT AS COUNT
FROM SYSTEM_AUDIT_LOG
WHERE CREATED_AT >= NOW() - INTERVAL '1 day' * #{days}
WHERE CREATED_DATE >= NOW() - INTERVAL '1 day' * #{days}
<if test="companyCode != null and companyCode != ''">
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</if>
@@ -60,7 +60,7 @@
COMPANY_CODE
, COMPANY_NAME
FROM COMPANY_MNG
WHERE (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
WHERE COMPANY_CODE = #{companyCode}
</select>
<!-- 로그인 접근 로그 기록 -->
@@ -119,7 +119,7 @@
, USER_TYPE
, SIGNUP_TYPE
, STATUS
, REGDATE
, CREATED_DATE
) VALUES (
#{userId}
, #{userPassword}
@@ -145,8 +145,8 @@
, STATUS
, COMPANY_CODE
, USER_ID
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{vehicleNumber}
, #{vehicleType}
@@ -24,9 +24,9 @@
, WIDTH_MM
, HEIGHT_MM
, USE_YN
, CREATED_AT
, CREATED_DATE
, CREATED_BY
, UPDATED_AT
, UPDATED_DATE
, UPDATED_BY
FROM BARCODE_LABELS
WHERE 1=1
@@ -53,9 +53,9 @@
, HEIGHT_MM
, LAYOUT_JSON
, USE_YN
, CREATED_AT
, CREATED_DATE
, CREATED_BY
, UPDATED_AT
, UPDATED_DATE
, UPDATED_BY
FROM BARCODE_LABELS
WHERE LABEL_ID = #{labelId}
@@ -73,7 +73,7 @@
, LAYOUT_JSON
, USE_YN
, CREATED_BY
, CREATED_AT
, CREATED_DATE
) VALUES (
#{labelId}
, #{labelNameKor}
@@ -96,7 +96,7 @@
<if test="labelNameEng != null">LABEL_NAME_ENG = #{labelNameEng},</if>
<if test="description != null">DESCRIPTION = #{description},</if>
<if test="useYn != null">USE_YN = #{useYn},</if>
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
<if test="updatedBy != null">, UPDATED_BY = #{updatedBy}</if>
</set>
WHERE LABEL_ID = #{labelId}
@@ -115,7 +115,7 @@
WIDTH_MM = #{widthMm}
, HEIGHT_MM = #{heightMm}
, LAYOUT_JSON = #{layoutJson}
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
<if test="updatedBy != null">, UPDATED_BY = #{updatedBy}</if>
WHERE LABEL_ID = #{labelId}
</update>
@@ -132,7 +132,7 @@
, LAYOUT_JSON
, USE_YN
, CREATED_BY
, CREATED_AT
, CREATED_DATE
)
SELECT
#{newLabelId}
@@ -15,10 +15,10 @@
WHERE 1=1
<include refid="common.companyCodeFilter"/>
<if test="itemCode != null and itemCode != ''">
AND B.ITEM_CODE ILIKE CONCAT('%', #{itemCode}, '%')
AND B.ITEM_CODE ILIKE '%' || #{itemCode} || '%'
</if>
<if test="itemName != null and itemName != ''">
AND COALESCE(B.ITEM_NAME, II.ITEM_NAME) ILIKE CONCAT('%', #{itemName}, '%')
AND COALESCE(B.ITEM_NAME, II.ITEM_NAME) ILIKE '%' || #{itemName} || '%'
</if>
<if test="status != null and status != ''">
AND B.STATUS = #{status}
@@ -34,10 +34,10 @@
WHERE 1=1
<include refid="common.companyCodeFilter"/>
<if test="itemCode != null and itemCode != ''">
AND B.ITEM_CODE ILIKE CONCAT('%', #{itemCode}, '%')
AND B.ITEM_CODE ILIKE '%' || #{itemCode} || '%'
</if>
<if test="itemName != null and itemName != ''">
AND COALESCE(B.ITEM_NAME, II.ITEM_NAME) ILIKE CONCAT('%', #{itemName}, '%')
AND COALESCE(B.ITEM_NAME, II.ITEM_NAME) ILIKE '%' || #{itemName} || '%'
</if>
<if test="status != null and status != ''">
AND B.STATUS = #{status}
@@ -61,9 +61,11 @@
<insert id="insertBom" parameterType="map" useGeneratedKeys="true" keyProperty="id">
INSERT INTO BOM (
COMPANY_CODE, ITEM_ID, ITEM_CODE, ITEM_NAME, BASE_QTY, UNIT, VERSION, STATUS, REMARK, WRITER
, CREATED_DATE, UPDATED_DATE
) VALUES (
#{companyCode}, #{itemId}, #{itemCode}, #{itemName}, #{baseQty}, #{unit},
COALESCE(#{version}, '1.0'), COALESCE(#{status}, 'active'), #{remark}, #{writer}
, NOW(), NOW()
)
</insert>
@@ -14,7 +14,7 @@
</if>
</sql>
<!-- Node.js: ORDER BY CASE WHEN priority='urgent' THEN 0 ELSE 1 END, created_at DESC -->
<!-- Node.js: ORDER BY CASE WHEN priority='urgent' THEN 0 ELSE 1 END, CREATED_DATE DESC -->
<select id="getBookingList" parameterType="map" resultType="map">
SELECT
ID
@@ -28,8 +28,8 @@
, WEIGHT
, STATUS
, PRIORITY
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
, ACCEPTED_AT
, REJECTED_AT
, COMPLETED_AT
@@ -43,7 +43,7 @@
<include refid="bookingSearchCondition"/>
ORDER BY CASE WHEN PRIORITY = 'urgent' THEN 0 ELSE 1 END,
CREATED_AT DESC
CREATED_DATE DESC
<include refid="common.pagination"/>
</select>
@@ -63,7 +63,7 @@
FROM BOOKING_REQUESTS
WHERE STATUS = 'pending'
AND CREATED_AT &gt;= NOW() - INTERVAL '5 minutes'
AND CREATED_DATE &gt;= NOW() - INTERVAL '5 minutes'
</select>
<!-- POST /:id/accept — status = 'accepted', accepted_at = NOW() -->
@@ -73,7 +73,7 @@
SET
STATUS = 'accepted'
, ACCEPTED_AT = NOW()
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE ID = #{id}
</update>
@@ -85,7 +85,7 @@
SET
STATUS = 'rejected'
, REJECTED_AT = NOW()
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
, REJECTION_REASON = #{rejectionReason, jdbcType=VARCHAR}
WHERE ID = #{id}
@@ -30,7 +30,7 @@
WHERE 1=1
<include refid="common.companyCodeFilter"/>
<include refid="cascadingMutualExclusionSearchCondition"/>
<include refid="common.dynamicOrderBy"/>
ORDER BY CREATED_DATE DESC
<include refid="common.pagination"/>
</select>
@@ -4,13 +4,29 @@
<mapper namespace="cascadingRelation">
<sql id="cascadingRelationColumns">
RELATION_ID, RELATION_CODE, RELATION_NAME, DESCRIPTION,
PARENT_TABLE, PARENT_VALUE_COLUMN, PARENT_LABEL_COLUMN,
CHILD_TABLE, CHILD_FILTER_COLUMN, CHILD_VALUE_COLUMN,
CHILD_LABEL_COLUMN, CHILD_ORDER_COLUMN, CHILD_ORDER_DIRECTION,
EMPTY_PARENT_MESSAGE, NO_OPTIONS_MESSAGE, LOADING_MESSAGE,
CLEAR_ON_PARENT_CHANGE, COMPANY_CODE, IS_ACTIVE,
CREATED_BY, CREATED_DATE, UPDATED_BY, UPDATED_DATE
RELATION_ID
, RELATION_CODE
, RELATION_NAME
, DESCRIPTION
, PARENT_TABLE
, PARENT_VALUE_COLUMN
, PARENT_LABEL_COLUMN
, CHILD_TABLE
, CHILD_FILTER_COLUMN
, CHILD_VALUE_COLUMN
, CHILD_LABEL_COLUMN
, CHILD_ORDER_COLUMN
, CHILD_ORDER_DIRECTION
, EMPTY_PARENT_MESSAGE
, NO_OPTIONS_MESSAGE
, LOADING_MESSAGE
, CLEAR_ON_PARENT_CHANGE
, COMPANY_CODE
, IS_ACTIVE
, CREATED_BY
, CREATED_DATE
, UPDATED_BY
, UPDATED_DATE
</sql>
<sql id="cascadingRelationSearchCondition">
@@ -29,7 +45,7 @@
WHERE 1=1
<include refid="common.companyCodeFilter"/>
<include refid="cascadingRelationSearchCondition"/>
<include refid="common.dynamicOrderBy"/>
ORDER BY CREATED_DATE DESC
<include refid="common.pagination"/>
</select>
@@ -61,67 +77,82 @@
<insert id="insertCascadingRelation" parameterType="map"
useGeneratedKeys="true" keyProperty="relationId" keyColumn="relation_id">
INSERT INTO CASCADING_RELATION (
RELATION_CODE, RELATION_NAME, DESCRIPTION,
PARENT_TABLE, PARENT_VALUE_COLUMN, PARENT_LABEL_COLUMN,
CHILD_TABLE, CHILD_FILTER_COLUMN, CHILD_VALUE_COLUMN,
CHILD_LABEL_COLUMN, CHILD_ORDER_COLUMN, CHILD_ORDER_DIRECTION,
EMPTY_PARENT_MESSAGE, NO_OPTIONS_MESSAGE, LOADING_MESSAGE,
CLEAR_ON_PARENT_CHANGE, COMPANY_CODE, IS_ACTIVE,
CREATED_BY, CREATED_DATE
RELATION_CODE
, RELATION_NAME
, DESCRIPTION
, PARENT_TABLE
, PARENT_VALUE_COLUMN
, PARENT_LABEL_COLUMN
, CHILD_TABLE
, CHILD_FILTER_COLUMN
, CHILD_VALUE_COLUMN
, CHILD_LABEL_COLUMN
, CHILD_ORDER_COLUMN
, CHILD_ORDER_DIRECTION
, EMPTY_PARENT_MESSAGE
, NO_OPTIONS_MESSAGE
, LOADING_MESSAGE
, CLEAR_ON_PARENT_CHANGE
, COMPANY_CODE
, IS_ACTIVE
, CREATED_BY
, CREATED_DATE
) VALUES (
#{relationCode, jdbcType=VARCHAR},
#{relationName, jdbcType=VARCHAR},
#{description, jdbcType=VARCHAR},
#{parentTable, jdbcType=VARCHAR},
#{parentValueColumn, jdbcType=VARCHAR},
#{parentLabelColumn, jdbcType=VARCHAR},
#{childTable, jdbcType=VARCHAR},
#{childFilterColumn, jdbcType=VARCHAR},
#{childValueColumn, jdbcType=VARCHAR},
#{childLabelColumn, jdbcType=VARCHAR},
#{childOrderColumn, jdbcType=VARCHAR},
#{childOrderDirection, jdbcType=VARCHAR},
#{emptyParentMessage, jdbcType=VARCHAR},
#{noOptionsMessage, jdbcType=VARCHAR},
#{loadingMessage, jdbcType=VARCHAR},
#{clearOnParentChange, jdbcType=VARCHAR},
#{companyCode},
#{isActive, jdbcType=VARCHAR},
#{userId, jdbcType=VARCHAR},
CURRENT_TIMESTAMP
#{relationCode, jdbcType=VARCHAR}
, #{relationName, jdbcType=VARCHAR}
, #{description, jdbcType=VARCHAR}
, #{parentTable, jdbcType=VARCHAR}
, #{parentValueColumn, jdbcType=VARCHAR}
, #{parentLabelColumn, jdbcType=VARCHAR}
, #{childTable, jdbcType=VARCHAR}
, #{childFilterColumn, jdbcType=VARCHAR}
, #{childValueColumn, jdbcType=VARCHAR}
, #{childLabelColumn, jdbcType=VARCHAR}
, #{childOrderColumn, jdbcType=VARCHAR}
, #{childOrderDirection, jdbcType=VARCHAR}
, #{emptyParentMessage, jdbcType=VARCHAR}
, #{noOptionsMessage, jdbcType=VARCHAR}
, #{loadingMessage, jdbcType=VARCHAR}
, #{clearOnParentChange, jdbcType=VARCHAR}
, #{companyCode}
, #{isActive, jdbcType=VARCHAR}
, #{userId, jdbcType=VARCHAR}
, CURRENT_TIMESTAMP
)
</insert>
<update id="updateCascadingRelation" parameterType="map">
UPDATE CASCADING_RELATION SET
RELATION_NAME = COALESCE(#{relationName, jdbcType=VARCHAR}, RELATION_NAME),
DESCRIPTION = COALESCE(#{description, jdbcType=VARCHAR}, DESCRIPTION),
PARENT_TABLE = COALESCE(#{parentTable, jdbcType=VARCHAR}, PARENT_TABLE),
PARENT_VALUE_COLUMN = COALESCE(#{parentValueColumn, jdbcType=VARCHAR}, PARENT_VALUE_COLUMN),
PARENT_LABEL_COLUMN = COALESCE(#{parentLabelColumn, jdbcType=VARCHAR}, PARENT_LABEL_COLUMN),
CHILD_TABLE = COALESCE(#{childTable, jdbcType=VARCHAR}, CHILD_TABLE),
CHILD_FILTER_COLUMN = COALESCE(#{childFilterColumn, jdbcType=VARCHAR}, CHILD_FILTER_COLUMN),
CHILD_VALUE_COLUMN = COALESCE(#{childValueColumn, jdbcType=VARCHAR}, CHILD_VALUE_COLUMN),
CHILD_LABEL_COLUMN = COALESCE(#{childLabelColumn, jdbcType=VARCHAR}, CHILD_LABEL_COLUMN),
CHILD_ORDER_COLUMN = COALESCE(#{childOrderColumn, jdbcType=VARCHAR}, CHILD_ORDER_COLUMN),
CHILD_ORDER_DIRECTION = COALESCE(#{childOrderDirection, jdbcType=VARCHAR}, CHILD_ORDER_DIRECTION),
EMPTY_PARENT_MESSAGE = COALESCE(#{emptyParentMessage, jdbcType=VARCHAR}, EMPTY_PARENT_MESSAGE),
NO_OPTIONS_MESSAGE = COALESCE(#{noOptionsMessage, jdbcType=VARCHAR}, NO_OPTIONS_MESSAGE),
LOADING_MESSAGE = COALESCE(#{loadingMessage, jdbcType=VARCHAR}, LOADING_MESSAGE),
CLEAR_ON_PARENT_CHANGE = COALESCE(#{clearOnParentChange, jdbcType=VARCHAR}, CLEAR_ON_PARENT_CHANGE),
IS_ACTIVE = COALESCE(#{isActive, jdbcType=VARCHAR}, IS_ACTIVE),
UPDATED_BY = #{userId, jdbcType=VARCHAR},
UPDATED_DATE = CURRENT_TIMESTAMP
UPDATE CASCADING_RELATION
SET
RELATION_NAME = COALESCE(#{relationName, jdbcType=VARCHAR}, RELATION_NAME)
, DESCRIPTION = COALESCE(#{description, jdbcType=VARCHAR}, DESCRIPTION)
, PARENT_TABLE = COALESCE(#{parentTable, jdbcType=VARCHAR}, PARENT_TABLE)
, PARENT_VALUE_COLUMN = COALESCE(#{parentValueColumn, jdbcType=VARCHAR}, PARENT_VALUE_COLUMN)
, PARENT_LABEL_COLUMN = COALESCE(#{parentLabelColumn, jdbcType=VARCHAR}, PARENT_LABEL_COLUMN)
, CHILD_TABLE = COALESCE(#{childTable, jdbcType=VARCHAR}, CHILD_TABLE)
, CHILD_FILTER_COLUMN = COALESCE(#{childFilterColumn, jdbcType=VARCHAR}, CHILD_FILTER_COLUMN)
, CHILD_VALUE_COLUMN = COALESCE(#{childValueColumn, jdbcType=VARCHAR}, CHILD_VALUE_COLUMN)
, CHILD_LABEL_COLUMN = COALESCE(#{childLabelColumn, jdbcType=VARCHAR}, CHILD_LABEL_COLUMN)
, CHILD_ORDER_COLUMN = COALESCE(#{childOrderColumn, jdbcType=VARCHAR}, CHILD_ORDER_COLUMN)
, CHILD_ORDER_DIRECTION = COALESCE(#{childOrderDirection, jdbcType=VARCHAR}, CHILD_ORDER_DIRECTION)
, EMPTY_PARENT_MESSAGE = COALESCE(#{emptyParentMessage, jdbcType=VARCHAR}, EMPTY_PARENT_MESSAGE)
, NO_OPTIONS_MESSAGE = COALESCE(#{noOptionsMessage, jdbcType=VARCHAR}, NO_OPTIONS_MESSAGE)
, LOADING_MESSAGE = COALESCE(#{loadingMessage, jdbcType=VARCHAR}, LOADING_MESSAGE)
, CLEAR_ON_PARENT_CHANGE = COALESCE(#{clearOnParentChange, jdbcType=VARCHAR}, CLEAR_ON_PARENT_CHANGE)
, IS_ACTIVE = COALESCE(#{isActive, jdbcType=VARCHAR}, IS_ACTIVE)
, UPDATED_BY = #{userId, jdbcType=VARCHAR}
, UPDATED_DATE = CURRENT_TIMESTAMP
WHERE RELATION_ID = #{id}
<include refid="common.companyCodeFilter"/>
</update>
<!-- 소프트 삭제: is_active = 'N' -->
<update id="deleteCascadingRelation" parameterType="map">
UPDATE CASCADING_RELATION SET
IS_ACTIVE = 'N',
UPDATED_BY = #{userId, jdbcType=VARCHAR},
UPDATED_DATE = CURRENT_TIMESTAMP
UPDATE CASCADING_RELATION
SET
IS_ACTIVE = 'N'
, UPDATED_BY = #{userId, jdbcType=VARCHAR}
, UPDATED_DATE = CURRENT_TIMESTAMP
WHERE RELATION_ID = #{id}
<include refid="common.companyCodeFilter"/>
</update>
@@ -8,7 +8,7 @@
value_id, table_name, column_name, value_code, value_label, value_order,
parent_value_id, depth, path, description, color, icon,
is_active, is_default, company_code,
created_at, updated_at, created_by, updated_by
CREATED_DATE, UPDATED_DATE, created_by, updated_by
</sql>
<!-- 카테고리 플랫 리스트 조회 (트리/플랫 모두 사용) -->
@@ -65,7 +65,7 @@
icon = COALESCE(#{icon}, icon),
is_active = COALESCE(#{isActive}, is_active),
is_default = COALESCE(#{isDefault}, is_default),
updated_at = NOW(),
UPDATED_DATE = NOW(),
updated_by = #{updatedBy}
WHERE (company_code = #{companyCode} OR company_code = '*')
@@ -139,7 +139,7 @@
<!-- 자식 path 단건 업데이트 -->
<update id="updateCategoryTreeChildPath" parameterType="map">
UPDATE category_values
SET path = #{path}, updated_at = NOW()
SET path = #{path}, UPDATED_DATE = NOW()
WHERE value_id = #{valueId}
</update>
@@ -35,7 +35,7 @@
, COLLECTION_TYPE
, COLLECTION_OPTIONS
, SCHEDULE_CRON
, CASE WHEN IS_ACTIVE THEN 'Y' ELSE 'N' END AS IS_ACTIVE
, CASE WHEN IS_ACTIVE = 'true' THEN 'Y' ELSE 'N' END AS IS_ACTIVE
, DESCRIPTION
, CREATED_BY
, UPDATED_BY
@@ -67,7 +67,7 @@
, COLLECTION_TYPE
, COLLECTION_OPTIONS
, SCHEDULE_CRON
, CASE WHEN IS_ACTIVE THEN 'Y' ELSE 'N' END AS IS_ACTIVE
, CASE WHEN IS_ACTIVE = 'true' THEN 'Y' ELSE 'N' END AS IS_ACTIVE
, DESCRIPTION
, CREATED_BY
, UPDATED_BY
@@ -27,19 +27,19 @@
</if>
</when>
<otherwise>
ORDER BY CREATED_AT DESC
ORDER BY CREATED_DATE DESC
</otherwise>
</choose>
</sql>
<!-- 소프트 삭제 필터 -->
<sql id="notDeleted">
AND DELETED_AT IS NULL
AND DELETED_DATE IS NULL
</sql>
<!-- 감사 필드 (INSERT용) -->
<sql id="auditInsertColumns">
CREATED_BY, CREATED_AT, UPDATED_BY, UPDATED_AT
CREATED_BY, CREATED_DATE, UPDATED_BY, UPDATED_DATE
</sql>
<sql id="auditInsertValues">
#{createdBy}, NOW(), #{updatedBy}, NOW()
@@ -47,7 +47,7 @@
<!-- 감사 필드 (UPDATE용) -->
<sql id="auditUpdateSet">
UPDATED_BY = #{updatedBy}, UPDATED_AT = NOW()
UPDATED_BY = #{updatedBy}, UPDATED_DATE = NOW()
</sql>
<!-- 공통 코드 목록 조회 -->
@@ -79,7 +79,7 @@
FROM ${tableName}
WHERE 1=1
<include refid="companyCodeFilter"/>
ORDER BY CREATED_AT DESC
ORDER BY CREATED_DATE DESC
<include refid="pagination"/>
</select>
@@ -149,6 +149,24 @@
<include refid="common.companyCodeFilter"/>
</select>
<select id="getCommonCodeCategoryDuplicateByField" parameterType="map" resultType="int">
SELECT COUNT(*)
FROM code_category
WHERE 1=1
<include refid="common.companyCodeFilter"/>
<choose>
<when test="field == 'categoryCode'">AND category_code = #{value}</when>
<when test="field == 'categoryName'">AND category_name = #{value}</when>
<when test="field == 'categoryNameEng'">AND category_name_eng = #{value}</when>
<otherwise>AND category_code = #{value}</otherwise>
</choose>
<if test="excludeCode != null and excludeCode != ''">
AND category_code != #{excludeCode}
</if>
</select>
<!-- ═══════════════════════════════════════════════════════════════ -->
<!-- code_info -->
<!-- ═══════════════════════════════════════════════════════════════ -->
@@ -317,6 +335,34 @@
<include refid="common.companyCodeFilter"/>
</select>
<select id="getCommonCodeDuplicateByField" parameterType="map" resultType="int">
SELECT COUNT(*)
FROM code_info
WHERE code_category = #{categoryCode}
<include refid="common.companyCodeFilter"/>
<choose>
<when test="field == 'codeValue'">AND code_value = #{value}</when>
<when test="field == 'codeName'">AND code_name = #{value}</when>
<when test="field == 'codeNameEng'">AND code_name_eng = #{value}</when>
<otherwise>AND code_value = #{value}</otherwise>
</choose>
<if test="excludeCode != null and excludeCode != ''">
AND code_value != #{excludeCode}
</if>
</select>
<select id="getCommonCodeParentDepth" parameterType="map" resultType="int">
SELECT COALESCE(depth, 0)
FROM code_info
WHERE code_category = #{categoryCode}
AND code_value = #{codeValue}
<include refid="common.companyCodeFilter"/>
</select>
<select id="getCommonCodeChildrenCnt" parameterType="map" resultType="int">
SELECT COUNT(*)
@@ -356,6 +402,12 @@
<if test="isActive != null">
AND is_active = #{isActive}
</if>
<if test="parentCodeValue != null">
AND parent_code_value = #{parentCodeValue}
</if>
<if test="depth != null">
AND depth = #{depth}
</if>
ORDER BY depth ASC, sort_order ASC, code_value ASC
</select>
@@ -37,8 +37,8 @@
<insert id="insertDashboard" parameterType="map" useGeneratedKeys="true" keyProperty="id">
INSERT INTO DASHBOARD (
COMPANY_CODE
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{companyCode}
, NOW()
@@ -49,7 +49,7 @@
<update id="updateDashboard" parameterType="map">
UPDATE DASHBOARD
SET
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
</update>
@@ -191,6 +191,16 @@
ORDER BY CREATED_DATE ASC
</select>
<!-- 다이어그램 이름 목록 조회 (복제 시 이름 중복 방지용) -->
<select id="getDiagramNameExists" parameterType="map" resultType="map">
SELECT DISTINCT
RELATIONSHIP_NAME AS diagram_name
FROM TABLE_RELATIONSHIPS
WHERE RELATIONSHIP_NAME LIKE #{pattern}
AND IS_ACTIVE = 'Y'
<include refid="common.companyCodeFilter"/>
</select>
<!-- diagram_id 기준 전체 소프트 삭제 -->
<update id="softDeleteDiagramByDiagramId" parameterType="map">
UPDATE TABLE_RELATIONSHIPS
@@ -220,7 +230,7 @@
, BRIDGE_DATA
, IS_ACTIVE
, CREATED_BY
, CREATED_AT
, CREATED_DATE
) VALUES (
#{relationshipId}
, #{fromTableName}
@@ -246,7 +256,7 @@
WHERE RELATIONSHIP_ID = #{relationshipId}
AND IS_ACTIVE = 'Y'
<include refid="common.companyCodeFilter"/>
ORDER BY CREATED_AT DESC
ORDER BY CREATED_DATE DESC
</select>
<!-- 연결 소프트 삭제 -->
@@ -254,7 +264,7 @@
UPDATE DATA_RELATIONSHIP_BRIDGE
SET
IS_ACTIVE = 'N'
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE BRIDGE_ID = #{bridgeId}
AND IS_ACTIVE = 'Y'
<include refid="common.companyCodeFilter"/>
@@ -14,7 +14,7 @@
<if test="searchTerm != null and searchTerm != ''">
AND DIAGRAM_NAME ILIKE '%' || #{searchTerm} || '%'
</if>
ORDER BY UPDATED_AT DESC
ORDER BY UPDATED_DATE DESC
<include refid="common.pagination"/>
</select>
@@ -56,8 +56,8 @@
, COMPANY_CODE
, CREATED_BY
, UPDATED_BY
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{diagram_name}
, #{relationships}::JSONB
@@ -96,7 +96,7 @@
UPDATE DATAFLOW_DIAGRAMS
<set>
UPDATED_BY = #{updated_by},
UPDATED_AT = NOW(),
UPDATED_DATE = NOW(),
<if test="diagram_name != null">DIAGRAM_NAME = #{diagram_name},</if>
<if test="relationships != null">RELATIONSHIPS = #{relationships}::JSONB,</if>
<if test="updateNodePositions == true">
@@ -34,7 +34,7 @@
<!-- 카테고리 생성 -->
<insert id="insertCategory" parameterType="map">
INSERT INTO db_type_categories
(type_code, display_name, icon, color, sort_order, is_active, created_at, updated_at)
(type_code, display_name, icon, color, sort_order, is_active, CREATED_DATE, UPDATED_DATE)
VALUES
(#{type_code}, #{display_name}, #{icon}, #{color},
#{sort_order, jdbcType=INTEGER}, TRUE, NOW(), NOW())
@@ -49,7 +49,7 @@
<if test="color != null">color = #{color},</if>
<if test="sort_order != null">sort_order = #{sort_order},</if>
<if test="is_active != null">is_active = #{is_active},</if>
updated_at = NOW()
UPDATED_DATE = NOW()
</set>
WHERE type_code = #{typeCode}
</update>
@@ -57,7 +57,7 @@
<!-- 카테고리 비활성화 (소프트 삭제) -->
<update id="deactivateCategory" parameterType="map">
UPDATE db_type_categories
SET is_active = FALSE, updated_at = NOW()
SET is_active = FALSE, UPDATED_DATE = NOW()
WHERE type_code = #{typeCode}
</update>
@@ -85,7 +85,7 @@
WHERE c.is_active = TRUE
GROUP BY c.type_code, c.display_name, c.icon, c.color,
c.sort_order, c.is_active, c.created_at, c.updated_at
c.sort_order, c.is_active, c.CREATED_DATE, c.UPDATED_DATE
ORDER BY c.sort_order ASC
</select>
@@ -93,7 +93,7 @@
<!-- 기본 카테고리 초기화 (ON CONFLICT DO NOTHING) -->
<insert id="insertDefaultCategories">
INSERT INTO db_type_categories
(type_code, display_name, icon, color, sort_order, is_active, created_at, updated_at)
(type_code, display_name, icon, color, sort_order, is_active, CREATED_DATE, UPDATED_DATE)
VALUES
('postgresql', 'PostgreSQL', 'postgresql', '#336791', 1, TRUE, NOW(), NOW()),
('oracle', 'Oracle', 'oracle', '#F80000', 2, TRUE, NOW(), NOW()),
@@ -15,11 +15,11 @@
ESTIMATED_DELIVERY,
DELAY_REASON,
PRIORITY,
CREATED_AT
CREATED_DATE
FROM DELIVERIES
WHERE DELETED_AT IS NULL
WHERE DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
ORDER BY CREATED_AT DESC
ORDER BY CREATED_DATE DESC
</select>
<!-- 지연 배송 목록 조회 -->
@@ -34,10 +34,10 @@
ESTIMATED_DELIVERY,
DELAY_REASON,
PRIORITY,
CREATED_AT
CREATED_DATE
FROM DELIVERIES
WHERE STATUS = 'delayed'
AND DELETED_AT IS NULL
AND DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
ORDER BY ESTIMATED_DELIVERY ASC
</select>
@@ -53,7 +53,7 @@
STATUS,
REPORTED_AT
FROM CUSTOMER_ISSUES
WHERE DELETED_AT IS NULL
WHERE DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
<if test="status != null and status != ''">
AND STATUS = #{status}
@@ -67,17 +67,17 @@
COUNT(*) FILTER (WHERE STATUS = 'in_transit') AS shipped,
COUNT(*) FILTER (WHERE STATUS = 'delivered') AS delivered
FROM DELIVERIES
WHERE DATE(CREATED_AT) = CURRENT_DATE
AND DELETED_AT IS NULL
WHERE DATE(CREATED_DATE) = CURRENT_DATE
AND DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
</select>
<!-- 배송 상태 업데이트 -->
<update id="updateDeliveryStatus" parameterType="map">
UPDATE DELIVERIES
SET STATUS = #{status},
DELAY_REASON = #{delayReason},
UPDATED_AT = NOW()
SET STATUS = #{status}
, DELAY_REASON = #{delayReason}
, UPDATED_DATE = NOW()
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
</update>
@@ -85,8 +85,8 @@
<!-- 고객 이슈 상태 업데이트 -->
<update id="updateCustomerIssueStatus" parameterType="map">
UPDATE CUSTOMER_ISSUES
SET STATUS = #{status},
UPDATED_AT = NOW()
SET STATUS = #{status}
, UPDATED_DATE = NOW()
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
</update>
@@ -60,7 +60,7 @@
COMPANY_NAME,
PARENT_DEPT_CODE,
STATUS,
REGDATE
CREATED_DATE
) VALUES (
#{deptCode},
#{deptName},
@@ -162,7 +162,7 @@
<!-- 부서원 추가 -->
<insert id="insertDeptMember" parameterType="map">
INSERT INTO USER_DEPT (USER_ID, DEPT_CODE, IS_PRIMARY, CREATED_AT)
INSERT INTO USER_DEPT (USER_ID, DEPT_CODE, IS_PRIMARY, CREATED_DATE)
VALUES (#{userId}, #{deptCode}, #{isPrimary}, NOW())
</insert>
@@ -37,7 +37,7 @@
</if>
<include refid="layoutSearchCondition"/>
GROUP BY L.ID, U1.USER_NAME, U2.USER_NAME
ORDER BY L.UPDATED_AT DESC
ORDER BY L.UPDATED_DATE DESC
<include refid="common.pagination"/>
</select>
@@ -66,7 +66,7 @@
SELECT *
FROM DIGITAL_TWIN_OBJECTS
WHERE LAYOUT_ID = #{layoutId}
ORDER BY DISPLAY_ORDER ASC, CREATED_AT ASC
ORDER BY DISPLAY_ORDER ASC, CREATED_DATE ASC
</select>
<!-- ========== 레이아웃 생성 ========== -->
@@ -80,8 +80,8 @@
, HIERARCHY_CONFIG
, CREATED_BY
, UPDATED_BY
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{companyCode}
, #{externalDbConnectionId}
@@ -124,7 +124,7 @@
, HIERARCHY_LEVEL
, PARENT_KEY
, EXTERNAL_KEY
, CREATED_AT
, CREATED_DATE
) VALUES (
#{layoutId}
, #{type}
@@ -166,7 +166,7 @@
, EXTERNAL_DB_CONNECTION_ID = COALESCE(#{externalDbConnectionId}, EXTERNAL_DB_CONNECTION_ID)
, WAREHOUSE_KEY = COALESCE(#{warehouseKey}, WAREHOUSE_KEY)
, UPDATED_BY = COALESCE(#{updatedBy}, UPDATED_BY)
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE ID = #{id}
<if test='companyCode != null and companyCode != "*"'>
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
@@ -209,7 +209,7 @@
WHERE 1=1
<include refid="common.companyCodeFilter"/>
<include refid="templateSearchCondition"/>
ORDER BY UPDATED_AT DESC, NAME ASC
ORDER BY UPDATED_DATE DESC, NAME ASC
<include refid="common.pagination"/>
</select>
@@ -239,9 +239,9 @@
, LAYOUT_TYPE
, CONFIG
, CREATED_BY
, CREATED_AT
, CREATED_DATE
, UPDATED_BY
, UPDATED_AT
, UPDATED_DATE
) VALUES (
#{companyCode}
, #{name}
@@ -37,7 +37,7 @@
</if>
</when>
<otherwise>
ORDER BY REGDATE DESC
ORDER BY CREATED_DATE DESC
</otherwise>
</choose>
<include refid="common.pagination"/>
@@ -110,7 +110,7 @@
, DRIVER_NAME = COALESCE(#{userName}, DRIVER_NAME)
, DRIVER_PHONE = COALESCE(#{phoneNumber}, DRIVER_PHONE)
, BRANCH_NAME = COALESCE(#{branchName}, BRANCH_NAME)
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE USER_ID = #{userId}
</update>
@@ -121,7 +121,7 @@
SET
STATUS = #{status}
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE USER_ID = #{userId}
</update>
@@ -133,7 +133,7 @@
SET
USER_ID = NULL
, STATUS = 'disabled'
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE USER_ID = #{userId}
</update>
@@ -158,8 +158,8 @@
, BRANCH_NAME
, STATUS
, COMPANY_CODE
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{vehicleNumber}
, #{vehicleType}
@@ -11,8 +11,8 @@
, SCREEN_ID
, TABLE_NAME
, FORM_DATA::TEXT AS FORM_DATA
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
, CREATED_BY
, UPDATED_BY
FROM DYNAMIC_FORM_DATA
@@ -25,8 +25,8 @@
, SCREEN_ID
, TABLE_NAME
, FORM_DATA::TEXT AS FORM_DATA
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
, CREATED_BY
, UPDATED_BY
FROM DYNAMIC_FORM_DATA
@@ -36,9 +36,9 @@
</if>
ORDER BY
<choose>
<when test='sortBy == "updated_at"'>UPDATED_AT</when>
<when test='sortBy == "UPDATED_DATE"'>UPDATED_DATE</when>
<when test='sortBy == "id"'>ID</when>
<otherwise>CREATED_AT</otherwise>
<otherwise>CREATED_DATE</otherwise>
</choose>
<choose>
<when test='sortOrder == "asc"'>ASC</when>
@@ -194,7 +194,7 @@
, DEPARTURE_NAME
, DESTINATION_NAME
, RECORDED_AT
, CREATED_AT
, CREATED_DATE
, COMPANY_CODE
FROM VEHICLE_LOCATION_HISTORY
<where>
@@ -29,7 +29,7 @@
, FILE_PATH
, COMPANY_CODE
, WRITER
, REGDATE
, CREATED_DATE
, STATUS
, IS_REPRESENTATIVE
FROM ATTACH_FILE_INFO
@@ -37,7 +37,7 @@
AND STATUS != 'DELETED'
<include refid="common.companyCodeFilter"/>
<include refid="fileSearchCondition"/>
ORDER BY REGDATE DESC
ORDER BY CREATED_DATE DESC
<include refid="common.pagination"/>
</select>
@@ -63,7 +63,7 @@
, FILE_PATH
, COMPANY_CODE
, WRITER
, REGDATE
, CREATED_DATE
, STATUS
, IS_REPRESENTATIVE
FROM ATTACH_FILE_INFO
@@ -85,7 +85,7 @@
, FILE_PATH
, COMPANY_CODE
, WRITER
, REGDATE
, CREATED_DATE
, STATUS
, PARENT_TARGET_OBJID
, IS_REPRESENTATIVE
@@ -139,14 +139,14 @@
, FILE_PATH
, COMPANY_CODE
, WRITER
, REGDATE
, CREATED_DATE
, STATUS
, IS_REPRESENTATIVE
FROM ATTACH_FILE_INFO
WHERE TARGET_OBJID LIKE #{targetObjid} || '%'
AND STATUS = 'ACTIVE'
<include refid="common.companyCodeFilter"/>
ORDER BY REGDATE DESC
ORDER BY CREATED_DATE DESC
</select>
</mapper>
@@ -18,7 +18,7 @@
<if test="isActive != null">
AND IS_ACTIVE = #{isActive}
</if>
ORDER BY CREATED_AT DESC
ORDER BY CREATED_DATE DESC
</select>
<select id="getFlowDefinitionInfo" parameterType="map" resultType="map">
@@ -45,8 +45,8 @@
, IS_ACTIVE
, CREATED_BY
, UPDATED_BY
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{name}
, #{description}
@@ -72,7 +72,7 @@
<update id="updateFlowDefinition" parameterType="map">
UPDATE FLOW_DEFINITIONS
<set>
UPDATED_AT = NOW(),
UPDATED_DATE = NOW(),
<if test="name != null">NAME = #{name},</if>
<if test="description != null">DESCRIPTION = #{description},</if>
<if test="isActive != null">IS_ACTIVE = #{isActive},</if>
@@ -132,8 +132,8 @@
, INTEGRATION_TYPE
, INTEGRATION_CONFIG
, DISPLAY_CONFIG
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{flowDefinitionId}
, #{stepName}
@@ -171,7 +171,7 @@
<update id="updateFlowStep" parameterType="map">
UPDATE FLOW_STEPS
<set>
UPDATED_AT = NOW(),
UPDATED_DATE = NOW(),
<if test="stepName != null">STEP_NAME = #{stepName},</if>
<if test="stepOrder != null">STEP_ORDER = #{stepOrder},</if>
<if test="tableName != null">TABLE_NAME = #{tableName},</if>
@@ -221,7 +221,7 @@
, FROM_STEP_ID
, TO_STEP_ID
, LABEL
, CREATED_AT
, CREATED_DATE
) VALUES (
#{flowDefinitionId}
, #{fromStepId}
@@ -292,14 +292,14 @@
FROM FLOW_STEP_AUDIT_LOGS
WHERE FLOW_DEFINITION_ID = #{flowId}
AND RECORD_ID = #{recordId}
ORDER BY CREATED_AT DESC
ORDER BY CREATED_DATE DESC
</select>
<select id="getFlowAuditLogList" parameterType="map" resultType="map">
SELECT *
FROM FLOW_STEP_AUDIT_LOGS
WHERE FLOW_DEFINITION_ID = #{flowId}
ORDER BY CREATED_AT DESC
ORDER BY CREATED_DATE DESC
<if test="limit != null">
LIMIT #{limit}
</if>
@@ -316,7 +316,7 @@
, MOVED_BY
, NOTE
, METADATA
, CREATED_AT
, CREATED_DATE
) VALUES (
#{flowDefinitionId}
, #{recordId}
@@ -24,8 +24,8 @@
, IS_ACTIVE
, CREATED_BY
, UPDATED_BY
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
FROM FLOW_EXTERNAL_DB_CONNECTION
<where>
<if test="activeOnly == true">
@@ -51,8 +51,8 @@
, IS_ACTIVE
, CREATED_BY
, UPDATED_BY
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
FROM FLOW_EXTERNAL_DB_CONNECTION
WHERE ID = #{id}
</select>
@@ -102,7 +102,7 @@
<if test="connectionOptions != null">CONNECTION_OPTIONS = #{connectionOptions}::JSONB,</if>
<if test="isActive != null">IS_ACTIVE = #{isActive},</if>
UPDATED_BY = #{updatedBy},
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
</set>
WHERE ID = #{id}
</update>
@@ -10,7 +10,19 @@
</sql>
<select id="getMailAccountFileList" parameterType="map" resultType="map">
SELECT *
SELECT
ID
, COMPANY_CODE
, NAME
, EMAIL
, SMTP_HOST
, SMTP_PORT
, SMTP_SECURE
, SMTP_USERNAME
, DAILY_LIMIT
, STATUS
, CREATED_DATE
, UPDATED_DATE
FROM MAIL_ACCOUNT_FILE
WHERE 1=1
<include refid="common.companyCodeFilter"/>
@@ -28,7 +40,20 @@
</select>
<select id="getMailAccountFileInfo" parameterType="map" resultType="map">
SELECT *
SELECT
ID
, COMPANY_CODE
, NAME
, EMAIL
, SMTP_HOST
, SMTP_PORT
, SMTP_SECURE
, SMTP_USERNAME
, SMTP_PASSWORD
, DAILY_LIMIT
, STATUS
, CREATED_DATE
, UPDATED_DATE
FROM MAIL_ACCOUNT_FILE
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
@@ -36,35 +61,47 @@
<insert id="insertMailAccountFile" parameterType="map" useGeneratedKeys="true" keyProperty="id">
INSERT INTO MAIL_ACCOUNT_FILE (
COMPANY_CODE, NAME, EMAIL, SMTP_HOST, SMTP_PORT, SMTP_SECURE,
SMTP_USERNAME, SMTP_PASSWORD, DAILY_LIMIT, STATUS, CREATED_AT, UPDATED_AT
COMPANY_CODE
, NAME
, EMAIL
, SMTP_HOST
, SMTP_PORT
, SMTP_SECURE
, SMTP_USERNAME
, SMTP_PASSWORD
, DAILY_LIMIT
, STATUS
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{companyCode},
#{name, jdbcType=VARCHAR},
#{email, jdbcType=VARCHAR},
#{smtpHost, jdbcType=VARCHAR},
#{smtpPort, jdbcType=INTEGER},
#{smtpSecure, jdbcType=BOOLEAN},
#{smtpUsername, jdbcType=VARCHAR},
#{smtpPassword, jdbcType=VARCHAR},
#{dailyLimit, jdbcType=INTEGER},
#{status, jdbcType=VARCHAR},
NOW(), NOW()
#{companyCode}
, #{name, jdbcType=VARCHAR}
, #{email, jdbcType=VARCHAR}
, #{smtpHost, jdbcType=VARCHAR}
, #{smtpPort, jdbcType=INTEGER}
, #{smtpSecure, jdbcType=BOOLEAN}
, #{smtpUsername, jdbcType=VARCHAR}
, #{smtpPassword, jdbcType=VARCHAR}
, #{dailyLimit, jdbcType=INTEGER}
, #{status, jdbcType=VARCHAR}
, NOW()
, NOW()
)
</insert>
<update id="updateMailAccountFile" parameterType="map">
UPDATE MAIL_ACCOUNT_FILE SET
NAME = COALESCE(#{name, jdbcType=VARCHAR}, NAME),
EMAIL = COALESCE(#{email, jdbcType=VARCHAR}, EMAIL),
SMTP_HOST = COALESCE(#{smtpHost, jdbcType=VARCHAR}, SMTP_HOST),
SMTP_PORT = COALESCE(#{smtpPort, jdbcType=INTEGER}, SMTP_PORT),
SMTP_SECURE = COALESCE(#{smtpSecure, jdbcType=BOOLEAN}, SMTP_SECURE),
SMTP_USERNAME = COALESCE(#{smtpUsername, jdbcType=VARCHAR}, SMTP_USERNAME),
SMTP_PASSWORD = COALESCE(#{smtpPassword, jdbcType=VARCHAR}, SMTP_PASSWORD),
DAILY_LIMIT = COALESCE(#{dailyLimit, jdbcType=INTEGER}, DAILY_LIMIT),
STATUS = COALESCE(#{status, jdbcType=VARCHAR}, STATUS),
UPDATED_AT = NOW()
UPDATE MAIL_ACCOUNT_FILE
SET
NAME = COALESCE(#{name, jdbcType=VARCHAR}, NAME)
, EMAIL = COALESCE(#{email, jdbcType=VARCHAR}, EMAIL)
, SMTP_HOST = COALESCE(#{smtpHost, jdbcType=VARCHAR}, SMTP_HOST)
, SMTP_PORT = COALESCE(#{smtpPort, jdbcType=INTEGER}, SMTP_PORT)
, SMTP_SECURE = COALESCE(#{smtpSecure, jdbcType=BOOLEAN}, SMTP_SECURE)
, SMTP_USERNAME = COALESCE(#{smtpUsername, jdbcType=VARCHAR}, SMTP_USERNAME)
, SMTP_PASSWORD = COALESCE(#{smtpPassword, jdbcType=VARCHAR}, SMTP_PASSWORD)
, DAILY_LIMIT = COALESCE(#{dailyLimit, jdbcType=INTEGER}, DAILY_LIMIT)
, STATUS = COALESCE(#{status, jdbcType=VARCHAR}, STATUS)
, UPDATED_DATE = NOW()
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
</update>
@@ -21,12 +21,21 @@
<select id="getMailReceiveBasicList" parameterType="map" resultType="map">
SELECT
ID, COMPANY_CODE, ACCOUNT_ID, SEQNO, SUBJECT,
FROM_ADDRESS, TO_ADDRESS, CC_ADDRESS, RECEIVED_DATE,
IS_READ, HAS_ATTACHMENT, CREATED_AT
ID
, COMPANY_CODE
, ACCOUNT_ID
, SEQNO
, SUBJECT
, FROM_ADDRESS
, TO_ADDRESS
, CC_ADDRESS
, RECEIVED_DATE
, IS_READ
, HAS_ATTACHMENT
, CREATED_DATE
FROM MAIL_RECEIVE_BASIC
WHERE ACCOUNT_ID = #{accountId}
AND DELETED_AT IS NULL
AND DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
<include refid="mailReceiveBasicSearchCondition"/>
<include refid="common.dynamicOrderBy"/>
@@ -37,7 +46,7 @@
SELECT COUNT(*)
FROM MAIL_RECEIVE_BASIC
WHERE ACCOUNT_ID = #{accountId}
AND DELETED_AT IS NULL
AND DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
<include refid="mailReceiveBasicSearchCondition"/>
</select>
@@ -46,35 +55,50 @@
SELECT COUNT(*)
FROM MAIL_RECEIVE_BASIC
WHERE DATE(RECEIVED_DATE) = CURRENT_DATE
AND DELETED_AT IS NULL
AND DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
</select>
<select id="getMailReceiveBasicInfo" parameterType="map" resultType="map">
SELECT
ID, COMPANY_CODE, ACCOUNT_ID, SEQNO, SUBJECT,
FROM_ADDRESS, TO_ADDRESS, CC_ADDRESS, BCC_ADDRESS,
RECEIVED_DATE, IS_READ, HAS_ATTACHMENT,
BODY_TEXT, BODY_HTML, CREATED_AT
ID
, COMPANY_CODE
, ACCOUNT_ID
, SEQNO
, SUBJECT
, FROM_ADDRESS
, TO_ADDRESS
, CC_ADDRESS
, BCC_ADDRESS
, RECEIVED_DATE
, IS_READ
, HAS_ATTACHMENT
, BODY_TEXT
, BODY_HTML
, CREATED_DATE
FROM MAIL_RECEIVE_BASIC
WHERE ACCOUNT_ID = #{accountId}
AND SEQNO = #{seqno}
AND DELETED_AT IS NULL
AND DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
</select>
<update id="updateMailReceiveBasicAsRead" parameterType="map">
UPDATE MAIL_RECEIVE_BASIC
SET IS_READ = TRUE, UPDATED_AT = NOW()
SET
IS_READ = TRUE
, UPDATED_DATE = NOW()
WHERE ACCOUNT_ID = #{accountId}
AND SEQNO = #{seqno}
AND DELETED_AT IS NULL
AND DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
</update>
<update id="deleteMailReceiveBasic" parameterType="map">
UPDATE MAIL_RECEIVE_BASIC
SET DELETED_AT = NOW(), UPDATED_AT = NOW()
SET
DELETED_DATE = NOW()
, UPDATED_DATE = NOW()
WHERE ACCOUNT_ID = #{accountId}
AND SEQNO = #{seqno}
<include refid="common.companyCodeFilter"/>
@@ -82,14 +106,19 @@
<select id="getMailReceiveBasicAttachment" parameterType="map" resultType="map">
SELECT
A.ID, A.MAIL_ID, A.FILE_NAME, A.CONTENT_TYPE,
A.FILE_SIZE, A.CONTENT_DATA, A.ATTACH_INDEX
A.ID
, A.MAIL_ID
, A.FILE_NAME
, A.CONTENT_TYPE
, A.FILE_SIZE
, A.CONTENT_DATA
, A.ATTACH_INDEX
FROM MAIL_RECEIVE_ATTACHMENT A
INNER JOIN MAIL_RECEIVE_BASIC M ON A.MAIL_ID = M.ID
WHERE M.ACCOUNT_ID = #{accountId}
AND M.SEQNO = #{seqno}
AND A.ATTACH_INDEX = #{attachIndex}
AND M.DELETED_AT IS NULL
AND M.DELETED_DATE IS NULL
<if test="companyCode != null and companyCode != &quot;*&quot;">
AND (M.COMPANY_CODE = #{companyCode} OR M.COMPANY_CODE = '*')
</if>
@@ -97,8 +126,14 @@
<select id="getMailReceiveBasicAccountInfo" parameterType="map" resultType="map">
SELECT
ID, COMPANY_CODE, EMAIL_ADDRESS, IMAP_HOST, IMAP_PORT,
IMAP_SSL, IMAP_USERNAME, IMAP_PASSWORD
ID
, COMPANY_CODE
, EMAIL_ADDRESS
, IMAP_HOST
, IMAP_PORT
, IMAP_SSL
, IMAP_USERNAME
, IMAP_PASSWORD
FROM MAIL_ACCOUNTS
WHERE ID = #{accountId}
<include refid="common.companyCodeFilter"/>
@@ -12,10 +12,10 @@
<!-- 삭제 상태 필터 -->
<choose>
<when test="onlyDeleted != null and onlyDeleted == true">
AND DELETED_AT IS NOT NULL
AND DELETED_DATE IS NOT NULL
</when>
<when test="includeDeleted == null or includeDeleted == false">
AND DELETED_AT IS NULL
AND DELETED_DATE IS NULL
</when>
<!-- includeDeleted == true → 필터 없음 -->
</choose>
@@ -50,7 +50,28 @@
목록 조회
──────────────────────────────────────────────────────── -->
<select id="getMailSentHistoryList" parameterType="map" resultType="map">
SELECT *
SELECT
ID
, COMPANY_CODE
, ACCOUNT_ID
, ACCOUNT_NAME
, ACCOUNT_EMAIL
, TO_EMAILS
, CC_EMAILS
, BCC_EMAILS
, SUBJECT
, TEMPLATE_ID
, TEMPLATE_NAME
, STATUS
, MESSAGE_ID
, ERROR_MESSAGE
, ACCEPTED
, REJECTED
, IS_DRAFT
, SENT_AT
, DELETED_DATE
, CREATED_DATE
, UPDATED_DATE
FROM MAIL_SENT_HISTORY
WHERE 1=1
<include refid="common.companyCodeFilter"/>
@@ -71,7 +92,30 @@
단건 조회
──────────────────────────────────────────────────────── -->
<select id="getMailSentHistoryInfo" parameterType="map" resultType="map">
SELECT *
SELECT
ID
, COMPANY_CODE
, ACCOUNT_ID
, ACCOUNT_NAME
, ACCOUNT_EMAIL
, TO_EMAILS
, CC_EMAILS
, BCC_EMAILS
, SUBJECT
, HTML_CONTENT
, TEMPLATE_ID
, TEMPLATE_NAME
, ATTACHMENTS
, STATUS
, MESSAGE_ID
, ERROR_MESSAGE
, ACCEPTED
, REJECTED
, IS_DRAFT
, SENT_AT
, DELETED_DATE
, CREATED_DATE
, UPDATED_DATE
FROM MAIL_SENT_HISTORY
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
@@ -82,17 +126,51 @@
──────────────────────────────────────────────────────── -->
<insert id="insertMailSentHistory" parameterType="map">
INSERT INTO MAIL_SENT_HISTORY (
ID, COMPANY_CODE, ACCOUNT_ID, ACCOUNT_NAME, ACCOUNT_EMAIL,
TO_EMAILS, CC_EMAILS, BCC_EMAILS,
SUBJECT, HTML_CONTENT, TEMPLATE_ID, TEMPLATE_NAME, ATTACHMENTS,
STATUS, MESSAGE_ID, ERROR_MESSAGE, ACCEPTED, REJECTED,
IS_DRAFT, SENT_AT, CREATED_AT, UPDATED_AT
ID
, COMPANY_CODE
, ACCOUNT_ID
, ACCOUNT_NAME
, ACCOUNT_EMAIL
, TO_EMAILS
, CC_EMAILS
, BCC_EMAILS
, SUBJECT
, HTML_CONTENT
, TEMPLATE_ID
, TEMPLATE_NAME
, ATTACHMENTS
, STATUS
, MESSAGE_ID
, ERROR_MESSAGE
, ACCEPTED
, REJECTED
, IS_DRAFT
, SENT_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{id}, #{companyCode}, #{accountId}, #{accountName}, #{accountEmail},
#{toEmails}, #{ccEmails}, #{bccEmails},
#{subject}, #{htmlContent}, #{templateId}, #{templateName}, #{attachments},
#{status}, #{messageId}, #{errorMessage}, #{accepted}, #{rejected},
#{isDraft}, #{sentAt}, NOW(), NOW()
#{id}
, #{companyCode}
, #{accountId}
, #{accountName}
, #{accountEmail}
, #{toEmails}
, #{ccEmails}
, #{bccEmails}
, #{subject}
, #{htmlContent}
, #{templateId}
, #{templateName}
, #{attachments}
, #{status}
, #{messageId}
, #{errorMessage}
, #{accepted}
, #{rejected}
, #{isDraft}
, #{sentAt}
, NOW()
, NOW()
)
</insert>
@@ -116,31 +194,35 @@
<if test="templateId != null">TEMPLATE_ID = #{templateId},</if>
<if test="templateName != null">TEMPLATE_NAME = #{templateName},</if>
<if test="errorMessage != null">ERROR_MESSAGE = #{errorMessage},</if>
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
</set>
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
</update>
<!-- ────────────────────────────────────────────────────────
소프트 삭제 (deleted_at 세팅)
소프트 삭제 (DELETED_DATE 세팅)
──────────────────────────────────────────────────────── -->
<update id="softDeleteMailSentHistory" parameterType="map">
UPDATE MAIL_SENT_HISTORY
SET DELETED_AT = NOW(), UPDATED_AT = NOW()
SET
DELETED_DATE = NOW()
, UPDATED_DATE = NOW()
WHERE ID = #{id}
AND DELETED_AT IS NULL
AND DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
</update>
<!-- ────────────────────────────────────────────────────────
복구 (deleted_at 초기화)
복구 (DELETED_DATE 초기화)
──────────────────────────────────────────────────────── -->
<update id="restoreMailSentHistory" parameterType="map">
UPDATE MAIL_SENT_HISTORY
SET DELETED_AT = NULL, UPDATED_AT = NOW()
SET
DELETED_DATE = NULL
, UPDATED_DATE = NOW()
WHERE ID = #{id}
AND DELETED_AT IS NOT NULL
AND DELETED_DATE IS NOT NULL
<include refid="common.companyCodeFilter"/>
</update>
@@ -158,12 +240,12 @@
──────────────────────────────────────────────────────── -->
<update id="bulkSoftDeleteMailSentHistory" parameterType="map">
UPDATE MAIL_SENT_HISTORY
SET DELETED_AT = NOW(), UPDATED_AT = NOW()
SET DELETED_DATE = NOW(), UPDATED_DATE = NOW()
WHERE ID IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
AND DELETED_AT IS NULL
AND DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
</update>
@@ -172,12 +254,12 @@
──────────────────────────────────────────────────────── -->
<update id="bulkRestoreMailSentHistory" parameterType="map">
UPDATE MAIL_SENT_HISTORY
SET DELETED_AT = NULL, UPDATED_AT = NOW()
SET DELETED_DATE = NULL, UPDATED_DATE = NOW()
WHERE ID IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
AND DELETED_AT IS NOT NULL
AND DELETED_DATE IS NOT NULL
<include refid="common.companyCodeFilter"/>
</update>
@@ -205,7 +287,7 @@
COUNT(CASE WHEN SENT_AT &gt;= CURRENT_DATE THEN 1 END) AS TODAY_COUNT,
COUNT(CASE WHEN SENT_AT &gt;= DATE_TRUNC('month', NOW()) THEN 1 END) AS THIS_MONTH_COUNT
FROM MAIL_SENT_HISTORY
WHERE DELETED_AT IS NULL
WHERE DELETED_DATE IS NULL
<include refid="common.companyCodeFilter"/>
<if test="accountId != null and accountId != ''">
AND ACCOUNT_ID = #{accountId}
@@ -13,7 +13,14 @@
</sql>
<select id="getMailTemplateFileList" parameterType="map" resultType="map">
SELECT *
SELECT
ID
, COMPANY_CODE
, NAME
, SUBJECT
, CATEGORY
, CREATED_DATE
, UPDATED_DATE
FROM MAIL_TEMPLATE_FILE
WHERE 1=1
<include refid="common.companyCodeFilter"/>
@@ -31,7 +38,17 @@
</select>
<select id="getMailTemplateFileInfo" parameterType="map" resultType="map">
SELECT *
SELECT
ID
, COMPANY_CODE
, NAME
, SUBJECT
, COMPONENTS
, QUERY_CONFIG
, RECIPIENT_CONFIG
, CATEGORY
, CREATED_DATE
, UPDATED_DATE
FROM MAIL_TEMPLATE_FILE
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
@@ -39,10 +56,25 @@
<insert id="insertMailTemplateFile" parameterType="map" useGeneratedKeys="true" keyProperty="id">
INSERT INTO MAIL_TEMPLATE_FILE (
COMPANY_CODE, NAME, SUBJECT, COMPONENTS, QUERY_CONFIG, RECIPIENT_CONFIG, CATEGORY, CREATED_AT, UPDATED_AT
COMPANY_CODE
, NAME
, SUBJECT
, COMPONENTS
, QUERY_CONFIG
, RECIPIENT_CONFIG
, CATEGORY
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{companyCode}, #{name}, #{subject}, CAST(#{components} AS JSONB),
CAST(#{queryConfig} AS JSONB), CAST(#{recipientConfig} AS JSONB), #{category}, NOW(), NOW()
#{companyCode}
, #{name}
, #{subject}
, CAST(#{components} AS JSONB)
, CAST(#{queryConfig} AS JSONB)
, CAST(#{recipientConfig} AS JSONB)
, #{category}
, NOW()
, NOW()
)
</insert>
@@ -55,7 +87,7 @@
<if test="queryConfig != null">QUERY_CONFIG = CAST(#{queryConfig} AS JSONB),</if>
<if test="recipientConfig != null">RECIPIENT_CONFIG = CAST(#{recipientConfig} AS JSONB),</if>
<if test="category != null">CATEGORY = #{category},</if>
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
</set>
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
@@ -35,13 +35,13 @@
</select>
<insert id="insertMultiConnection" parameterType="map" useGeneratedKeys="true" keyProperty="id">
INSERT INTO MULTI_CONNECTION (COMPANY_CODE, CREATED_AT, UPDATED_AT)
INSERT INTO MULTI_CONNECTION (COMPANY_CODE, CREATED_DATE, UPDATED_DATE)
VALUES (#{companyCode}, NOW(), NOW())
</insert>
<update id="updateMultiConnection" parameterType="map">
UPDATE MULTI_CONNECTION
SET UPDATED_AT = NOW()
SET UPDATED_DATE = NOW()
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
</update>
@@ -6,7 +6,7 @@
<!--
node_flows 테이블
컬럼: flow_id (PK, serial), flow_name, flow_description, flow_data (JSONB),
company_code, created_at, updated_at
company_code, CREATED_DATE, UPDATED_DATE
Node 코드와 동일한 camelCase 응답 키를 위해 AS "camelCase" 별칭 사용
-->
@@ -20,14 +20,14 @@
, FLOW_NAME AS "flowName"
, FLOW_DESCRIPTION AS "flowDescription"
, COMPANY_CODE AS "companyCode"
, CREATED_AT AS "createdAt"
, UPDATED_AT AS "updatedAt"
, CREATED_DATE AS "createdAt"
, UPDATED_DATE AS "updatedAt"
FROM NODE_FLOWS
WHERE 1=1
<if test="companyCode != null and companyCode != &quot;*&quot;">
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</if>
ORDER BY UPDATED_AT DESC
ORDER BY UPDATED_DATE DESC
</select>
<!-- ────────────────────────────────────────────────────── -->
@@ -39,8 +39,8 @@
, FLOW_NAME AS "flowName"
, FLOW_DESCRIPTION AS "flowDescription"
, FLOW_DATA AS "flowData"
, CREATED_AT AS "createdAt"
, UPDATED_AT AS "updatedAt"
, CREATED_DATE AS "createdAt"
, UPDATED_DATE AS "updatedAt"
FROM NODE_FLOWS
WHERE FLOW_ID = #{flowId}
<include refid="common.companyCodeFilter"/>
@@ -97,7 +97,7 @@
FLOW_NAME = #{flowName}
, FLOW_DESCRIPTION = #{flowDescription}
, FLOW_DATA = #{flowData}::JSONB
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE FLOW_ID = #{flowId}
</update>
@@ -16,8 +16,8 @@
category_column AS category_column,
category_value_id AS category_value_id,
created_by AS created_by,
created_at AS created_at,
updated_at AS updated_at
CREATED_DATE AS CREATED_DATE,
UPDATED_DATE AS UPDATED_DATE
</sql>
<sql id="partColumns">
@@ -42,7 +42,7 @@
<otherwise>AND (company_code = #{companyCode} OR company_code = '*')</otherwise>
</choose>
ORDER BY created_at DESC
ORDER BY CREATED_DATE DESC
</select>
<select id="getRuleById" parameterType="map" resultType="map">
@@ -61,7 +61,7 @@
INSERT INTO numbering_rules (
rule_id, rule_name, description, separator, reset_period,
current_sequence, table_name, column_name, company_code,
category_column, category_value_id, created_by, created_at, updated_at
category_column, category_value_id, created_by, CREATED_DATE, UPDATED_DATE
) VALUES (
#{ruleId},
#{ruleName},
@@ -90,7 +90,7 @@
column_name = COALESCE(#{columnName, jdbcType=VARCHAR}, column_name),
category_column = COALESCE(#{categoryColumn, jdbcType=VARCHAR}, category_column),
category_value_id = COALESCE(#{categoryValueId, jdbcType=INTEGER}, category_value_id),
updated_at = NOW()
UPDATED_DATE = NOW()
WHERE rule_id = #{ruleId}
AND (company_code = #{companyCode} OR company_code = '*')
@@ -122,7 +122,7 @@
<insert id="insertRulePart" parameterType="map">
INSERT INTO numbering_rule_parts (
rule_id, part_order, part_type, generation_method,
auto_config, manual_config, company_code, created_at
auto_config, manual_config, company_code, CREATED_DATE
) VALUES (
#{ruleId},
#{order},
@@ -164,7 +164,7 @@
<update id="updateCurrentSequenceInRule" parameterType="map">
UPDATE numbering_rules
SET current_sequence = GREATEST(COALESCE(current_sequence, '0'), #{currentSequence}),
updated_at = NOW()
UPDATED_DATE = NOW()
WHERE rule_id = #{ruleId}
AND (company_code = #{companyCode} OR company_code = '*')
@@ -183,7 +183,7 @@
<otherwise>AND (company_code = #{companyCode} OR company_code = '*')</otherwise>
</choose>
ORDER BY created_at DESC
ORDER BY CREATED_DATE DESC
</select>
<select id="getAvailableRulesForScreen" parameterType="map" resultType="map">
@@ -200,7 +200,7 @@
AND table_name = #{tableName}
</if>
ORDER BY created_at DESC
ORDER BY CREATED_DATE DESC
</select>
<select id="getRuleByColumn" parameterType="map" resultType="map">
@@ -218,8 +218,8 @@
r.category_value_id AS category_value_id,
cv.value_label AS category_value_label,
r.created_by AS created_by,
r.created_at AS created_at,
r.updated_at AS updated_at
r.CREATED_DATE AS CREATED_DATE,
r.UPDATED_DATE AS UPDATED_DATE
FROM numbering_rules r
@@ -247,8 +247,8 @@
r.category_value_id AS category_value_id,
cv.value_label AS category_value_label,
r.created_by AS created_by,
r.created_at AS created_at,
r.updated_at AS updated_at
r.CREATED_DATE AS CREATED_DATE,
r.UPDATED_DATE AS UPDATED_DATE
FROM numbering_rules r
@@ -259,7 +259,7 @@
AND (r.column_name IS NULL OR r.column_name = '')
AND r.category_value_id IS NULL
ORDER BY r.updated_at DESC
ORDER BY r.UPDATED_DATE DESC
LIMIT 1
</select>
@@ -280,7 +280,7 @@
WHERE (company_code = #{companyCode} OR company_code = '*')
ORDER BY created_at
ORDER BY CREATED_DATE
</select>
<select id="getRulePartsForCopy" parameterType="map" resultType="map">
@@ -35,13 +35,13 @@
</select>
<insert id="insertOpenApiProxy" parameterType="map" useGeneratedKeys="true" keyProperty="id">
INSERT INTO OPEN_API_PROXY (COMPANY_CODE, CREATED_AT, UPDATED_AT)
INSERT INTO OPEN_API_PROXY (COMPANY_CODE, CREATED_DATE, UPDATED_DATE)
VALUES (#{companyCode}, NOW(), NOW())
</insert>
<update id="updateOpenApiProxy" parameterType="map">
UPDATE OPEN_API_PROXY
SET UPDATED_AT = NOW()
SET UPDATED_DATE = NOW()
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
</update>
@@ -106,7 +106,7 @@
<insert id="insertProcessWorkStandardWorkItem" parameterType="map" useGeneratedKeys="true" keyProperty="id">
INSERT INTO process_work_item (
company_code, routing_detail_id, work_item_code, work_item_name,
sequence_no, work_time, description, created_at, updated_at
sequence_no, work_time, description, CREATED_DATE, UPDATED_DATE
) VALUES (
#{companyCode}, #{routingDetailId}, #{workItemCode}, #{workItemName},
COALESCE(#{sequenceNo}, 0), COALESCE(#{workTime}, 0), #{description}, NOW(), NOW()
@@ -120,7 +120,7 @@
<if test="sequenceNo != null">sequence_no = #{sequenceNo},</if>
<if test="workTime != null">work_time = #{workTime},</if>
<if test="description != null">description = #{description},</if>
updated_at = NOW()
UPDATED_DATE = NOW()
</set>
WHERE id = #{id}
@@ -152,7 +152,7 @@
<insert id="insertProcessWorkStandardWorkItemDetail" parameterType="map" useGeneratedKeys="true" keyProperty="id">
INSERT INTO process_work_item_detail (
company_code, work_item_id, detail_no, content,
standard_time, quality_point, safety_note, created_at, updated_at
standard_time, quality_point, safety_note, CREATED_DATE, UPDATED_DATE
) VALUES (
#{companyCode}, #{workItemId}, COALESCE(#{detailNo}, 1), #{content},
COALESCE(#{standardTime}, 0), #{qualityPoint}, #{safetyNote}, NOW(), NOW()
@@ -167,7 +167,7 @@
<if test="standardTime != null">standard_time = #{standardTime},</if>
<if test="qualityPoint != null">quality_point = #{qualityPoint},</if>
<if test="safetyNote != null">safety_note = #{safetyNote},</if>
updated_at = NOW()
UPDATED_DATE = NOW()
</set>
WHERE id = #{id}
@@ -202,7 +202,7 @@
<insert id="insertProcessWorkStandardRegisteredItem" parameterType="map" useGeneratedKeys="true" keyProperty="id">
INSERT INTO process_registered_item (
company_code, screen_code, item_code, routing_id, created_at, updated_at
company_code, screen_code, item_code, routing_id, CREATED_DATE, UPDATED_DATE
) VALUES (
#{companyCode}, #{screenCode}, #{itemCode}, #{routingId}, NOW(), NOW()
)
@@ -210,7 +210,7 @@
<insert id="insertProcessWorkStandardRegisteredItemBatch" parameterType="map">
INSERT INTO process_registered_item (
company_code, screen_code, item_code, routing_id, created_at, updated_at
company_code, screen_code, item_code, routing_id, CREATED_DATE, UPDATED_DATE
) VALUES
<foreach collection="items" item="item" separator=",">
(#{companyCode}, #{item.screenCode}, #{item.itemCode}, #{item.routingId}, NOW(), NOW())
@@ -28,9 +28,9 @@
, COMPANY_CODE
, DESCRIPTION
, USE_YN
, CREATED_AT
, CREATED_DATE
, CREATED_BY
, UPDATED_AT
, UPDATED_DATE
, UPDATED_BY
FROM REPORT_MASTER
WHERE 1=1
@@ -58,9 +58,9 @@
, COMPANY_CODE
, DESCRIPTION
, USE_YN
, CREATED_AT
, CREATED_DATE
, CREATED_BY
, UPDATED_AT
, UPDATED_DATE
, UPDATED_BY
FROM REPORT_MASTER
WHERE REPORT_ID = #{reportId}
@@ -94,7 +94,7 @@
<update id="updateReport" parameterType="map">
UPDATE REPORT_MASTER
SET
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
<if test="reportNameKor != null">, REPORT_NAME_KOR = #{reportNameKor}</if>
<if test="reportNameEng != null">, REPORT_NAME_ENG = #{reportNameEng}</if>
<if test="reportType != null">, REPORT_TYPE = #{reportType}</if>
@@ -125,9 +125,9 @@
, MARGIN_LEFT
, MARGIN_RIGHT
, COMPONENTS::TEXT AS COMPONENTS
, CREATED_AT
, CREATED_DATE
, CREATED_BY
, UPDATED_AT
, UPDATED_DATE
, UPDATED_BY
FROM REPORT_LAYOUT
WHERE REPORT_ID = #{reportId}
@@ -172,7 +172,7 @@
, MARGIN_LEFT = #{marginLeft, jdbcType=NUMERIC}
, MARGIN_RIGHT = #{marginRight, jdbcType=NUMERIC}
, COMPONENTS = #{components}::jsonb
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
, UPDATED_BY = #{updatedBy, jdbcType=VARCHAR}
WHERE REPORT_ID = #{reportId}
</update>
@@ -194,13 +194,13 @@
, PARAMETERS::TEXT AS PARAMETERS
, EXTERNAL_CONNECTION_ID
, DISPLAY_ORDER
, CREATED_AT
, CREATED_DATE
, CREATED_BY
, UPDATED_AT
, UPDATED_DATE
, UPDATED_BY
FROM REPORT_QUERY
WHERE REPORT_ID = #{reportId}
ORDER BY DISPLAY_ORDER ASC, CREATED_AT ASC
ORDER BY DISPLAY_ORDER ASC, CREATED_DATE ASC
</select>
<select id="getReportQueryById" parameterType="map" resultType="map">
@@ -213,9 +213,9 @@
, PARAMETERS::TEXT AS PARAMETERS
, EXTERNAL_CONNECTION_ID
, DISPLAY_ORDER
, CREATED_AT
, CREATED_DATE
, CREATED_BY
, UPDATED_AT
, UPDATED_DATE
, UPDATED_BY
FROM REPORT_QUERY
WHERE QUERY_ID = #{queryId}
@@ -266,9 +266,9 @@
, DEFAULT_QUERIES::TEXT AS DEFAULT_QUERIES
, USE_YN
, SORT_ORDER
, CREATED_AT
, CREATED_DATE
, CREATED_BY
, UPDATED_AT
, UPDATED_DATE
, UPDATED_BY
FROM REPORT_TEMPLATE
WHERE USE_YN = 'Y'
@@ -288,9 +288,9 @@
, DEFAULT_QUERIES::TEXT AS DEFAULT_QUERIES
, USE_YN
, SORT_ORDER
, CREATED_AT
, CREATED_DATE
, CREATED_BY
, UPDATED_AT
, UPDATED_DATE
, UPDATED_BY
FROM REPORT_TEMPLATE
WHERE TEMPLATE_ID = #{templateId}
@@ -337,11 +337,11 @@
REPORT_ID
, MENU_OBJID
, COMPANY_CODE
, CREATED_AT
, CREATED_DATE
, CREATED_BY
FROM REPORT_MENU_MAPPING
WHERE REPORT_ID = #{reportId}
ORDER BY CREATED_AT ASC
ORDER BY CREATED_DATE ASC
</select>
<insert id="insertReportMenuMapping" parameterType="map">
@@ -31,8 +31,8 @@
, START_DATE
, END_DATE
, IS_ACTIVE
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
FROM RISK_ALERT
WHERE 1=1
<include refid="riskAlertSearchCondition"/>
@@ -60,8 +60,8 @@
, START_DATE
, END_DATE
, IS_ACTIVE
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
FROM RISK_ALERT
WHERE 1=1
<include refid="common.companyCodeFilter"/>
@@ -71,7 +71,7 @@
<if test="isActive != null and isActive != ''">
AND IS_ACTIVE = #{isActive}
</if>
ORDER BY CREATED_AT DESC
ORDER BY CREATED_DATE DESC
</select>
</mapper>
@@ -14,7 +14,7 @@
, COMPANY_CODE
, STATUS
, WRITER
, REGDATE
, CREATED_DATE
FROM AUTHORITY_MASTER
WHERE 1=1
<if test="companyCode != null and companyCode != ''">
@@ -23,7 +23,7 @@
<if test="search != null and search != ''">
AND AUTH_NAME ILIKE '%' || #{search} || '%'
</if>
ORDER BY REGDATE DESC
ORDER BY CREATED_DATE DESC
</select>
<!-- 권한 그룹 단건 조회 -->
@@ -35,7 +35,7 @@
, COMPANY_CODE
, STATUS
, WRITER
, REGDATE
, CREATED_DATE
FROM AUTHORITY_MASTER
WHERE OBJID = #{objid}
</select>
@@ -49,7 +49,7 @@
, COMPANY_CODE
, STATUS
, WRITER
, REGDATE
, CREATED_DATE
) VALUES (
#{authName}
, #{authCode}
@@ -92,14 +92,14 @@
, ASU.MASTER_OBJID
, ASU.USER_ID
, ASU.WRITER
, ASU.REGDATE
, ASU.CREATED_DATE
, UI.USER_NAME
, UI.DEPT_NAME
, UI.EMAIL
FROM AUTHORITY_SUB_USER ASU
LEFT JOIN USER_INFO UI ON ASU.USER_ID = UI.USER_ID
WHERE ASU.MASTER_OBJID = #{masterObjid}
ORDER BY ASU.REGDATE ASC
ORDER BY ASU.CREATED_DATE ASC
</select>
<!-- 멤버 일괄 추가 -->
@@ -108,7 +108,7 @@
MASTER_OBJID
, USER_ID
, WRITER
, REGDATE
, CREATED_DATE
) VALUES
<foreach collection="userIds" item="userId" separator=",">
(#{masterObjid}, #{userId}, #{writer}, NOW())
@@ -140,7 +140,7 @@
, ASM.MASTER_OBJID
, ASM.MENU_OBJID
, ASM.WRITER
, ASM.REGDATE
, ASM.CREATED_DATE
, MI.MENU_NAME
, MI.MENU_URL
, MI.LEV
@@ -163,7 +163,7 @@
MASTER_OBJID
, MENU_OBJID
, WRITER
, REGDATE
, CREATED_DATE
) VALUES
<foreach collection="permissions" item="perm" separator=",">
(#{authObjid}, #{perm.menuObjid}, #{writer}, NOW())
@@ -131,8 +131,8 @@
SOM.ORDER_NO,
SOM.COMPANY_CODE,
SOM.STATUS,
SOM.CREATED_DATE AS CREATED_AT,
SOM.UPDATED_DATE AS UPDATED_AT
SOM.CREATED_DATE AS CREATED_DATE,
SOM.UPDATED_DATE AS UPDATED_DATE
FROM SALES_ORDER_MNG SOM
WHERE SOM.ORDER_NO = #{id}
<if test="companyCode != null and companyCode != &quot;*&quot;">
@@ -25,7 +25,16 @@
</sql>
<select id="getScheduleList" parameterType="map" resultType="map">
SELECT * FROM schedule_mng
SELECT SCHEDULE_ID, COALESCE(SCHEDULE_NO, '') AS SCHEDULE_NO, SCHEDULE_NAME, SCHEDULE_TYPE
, RESOURCE_ID, RESOURCE_NAME, RESOURCE_TYPE
, START_DATE, END_DATE, DUE_DATE
, PLAN_QTY, COALESCE(ACTUAL_QTY, '') AS ACTUAL_QTY, COALESCE(UNIT, '') AS UNIT, COALESCE(PRIORITY, '') AS PRIORITY
, STATUS, COALESCE(REMARKS, '') AS REMARKS, COMPANY_CODE
, SOURCE_TABLE, SOURCE_ID, SOURCE_GROUP_KEY
, AUTO_GENERATED, GENERATED_BY, GENERATED_AT, METADATA
, CREATED_BY, CREATED_DATE AS CREATED_AT
, UPDATED_BY, UPDATED_DATE AS UPDATED_AT
FROM SCHEDULE_MNG
WHERE 1=1
<include refid="common.companyCodeFilter"/>
@@ -17,7 +17,7 @@
LEFT JOIN SCREEN_DEFINITIONS CS ON SE.CHILD_SCREEN_ID = CS.SCREEN_ID
WHERE SE.PARENT_SCREEN_ID = #{parentScreenId}
<include refid="common.companyCodeFilter"/>
ORDER BY SE.POSITION, SE.CREATED_AT
ORDER BY SE.POSITION, SE.CREATED_DATE
</select>
<select id="getScreenEmbeddingInfo" parameterType="map" resultType="map">
@@ -36,7 +36,7 @@
useGeneratedKeys="true" keyProperty="id" keyColumn="id">
INSERT INTO SCREEN_EMBEDDING (
PARENT_SCREEN_ID, CHILD_SCREEN_ID, POSITION, MODE,
CONFIG, COMPANY_CODE, CREATED_BY, CREATED_AT, UPDATED_AT
CONFIG, COMPANY_CODE, CREATED_BY, CREATED_DATE, UPDATED_DATE
) VALUES (
#{parentScreenId}, #{childScreenId}, #{position}, #{mode},
#{config}::JSONB, #{companyCode}, #{userId}, NOW(), NOW()
@@ -49,7 +49,7 @@
<if test="position != null">POSITION = #{position},</if>
<if test="mode != null">MODE = #{mode},</if>
<if test="config != null">CONFIG = #{config}::JSONB,</if>
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
</set>
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
@@ -89,7 +89,7 @@
useGeneratedKeys="true" keyProperty="id" keyColumn="id">
INSERT INTO SCREEN_DATA_TRANSFER (
SOURCE_SCREEN_ID, TARGET_SCREEN_ID, SOURCE_COMPONENT_ID, SOURCE_COMPONENT_TYPE,
DATA_RECEIVERS, BUTTON_CONFIG, COMPANY_CODE, CREATED_BY, CREATED_AT, UPDATED_AT
DATA_RECEIVERS, BUTTON_CONFIG, COMPANY_CODE, CREATED_BY, CREATED_DATE, UPDATED_DATE
) VALUES (
#{sourceScreenId}, #{targetScreenId}, #{sourceComponentId}, #{sourceComponentType},
#{dataReceivers}::JSONB, #{buttonConfig}::JSONB, #{companyCode}, #{userId}, NOW(), NOW()
@@ -101,7 +101,7 @@
<set>
<if test="dataReceivers != null">DATA_RECEIVERS = #{dataReceivers}::JSONB,</if>
<if test="buttonConfig != null">BUTTON_CONFIG = #{buttonConfig}::JSONB,</if>
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
</set>
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
@@ -128,8 +128,8 @@
SSP.DATA_TRANSFER_ID AS "dataTransferId",
SSP.LAYOUT_CONFIG AS "layoutConfig",
SSP.COMPANY_CODE AS "companyCode",
SSP.CREATED_AT AS "createdAt",
SSP.UPDATED_AT AS "updatedAt",
SSP.CREATED_DATE AS "createdAt",
SSP.UPDATED_DATE AS "updatedAt",
LE.PARENT_SCREEN_ID AS "leParentScreenId",
LE.CHILD_SCREEN_ID AS "leChildScreenId",
LE.POSITION AS "lePosition",
@@ -172,7 +172,7 @@
useGeneratedKeys="true" keyProperty="id" keyColumn="id">
INSERT INTO SCREEN_SPLIT_PANEL (
SCREEN_ID, LEFT_EMBEDDING_ID, RIGHT_EMBEDDING_ID, DATA_TRANSFER_ID,
LAYOUT_CONFIG, COMPANY_CODE, CREATED_AT, UPDATED_AT
LAYOUT_CONFIG, COMPANY_CODE, CREATED_DATE, UPDATED_DATE
) VALUES (
#{screenId}, #{leftEmbeddingId}, #{rightEmbeddingId}, #{dataTransferId},
#{layoutConfig}::JSONB, #{companyCode}, NOW(), NOW()
@@ -182,7 +182,7 @@
<update id="updateScreenSplitPanel" parameterType="map">
UPDATE SCREEN_SPLIT_PANEL
SET LAYOUT_CONFIG = #{layoutConfig}::JSONB,
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
WHERE ID = #{id}
<if test='companyCode != null and companyCode != "*"'>
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
@@ -20,12 +20,12 @@
, TARGET_OBJID
, PARENT_TARGET_OBJID
, WRITER
, REGDATE
, CREATED_DATE
, STATUS
FROM ATTACH_FILE_INFO
WHERE TARGET_OBJID LIKE #{targetObjidPattern}
AND STATUS = 'ACTIVE'
ORDER BY REGDATE DESC
ORDER BY CREATED_DATE DESC
</select>
<!--
@@ -45,12 +45,12 @@
, TARGET_OBJID
, PARENT_TARGET_OBJID
, WRITER
, REGDATE
, CREATED_DATE
, STATUS
FROM ATTACH_FILE_INFO
WHERE TARGET_OBJID LIKE #{targetObjidPattern}
AND STATUS = 'ACTIVE'
ORDER BY REGDATE DESC
ORDER BY CREATED_DATE DESC
</select>
</mapper>
@@ -917,7 +917,7 @@
<insert id="insertUserMenuRoot" parameterType="map">
INSERT INTO MENU_INFO (
OBJID, PARENT_OBJ_ID, MENU_NAME_KOR, MENU_NAME_ENG,
SEQ, MENU_TYPE, COMPANY_CODE, WRITER, REGDATE, STATUS
SEQ, MENU_TYPE, COMPANY_CODE, WRITER, CREATED_DATE, STATUS
) VALUES (
#{objid}, 0, '사용자', 'User', 1, 1,
#{companyCode}, #{userId}, NOW(), 'active'
@@ -952,7 +952,7 @@
<insert id="insertMenuForGroup" parameterType="map">
INSERT INTO MENU_INFO (
OBJID, PARENT_OBJ_ID, MENU_NAME_KOR, MENU_NAME_ENG,
SEQ, MENU_TYPE, COMPANY_CODE, WRITER, REGDATE, STATUS,
SEQ, MENU_TYPE, COMPANY_CODE, WRITER, CREATED_DATE, STATUS,
SCREEN_GROUP_ID, MENU_DESC, MENU_URL, SCREEN_CODE, MENU_ICON
) VALUES (
#{objid}, #{parentObjid}, #{groupName}, #{groupCode},
@@ -66,7 +66,7 @@
FROM SCREEN_DEFINITIONS SD
WHERE SD.IS_ACTIVE != 'D'
<if test="companyCode != null and companyCode != &quot;*&quot;">
AND (SD.COMPANY_CODE = #{companyCode} OR SD.COMPANY_CODE = '*')
AND SD.COMPANY_CODE = #{companyCode}
</if>
<if test="searchTerm != null and searchTerm != ''">
AND (SD.SCREEN_NAME ILIKE #{searchLike}
@@ -89,7 +89,7 @@
FROM SCREEN_DEFINITIONS SD
WHERE SD.IS_ACTIVE != 'D'
<if test="companyCode != null and companyCode != &quot;*&quot;">
AND (SD.COMPANY_CODE = #{companyCode} OR SD.COMPANY_CODE = '*')
AND SD.COMPANY_CODE = #{companyCode}
</if>
<if test="searchTerm != null and searchTerm != ''">
AND (SD.SCREEN_NAME ILIKE #{searchLike}
@@ -117,7 +117,7 @@
, SD.CREATED_DATE
, SD.CREATED_BY
, SD.UPDATED_DATE
, SD.UPDATED_BY
, COALESCE(SD.UPDATED_BY, '') AS UPDATED_BY
, SD.DB_SOURCE_TYPE
, SD.DB_CONNECTION_ID
, SD.DATA_SOURCE_TYPE
@@ -232,9 +232,27 @@
<select id="selectDeletedScreenList" parameterType="map" resultType="map">
SELECT
*
FROM SCREEN_DEFINITIONS
WHERE IS_ACTIVE = 'D'
SD.SCREEN_ID
, SD.SCREEN_NAME
, SD.SCREEN_CODE
, COALESCE(SD.TABLE_NAME, '') AS TABLE_NAME
, SD.COMPANY_CODE
, COALESCE(SD.DESCRIPTION, '') AS DESCRIPTION
, SD.IS_ACTIVE
, SD.CREATED_DATE
, COALESCE(SD.CREATED_BY, '') AS CREATED_BY
, SD.UPDATED_DATE
, COALESCE(SD.UPDATED_BY, '') AS UPDATED_BY
, COALESCE(SD.DB_SOURCE_TYPE, '') AS DB_SOURCE_TYPE
, COALESCE(SD.DATA_SOURCE_TYPE, '') AS DATA_SOURCE_TYPE
, COALESCE(SD.REST_API_JSON_PATH, '') AS REST_API_JSON_PATH
, SD.DELETED_DATE
, COALESCE(SD.DELETED_BY, '') AS DELETED_BY
, COALESCE(SD.DELETE_REASON, '') AS 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.IS_ACTIVE = 'D'
<if test="companyCode != null and companyCode != &quot;*&quot;">
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
</if>
@@ -333,6 +351,15 @@
ORDER BY DISPLAY_ORDER ASC NULLS LAST, LAYOUT_ID ASC
</select>
<select id="selectLayoutV1FromV1Table" parameterType="map" resultType="map">
SELECT
*
FROM SCREEN_LAYOUTS_V1
WHERE SCREEN_ID = #{screenId}
AND (COMPANY_CODE = #{companyCode} OR #{companyCode} = '*')
ORDER BY DISPLAY_ORDER ASC NULLS LAST, LAYOUT_ID ASC
</select>
<!-- ─── Layout V2 ───────────────────────────────────────────────── -->
<select id="selectLayoutV2" parameterType="map" resultType="map">
@@ -349,6 +376,20 @@
LIMIT 1
</select>
<select id="selectLayoutV2Exact" parameterType="map" resultType="map">
SELECT
LAYOUT_DATA
, LAYER_NAME
, CONDITION_CONFIG
, COMPANY_CODE
FROM SCREEN_LAYOUTS_V2
WHERE SCREEN_ID = #{screenId}
AND COMPANY_CODE = #{companyCode}
<if test="layerId != null">AND LAYER_ID = #{layerId}</if>
ORDER BY LAYER_ID ASC
LIMIT 1
</select>
<insert id="upsertLayoutV2" parameterType="map">
INSERT INTO SCREEN_LAYOUTS_V2 (
SCREEN_ID
@@ -356,8 +397,8 @@
, LAYER_ID
, LAYER_NAME
, LAYOUT_DATA
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{screenId}
, #{companyCode}
@@ -370,7 +411,7 @@
ON CONFLICT (SCREEN_ID, COMPANY_CODE, LAYER_ID) DO UPDATE SET
LAYOUT_DATA = EXCLUDED.LAYOUT_DATA
, LAYER_NAME = EXCLUDED.LAYER_NAME
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
</insert>
<insert id="upsertLayoutV2WithCondition" parameterType="map">
@@ -381,8 +422,8 @@
, LAYER_NAME
, CONDITION_CONFIG
, LAYOUT_DATA
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{screenId}
, #{companyCode}
@@ -397,7 +438,7 @@
LAYOUT_DATA = EXCLUDED.LAYOUT_DATA
, LAYER_NAME = EXCLUDED.LAYER_NAME
, CONDITION_CONFIG = EXCLUDED.CONDITION_CONFIG
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
</insert>
<update id="updateScreenMainTable" parameterType="map">
@@ -416,7 +457,7 @@
, LAYER_NAME
, COALESCE(CONDITION_CONFIG, '{}') AS CONDITION_CONFIG
, JSONB_ARRAY_LENGTH(COALESCE(LAYOUT_DATA->'components', '[]'::jsonb)) AS COMPONENT_COUNT
, UPDATED_AT
, UPDATED_DATE AS UPDATED_AT
FROM SCREEN_LAYOUTS_V2
WHERE SCREEN_ID = #{screenId}
<if test='companyCode != null and companyCode != "*"'>
@@ -432,8 +473,8 @@
, LAYER_ID
, LAYER_NAME
, LAYOUT_DATA
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{screenId}
, #{companyCode}
@@ -469,7 +510,7 @@
UPDATE SCREEN_LAYOUTS_V2
<set>
CONDITION_CONFIG = #{conditionConfig}::jsonb,
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
<if test="layerName != null">, LAYER_NAME = #{layerName}</if>
</set>
WHERE SCREEN_ID = #{screenId}
@@ -505,7 +546,7 @@
LAYOUT_DATA = EXCLUDED.LAYOUT_DATA
, LAYER_NAME = EXCLUDED.LAYER_NAME
, CONDITION_CONFIG = EXCLUDED.CONDITION_CONFIG
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
</insert>
<!-- ─── Zone management ─────────────────────────────────────────── -->
@@ -549,7 +590,7 @@
<update id="updateZone" parameterType="map">
UPDATE SCREEN_CONDITIONAL_ZONES
<set>
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
<if test="zoneName != null">, ZONE_NAME = #{zoneName}</if>
<if test="x != null">, X = #{x}</if>
<if test="y != null">, Y = #{y}</if>
@@ -572,7 +613,7 @@
UPDATE SCREEN_LAYOUTS_V2
SET
CONDITION_CONFIG = NULL
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
AND CONDITION_CONFIG->>'zone_id' = #{zoneIdStr}
</update>
@@ -602,8 +643,8 @@
SCREEN_ID
, COMPANY_CODE
, LAYOUT_DATA
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
, CREATED_BY
, UPDATED_BY
) VALUES (
@@ -617,7 +658,7 @@
)
ON CONFLICT (SCREEN_ID, COMPANY_CODE) DO UPDATE SET
LAYOUT_DATA = EXCLUDED.LAYOUT_DATA
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
, UPDATED_BY = EXCLUDED.UPDATED_BY
</insert>
@@ -906,8 +947,8 @@
, LAYER_NAME
, CONDITION_CONFIG
, LAYOUT_DATA
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{screenId}
, #{companyCode}
@@ -920,7 +961,7 @@
)
ON CONFLICT (SCREEN_ID, COMPANY_CODE, LAYER_ID) DO UPDATE SET
LAYOUT_DATA = EXCLUDED.LAYOUT_DATA
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
</insert>
<!-- ─── Layout properties update (tab references) ────────────────── -->
@@ -957,7 +998,7 @@
UPDATE SCREEN_LAYOUTS_V2
SET
LAYOUT_DATA = #{layoutData}::jsonb
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE SCREEN_ID = #{screenId}
AND LAYER_ID = #{layerId}
AND (COMPANY_CODE = #{companyCode} OR COMPANY_CODE = '*')
@@ -1257,8 +1298,8 @@
SCREEN_ID
, COMPANY_CODE
, LAYOUT_DATA
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
, CREATED_BY
, UPDATED_BY
) VALUES (
@@ -1272,7 +1313,7 @@
)
ON CONFLICT (SCREEN_ID, COMPANY_CODE) DO UPDATE SET
LAYOUT_DATA = EXCLUDED.LAYOUT_DATA
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
, UPDATED_BY = EXCLUDED.UPDATED_BY
</insert>
@@ -67,8 +67,8 @@
COALESCE(c.customer_name, m.partner_id, d.delivery_partner_code, '') AS customer_name,
COALESCE(m.partner_id, d.delivery_partner_code, '') AS partner_code,
COALESCE(d.due_date, m.due_date::text, '') AS due_date,
COALESCE(NULLIF(d.qty,'')::numeric, m.order_qty, 0) AS order_qty,
COALESCE(NULLIF(d.ship_qty,'')::numeric, m.ship_qty, 0) AS shipped_qty
COALESCE(NULLIF(d.qty,''), m.order_qty, '0') AS order_qty,
COALESCE(NULLIF(d.ship_qty,''), m.ship_qty, '0') AS shipped_qty
FROM shipment_plan sp
<include refid="shippingPlanJoins"/>
@@ -12,15 +12,15 @@
CONTENT,
IS_ACTIVE,
CREATED_BY,
CREATED_AT,
UPDATED_AT
CREATED_DATE,
UPDATED_DATE
FROM SYSTEM_NOTICE
WHERE 1=1
<include refid="common.companyCodeFilter"/>
<if test="isActive != null">
AND IS_ACTIVE = #{isActive}
</if>
ORDER BY CREATED_AT DESC
ORDER BY CREATED_DATE DESC
<include refid="common.pagination"/>
</select>
@@ -44,8 +44,8 @@
CONTENT,
IS_ACTIVE,
CREATED_BY,
CREATED_AT,
UPDATED_AT
CREATED_DATE,
UPDATED_DATE
FROM SYSTEM_NOTICE
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
@@ -53,7 +53,7 @@
<!-- 공지사항 등록 -->
<insert id="insertSystemNotice" parameterType="map" useGeneratedKeys="true" keyProperty="id">
INSERT INTO SYSTEM_NOTICE (COMPANY_CODE, TITLE, CONTENT, IS_ACTIVE, CREATED_BY, CREATED_AT, UPDATED_AT)
INSERT INTO SYSTEM_NOTICE (COMPANY_CODE, TITLE, CONTENT, IS_ACTIVE, CREATED_BY, CREATED_DATE, UPDATED_DATE)
VALUES (#{companyCode}, #{title}, #{content},
COALESCE(#{isActive}, TRUE),
#{createdBy}, NOW(), NOW())
@@ -72,7 +72,7 @@
<if test="isActive != null">
IS_ACTIVE = #{isActive},
</if>
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
</set>
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
@@ -82,8 +82,8 @@
is_default AS "isDefault",
company_code AS "companyCode",
menu_objid AS "menuObjid",
created_at AS "createdAt",
updated_at AS "updatedAt",
CREATED_DATE AS "createdAt",
UPDATED_DATE AS "updatedAt",
created_by AS "createdBy",
updated_by AS "updatedBy"
@@ -123,8 +123,8 @@
is_default AS "isDefault",
company_code AS "companyCode",
menu_objid AS "menuObjid",
created_at AS "createdAt",
updated_at AS "updatedAt",
CREATED_DATE AS "createdAt",
UPDATED_DATE AS "updatedAt",
created_by AS "createdBy",
updated_by AS "updatedBy"
@@ -221,7 +221,7 @@
<if test="icon != null">icon = #{icon},</if>
<if test="isActive != null">is_active = #{isActive},</if>
<if test="isDefault != null">is_default = #{isDefault},</if>
updated_at = NOW(),
UPDATED_DATE = NOW(),
updated_by = #{userId}
</set>
WHERE value_id = #{valueId}
@@ -307,7 +307,7 @@
<update id="bulkSoftDeleteValues" parameterType="map">
UPDATE category_values
SET is_active = FALSE,
updated_at = NOW(),
UPDATED_DATE = NOW(),
updated_by = #{userId}
WHERE value_id IN
<foreach collection="valueIds" item="id" open="(" separator="," close=")">
@@ -321,7 +321,7 @@
<update id="updateValueOrder" parameterType="map">
UPDATE category_values
SET value_order = #{valueOrder},
updated_at = NOW()
UPDATED_DATE = NOW()
WHERE value_id = #{valueId}
<if test='companyCode != null and companyCode != "*"'>
AND (company_code = #{companyCode} OR company_code = '*')
@@ -384,7 +384,7 @@
DO UPDATE SET
physical_column_name = EXCLUDED.physical_column_name,
description = EXCLUDED.description,
updated_at = NOW(),
UPDATED_DATE = NOW(),
updated_by = EXCLUDED.updated_by
</insert>
@@ -11,7 +11,7 @@
BUYER_BUSINESS_NO, BUYER_NAME, BUYER_CEO_NAME, BUYER_ADDRESS, BUYER_EMAIL,
SUPPLY_AMOUNT, TAX_AMOUNT, TOTAL_AMOUNT, INVOICE_DATE, ISSUE_DATE,
REMARKS, ORDER_ID, CUSTOMER_ID, COST_TYPE, WRITER,
CREATED_AT, UPDATED_AT
CREATED_DATE, UPDATED_DATE
FROM TAX_INVOICE
WHERE 1=1
<include refid="common.companyCodeFilter"/>
@@ -38,7 +38,7 @@
<if test="cost_type != null and cost_type != ''">
AND COST_TYPE = #{cost_type}
</if>
ORDER BY CREATED_AT DESC
ORDER BY CREATED_DATE DESC
<include refid="common.pagination"/>
</select>
@@ -80,7 +80,7 @@
BUYER_BUSINESS_NO, BUYER_NAME, BUYER_CEO_NAME, BUYER_ADDRESS, BUYER_EMAIL,
SUPPLY_AMOUNT, TAX_AMOUNT, TOTAL_AMOUNT, INVOICE_DATE, ISSUE_DATE,
REMARKS, ORDER_ID, CUSTOMER_ID, COST_TYPE, WRITER,
CREATED_AT, UPDATED_AT
CREATED_DATE, UPDATED_DATE
FROM TAX_INVOICE
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
@@ -114,7 +114,7 @@
BUYER_BUSINESS_NO, BUYER_NAME, BUYER_CEO_NAME, BUYER_ADDRESS, BUYER_EMAIL,
SUPPLY_AMOUNT, TAX_AMOUNT, TOTAL_AMOUNT, INVOICE_DATE,
REMARKS, ORDER_ID, CUSTOMER_ID, COST_TYPE, WRITER,
CREATED_AT, UPDATED_AT
CREATED_DATE, UPDATED_DATE
) VALUES (
#{companyCode}, #{invoiceNumber}, #{invoice_type}, 'draft',
#{supplier_business_no}, #{supplier_name}, #{supplier_ceo_name}, #{supplier_address},
@@ -198,7 +198,7 @@
<if test="cost_type != null">
COST_TYPE = #{cost_type},
</if>
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
</set>
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
@@ -209,7 +209,7 @@
SET
INVOICE_STATUS = 'issued',
ISSUE_DATE = NOW(),
UPDATED_AT = NOW()
UPDATED_DATE = NOW()
WHERE ID = #{id}
AND INVOICE_STATUS = 'draft'
<include refid="common.companyCodeFilter"/>
@@ -219,7 +219,10 @@
UPDATE TAX_INVOICE
SET
INVOICE_STATUS = 'cancelled',
UPDATED_AT = NOW()
<if test="cancelReason != null and cancelReason != ''">
REMARKS = #{cancelReason},
</if>
UPDATED_DATE = NOW()
WHERE ID = #{id}
AND INVOICE_STATUS IN ('draft', 'issued')
<include refid="common.companyCodeFilter"/>
@@ -7,7 +7,7 @@
<sql id="templateColumns">
template_code, template_name, template_name_eng, description, category,
icon_name, sort_order, is_active, is_public, company_code,
created_by, updated_by, created_at, updated_at,
created_by, updated_by, CREATED_DATE, UPDATED_DATE,
layout_config::text AS layout_config,
default_size::text AS default_size,
preview_image
@@ -70,7 +70,7 @@
template_code, template_name, template_name_eng, description, category,
icon_name, default_size, layout_config, preview_image,
sort_order, is_active, is_public, company_code,
created_by, updated_by, created_at, updated_at
created_by, updated_by, CREATED_DATE, UPDATED_DATE
) VALUES (
#{template_code}, #{template_name}, #{template_name_eng}, #{description}, #{category},
#{icon_name},
@@ -86,7 +86,7 @@
<update id="updateTemplateStandard" parameterType="map">
UPDATE template_standards
<set>
updated_at = NOW(),
UPDATED_DATE = NOW(),
<if test="template_name != null">template_name = #{template_name},</if>
<if test="template_name_eng != null">template_name_eng = #{template_name_eng},</if>
<if test="description != null">description = #{description},</if>
@@ -114,7 +114,7 @@
<!-- 정렬 순서 단건 업데이트 -->
<update id="updateTemplateStandardSortOrder" parameterType="map">
UPDATE template_standards
SET sort_order = #{sort_order}, updated_at = NOW()
SET sort_order = #{sort_order}, UPDATED_DATE = NOW()
WHERE template_code = #{template_code}
</update>
@@ -9,7 +9,7 @@
SELECT diagram_id, diagram_name, relationships
FROM dataflow_diagrams
WHERE company_code = $1
ORDER BY updated_at DESC
ORDER BY UPDATED_DATE DESC
-->
<select id="selectDiagramsForRelationships" parameterType="map" resultType="map">
SELECT
@@ -19,7 +19,7 @@
FROM DATAFLOW_DIAGRAMS
WHERE 1=1
<include refid="common.companyCodeFilter"/>
ORDER BY UPDATED_AT DESC
ORDER BY UPDATED_DATE DESC
</select>
</mapper>
@@ -28,8 +28,8 @@
, STATUS
, ASSIGNED_TO
, DUE_DATE
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
, COMPLETED_AT
, IS_URGENT
, DISPLAY_ORDER
@@ -65,8 +65,8 @@
, STATUS
, ASSIGNED_TO
, DUE_DATE
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
, COMPLETED_AT
, IS_URGENT
, DISPLAY_ORDER
@@ -85,8 +85,8 @@
, DUE_DATE
, IS_URGENT
, DISPLAY_ORDER
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{id}
, #{title}
@@ -104,7 +104,7 @@
<update id="updateTodo" parameterType="map">
UPDATE TODO_ITEMS
SET UPDATED_AT = NOW()
SET UPDATED_DATE = NOW()
<if test="title != null">, TITLE = #{title}</if>
<if test="description != null">, DESCRIPTION = #{description}</if>
<if test="priority != null">, PRIORITY = #{priority}</if>
@@ -127,7 +127,7 @@
UPDATE TODO_ITEMS
SET
DISPLAY_ORDER = #{displayOrder}
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE ID = #{id}
</update>
@@ -56,8 +56,8 @@
, BRANCH_NAME
, STATUS
, COMPANY_CODE
, CREATED_AT
, UPDATED_AT
, CREATED_DATE
, UPDATED_DATE
) VALUES (
#{vehicleNumber}
, #{vehicleType}
@@ -82,7 +82,7 @@
, DRIVER_PHONE = COALESCE(#{driverPhone}, DRIVER_PHONE)
, BRANCH_NAME = COALESCE(#{branchName}, BRANCH_NAME)
, STATUS = COALESCE(#{status}, STATUS)
, UPDATED_AT = NOW()
, UPDATED_DATE = NOW()
WHERE ID = #{id}
<include refid="common.companyCodeFilter"/>
@@ -4,7 +4,7 @@
<mapper namespace="workHistory">
<sql id="workHistorySearchCondition">
AND deleted_at IS NULL
AND DELETED_DATE IS NULL
<if test="work_type != null and work_type != ''">
AND work_type = #{work_type}
</if>
@@ -57,7 +57,7 @@
FROM work_history
WHERE id = #{id} AND deleted_at IS NULL
WHERE id = #{id} AND DELETED_DATE IS NULL
</select>
<insert id="insertWorkHistory" parameterType="map" useGeneratedKeys="true" keyProperty="id">
@@ -65,7 +65,7 @@
work_type, vehicle_number, driver_name, origin, destination,
cargo_name, cargo_weight, cargo_unit, distance, distance_unit,
status, scheduled_time, estimated_arrival, notes, created_by,
work_date, created_at, updated_at
work_date, CREATED_DATE, UPDATED_DATE
) VALUES (
#{work_type, jdbcType=VARCHAR},
#{vehicle_number, jdbcType=VARCHAR},
@@ -88,7 +88,7 @@
</insert>
<update id="updateWorkHistory" parameterType="map">
UPDATE work_history SET updated_at = NOW()
UPDATE work_history SET UPDATED_DATE = NOW()
<if test="work_type != null">, work_type = #{work_type}</if>
<if test="vehicle_number != null">, vehicle_number = #{vehicle_number}</if>
<if test="driver_name != null">, driver_name = #{driver_name}</if>
@@ -107,13 +107,13 @@
<if test="work_date != null">, work_date = #{work_date}</if>
<if test="notes != null">, notes = #{notes}</if>
WHERE id = #{id} AND deleted_at IS NULL
WHERE id = #{id} AND DELETED_DATE IS NULL
</update>
<update id="deleteWorkHistory" parameterType="map">
UPDATE work_history SET deleted_at = NOW(), updated_at = NOW()
UPDATE work_history SET DELETED_DATE = NOW(), UPDATED_DATE = NOW()
WHERE id = #{id} AND deleted_at IS NULL
WHERE id = #{id} AND DELETED_DATE IS NULL
</update>
<select id="getWorkHistoryTodayStats" parameterType="map" resultType="map">
@@ -123,7 +123,7 @@
FROM work_history
WHERE DATE(work_date) = CURRENT_DATE AND deleted_at IS NULL
WHERE DATE(work_date) = CURRENT_DATE AND DELETED_DATE IS NULL
</select>
<select id="getWorkHistoryTotalStats" parameterType="map" resultType="map">
@@ -133,7 +133,7 @@
FROM work_history
WHERE deleted_at IS NULL AND status = 'completed'
WHERE DELETED_DATE IS NULL AND status = 'completed'
</select>
<select id="getWorkHistoryOnTimeRate" parameterType="map" resultType="map">
@@ -145,7 +145,7 @@
FROM work_history
WHERE deleted_at IS NULL
WHERE DELETED_DATE IS NULL
AND status = 'completed'
AND is_on_time IS NOT NULL
</select>
@@ -155,7 +155,7 @@
FROM work_history
WHERE deleted_at IS NULL
WHERE DELETED_DATE IS NULL
GROUP BY work_type
</select>
@@ -170,7 +170,7 @@
FROM work_history
WHERE deleted_at IS NULL
WHERE DELETED_DATE IS NULL
AND work_date >= CURRENT_DATE - (#{months}::INTEGER * INTERVAL '1 month')
GROUP BY TO_CHAR(work_date, 'YYYY-MM')
@@ -187,7 +187,7 @@
FROM work_history
WHERE deleted_at IS NULL
WHERE DELETED_DATE IS NULL
AND origin IS NOT NULL
AND destination IS NOT NULL
AND work_type IN ('inbound', 'outbound', 'transfer')
@@ -44,7 +44,7 @@
</select>
<insert id="insertYardLayout" parameterType="map" useGeneratedKeys="true" keyProperty="id">
INSERT INTO yard_layout (name, description, created_by, company_code, created_at, updated_at)
INSERT INTO yard_layout (name, description, created_by, company_code, CREATED_DATE, UPDATED_DATE)
VALUES (#{name}, #{description}, #{createdBy}, #{companyCode}, NOW(), NOW())
</insert>
@@ -54,7 +54,7 @@
SET
name = COALESCE(#{name}, name),
description = COALESCE(#{description}, description),
updated_at = NOW()
UPDATED_DATE = NOW()
WHERE id = #{id}
<include refid="common.companyCodeFilter"/>
@@ -84,7 +84,7 @@
position_x, position_y, position_z,
size_x, size_y, size_z,
color, data_source_type, data_source_config,
data_binding, memo, created_at, updated_at
data_binding, memo, CREATED_DATE, UPDATED_DATE
) VALUES (
#{yardLayoutId}, #{materialCode}, #{materialName}, #{quantity}, #{unit},
#{positionX}, #{positionY}, #{positionZ},
@@ -113,7 +113,7 @@
data_source_config = COALESCE(#{dataSourceConfig}, data_source_config),
data_binding = COALESCE(#{dataBinding}, data_binding),
memo = COALESCE(#{memo}, memo),
updated_at = NOW()
UPDATED_DATE = NOW()
WHERE id = #{id}
</update>
+86 -86
View File
@@ -65,129 +65,129 @@
--radius-xl: calc(var(--radius) + 4px);
}
/* ===== CSS Variables (Vivid Blue Theme) ===== */
/* ===== CSS Variables (Cosmic Design System) ===== */
:root {
/* Light Theme Colors - HSL Format */
--background: 0 0% 100%;
--foreground: 224 71% 4%;
/* Light Theme: Stellar White — 맑은 은하, 미묘한 코스믹 톤 */
--background: 240 20% 99%;
--foreground: 240 10% 5%;
--card: 0 0% 100%;
--card-foreground: 224 71% 4%;
--card-foreground: 240 10% 5%;
--popover: 0 0% 100%;
--popover-foreground: 224 71% 4%;
--primary: 217.2 91.2% 59.8%;
--popover-foreground: 240 10% 5%;
--primary: 245 75% 57%;
--primary-foreground: 0 0% 100%;
--secondary: 220 14.3% 95.9%;
--secondary-foreground: 220.9 39.3% 11%;
--muted: 220 14.3% 95.9%;
--muted-foreground: 220 8.9% 46.1%;
--accent: 220 14.3% 95.9%;
--accent-foreground: 220.9 39.3% 11%;
--destructive: 0 84.2% 60.2%;
--secondary: 240 10% 95%;
--secondary-foreground: 240 20% 15%;
--muted: 240 10% 94%;
--muted-foreground: 240 5% 46%;
--accent: 240 10% 93%;
--accent-foreground: 240 20% 15%;
--destructive: 0 80% 60%;
--destructive-foreground: 0 0% 100%;
--border: 220 13% 88%;
--input: 220 13% 88%;
--ring: 217.2 91.2% 59.8%;
--border: 240 8% 88%;
--input: 240 8% 88%;
--ring: 245 75% 57%;
/* Success Colors (Emerald) */
--success: 142 76% 36%;
/* Success: Aurora Green */
--success: 152 72% 38%;
--success-foreground: 0 0% 100%;
/* Warning Colors (Amber) */
--warning: 38 92% 50%;
/* Warning: Stellar Amber */
--warning: 38 95% 50%;
--warning-foreground: 0 0% 100%;
/* Info Colors (Cyan) */
--info: 188 94% 43%;
/* Info: Nebula Cyan */
--info: 195 90% 45%;
--info-foreground: 0 0% 100%;
/* Chart Colors */
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
/* Chart: Cosmic Palette */
--chart-1: 265 70% 62%;
--chart-2: 152 65% 42%;
--chart-3: 210 75% 55%;
--chart-4: 38 85% 58%;
--chart-5: 340 72% 58%;
/* Border Radius */
--radius: 0.5rem;
/* Border Radius: Slightly rounder for modern cosmic feel */
--radius: 0.625rem;
/* Sidebar Colors */
--sidebar-background: 220 20% 97%;
--sidebar-foreground: 224 71% 4%;
--sidebar-primary: 217.2 91.2% 59.8%;
/* Sidebar: Subtle cosmic tint */
--sidebar-background: 240 15% 97%;
--sidebar-foreground: 240 10% 5%;
--sidebar-primary: 245 75% 57%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 220 14.3% 95.9%;
--sidebar-accent-foreground: 220.9 39.3% 11%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
--sidebar-accent: 240 10% 93%;
--sidebar-accent-foreground: 240 20% 15%;
--sidebar-border: 240 8% 90%;
--sidebar-ring: 245 75% 57%;
}
/* ===== Dark Theme (Palantir-Inspired) ===== */
/* ===== Dark Theme (Deep Space) ===== */
.dark {
/* 배경: 팔란티어 스타일 깊은 네이비 */
--background: 222 47% 6%;
--foreground: 210 20% 95%;
/* 배경: 딥 스페이스 — 보라빛 암흑 */
--background: 240 20% 3.5%;
--foreground: 240 10% 95%;
/* 카드: 배경보다 약간 밝게 (레이어 구분) */
--card: 220 40% 9%;
--card-foreground: 210 20% 95%;
/* 카드: 성운 표면 — 배경보다 약간 밝은 우주 공간 */
--card: 240 18% 7%;
--card-foreground: 240 10% 95%;
/* 팝오버: 카드와 동일 */
--popover: 220 40% 9%;
--popover-foreground: 210 20% 95%;
/* 팝오버: 카드와 동일한 우주 공간 */
--popover: 240 18% 7%;
--popover-foreground: 240 10% 95%;
/* Primary: 다크 배경에서 약간 더 밝은 블루 */
--primary: 217 91% 65%;
/* Primary: 코스믹 바이올렛-블루 — 성운 핵심 컬러 */
--primary: 245 85% 68%;
--primary-foreground: 0 0% 100%;
/* Secondary: 어두운 슬레이트 */
--secondary: 220 25% 14%;
--secondary-foreground: 210 20% 90%;
/* Secondary: 우주 먼지 — 깊은 슬레이트 */
--secondary: 240 15% 14%;
--secondary-foreground: 240 10% 90%;
/* Muted: 차분한 회색-네이비 */
--muted: 220 20% 13%;
--muted-foreground: 215 15% 58%;
/* Muted: 암흑 성운 — 차분한 보라빛 회색 */
--muted: 240 12% 12%;
--muted-foreground: 240 8% 58%;
/* Accent: secondary와 유사 */
--accent: 220 25% 16%;
--accent-foreground: 210 20% 90%;
/* Accent: 은하 표면 — secondary보다 약간 밝게 */
--accent: 240 15% 18%;
--accent-foreground: 240 10% 90%;
/* Destructive: 다크에서 더 밝은 레드 */
--destructive: 0 72% 51%;
/* Destructive: 초신성 레드 */
--destructive: 0 75% 55%;
--destructive-foreground: 0 0% 100%;
/* Border: 팔란티어 스타일 - 보더가 더 잘 보임 */
--border: 220 20% 18%;
--input: 220 20% 18%;
--ring: 217 91% 65%;
/* Border: 스타더스트 라인 */
--border: 240 12% 15%;
--input: 240 12% 15%;
--ring: 245 85% 68%;
/* Success (Emerald) - 다크 배경용 밝기 조정 */
--success: 142 70% 42%;
/* Success: 오로라 그린 */
--success: 152 70% 45%;
--success-foreground: 0 0% 100%;
/* Warning (Amber) - 다크 배경용 밝기 조정 */
--warning: 38 92% 55%;
/* Warning: 항성 앰버 */
--warning: 38 92% 58%;
--warning-foreground: 0 0% 10%;
/* Info (Cyan) - 다크 배경용 밝기 조정 */
--info: 188 90% 48%;
/* Info: 성운 시안 */
--info: 195 85% 52%;
--info-foreground: 0 0% 100%;
/* Chart Colors - 다크 배경에서 선명한 컬러 */
--chart-1: 220 70% 55%;
--chart-2: 160 60% 48%;
--chart-3: 30 80% 58%;
--chart-4: 280 65% 63%;
--chart-5: 340 75% 58%;
/* Chart: Cosmic Neon Palette */
--chart-1: 265 80% 68%;
--chart-2: 152 70% 50%;
--chart-3: 210 80% 62%;
--chart-4: 38 90% 62%;
--chart-5: 340 78% 62%;
/* Sidebar - 메인 배경보다 약간 어둡게 */
--sidebar-background: 222 47% 5%;
--sidebar-foreground: 210 20% 90%;
--sidebar-primary: 217 91% 65%;
/* Sidebar: 이벤트 호라이즌 — 메인 배경보다 더 깊은 우주 */
--sidebar-background: 240 22% 5%;
--sidebar-foreground: 240 10% 90%;
--sidebar-primary: 245 85% 68%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 220 25% 14%;
--sidebar-accent-foreground: 210 20% 90%;
--sidebar-border: 220 20% 16%;
--sidebar-ring: 217 91% 65%;
--sidebar-accent: 240 15% 14%;
--sidebar-accent-foreground: 240 10% 90%;
--sidebar-border: 240 12% 13%;
--sidebar-ring: 245 85% 68%;
}
/* ===== Base Styles ===== */
@@ -327,7 +327,8 @@ const RealtimePreviewDynamicComponent: React.FC<RealtimePreviewProps> = ({
};
}
}, [component.type, component.id, actualHeight, component.size?.height, onConfigChange]);
const { id, type, position, size, style: componentStyle } = component;
const { id, type, position: rawPosition, size, style: componentStyle } = component;
const position = rawPosition ?? { x: 0, y: 0, z: 1 };
// 선택 상태에 따른 스타일 (z-index 낮춤 - 패널과 모달보다 아래)
const selectionStyle = isSelected
@@ -449,7 +450,7 @@ const RealtimePreviewDynamicComponent: React.FC<RealtimePreviewProps> = ({
type === "component" && componentType === "v2-split-line";
if (isSplitLineComponent) {
return { adjustedPositionX: position.x, adjustedWidth: null, isOnSplitPanel: false, isDraggingSplitPanel: false };
return { adjustedPositionX: position?.x ?? 0, adjustedWidth: null, isOnSplitPanel: false, isDraggingSplitPanel: false };
}
// === 1. 캔버스 분할선 (글로벌 스토어) ===
@@ -460,7 +461,7 @@ const RealtimePreviewDynamicComponent: React.FC<RealtimePreviewProps> = ({
myScopeIdRef.current = container?.getAttribute("data-split-scope") || "__none__";
}
if (myScopeIdRef.current !== canvasSplit.scopeId) {
return { adjustedPositionX: position.x, adjustedWidth: null, isOnSplitPanel: false, isDraggingSplitPanel: false };
return { adjustedPositionX: position?.x ?? 0, adjustedWidth: null, isOnSplitPanel: false, isDraggingSplitPanel: false };
}
const { initialDividerX, currentDividerX, canvasWidth, isDragging: splitDragging } = canvasSplit;
const delta = currentDividerX - initialDividerX;
@@ -512,11 +513,11 @@ const RealtimePreviewDynamicComponent: React.FC<RealtimePreviewProps> = ({
type === "component" && ["split-panel-layout", "split-panel-layout2"].includes(componentType);
if (isSplitPanelComponent) {
return { adjustedPositionX: position.x, adjustedWidth: null, isOnSplitPanel: false, isDraggingSplitPanel: false };
return { adjustedPositionX: position?.x ?? 0, adjustedWidth: null, isOnSplitPanel: false, isDraggingSplitPanel: false };
}
if (!isButtonComponent) {
return { adjustedPositionX: position.x, adjustedWidth: null, isOnSplitPanel: false, isDraggingSplitPanel: false };
return { adjustedPositionX: position?.x ?? 0, adjustedWidth: null, isOnSplitPanel: false, isDraggingSplitPanel: false };
}
const componentWidth = size?.width || 100;
@@ -530,7 +531,7 @@ const RealtimePreviewDynamicComponent: React.FC<RealtimePreviewProps> = ({
initialPanelIdRef.current = null;
isInLeftPanelRef.current = null;
}
return { adjustedPositionX: position.x, adjustedWidth: null, isOnSplitPanel: false, isDraggingSplitPanel: false };
return { adjustedPositionX: position?.x ?? 0, adjustedWidth: null, isOnSplitPanel: false, isDraggingSplitPanel: false };
}
const { panel } = overlap;
@@ -56,20 +56,20 @@ function ProportionalRenderer({
className="bg-background relative h-full w-full overflow-hidden"
>
{containerW > 0 &&
topLevel.map((component) => {
topLevel.map((component, idx) => {
const typeId = getComponentTypeId(component);
return (
<div
key={component.id}
key={component.id ?? `comp-${idx}`}
data-component-id={component.id}
data-component-type={typeId}
style={{
position: "absolute",
left: `${(component.position.x / canvasWidth) * 100}%`,
top: `${(component.position.y / canvasHeight) * 100}%`,
left: `${((component.position?.x ?? 0) / canvasWidth) * 100}%`,
top: `${((component.position?.y ?? 0) / canvasHeight) * 100}%`,
width: `${((component.size?.width || 100) / canvasWidth) * 100}%`,
height: `${((component.size?.height || 40) / canvasHeight) * 100}%`,
zIndex: component.position.z || 1,
zIndex: component.position?.z ?? 1,
}}
>
{renderComponent(component)}
+749
View File
@@ -0,0 +1,749 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>INVION Cosmic Design System</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<style>
/* ===== Cosmic Design Tokens ===== */
:root {
--bg: #fafaff;
--bg-subtle: #f3f2fa;
--surface: #ffffff;
--surface-hover: #f7f6fd;
--text: #0f0e1a;
--text-secondary: #6b6a80;
--text-muted: #9998ad;
--primary: #6c5ce7;
--primary-light: #a29bfe;
--primary-dark: #5041c2;
--primary-glow: rgba(108, 92, 231, 0.25);
--accent-cyan: #00cec9;
--accent-cyan-glow: rgba(0, 206, 201, 0.2);
--accent-pink: #fd79a8;
--accent-pink-glow: rgba(253, 121, 168, 0.2);
--destructive: #ff4757;
--success: #00b894;
--warning: #fdcb6e;
--info: #0984e3;
--border: rgba(108, 92, 231, 0.1);
--border-subtle: rgba(0,0,0,0.06);
--card-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 4px 12px rgba(108,92,231,0.06);
--glow-sm: 0 0 15px rgba(108, 92, 231, 0.15);
--glow-md: 0 0 30px rgba(108, 92, 231, 0.2);
--glow-lg: 0 0 60px rgba(108, 92, 231, 0.25);
--radius: 12px;
--radius-lg: 20px;
--radius-full: 9999px;
}
.dark {
--bg: #08070f;
--bg-subtle: #0e0d1a;
--surface: #13122a;
--surface-hover: #1a1940;
--text: #e8e6f0;
--text-secondary: #8b89a6;
--text-muted: #5c5a75;
--primary: #a29bfe;
--primary-light: #c8c4ff;
--primary-dark: #6c5ce7;
--primary-glow: rgba(162, 155, 254, 0.3);
--accent-cyan: #55efc4;
--accent-cyan-glow: rgba(85, 239, 196, 0.15);
--accent-pink: #fd79a8;
--accent-pink-glow: rgba(253, 121, 168, 0.15);
--destructive: #ff6b6b;
--success: #55efc4;
--warning: #ffeaa7;
--info: #74b9ff;
--border: rgba(162, 155, 254, 0.12);
--border-subtle: rgba(255,255,255,0.05);
--card-shadow: 0 1px 3px rgba(0,0,0,0.3), 0 8px 24px rgba(0,0,0,0.4);
--glow-sm: 0 0 15px rgba(162, 155, 254, 0.15);
--glow-md: 0 0 30px rgba(162, 155, 254, 0.2);
--glow-lg: 0 0 60px rgba(162, 155, 254, 0.3);
}
/* ===== Reset & Base ===== */
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Inter', system-ui, sans-serif;
background: var(--bg);
color: var(--text);
transition: background 0.4s ease, color 0.3s ease;
overflow-x: hidden;
}
/* ===== Star Field Background (Dark Only) ===== */
.dark body::before {
content: '';
position: fixed;
inset: 0;
background-image:
radial-gradient(1px 1px at 10% 20%, rgba(255,255,255,0.4) 0%, transparent 100%),
radial-gradient(1px 1px at 30% 60%, rgba(255,255,255,0.3) 0%, transparent 100%),
radial-gradient(1px 1px at 50% 10%, rgba(255,255,255,0.5) 0%, transparent 100%),
radial-gradient(1px 1px at 70% 80%, rgba(255,255,255,0.3) 0%, transparent 100%),
radial-gradient(1px 1px at 90% 40%, rgba(255,255,255,0.4) 0%, transparent 100%),
radial-gradient(1.5px 1.5px at 15% 85%, rgba(162,155,254,0.6) 0%, transparent 100%),
radial-gradient(1.5px 1.5px at 55% 45%, rgba(85,239,196,0.5) 0%, transparent 100%),
radial-gradient(1.5px 1.5px at 85% 15%, rgba(253,121,168,0.5) 0%, transparent 100%),
radial-gradient(1px 1px at 25% 35%, rgba(255,255,255,0.2) 0%, transparent 100%),
radial-gradient(1px 1px at 45% 75%, rgba(255,255,255,0.25) 0%, transparent 100%),
radial-gradient(1px 1px at 65% 25%, rgba(255,255,255,0.3) 0%, transparent 100%),
radial-gradient(1px 1px at 80% 55%, rgba(255,255,255,0.2) 0%, transparent 100%),
radial-gradient(1px 1px at 5% 50%, rgba(255,255,255,0.35) 0%, transparent 100%),
radial-gradient(1px 1px at 95% 70%, rgba(255,255,255,0.3) 0%, transparent 100%),
radial-gradient(1px 1px at 40% 95%, rgba(255,255,255,0.2) 0%, transparent 100%),
radial-gradient(0.8px 0.8px at 20% 45%, rgba(255,255,255,0.15) 0%, transparent 100%),
radial-gradient(0.8px 0.8px at 60% 5%, rgba(255,255,255,0.2) 0%, transparent 100%),
radial-gradient(0.8px 0.8px at 75% 65%, rgba(255,255,255,0.15) 0%, transparent 100%);
pointer-events: none;
z-index: 0;
}
/* Nebula glow (Dark) */
.dark body::after {
content: '';
position: fixed;
top: -30%;
right: -20%;
width: 800px;
height: 800px;
background: radial-gradient(circle, rgba(108,92,231,0.08) 0%, rgba(253,121,168,0.04) 40%, transparent 70%);
pointer-events: none;
z-index: 0;
}
/* Light mode subtle gradient */
body::before {
content: '';
position: fixed;
top: -200px;
right: -200px;
width: 600px;
height: 600px;
background: radial-gradient(circle, rgba(108,92,231,0.06) 0%, transparent 70%);
pointer-events: none;
z-index: 0;
}
.preview-container {
max-width: 1300px;
margin: 0 auto;
padding: 2.5rem;
position: relative;
z-index: 1;
}
/* ===== Header ===== */
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 3.5rem;
padding-bottom: 2rem;
border-bottom: 1px solid var(--border);
}
.header h1 {
font-size: 2rem;
font-weight: 800;
letter-spacing: -0.03em;
background: linear-gradient(135deg, var(--primary) 0%, var(--accent-cyan) 50%, var(--accent-pink) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.header p {
color: var(--text-muted);
font-size: 0.85rem;
margin-top: 0.35rem;
font-weight: 400;
}
.theme-toggle {
display: flex;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-full);
padding: 3px;
gap: 2px;
}
.theme-toggle button {
padding: 0.5rem 1.2rem;
border-radius: var(--radius-full);
border: none;
background: transparent;
color: var(--text-muted);
cursor: pointer;
font-size: 0.8rem;
font-weight: 500;
transition: all 0.25s;
font-family: inherit;
}
.theme-toggle button.active {
background: var(--primary);
color: white;
box-shadow: var(--glow-sm);
}
/* ===== Section ===== */
.section { margin-bottom: 3.5rem; }
.section-title {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--primary);
margin-bottom: 1rem;
}
.section-subtitle {
font-size: 1.15rem;
font-weight: 600;
color: var(--text);
margin-bottom: 1.25rem;
letter-spacing: -0.01em;
}
/* ===== Color Palette ===== */
.color-grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 0.75rem;
}
.color-card {
border-radius: var(--radius);
overflow: hidden;
border: 1px solid var(--border);
background: var(--surface);
transition: transform 0.2s, box-shadow 0.2s;
}
.color-card:hover {
transform: translateY(-2px);
box-shadow: var(--glow-sm);
}
.color-swatch {
height: 64px;
display: flex;
align-items: flex-end;
padding: 0.5rem;
font-size: 0.6rem;
font-weight: 600;
letter-spacing: 0.02em;
}
.color-info { padding: 0.6rem; }
.color-name { font-size: 0.75rem; font-weight: 600; color: var(--text); }
.color-value { font-size: 0.65rem; color: var(--text-muted); margin-top: 2px; }
/* ===== Buttons ===== */
.button-row {
display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center;
margin-bottom: 0.75rem;
}
.btn {
display: inline-flex; align-items: center; justify-content: center;
padding: 0.55rem 1.2rem; border-radius: var(--radius); font-size: 0.8rem;
font-weight: 600; cursor: pointer; border: none; transition: all 0.2s;
font-family: inherit; letter-spacing: -0.01em;
}
.btn-primary {
background: var(--primary); color: white;
box-shadow: 0 2px 8px var(--primary-glow);
}
.btn-primary:hover { box-shadow: var(--glow-md); transform: translateY(-1px); }
.btn-secondary { background: var(--surface); color: var(--text); border: 1px solid var(--border); }
.btn-destructive { background: var(--destructive); color: white; }
.btn-success { background: var(--success); color: #0a2e1f; }
.btn-warning { background: var(--warning); color: #3d2e00; }
.btn-outline { background: transparent; color: var(--primary); border: 1px solid var(--primary); }
.btn-outline:hover { background: var(--primary); color: white; }
.btn-ghost { background: transparent; color: var(--text-secondary); }
.btn-ghost:hover { background: var(--surface-hover); color: var(--text); }
.btn-sm { height: 1.85rem; padding: 0 0.75rem; font-size: 0.7rem; }
.btn-lg { height: 2.75rem; padding: 0 2rem; font-size: 0.85rem; }
.btn-cosmic {
background: linear-gradient(135deg, var(--primary) 0%, #a29bfe 50%, var(--accent-cyan) 100%);
color: white; font-weight: 700;
box-shadow: 0 4px 20px var(--primary-glow), 0 0 40px rgba(0,206,201,0.1);
}
.btn-cosmic:hover { box-shadow: var(--glow-lg); transform: translateY(-2px); }
/* ===== Badges ===== */
.badge {
display: inline-flex; align-items: center; padding: 0.2rem 0.6rem;
border-radius: var(--radius-full); font-size: 0.65rem; font-weight: 600;
}
.badge-primary { background: rgba(108,92,231,0.12); color: var(--primary); }
.badge-success { background: rgba(0,184,148,0.12); color: var(--success); }
.badge-warning { background: rgba(253,203,110,0.2); color: #b8860b; }
.dark .badge-warning { color: var(--warning); background: rgba(253,203,110,0.1); }
.badge-destructive { background: rgba(255,71,87,0.12); color: var(--destructive); }
.badge-info { background: rgba(9,132,227,0.12); color: var(--info); }
.badge-cyan { background: var(--accent-cyan-glow); color: var(--accent-cyan); }
.badge-pink { background: var(--accent-pink-glow); color: var(--accent-pink); }
/* ===== Inputs ===== */
.input-row { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }
.input-group { display: flex; flex-direction: column; gap: 0.4rem; min-width: 200px; flex: 1; }
.input-label { font-size: 0.75rem; font-weight: 500; color: var(--text-secondary); }
.input-field {
height: 2.5rem; padding: 0 0.85rem; border: 1px solid var(--border);
border-radius: var(--radius); background: var(--surface); color: var(--text);
font-size: 0.8rem; font-family: inherit; outline: none; transition: all 0.2s;
}
.input-field::placeholder { color: var(--text-muted); }
.input-field:focus {
border-color: var(--primary);
box-shadow: 0 0 0 3px var(--primary-glow);
}
/* ===== Cards ===== */
.card-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.card {
background: var(--surface); border: 1px solid var(--border);
border-radius: var(--radius-lg); padding: 1.75rem;
transition: all 0.25s;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--card-shadow); }
.card-title { font-size: 0.95rem; font-weight: 600; color: var(--text); margin-bottom: 0.5rem; }
.card-desc { font-size: 0.8rem; color: var(--text-secondary); line-height: 1.6; }
.card-glass {
background: rgba(255,255,255,0.5); backdrop-filter: blur(20px);
border: 1px solid rgba(108,92,231,0.1);
}
.dark .card-glass {
background: rgba(19,18,42,0.6);
border: 1px solid rgba(162,155,254,0.1);
}
.card-glow {
border: 1px solid rgba(108,92,231,0.2);
box-shadow: var(--glow-sm);
}
.card-glow:hover { box-shadow: var(--glow-md); }
.card-gradient {
background: linear-gradient(135deg, var(--surface) 0%, rgba(108,92,231,0.05) 100%);
border: 1px solid rgba(108,92,231,0.12);
}
.dark .card-gradient {
background: linear-gradient(135deg, var(--surface) 0%, rgba(162,155,254,0.08) 100%);
}
/* ===== Table ===== */
.table-wrapper {
border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden;
background: var(--surface);
}
table { width: 100%; border-collapse: collapse; font-size: 0.8rem; }
th {
text-align: left; padding: 0.85rem 1.2rem;
background: var(--bg-subtle); color: var(--text-muted);
font-weight: 600; font-size: 0.7rem; text-transform: uppercase;
letter-spacing: 0.06em; border-bottom: 1px solid var(--border);
}
td {
padding: 0.85rem 1.2rem; border-bottom: 1px solid var(--border-subtle);
color: var(--text);
}
tr:last-child td { border-bottom: none; }
tr:hover td { background: var(--surface-hover); }
/* ===== Layout Preview ===== */
.layout-preview {
display: grid; grid-template-columns: 240px 1fr;
height: 520px; border: 1px solid var(--border);
border-radius: var(--radius-lg); overflow: hidden;
}
.sidebar-preview {
background: var(--bg-subtle); border-right: 1px solid var(--border);
padding: 1.5rem; display: flex; flex-direction: column; gap: 2px;
}
.sidebar-logo {
font-size: 1.1rem; font-weight: 800; letter-spacing: -0.03em;
margin-bottom: 2rem; padding-left: 0.5rem;
background: linear-gradient(135deg, var(--primary), var(--accent-cyan));
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.sidebar-item {
padding: 0.55rem 0.75rem; border-radius: 8px; font-size: 0.8rem;
color: var(--text-secondary); cursor: pointer; transition: all 0.15s; font-weight: 450;
}
.sidebar-item:hover { background: var(--surface-hover); color: var(--text); }
.sidebar-item.active {
background: linear-gradient(135deg, rgba(108,92,231,0.1), rgba(108,92,231,0.05));
color: var(--primary); font-weight: 600;
border: 1px solid rgba(108,92,231,0.15);
}
.dark .sidebar-item.active {
background: linear-gradient(135deg, rgba(162,155,254,0.12), rgba(162,155,254,0.05));
color: var(--primary);
border-color: rgba(162,155,254,0.15);
}
.sidebar-section {
font-size: 0.6rem; font-weight: 700; text-transform: uppercase;
letter-spacing: 0.1em; color: var(--text-muted);
padding: 1rem 0.75rem 0.4rem; margin-top: 0.25rem;
}
.main-content {
background: var(--bg); padding: 2rem; overflow-y: auto;
}
.main-header {
display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;
}
.main-title { font-size: 1.15rem; font-weight: 700; letter-spacing: -0.02em; }
.main-subtitle { font-size: 0.75rem; color: var(--text-muted); margin-top: 0.2rem; }
/* ===== Login Preview ===== */
.login-preview {
display: flex; align-items: center; justify-content: center;
min-height: 560px; border-radius: var(--radius-lg);
position: relative; overflow: hidden;
background: var(--bg);
border: 1px solid var(--border);
}
.login-nebula {
position: absolute; border-radius: 50%; filter: blur(100px); pointer-events: none;
}
.login-nebula-1 {
width: 500px; height: 500px; top: -150px; right: -100px;
background: radial-gradient(circle, var(--primary-glow) 0%, transparent 70%);
}
.login-nebula-2 {
width: 400px; height: 400px; bottom: -200px; left: -100px;
background: radial-gradient(circle, var(--accent-cyan-glow) 0%, transparent 70%);
}
.login-nebula-3 {
width: 300px; height: 300px; top: 50%; left: 50%;
transform: translate(-50%, -50%);
background: radial-gradient(circle, var(--accent-pink-glow) 0%, transparent 70%);
}
.login-card {
position: relative; width: 400px;
background: rgba(255,255,255,0.7); backdrop-filter: blur(24px);
border: 1px solid rgba(108,92,231,0.12);
border-radius: var(--radius-lg); padding: 2.5rem;
box-shadow: 0 8px 40px rgba(0,0,0,0.06);
}
.dark .login-card {
background: rgba(19,18,42,0.7);
border: 1px solid rgba(162,155,254,0.12);
box-shadow: 0 8px 40px rgba(0,0,0,0.5), var(--glow-sm);
}
.login-logo {
text-align: center; font-size: 1.6rem; font-weight: 800; letter-spacing: -0.03em;
margin-bottom: 0.5rem;
background: linear-gradient(135deg, var(--primary), var(--accent-cyan));
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.login-subtitle {
text-align: center; font-size: 0.8rem; color: var(--text-muted); margin-bottom: 2rem;
}
.login-form { display: flex; flex-direction: column; gap: 1rem; }
.login-btn {
height: 2.75rem; margin-top: 0.5rem;
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%);
color: white; border: none; border-radius: var(--radius); font-size: 0.85rem;
font-weight: 600; cursor: pointer; font-family: inherit; transition: all 0.25s;
box-shadow: 0 4px 15px var(--primary-glow);
}
.login-btn:hover {
box-shadow: var(--glow-md); transform: translateY(-1px);
}
.login-footer {
text-align: center; margin-top: 1.25rem;
font-size: 0.75rem; color: var(--text-muted);
}
.login-footer a { color: var(--primary); text-decoration: none; font-weight: 500; }
/* ===== Chart ===== */
.chart-bars { display: flex; flex-direction: column; gap: 0.4rem; }
.chart-bar {
height: 36px; border-radius: 8px; display: flex; align-items: center;
padding: 0 1rem; font-size: 0.7rem; font-weight: 600; color: white;
transition: all 0.2s;
}
.chart-bar:hover { transform: scaleX(1.02); transform-origin: left; }
/* ===== Stats Row ===== */
.stats-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 1rem; }
.stat-card {
background: var(--surface); border: 1px solid var(--border);
border-radius: var(--radius); padding: 1.25rem; text-align: center;
}
.stat-value {
font-size: 1.75rem; font-weight: 800; letter-spacing: -0.03em;
background: linear-gradient(135deg, var(--primary), var(--accent-cyan));
-webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
}
.stat-label { font-size: 0.7rem; color: var(--text-muted); margin-top: 0.3rem; font-weight: 500; }
/* ===== Divider ===== */
.divider { height: 1px; background: var(--border); margin: 2rem 0; }
</style>
</head>
<body>
<div class="preview-container">
<!-- Header -->
<div class="header">
<div>
<h1>INVION Cosmic Design System</h1>
<p>Deep Space / Stellar White</p>
</div>
<div class="theme-toggle">
<button class="active" onclick="setTheme('light')">Stellar White</button>
<button onclick="setTheme('dark')">Deep Space</button>
</div>
</div>
<!-- Color Palette -->
<div class="section">
<div class="section-title">Color System</div>
<div class="section-subtitle">Core Semantic Palette</div>
<div class="color-grid">
<div class="color-card">
<div class="color-swatch" style="background:var(--primary);color:white">PRIMARY</div>
<div class="color-info"><div class="color-name">Cosmic Violet</div><div class="color-value">#6c5ce7 / #a29bfe</div></div>
</div>
<div class="color-card">
<div class="color-swatch" style="background:var(--accent-cyan);color:#0a2e2d">ACCENT</div>
<div class="color-info"><div class="color-name">Nebula Cyan</div><div class="color-value">#00cec9 / #55efc4</div></div>
</div>
<div class="color-card">
<div class="color-swatch" style="background:var(--accent-pink);color:white">ACCENT</div>
<div class="color-info"><div class="color-name">Stellar Pink</div><div class="color-value">#fd79a8</div></div>
</div>
<div class="color-card">
<div class="color-swatch" style="background:var(--success);color:white">SUCCESS</div>
<div class="color-info"><div class="color-name">Aurora Green</div><div class="color-value">#00b894 / #55efc4</div></div>
</div>
<div class="color-card">
<div class="color-swatch" style="background:var(--destructive);color:white">ERROR</div>
<div class="color-info"><div class="color-name">Supernova Red</div><div class="color-value">#ff4757 / #ff6b6b</div></div>
</div>
<div class="color-card">
<div class="color-swatch" style="background:var(--warning);color:#3d2e00">WARNING</div>
<div class="color-info"><div class="color-name">Solar Amber</div><div class="color-value">#fdcb6e / #ffeaa7</div></div>
</div>
</div>
<div style="margin-top:0.75rem">
<div class="color-grid" style="grid-template-columns: repeat(4, 1fr)">
<div class="color-card">
<div class="color-swatch" style="background:var(--bg);color:var(--text);border-bottom:1px solid var(--border)">BG</div>
<div class="color-info"><div class="color-name">Background</div><div class="color-value">Space / White</div></div>
</div>
<div class="color-card">
<div class="color-swatch" style="background:var(--surface);color:var(--text);border-bottom:1px solid var(--border)">SURFACE</div>
<div class="color-info"><div class="color-name">Surface</div><div class="color-value">Card layer</div></div>
</div>
<div class="color-card">
<div class="color-swatch" style="background:var(--text);color:var(--bg)">TEXT</div>
<div class="color-info"><div class="color-name">Foreground</div><div class="color-value">Primary text</div></div>
</div>
<div class="color-card">
<div class="color-swatch" style="background:var(--border);height:32px"></div>
<div class="color-info"><div class="color-name">Border</div><div class="color-value">Stardust line</div></div>
</div>
</div>
</div>
</div>
<!-- Buttons -->
<div class="section">
<div class="section-title">Interactive</div>
<div class="section-subtitle">Buttons & Badges</div>
<div class="button-row">
<button class="btn btn-primary">Primary</button>
<button class="btn btn-secondary">Secondary</button>
<button class="btn btn-outline">Outline</button>
<button class="btn btn-ghost">Ghost</button>
<button class="btn btn-destructive">Delete</button>
<button class="btn btn-success">Confirm</button>
<button class="btn btn-cosmic btn-lg">Launch Mission</button>
</div>
<div class="button-row" style="margin-top:0.5rem">
<span class="badge badge-primary">Deployed</span>
<span class="badge badge-success">Online</span>
<span class="badge badge-warning">Standby</span>
<span class="badge badge-destructive">Offline</span>
<span class="badge badge-info">Syncing</span>
<span class="badge badge-cyan">Connected</span>
<span class="badge badge-pink">New</span>
</div>
</div>
<!-- Form -->
<div class="section">
<div class="section-title">Form</div>
<div class="section-subtitle">Input Fields</div>
<div class="input-row">
<div class="input-group">
<label class="input-label">Username</label>
<input class="input-field" value="commander">
</div>
<div class="input-group">
<label class="input-label">Email</label>
<input class="input-field" type="email" placeholder="pilot@invion.io">
</div>
<div class="input-group">
<label class="input-label">Password</label>
<input class="input-field" type="password" value="cosmicpass">
</div>
<div class="input-group">
<label class="input-label">Search</label>
<input class="input-field" placeholder="Search the galaxy...">
</div>
</div>
</div>
<!-- Cards -->
<div class="section">
<div class="section-title">Surfaces</div>
<div class="section-subtitle">Card Variants</div>
<div class="card-grid">
<div class="card">
<div class="card-title">Standard</div>
<div class="card-desc">Default card surface. Clean border with subtle elevation on hover.</div>
</div>
<div class="card card-glass">
<div class="card-title">Glass</div>
<div class="card-desc">Glassmorphism with backdrop blur. Cosmic transparency for overlays.</div>
</div>
<div class="card card-glow">
<div class="card-title">Glow</div>
<div class="card-desc">Subtle cosmic glow. For featured or highlighted content.</div>
</div>
<div class="card card-gradient">
<div class="card-title">Gradient</div>
<div class="card-desc">Nebula gradient surface. For premium or interactive sections.</div>
</div>
</div>
</div>
<!-- Table -->
<div class="section">
<div class="section-title">Data</div>
<div class="section-subtitle">Table & Statistics</div>
<div class="stats-row">
<div class="stat-card"><div class="stat-value">1,247</div><div class="stat-label">Total Devices</div></div>
<div class="stat-card"><div class="stat-value">98.5%</div><div class="stat-label">Uptime</div></div>
<div class="stat-card"><div class="stat-value">342</div><div class="stat-label">Active Sessions</div></div>
<div class="stat-card"><div class="stat-value">12ms</div><div class="stat-label">Avg Latency</div></div>
</div>
<div class="table-wrapper">
<table>
<thead><tr><th>Device</th><th>Serial</th><th>Manufacturer</th><th>Model</th><th>Region</th><th>Status</th></tr></thead>
<tbody>
<tr><td style="font-weight:500">DTG-001</td><td>0004</td><td>LOOP</td><td>LDT400BS</td><td>Seoul</td><td><span class="badge badge-success">Active</span></td></tr>
<tr><td style="font-weight:500">DTG-002</td><td>0001</td><td>LOOP</td><td>LDT400BS</td><td>Busan</td><td><span class="badge badge-warning">Standby</span></td></tr>
<tr><td style="font-weight:500">DTG-003</td><td>0003</td><td>LOOP</td><td>LDT400BS</td><td>Incheon</td><td><span class="badge badge-primary">Installing</span></td></tr>
<tr><td style="font-weight:500">DTG-004</td><td>0005</td><td>LOOP</td><td>LDT400BS</td><td>Daegu</td><td><span class="badge badge-destructive">Offline</span></td></tr>
<tr><td style="font-weight:500">DTG-005</td><td>0007</td><td>LOOP</td><td>LDT500BS</td><td>Jeju</td><td><span class="badge badge-cyan">Syncing</span></td></tr>
</tbody>
</table>
</div>
</div>
<!-- Chart -->
<div class="section">
<div class="section-title">Visualization</div>
<div class="section-subtitle">Chart Palette</div>
<div class="chart-bars">
<div class="chart-bar" style="background:linear-gradient(90deg, var(--primary), var(--primary-light));width:92%">Nebula Purple — 92%</div>
<div class="chart-bar" style="background:linear-gradient(90deg, #00b894, var(--accent-cyan));width:78%">Aurora Green — 78%</div>
<div class="chart-bar" style="background:linear-gradient(90deg, #0984e3, #74b9ff);width:85%">Stellar Blue — 85%</div>
<div class="chart-bar" style="background:linear-gradient(90deg, #e17055, var(--accent-pink));width:64%">Cosmic Pink — 64%</div>
<div class="chart-bar" style="background:linear-gradient(90deg, #d4a017, var(--warning));width:71%">Solar Gold — 71%</div>
</div>
</div>
<!-- Login -->
<div class="section">
<div class="section-title">Authentication</div>
<div class="section-subtitle">Login Page</div>
<div class="login-preview">
<div class="login-nebula login-nebula-1"></div>
<div class="login-nebula login-nebula-2"></div>
<div class="login-nebula login-nebula-3"></div>
<div class="login-card">
<div class="login-logo">INVION</div>
<div class="login-subtitle">Welcome to the cosmos</div>
<div class="login-form">
<div class="input-group">
<label class="input-label">User ID</label>
<input class="input-field" value="commander">
</div>
<div class="input-group">
<label class="input-label">Password</label>
<input class="input-field" type="password" value="cosmicpass">
</div>
<button class="login-btn">Sign In</button>
<div class="login-footer">Powered by <a href="#">INVION</a></div>
</div>
</div>
</div>
</div>
<!-- Layout -->
<div class="section">
<div class="section-title">Layout</div>
<div class="section-subtitle">Sidebar + Content</div>
<div class="layout-preview">
<div class="sidebar-preview">
<div class="sidebar-logo">INVION</div>
<div class="sidebar-section">Management</div>
<div class="sidebar-item active">DTG Management</div>
<div class="sidebar-item">Settlement</div>
<div class="sidebar-item">Logistics Control</div>
<div class="sidebar-section">Configuration</div>
<div class="sidebar-item">Menu Settings</div>
<div class="sidebar-item">User Management</div>
<div class="sidebar-item">Screen Builder</div>
<div class="sidebar-section">Analytics</div>
<div class="sidebar-item">Dashboard</div>
<div class="sidebar-item">Reports</div>
</div>
<div class="main-content">
<div class="main-header">
<div>
<div class="main-title">DTG Management</div>
<div class="main-subtitle">4 devices registered</div>
</div>
<button class="btn btn-primary">+ New Device</button>
</div>
<div class="stats-row">
<div class="stat-card"><div class="stat-value">4</div><div class="stat-label">Registered</div></div>
<div class="stat-card"><div class="stat-value">3</div><div class="stat-label">Installed</div></div>
<div class="stat-card"><div class="stat-value">0</div><div class="stat-label">Maintenance</div></div>
<div class="stat-card"><div class="stat-value">0</div><div class="stat-label">Decommissioned</div></div>
</div>
<div class="table-wrapper">
<table>
<thead><tr><th>Code</th><th>Serial</th><th>Model</th><th>Status</th></tr></thead>
<tbody>
<tr><td>DTG-001</td><td>0004</td><td>LDT400BS</td><td><span class="badge badge-success">Active</span></td></tr>
<tr><td>DTG-002</td><td>0001</td><td>LDT400BS</td><td><span class="badge badge-warning">Standby</span></td></tr>
<tr><td>DTG-003</td><td>0003</td><td>LDT400BS</td><td><span class="badge badge-primary">Installing</span></td></tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<script>
function setTheme(t) {
document.documentElement.classList.toggle('dark', t === 'dark');
document.body.classList.toggle('dark', t === 'dark');
document.querySelectorAll('.theme-toggle button').forEach(b => {
b.classList.toggle('active', b.textContent.includes(t === 'dark' ? 'Deep' : 'Stellar'));
});
}
</script>
</body>
</html>
+47 -47
View File
@@ -1,85 +1,85 @@
// WACE 솔루션 공통 테마 정의
// VEXPLOR Cosmic Design System — 우주 테마 정의
export const theme = {
// 색상 팔레트
// 색상 팔레트 (Stellar White — 라이트 모드)
colors: {
// 주요 브랜드 색상
// 주요 브랜드 색상: Cosmic Indigo-Violet
primary: {
50: "hsl(210 40% 98%)",
100: "hsl(210 40% 96%)",
200: "hsl(214 32% 91%)",
300: "hsl(213 27% 84%)",
400: "hsl(215 20% 65%)",
500: "hsl(215 16% 47%)",
600: "hsl(215 19% 35%)",
700: "hsl(215 25% 27%)",
800: "hsl(217 33% 17%)",
900: "hsl(222.2 47.4% 11.2%)",
DEFAULT: "hsl(222.2 47.4% 11.2%)",
foreground: "hsl(210 40% 98%)",
50: "hsl(245 80% 98%)",
100: "hsl(245 70% 95%)",
200: "hsl(245 60% 90%)",
300: "hsl(245 55% 82%)",
400: "hsl(245 65% 70%)",
500: "hsl(245 75% 57%)",
600: "hsl(245 75% 50%)",
700: "hsl(245 70% 42%)",
800: "hsl(245 65% 33%)",
900: "hsl(245 55% 22%)",
DEFAULT: "hsl(245 75% 57%)",
foreground: "hsl(0 0% 100%)",
},
// 보조 색상
// 보조 색상: Nebula Slate
secondary: {
DEFAULT: "hsl(210 40% 96%)",
foreground: "hsl(222.2 84% 4.9%)",
DEFAULT: "hsl(240 10% 95%)",
foreground: "hsl(240 20% 15%)",
},
// 액센트 색상
// 액센트 색상: Stellar Surface
accent: {
DEFAULT: "hsl(210 40% 98%)",
foreground: "hsl(222.2 84% 4.9%)",
DEFAULT: "hsl(240 10% 93%)",
foreground: "hsl(240 20% 15%)",
},
// 파괴적 액션 (삭제, 경고 등)
// 파괴적 액션: Supernova Red
destructive: {
DEFAULT: "hsl(0 62.8% 30.6%)",
foreground: "hsl(210 40% 98%)",
DEFAULT: "hsl(0 80% 60%)",
foreground: "hsl(0 0% 100%)",
},
// 성공 색상
// 성공: Aurora Green
success: {
DEFAULT: "hsl(142.1 76.2% 36.3%)",
foreground: "hsl(355.7 100% 97.3%)",
DEFAULT: "hsl(152 72% 38%)",
foreground: "hsl(0 0% 100%)",
},
// 경고 색상
// 경고: Stellar Amber
warning: {
DEFAULT: "hsl(32.1 94.6% 43.7%)",
foreground: "hsl(355.7 100% 97.3%)",
DEFAULT: "hsl(38 95% 50%)",
foreground: "hsl(0 0% 100%)",
},
// 정보 색상
// 정보: Nebula Cyan
info: {
DEFAULT: "hsl(221.2 83.2% 53.3%)",
foreground: "hsl(210 40% 98%)",
DEFAULT: "hsl(195 90% 45%)",
foreground: "hsl(0 0% 100%)",
},
// 뮤트된 색상
// 뮤트: Cosmic Dust
muted: {
DEFAULT: "hsl(210 40% 96%)",
foreground: "hsl(215.4 16.3% 46.9%)",
DEFAULT: "hsl(240 10% 94%)",
foreground: "hsl(240 5% 46%)",
},
// 배경 색상
background: "hsl(0 0% 100%)",
foreground: "hsl(222.2 84% 4.9%)",
// 배경: Stellar White
background: "hsl(240 20% 99%)",
foreground: "hsl(240 10% 5%)",
// 카드 색상
// 카드: Pure White
card: {
DEFAULT: "hsl(0 0% 100%)",
foreground: "hsl(222.2 84% 4.9%)",
foreground: "hsl(240 10% 5%)",
},
// 팝오버 색상
// 팝오버
popover: {
DEFAULT: "hsl(0 0% 100%)",
foreground: "hsl(222.2 84% 4.9%)",
foreground: "hsl(240 10% 5%)",
},
// 테두리 색상
border: "hsl(214.3 31.8% 91.4%)",
input: "hsl(214.3 31.8% 91.4%)",
ring: "hsl(222.2 84% 4.9%)",
// 테두리: Stardust
border: "hsl(240 8% 88%)",
input: "hsl(240 8% 88%)",
ring: "hsl(245 75% 57%)",
},
// 타이포그래피