동기화
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
package com.ga.api.controller.approval;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AdvanceReq {
|
||||
@NotNull
|
||||
private Long approverId;
|
||||
/** APPROVE / REJECT */
|
||||
@NotBlank
|
||||
private String action;
|
||||
private String comment;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.ga.api.controller.approval;
|
||||
|
||||
import com.ga.api.service.approval.ApprovalService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.approval.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "결재 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/approvals")
|
||||
@RequiredArgsConstructor
|
||||
public class ApprovalController {
|
||||
|
||||
private final ApprovalService service;
|
||||
|
||||
// ── 결재선 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/lines")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "READ")
|
||||
public ApiResponse<PageResponse<ApprovalLineResp>> listLines(
|
||||
@ModelAttribute ApprovalLineSearchParam param) {
|
||||
return ApiResponse.ok(service.listLines(param));
|
||||
}
|
||||
|
||||
@GetMapping("/lines/{lineId}")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "READ")
|
||||
public ApiResponse<ApprovalLineResp> detailLine(@PathVariable Long lineId) {
|
||||
return ApiResponse.ok(service.detailLine(lineId));
|
||||
}
|
||||
|
||||
@GetMapping("/lines/{lineId}/steps")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "READ")
|
||||
public ApiResponse<List<ApprovalLineStepResp>> stepsOfLine(@PathVariable Long lineId) {
|
||||
return ApiResponse.ok(service.stepsOfLine(lineId));
|
||||
}
|
||||
|
||||
@PostMapping("/lines")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "CREATE")
|
||||
@DataChangeLog(menu = "APPROVAL", table = "approval_line")
|
||||
public ApiResponse<Long> createLine(@Valid @RequestBody ApprovalLineSaveReq req) {
|
||||
return ApiResponse.ok(service.createLine(req));
|
||||
}
|
||||
|
||||
@PutMapping("/lines/{lineId}")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "APPROVAL", table = "approval_line")
|
||||
public ApiResponse<Void> updateLine(@PathVariable Long lineId,
|
||||
@Valid @RequestBody ApprovalLineSaveReq req) {
|
||||
service.updateLine(lineId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/lines/{lineId}/steps")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "APPROVAL", table = "approval_line_step")
|
||||
public ApiResponse<Void> addStep(@PathVariable Long lineId,
|
||||
@Valid @RequestBody ApprovalLineStepSaveReq req) {
|
||||
req.setLineId(lineId);
|
||||
service.addStep(req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
// ── 결재 요청 ──────────────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/requests")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "READ")
|
||||
public ApiResponse<PageResponse<ApprovalRequestResp>> listRequests(
|
||||
@ModelAttribute ApprovalRequestSearchParam param) {
|
||||
return ApiResponse.ok(service.listRequests(param));
|
||||
}
|
||||
|
||||
@GetMapping("/requests/{requestId}")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "READ")
|
||||
public ApiResponse<ApprovalRequestResp> detailRequest(@PathVariable Long requestId) {
|
||||
return ApiResponse.ok(service.detailRequest(requestId));
|
||||
}
|
||||
|
||||
@GetMapping("/requests/{requestId}/history")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "READ")
|
||||
public ApiResponse<List<ApprovalHistoryResp>> historyOfRequest(@PathVariable Long requestId) {
|
||||
return ApiResponse.ok(service.historyOfRequest(requestId));
|
||||
}
|
||||
|
||||
@PostMapping("/requests")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "CREATE")
|
||||
@DataChangeLog(menu = "APPROVAL", table = "approval_request")
|
||||
public ApiResponse<Long> createRequest(@Valid @RequestBody ApprovalRequestSaveReq req) {
|
||||
return ApiResponse.ok(service.createRequest(req));
|
||||
}
|
||||
|
||||
@PostMapping("/requests/{requestId}/advance")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "APPROVE")
|
||||
@DataChangeLog(menu = "APPROVAL", table = "approval_request")
|
||||
public ApiResponse<Void> advance(@PathVariable Long requestId,
|
||||
@Valid @RequestBody AdvanceReq req) {
|
||||
service.advance(requestId, req.getApproverId(), req.getAction(), req.getComment());
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/requests/{requestId}/cancel")
|
||||
@RequirePermission(menu = "APPROVAL", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "APPROVAL", table = "approval_request")
|
||||
public ApiResponse<Void> cancel(@PathVariable Long requestId) {
|
||||
service.cancel(requestId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.ga.api.controller.attachment;
|
||||
|
||||
import com.ga.api.service.attachment.AttachmentService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.attachment.AttachmentResp;
|
||||
import com.ga.core.vo.attachment.AttachmentSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "첨부파일")
|
||||
@RestController
|
||||
@RequestMapping("/api/attachments")
|
||||
@RequiredArgsConstructor
|
||||
public class AttachmentController {
|
||||
|
||||
private final AttachmentService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "ATTACHMENT", perm = "READ")
|
||||
public ApiResponse<PageResponse<AttachmentResp>> list(@ModelAttribute AttachmentSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/by-ref")
|
||||
@RequirePermission(menu = "ATTACHMENT", perm = "READ")
|
||||
public ApiResponse<List<AttachmentResp>> listByRef(@RequestParam String refType,
|
||||
@RequestParam Long refId) {
|
||||
return ApiResponse.ok(service.listByRef(refType, refId));
|
||||
}
|
||||
|
||||
@GetMapping("/{attachmentId}/meta")
|
||||
@RequirePermission(menu = "ATTACHMENT", perm = "READ")
|
||||
public ApiResponse<AttachmentResp> detail(@PathVariable Long attachmentId) {
|
||||
return ApiResponse.ok(service.detail(attachmentId));
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data")
|
||||
@RequirePermission(menu = "ATTACHMENT", perm = "CREATE")
|
||||
@DataChangeLog(menu = "ATTACHMENT", table = "attachment")
|
||||
public ApiResponse<Long> upload(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam String refType,
|
||||
@RequestParam Long refId) {
|
||||
return ApiResponse.ok(service.upload(file, refType, refId));
|
||||
}
|
||||
|
||||
@GetMapping("/{attachmentId}/download")
|
||||
@RequirePermission(menu = "ATTACHMENT", perm = "READ")
|
||||
public void download(@PathVariable Long attachmentId, HttpServletResponse response) throws IOException {
|
||||
AttachmentResp meta = service.detail(attachmentId);
|
||||
Path filePath = service.resolveFilePath(attachmentId);
|
||||
|
||||
response.setContentType(meta.getMimeType() != null ? meta.getMimeType() : MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE);
|
||||
String encodedName = URLEncoder.encode(meta.getFileName(), StandardCharsets.UTF_8).replace("+", "%20");
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedName);
|
||||
response.setContentLengthLong(meta.getFileSize() != null ? meta.getFileSize() : 0L);
|
||||
|
||||
try (OutputStream out = response.getOutputStream()) {
|
||||
Files.copy(filePath, out);
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/{attachmentId}")
|
||||
@RequirePermission(menu = "ATTACHMENT", perm = "DELETE")
|
||||
@DataChangeLog(menu = "ATTACHMENT", table = "attachment")
|
||||
public ApiResponse<Void> delete(@PathVariable Long attachmentId) {
|
||||
service.delete(attachmentId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package com.ga.api.controller.commission;
|
||||
|
||||
import com.ga.api.service.commission.CollectionCommissionService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.commission.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "수금수수료")
|
||||
@RestController
|
||||
@RequestMapping("/api/collection-commissions")
|
||||
@RequiredArgsConstructor
|
||||
public class CollectionCommissionController {
|
||||
|
||||
private final CollectionCommissionService service;
|
||||
|
||||
// ── Rule ──────────────────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/rules")
|
||||
@RequirePermission(menu = "COLLECT_COMM", perm = "READ")
|
||||
public ApiResponse<PageResponse<CollectionCommissionRuleResp>> listRules(
|
||||
@ModelAttribute CollectionCommissionRuleSearchParam param) {
|
||||
return ApiResponse.ok(service.listRules(param));
|
||||
}
|
||||
|
||||
@GetMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "COLLECT_COMM", perm = "READ")
|
||||
public ApiResponse<CollectionCommissionRuleResp> detailRule(@PathVariable Long ruleId) {
|
||||
return ApiResponse.ok(service.detailRule(ruleId));
|
||||
}
|
||||
|
||||
@PostMapping("/rules")
|
||||
@RequirePermission(menu = "COLLECT_COMM", perm = "CREATE")
|
||||
@DataChangeLog(menu = "COLLECT_COMM", table = "collection_commission_rule")
|
||||
public ApiResponse<Long> createRule(@Valid @RequestBody CollectionCommissionRuleSaveReq req) {
|
||||
return ApiResponse.ok(service.createRule(req));
|
||||
}
|
||||
|
||||
@PutMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "COLLECT_COMM", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "COLLECT_COMM", table = "collection_commission_rule")
|
||||
public ApiResponse<Void> updateRule(@PathVariable Long ruleId,
|
||||
@Valid @RequestBody CollectionCommissionRuleSaveReq req) {
|
||||
service.updateRule(ruleId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "COLLECT_COMM", perm = "DELETE")
|
||||
@DataChangeLog(menu = "COLLECT_COMM", table = "collection_commission_rule")
|
||||
public ApiResponse<Void> deleteRule(@PathVariable Long ruleId) {
|
||||
service.deleteRule(ruleId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
// ── Ledger ────────────────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/ledgers")
|
||||
@RequirePermission(menu = "COLLECT_COMM", perm = "READ")
|
||||
public ApiResponse<PageResponse<CollectionCommissionLedgerResp>> listLedgers(
|
||||
@ModelAttribute CollectionCommissionLedgerSearchParam param) {
|
||||
return ApiResponse.ok(service.listLedgers(param));
|
||||
}
|
||||
|
||||
@GetMapping("/ledgers/{ledgerId}")
|
||||
@RequirePermission(menu = "COLLECT_COMM", perm = "READ")
|
||||
public ApiResponse<CollectionCommissionLedgerResp> detailLedger(@PathVariable Long ledgerId) {
|
||||
return ApiResponse.ok(service.detailLedger(ledgerId));
|
||||
}
|
||||
|
||||
@PostMapping("/ledgers")
|
||||
@RequirePermission(menu = "COLLECT_COMM", perm = "CREATE")
|
||||
@DataChangeLog(menu = "COLLECT_COMM", table = "collection_commission_ledger")
|
||||
public ApiResponse<Long> createLedger(@Valid @RequestBody CollectionCommissionLedgerSaveReq req) {
|
||||
return ApiResponse.ok(service.createLedger(req));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.ga.api.controller.commission;
|
||||
|
||||
import com.ga.api.service.commission.CommissionMasterService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.commission.CommissionMasterResp;
|
||||
import com.ga.core.vo.commission.CommissionMasterSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "수수료 마스터")
|
||||
@RestController
|
||||
@RequestMapping("/api/commissions")
|
||||
@RequiredArgsConstructor
|
||||
public class CommissionMasterController {
|
||||
|
||||
private final CommissionMasterService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "COMM_MASTER", perm = "READ")
|
||||
public ApiResponse<PageResponse<CommissionMasterResp>> list(@ModelAttribute CommissionMasterSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{masterId}")
|
||||
@RequirePermission(menu = "COMM_MASTER", perm = "READ")
|
||||
public ApiResponse<CommissionMasterResp> detail(@PathVariable Long masterId) {
|
||||
return ApiResponse.ok(service.detail(masterId));
|
||||
}
|
||||
|
||||
@GetMapping("/by-agent")
|
||||
@RequirePermission(menu = "COMM_MASTER", perm = "READ")
|
||||
public ApiResponse<List<CommissionMasterResp>> byAgent(@RequestParam Long agentId,
|
||||
@RequestParam String settleMonth) {
|
||||
return ApiResponse.ok(service.listByAgentAndMonth(agentId, settleMonth));
|
||||
}
|
||||
|
||||
@GetMapping("/aggregated")
|
||||
@RequirePermission(menu = "COMM_MASTER", perm = "READ")
|
||||
public ApiResponse<List<CommissionMasterResp>> aggregated(@RequestParam String settleMonth) {
|
||||
return ApiResponse.ok(service.aggregatedByMonth(settleMonth));
|
||||
}
|
||||
|
||||
@PutMapping("/{masterId}/status")
|
||||
@RequirePermission(menu = "COMM_MASTER", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "COMM_MASTER", table = "commission_master")
|
||||
public ApiResponse<Void> updateStatus(@PathVariable Long masterId,
|
||||
@RequestBody Map<String, String> body) {
|
||||
service.updateStatus(masterId, body.get("status"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{masterId}")
|
||||
@RequirePermission(menu = "COMM_MASTER", perm = "DELETE")
|
||||
@DataChangeLog(menu = "COMM_MASTER", table = "commission_master")
|
||||
public ApiResponse<Void> delete(@PathVariable Long masterId) {
|
||||
service.delete(masterId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.ga.api.controller.commission;
|
||||
|
||||
import com.ga.api.service.commission.OverrideLedgerService;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.commission.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "오버라이드 원장")
|
||||
@RestController
|
||||
@RequestMapping("/api/override-ledgers")
|
||||
@RequiredArgsConstructor
|
||||
public class OverrideLedgerController {
|
||||
|
||||
private final OverrideLedgerService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "OVERRIDE_LEDGER", perm = "READ")
|
||||
public ApiResponse<PageResponse<OverrideLedgerResp>> list(@ModelAttribute OverrideLedgerSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{ledgerId}")
|
||||
@RequirePermission(menu = "OVERRIDE_LEDGER", perm = "READ")
|
||||
public ApiResponse<OverrideLedgerResp> detail(@PathVariable Long ledgerId) {
|
||||
return ApiResponse.ok(service.detail(ledgerId));
|
||||
}
|
||||
|
||||
@GetMapping("/summary")
|
||||
@RequirePermission(menu = "OVERRIDE_LEDGER", perm = "READ")
|
||||
public ApiResponse<List<OverrideSummaryResp>> summaryList(@ModelAttribute OverrideSummarySearchParam param) {
|
||||
return ApiResponse.ok(service.summaryList(param));
|
||||
}
|
||||
|
||||
@GetMapping("/summary/by-agent")
|
||||
@RequirePermission(menu = "OVERRIDE_LEDGER", perm = "READ")
|
||||
public ApiResponse<OverrideSummaryResp> summaryByAgent(@RequestParam Long toAgentId,
|
||||
@RequestParam String settleMonth) {
|
||||
return ApiResponse.ok(service.summaryByAgentAndMonth(toAgentId, settleMonth));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.ga.api.controller.commission;
|
||||
|
||||
import com.ga.api.service.commission.PersistencyBonusService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.commission.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "유지보수수당")
|
||||
@RestController
|
||||
@RequestMapping("/api/persistency-bonus")
|
||||
@RequiredArgsConstructor
|
||||
public class PersistencyBonusController {
|
||||
|
||||
private final PersistencyBonusService service;
|
||||
|
||||
@GetMapping("/rules")
|
||||
@RequirePermission(menu = "PERSIST_BONUS", perm = "READ")
|
||||
public ApiResponse<PageResponse<PersistencyBonusRuleResp>> listRules(
|
||||
@ModelAttribute PersistencyBonusRuleSearchParam param) {
|
||||
return ApiResponse.ok(service.listRules(param));
|
||||
}
|
||||
|
||||
@GetMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "PERSIST_BONUS", perm = "READ")
|
||||
public ApiResponse<PersistencyBonusRuleResp> detailRule(@PathVariable Long ruleId) {
|
||||
return ApiResponse.ok(service.detailRule(ruleId));
|
||||
}
|
||||
|
||||
@PostMapping("/rules")
|
||||
@RequirePermission(menu = "PERSIST_BONUS", perm = "CREATE")
|
||||
@DataChangeLog(menu = "PERSIST_BONUS", table = "persistency_bonus_rule")
|
||||
public ApiResponse<Long> createRule(@Valid @RequestBody PersistencyBonusRuleSaveReq req) {
|
||||
return ApiResponse.ok(service.createRule(req));
|
||||
}
|
||||
|
||||
@PutMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "PERSIST_BONUS", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "PERSIST_BONUS", table = "persistency_bonus_rule")
|
||||
public ApiResponse<Void> updateRule(@PathVariable Long ruleId,
|
||||
@Valid @RequestBody PersistencyBonusRuleSaveReq req) {
|
||||
service.updateRule(ruleId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "PERSIST_BONUS", perm = "DELETE")
|
||||
@DataChangeLog(menu = "PERSIST_BONUS", table = "persistency_bonus_rule")
|
||||
public ApiResponse<Void> deleteRule(@PathVariable Long ruleId) {
|
||||
service.deleteRule(ruleId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/bonuses")
|
||||
@RequirePermission(menu = "PERSIST_BONUS", perm = "READ")
|
||||
public ApiResponse<PageResponse<PersistencyBonusResp>> listBonuses(
|
||||
@ModelAttribute PersistencyBonusSearchParam param) {
|
||||
return ApiResponse.ok(service.listBonuses(param));
|
||||
}
|
||||
|
||||
@GetMapping("/bonuses/{bonusId}")
|
||||
@RequirePermission(menu = "PERSIST_BONUS", perm = "READ")
|
||||
public ApiResponse<PersistencyBonusResp> detailBonus(@PathVariable Long bonusId) {
|
||||
return ApiResponse.ok(service.detailBonus(bonusId));
|
||||
}
|
||||
|
||||
@PostMapping("/bonuses")
|
||||
@RequirePermission(menu = "PERSIST_BONUS", perm = "CREATE")
|
||||
@DataChangeLog(menu = "PERSIST_BONUS", table = "persistency_bonus")
|
||||
public ApiResponse<Void> upsertBonus(@Valid @RequestBody PersistencyBonusSaveReq req) {
|
||||
service.upsertBonus(req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package com.ga.api.controller.commission;
|
||||
|
||||
import com.ga.api.service.commission.ReinstatementCommissionService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.commission.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "부활수수료")
|
||||
@RestController
|
||||
@RequestMapping("/api/reinstatement-commissions")
|
||||
@RequiredArgsConstructor
|
||||
public class ReinstatementCommissionController {
|
||||
|
||||
private final ReinstatementCommissionService service;
|
||||
|
||||
@GetMapping("/rules")
|
||||
@RequirePermission(menu = "REINSTATE_COMM", perm = "READ")
|
||||
public ApiResponse<PageResponse<ReinstatementCommissionRuleResp>> listRules(
|
||||
@ModelAttribute ReinstatementCommissionRuleSearchParam param) {
|
||||
return ApiResponse.ok(service.listRules(param));
|
||||
}
|
||||
|
||||
@GetMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "REINSTATE_COMM", perm = "READ")
|
||||
public ApiResponse<ReinstatementCommissionRuleResp> detailRule(@PathVariable Long ruleId) {
|
||||
return ApiResponse.ok(service.detailRule(ruleId));
|
||||
}
|
||||
|
||||
@PostMapping("/rules")
|
||||
@RequirePermission(menu = "REINSTATE_COMM", perm = "CREATE")
|
||||
@DataChangeLog(menu = "REINSTATE_COMM", table = "reinstatement_commission_rule")
|
||||
public ApiResponse<Long> createRule(@Valid @RequestBody ReinstatementCommissionRuleSaveReq req) {
|
||||
return ApiResponse.ok(service.createRule(req));
|
||||
}
|
||||
|
||||
@PutMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "REINSTATE_COMM", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "REINSTATE_COMM", table = "reinstatement_commission_rule")
|
||||
public ApiResponse<Void> updateRule(@PathVariable Long ruleId,
|
||||
@Valid @RequestBody ReinstatementCommissionRuleSaveReq req) {
|
||||
service.updateRule(ruleId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "REINSTATE_COMM", perm = "DELETE")
|
||||
@DataChangeLog(menu = "REINSTATE_COMM", table = "reinstatement_commission_rule")
|
||||
public ApiResponse<Void> deleteRule(@PathVariable Long ruleId) {
|
||||
service.deleteRule(ruleId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/ledgers")
|
||||
@RequirePermission(menu = "REINSTATE_COMM", perm = "READ")
|
||||
public ApiResponse<PageResponse<ReinstatementCommissionLedgerResp>> listLedgers(
|
||||
@ModelAttribute ReinstatementCommissionLedgerSearchParam param) {
|
||||
return ApiResponse.ok(service.listLedgers(param));
|
||||
}
|
||||
|
||||
@GetMapping("/ledgers/{ledgerId}")
|
||||
@RequirePermission(menu = "REINSTATE_COMM", perm = "READ")
|
||||
public ApiResponse<ReinstatementCommissionLedgerResp> detailLedger(@PathVariable Long ledgerId) {
|
||||
return ApiResponse.ok(service.detailLedger(ledgerId));
|
||||
}
|
||||
|
||||
@PostMapping("/ledgers")
|
||||
@RequirePermission(menu = "REINSTATE_COMM", perm = "CREATE")
|
||||
@DataChangeLog(menu = "REINSTATE_COMM", table = "reinstatement_commission_ledger")
|
||||
public ApiResponse<Long> createLedger(@Valid @RequestBody ReinstatementCommissionLedgerSaveReq req) {
|
||||
return ApiResponse.ok(service.createLedger(req));
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package com.ga.api.controller.commission;
|
||||
|
||||
import com.ga.api.service.commission.RenewalCommissionService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.commission.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "갱신수수료")
|
||||
@RestController
|
||||
@RequestMapping("/api/renewal-commissions")
|
||||
@RequiredArgsConstructor
|
||||
public class RenewalCommissionController {
|
||||
|
||||
private final RenewalCommissionService service;
|
||||
|
||||
@GetMapping("/rules")
|
||||
@RequirePermission(menu = "RENEWAL_COMM", perm = "READ")
|
||||
public ApiResponse<PageResponse<RenewalCommissionRuleResp>> listRules(
|
||||
@ModelAttribute RenewalCommissionRuleSearchParam param) {
|
||||
return ApiResponse.ok(service.listRules(param));
|
||||
}
|
||||
|
||||
@GetMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "RENEWAL_COMM", perm = "READ")
|
||||
public ApiResponse<RenewalCommissionRuleResp> detailRule(@PathVariable Long ruleId) {
|
||||
return ApiResponse.ok(service.detailRule(ruleId));
|
||||
}
|
||||
|
||||
@PostMapping("/rules")
|
||||
@RequirePermission(menu = "RENEWAL_COMM", perm = "CREATE")
|
||||
@DataChangeLog(menu = "RENEWAL_COMM", table = "renewal_commission_rule")
|
||||
public ApiResponse<Long> createRule(@Valid @RequestBody RenewalCommissionRuleSaveReq req) {
|
||||
return ApiResponse.ok(service.createRule(req));
|
||||
}
|
||||
|
||||
@PutMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "RENEWAL_COMM", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "RENEWAL_COMM", table = "renewal_commission_rule")
|
||||
public ApiResponse<Void> updateRule(@PathVariable Long ruleId,
|
||||
@Valid @RequestBody RenewalCommissionRuleSaveReq req) {
|
||||
service.updateRule(ruleId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/rules/{ruleId}")
|
||||
@RequirePermission(menu = "RENEWAL_COMM", perm = "DELETE")
|
||||
@DataChangeLog(menu = "RENEWAL_COMM", table = "renewal_commission_rule")
|
||||
public ApiResponse<Void> deleteRule(@PathVariable Long ruleId) {
|
||||
service.deleteRule(ruleId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/ledgers")
|
||||
@RequirePermission(menu = "RENEWAL_COMM", perm = "READ")
|
||||
public ApiResponse<PageResponse<RenewalCommissionLedgerResp>> listLedgers(
|
||||
@ModelAttribute RenewalCommissionLedgerSearchParam param) {
|
||||
return ApiResponse.ok(service.listLedgers(param));
|
||||
}
|
||||
|
||||
@GetMapping("/ledgers/{ledgerId}")
|
||||
@RequirePermission(menu = "RENEWAL_COMM", perm = "READ")
|
||||
public ApiResponse<RenewalCommissionLedgerResp> detailLedger(@PathVariable Long ledgerId) {
|
||||
return ApiResponse.ok(service.detailLedger(ledgerId));
|
||||
}
|
||||
|
||||
@PostMapping("/ledgers")
|
||||
@RequirePermission(menu = "RENEWAL_COMM", perm = "CREATE")
|
||||
@DataChangeLog(menu = "RENEWAL_COMM", table = "renewal_commission_ledger")
|
||||
public ApiResponse<Long> createLedger(@Valid @RequestBody RenewalCommissionLedgerSaveReq req) {
|
||||
return ApiResponse.ok(service.createLedger(req));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.ga.api.controller.complaint;
|
||||
|
||||
import com.ga.api.service.complaint.ComplaintService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.complaint.ComplaintResp;
|
||||
import com.ga.core.vo.complaint.ComplaintSaveReq;
|
||||
import com.ga.core.vo.complaint.ComplaintSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "민원 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/complaints")
|
||||
@RequiredArgsConstructor
|
||||
public class ComplaintController {
|
||||
|
||||
private final ComplaintService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "COMPLAINT", perm = "READ")
|
||||
public ApiResponse<PageResponse<ComplaintResp>> list(@ModelAttribute ComplaintSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{complaintId}")
|
||||
@RequirePermission(menu = "COMPLAINT", perm = "READ")
|
||||
public ApiResponse<ComplaintResp> detail(@PathVariable Long complaintId) {
|
||||
return ApiResponse.ok(service.detail(complaintId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "COMPLAINT", perm = "CREATE")
|
||||
@DataChangeLog(menu = "COMPLAINT", table = "complaint")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody ComplaintSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PutMapping("/{complaintId}")
|
||||
@RequirePermission(menu = "COMPLAINT", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "COMPLAINT", table = "complaint")
|
||||
public ApiResponse<Void> update(@PathVariable Long complaintId,
|
||||
@Valid @RequestBody ComplaintSaveReq req) {
|
||||
service.update(complaintId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{complaintId}/close")
|
||||
@RequirePermission(menu = "COMPLAINT", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "COMPLAINT", table = "complaint")
|
||||
public ApiResponse<Void> close(@PathVariable Long complaintId,
|
||||
@RequestBody Map<String, String> body) {
|
||||
service.close(complaintId, body.get("resolution"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{complaintId}")
|
||||
@RequirePermission(menu = "COMPLAINT", perm = "DELETE")
|
||||
@DataChangeLog(menu = "COMPLAINT", table = "complaint")
|
||||
public ApiResponse<Void> delete(@PathVariable Long complaintId) {
|
||||
service.delete(complaintId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.ga.api.controller.contract;
|
||||
|
||||
import com.ga.api.service.contract.AgentContractService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.contract.AgentContractResp;
|
||||
import com.ga.core.vo.contract.AgentContractSaveReq;
|
||||
import com.ga.core.vo.contract.AgentContractSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "위촉계약 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/agent-contracts")
|
||||
@RequiredArgsConstructor
|
||||
public class AgentContractController {
|
||||
|
||||
private final AgentContractService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "AGENT_CONTRACT", perm = "READ")
|
||||
public ApiResponse<PageResponse<AgentContractResp>> list(@ModelAttribute AgentContractSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{contractId}")
|
||||
@RequirePermission(menu = "AGENT_CONTRACT", perm = "READ")
|
||||
public ApiResponse<AgentContractResp> detail(@PathVariable Long contractId) {
|
||||
return ApiResponse.ok(service.detail(contractId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "AGENT_CONTRACT", perm = "CREATE")
|
||||
@DataChangeLog(menu = "AGENT_CONTRACT", table = "agent_contract")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody AgentContractSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PutMapping("/{contractId}")
|
||||
@RequirePermission(menu = "AGENT_CONTRACT", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "AGENT_CONTRACT", table = "agent_contract")
|
||||
public ApiResponse<Void> update(@PathVariable Long contractId,
|
||||
@Valid @RequestBody AgentContractSaveReq req) {
|
||||
service.update(contractId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{contractId}/terminate")
|
||||
@RequirePermission(menu = "AGENT_CONTRACT", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "AGENT_CONTRACT", table = "agent_contract")
|
||||
public ApiResponse<Void> terminate(@PathVariable Long contractId,
|
||||
@RequestBody Map<String, String> body) {
|
||||
service.terminate(contractId, body.get("reason"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{contractId}")
|
||||
@RequirePermission(menu = "AGENT_CONTRACT", perm = "DELETE")
|
||||
@DataChangeLog(menu = "AGENT_CONTRACT", table = "agent_contract")
|
||||
public ApiResponse<Void> delete(@PathVariable Long contractId) {
|
||||
service.delete(contractId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.ga.api.controller.endorse;
|
||||
|
||||
import com.ga.api.service.endorse.ContractEndorsementService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.endorse.ContractEndorsementResp;
|
||||
import com.ga.core.vo.endorse.ContractEndorsementSaveReq;
|
||||
import com.ga.core.vo.endorse.ContractEndorsementSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "계약 변경")
|
||||
@RestController
|
||||
@RequestMapping("/api/contract-endorsements")
|
||||
@RequiredArgsConstructor
|
||||
public class ContractEndorsementController {
|
||||
|
||||
private final ContractEndorsementService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "ENDORSE", perm = "READ")
|
||||
public ApiResponse<PageResponse<ContractEndorsementResp>> list(
|
||||
@ModelAttribute ContractEndorsementSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{endorsementId}")
|
||||
@RequirePermission(menu = "ENDORSE", perm = "READ")
|
||||
public ApiResponse<ContractEndorsementResp> detail(@PathVariable Long endorsementId) {
|
||||
return ApiResponse.ok(service.detail(endorsementId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "ENDORSE", perm = "CREATE")
|
||||
@DataChangeLog(menu = "ENDORSE", table = "contract_endorsement")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody ContractEndorsementSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PostMapping("/{endorsementId}/process")
|
||||
@RequirePermission(menu = "ENDORSE", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "ENDORSE", table = "contract_endorsement")
|
||||
public ApiResponse<Void> process(@PathVariable Long endorsementId) {
|
||||
service.process(endorsementId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{endorsementId}")
|
||||
@RequirePermission(menu = "ENDORSE", perm = "DELETE")
|
||||
@DataChangeLog(menu = "ENDORSE", table = "contract_endorsement")
|
||||
public ApiResponse<Void> delete(@PathVariable Long endorsementId) {
|
||||
service.delete(endorsementId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.ga.api.controller.kpi;
|
||||
|
||||
import com.ga.api.service.kpi.KpiService;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.kpi.KpiCumulativeResp;
|
||||
import com.ga.core.vo.kpi.KpiMonthlySummaryResp;
|
||||
import com.ga.core.vo.kpi.KpiOrgSummaryResp;
|
||||
import com.ga.core.vo.kpi.KpiRetentionResp;
|
||||
import com.ga.core.vo.kpi.KpiSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "KPI 대시보드")
|
||||
@RestController
|
||||
@RequestMapping("/api/kpi")
|
||||
@RequiredArgsConstructor
|
||||
public class KpiController {
|
||||
|
||||
private final KpiService service;
|
||||
|
||||
@GetMapping("/monthly-summary")
|
||||
@RequirePermission(menu = "KPI_MONTHLY", perm = "READ")
|
||||
public ApiResponse<PageResponse<KpiMonthlySummaryResp>> monthlySummary(@ModelAttribute KpiSearchParam param) {
|
||||
return ApiResponse.ok(service.monthlySummary(param));
|
||||
}
|
||||
|
||||
@GetMapping("/org-summary")
|
||||
@RequirePermission(menu = "KPI_ORG", perm = "READ")
|
||||
public ApiResponse<PageResponse<KpiOrgSummaryResp>> orgSummary(@ModelAttribute KpiSearchParam param) {
|
||||
return ApiResponse.ok(service.orgSummary(param));
|
||||
}
|
||||
|
||||
@GetMapping("/retention")
|
||||
@RequirePermission(menu = "KPI_RETENTION", perm = "READ")
|
||||
public ApiResponse<PageResponse<KpiRetentionResp>> retention(@ModelAttribute KpiSearchParam param) {
|
||||
return ApiResponse.ok(service.retention(param));
|
||||
}
|
||||
|
||||
@GetMapping("/cumulative")
|
||||
@RequirePermission(menu = "KPI_CUMULATIVE", perm = "READ")
|
||||
public ApiResponse<PageResponse<KpiCumulativeResp>> cumulative(@ModelAttribute KpiSearchParam param) {
|
||||
return ApiResponse.ok(service.cumulative(param));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.ga.api.controller.license;
|
||||
|
||||
import com.ga.api.service.license.AgentLicenseService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.license.AgentLicenseResp;
|
||||
import com.ga.core.vo.license.AgentLicenseSaveReq;
|
||||
import com.ga.core.vo.license.AgentLicenseSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "자격 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/agent-licenses")
|
||||
@RequiredArgsConstructor
|
||||
public class AgentLicenseController {
|
||||
|
||||
private final AgentLicenseService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "AGENT_LICENSE", perm = "READ")
|
||||
public ApiResponse<PageResponse<AgentLicenseResp>> list(@ModelAttribute AgentLicenseSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{licenseId}")
|
||||
@RequirePermission(menu = "AGENT_LICENSE", perm = "READ")
|
||||
public ApiResponse<AgentLicenseResp> detail(@PathVariable Long licenseId) {
|
||||
return ApiResponse.ok(service.detail(licenseId));
|
||||
}
|
||||
|
||||
@GetMapping("/expiring")
|
||||
@RequirePermission(menu = "AGENT_LICENSE", perm = "READ")
|
||||
public ApiResponse<List<AgentLicenseResp>> expiring(
|
||||
@RequestParam(defaultValue = "30") int days) {
|
||||
return ApiResponse.ok(service.expiring(days));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "AGENT_LICENSE", perm = "CREATE")
|
||||
@DataChangeLog(menu = "AGENT_LICENSE", table = "agent_license")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody AgentLicenseSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PutMapping("/{licenseId}")
|
||||
@RequirePermission(menu = "AGENT_LICENSE", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "AGENT_LICENSE", table = "agent_license")
|
||||
public ApiResponse<Void> update(@PathVariable Long licenseId,
|
||||
@Valid @RequestBody AgentLicenseSaveReq req) {
|
||||
service.update(licenseId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{licenseId}")
|
||||
@RequirePermission(menu = "AGENT_LICENSE", perm = "DELETE")
|
||||
@DataChangeLog(menu = "AGENT_LICENSE", table = "agent_license")
|
||||
public ApiResponse<Void> delete(@PathVariable Long licenseId) {
|
||||
service.delete(licenseId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.ga.api.controller.notice;
|
||||
|
||||
import com.ga.api.service.notice.NoticeService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.vo.notice.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "공지사항 & 알림")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class NoticeController {
|
||||
|
||||
private final NoticeService service;
|
||||
|
||||
// ── Notice ────────────────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/api/notices")
|
||||
@RequirePermission(menu = "NOTICE", perm = "READ")
|
||||
public ApiResponse<PageResponse<NoticeResp>> list(@ModelAttribute NoticeSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/api/notices/active")
|
||||
@RequirePermission(menu = "NOTICE", perm = "READ")
|
||||
public ApiResponse<List<NoticeResp>> activeList() {
|
||||
return ApiResponse.ok(service.activeList());
|
||||
}
|
||||
|
||||
@GetMapping("/api/notices/{noticeId}")
|
||||
@RequirePermission(menu = "NOTICE", perm = "READ")
|
||||
public ApiResponse<NoticeResp> detail(@PathVariable Long noticeId) {
|
||||
return ApiResponse.ok(service.detail(noticeId));
|
||||
}
|
||||
|
||||
@PostMapping("/api/notices")
|
||||
@RequirePermission(menu = "NOTICE", perm = "CREATE")
|
||||
@DataChangeLog(menu = "NOTICE", table = "notice")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody NoticeSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PutMapping("/api/notices/{noticeId}")
|
||||
@RequirePermission(menu = "NOTICE", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "NOTICE", table = "notice")
|
||||
public ApiResponse<Void> update(@PathVariable Long noticeId,
|
||||
@Valid @RequestBody NoticeSaveReq req) {
|
||||
service.update(noticeId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/api/notices/{noticeId}")
|
||||
@RequirePermission(menu = "NOTICE", perm = "DELETE")
|
||||
@DataChangeLog(menu = "NOTICE", table = "notice")
|
||||
public ApiResponse<Void> delete(@PathVariable Long noticeId) {
|
||||
service.delete(noticeId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
// ── UserNotification ──────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/api/user-notifications")
|
||||
@RequirePermission(menu = "NOTICE", perm = "READ")
|
||||
public ApiResponse<PageResponse<UserNotificationResp>> listNotifications(
|
||||
@ModelAttribute UserNotificationSearchParam param) {
|
||||
return ApiResponse.ok(service.listNotifications(param));
|
||||
}
|
||||
|
||||
@GetMapping("/api/user-notifications/unread-count")
|
||||
@RequirePermission(menu = "NOTICE", perm = "READ")
|
||||
public ApiResponse<Integer> unreadCount(@RequestParam Long userId) {
|
||||
return ApiResponse.ok(service.unreadCount(userId));
|
||||
}
|
||||
|
||||
@PostMapping("/api/user-notifications/{notificationId}/read")
|
||||
@RequirePermission(menu = "NOTICE", perm = "READ")
|
||||
public ApiResponse<Void> markRead(@PathVariable Long notificationId,
|
||||
@RequestParam Long userId) {
|
||||
service.markRead(notificationId, userId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/api/user-notifications/read-all")
|
||||
@RequirePermission(menu = "NOTICE", perm = "READ")
|
||||
public ApiResponse<Void> markAllRead(@RequestParam Long userId) {
|
||||
service.markAllRead(userId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.ga.api.controller.settle;
|
||||
|
||||
import com.ga.api.service.settle.CarrierReconciliationOutService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.settle.CarrierReconciliationOutResp;
|
||||
import com.ga.core.vo.settle.CarrierReconciliationOutSaveReq;
|
||||
import com.ga.core.vo.settle.CarrierReconciliationOutSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "보험사 회신 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/carrier-reconciliation")
|
||||
@RequiredArgsConstructor
|
||||
public class CarrierReconciliationOutController {
|
||||
|
||||
private final CarrierReconciliationOutService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "RECON_OUT", perm = "READ")
|
||||
public ApiResponse<PageResponse<CarrierReconciliationOutResp>> list(@ModelAttribute CarrierReconciliationOutSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{reconOutId}")
|
||||
@RequirePermission(menu = "RECON_OUT", perm = "READ")
|
||||
public ApiResponse<CarrierReconciliationOutResp> detail(@PathVariable Long reconOutId) {
|
||||
return ApiResponse.ok(service.detail(reconOutId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "RECON_OUT", perm = "CREATE")
|
||||
@DataChangeLog(menu = "RECON_OUT", table = "carrier_reconciliation_out")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody CarrierReconciliationOutSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PostMapping("/{reconOutId}/retry")
|
||||
@RequirePermission(menu = "RECON_OUT", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "RECON_OUT", table = "carrier_reconciliation_out")
|
||||
public ApiResponse<Void> retry(@PathVariable Long reconOutId) {
|
||||
service.retry(reconOutId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.ga.api.controller.settle;
|
||||
|
||||
import com.ga.api.service.settle.CommissionDisputeService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.settle.CommissionDisputeResp;
|
||||
import com.ga.core.vo.settle.CommissionDisputeSaveReq;
|
||||
import com.ga.core.vo.settle.CommissionDisputeSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "수수료 이의신청 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/disputes")
|
||||
@RequiredArgsConstructor
|
||||
public class CommissionDisputeController {
|
||||
|
||||
private final CommissionDisputeService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "DISPUTE", perm = "READ")
|
||||
public ApiResponse<PageResponse<CommissionDisputeResp>> list(@ModelAttribute CommissionDisputeSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{disputeId}")
|
||||
@RequirePermission(menu = "DISPUTE", perm = "READ")
|
||||
public ApiResponse<CommissionDisputeResp> detail(@PathVariable Long disputeId) {
|
||||
return ApiResponse.ok(service.detail(disputeId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "DISPUTE", perm = "CREATE")
|
||||
@DataChangeLog(menu = "DISPUTE", table = "commission_dispute")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody CommissionDisputeSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PostMapping("/{disputeId}/review")
|
||||
@RequirePermission(menu = "DISPUTE", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "DISPUTE", table = "commission_dispute")
|
||||
public ApiResponse<Void> startReview(@PathVariable Long disputeId) {
|
||||
service.startReview(disputeId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{disputeId}/approve")
|
||||
@RequirePermission(menu = "DISPUTE", perm = "APPROVE")
|
||||
@DataChangeLog(menu = "DISPUTE", table = "commission_dispute")
|
||||
public ApiResponse<Void> approve(@PathVariable Long disputeId, @RequestBody Map<String, Object> body) {
|
||||
String resolution = (String) body.get("resolution");
|
||||
BigDecimal adjustmentAmount = body.get("adjustmentAmount") != null
|
||||
? new BigDecimal(body.get("adjustmentAmount").toString()) : null;
|
||||
Long correctionId = body.get("correctionId") != null
|
||||
? Long.valueOf(body.get("correctionId").toString()) : null;
|
||||
service.approve(disputeId, resolution, adjustmentAmount, correctionId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{disputeId}/reject")
|
||||
@RequirePermission(menu = "DISPUTE", perm = "APPROVE")
|
||||
@DataChangeLog(menu = "DISPUTE", table = "commission_dispute")
|
||||
public ApiResponse<Void> reject(@PathVariable Long disputeId, @RequestBody Map<String, String> body) {
|
||||
service.reject(disputeId, body.get("resolution"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.ga.api.controller.settle;
|
||||
|
||||
import com.ga.api.service.settle.IncentivePaymentService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.settle.IncentivePaymentResp;
|
||||
import com.ga.core.vo.settle.IncentivePaymentSaveReq;
|
||||
import com.ga.core.vo.settle.IncentivePaymentSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "시책 지급 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/incentive-payments")
|
||||
@RequiredArgsConstructor
|
||||
public class IncentivePaymentController {
|
||||
|
||||
private final IncentivePaymentService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "INCENTIVE_PAY", perm = "READ")
|
||||
public ApiResponse<PageResponse<IncentivePaymentResp>> list(@ModelAttribute IncentivePaymentSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{incentivePayId}")
|
||||
@RequirePermission(menu = "INCENTIVE_PAY", perm = "READ")
|
||||
public ApiResponse<IncentivePaymentResp> detail(@PathVariable Long incentivePayId) {
|
||||
return ApiResponse.ok(service.detail(incentivePayId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "INCENTIVE_PAY", perm = "CREATE")
|
||||
@DataChangeLog(menu = "INCENTIVE_PAY", table = "incentive_payment")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody IncentivePaymentSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PostMapping("/{incentivePayId}/confirm")
|
||||
@RequirePermission(menu = "INCENTIVE_PAY", perm = "APPROVE")
|
||||
@DataChangeLog(menu = "INCENTIVE_PAY", table = "incentive_payment")
|
||||
public ApiResponse<Void> confirm(@PathVariable Long incentivePayId) {
|
||||
service.confirm(incentivePayId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{incentivePayId}/cancel")
|
||||
@RequirePermission(menu = "INCENTIVE_PAY", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "INCENTIVE_PAY", table = "incentive_payment")
|
||||
public ApiResponse<Void> cancel(@PathVariable Long incentivePayId, @RequestBody Map<String, String> body) {
|
||||
service.cancel(incentivePayId, body.get("cancelReason"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.ga.api.controller.settle;
|
||||
|
||||
import com.ga.api.service.settle.IncentiveProgramService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.settle.IncentiveProgramResp;
|
||||
import com.ga.core.vo.settle.IncentiveProgramSaveReq;
|
||||
import com.ga.core.vo.settle.IncentiveProgramSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "시책 프로그램 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/incentive-programs")
|
||||
@RequiredArgsConstructor
|
||||
public class IncentiveProgramController {
|
||||
|
||||
private final IncentiveProgramService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "INCENTIVE_PROG", perm = "READ")
|
||||
public ApiResponse<PageResponse<IncentiveProgramResp>> list(@ModelAttribute IncentiveProgramSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{programId}")
|
||||
@RequirePermission(menu = "INCENTIVE_PROG", perm = "READ")
|
||||
public ApiResponse<IncentiveProgramResp> detail(@PathVariable Long programId) {
|
||||
return ApiResponse.ok(service.detail(programId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "INCENTIVE_PROG", perm = "CREATE")
|
||||
@DataChangeLog(menu = "INCENTIVE_PROG", table = "incentive_program")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody IncentiveProgramSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PutMapping("/{programId}")
|
||||
@RequirePermission(menu = "INCENTIVE_PROG", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "INCENTIVE_PROG", table = "incentive_program")
|
||||
public ApiResponse<Void> update(@PathVariable Long programId, @Valid @RequestBody IncentiveProgramSaveReq req) {
|
||||
service.update(programId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PutMapping("/{programId}/active")
|
||||
@RequirePermission(menu = "INCENTIVE_PROG", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "INCENTIVE_PROG", table = "incentive_program")
|
||||
public ApiResponse<Void> toggleActive(@PathVariable Long programId, @RequestBody Map<String, Boolean> body) {
|
||||
service.toggleActive(programId, Boolean.TRUE.equals(body.get("isActive")));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ga.api.controller.settle;
|
||||
|
||||
import com.ga.api.service.settle.PeriodCloseService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.settle.PeriodCloseResp;
|
||||
import com.ga.core.vo.settle.PeriodCloseSaveReq;
|
||||
import com.ga.core.vo.settle.PeriodCloseSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "정산 마감 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/period-close")
|
||||
@RequiredArgsConstructor
|
||||
public class PeriodCloseController {
|
||||
|
||||
private final PeriodCloseService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "PERIOD_CLOSE", perm = "READ")
|
||||
public ApiResponse<PageResponse<PeriodCloseResp>> list(@ModelAttribute PeriodCloseSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{closeId}")
|
||||
@RequirePermission(menu = "PERIOD_CLOSE", perm = "READ")
|
||||
public ApiResponse<PeriodCloseResp> detail(@PathVariable Long closeId) {
|
||||
return ApiResponse.ok(service.detail(closeId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "PERIOD_CLOSE", perm = "CREATE")
|
||||
@DataChangeLog(menu = "PERIOD_CLOSE", table = "period_close")
|
||||
public ApiResponse<Void> close(@Valid @RequestBody PeriodCloseSaveReq req) {
|
||||
service.close(req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{closeId}/reopen")
|
||||
@RequirePermission(menu = "PERIOD_CLOSE", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "PERIOD_CLOSE", table = "period_close")
|
||||
public ApiResponse<Void> reopen(@PathVariable Long closeId, @RequestBody Map<String, String> body) {
|
||||
service.reopen(closeId, body.get("reopenReason"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public class SettleController {
|
||||
@RequirePermission(menu = "SETTLE_LIST", perm = "APPROVE")
|
||||
@DataChangeLog(menu = "SETTLE_LIST", table = "settle_master")
|
||||
public ApiResponse<Void> hold(@PathVariable Long settleId, @RequestBody Map<String, String> body) {
|
||||
service.hold(settleId, body.get("reason"));
|
||||
service.hold(settleId, body.get("reason"), body.get("reasonCode"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.ga.api.controller.settle;
|
||||
|
||||
import com.ga.api.service.settle.SettleCorrectionService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.settle.SettleCorrectionResp;
|
||||
import com.ga.core.vo.settle.SettleCorrectionSaveReq;
|
||||
import com.ga.core.vo.settle.SettleCorrectionSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "정산 정정 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/settle-corrections")
|
||||
@RequiredArgsConstructor
|
||||
public class SettleCorrectionController {
|
||||
|
||||
private final SettleCorrectionService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "SETTLE_CORR", perm = "READ")
|
||||
public ApiResponse<PageResponse<SettleCorrectionResp>> list(@ModelAttribute SettleCorrectionSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{correctionId}")
|
||||
@RequirePermission(menu = "SETTLE_CORR", perm = "READ")
|
||||
public ApiResponse<SettleCorrectionResp> detail(@PathVariable Long correctionId) {
|
||||
return ApiResponse.ok(service.detail(correctionId));
|
||||
}
|
||||
|
||||
@GetMapping("/by-settle/{originalSettleId}")
|
||||
@RequirePermission(menu = "SETTLE_CORR", perm = "READ")
|
||||
public ApiResponse<List<SettleCorrectionResp>> listByOriginalSettle(@PathVariable Long originalSettleId) {
|
||||
return ApiResponse.ok(service.listByOriginalSettle(originalSettleId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "SETTLE_CORR", perm = "CREATE")
|
||||
@DataChangeLog(menu = "SETTLE_CORR", table = "settle_correction")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody SettleCorrectionSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PostMapping("/{correctionId}/approve")
|
||||
@RequirePermission(menu = "SETTLE_CORR", perm = "APPROVE")
|
||||
@DataChangeLog(menu = "SETTLE_CORR", table = "settle_correction")
|
||||
public ApiResponse<Void> approve(@PathVariable Long correctionId) {
|
||||
service.approve(correctionId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{correctionId}/cancel")
|
||||
@RequirePermission(menu = "SETTLE_CORR", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "SETTLE_CORR", table = "settle_correction")
|
||||
public ApiResponse<Void> cancel(@PathVariable Long correctionId, @RequestBody Map<String, String> body) {
|
||||
service.cancel(correctionId, body.get("cancelReason"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.ga.api.controller.settle;
|
||||
|
||||
import com.ga.api.service.settle.TaxInvoiceService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.settle.TaxInvoiceResp;
|
||||
import com.ga.core.vo.settle.TaxInvoiceSaveReq;
|
||||
import com.ga.core.vo.settle.TaxInvoiceSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "세금계산서 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/tax-invoices")
|
||||
@RequiredArgsConstructor
|
||||
public class TaxInvoiceController {
|
||||
|
||||
private final TaxInvoiceService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "TAX_INVOICE", perm = "READ")
|
||||
public ApiResponse<PageResponse<TaxInvoiceResp>> list(@ModelAttribute TaxInvoiceSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{invoiceId}")
|
||||
@RequirePermission(menu = "TAX_INVOICE", perm = "READ")
|
||||
public ApiResponse<TaxInvoiceResp> detail(@PathVariable Long invoiceId) {
|
||||
return ApiResponse.ok(service.detail(invoiceId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "TAX_INVOICE", perm = "CREATE")
|
||||
@DataChangeLog(menu = "TAX_INVOICE", table = "tax_invoice")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody TaxInvoiceSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PostMapping("/{invoiceId}/cancel")
|
||||
@RequirePermission(menu = "TAX_INVOICE", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "TAX_INVOICE", table = "tax_invoice")
|
||||
public ApiResponse<Void> cancel(@PathVariable Long invoiceId, @RequestBody Map<String, String> body) {
|
||||
service.cancel(invoiceId, body.get("cancelReason"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package com.ga.api.controller.settle;
|
||||
|
||||
import com.ga.api.service.settle.TerminationSettlementService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.settle.TerminationSettlementResp;
|
||||
import com.ga.core.vo.settle.TerminationSettlementSaveReq;
|
||||
import com.ga.core.vo.settle.TerminationSettlementSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "해촉 정산 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/termination-settlements")
|
||||
@RequiredArgsConstructor
|
||||
public class TerminationSettlementController {
|
||||
|
||||
private final TerminationSettlementService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "TERM_SETTLE", perm = "READ")
|
||||
public ApiResponse<PageResponse<TerminationSettlementResp>> list(@ModelAttribute TerminationSettlementSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{termSettleId}")
|
||||
@RequirePermission(menu = "TERM_SETTLE", perm = "READ")
|
||||
public ApiResponse<TerminationSettlementResp> detail(@PathVariable Long termSettleId) {
|
||||
return ApiResponse.ok(service.detail(termSettleId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "TERM_SETTLE", perm = "CREATE")
|
||||
@DataChangeLog(menu = "TERM_SETTLE", table = "termination_settlement")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody TerminationSettlementSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PutMapping("/{termSettleId}")
|
||||
@RequirePermission(menu = "TERM_SETTLE", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "TERM_SETTLE", table = "termination_settlement")
|
||||
public ApiResponse<Void> update(@PathVariable Long termSettleId, @Valid @RequestBody TerminationSettlementSaveReq req) {
|
||||
service.update(termSettleId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/process")
|
||||
@RequirePermission(menu = "TERM_SETTLE", perm = "CREATE")
|
||||
@DataChangeLog(menu = "TERM_SETTLE", table = "termination_settlement")
|
||||
public ApiResponse<Long> process(@Valid @RequestBody TerminationSettlementSaveReq req) {
|
||||
return ApiResponse.ok(service.process(req));
|
||||
}
|
||||
|
||||
@PostMapping("/{termSettleId}/confirm")
|
||||
@RequirePermission(menu = "TERM_SETTLE", perm = "APPROVE")
|
||||
@DataChangeLog(menu = "TERM_SETTLE", table = "termination_settlement")
|
||||
public ApiResponse<Void> confirm(@PathVariable Long termSettleId) {
|
||||
service.confirm(termSettleId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.ga.api.controller.training;
|
||||
|
||||
import com.ga.api.service.training.AgentTrainingService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.training.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "보수교육 관리")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class AgentTrainingController {
|
||||
|
||||
private final AgentTrainingService service;
|
||||
|
||||
// ── Training ──────────────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/api/agent-trainings")
|
||||
@RequirePermission(menu = "AGENT_TRAINING", perm = "READ")
|
||||
public ApiResponse<PageResponse<AgentTrainingResp>> list(@ModelAttribute AgentTrainingSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/api/agent-trainings/{trainingId}")
|
||||
@RequirePermission(menu = "AGENT_TRAINING", perm = "READ")
|
||||
public ApiResponse<AgentTrainingResp> detail(@PathVariable Long trainingId) {
|
||||
return ApiResponse.ok(service.detail(trainingId));
|
||||
}
|
||||
|
||||
@GetMapping("/api/agent-trainings/annual-hours")
|
||||
@RequirePermission(menu = "AGENT_TRAINING", perm = "READ")
|
||||
public ApiResponse<BigDecimal> annualHours(@RequestParam Long agentId,
|
||||
@RequestParam int year) {
|
||||
return ApiResponse.ok(service.annualHours(agentId, year));
|
||||
}
|
||||
|
||||
@PostMapping("/api/agent-trainings")
|
||||
@RequirePermission(menu = "AGENT_TRAINING", perm = "CREATE")
|
||||
@DataChangeLog(menu = "AGENT_TRAINING", table = "agent_training")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody AgentTrainingSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PutMapping("/api/agent-trainings/{trainingId}")
|
||||
@RequirePermission(menu = "AGENT_TRAINING", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "AGENT_TRAINING", table = "agent_training")
|
||||
public ApiResponse<Void> update(@PathVariable Long trainingId,
|
||||
@Valid @RequestBody AgentTrainingSaveReq req) {
|
||||
service.update(trainingId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/api/agent-trainings/{trainingId}")
|
||||
@RequirePermission(menu = "AGENT_TRAINING", perm = "DELETE")
|
||||
@DataChangeLog(menu = "AGENT_TRAINING", table = "agent_training")
|
||||
public ApiResponse<Void> delete(@PathVariable Long trainingId) {
|
||||
service.delete(trainingId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
// ── Requirement ───────────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/api/training-requirements")
|
||||
@RequirePermission(menu = "AGENT_TRAINING", perm = "READ")
|
||||
public ApiResponse<List<TrainingRequirementResp>> listRequirements(
|
||||
@ModelAttribute TrainingRequirementSearchParam param) {
|
||||
return ApiResponse.ok(service.listRequirements(param));
|
||||
}
|
||||
|
||||
@GetMapping("/api/training-requirements/{year}")
|
||||
@RequirePermission(menu = "AGENT_TRAINING", perm = "READ")
|
||||
public ApiResponse<TrainingRequirementResp> requirementByYear(@PathVariable int year) {
|
||||
return ApiResponse.ok(service.requirementByYear(year));
|
||||
}
|
||||
|
||||
@PostMapping("/api/training-requirements")
|
||||
@RequirePermission(menu = "AGENT_TRAINING", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "AGENT_TRAINING", table = "training_requirement")
|
||||
public ApiResponse<Void> saveRequirement(@Valid @RequestBody TrainingRequirementSaveReq req) {
|
||||
service.saveRequirement(req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.ga.api.controller.withdraw;
|
||||
|
||||
import com.ga.api.service.withdraw.WithdrawRequestService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.vo.withdraw.WithdrawRequestResp;
|
||||
import com.ga.core.vo.withdraw.WithdrawRequestSaveReq;
|
||||
import com.ga.core.vo.withdraw.WithdrawRequestSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "출금 신청")
|
||||
@RestController
|
||||
@RequestMapping("/api/withdraw-requests")
|
||||
@RequiredArgsConstructor
|
||||
public class WithdrawRequestController {
|
||||
|
||||
private final WithdrawRequestService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "WITHDRAW", perm = "READ")
|
||||
public ApiResponse<PageResponse<WithdrawRequestResp>> list(@ModelAttribute WithdrawRequestSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{requestId}")
|
||||
@RequirePermission(menu = "WITHDRAW", perm = "READ")
|
||||
public ApiResponse<WithdrawRequestResp> detail(@PathVariable Long requestId) {
|
||||
return ApiResponse.ok(service.detail(requestId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "WITHDRAW", perm = "CREATE")
|
||||
@DataChangeLog(menu = "WITHDRAW", table = "withdraw_request")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody WithdrawRequestSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PostMapping("/{requestId}/cancel")
|
||||
@RequirePermission(menu = "WITHDRAW", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "WITHDRAW", table = "withdraw_request")
|
||||
public ApiResponse<Void> cancel(@PathVariable Long requestId) {
|
||||
service.cancel(requestId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
package com.ga.api.service.approval;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.approval.*;
|
||||
import com.ga.core.mapper.notice.UserNotificationMapper;
|
||||
import com.ga.core.mapper.settle.CommissionDisputeMapper;
|
||||
import com.ga.core.mapper.settle.IncentivePaymentMapper;
|
||||
import com.ga.core.mapper.settle.SettleMasterMapper;
|
||||
import com.ga.core.mapper.withdraw.WithdrawRequestMapper;
|
||||
import com.ga.core.vo.approval.*;
|
||||
import com.ga.core.vo.notice.NotificationRefType;
|
||||
// Note: ApprovalLineVO kept for createLine/updateLine methods
|
||||
import com.ga.core.vo.notice.UserNotificationVO;
|
||||
import com.ga.core.vo.settle.SettleStatus;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class ApprovalService {
|
||||
|
||||
private final ApprovalLineMapper lineMapper;
|
||||
private final ApprovalLineStepMapper stepMapper;
|
||||
private final ApprovalRequestMapper requestMapper;
|
||||
private final ApprovalHistoryMapper historyMapper;
|
||||
private final UserNotificationMapper notificationMapper;
|
||||
|
||||
// 콜백 대상 도메인 Mapper
|
||||
private final WithdrawRequestMapper withdrawMapper;
|
||||
private final SettleMasterMapper settleMasterMapper;
|
||||
private final CommissionDisputeMapper disputeMapper;
|
||||
private final IncentivePaymentMapper incentivePaymentMapper;
|
||||
|
||||
// ── Line ──────────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<ApprovalLineResp> listLines(ApprovalLineSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(lineMapper.selectList(param));
|
||||
}
|
||||
|
||||
public ApprovalLineResp detailLine(Long lineId) {
|
||||
ApprovalLineResp resp = lineMapper.selectById(lineId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
public List<ApprovalLineStepResp> stepsOfLine(Long lineId) {
|
||||
return stepMapper.selectByLine(lineId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long createLine(ApprovalLineSaveReq req) {
|
||||
ApprovalLineVO vo = new ApprovalLineVO();
|
||||
vo.setLineCode(req.getLineCode());
|
||||
vo.setLineName(req.getLineName());
|
||||
vo.setMaxStep(req.getMaxStep());
|
||||
vo.setTargetType(req.getTargetType());
|
||||
vo.setIsActive(true);
|
||||
vo.setCreatedBy(SecurityUtil.getCurrentUserId());
|
||||
lineMapper.insert(vo);
|
||||
return vo.getLineId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateLine(Long lineId, ApprovalLineSaveReq req) {
|
||||
ApprovalLineResp existing = lineMapper.selectById(lineId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
ApprovalLineVO vo = new ApprovalLineVO();
|
||||
vo.setLineId(lineId);
|
||||
vo.setLineCode(req.getLineCode());
|
||||
vo.setLineName(req.getLineName());
|
||||
vo.setMaxStep(req.getMaxStep());
|
||||
vo.setTargetType(req.getTargetType());
|
||||
lineMapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void addStep(ApprovalLineStepSaveReq req) {
|
||||
ApprovalLineStepVO vo = new ApprovalLineStepVO();
|
||||
vo.setLineId(req.getLineId());
|
||||
vo.setStepNo(req.getStepNo());
|
||||
vo.setRoleCode(req.getRoleCode());
|
||||
stepMapper.insert(vo);
|
||||
}
|
||||
|
||||
// ── Request ───────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<ApprovalRequestResp> listRequests(ApprovalRequestSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(requestMapper.selectList(param));
|
||||
}
|
||||
|
||||
public ApprovalRequestResp detailRequest(Long requestId) {
|
||||
ApprovalRequestResp resp = requestMapper.selectById(requestId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
public List<ApprovalHistoryResp> historyOfRequest(Long requestId) {
|
||||
return historyMapper.selectByRequest(requestId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 결재 요청 생성 — PENDING status=1, 첫 결재자에게 알림 발송.
|
||||
*/
|
||||
@Transactional
|
||||
public Long createRequest(ApprovalRequestSaveReq req) {
|
||||
// 결재선 존재 확인
|
||||
ApprovalLineResp line = lineMapper.selectById(req.getLineId());
|
||||
if (line == null) throw new BizException(ErrorCode.NOT_FOUND, "결재선을 찾을 수 없습니다");
|
||||
|
||||
ApprovalRequestVO vo = new ApprovalRequestVO();
|
||||
vo.setTargetType(req.getTargetType());
|
||||
vo.setTargetId(req.getTargetId());
|
||||
vo.setLineId(req.getLineId());
|
||||
vo.setRequestedBy(req.getRequestedBy());
|
||||
vo.setRequestedAt(LocalDateTime.now());
|
||||
vo.setCurrentStep(1);
|
||||
vo.setStatus(ApprovalStatus.PENDING.name());
|
||||
requestMapper.insert(vo);
|
||||
|
||||
// 1단계 결재자에게 알림
|
||||
sendStepNotification(vo.getRequestId(), req.getLineId(), 1, req.getTargetType());
|
||||
return vo.getRequestId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 결재 단계 진행 — history INSERT + step advance + 최종 처리.
|
||||
* @param requestId 결재 요청 PK
|
||||
* @param approverId 결재자 user_id
|
||||
* @param action APPROVE / REJECT
|
||||
* @param comment 코멘트
|
||||
*/
|
||||
@Transactional
|
||||
public void advance(Long requestId, Long approverId, String action, String comment) {
|
||||
ApprovalRequestResp reqResp = requestMapper.selectById(requestId);
|
||||
if (reqResp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!ApprovalStatus.PENDING.name().equals(reqResp.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "진행 중인 결재 요청이 아닙니다");
|
||||
}
|
||||
|
||||
// 1. 결재 이력 INSERT
|
||||
ApprovalHistoryVO history = new ApprovalHistoryVO();
|
||||
history.setRequestId(requestId);
|
||||
history.setStepNo(reqResp.getCurrentStep());
|
||||
history.setApproverId(approverId);
|
||||
history.setAction(action);
|
||||
history.setComment(comment);
|
||||
history.setProcessedAt(LocalDateTime.now());
|
||||
historyMapper.insert(history);
|
||||
|
||||
// 2. advanceStep — DB에서 current_step 갱신
|
||||
requestMapper.advanceStep(requestId, approverId, action, comment);
|
||||
|
||||
// 3. REJECT → 종료
|
||||
if (ApprovalAction.REJECT.name().equals(action)) {
|
||||
requestMapper.updateStatus(requestId, ApprovalStatus.REJECTED.name());
|
||||
log.info("결재 요청 반려: requestId={}", requestId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. APPROVE 처리
|
||||
if (ApprovalAction.APPROVE.name().equals(action)) {
|
||||
int maxStep = reqResp.getMaxStep() != null ? reqResp.getMaxStep() : 1;
|
||||
int currentStep = reqResp.getCurrentStep();
|
||||
|
||||
if (currentStep < maxStep) {
|
||||
// 다음 단계 알림
|
||||
sendStepNotification(requestId, reqResp.getLineId(), currentStep + 1, reqResp.getTargetType());
|
||||
} else {
|
||||
// 최종 승인 — 콜백 처리
|
||||
requestMapper.updateStatus(requestId, ApprovalStatus.APPROVED.name());
|
||||
handleApprovalCallback(reqResp.getTargetType(), reqResp.getTargetId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 결재 취소.
|
||||
*/
|
||||
@Transactional
|
||||
public void cancel(Long requestId) {
|
||||
ApprovalRequestResp reqResp = requestMapper.selectById(requestId);
|
||||
if (reqResp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!ApprovalStatus.PENDING.name().equals(reqResp.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "진행 중인 결재만 취소 가능합니다");
|
||||
}
|
||||
requestMapper.cancel(requestId);
|
||||
}
|
||||
|
||||
// ── Callback ──────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* 최종 승인 후 target_type 별 도메인 후처리.
|
||||
* - WITHDRAW → withdraw_request.status=APPROVED (펌뱅킹 SENT는 P5)
|
||||
* - SETTLE → settle_master.status=CONFIRMED
|
||||
* - DISPUTE → commission_dispute.status=APPROVED (정정 생성은 P5)
|
||||
* - INCENTIVE → incentive_payment.status=CONFIRMED
|
||||
*/
|
||||
private void handleApprovalCallback(String targetType, Long targetId) {
|
||||
if (targetType == null || targetId == null) return;
|
||||
try {
|
||||
switch (targetType) {
|
||||
case "WITHDRAW" -> {
|
||||
withdrawMapper.updateStatus(targetId, "APPROVED", null);
|
||||
log.info("출금신청 승인 완료: requestId={}", targetId);
|
||||
}
|
||||
case "SETTLE" -> {
|
||||
settleMasterMapper.updateStatus(targetId, SettleStatus.CONFIRMED.name(),
|
||||
SecurityUtil.getCurrentUserId());
|
||||
log.info("정산 확정 완료: settleId={}", targetId);
|
||||
}
|
||||
case "DISPUTE" -> {
|
||||
disputeMapper.resolve(targetId, "APPROVED", null, null, null,
|
||||
SecurityUtil.getCurrentUserId());
|
||||
log.info("이의신청 승인 완료: disputeId={}", targetId);
|
||||
}
|
||||
case "INCENTIVE" -> {
|
||||
incentivePaymentMapper.updateStatus(targetId, "CONFIRMED",
|
||||
SecurityUtil.getCurrentUserId());
|
||||
log.info("시책 확정 완료: incentivePayId={}", targetId);
|
||||
}
|
||||
default -> log.warn("알 수 없는 결재 대상 타입: targetType={}", targetType);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("결재 콜백 실패: targetType={}, targetId={}", targetType, targetId, e);
|
||||
throw new BizException(ErrorCode.INTERNAL_ERROR, "결재 후처리 중 오류가 발생했습니다");
|
||||
}
|
||||
}
|
||||
|
||||
/** 다음 결재 단계 담당자에게 알림 발송 */
|
||||
private void sendStepNotification(Long requestId, Long lineId, int stepNo, String targetType) {
|
||||
try {
|
||||
ApprovalLineStepVO step = stepMapper.selectByLineAndStep(lineId, stepNo);
|
||||
if (step == null) return;
|
||||
// roleCode 기반 userId 매핑은 P5에서 고도화 — 현재는 메타만 저장
|
||||
UserNotificationVO noti = new UserNotificationVO();
|
||||
noti.setUserId(0L); // 실제 담당자 ID 조회 로직은 P5
|
||||
noti.setTitle("[결재요청] " + (targetType != null ? targetType : "") + " 결재 " + stepNo + "단계");
|
||||
noti.setContent("결재 요청 ID " + requestId + " 에 대한 " + stepNo + "단계 결재가 필요합니다.");
|
||||
noti.setRefType(NotificationRefType.APPROVAL.name());
|
||||
noti.setRefId(requestId);
|
||||
noti.setIsRead(false);
|
||||
notificationMapper.insert(noti);
|
||||
} catch (Exception e) {
|
||||
log.warn("결재 알림 발송 실패 (non-critical): requestId={}", requestId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.ga.api.service.attachment;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.attachment.AttachmentMapper;
|
||||
import com.ga.core.vo.attachment.AttachmentResp;
|
||||
import com.ga.core.vo.attachment.AttachmentSearchParam;
|
||||
import com.ga.core.vo.attachment.AttachmentVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class AttachmentService {
|
||||
|
||||
private final AttachmentMapper mapper;
|
||||
|
||||
@Value("${app.attachment.path:./uploads}")
|
||||
private String uploadBasePath;
|
||||
|
||||
public PageResponse<AttachmentResp> list(AttachmentSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(mapper.selectList(param));
|
||||
}
|
||||
|
||||
public List<AttachmentResp> listByRef(String refType, Long refId) {
|
||||
return mapper.selectByRef(refType, refId);
|
||||
}
|
||||
|
||||
public AttachmentResp detail(Long attachmentId) {
|
||||
AttachmentResp resp = mapper.selectById(attachmentId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 파일 업로드 + 메타 저장.
|
||||
* 파일 저장 실패 시 경고 로그 후 메타만 저장하는 fallback.
|
||||
*/
|
||||
@Transactional
|
||||
public Long upload(MultipartFile file, String refType, Long refId) {
|
||||
String originalName = file.getOriginalFilename() != null ? file.getOriginalFilename() : "unknown";
|
||||
String storedPath = null;
|
||||
|
||||
try {
|
||||
Path dir = Paths.get(uploadBasePath, refType.toLowerCase());
|
||||
Files.createDirectories(dir);
|
||||
String storedName = UUID.randomUUID() + "_" + originalName;
|
||||
Path dest = dir.resolve(storedName);
|
||||
file.transferTo(dest);
|
||||
storedPath = dest.toString();
|
||||
} catch (IOException e) {
|
||||
log.warn("파일 저장 실패 (fallback: 메타만 저장): refType={}, refId={}, file={}, error={}",
|
||||
refType, refId, originalName, e.getMessage());
|
||||
storedPath = "[STORAGE_FAILED]/" + originalName;
|
||||
}
|
||||
|
||||
AttachmentVO vo = new AttachmentVO();
|
||||
vo.setRefType(refType);
|
||||
vo.setRefId(refId);
|
||||
vo.setFileName(originalName);
|
||||
vo.setFilePath(storedPath);
|
||||
vo.setFileSize(file.getSize());
|
||||
vo.setMimeType(file.getContentType());
|
||||
vo.setUploadedBy(SecurityUtil.getCurrentUserId());
|
||||
mapper.insert(vo);
|
||||
return vo.getAttachmentId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 파일 다운로드를 위한 실제 경로 반환.
|
||||
*/
|
||||
public Path resolveFilePath(Long attachmentId) {
|
||||
AttachmentResp resp = mapper.selectById(attachmentId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (resp.getFilePath() == null || resp.getFilePath().startsWith("[STORAGE_FAILED]")) {
|
||||
throw new BizException(ErrorCode.NOT_FOUND, "파일이 저장되지 않아 다운로드할 수 없습니다");
|
||||
}
|
||||
return Paths.get(resp.getFilePath());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Long attachmentId) {
|
||||
AttachmentResp resp = mapper.selectById(attachmentId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
// 실제 파일 삭제 시도 (실패해도 메타 삭제 진행)
|
||||
if (resp.getFilePath() != null && !resp.getFilePath().startsWith("[STORAGE_FAILED]")) {
|
||||
try {
|
||||
Files.deleteIfExists(Paths.get(resp.getFilePath()));
|
||||
} catch (IOException e) {
|
||||
log.warn("파일 삭제 실패: path={}", resp.getFilePath(), e);
|
||||
}
|
||||
}
|
||||
mapper.delete(attachmentId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.ga.api.service.commission;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.commission.CollectionCommissionLedgerMapper;
|
||||
import com.ga.core.mapper.commission.CollectionCommissionRuleMapper;
|
||||
import com.ga.core.vo.commission.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class CollectionCommissionService {
|
||||
|
||||
private final CollectionCommissionRuleMapper ruleMapper;
|
||||
private final CollectionCommissionLedgerMapper ledgerMapper;
|
||||
|
||||
// ── Rule ──────────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<CollectionCommissionRuleResp> listRules(CollectionCommissionRuleSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(ruleMapper.selectList(param));
|
||||
}
|
||||
|
||||
public CollectionCommissionRuleResp detailRule(Long ruleId) {
|
||||
CollectionCommissionRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long createRule(CollectionCommissionRuleSaveReq req) {
|
||||
CollectionCommissionRuleVO vo = new CollectionCommissionRuleVO();
|
||||
vo.setProductId(req.getProductId());
|
||||
vo.setPaymentCycle(req.getPaymentCycle());
|
||||
vo.setCommissionRate(req.getCommissionRate());
|
||||
vo.setEffectiveFrom(req.getEffectiveFrom());
|
||||
vo.setEffectiveTo(req.getEffectiveTo());
|
||||
ruleMapper.insert(vo);
|
||||
return vo.getRuleId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateRule(Long ruleId, CollectionCommissionRuleSaveReq req) {
|
||||
CollectionCommissionRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
CollectionCommissionRuleVO vo = new CollectionCommissionRuleVO();
|
||||
vo.setRuleId(ruleId);
|
||||
vo.setProductId(req.getProductId());
|
||||
vo.setPaymentCycle(req.getPaymentCycle());
|
||||
vo.setCommissionRate(req.getCommissionRate());
|
||||
vo.setEffectiveFrom(req.getEffectiveFrom());
|
||||
vo.setEffectiveTo(req.getEffectiveTo());
|
||||
ruleMapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteRule(Long ruleId) {
|
||||
CollectionCommissionRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
ruleMapper.delete(ruleId);
|
||||
}
|
||||
|
||||
// ── Ledger ────────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<CollectionCommissionLedgerResp> listLedgers(CollectionCommissionLedgerSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(ledgerMapper.selectList(param));
|
||||
}
|
||||
|
||||
public CollectionCommissionLedgerResp detailLedger(Long ledgerId) {
|
||||
CollectionCommissionLedgerResp resp = ledgerMapper.selectById(ledgerId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long createLedger(CollectionCommissionLedgerSaveReq req) {
|
||||
CollectionCommissionLedgerVO vo = new CollectionCommissionLedgerVO();
|
||||
vo.setContractId(req.getContractId());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setSettleMonth(req.getSettleMonth());
|
||||
vo.setPremiumAmount(req.getPremiumAmount());
|
||||
vo.setCommissionRate(req.getCommissionRate());
|
||||
// 수금수수료 = 보험료 × 수수료율
|
||||
vo.setCommissionAmount(req.getPremiumAmount().multiply(req.getCommissionRate()));
|
||||
vo.setPaymentCycle(req.getPaymentCycle());
|
||||
vo.setPaidAt(req.getPaidAt());
|
||||
vo.setStatus("CALCULATED");
|
||||
ledgerMapper.insert(vo);
|
||||
return vo.getLedgerId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.ga.api.service.commission;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.commission.CommissionMasterMapper;
|
||||
import com.ga.core.vo.commission.CommissionMasterResp;
|
||||
import com.ga.core.vo.commission.CommissionMasterSearchParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class CommissionMasterService {
|
||||
|
||||
private final CommissionMasterMapper mapper;
|
||||
|
||||
public PageResponse<CommissionMasterResp> list(CommissionMasterSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(mapper.selectList(param));
|
||||
}
|
||||
|
||||
public CommissionMasterResp detail(Long masterId) {
|
||||
CommissionMasterResp resp = mapper.selectById(masterId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
public List<CommissionMasterResp> listByAgentAndMonth(Long agentId, String settleMonth) {
|
||||
return mapper.selectByAgentAndMonth(agentId, settleMonth);
|
||||
}
|
||||
|
||||
public List<CommissionMasterResp> aggregatedByMonth(String settleMonth) {
|
||||
return mapper.selectAggregatedByMonth(settleMonth);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateStatus(Long masterId, String status) {
|
||||
CommissionMasterResp resp = mapper.selectById(masterId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
mapper.updateStatus(masterId, status);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Long masterId) {
|
||||
CommissionMasterResp resp = mapper.selectById(masterId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
mapper.delete(masterId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.ga.api.service.commission;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.commission.OverrideLedgerMapper;
|
||||
import com.ga.core.mapper.commission.OverrideSummaryMapper;
|
||||
import com.ga.core.vo.commission.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class OverrideLedgerService {
|
||||
|
||||
private final OverrideLedgerMapper ledgerMapper;
|
||||
private final OverrideSummaryMapper summaryMapper;
|
||||
|
||||
public PageResponse<OverrideLedgerResp> list(OverrideLedgerSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(ledgerMapper.selectList(param));
|
||||
}
|
||||
|
||||
public OverrideLedgerResp detail(Long ledgerId) {
|
||||
OverrideLedgerResp resp = ledgerMapper.selectById(ledgerId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
public List<OverrideSummaryResp> summaryList(OverrideSummarySearchParam param) {
|
||||
return summaryMapper.selectList(param);
|
||||
}
|
||||
|
||||
public OverrideSummaryResp summaryByAgentAndMonth(Long toAgentId, String settleMonth) {
|
||||
OverrideSummaryResp resp = summaryMapper.selectByAgentAndMonth(toAgentId, settleMonth);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.ga.api.service.commission;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.commission.PersistencyBonusMapper;
|
||||
import com.ga.core.mapper.commission.PersistencyBonusRuleMapper;
|
||||
import com.ga.core.vo.commission.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class PersistencyBonusService {
|
||||
|
||||
private final PersistencyBonusRuleMapper ruleMapper;
|
||||
private final PersistencyBonusMapper bonusMapper;
|
||||
|
||||
// ── Rule ──────────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<PersistencyBonusRuleResp> listRules(PersistencyBonusRuleSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(ruleMapper.selectList(param));
|
||||
}
|
||||
|
||||
public PersistencyBonusRuleResp detailRule(Long ruleId) {
|
||||
PersistencyBonusRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long createRule(PersistencyBonusRuleSaveReq req) {
|
||||
PersistencyBonusRuleVO vo = new PersistencyBonusRuleVO();
|
||||
vo.setGradeId(req.getGradeId());
|
||||
vo.setRetentionMonth(req.getRetentionMonth());
|
||||
vo.setRetentionRateThreshold(req.getRetentionRateThreshold());
|
||||
vo.setBonusType(req.getBonusType());
|
||||
vo.setBonusValue(req.getBonusValue());
|
||||
vo.setEffectiveFrom(req.getEffectiveFrom());
|
||||
vo.setEffectiveTo(req.getEffectiveTo());
|
||||
ruleMapper.insert(vo);
|
||||
return vo.getRuleId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateRule(Long ruleId, PersistencyBonusRuleSaveReq req) {
|
||||
PersistencyBonusRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
PersistencyBonusRuleVO vo = new PersistencyBonusRuleVO();
|
||||
vo.setRuleId(ruleId);
|
||||
vo.setGradeId(req.getGradeId());
|
||||
vo.setRetentionMonth(req.getRetentionMonth());
|
||||
vo.setRetentionRateThreshold(req.getRetentionRateThreshold());
|
||||
vo.setBonusType(req.getBonusType());
|
||||
vo.setBonusValue(req.getBonusValue());
|
||||
vo.setEffectiveFrom(req.getEffectiveFrom());
|
||||
vo.setEffectiveTo(req.getEffectiveTo());
|
||||
ruleMapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteRule(Long ruleId) {
|
||||
PersistencyBonusRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
ruleMapper.delete(ruleId);
|
||||
}
|
||||
|
||||
// ── Bonus ─────────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<PersistencyBonusResp> listBonuses(PersistencyBonusSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(bonusMapper.selectList(param));
|
||||
}
|
||||
|
||||
public PersistencyBonusResp detailBonus(Long bonusId) {
|
||||
PersistencyBonusResp resp = bonusMapper.selectById(bonusId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 수동 지급 등록/갱신 — UNIQUE(agent_id, base_month, retention_month) 기반 upsert.
|
||||
*/
|
||||
@Transactional
|
||||
public void upsertBonus(PersistencyBonusSaveReq req) {
|
||||
PersistencyBonusVO vo = new PersistencyBonusVO();
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setRuleId(req.getRuleId());
|
||||
vo.setBaseMonth(req.getBaseMonth());
|
||||
vo.setRetentionMonth(req.getRetentionMonth());
|
||||
vo.setSettleMonth(req.getSettleMonth());
|
||||
vo.setRetentionRate(req.getRetentionRate());
|
||||
vo.setBonusAmount(req.getBonusAmount());
|
||||
vo.setStatus("CALCULATED");
|
||||
bonusMapper.upsert(vo);
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
package com.ga.api.service.commission;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.commission.ReinstatementCommissionLedgerMapper;
|
||||
import com.ga.core.mapper.commission.ReinstatementCommissionRuleMapper;
|
||||
import com.ga.core.vo.commission.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class ReinstatementCommissionService {
|
||||
|
||||
private final ReinstatementCommissionRuleMapper ruleMapper;
|
||||
private final ReinstatementCommissionLedgerMapper ledgerMapper;
|
||||
|
||||
// ── Rule ──────────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<ReinstatementCommissionRuleResp> listRules(ReinstatementCommissionRuleSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(ruleMapper.selectList(param));
|
||||
}
|
||||
|
||||
public ReinstatementCommissionRuleResp detailRule(Long ruleId) {
|
||||
ReinstatementCommissionRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long createRule(ReinstatementCommissionRuleSaveReq req) {
|
||||
ReinstatementCommissionRuleVO vo = new ReinstatementCommissionRuleVO();
|
||||
vo.setProductId(req.getProductId());
|
||||
vo.setPayType(req.getPayType());
|
||||
vo.setRateValue(req.getRateValue());
|
||||
vo.setFixedAmount(req.getFixedAmount());
|
||||
vo.setChargebackReversalRate(req.getChargebackReversalRate());
|
||||
vo.setEffectiveFrom(req.getEffectiveFrom());
|
||||
vo.setEffectiveTo(req.getEffectiveTo());
|
||||
ruleMapper.insert(vo);
|
||||
return vo.getRuleId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateRule(Long ruleId, ReinstatementCommissionRuleSaveReq req) {
|
||||
ReinstatementCommissionRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
ReinstatementCommissionRuleVO vo = new ReinstatementCommissionRuleVO();
|
||||
vo.setRuleId(ruleId);
|
||||
vo.setProductId(req.getProductId());
|
||||
vo.setPayType(req.getPayType());
|
||||
vo.setRateValue(req.getRateValue());
|
||||
vo.setFixedAmount(req.getFixedAmount());
|
||||
vo.setChargebackReversalRate(req.getChargebackReversalRate());
|
||||
vo.setEffectiveFrom(req.getEffectiveFrom());
|
||||
vo.setEffectiveTo(req.getEffectiveTo());
|
||||
ruleMapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteRule(Long ruleId) {
|
||||
ReinstatementCommissionRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
ruleMapper.delete(ruleId);
|
||||
}
|
||||
|
||||
// ── Ledger ────────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<ReinstatementCommissionLedgerResp> listLedgers(ReinstatementCommissionLedgerSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(ledgerMapper.selectList(param));
|
||||
}
|
||||
|
||||
public ReinstatementCommissionLedgerResp detailLedger(Long ledgerId) {
|
||||
ReinstatementCommissionLedgerResp resp = ledgerMapper.selectById(ledgerId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 수동 등록 — chargebackReversal 은 요청값 그대로.
|
||||
* netCommission = commissionAmount + chargebackReversal 로 자동 계산.
|
||||
*/
|
||||
@Transactional
|
||||
public Long createLedger(ReinstatementCommissionLedgerSaveReq req) {
|
||||
ReinstatementCommissionLedgerVO vo = new ReinstatementCommissionLedgerVO();
|
||||
vo.setContractId(req.getContractId());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setRuleId(req.getRuleId());
|
||||
vo.setSettleMonth(req.getSettleMonth());
|
||||
vo.setReinstatementDate(req.getReinstatementDate());
|
||||
vo.setReinstatementPremium(req.getReinstatementPremium());
|
||||
vo.setCommissionAmount(req.getCommissionAmount());
|
||||
BigDecimal reversal = req.getChargebackReversal() != null ? req.getChargebackReversal() : BigDecimal.ZERO;
|
||||
vo.setChargebackReversal(reversal);
|
||||
vo.setNetCommission(req.getCommissionAmount().add(reversal));
|
||||
vo.setPayType(req.getPayType());
|
||||
vo.setStatus("CALCULATED");
|
||||
ledgerMapper.insert(vo);
|
||||
return vo.getLedgerId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.ga.api.service.commission;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.commission.RenewalCommissionLedgerMapper;
|
||||
import com.ga.core.mapper.commission.RenewalCommissionRuleMapper;
|
||||
import com.ga.core.vo.commission.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class RenewalCommissionService {
|
||||
|
||||
private final RenewalCommissionRuleMapper ruleMapper;
|
||||
private final RenewalCommissionLedgerMapper ledgerMapper;
|
||||
|
||||
// ── Rule ──────────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<RenewalCommissionRuleResp> listRules(RenewalCommissionRuleSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(ruleMapper.selectList(param));
|
||||
}
|
||||
|
||||
public RenewalCommissionRuleResp detailRule(Long ruleId) {
|
||||
RenewalCommissionRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long createRule(RenewalCommissionRuleSaveReq req) {
|
||||
RenewalCommissionRuleVO vo = new RenewalCommissionRuleVO();
|
||||
vo.setProductId(req.getProductId());
|
||||
vo.setPayType(req.getPayType());
|
||||
vo.setRateValue(req.getRateValue());
|
||||
vo.setFixedAmount(req.getFixedAmount());
|
||||
vo.setEffectiveFrom(req.getEffectiveFrom());
|
||||
vo.setEffectiveTo(req.getEffectiveTo());
|
||||
ruleMapper.insert(vo);
|
||||
return vo.getRuleId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateRule(Long ruleId, RenewalCommissionRuleSaveReq req) {
|
||||
RenewalCommissionRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
RenewalCommissionRuleVO vo = new RenewalCommissionRuleVO();
|
||||
vo.setRuleId(ruleId);
|
||||
vo.setProductId(req.getProductId());
|
||||
vo.setPayType(req.getPayType());
|
||||
vo.setRateValue(req.getRateValue());
|
||||
vo.setFixedAmount(req.getFixedAmount());
|
||||
vo.setEffectiveFrom(req.getEffectiveFrom());
|
||||
vo.setEffectiveTo(req.getEffectiveTo());
|
||||
ruleMapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteRule(Long ruleId) {
|
||||
RenewalCommissionRuleResp resp = ruleMapper.selectById(ruleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
ruleMapper.delete(ruleId);
|
||||
}
|
||||
|
||||
// ── Ledger ────────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<RenewalCommissionLedgerResp> listLedgers(RenewalCommissionLedgerSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(ledgerMapper.selectList(param));
|
||||
}
|
||||
|
||||
public RenewalCommissionLedgerResp detailLedger(Long ledgerId) {
|
||||
RenewalCommissionLedgerResp resp = ledgerMapper.selectById(ledgerId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long createLedger(RenewalCommissionLedgerSaveReq req) {
|
||||
RenewalCommissionLedgerVO vo = new RenewalCommissionLedgerVO();
|
||||
vo.setContractId(req.getContractId());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setRuleId(req.getRuleId());
|
||||
vo.setSettleMonth(req.getSettleMonth());
|
||||
vo.setRenewalDate(req.getRenewalDate());
|
||||
vo.setRenewalPremium(req.getRenewalPremium());
|
||||
vo.setCommissionAmount(req.getCommissionAmount());
|
||||
vo.setPayType(req.getPayType());
|
||||
vo.setStatus("CALCULATED");
|
||||
ledgerMapper.insert(vo);
|
||||
return vo.getLedgerId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.ga.api.service.complaint;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.complaint.ComplaintMapper;
|
||||
import com.ga.core.vo.complaint.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class ComplaintService {
|
||||
|
||||
private final ComplaintMapper mapper;
|
||||
|
||||
public PageResponse<ComplaintResp> list(ComplaintSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(mapper.selectList(param));
|
||||
}
|
||||
|
||||
public ComplaintResp detail(Long complaintId) {
|
||||
ComplaintResp resp = mapper.selectById(complaintId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(ComplaintSaveReq req) {
|
||||
ComplaintVO vo = new ComplaintVO();
|
||||
vo.setContractId(req.getContractId());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setCustomerName(req.getCustomerName());
|
||||
vo.setComplaintDate(req.getComplaintDate());
|
||||
vo.setChannel(req.getChannel());
|
||||
vo.setComplaintType(req.getComplaintType());
|
||||
vo.setSeverity(req.getSeverity() != null ? req.getSeverity() : "MID");
|
||||
vo.setStatus(ComplaintStatus.OPEN.name());
|
||||
vo.setResolution(req.getResolution());
|
||||
// chargebackTriggered=true 면 P5에서 chargeback_ledger 자동 생성 예정 — 지금은 플래그만 저장
|
||||
vo.setChargebackTriggered(req.getChargebackTriggered());
|
||||
mapper.insert(vo);
|
||||
return vo.getComplaintId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(Long complaintId, ComplaintSaveReq req) {
|
||||
ComplaintResp existing = mapper.selectById(complaintId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
ComplaintVO vo = new ComplaintVO();
|
||||
vo.setComplaintId(complaintId);
|
||||
vo.setContractId(req.getContractId());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setCustomerName(req.getCustomerName());
|
||||
vo.setComplaintDate(req.getComplaintDate());
|
||||
vo.setChannel(req.getChannel());
|
||||
vo.setComplaintType(req.getComplaintType());
|
||||
vo.setSeverity(req.getSeverity());
|
||||
vo.setResolution(req.getResolution());
|
||||
vo.setChargebackTriggered(req.getChargebackTriggered());
|
||||
mapper.update(vo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 처리완료 — status=CLOSED.
|
||||
* chargebackTriggered=true 인 건의 실제 환수 생성은 P5 배치에서.
|
||||
*/
|
||||
@Transactional
|
||||
public void close(Long complaintId, String resolution) {
|
||||
ComplaintResp existing = mapper.selectById(complaintId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (ComplaintStatus.CLOSED.name().equals(existing.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "이미 처리완료된 민원입니다");
|
||||
}
|
||||
mapper.updateStatus(complaintId, ComplaintStatus.CLOSED.name(), resolution);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Long complaintId) {
|
||||
ComplaintResp existing = mapper.selectById(complaintId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
mapper.delete(complaintId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.ga.api.service.contract;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.contract.AgentContractMapper;
|
||||
import com.ga.core.vo.contract.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class AgentContractService {
|
||||
|
||||
private final AgentContractMapper mapper;
|
||||
|
||||
public PageResponse<AgentContractResp> list(AgentContractSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(mapper.selectList(param));
|
||||
}
|
||||
|
||||
public AgentContractResp detail(Long contractId) {
|
||||
AgentContractResp resp = mapper.selectById(contractId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(AgentContractSaveReq req) {
|
||||
AgentContractVO vo = new AgentContractVO();
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setCarrierId(req.getCarrierId());
|
||||
vo.setContractNo(req.getContractNo());
|
||||
vo.setSignedDate(req.getSignedDate());
|
||||
vo.setEffectiveFrom(req.getEffectiveFrom());
|
||||
vo.setEffectiveTo(req.getEffectiveTo());
|
||||
vo.setOnboardingBonusAmount(req.getOnboardingBonusAmount());
|
||||
vo.setStatus(AgentContractStatus.ACTIVE.name());
|
||||
mapper.insert(vo);
|
||||
return vo.getContractId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(Long contractId, AgentContractSaveReq req) {
|
||||
AgentContractResp existing = mapper.selectById(contractId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
AgentContractVO vo = new AgentContractVO();
|
||||
vo.setContractId(contractId);
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setCarrierId(req.getCarrierId());
|
||||
vo.setContractNo(req.getContractNo());
|
||||
vo.setSignedDate(req.getSignedDate());
|
||||
vo.setEffectiveFrom(req.getEffectiveFrom());
|
||||
vo.setEffectiveTo(req.getEffectiveTo());
|
||||
vo.setOnboardingBonusAmount(req.getOnboardingBonusAmount());
|
||||
mapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void terminate(Long contractId, String reason) {
|
||||
AgentContractResp existing = mapper.selectById(contractId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (AgentContractStatus.TERMINATED.name().equals(existing.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "이미 해촉된 위촉계약입니다");
|
||||
}
|
||||
mapper.updateStatus(contractId, AgentContractStatus.TERMINATED.name(), reason);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Long contractId) {
|
||||
AgentContractResp existing = mapper.selectById(contractId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
mapper.delete(contractId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.ga.api.service.endorse;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.endorse.ContractEndorsementMapper;
|
||||
import com.ga.core.vo.endorse.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class ContractEndorsementService {
|
||||
|
||||
private final ContractEndorsementMapper mapper;
|
||||
|
||||
public PageResponse<ContractEndorsementResp> list(ContractEndorsementSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(mapper.selectList(param));
|
||||
}
|
||||
|
||||
public ContractEndorsementResp detail(Long endorsementId) {
|
||||
ContractEndorsementResp resp = mapper.selectById(endorsementId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(ContractEndorsementSaveReq req) {
|
||||
ContractEndorsementVO vo = new ContractEndorsementVO();
|
||||
vo.setContractId(req.getContractId());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setEndorsementType(req.getEndorsementType());
|
||||
vo.setOldValue(req.getOldValue());
|
||||
vo.setNewValue(req.getNewValue());
|
||||
vo.setReason(req.getReason());
|
||||
vo.setRequiresCommissionRecalc(req.getRequiresCommissionRecalc());
|
||||
vo.setProcessed(false);
|
||||
mapper.insert(vo);
|
||||
return vo.getEndorsementId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 수동 처리 완료 표시 — 실제 수수료 재계산은 배치 담당(P5).
|
||||
* status 변경(processed=true) 만 수행.
|
||||
*/
|
||||
@Transactional
|
||||
public void process(Long endorsementId) {
|
||||
ContractEndorsementResp existing = mapper.selectById(endorsementId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
mapper.markProcessed(endorsementId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Long endorsementId) {
|
||||
ContractEndorsementResp existing = mapper.selectById(endorsementId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
mapper.delete(endorsementId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.ga.api.service.kpi;
|
||||
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.kpi.KpiMapper;
|
||||
import com.ga.core.vo.kpi.KpiCumulativeResp;
|
||||
import com.ga.core.vo.kpi.KpiMonthlySummaryResp;
|
||||
import com.ga.core.vo.kpi.KpiOrgSummaryResp;
|
||||
import com.ga.core.vo.kpi.KpiRetentionResp;
|
||||
import com.ga.core.vo.kpi.KpiSearchParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class KpiService {
|
||||
|
||||
private final KpiMapper kpiMapper;
|
||||
|
||||
public PageResponse<KpiMonthlySummaryResp> monthlySummary(KpiSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(kpiMapper.selectMonthlySummary(param));
|
||||
}
|
||||
|
||||
public PageResponse<KpiOrgSummaryResp> orgSummary(KpiSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(kpiMapper.selectOrgSummary(param));
|
||||
}
|
||||
|
||||
public PageResponse<KpiRetentionResp> retention(KpiSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(kpiMapper.selectRetention(param));
|
||||
}
|
||||
|
||||
public PageResponse<KpiCumulativeResp> cumulative(KpiSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(kpiMapper.selectCumulative(param));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.ga.api.service.license;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.license.AgentLicenseMapper;
|
||||
import com.ga.core.vo.license.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class AgentLicenseService {
|
||||
|
||||
private final AgentLicenseMapper mapper;
|
||||
|
||||
public PageResponse<AgentLicenseResp> list(AgentLicenseSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(mapper.selectList(param));
|
||||
}
|
||||
|
||||
public AgentLicenseResp detail(Long licenseId) {
|
||||
AgentLicenseResp resp = mapper.selectById(licenseId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
public List<AgentLicenseResp> expiring(int days) {
|
||||
return mapper.selectExpiringWithin(days);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(AgentLicenseSaveReq req) {
|
||||
AgentLicenseVO vo = new AgentLicenseVO();
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setLicenseType(req.getLicenseType());
|
||||
vo.setLicenseNo(req.getLicenseNo());
|
||||
vo.setIssuedDate(req.getIssuedDate());
|
||||
vo.setExpiresDate(req.getExpiresDate());
|
||||
vo.setRenewedFrom(req.getRenewedFrom());
|
||||
vo.setStatus(LicenseStatus.ACTIVE.name());
|
||||
mapper.insert(vo);
|
||||
return vo.getLicenseId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(Long licenseId, AgentLicenseSaveReq req) {
|
||||
AgentLicenseResp existing = mapper.selectById(licenseId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
AgentLicenseVO vo = new AgentLicenseVO();
|
||||
vo.setLicenseId(licenseId);
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setLicenseType(req.getLicenseType());
|
||||
vo.setLicenseNo(req.getLicenseNo());
|
||||
vo.setIssuedDate(req.getIssuedDate());
|
||||
vo.setExpiresDate(req.getExpiresDate());
|
||||
vo.setRenewedFrom(req.getRenewedFrom());
|
||||
mapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Long licenseId) {
|
||||
AgentLicenseResp existing = mapper.selectById(licenseId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
mapper.delete(licenseId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.ga.api.service.notice;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.notice.NoticeMapper;
|
||||
import com.ga.core.mapper.notice.UserNotificationMapper;
|
||||
import com.ga.core.vo.notice.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class NoticeService {
|
||||
|
||||
private final NoticeMapper noticeMapper;
|
||||
private final UserNotificationMapper notificationMapper;
|
||||
|
||||
// ── Notice ────────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<NoticeResp> list(NoticeSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(noticeMapper.selectList(param));
|
||||
}
|
||||
|
||||
public NoticeResp detail(Long noticeId) {
|
||||
NoticeResp resp = noticeMapper.selectById(noticeId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
public List<NoticeResp> activeList() {
|
||||
return noticeMapper.selectActive();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(NoticeSaveReq req) {
|
||||
NoticeVO vo = new NoticeVO();
|
||||
vo.setTitle(req.getTitle());
|
||||
vo.setContent(req.getContent());
|
||||
vo.setNoticeType(req.getNoticeType());
|
||||
vo.setStartDate(req.getStartDate());
|
||||
vo.setEndDate(req.getEndDate());
|
||||
vo.setIsActive(true);
|
||||
vo.setCreatedBy(SecurityUtil.getCurrentUserId());
|
||||
noticeMapper.insert(vo);
|
||||
return vo.getNoticeId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(Long noticeId, NoticeSaveReq req) {
|
||||
NoticeResp existing = noticeMapper.selectById(noticeId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
NoticeVO vo = new NoticeVO();
|
||||
vo.setNoticeId(noticeId);
|
||||
vo.setTitle(req.getTitle());
|
||||
vo.setContent(req.getContent());
|
||||
vo.setNoticeType(req.getNoticeType());
|
||||
vo.setStartDate(req.getStartDate());
|
||||
vo.setEndDate(req.getEndDate());
|
||||
noticeMapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Long noticeId) {
|
||||
NoticeResp existing = noticeMapper.selectById(noticeId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
noticeMapper.delete(noticeId);
|
||||
}
|
||||
|
||||
// ── UserNotification ──────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<UserNotificationResp> listNotifications(UserNotificationSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(notificationMapper.selectList(param));
|
||||
}
|
||||
|
||||
public int unreadCount(Long userId) {
|
||||
return notificationMapper.selectUnreadCount(userId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void markRead(Long notificationId, Long userId) {
|
||||
int affected = notificationMapper.markRead(notificationId, userId);
|
||||
if (affected == 0) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void markAllRead(Long userId) {
|
||||
notificationMapper.markAllRead(userId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.ga.api.service.settle;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.settle.CarrierReconciliationOutMapper;
|
||||
import com.ga.core.vo.settle.CarrierReconciliationOutResp;
|
||||
import com.ga.core.vo.settle.CarrierReconciliationOutSaveReq;
|
||||
import com.ga.core.vo.settle.CarrierReconciliationOutSearchParam;
|
||||
import com.ga.core.vo.settle.CarrierReconciliationOutVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class CarrierReconciliationOutService {
|
||||
|
||||
private final CarrierReconciliationOutMapper reconOutMapper;
|
||||
|
||||
public PageResponse<CarrierReconciliationOutResp> list(CarrierReconciliationOutSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(reconOutMapper.selectList(param));
|
||||
}
|
||||
|
||||
public CarrierReconciliationOutResp detail(Long reconOutId) {
|
||||
CarrierReconciliationOutResp resp = reconOutMapper.selectById(reconOutId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(CarrierReconciliationOutSaveReq req) {
|
||||
// 보험사+정산월 중복 확인
|
||||
CarrierReconciliationOutVO existing = reconOutMapper.selectByCarrierMonth(req.getCarrierId(), req.getSettleMonth());
|
||||
if (existing != null) {
|
||||
throw new BizException(ErrorCode.DUPLICATE_DATA,
|
||||
"이미 등록된 회신 이력입니다: carrierId=" + req.getCarrierId() + ", settleMonth=" + req.getSettleMonth());
|
||||
}
|
||||
|
||||
CarrierReconciliationOutVO vo = new CarrierReconciliationOutVO();
|
||||
vo.setCarrierId(req.getCarrierId());
|
||||
vo.setSettleMonth(req.getSettleMonth());
|
||||
vo.setFilePath(req.getFilePath());
|
||||
vo.setFileName(req.getFileName());
|
||||
vo.setFileSize(req.getFileSize());
|
||||
vo.setRecordCount(req.getRecordCount());
|
||||
vo.setStatus("READY");
|
||||
vo.setRetryCount(0);
|
||||
vo.setCreatedBy(SecurityUtil.getCurrentUserId());
|
||||
reconOutMapper.insert(vo);
|
||||
return vo.getReconOutId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void retry(Long reconOutId) {
|
||||
CarrierReconciliationOutVO vo = reconOutMapper.selectVoById(reconOutId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!"FAIL".equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "실패 상태만 재전송 가능합니다");
|
||||
}
|
||||
// 상태를 READY로 초기화하여 배치가 재처리
|
||||
reconOutMapper.updateStatus(reconOutId, "READY");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.ga.api.service.settle;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.settle.CommissionDisputeMapper;
|
||||
import com.ga.core.vo.settle.CommissionDisputeResp;
|
||||
import com.ga.core.vo.settle.CommissionDisputeSaveReq;
|
||||
import com.ga.core.vo.settle.CommissionDisputeSearchParam;
|
||||
import com.ga.core.vo.settle.CommissionDisputeVO;
|
||||
import com.ga.core.vo.settle.DisputeStatus;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class CommissionDisputeService {
|
||||
|
||||
private final CommissionDisputeMapper disputeMapper;
|
||||
|
||||
public PageResponse<CommissionDisputeResp> list(CommissionDisputeSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(disputeMapper.selectList(param));
|
||||
}
|
||||
|
||||
public CommissionDisputeResp detail(Long disputeId) {
|
||||
CommissionDisputeResp resp = disputeMapper.selectById(disputeId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(CommissionDisputeSaveReq req) {
|
||||
CommissionDisputeVO vo = new CommissionDisputeVO();
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setSettleMonth(req.getSettleMonth());
|
||||
vo.setSettleId(req.getSettleId());
|
||||
vo.setDisputedAmount(req.getDisputedAmount());
|
||||
vo.setClaimAmount(req.getClaimAmount());
|
||||
vo.setReason(req.getReason());
|
||||
vo.setEvidenceUrl(req.getEvidenceUrl());
|
||||
vo.setStatus(DisputeStatus.OPEN.name());
|
||||
disputeMapper.insert(vo);
|
||||
return vo.getDisputeId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void approve(Long disputeId, String resolution, BigDecimal adjustmentAmount, Long correctionId) {
|
||||
CommissionDisputeVO vo = disputeMapper.selectVoById(disputeId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!DisputeStatus.IN_REVIEW.name().equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "검토 중 상태만 승인 가능합니다");
|
||||
}
|
||||
disputeMapper.resolve(disputeId, DisputeStatus.APPROVED.name(),
|
||||
resolution, adjustmentAmount, correctionId, SecurityUtil.getCurrentUserId());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void reject(Long disputeId, String resolution) {
|
||||
CommissionDisputeVO vo = disputeMapper.selectVoById(disputeId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!DisputeStatus.IN_REVIEW.name().equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "검토 중 상태만 기각 가능합니다");
|
||||
}
|
||||
disputeMapper.resolve(disputeId, DisputeStatus.REJECTED.name(),
|
||||
resolution, null, null, SecurityUtil.getCurrentUserId());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void startReview(Long disputeId) {
|
||||
CommissionDisputeVO vo = disputeMapper.selectVoById(disputeId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!DisputeStatus.OPEN.name().equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "OPEN 상태만 검토 시작 가능합니다");
|
||||
}
|
||||
disputeMapper.startReview(disputeId, SecurityUtil.getCurrentUserId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.ga.api.service.settle;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.settle.IncentivePaymentMapper;
|
||||
import com.ga.core.vo.settle.IncentivePayStatus;
|
||||
import com.ga.core.vo.settle.IncentivePaymentResp;
|
||||
import com.ga.core.vo.settle.IncentivePaymentSaveReq;
|
||||
import com.ga.core.vo.settle.IncentivePaymentSearchParam;
|
||||
import com.ga.core.vo.settle.IncentivePaymentVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class IncentivePaymentService {
|
||||
|
||||
private final IncentivePaymentMapper paymentMapper;
|
||||
private final PeriodCloseService periodCloseService;
|
||||
|
||||
public PageResponse<IncentivePaymentResp> list(IncentivePaymentSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(paymentMapper.selectList(param));
|
||||
}
|
||||
|
||||
public IncentivePaymentResp detail(Long incentivePayId) {
|
||||
IncentivePaymentResp resp = paymentMapper.selectById(incentivePayId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(IncentivePaymentSaveReq req) {
|
||||
// 마감 가드
|
||||
periodCloseService.assertNotClosed(req.getSettleMonth());
|
||||
|
||||
IncentivePaymentVO vo = new IncentivePaymentVO();
|
||||
vo.setProgramId(req.getProgramId());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setSettleMonth(req.getSettleMonth());
|
||||
vo.setBaseAmount(req.getBaseAmount());
|
||||
vo.setIncentiveAmount(req.getIncentiveAmount());
|
||||
vo.setStatus(IncentivePayStatus.CALCULATED.name());
|
||||
paymentMapper.insert(vo);
|
||||
return vo.getIncentivePayId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void confirm(Long incentivePayId) {
|
||||
IncentivePaymentVO vo = paymentMapper.selectVoById(incentivePayId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!IncentivePayStatus.CALCULATED.name().equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "CALCULATED 상태만 확정 가능합니다");
|
||||
}
|
||||
// 마감 가드
|
||||
periodCloseService.assertNotClosed(vo.getSettleMonth());
|
||||
paymentMapper.updateStatus(incentivePayId, IncentivePayStatus.CONFIRMED.name(), SecurityUtil.getCurrentUserId());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void cancel(Long incentivePayId, String cancelReason) {
|
||||
IncentivePaymentVO vo = paymentMapper.selectVoById(incentivePayId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (IncentivePayStatus.PAID.name().equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "지급완료된 시책은 취소할 수 없습니다");
|
||||
}
|
||||
paymentMapper.updateStatus(incentivePayId, IncentivePayStatus.CANCELLED.name(), SecurityUtil.getCurrentUserId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.ga.api.service.settle;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.settle.IncentiveProgramMapper;
|
||||
import com.ga.core.vo.settle.IncentiveProgramResp;
|
||||
import com.ga.core.vo.settle.IncentiveProgramSaveReq;
|
||||
import com.ga.core.vo.settle.IncentiveProgramSearchParam;
|
||||
import com.ga.core.vo.settle.IncentiveProgramVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class IncentiveProgramService {
|
||||
|
||||
private final IncentiveProgramMapper programMapper;
|
||||
|
||||
public PageResponse<IncentiveProgramResp> list(IncentiveProgramSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(programMapper.selectList(param));
|
||||
}
|
||||
|
||||
public IncentiveProgramResp detail(Long programId) {
|
||||
IncentiveProgramResp resp = programMapper.selectById(programId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(IncentiveProgramSaveReq req) {
|
||||
IncentiveProgramVO vo = new IncentiveProgramVO();
|
||||
vo.setProgramName(req.getProgramName());
|
||||
vo.setProgramType(req.getProgramType());
|
||||
vo.setTargetType(req.getTargetType());
|
||||
vo.setTargetGradeId(req.getTargetGradeId());
|
||||
vo.setTargetOrgId(req.getTargetOrgId());
|
||||
vo.setProductCategory(req.getProductCategory());
|
||||
vo.setStartMonth(req.getStartMonth());
|
||||
vo.setEndMonth(req.getEndMonth());
|
||||
vo.setConditionDesc(req.getConditionDesc());
|
||||
vo.setPayRate(req.getPayRate());
|
||||
vo.setPayAmountFixed(req.getPayAmountFixed());
|
||||
vo.setPayType(req.getPayType());
|
||||
vo.setBudgetAmount(req.getBudgetAmount());
|
||||
vo.setIsActive(true);
|
||||
vo.setCreatedBy(SecurityUtil.getCurrentUserId());
|
||||
programMapper.insert(vo);
|
||||
return vo.getProgramId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(Long programId, IncentiveProgramSaveReq req) {
|
||||
IncentiveProgramVO existing = programMapper.selectVoById(programId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
|
||||
existing.setProgramName(req.getProgramName());
|
||||
existing.setProgramType(req.getProgramType());
|
||||
existing.setTargetType(req.getTargetType());
|
||||
existing.setTargetGradeId(req.getTargetGradeId());
|
||||
existing.setTargetOrgId(req.getTargetOrgId());
|
||||
existing.setProductCategory(req.getProductCategory());
|
||||
existing.setStartMonth(req.getStartMonth());
|
||||
existing.setEndMonth(req.getEndMonth());
|
||||
existing.setConditionDesc(req.getConditionDesc());
|
||||
existing.setPayRate(req.getPayRate());
|
||||
existing.setPayAmountFixed(req.getPayAmountFixed());
|
||||
existing.setPayType(req.getPayType());
|
||||
existing.setBudgetAmount(req.getBudgetAmount());
|
||||
existing.setUpdatedBy(SecurityUtil.getCurrentUserId());
|
||||
programMapper.update(existing);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void toggleActive(Long programId, boolean isActive) {
|
||||
IncentiveProgramVO existing = programMapper.selectVoById(programId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
programMapper.updateActive(programId, isActive, SecurityUtil.getCurrentUserId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.ga.api.service.settle;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.settle.PeriodCloseMapper;
|
||||
import com.ga.core.vo.settle.PeriodCloseResp;
|
||||
import com.ga.core.vo.settle.PeriodCloseSaveReq;
|
||||
import com.ga.core.vo.settle.PeriodCloseSearchParam;
|
||||
import com.ga.core.vo.settle.PeriodCloseVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class PeriodCloseService {
|
||||
|
||||
private final PeriodCloseMapper periodCloseMapper;
|
||||
|
||||
public PageResponse<PeriodCloseResp> list(PeriodCloseSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(periodCloseMapper.selectList(param));
|
||||
}
|
||||
|
||||
public PeriodCloseResp detail(Long closeId) {
|
||||
PeriodCloseResp resp = periodCloseMapper.selectById(closeId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void close(PeriodCloseSaveReq req) {
|
||||
// 이미 마감된 월인지 확인
|
||||
if (periodCloseMapper.isClosedMonth(req.getCloseMonth())) {
|
||||
throw new BizException(ErrorCode.DUPLICATE_DATA, "이미 마감된 정산월입니다: " + req.getCloseMonth());
|
||||
}
|
||||
PeriodCloseVO vo = new PeriodCloseVO();
|
||||
vo.setCloseMonth(req.getCloseMonth());
|
||||
vo.setNote(req.getNote());
|
||||
vo.setClosedBy(SecurityUtil.getCurrentUserId());
|
||||
periodCloseMapper.insert(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void reopen(Long closeId, String reopenReason) {
|
||||
PeriodCloseResp resp = periodCloseMapper.selectById(closeId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
periodCloseMapper.reopen(closeId, SecurityUtil.getCurrentUserId(), reopenReason);
|
||||
}
|
||||
|
||||
/**
|
||||
* 마감 가드: 해당 정산월이 마감 상태이면 예외 발생.
|
||||
* settle_correction, payment 등 변경 서비스에서 호출.
|
||||
*/
|
||||
public void assertNotClosed(String settleMonth) {
|
||||
if (periodCloseMapper.isClosedMonth(settleMonth)) {
|
||||
throw new BizException(ErrorCode.NOT_PERMITTED, "마감된 기간입니다: " + settleMonth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.ga.api.service.settle;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.settle.SettleCorrectionMapper;
|
||||
import com.ga.core.vo.settle.CorrectionStatus;
|
||||
import com.ga.core.vo.settle.SettleCorrectionResp;
|
||||
import com.ga.core.vo.settle.SettleCorrectionSaveReq;
|
||||
import com.ga.core.vo.settle.SettleCorrectionSearchParam;
|
||||
import com.ga.core.vo.settle.SettleCorrectionVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class SettleCorrectionService {
|
||||
|
||||
private final SettleCorrectionMapper correctionMapper;
|
||||
private final PeriodCloseService periodCloseService;
|
||||
|
||||
public PageResponse<SettleCorrectionResp> list(SettleCorrectionSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(correctionMapper.selectList(param));
|
||||
}
|
||||
|
||||
public SettleCorrectionResp detail(Long correctionId) {
|
||||
SettleCorrectionResp resp = correctionMapper.selectById(correctionId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
public List<SettleCorrectionResp> listByOriginalSettle(Long originalSettleId) {
|
||||
return correctionMapper.selectByOriginalSettleId(originalSettleId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(SettleCorrectionSaveReq req) {
|
||||
// 마감 가드
|
||||
periodCloseService.assertNotClosed(req.getSettleMonth());
|
||||
|
||||
SettleCorrectionVO vo = new SettleCorrectionVO();
|
||||
vo.setOriginalSettleId(req.getOriginalSettleId());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setSettleMonth(req.getSettleMonth());
|
||||
vo.setBeforeAmount(req.getBeforeAmount());
|
||||
vo.setAfterAmount(req.getAfterAmount());
|
||||
vo.setDiffAmount(req.getAfterAmount().subtract(req.getBeforeAmount()));
|
||||
vo.setReasonCode(req.getReasonCode());
|
||||
vo.setReasonDetail(req.getReasonDetail());
|
||||
vo.setStatus(CorrectionStatus.DRAFT.name());
|
||||
vo.setRequestedBy(SecurityUtil.getCurrentUserId());
|
||||
correctionMapper.insert(vo);
|
||||
return vo.getCorrectionId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void approve(Long correctionId) {
|
||||
SettleCorrectionVO vo = correctionMapper.selectVoById(correctionId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!CorrectionStatus.DRAFT.name().equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "DRAFT 상태만 승인 가능합니다");
|
||||
}
|
||||
correctionMapper.updateStatus(correctionId, CorrectionStatus.APPROVED.name(), SecurityUtil.getCurrentUserId());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void cancel(Long correctionId, String cancelReason) {
|
||||
SettleCorrectionVO vo = correctionMapper.selectVoById(correctionId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (CorrectionStatus.APPLIED.name().equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "이미 반영된 정정은 취소할 수 없습니다");
|
||||
}
|
||||
correctionMapper.cancel(correctionId, cancelReason, SecurityUtil.getCurrentUserId());
|
||||
}
|
||||
}
|
||||
@@ -56,13 +56,13 @@ public class SettleService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void hold(Long settleId, String reason) {
|
||||
public void hold(Long settleId, String reason, String reasonCode) {
|
||||
SettleMasterVO vo = masterMapper.selectById(settleId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (SettleStatus.PAID.name().equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.NOT_PERMITTED, "지급완료된 정산은 보류할 수 없습니다");
|
||||
}
|
||||
masterMapper.updateHold(settleId, reason);
|
||||
masterMapper.updateHold(settleId, reason, reasonCode);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.ga.api.service.settle;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.settle.TaxInvoiceMapper;
|
||||
import com.ga.core.vo.settle.TaxInvoiceResp;
|
||||
import com.ga.core.vo.settle.TaxInvoiceSaveReq;
|
||||
import com.ga.core.vo.settle.TaxInvoiceSearchParam;
|
||||
import com.ga.core.vo.settle.TaxInvoiceVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class TaxInvoiceService {
|
||||
|
||||
private final TaxInvoiceMapper taxInvoiceMapper;
|
||||
|
||||
public PageResponse<TaxInvoiceResp> list(TaxInvoiceSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(taxInvoiceMapper.selectList(param));
|
||||
}
|
||||
|
||||
public TaxInvoiceResp detail(Long invoiceId) {
|
||||
TaxInvoiceResp resp = taxInvoiceMapper.selectById(invoiceId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(TaxInvoiceSaveReq req) {
|
||||
// 발행번호 중복 확인
|
||||
if (taxInvoiceMapper.selectByInvoiceNo(req.getInvoiceNo()) != null) {
|
||||
throw new BizException(ErrorCode.DUPLICATE_DATA, "이미 등록된 발행번호입니다: " + req.getInvoiceNo());
|
||||
}
|
||||
|
||||
TaxInvoiceVO vo = new TaxInvoiceVO();
|
||||
vo.setInvoiceNo(req.getInvoiceNo());
|
||||
vo.setInvoiceType(req.getInvoiceType());
|
||||
vo.setIssueDate(req.getIssueDate());
|
||||
vo.setSupplyAmount(req.getSupplyAmount());
|
||||
vo.setTaxAmount(req.getTaxAmount());
|
||||
vo.setTotalAmount(req.getSupplyAmount().add(req.getTaxAmount()));
|
||||
vo.setCounterpartName(req.getCounterpartName());
|
||||
vo.setCounterpartBizNo(req.getCounterpartBizNo());
|
||||
vo.setCounterpartRep(req.getCounterpartRep());
|
||||
vo.setCounterpartAddr(req.getCounterpartAddr());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setSettleMonth(req.getSettleMonth());
|
||||
vo.setSettleId(req.getSettleId());
|
||||
vo.setDescription(req.getDescription());
|
||||
vo.setIssuedBy(SecurityUtil.getCurrentUserId());
|
||||
taxInvoiceMapper.insert(vo);
|
||||
return vo.getInvoiceId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void cancel(Long invoiceId, String cancelReason) {
|
||||
TaxInvoiceResp resp = taxInvoiceMapper.selectById(invoiceId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
taxInvoiceMapper.cancel(invoiceId, LocalDate.now(), cancelReason);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.ga.api.service.settle;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.settle.TerminationSettlementMapper;
|
||||
import com.ga.core.vo.settle.TermSettleStatus;
|
||||
import com.ga.core.vo.settle.TerminationSettlementResp;
|
||||
import com.ga.core.vo.settle.TerminationSettlementSaveReq;
|
||||
import com.ga.core.vo.settle.TerminationSettlementSearchParam;
|
||||
import com.ga.core.vo.settle.TerminationSettlementVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class TerminationSettlementService {
|
||||
|
||||
private final TerminationSettlementMapper termSettleMapper;
|
||||
|
||||
public PageResponse<TerminationSettlementResp> list(TerminationSettlementSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(termSettleMapper.selectList(param));
|
||||
}
|
||||
|
||||
public TerminationSettlementResp detail(Long termSettleId) {
|
||||
TerminationSettlementResp resp = termSettleMapper.selectById(termSettleId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(TerminationSettlementSaveReq req) {
|
||||
// 해당 설계사의 해촉 정산이 이미 있는지 확인
|
||||
TerminationSettlementVO existing = termSettleMapper.selectByAgent(req.getAgentId());
|
||||
if (existing != null && !TermSettleStatus.CANCELLED.name().equals(existing.getStatus())) {
|
||||
throw new BizException(ErrorCode.DUPLICATE_DATA, "이미 처리 중인 해촉 정산이 있습니다");
|
||||
}
|
||||
|
||||
TerminationSettlementVO vo = new TerminationSettlementVO();
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setTerminationDate(req.getTerminationDate());
|
||||
vo.setOrgHistoryId(req.getOrgHistoryId());
|
||||
vo.setCalcMonth(req.getCalcMonth());
|
||||
vo.setUnpaidRecruitAmount(req.getUnpaidRecruitAmount());
|
||||
vo.setUnpaidInstallmentAmount(req.getUnpaidInstallmentAmount());
|
||||
vo.setUnpaidIncentiveAmount(req.getUnpaidIncentiveAmount());
|
||||
vo.setChargebackExpectedAmount(req.getChargebackExpectedAmount());
|
||||
vo.setChargebackWaivedAmount(req.getChargebackWaivedAmount());
|
||||
vo.setDeductionAmount(req.getDeductionAmount());
|
||||
vo.setFinalPayAmount(req.getFinalPayAmount());
|
||||
vo.setNote(req.getNote());
|
||||
vo.setStatus(TermSettleStatus.CALCULATING.name());
|
||||
vo.setCreatedBy(SecurityUtil.getCurrentUserId());
|
||||
termSettleMapper.insert(vo);
|
||||
return vo.getTermSettleId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(Long termSettleId, TerminationSettlementSaveReq req) {
|
||||
TerminationSettlementVO vo = termSettleMapper.selectVoById(termSettleId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!TermSettleStatus.CALCULATING.name().equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "산출 중 상태만 수정 가능합니다");
|
||||
}
|
||||
|
||||
vo.setUnpaidRecruitAmount(req.getUnpaidRecruitAmount());
|
||||
vo.setUnpaidInstallmentAmount(req.getUnpaidInstallmentAmount());
|
||||
vo.setUnpaidIncentiveAmount(req.getUnpaidIncentiveAmount());
|
||||
vo.setChargebackExpectedAmount(req.getChargebackExpectedAmount());
|
||||
vo.setChargebackWaivedAmount(req.getChargebackWaivedAmount());
|
||||
vo.setDeductionAmount(req.getDeductionAmount());
|
||||
vo.setFinalPayAmount(req.getFinalPayAmount());
|
||||
vo.setNote(req.getNote());
|
||||
vo.setUpdatedBy(SecurityUtil.getCurrentUserId());
|
||||
termSettleMapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void confirm(Long termSettleId) {
|
||||
TerminationSettlementVO vo = termSettleMapper.selectVoById(termSettleId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!TermSettleStatus.CALCULATING.name().equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "산출 중 상태만 확정 가능합니다");
|
||||
}
|
||||
termSettleMapper.updateStatus(termSettleId, TermSettleStatus.CONFIRMED.name(), SecurityUtil.getCurrentUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 해촉 시 자동 생성 처리 (POST /process).
|
||||
* agentId를 받아 CALCULATING 상태로 해촉 정산 레코드 생성.
|
||||
* 실제 금액 산출은 배치 또는 별도 update 호출로 완성.
|
||||
*/
|
||||
@Transactional
|
||||
public Long process(TerminationSettlementSaveReq req) {
|
||||
return create(req);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.ga.api.service.training;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.training.AgentTrainingMapper;
|
||||
import com.ga.core.mapper.training.TrainingRequirementMapper;
|
||||
import com.ga.core.vo.training.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class AgentTrainingService {
|
||||
|
||||
private final AgentTrainingMapper trainingMapper;
|
||||
private final TrainingRequirementMapper requirementMapper;
|
||||
|
||||
// ── Training ──────────────────────────────────────────────────────────────
|
||||
|
||||
public PageResponse<AgentTrainingResp> list(AgentTrainingSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(trainingMapper.selectList(param));
|
||||
}
|
||||
|
||||
public AgentTrainingResp detail(Long trainingId) {
|
||||
AgentTrainingResp resp = trainingMapper.selectById(trainingId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 설계사 + 연도 기준 연간 이수 시간 합계.
|
||||
* 의무 시간 충족 여부도 함께 반환.
|
||||
*/
|
||||
public BigDecimal annualHours(Long agentId, int year) {
|
||||
BigDecimal hours = trainingMapper.selectAnnualHoursByAgent(agentId, year);
|
||||
return hours != null ? hours : BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(AgentTrainingSaveReq req) {
|
||||
AgentTrainingVO vo = new AgentTrainingVO();
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setCourseName(req.getCourseName());
|
||||
vo.setCourseType(req.getCourseType());
|
||||
vo.setTrainingDate(req.getTrainingDate());
|
||||
vo.setHours(req.getHours());
|
||||
vo.setCertificateNo(req.getCertificateNo());
|
||||
vo.setInstructor(req.getInstructor());
|
||||
trainingMapper.insert(vo);
|
||||
return vo.getTrainingId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(Long trainingId, AgentTrainingSaveReq req) {
|
||||
AgentTrainingResp existing = trainingMapper.selectById(trainingId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
AgentTrainingVO vo = new AgentTrainingVO();
|
||||
vo.setTrainingId(trainingId);
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setCourseName(req.getCourseName());
|
||||
vo.setCourseType(req.getCourseType());
|
||||
vo.setTrainingDate(req.getTrainingDate());
|
||||
vo.setHours(req.getHours());
|
||||
vo.setCertificateNo(req.getCertificateNo());
|
||||
vo.setInstructor(req.getInstructor());
|
||||
trainingMapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Long trainingId) {
|
||||
AgentTrainingResp existing = trainingMapper.selectById(trainingId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
trainingMapper.delete(trainingId);
|
||||
}
|
||||
|
||||
// ── Requirement ───────────────────────────────────────────────────────────
|
||||
|
||||
public List<TrainingRequirementResp> listRequirements(TrainingRequirementSearchParam param) {
|
||||
return requirementMapper.selectList(param);
|
||||
}
|
||||
|
||||
public TrainingRequirementResp requirementByYear(int year) {
|
||||
TrainingRequirementResp resp = requirementMapper.selectByYear(year);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void saveRequirement(TrainingRequirementSaveReq req) {
|
||||
TrainingRequirementVO existing = new TrainingRequirementVO();
|
||||
existing.setTargetYear(req.getTargetYear());
|
||||
existing.setRequiredHours(req.getRequiredHours());
|
||||
existing.setDescription(req.getDescription());
|
||||
// upsert: try update first, insert if 0 rows
|
||||
TrainingRequirementResp curr = requirementMapper.selectByYear(req.getTargetYear());
|
||||
if (curr == null) {
|
||||
requirementMapper.insert(existing);
|
||||
} else {
|
||||
existing.setReqId(curr.getReqId());
|
||||
requirementMapper.update(existing);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.ga.api.service.withdraw;
|
||||
|
||||
import com.ga.api.service.approval.ApprovalService;
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.withdraw.WithdrawRequestMapper;
|
||||
import com.ga.core.vo.approval.ApprovalRequestSaveReq;
|
||||
import com.ga.core.vo.withdraw.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class WithdrawRequestService {
|
||||
|
||||
private final WithdrawRequestMapper mapper;
|
||||
private final ApprovalService approvalService;
|
||||
|
||||
/** 출금 신청 기본 결재선 코드 (application.yml 외부화 권장) */
|
||||
@Value("${app.withdraw.approval-line-id:1}")
|
||||
private Long defaultApprovalLineId;
|
||||
|
||||
public PageResponse<WithdrawRequestResp> list(WithdrawRequestSearchParam param) {
|
||||
param.startPage();
|
||||
java.util.List<WithdrawRequestResp> rows = mapper.selectList(param);
|
||||
rows.forEach(this::maskAccountNo);
|
||||
return PageResponse.of(rows);
|
||||
}
|
||||
|
||||
public WithdrawRequestResp detail(Long requestId) {
|
||||
WithdrawRequestResp resp = mapper.selectById(requestId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
maskAccountNo(resp);
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 출금 신청 등록 + 결재 요청 자동 연동.
|
||||
* account_no 마스킹은 응답 시에만 적용 — VO 저장 시 원문 저장.
|
||||
*/
|
||||
@Transactional
|
||||
public Long create(WithdrawRequestSaveReq req) {
|
||||
WithdrawRequestVO vo = new WithdrawRequestVO();
|
||||
vo.setSettleMasterId(req.getSettleMasterId());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setAmount(req.getAmount());
|
||||
vo.setRequestedBy(req.getRequestedBy());
|
||||
vo.setRequestedAt(LocalDateTime.now());
|
||||
vo.setBankCode(req.getBankCode());
|
||||
vo.setAccountNo(req.getAccountNo()); // 원문 저장 (EncryptTypeHandler가 암호화)
|
||||
vo.setStatus(WithdrawStatus.REQUESTED.name());
|
||||
mapper.insert(vo);
|
||||
|
||||
// 결재 요청 자동 생성
|
||||
try {
|
||||
ApprovalRequestSaveReq approvalReq = new ApprovalRequestSaveReq();
|
||||
approvalReq.setTargetType("WITHDRAW");
|
||||
approvalReq.setTargetId(vo.getRequestId());
|
||||
approvalReq.setLineId(defaultApprovalLineId);
|
||||
approvalReq.setRequestedBy(req.getRequestedBy());
|
||||
Long approvalRequestId = approvalService.createRequest(approvalReq);
|
||||
// 결재 요청 ID를 withdraw_request에 업데이트 (approve 후 연동 위해)
|
||||
log.info("출금신청 결재 요청 생성: withdrawId={}, approvalRequestId={}", vo.getRequestId(), approvalRequestId);
|
||||
} catch (Exception e) {
|
||||
log.warn("결재 요청 생성 실패 (출금신청은 유지): withdrawId={}, error={}", vo.getRequestId(), e.getMessage());
|
||||
}
|
||||
|
||||
return vo.getRequestId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void cancel(Long requestId) {
|
||||
WithdrawRequestResp existing = mapper.selectById(requestId);
|
||||
if (existing == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!WithdrawStatus.REQUESTED.name().equals(existing.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "신청 상태에서만 취소 가능합니다");
|
||||
}
|
||||
mapper.cancel(requestId);
|
||||
}
|
||||
|
||||
/**
|
||||
* account_no 마스킹: 뒤 4자리만 표출.
|
||||
* 원본: "123-456-78901234" → 마스킹: "*** *** *1234"
|
||||
*/
|
||||
private void maskAccountNo(WithdrawRequestResp resp) {
|
||||
String raw = resp.getAccountNo();
|
||||
if (raw == null || raw.isBlank()) return;
|
||||
// 숫자만 추출 후 뒤 4자리만 남기고 마스킹
|
||||
String digits = raw.replaceAll("[^0-9]", "");
|
||||
if (digits.length() <= 4) {
|
||||
resp.setAccountNo("*** *** *" + digits);
|
||||
} else {
|
||||
String last4 = digits.substring(digits.length() - 4);
|
||||
resp.setAccountNo("*** *** *" + last4);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user