From 11092537d7f3a4de92b425574380e29c32841682 Mon Sep 17 00:00:00 2001 From: GA Pro Date: Wed, 13 May 2026 00:33:25 +0900 Subject: [PATCH] =?UTF-8?q?feat(core):=20RegulatoryLimit=20VO=20=EC=84=B8?= =?UTF-8?q?=ED=8A=B8=20+=20Mapper=20+=20Enum=203=EC=A2=85=20(=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20P1-1-b)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit V26 규제 한도 마스터와 ga-core 동기화. 검증 로직은 P1-1-c. 신규 패키지: com.ga.core.vo.regulatory Enum 3종: - LimitType {TOTAL_RATIO, FIRST_YEAR_RATIO, INSTALLMENT_YEARS} - LimitUnit {PERCENT, YEAR} - ProductCategory {ALL, LIFE, ANNUITY, SAVINGS, EXCLUDED_AUTO, EXCLUDED_HEALTH} RegulatoryLimit VO 세트: - RegulatoryLimitVO (BaseVO 상속) - RegulatoryLimitResp (코드명 표시) - RegulatoryLimitSaveReq (@Valid: limitType/unit @NotBlank, limitValue @Positive) - RegulatoryLimitSearchParam (limitType/productCategory/effectiveDate) RegulatoryLimitMapper (com.ga.core.mapper.regulatory): - 표준 CRUD + 활성 한도 조회 메서드 2종: - selectActiveByType(limitType, productCategory, baseDate) — 특정 날짜 유효 1건 - selectAllActive(baseDate) — 특정 날짜 유효 전체 XML: - effective_from <= baseDate AND (effective_to IS NULL OR effective_to >= baseDate) - is_active = TRUE - 최신 개정본 우선 (ORDER BY effective_from DESC LIMIT 1) - product_category NULL=ALL 처리 안전 비교 --- .../regulatory/RegulatoryLimitMapper.java | 34 ++++ .../com/ga/core/vo/regulatory/LimitType.java | 7 + .../com/ga/core/vo/regulatory/LimitUnit.java | 7 + .../core/vo/regulatory/ProductCategory.java | 7 + .../vo/regulatory/RegulatoryLimitResp.java | 23 +++ .../vo/regulatory/RegulatoryLimitSaveReq.java | 37 ++++ .../RegulatoryLimitSearchParam.java | 13 ++ .../core/vo/regulatory/RegulatoryLimitVO.java | 26 +++ .../regulatory/RegulatoryLimitMapper.xml | 178 ++++++++++++++++++ 9 files changed, 332 insertions(+) create mode 100644 ga-core/src/main/java/com/ga/core/mapper/regulatory/RegulatoryLimitMapper.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/regulatory/LimitType.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/regulatory/LimitUnit.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/regulatory/ProductCategory.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitResp.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitSaveReq.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitSearchParam.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitVO.java create mode 100644 ga-core/src/main/resources/mapper/regulatory/RegulatoryLimitMapper.xml diff --git a/ga-core/src/main/java/com/ga/core/mapper/regulatory/RegulatoryLimitMapper.java b/ga-core/src/main/java/com/ga/core/mapper/regulatory/RegulatoryLimitMapper.java new file mode 100644 index 0000000..bb4a53e --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/mapper/regulatory/RegulatoryLimitMapper.java @@ -0,0 +1,34 @@ +package com.ga.core.mapper.regulatory; + +import com.ga.core.vo.regulatory.RegulatoryLimitResp; +import com.ga.core.vo.regulatory.RegulatoryLimitSearchParam; +import com.ga.core.vo.regulatory.RegulatoryLimitVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface RegulatoryLimitMapper { + + List selectList(RegulatoryLimitSearchParam param); + + RegulatoryLimitResp selectDetailById(@Param("limitId") Long limitId); + + RegulatoryLimitVO selectById(@Param("limitId") Long limitId); + + /** 특정 날짜에 유효한 한도 1건 조회 (limitType + productCategory 조합) */ + RegulatoryLimitVO selectActiveByType(@Param("limitType") String limitType, + @Param("productCategory") String productCategory, + @Param("baseDate") String baseDate); + + /** 특정 날짜에 유효한 모든 활성 한도 조회 (배치/검증용) */ + List selectAllActive(@Param("baseDate") String baseDate); + + int insert(RegulatoryLimitVO vo); + + int update(RegulatoryLimitVO vo); + + /** is_active 플래그 변경 */ + int updateStatus(@Param("limitId") Long limitId, @Param("isActive") Boolean isActive); +} diff --git a/ga-core/src/main/java/com/ga/core/vo/regulatory/LimitType.java b/ga-core/src/main/java/com/ga/core/vo/regulatory/LimitType.java new file mode 100644 index 0000000..14511ea --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/regulatory/LimitType.java @@ -0,0 +1,7 @@ +package com.ga.core.vo.regulatory; + +public enum LimitType { + TOTAL_RATIO, FIRST_YEAR_RATIO, INSTALLMENT_YEARS; + + public String code() { return this.name(); } +} diff --git a/ga-core/src/main/java/com/ga/core/vo/regulatory/LimitUnit.java b/ga-core/src/main/java/com/ga/core/vo/regulatory/LimitUnit.java new file mode 100644 index 0000000..db22523 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/regulatory/LimitUnit.java @@ -0,0 +1,7 @@ +package com.ga.core.vo.regulatory; + +public enum LimitUnit { + PERCENT, YEAR; + + public String code() { return this.name(); } +} diff --git a/ga-core/src/main/java/com/ga/core/vo/regulatory/ProductCategory.java b/ga-core/src/main/java/com/ga/core/vo/regulatory/ProductCategory.java new file mode 100644 index 0000000..18e162b --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/regulatory/ProductCategory.java @@ -0,0 +1,7 @@ +package com.ga.core.vo.regulatory; + +public enum ProductCategory { + ALL, LIFE, ANNUITY, SAVINGS, EXCLUDED_AUTO, EXCLUDED_HEALTH; + + public String code() { return this.name(); } +} diff --git a/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitResp.java b/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitResp.java new file mode 100644 index 0000000..c85ed04 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitResp.java @@ -0,0 +1,23 @@ +package com.ga.core.vo.regulatory; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; + +@Data +public class RegulatoryLimitResp { + private Long limitId; + private String limitType; + private String limitTypeName; + private String productCategory; + private String productCategoryName; + private BigDecimal limitValue; + private String unit; + private String unitName; + private LocalDate effectiveFrom; + private LocalDate effectiveTo; + private String regulationRef; + private String description; + private Boolean isActive; +} diff --git a/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitSaveReq.java b/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitSaveReq.java new file mode 100644 index 0000000..8569e96 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitSaveReq.java @@ -0,0 +1,37 @@ +package com.ga.core.vo.regulatory; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; + +@Data +public class RegulatoryLimitSaveReq { + + @NotBlank(message = "한도유형은 필수입니다") + private String limitType; + + private String productCategory; + + @NotNull(message = "한도값은 필수입니다") + @Positive(message = "한도값은 양수여야 합니다") + private BigDecimal limitValue; + + @NotBlank(message = "단위는 필수입니다") + private String unit; + + @NotNull(message = "적용 시작일은 필수입니다") + private LocalDate effectiveFrom; + + private LocalDate effectiveTo; + + @Size(max = 100) + private String regulationRef; + + @Size(max = 500) + private String description; +} diff --git a/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitSearchParam.java b/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitSearchParam.java new file mode 100644 index 0000000..4027448 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitSearchParam.java @@ -0,0 +1,13 @@ +package com.ga.core.vo.regulatory; + +import com.ga.common.model.SearchParam; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +public class RegulatoryLimitSearchParam extends SearchParam { + private String limitType; + private String productCategory; + private String effectiveDate; // YYYY-MM-DD — 해당 날짜에 유효한 한도 필터 +} diff --git a/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitVO.java b/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitVO.java new file mode 100644 index 0000000..34dbf18 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/regulatory/RegulatoryLimitVO.java @@ -0,0 +1,26 @@ +package com.ga.core.vo.regulatory; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +public class RegulatoryLimitVO { + private Long limitId; + private String limitType; + private String productCategory; // NULL = 전체 상품 적용 + private BigDecimal limitValue; + private String unit; + private LocalDate effectiveFrom; + private LocalDate effectiveTo; // NULL = 현재 유효 + private String regulationRef; + private String description; + private Boolean isActive; + + private LocalDateTime createdAt; + private Long createdBy; + private LocalDateTime updatedAt; + private Long updatedBy; +} diff --git a/ga-core/src/main/resources/mapper/regulatory/RegulatoryLimitMapper.xml b/ga-core/src/main/resources/mapper/regulatory/RegulatoryLimitMapper.xml new file mode 100644 index 0000000..6f29492 --- /dev/null +++ b/ga-core/src/main/resources/mapper/regulatory/RegulatoryLimitMapper.xml @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + r.limit_id, + r.limit_type, + (SELECT cc.code_name FROM common_code cc + WHERE cc.group_code = 'LIMIT_TYPE' AND cc.code = r.limit_type) AS limit_type_name, + r.product_category, + (SELECT cc.code_name FROM common_code cc + WHERE cc.group_code = 'PRODUCT_CATEGORY' AND cc.code = r.product_category) AS product_category_name, + r.limit_value, + r.unit, + (SELECT cc.code_name FROM common_code cc + WHERE cc.group_code = 'LIMIT_UNIT' AND cc.code = r.unit) AS unit_name, + r.effective_from, + r.effective_to, + r.regulation_ref, + r.description, + r.is_active + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO regulatory_limit ( + limit_type, product_category, limit_value, unit, + effective_from, effective_to, regulation_ref, description, + is_active, created_at, created_by + ) VALUES ( + #{limitType}, #{productCategory}, #{limitValue}, #{unit}, + #{effectiveFrom}, #{effectiveTo}, #{regulationRef}, #{description}, + COALESCE(#{isActive}, TRUE), NOW(), #{createdBy} + ) + + + + + + UPDATE regulatory_limit + + limit_value = #{limitValue}, + unit = #{unit}, + effective_from = #{effectiveFrom}, + effective_to = #{effectiveTo}, + regulation_ref = #{regulationRef}, + description = #{description}, + is_active = #{isActive}, + updated_at = NOW(), + updated_by = #{updatedBy} + + WHERE limit_id = #{limitId} + + + + + UPDATE regulatory_limit + SET is_active = #{isActive}, updated_at = NOW() + WHERE limit_id = #{limitId} + + +