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 localTaxAmount; // 지방소득세
|
||||||
private BigDecimal vatAmount; // 부가세
|
private BigDecimal vatAmount; // 부가세
|
||||||
private BigDecimal netAmount; // 실수령액 (payAmount - 세금 합계)
|
private BigDecimal netAmount; // 실수령액 (payAmount - 세금 합계)
|
||||||
|
private BigDecimal deductionAmount; // 공제 합계
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
private LocalDateTime updatedAt;
|
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="localTaxAmount" column="local_tax_amount"/>
|
||||||
<result property="vatAmount" column="vat_amount"/>
|
<result property="vatAmount" column="vat_amount"/>
|
||||||
<result property="netAmount" column="net_amount"/>
|
<result property="netAmount" column="net_amount"/>
|
||||||
|
<result property="deductionAmount" column="deduction_amount"/>
|
||||||
<result property="createdAt" column="created_at"/>
|
<result property="createdAt" column="created_at"/>
|
||||||
<result property="updatedAt" column="updated_at"/>
|
<result property="updatedAt" column="updated_at"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|||||||
Reference in New Issue
Block a user