From 5029bc55d4edd77f0df035e51a5231b480dfc0b3 Mon Sep 17 00:00:00 2001 From: GA Pro Date: Wed, 13 May 2026 00:45:53 +0900 Subject: [PATCH] =?UTF-8?q?feat(core):=20Installment=20VO=20=EC=84=B8?= =?UTF-8?q?=ED=8A=B8=20+=20Mapper=20+=20InstallmentStatus=20Enum=20(?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20P1-2-b)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit V27 분급 스키마와 ga-core 동기화. 분급 계획 생성 로직은 P1-2-c. 신규 패키지: com.ga.core.vo.installment, com.ga.core.mapper.installment Enum: - InstallmentStatus {SCHEDULED, PAID, DEFERRED, CANCELLED} InstallmentRatio VO 세트 (분급 비율 마스터): - VO/Resp/SaveReq/SearchParam 4종 - SaveReq: @Min(1)/@Max(7) planYear, @Positive ratioPercent InstallmentPlan VO 세트 (계약별 분급): - VO/Resp/SearchParam 3종 - Resp에 contract/product/agent 조인 표시 (policyNo, productName, agentName, statusName) Mapper 2종: - InstallmentRatioMapper: selectActive(category, year, baseDate), selectAllActiveRatios(category, baseDate) — 1~7차년 비율 일괄 조회 - InstallmentPlanMapper: insertBatch(), selectByContract, selectScheduledByMonth, updateStatus(paidAmount/paidAt/paymentId) XML 핵심: - 활성 비율: effective_from/to + is_active=TRUE + LIMIT 1 (최신 우선) - selectAllActiveRatios: plan_year ASC (1~7년 순서 보장) - selectScheduledByMonth: settle_month + status='SCHEDULED' (배치 진입점) --- .../installment/InstallmentPlanMapper.java | 34 ++++ .../installment/InstallmentRatioMapper.java | 32 +++ .../vo/installment/InstallmentPlanResp.java | 25 +++ .../InstallmentPlanSearchParam.java | 14 ++ .../vo/installment/InstallmentPlanVO.java | 25 +++ .../vo/installment/InstallmentRatioResp.java | 18 ++ .../installment/InstallmentRatioSaveReq.java | 30 +++ .../InstallmentRatioSearchParam.java | 13 ++ .../vo/installment/InstallmentRatioVO.java | 23 +++ .../vo/installment/InstallmentStatus.java | 7 + .../installment/InstallmentPlanMapper.xml | 191 ++++++++++++++++++ .../installment/InstallmentRatioMapper.xml | 155 ++++++++++++++ 12 files changed, 567 insertions(+) create mode 100644 ga-core/src/main/java/com/ga/core/mapper/installment/InstallmentPlanMapper.java create mode 100644 ga-core/src/main/java/com/ga/core/mapper/installment/InstallmentRatioMapper.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanResp.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanSearchParam.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanVO.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioResp.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioSaveReq.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioSearchParam.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioVO.java create mode 100644 ga-core/src/main/java/com/ga/core/vo/installment/InstallmentStatus.java create mode 100644 ga-core/src/main/resources/mapper/installment/InstallmentPlanMapper.xml create mode 100644 ga-core/src/main/resources/mapper/installment/InstallmentRatioMapper.xml diff --git a/ga-core/src/main/java/com/ga/core/mapper/installment/InstallmentPlanMapper.java b/ga-core/src/main/java/com/ga/core/mapper/installment/InstallmentPlanMapper.java new file mode 100644 index 0000000..0e0d1c7 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/mapper/installment/InstallmentPlanMapper.java @@ -0,0 +1,34 @@ +package com.ga.core.mapper.installment; + +import com.ga.core.vo.installment.InstallmentPlanResp; +import com.ga.core.vo.installment.InstallmentPlanSearchParam; +import com.ga.core.vo.installment.InstallmentPlanVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface InstallmentPlanMapper { + + List selectList(InstallmentPlanSearchParam param); + + InstallmentPlanResp selectDetailById(@Param("planId") Long planId); + + InstallmentPlanVO selectById(@Param("planId") Long planId); + + /** 계약의 전체 분급 계획 조회 (계약 상세 화면용) */ + List selectByContract(@Param("contractId") Long contractId); + + /** 정산월의 SCHEDULED 분급 계획 조회 (배치 지급 처리용) */ + List selectScheduledByMonth(@Param("settleMonth") String settleMonth); + + int insert(InstallmentPlanVO vo); + + /** 7년치 분급 계획 일괄 생성 */ + int insertBatch(@Param("list") List list); + + int update(InstallmentPlanVO vo); + + int updateStatus(@Param("planId") Long planId, @Param("status") String status); +} diff --git a/ga-core/src/main/java/com/ga/core/mapper/installment/InstallmentRatioMapper.java b/ga-core/src/main/java/com/ga/core/mapper/installment/InstallmentRatioMapper.java new file mode 100644 index 0000000..90e70c9 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/mapper/installment/InstallmentRatioMapper.java @@ -0,0 +1,32 @@ +package com.ga.core.mapper.installment; + +import com.ga.core.vo.installment.InstallmentRatioResp; +import com.ga.core.vo.installment.InstallmentRatioSearchParam; +import com.ga.core.vo.installment.InstallmentRatioVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface InstallmentRatioMapper { + + List selectList(InstallmentRatioSearchParam param); + + InstallmentRatioResp selectDetailById(@Param("ratioId") Long ratioId); + + InstallmentRatioVO selectById(@Param("ratioId") Long ratioId); + + /** 특정 날짜에 유효한 분급 비율 1건 (planYear + productCategory 조합) */ + InstallmentRatioVO selectActive(@Param("productCategory") String productCategory, + @Param("planYear") Integer planYear, + @Param("baseDate") String baseDate); + + /** 특정 날짜에 유효한 1~7년 차 전체 비율 조회 (분급 계획 일괄 생성 시 사용) */ + List selectAllActiveRatios(@Param("productCategory") String productCategory, + @Param("baseDate") String baseDate); + + int insert(InstallmentRatioVO vo); + + int update(InstallmentRatioVO vo); +} diff --git a/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanResp.java b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanResp.java new file mode 100644 index 0000000..b6a2724 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanResp.java @@ -0,0 +1,25 @@ +package com.ga.core.vo.installment; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +public class InstallmentPlanResp { + private Long planId; + private Long contractId; + private String policyNo; + private String productName; + private Long agentId; + private String agentName; + private Integer planYear; + private Integer planMonth; + private String settleMonth; + private BigDecimal expectedAmount; + private BigDecimal paidAmount; + private LocalDateTime paidAt; + private Long paymentId; + private String status; + private String statusName; +} diff --git a/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanSearchParam.java b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanSearchParam.java new file mode 100644 index 0000000..fbae505 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanSearchParam.java @@ -0,0 +1,14 @@ +package com.ga.core.vo.installment; + +import com.ga.common.model.SearchParam; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +public class InstallmentPlanSearchParam extends SearchParam { + private Long contractId; + private String settleMonth; + private String status; + private Integer planYear; +} diff --git a/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanVO.java b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanVO.java new file mode 100644 index 0000000..bbac84f --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentPlanVO.java @@ -0,0 +1,25 @@ +package com.ga.core.vo.installment; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +public class InstallmentPlanVO { + private Long planId; + private Long contractId; + private Integer planYear; // 1~7 + private Integer planMonth; // 1~12 + private String settleMonth; // YYYYMM + private BigDecimal expectedAmount; + private BigDecimal paidAmount; + private LocalDateTime paidAt; + private Long paymentId; + private String status; + + private LocalDateTime createdAt; + private Long createdBy; + private LocalDateTime updatedAt; + private Long updatedBy; +} diff --git a/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioResp.java b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioResp.java new file mode 100644 index 0000000..df00ed8 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioResp.java @@ -0,0 +1,18 @@ +package com.ga.core.vo.installment; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; + +@Data +public class InstallmentRatioResp { + private Long ratioId; + private String productCategory; + private String productCategoryName; + private Integer planYear; + private BigDecimal ratioPercent; + private LocalDate effectiveFrom; + private LocalDate effectiveTo; + private Boolean isActive; +} diff --git a/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioSaveReq.java b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioSaveReq.java new file mode 100644 index 0000000..88eb5f0 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioSaveReq.java @@ -0,0 +1,30 @@ +package com.ga.core.vo.installment; + +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; + +@Data +public class InstallmentRatioSaveReq { + + private String productCategory; // NULL = 전체 상품 + + @NotNull(message = "분급 연차는 필수입니다") + @Min(value = 1, message = "분급 연차는 1 이상이어야 합니다") + @Max(value = 7, message = "분급 연차는 7 이하여야 합니다") + private Integer planYear; + + @NotNull(message = "비율은 필수입니다") + @Positive(message = "비율은 양수여야 합니다") + private BigDecimal ratioPercent; + + @NotNull(message = "적용 시작일은 필수입니다") + private LocalDate effectiveFrom; + + private LocalDate effectiveTo; +} diff --git a/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioSearchParam.java b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioSearchParam.java new file mode 100644 index 0000000..06e4143 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioSearchParam.java @@ -0,0 +1,13 @@ +package com.ga.core.vo.installment; + +import com.ga.common.model.SearchParam; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +public class InstallmentRatioSearchParam extends SearchParam { + private String productCategory; + private Integer planYear; + private String effectiveDate; // YYYY-MM-DD — 해당 날짜 유효 비율 필터 +} diff --git a/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioVO.java b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioVO.java new file mode 100644 index 0000000..6e3a678 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentRatioVO.java @@ -0,0 +1,23 @@ +package com.ga.core.vo.installment; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +public class InstallmentRatioVO { + private Long ratioId; + private String productCategory; // NULL = ALL 상품 + private Integer planYear; // 1~7 + private BigDecimal ratioPercent; + private LocalDate effectiveFrom; + private LocalDate effectiveTo; // NULL = 현재 유효 + private Boolean isActive; + + private LocalDateTime createdAt; + private Long createdBy; + private LocalDateTime updatedAt; + private Long updatedBy; +} diff --git a/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentStatus.java b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentStatus.java new file mode 100644 index 0000000..3786617 --- /dev/null +++ b/ga-core/src/main/java/com/ga/core/vo/installment/InstallmentStatus.java @@ -0,0 +1,7 @@ +package com.ga.core.vo.installment; + +public enum InstallmentStatus { + SCHEDULED, PAID, DEFERRED, CANCELLED; + + public String code() { return this.name(); } +} diff --git a/ga-core/src/main/resources/mapper/installment/InstallmentPlanMapper.xml b/ga-core/src/main/resources/mapper/installment/InstallmentPlanMapper.xml new file mode 100644 index 0000000..ef0713b --- /dev/null +++ b/ga-core/src/main/resources/mapper/installment/InstallmentPlanMapper.xml @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + p.plan_id, + p.contract_id, + c.policy_no, + pr.product_name, + c.agent_id, + a.agent_name, + p.plan_year, + p.plan_month, + p.settle_month, + p.expected_amount, + p.paid_amount, + p.paid_at, + p.payment_id, + p.status, + (SELECT cc.code_name FROM common_code cc + WHERE cc.group_code = 'INSTALLMENT_STATUS' AND cc.code = p.status) AS status_name + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO installment_plan ( + contract_id, plan_year, plan_month, settle_month, + expected_amount, paid_amount, status, + created_at, created_by + ) VALUES ( + #{contractId}, #{planYear}, #{planMonth}, #{settleMonth}, + #{expectedAmount}, COALESCE(#{paidAmount}, 0), + COALESCE(#{status}, 'SCHEDULED'), + NOW(), #{createdBy} + ) + + + + + INSERT INTO installment_plan ( + contract_id, plan_year, plan_month, settle_month, + expected_amount, paid_amount, status, + created_at, created_by + ) VALUES + + (#{p.contractId}, #{p.planYear}, #{p.planMonth}, #{p.settleMonth}, + #{p.expectedAmount}, COALESCE(#{p.paidAmount}, 0), + COALESCE(#{p.status}, 'SCHEDULED'), + NOW(), #{p.createdBy}) + + + + + + + UPDATE installment_plan + + settle_month = #{settleMonth}, + expected_amount = #{expectedAmount}, + paid_amount = #{paidAmount}, + paid_at = #{paidAt}, + payment_id = #{paymentId}, + status = #{status}, + updated_at = NOW(), + updated_by = #{updatedBy} + + WHERE plan_id = #{planId} + + + + + UPDATE installment_plan + SET status = #{status}, updated_at = NOW() + WHERE plan_id = #{planId} + + + diff --git a/ga-core/src/main/resources/mapper/installment/InstallmentRatioMapper.xml b/ga-core/src/main/resources/mapper/installment/InstallmentRatioMapper.xml new file mode 100644 index 0000000..b896177 --- /dev/null +++ b/ga-core/src/main/resources/mapper/installment/InstallmentRatioMapper.xml @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + r.ratio_id, + 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.plan_year, + r.ratio_percent, + r.effective_from, + r.effective_to, + r.is_active + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO installment_ratio ( + product_category, plan_year, ratio_percent, + effective_from, effective_to, is_active, + created_at, created_by + ) VALUES ( + #{productCategory}, #{planYear}, #{ratioPercent}, + #{effectiveFrom}, #{effectiveTo}, COALESCE(#{isActive}, TRUE), + NOW(), #{createdBy} + ) + + + + + + UPDATE installment_ratio + + ratio_percent = #{ratioPercent}, + effective_from = #{effectiveFrom}, + effective_to = #{effectiveTo}, + is_active = #{isActive}, + updated_at = NOW(), + updated_by = #{updatedBy} + + WHERE ratio_id = #{ratioId} + + +