detail(@PathVariable Long reconOutId) {
return ApiResponse.ok(service.detail(reconOutId));
}
+ /** 회신 이력 신규 등록(READY 상태로 시작). 같은 보험사+정산월 중복 등록은 거부됩니다. */
@PostMapping
@RequirePermission(menu = "RECON_OUT", perm = "CREATE")
@DataChangeLog(menu = "RECON_OUT", table = "carrier_reconciliation_out")
@@ -40,6 +51,7 @@ public class CarrierReconciliationOutController {
return ApiResponse.ok(service.create(req));
}
+ /** 전송 실패(FAIL) 건 재전송. 상태를 READY 로 되돌려 배치가 다시 처리하도록 합니다. */
@PostMapping("/{reconOutId}/retry")
@RequirePermission(menu = "RECON_OUT", perm = "UPDATE")
@DataChangeLog(menu = "RECON_OUT", table = "carrier_reconciliation_out")
diff --git a/ga-api/src/main/java/com/ga/api/controller/settle/ChargebackController.java b/ga-api/src/main/java/com/ga/api/controller/settle/ChargebackController.java
index b306be0..1708a12 100644
--- a/ga-api/src/main/java/com/ga/api/controller/settle/ChargebackController.java
+++ b/ga-api/src/main/java/com/ga/api/controller/settle/ChargebackController.java
@@ -17,6 +17,18 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
+/**
+ * 환수(chargeback) 자료 관리 컨트롤러.
+ *
+ * "환수"란 이미 설계사에게 지급한 수수료를 도로 거둬들이는 것입니다. 계약이 일찍 해지/실효되면
+ * 보험사가 GA에게 수수료를 돌려달라 하고, GA는 그만큼을 설계사 정산에서 회수합니다.
+ *
+ *
주 업무는 보험사가 보내준 환수 엑셀(증권번호·환수금액·실효월·환수율)을 업로드(upload)해
+ * chargeback 테이블에 적재하는 것입니다. 존재하지 않는 증권번호나 잘못된 금액은 에러행으로 돌려주고,
+ * 같은 계약+정산월 중복은 건너뜁니다(스킵).
+ *
+ *
권한(menu=CHARGEBACK_DATA): 조회 READ, 엑셀 EXPORT, 업로드 CREATE.
+ */
@Tag(name = "환수자료 관리")
@Validated
@RestController
diff --git a/ga-api/src/main/java/com/ga/api/controller/settle/CommissionDisputeController.java b/ga-api/src/main/java/com/ga/api/controller/settle/CommissionDisputeController.java
index 544c221..b4bfa98 100644
--- a/ga-api/src/main/java/com/ga/api/controller/settle/CommissionDisputeController.java
+++ b/ga-api/src/main/java/com/ga/api/controller/settle/CommissionDisputeController.java
@@ -16,6 +16,18 @@ import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.Map;
+/**
+ * 수수료 이의신청(commission_dispute) 관리 컨트롤러.
+ *
+ *
설계사가 "내 수수료 정산 금액이 이상하다"고 문제를 제기하면 이의신청 건이 만들어집니다.
+ * 담당자는 검토를 시작(startReview)하고, 타당하면 승인(approve)하며 보정 금액을 정정(correction)과 연결하거나,
+ * 타당하지 않으면 기각(reject)합니다.
+ *
+ *
상태 흐름(DisputeStatus): OPEN(접수) → IN_REVIEW(검토중) → APPROVED(승인)/REJECTED(기각).
+ * 승인/기각은 IN_REVIEW 상태에서만 가능합니다.
+ *
+ *
권한(menu=DISPUTE): 조회 READ, 접수 CREATE, 검토시작 UPDATE, 승인/기각 APPROVE.
+ */
@Tag(name = "수수료 이의신청 관리")
@RestController
@RequestMapping("/api/disputes")
@@ -24,18 +36,21 @@ public class CommissionDisputeController {
private final CommissionDisputeService service;
+ /** 이의신청 목록 조회(검색 + 페이징). */
@GetMapping
@RequirePermission(menu = "DISPUTE", perm = "READ")
public ApiResponse> list(@ModelAttribute CommissionDisputeSearchParam param) {
return ApiResponse.ok(service.list(param));
}
+ /** 이의신청 단건 상세 조회. */
@GetMapping("/{disputeId}")
@RequirePermission(menu = "DISPUTE", perm = "READ")
public ApiResponse detail(@PathVariable Long disputeId) {
return ApiResponse.ok(service.detail(disputeId));
}
+ /** 이의신청 접수(OPEN 상태로 생성). */
@PostMapping
@RequirePermission(menu = "DISPUTE", perm = "CREATE")
@DataChangeLog(menu = "DISPUTE", table = "commission_dispute")
@@ -43,6 +58,7 @@ public class CommissionDisputeController {
return ApiResponse.ok(service.create(req));
}
+ /** 검토 시작(OPEN → IN_REVIEW). */
@PostMapping("/{disputeId}/review")
@RequirePermission(menu = "DISPUTE", perm = "UPDATE")
@DataChangeLog(menu = "DISPUTE", table = "commission_dispute")
@@ -51,6 +67,10 @@ public class CommissionDisputeController {
return ApiResponse.ok();
}
+ /**
+ * 이의신청 승인(IN_REVIEW → APPROVED).
+ * body 의 resolution(처리내용), adjustmentAmount(보정금액, 선택), correctionId(연결된 정산정정ID, 선택)를 받습니다.
+ */
@PostMapping("/{disputeId}/approve")
@RequirePermission(menu = "DISPUTE", perm = "APPROVE")
@DataChangeLog(menu = "DISPUTE", table = "commission_dispute")
@@ -64,6 +84,7 @@ public class CommissionDisputeController {
return ApiResponse.ok();
}
+ /** 이의신청 기각(IN_REVIEW → REJECTED). body 의 resolution 에 기각 사유를 담습니다. */
@PostMapping("/{disputeId}/reject")
@RequirePermission(menu = "DISPUTE", perm = "APPROVE")
@DataChangeLog(menu = "DISPUTE", table = "commission_dispute")
diff --git a/ga-api/src/main/java/com/ga/api/controller/settle/IncentivePaymentController.java b/ga-api/src/main/java/com/ga/api/controller/settle/IncentivePaymentController.java
index d425180..f0b0bb5 100644
--- a/ga-api/src/main/java/com/ga/api/controller/settle/IncentivePaymentController.java
+++ b/ga-api/src/main/java/com/ga/api/controller/settle/IncentivePaymentController.java
@@ -15,6 +15,17 @@ import org.springframework.web.bind.annotation.*;
import java.util.Map;
+/**
+ * 시책 지급(incentive_payment) 관리 컨트롤러.
+ *
+ * "시책"은 보험사/GA가 특정 기간·상품에 거는 추가 인센티브(판매 장려금)입니다.
+ * 시책 프로그램(incentive_program) 조건을 충족한 설계사에게 지급할 금액을 건별로 만들어 확정/취소합니다.
+ *
+ *
상태 흐름(IncentivePayStatus): CALCULATED(산출) → CONFIRMED(확정) → PAID(지급완료), 또는 CANCELLED(취소).
+ * 확정은 CALCULATED 상태에서만, 취소는 PAID 가 아닐 때만 가능합니다. 생성·확정 시 정산월 마감 여부를 확인합니다.
+ *
+ *
권한(menu=INCENTIVE_PAY): 조회 READ, 생성 CREATE, 확정 APPROVE, 취소 UPDATE.
+ */
@Tag(name = "시책 지급 관리")
@RestController
@RequestMapping("/api/incentive-payments")
@@ -23,18 +34,21 @@ public class IncentivePaymentController {
private final IncentivePaymentService service;
+ /** 시책 지급 목록 조회(검색 + 페이징). */
@GetMapping
@RequirePermission(menu = "INCENTIVE_PAY", perm = "READ")
public ApiResponse> list(@ModelAttribute IncentivePaymentSearchParam param) {
return ApiResponse.ok(service.list(param));
}
+ /** 시책 지급 단건 상세 조회. */
@GetMapping("/{incentivePayId}")
@RequirePermission(menu = "INCENTIVE_PAY", perm = "READ")
public ApiResponse detail(@PathVariable Long incentivePayId) {
return ApiResponse.ok(service.detail(incentivePayId));
}
+ /** 시책 지급 생성(CALCULATED 상태). 해당 정산월이 마감되어 있으면 거부됩니다. */
@PostMapping
@RequirePermission(menu = "INCENTIVE_PAY", perm = "CREATE")
@DataChangeLog(menu = "INCENTIVE_PAY", table = "incentive_payment")
@@ -42,6 +56,7 @@ public class IncentivePaymentController {
return ApiResponse.ok(service.create(req));
}
+ /** 시책 지급 확정(CALCULATED → CONFIRMED). 마감 가드 적용. APPROVE 권한 필요. */
@PostMapping("/{incentivePayId}/confirm")
@RequirePermission(menu = "INCENTIVE_PAY", perm = "APPROVE")
@DataChangeLog(menu = "INCENTIVE_PAY", table = "incentive_payment")
@@ -50,6 +65,7 @@ public class IncentivePaymentController {
return ApiResponse.ok();
}
+ /** 시책 지급 취소(→ CANCELLED). body 의 cancelReason 에 취소 사유를 담습니다. 지급완료건은 취소 불가. */
@PostMapping("/{incentivePayId}/cancel")
@RequirePermission(menu = "INCENTIVE_PAY", perm = "UPDATE")
@DataChangeLog(menu = "INCENTIVE_PAY", table = "incentive_payment")
diff --git a/ga-api/src/main/java/com/ga/api/controller/settle/IncentiveProgramController.java b/ga-api/src/main/java/com/ga/api/controller/settle/IncentiveProgramController.java
index b21183b..c5eacd7 100644
--- a/ga-api/src/main/java/com/ga/api/controller/settle/IncentiveProgramController.java
+++ b/ga-api/src/main/java/com/ga/api/controller/settle/IncentiveProgramController.java
@@ -15,6 +15,16 @@ import org.springframework.web.bind.annotation.*;
import java.util.Map;
+/**
+ * 시책 프로그램(incentive_program) 관리 컨트롤러.
+ *
+ * 시책 "프로그램"은 인센티브 지급의 규칙 정의입니다. 대상(등급/조직/상품군), 기간(시작월~종료월),
+ * 지급 방식(정률 payRate 또는 정액 payAmountFixed), 예산(budgetAmount) 등을 설정합니다.
+ * 실제 지급(incentive_payment)은 이 프로그램 조건에 따라 산출됩니다.
+ *
+ *
활성/비활성(isActive)은 toggleActive 로 전환합니다. 비활성 프로그램은 신규 지급 대상에서 제외됩니다.
+ * 권한(menu=INCENTIVE_PROG): 조회 READ, 생성 CREATE, 수정/활성토글 UPDATE.
+ */
@Tag(name = "시책 프로그램 관리")
@RestController
@RequestMapping("/api/incentive-programs")
@@ -23,18 +33,21 @@ public class IncentiveProgramController {
private final IncentiveProgramService service;
+ /** 시책 프로그램 목록 조회(검색 + 페이징). */
@GetMapping
@RequirePermission(menu = "INCENTIVE_PROG", perm = "READ")
public ApiResponse> list(@ModelAttribute IncentiveProgramSearchParam param) {
return ApiResponse.ok(service.list(param));
}
+ /** 시책 프로그램 단건 상세 조회. */
@GetMapping("/{programId}")
@RequirePermission(menu = "INCENTIVE_PROG", perm = "READ")
public ApiResponse detail(@PathVariable Long programId) {
return ApiResponse.ok(service.detail(programId));
}
+ /** 시책 프로그램 신규 등록(기본 활성 상태로 생성). */
@PostMapping
@RequirePermission(menu = "INCENTIVE_PROG", perm = "CREATE")
@DataChangeLog(menu = "INCENTIVE_PROG", table = "incentive_program")
@@ -42,6 +55,7 @@ public class IncentiveProgramController {
return ApiResponse.ok(service.create(req));
}
+ /** 시책 프로그램 수정(전체 필드 갱신). */
@PutMapping("/{programId}")
@RequirePermission(menu = "INCENTIVE_PROG", perm = "UPDATE")
@DataChangeLog(menu = "INCENTIVE_PROG", table = "incentive_program")
@@ -50,6 +64,7 @@ public class IncentiveProgramController {
return ApiResponse.ok();
}
+ /** 활성/비활성 토글. body 의 isActive(true/false)로 사용 여부를 전환합니다. */
@PutMapping("/{programId}/active")
@RequirePermission(menu = "INCENTIVE_PROG", perm = "UPDATE")
@DataChangeLog(menu = "INCENTIVE_PROG", table = "incentive_program")
diff --git a/ga-api/src/main/java/com/ga/api/controller/settle/PaymentBatchController.java b/ga-api/src/main/java/com/ga/api/controller/settle/PaymentBatchController.java
index 77dc984..069b426 100644
--- a/ga-api/src/main/java/com/ga/api/controller/settle/PaymentBatchController.java
+++ b/ga-api/src/main/java/com/ga/api/controller/settle/PaymentBatchController.java
@@ -16,6 +16,18 @@ import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
+/**
+ * 지급대상 배치(payment_batch) 관리 컨트롤러.
+ *
+ * "배치"는 한 정산월에 실제로 돈을 보낼 대상 설계사들을 한 묶음으로 모은 작업 단위입니다.
+ * 담당자는 배치를 만들어(create) 대상 명단을 확인하고, 빼야 할 사람은 제외(updateItem)한 뒤,
+ * 최종 확정(finalize)하여 이후 이체 처리로 넘깁니다.
+ *
+ *
상태 흐름(PaymentBatchStatus): DRAFT(작성중) → FINALIZED(확정) / CANCELLED(취소).
+ * 수정(updateItem)은 DRAFT 상태에서만 가능합니다.
+ *
+ *
권한(menu=PAYMENT_TARGET): 생성 CREATE, 조회/엑셀 READ, 항목수정 UPDATE, 확정 EXECUTE.
+ */
@Tag(name = "지급대상 배치 관리")
@RestController
@RequestMapping("/api/payment-batches")
diff --git a/ga-api/src/main/java/com/ga/api/controller/settle/PaymentController.java b/ga-api/src/main/java/com/ga/api/controller/settle/PaymentController.java
index d676c37..e1096bf 100644
--- a/ga-api/src/main/java/com/ga/api/controller/settle/PaymentController.java
+++ b/ga-api/src/main/java/com/ga/api/controller/settle/PaymentController.java
@@ -16,6 +16,19 @@ import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
+/**
+ * 지급(payment) 관리 컨트롤러.
+ *
+ *
정산 마스터가 "이번 달 줄 금액"을 확정하면, 실제 계좌로 보낼 한 건 한 건이 payment(지급) 레코드가 됩니다.
+ * 이 컨트롤러는 지급 건 목록 조회, 상태 변경, 세금 계산, 차감 적용, 은행 이체파일 생성을 담당합니다.
+ *
+ *
지급 한 건의 금액 계산 순서(도메인):
+ * payAmount(지급원금) → 세금(소득세·지방세·부가세) 차감 → 각종 공제(차감) 차감 → netAmount(실지급액).
+ * 이 netAmount 가 최종적으로 설계사 통장에 들어가는 금액입니다.
+ *
+ *
@Validated + @Pattern 으로 settleMonth 는 YYYYMM(숫자 6자리) 형식만 허용합니다.
+ * 권한(menu=PAYMENT): 조회 READ, 상태/세금/차감 변경 UPDATE, 이체파일 생성 EXPORT.
+ */
@Tag(name = "지급 관리")
@Validated
@RestController
@@ -25,12 +38,14 @@ public class PaymentController {
private final PaymentService paymentService;
+ /** 지급 건 목록 조회(검색 + 페이징). */
@GetMapping
@RequirePermission(menu = "PAYMENT", perm = "READ")
public ApiResponse> list(@ModelAttribute SettleSearchParam param) {
return ApiResponse.ok(paymentService.list(param));
}
+ /** 지급 상태 수동 변경(예: 실패 처리). 실패 시 req.failReason 에 사유를 담아 기록합니다. */
@PutMapping("/{paymentId}/status")
@RequirePermission(menu = "PAYMENT", perm = "UPDATE")
@DataChangeLog(menu = "PAYMENT", table = "payment")
diff --git a/ga-api/src/main/java/com/ga/api/controller/settle/PaymentStatusUpdateReq.java b/ga-api/src/main/java/com/ga/api/controller/settle/PaymentStatusUpdateReq.java
index d0db4d5..1f618f6 100644
--- a/ga-api/src/main/java/com/ga/api/controller/settle/PaymentStatusUpdateReq.java
+++ b/ga-api/src/main/java/com/ga/api/controller/settle/PaymentStatusUpdateReq.java
@@ -4,6 +4,10 @@ import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
+/**
+ * 지급 상태 변경 요청 DTO.
+ * status: 변경할 상태값(필수). failReason: 실패 처리 시 사유(선택).
+ */
@Getter
@Setter
public class PaymentStatusUpdateReq {
diff --git a/ga-api/src/main/java/com/ga/api/controller/settle/PeriodCloseController.java b/ga-api/src/main/java/com/ga/api/controller/settle/PeriodCloseController.java
index b2f9717..c450b70 100644
--- a/ga-api/src/main/java/com/ga/api/controller/settle/PeriodCloseController.java
+++ b/ga-api/src/main/java/com/ga/api/controller/settle/PeriodCloseController.java
@@ -15,6 +15,15 @@ import org.springframework.web.bind.annotation.*;
import java.util.Map;
+/**
+ * 정산 마감(period_close) 관리 컨트롤러.
+ *
+ * "마감"은 특정 정산월의 정산 데이터를 잠그는 작업입니다. 마감된 월에는 정정·시책지급 등 금액을 바꾸는
+ * 작업이 막혀(마감 가드), 이미 확정된 숫자가 사후에 흔들리는 것을 방지합니다.
+ *
+ *
마감(close) 후 정정이 필요하면 재오픈(reopen)으로 잠금을 풀 수 있으며, 재오픈 사유를 함께 기록합니다.
+ * 권한(menu=PERIOD_CLOSE): 조회 READ, 마감 CREATE, 재오픈 UPDATE.
+ */
@Tag(name = "정산 마감 관리")
@RestController
@RequestMapping("/api/period-close")
@@ -23,18 +32,21 @@ public class PeriodCloseController {
private final PeriodCloseService service;
+ /** 마감 이력 목록 조회(검색 + 페이징). */
@GetMapping
@RequirePermission(menu = "PERIOD_CLOSE", perm = "READ")
public ApiResponse> list(@ModelAttribute PeriodCloseSearchParam param) {
return ApiResponse.ok(service.list(param));
}
+ /** 마감 이력 단건 상세 조회. */
@GetMapping("/{closeId}")
@RequirePermission(menu = "PERIOD_CLOSE", perm = "READ")
public ApiResponse detail(@PathVariable Long closeId) {
return ApiResponse.ok(service.detail(closeId));
}
+ /** 정산월 마감 실행. 이미 마감된 월이면 거부됩니다. */
@PostMapping
@RequirePermission(menu = "PERIOD_CLOSE", perm = "CREATE")
@DataChangeLog(menu = "PERIOD_CLOSE", table = "period_close")
@@ -43,6 +55,7 @@ public class PeriodCloseController {
return ApiResponse.ok();
}
+ /** 마감 재오픈(잠금 해제). body 의 reopenReason 에 재오픈 사유를 담습니다. */
@PostMapping("/{closeId}/reopen")
@RequirePermission(menu = "PERIOD_CLOSE", perm = "UPDATE")
@DataChangeLog(menu = "PERIOD_CLOSE", table = "period_close")
diff --git a/ga-api/src/main/java/com/ga/api/controller/settle/SettleController.java b/ga-api/src/main/java/com/ga/api/controller/settle/SettleController.java
index f27abd6..4924e12 100644
--- a/ga-api/src/main/java/com/ga/api/controller/settle/SettleController.java
+++ b/ga-api/src/main/java/com/ga/api/controller/settle/SettleController.java
@@ -14,6 +14,18 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
+/**
+ * 정산 마스터(settle_master) 관리 컨트롤러.
+ *
+ * 정산 마스터는 "설계사 1명 × 정산월 1개" 단위로 그 달에 줄 수수료 합계를 모아둔 표(원장)입니다.
+ * 매달 배치가 각종 원장을 집계해 settle_master 한 행을 만들고, 담당자가 이 화면에서 확인/승인합니다.
+ *
+ *
상태 흐름(SettleStatus): CALCULATED(산출완료) → CONFIRMED(확정) → PAID(지급완료).
+ * 중간에 문제가 있으면 HOLD(보류)로 묶었다가 release 로 다시 CALCULATED 로 풀 수 있습니다.
+ *
+ *
권한(menu=SETTLE_LIST): 조회는 READ, 확정/보류/해제 같은 상태변경은 APPROVE 권한이 필요합니다.
+ * 상태변경 엔드포인트에는 @DataChangeLog 가 붙어 누가 무엇을 바꿨는지 변경이력이 자동 기록됩니다.
+ */
@Tag(name = "정산 관리")
@RestController
@RequestMapping("/api/settle")
@@ -22,12 +34,14 @@ public class SettleController {
private final SettleService service;
+ /** 정산 마스터 목록 조회(검색조건 + 페이징). 요청: SettleSearchParam, 응답: 페이지 형태의 정산 요약 목록. */
@GetMapping
@RequirePermission(menu = "SETTLE_LIST", perm = "READ")
public ApiResponse> list(@ModelAttribute SettleSearchParam param) {
return ApiResponse.ok(service.list(param));
}
+ /** 정산 마스터 단건 상세 조회. 키는 "설계사ID + 정산월(YYYYMM)" 조합입니다. */
@GetMapping("/{agentId}/months/{settleMonth}")
@RequirePermission(menu = "SETTLE_LIST", perm = "READ")
public ApiResponse detail(@PathVariable Long agentId,
@@ -35,18 +49,21 @@ public class SettleController {
return ApiResponse.ok(service.detail(agentId, settleMonth));
}
+ /** 특정 정산월 전체 합계 요약(총 인원, 총 지급액 등 대시보드용 집계). */
@GetMapping("/summary")
@RequirePermission(menu = "SETTLE_LIST", perm = "READ")
public ApiResponse