feat(core): 공제 VO 세트 + Mapper + DeductionType/Status Enum (도메인 P0-2-b)
V24 공제 스키마와 ga-core 동기화. 비즈니스 로직은 P0-2-c.
신규:
- vo/settle/DeductionType {LOAN, ADVANCE, GUARANTEE, DUES, AD, CHARGEBACK_PENDING, OTHER}
- vo/settle/DeductionStatus {PENDING, APPLIED, CANCELLED}
AgentDeduction VO 세트 (표준 5종):
- AgentDeductionVO (감사 4종 포함)
- AgentDeductionResp (agentName/deductionTypeName/statusName 조인 표시 필드)
- AgentDeductionSaveReq (@Valid)
- AgentDeductionSearchParam (settleMonth/agentId/deductionType/status)
PaymentDeductionDetailVO (이체 명세 단순 VO)
Mapper (2종 신규):
- AgentDeductionMapper: selectList/Detail/insert/update/updateStatus/
sumPendingByAgent/selectPendingByMonth
- PaymentDeductionDetailMapper: selectByPaymentId/insert/insertBatch
PaymentVO.deductionAmount + PaymentMapper.xml VOMap 갱신.
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
package com.ga.core.mapper.settle;
|
||||
|
||||
import com.ga.core.vo.settle.AgentDeductionResp;
|
||||
import com.ga.core.vo.settle.AgentDeductionSearchParam;
|
||||
import com.ga.core.vo.settle.AgentDeductionVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface AgentDeductionMapper {
|
||||
List<AgentDeductionResp> selectList(AgentDeductionSearchParam param);
|
||||
AgentDeductionResp selectDetailById(@Param("deductionId") Long deductionId);
|
||||
AgentDeductionVO selectById(@Param("deductionId") Long deductionId);
|
||||
|
||||
int insert(AgentDeductionVO vo);
|
||||
int update(AgentDeductionVO vo);
|
||||
int updateStatus(@Param("deductionId") Long deductionId, @Param("status") String status);
|
||||
|
||||
/** 정산월 + 설계사의 PENDING 차감 합계 */
|
||||
BigDecimal sumPendingByAgent(@Param("agentId") Long agentId,
|
||||
@Param("settleMonth") String settleMonth);
|
||||
|
||||
/** 정산월 전체 PENDING 목록 (배치용) */
|
||||
List<AgentDeductionVO> selectPendingByMonth(@Param("settleMonth") String settleMonth);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.ga.core.mapper.settle;
|
||||
|
||||
import com.ga.core.vo.settle.PaymentDeductionDetailVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface PaymentDeductionDetailMapper {
|
||||
List<PaymentDeductionDetailVO> selectByPaymentId(@Param("paymentId") Long paymentId);
|
||||
int insert(PaymentDeductionDetailVO vo);
|
||||
int insertBatch(@Param("list") List<PaymentDeductionDetailVO> list);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ga.core.vo.settle;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class AgentDeductionResp {
|
||||
private Long deductionId;
|
||||
private Long agentId;
|
||||
private String agentName;
|
||||
private String settleMonth;
|
||||
private String deductionType;
|
||||
private String deductionTypeName;
|
||||
private BigDecimal amount;
|
||||
private String description;
|
||||
private String status;
|
||||
private String statusName;
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ga.core.vo.settle;
|
||||
|
||||
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;
|
||||
|
||||
@Data
|
||||
public class AgentDeductionSaveReq {
|
||||
|
||||
@NotNull(message = "설계사 ID는 필수입니다")
|
||||
private Long agentId;
|
||||
|
||||
@NotBlank(message = "정산월은 필수입니다")
|
||||
@Size(min = 6, max = 6, message = "정산월은 6자리(YYYYMM)입니다")
|
||||
private String settleMonth;
|
||||
|
||||
@NotBlank(message = "차감유형은 필수입니다")
|
||||
private String deductionType;
|
||||
|
||||
@NotNull(message = "차감금액은 필수입니다")
|
||||
@Positive(message = "차감금액은 양수여야 합니다")
|
||||
private BigDecimal amount;
|
||||
|
||||
@Size(max = 255)
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.ga.core.vo.settle;
|
||||
|
||||
import com.ga.common.model.SearchParam;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class AgentDeductionSearchParam extends SearchParam {
|
||||
private Long agentId;
|
||||
private String settleMonth;
|
||||
private String deductionType;
|
||||
private String status;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ga.core.vo.settle;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class AgentDeductionVO {
|
||||
private Long deductionId;
|
||||
private Long agentId;
|
||||
private String settleMonth;
|
||||
private String deductionType; // DeductionType
|
||||
private BigDecimal amount;
|
||||
private String description;
|
||||
private String status; // DeductionStatus
|
||||
private LocalDateTime createdAt;
|
||||
private Long createdBy;
|
||||
private LocalDateTime updatedAt;
|
||||
private Long updatedBy;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ga.core.vo.settle;
|
||||
|
||||
/**
|
||||
* 차감 상태 (common_code_group: DEDUCTION_STATUS, V24 기준)
|
||||
* DB agent_deduction.status: PENDING / APPLIED / CANCELLED
|
||||
*/
|
||||
public enum DeductionStatus {
|
||||
PENDING, // 대기 — 차감 등록 후 미적용
|
||||
APPLIED, // 적용됨 — 이체 시 차감 완료
|
||||
CANCELLED; // 취소
|
||||
|
||||
public String code() {
|
||||
return this.name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ga.core.vo.settle;
|
||||
|
||||
/**
|
||||
* 차감 유형 (common_code_group: DEDUCTION_TYPE, V24 기준)
|
||||
*/
|
||||
public enum DeductionType {
|
||||
LOAN, // 대출잔액
|
||||
ADVANCE, // 가불금
|
||||
GUARANTEE, // 신원보증보험료
|
||||
DUES, // 협회비
|
||||
AD, // 광고비/판촉비
|
||||
CHARGEBACK_PENDING, // 미회수환수금
|
||||
OTHER; // 기타
|
||||
|
||||
public String code() {
|
||||
return this.name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.ga.core.vo.settle;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class PaymentDeductionDetailVO {
|
||||
private Long detailId;
|
||||
private Long paymentId;
|
||||
private String deductionType; // DeductionType
|
||||
private BigDecimal amount;
|
||||
private String description;
|
||||
private LocalDateTime appliedAt;
|
||||
}
|
||||
@@ -22,6 +22,7 @@ public class PaymentVO {
|
||||
private BigDecimal localTaxAmount; // 지방소득세
|
||||
private BigDecimal vatAmount; // 부가세
|
||||
private BigDecimal netAmount; // 실수령액 (payAmount - 세금 합계)
|
||||
private BigDecimal deductionAmount; // 공제 합계
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ga.core.mapper.settle.AgentDeductionMapper">
|
||||
|
||||
<!-- ==================== ResultMap ==================== -->
|
||||
|
||||
<!-- agent_deduction 테이블 1:1 매핑 -->
|
||||
<resultMap id="VOMap" type="com.ga.core.vo.settle.AgentDeductionVO">
|
||||
<id property="deductionId" column="deduction_id"/>
|
||||
<result property="agentId" column="agent_id"/>
|
||||
<result property="settleMonth" column="settle_month"/>
|
||||
<result property="deductionType" column="deduction_type"/>
|
||||
<result property="amount" column="amount"/>
|
||||
<result property="description" column="description"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="createdAt" column="created_at"/>
|
||||
<result property="createdBy" column="created_by"/>
|
||||
<result property="updatedAt" column="updated_at"/>
|
||||
<result property="updatedBy" column="updated_by"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 조인 결과 포함 API 응답용 -->
|
||||
<resultMap id="RespMap" type="com.ga.core.vo.settle.AgentDeductionResp">
|
||||
<id property="deductionId" column="deduction_id"/>
|
||||
<result property="agentId" column="agent_id"/>
|
||||
<result property="agentName" column="agent_name"/>
|
||||
<result property="settleMonth" column="settle_month"/>
|
||||
<result property="deductionType" column="deduction_type"/>
|
||||
<result property="deductionTypeName" column="deduction_type_name"/>
|
||||
<result property="amount" column="amount"/>
|
||||
<result property="description" column="description"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="statusName" column="status_name"/>
|
||||
<result property="createdAt" column="created_at"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- ==================== 공통 SELECT 컬럼 (목록/상세 공유) ==================== -->
|
||||
|
||||
<sql id="selectRespCols">
|
||||
d.deduction_id,
|
||||
d.agent_id,
|
||||
a.agent_name,
|
||||
d.settle_month,
|
||||
d.deduction_type,
|
||||
(SELECT cc.code_name FROM common_code cc
|
||||
WHERE cc.group_code = 'DEDUCTION_TYPE' AND cc.code = d.deduction_type) AS deduction_type_name,
|
||||
d.amount,
|
||||
d.description,
|
||||
d.status,
|
||||
(SELECT cc.code_name FROM common_code cc
|
||||
WHERE cc.group_code = 'DEDUCTION_STATUS' AND cc.code = d.status) AS status_name,
|
||||
d.created_at
|
||||
</sql>
|
||||
|
||||
<!-- ==================== SELECT ==================== -->
|
||||
|
||||
<!-- 목록 조회 (검색 조건 + 페이징) -->
|
||||
<select id="selectList" parameterType="com.ga.core.vo.settle.AgentDeductionSearchParam"
|
||||
resultMap="RespMap">
|
||||
SELECT <include refid="selectRespCols"/>
|
||||
FROM agent_deduction d
|
||||
JOIN agent a ON a.agent_id = d.agent_id
|
||||
<where>
|
||||
<if test="agentId != null">
|
||||
AND d.agent_id = #{agentId}
|
||||
</if>
|
||||
<if test="settleMonth != null and settleMonth != ''">
|
||||
AND d.settle_month = #{settleMonth}
|
||||
</if>
|
||||
<if test="deductionType != null and deductionType != ''">
|
||||
AND d.deduction_type = #{deductionType}
|
||||
</if>
|
||||
<if test="status != null and status != ''">
|
||||
AND d.status = #{status}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY d.deduction_id DESC
|
||||
<if test="pageSize != null and pageSize > 0">
|
||||
LIMIT #{pageSize} OFFSET #{offset}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 단건 조회 (Resp: 조인 포함) -->
|
||||
<select id="selectDetailById" resultMap="RespMap">
|
||||
SELECT <include refid="selectRespCols"/>
|
||||
FROM agent_deduction d
|
||||
JOIN agent a ON a.agent_id = d.agent_id
|
||||
WHERE d.deduction_id = #{deductionId}
|
||||
</select>
|
||||
|
||||
<!-- 단건 조회 (VO: CUD용) -->
|
||||
<select id="selectById" resultMap="VOMap">
|
||||
SELECT deduction_id, agent_id, settle_month, deduction_type,
|
||||
amount, description, status,
|
||||
created_at, created_by, updated_at, updated_by
|
||||
FROM agent_deduction
|
||||
WHERE deduction_id = #{deductionId}
|
||||
</select>
|
||||
|
||||
<!-- 정산월 전체 PENDING 목록 (배치 처리용) -->
|
||||
<select id="selectPendingByMonth" resultMap="VOMap">
|
||||
SELECT deduction_id, agent_id, settle_month, deduction_type,
|
||||
amount, description, status,
|
||||
created_at, created_by, updated_at, updated_by
|
||||
FROM agent_deduction
|
||||
WHERE settle_month = #{settleMonth}
|
||||
AND status = 'PENDING'
|
||||
ORDER BY agent_id, deduction_id
|
||||
</select>
|
||||
|
||||
<!-- ==================== 집계 ==================== -->
|
||||
|
||||
<!-- 정산월 + 설계사의 PENDING 차감 합계 (BigDecimal 반환) -->
|
||||
<select id="sumPendingByAgent" resultType="java.math.BigDecimal">
|
||||
SELECT COALESCE(SUM(amount), 0)
|
||||
FROM agent_deduction
|
||||
WHERE agent_id = #{agentId}
|
||||
AND settle_month = #{settleMonth}
|
||||
AND status = 'PENDING'
|
||||
</select>
|
||||
|
||||
<!-- ==================== INSERT ==================== -->
|
||||
|
||||
<insert id="insert" parameterType="com.ga.core.vo.settle.AgentDeductionVO"
|
||||
useGeneratedKeys="true" keyProperty="deductionId">
|
||||
INSERT INTO agent_deduction (agent_id, settle_month, deduction_type,
|
||||
amount, description, status,
|
||||
created_at, created_by)
|
||||
VALUES (#{agentId}, #{settleMonth}, #{deductionType},
|
||||
#{amount}, #{description}, COALESCE(#{status}, 'PENDING'),
|
||||
NOW(), #{createdBy})
|
||||
</insert>
|
||||
|
||||
<!-- ==================== UPDATE ==================== -->
|
||||
|
||||
<update id="update" parameterType="com.ga.core.vo.settle.AgentDeductionVO">
|
||||
UPDATE agent_deduction
|
||||
<set>
|
||||
<if test="deductionType != null and deductionType != ''">deduction_type = #{deductionType},</if>
|
||||
<if test="amount != null">amount = #{amount},</if>
|
||||
<if test="description != null">description = #{description},</if>
|
||||
updated_at = NOW(),
|
||||
updated_by = #{updatedBy}
|
||||
</set>
|
||||
WHERE deduction_id = #{deductionId}
|
||||
</update>
|
||||
|
||||
<!-- 상태만 변경 (배치 적용/취소 시 단순 호출) -->
|
||||
<update id="updateStatus">
|
||||
UPDATE agent_deduction
|
||||
SET status = #{status}, updated_at = NOW()
|
||||
WHERE deduction_id = #{deductionId}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ga.core.mapper.settle.PaymentDeductionDetailMapper">
|
||||
|
||||
<!-- ==================== ResultMap ==================== -->
|
||||
|
||||
<!-- payment_deduction_detail 테이블 1:1 매핑 -->
|
||||
<resultMap id="VOMap" type="com.ga.core.vo.settle.PaymentDeductionDetailVO">
|
||||
<id property="detailId" column="detail_id"/>
|
||||
<result property="paymentId" column="payment_id"/>
|
||||
<result property="deductionType" column="deduction_type"/>
|
||||
<result property="amount" column="amount"/>
|
||||
<result property="description" column="description"/>
|
||||
<result property="appliedAt" column="applied_at"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- ==================== SELECT ==================== -->
|
||||
|
||||
<!-- 지급 ID로 공제 내역 전체 조회 (지급 상세 화면용) -->
|
||||
<select id="selectByPaymentId" resultMap="VOMap">
|
||||
SELECT detail_id, payment_id, deduction_type,
|
||||
amount, description, applied_at
|
||||
FROM payment_deduction_detail
|
||||
WHERE payment_id = #{paymentId}
|
||||
ORDER BY detail_id
|
||||
</select>
|
||||
|
||||
<!-- ==================== INSERT ==================== -->
|
||||
|
||||
<!-- 단건 삽입 -->
|
||||
<insert id="insert" parameterType="com.ga.core.vo.settle.PaymentDeductionDetailVO"
|
||||
useGeneratedKeys="true" keyProperty="detailId">
|
||||
INSERT INTO payment_deduction_detail (payment_id, deduction_type,
|
||||
amount, description, applied_at)
|
||||
VALUES (#{paymentId}, #{deductionType},
|
||||
#{amount}, #{description}, COALESCE(#{appliedAt}, NOW()))
|
||||
</insert>
|
||||
|
||||
<!-- 배치 삽입 (지급 생성 시 공제 내역 일괄 기록) -->
|
||||
<insert id="insertBatch">
|
||||
INSERT INTO payment_deduction_detail (payment_id, deduction_type,
|
||||
amount, description, applied_at)
|
||||
VALUES
|
||||
<foreach collection="list" item="d" separator=",">
|
||||
(#{d.paymentId}, #{d.deductionType},
|
||||
#{d.amount}, #{d.description}, COALESCE(#{d.appliedAt}, NOW()))
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
@@ -18,6 +18,7 @@
|
||||
<result property="localTaxAmount" column="local_tax_amount"/>
|
||||
<result property="vatAmount" column="vat_amount"/>
|
||||
<result property="netAmount" column="net_amount"/>
|
||||
<result property="deductionAmount" column="deduction_amount"/>
|
||||
<result property="createdAt" column="created_at"/>
|
||||
<result property="updatedAt" column="updated_at"/>
|
||||
</resultMap>
|
||||
|
||||
Reference in New Issue
Block a user