feat: ga-core + ga-api + ga-batch + V13-V15 + Docker + frontend skeleton
ga-core (22 tables): - user/role: VO + Mapper + XML (login + RBAC) - org: Grade, Organization (CTE recursive tree), Agent + history - product: InsuranceCompany, Product, Contract - rule: CommissionRate, PayoutRule, OverrideRule, ChargebackRule, ExceptionTypeCode - receive: CompanyProfile, FieldMapping, CodeMapping, RawCommissionData, ParseError - ledger: Recruit, Maintain, Exception (batch insert + cursor) - settle: SettleMaster (UPSERT), Override, Chargeback, Payment, Reconciliation, BatchJobLog - All XMLs use EncryptTypeHandler for PII fields ga-api: - AuthController: login (lock on N fails), refresh, me, password, logout - Domain controllers: Agent, Organization, Contract, Company, Product, Rule, Receive, Ledger (recruit/maintain/exception + approve), Settle (confirm/hold/release), Payment, User, Role (matrix), BatchTrigger - All use @RequirePermission + @DataChangeLog ga-batch: - MonthlySettlementJob: 8 Steps (receiveData, transformData, reconcile, calcRecruit, calcMaintain, chargebackException, calcOverride, aggregate) - DataReceiver strategy + ManualReceiver, MappingEngine stub - CommissionCalculator (pct/tax via MoneyUtil), JobLauncherController DB V13~V15: - V13: 14 indexes (settle_master, ledgers, contract, chargeback, payment, raw, logs) - V14: create_monthly_partition() helper function - V15: v_agent_monthly_summary, v_org_settle_summary, v_chargeback_risk views Infra: - docker-compose: postgres + redis + api + batch + frontend - Multi-stage Dockerfile (gradle build → JRE) ga-frontend (skeleton): - Vite + React 18 + TypeScript + AntD 5 + AG Grid + React Query + Zustand - API request layer (axios + JWT), LoginPage, MainLayout (dynamic menu), Dashboard - nginx.conf for /api proxying
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
package com.ga.api.auth;
|
||||
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.core.vo.user.UserResp;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "인증")
|
||||
@RestController
|
||||
@RequestMapping("/api/auth")
|
||||
@RequiredArgsConstructor
|
||||
public class AuthController {
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
@PostMapping("/login")
|
||||
public ApiResponse<LoginResp> login(@Valid @RequestBody LoginReq req, HttpServletRequest http) {
|
||||
return ApiResponse.ok(authService.login(req, ipOf(http), http.getHeader("User-Agent")));
|
||||
}
|
||||
|
||||
@PostMapping("/refresh")
|
||||
public ApiResponse<LoginResp> refresh(@RequestBody Map<String, String> body) {
|
||||
return ApiResponse.ok(authService.refresh(body.get("refreshToken")));
|
||||
}
|
||||
|
||||
@GetMapping("/me")
|
||||
public ApiResponse<UserResp> me() {
|
||||
return ApiResponse.ok(authService.me());
|
||||
}
|
||||
|
||||
@PostMapping("/password")
|
||||
public ApiResponse<Void> changePassword(@RequestBody Map<String, String> body) {
|
||||
authService.changePassword(body.get("oldPassword"), body.get("newPassword"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/logout")
|
||||
public ApiResponse<Void> logout() {
|
||||
authService.logout();
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
private String ipOf(HttpServletRequest req) {
|
||||
String xf = req.getHeader("X-Forwarded-For");
|
||||
if (xf != null && !xf.isBlank()) return xf.split(",")[0].trim();
|
||||
return req.getRemoteAddr();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.ga.api.auth;
|
||||
|
||||
import com.ga.common.auth.JwtTokenProvider;
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.system.SystemConfigService;
|
||||
import com.ga.common.system.SystemLogMapper;
|
||||
import com.ga.common.util.SecurityUtil;
|
||||
import com.ga.core.mapper.user.UserMapper;
|
||||
import com.ga.core.vo.user.UserResp;
|
||||
import com.ga.core.vo.user.UserVO;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AuthService {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final JwtTokenProvider tokenProvider;
|
||||
private final SystemConfigService configService;
|
||||
private final SystemLogMapper systemLogMapper;
|
||||
|
||||
@Transactional
|
||||
public LoginResp login(LoginReq req, String ipAddress, String userAgent) {
|
||||
UserVO user = userMapper.selectByLoginId(req.getLoginId());
|
||||
int failLimit = configService.getInt("LOGIN_FAIL_LIMIT", 5);
|
||||
|
||||
if (user == null) {
|
||||
saveLoginLog(null, req.getLoginId(), "FAIL", "USER_NOT_FOUND", ipAddress, userAgent);
|
||||
throw new BizException(ErrorCode.LOGIN_FAIL);
|
||||
}
|
||||
if ("LOCKED".equals(user.getStatus())) {
|
||||
saveLoginLog(user.getUserId(), req.getLoginId(), "FAIL", "ACCOUNT_LOCKED", ipAddress, userAgent);
|
||||
throw new BizException(ErrorCode.ACCOUNT_LOCKED);
|
||||
}
|
||||
if ("RETIRED".equals(user.getStatus())) {
|
||||
throw new BizException(ErrorCode.ACCOUNT_RETIRED);
|
||||
}
|
||||
if (!passwordEncoder.matches(req.getPassword(), user.getPassword())) {
|
||||
userMapper.incrementFailCount(user.getUserId());
|
||||
int newFail = (user.getFailCount() == null ? 0 : user.getFailCount()) + 1;
|
||||
if (newFail >= failLimit) {
|
||||
userMapper.updateStatus(user.getUserId(), "LOCKED");
|
||||
}
|
||||
saveLoginLog(user.getUserId(), req.getLoginId(), "FAIL", "BAD_PASSWORD", ipAddress, userAgent);
|
||||
throw new BizException(ErrorCode.LOGIN_FAIL);
|
||||
}
|
||||
|
||||
// 로그인 성공
|
||||
userMapper.updateLastLogin(user.getUserId());
|
||||
List<String> roles = userMapper.selectRoleCodes(user.getUserId());
|
||||
String access = tokenProvider.createAccessToken(user.getUserId(), user.getLoginId(), roles);
|
||||
String refresh = tokenProvider.createRefreshToken(user.getUserId(), user.getLoginId());
|
||||
saveLoginLog(user.getUserId(), req.getLoginId(), "SUCCESS", null, ipAddress, userAgent);
|
||||
|
||||
return LoginResp.builder()
|
||||
.accessToken(access)
|
||||
.refreshToken(refresh)
|
||||
.accessTokenExpiresIn(tokenProvider.getAccessExpire())
|
||||
.userId(user.getUserId())
|
||||
.loginId(user.getLoginId())
|
||||
.userName(user.getUserName())
|
||||
.roles(roles)
|
||||
.build();
|
||||
}
|
||||
|
||||
public LoginResp refresh(String refreshToken) {
|
||||
Claims claims = tokenProvider.parse(refreshToken);
|
||||
if (!"REFRESH".equals(claims.get("type"))) {
|
||||
throw new BizException(ErrorCode.TOKEN_INVALID);
|
||||
}
|
||||
Long userId = claims.get("uid", Long.class);
|
||||
UserVO user = userMapper.selectById(userId);
|
||||
if (user == null || !"ACTIVE".equals(user.getStatus())) {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED);
|
||||
}
|
||||
List<String> roles = userMapper.selectRoleCodes(userId);
|
||||
String newAccess = tokenProvider.createAccessToken(userId, user.getLoginId(), roles);
|
||||
return LoginResp.builder()
|
||||
.accessToken(newAccess)
|
||||
.accessTokenExpiresIn(tokenProvider.getAccessExpire())
|
||||
.userId(userId)
|
||||
.loginId(user.getLoginId())
|
||||
.userName(user.getUserName())
|
||||
.roles(roles)
|
||||
.build();
|
||||
}
|
||||
|
||||
public UserResp me() {
|
||||
Long userId = SecurityUtil.getCurrentUserId();
|
||||
if (userId == null) throw new BizException(ErrorCode.UNAUTHORIZED);
|
||||
UserResp resp = userMapper.selectDetailById(userId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
resp.setRoleCodes(userMapper.selectRoleCodes(userId));
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void changePassword(String oldPassword, String newPassword) {
|
||||
Long userId = SecurityUtil.getCurrentUserId();
|
||||
if (userId == null) throw new BizException(ErrorCode.UNAUTHORIZED);
|
||||
UserVO user = userMapper.selectById(userId);
|
||||
if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
|
||||
throw new BizException(ErrorCode.LOGIN_FAIL, "기존 비밀번호가 일치하지 않습니다");
|
||||
}
|
||||
validatePasswordPolicy(newPassword);
|
||||
userMapper.updatePassword(userId, passwordEncoder.encode(newPassword));
|
||||
}
|
||||
|
||||
public void logout() {
|
||||
Long userId = SecurityUtil.getCurrentUserId();
|
||||
saveLoginLog(userId, SecurityUtil.getCurrentLoginId(), "LOGOUT", null, null, null);
|
||||
}
|
||||
|
||||
private void saveLoginLog(Long userId, String loginId, String type, String reason, String ip, String ua) {
|
||||
try {
|
||||
systemLogMapper.insertLoginLog(userId, loginId, type, reason, ip, ua);
|
||||
} catch (Exception e) {
|
||||
log.warn("Login log save failed: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePasswordPolicy(String password) {
|
||||
int min = configService.getInt("PASSWORD_MIN_LEN", 8);
|
||||
if (password == null || password.length() < min) {
|
||||
throw new BizException(ErrorCode.PASSWORD_POLICY,
|
||||
"비밀번호는 " + min + "자 이상이어야 합니다");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.ga.api.auth;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class LoginReq {
|
||||
@NotBlank(message = "아이디는 필수입니다")
|
||||
private String loginId;
|
||||
@NotBlank(message = "비밀번호는 필수입니다")
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ga.api.auth;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class LoginResp {
|
||||
private String accessToken;
|
||||
private String refreshToken;
|
||||
private long accessTokenExpiresIn; // ms
|
||||
private Long userId;
|
||||
private String loginId;
|
||||
private String userName;
|
||||
private List<String> roles;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.ga.api.controller.batch;
|
||||
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.core.mapper.settle.BatchJobLogMapper;
|
||||
import com.ga.core.vo.settle.BatchJobLogVO;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 배치 트리거 — 실제 배치 잡 실행은 ga-batch 모듈의 별도 Spring Boot 프로세스에서 수행.
|
||||
* ga-api 에서는 batch_job_log 만 조회/요청 등록.
|
||||
*
|
||||
* 운영 환경에서는 메시지 큐(Kafka, Redis Streams) 또는
|
||||
* Spring Batch JobLauncher REST API 로 ga-batch 프로세스를 호출하는 것을 권장.
|
||||
*/
|
||||
@Slf4j
|
||||
@Tag(name = "배치")
|
||||
@RestController
|
||||
@RequestMapping("/api/batch")
|
||||
@RequiredArgsConstructor
|
||||
public class BatchTriggerController {
|
||||
|
||||
private final BatchJobLogMapper jobLogMapper;
|
||||
|
||||
/** 정산 배치 시작 요청 (실제 실행은 ga-batch 프로세스가 폴링/큐) */
|
||||
@PostMapping("/settlement/run")
|
||||
@RequirePermission(menu = "BATCH_RUN", perm = "APPROVE")
|
||||
public ApiResponse<Long> runSettlement(@RequestBody Map<String, String> body) {
|
||||
String settleMonth = body.get("settleMonth");
|
||||
if (settleMonth == null || !settleMonth.matches("\\d{6}")) {
|
||||
throw new BizException(ErrorCode.INVALID_PARAMETER, "settleMonth (yyyyMM) 가 필요합니다");
|
||||
}
|
||||
if (jobLogMapper.isRunning("MONTHLY_SETTLEMENT") > 0) {
|
||||
throw new BizException(ErrorCode.BATCH_RUNNING);
|
||||
}
|
||||
BatchJobLogVO log = new BatchJobLogVO();
|
||||
log.setJobName("MONTHLY_SETTLEMENT");
|
||||
log.setSettleMonth(settleMonth);
|
||||
log.setStatus("REQUESTED");
|
||||
log.setTriggeredBy(com.ga.common.util.SecurityUtil.getCurrentUserId());
|
||||
jobLogMapper.insert(log);
|
||||
return ApiResponse.ok(log.getJobId());
|
||||
}
|
||||
|
||||
@GetMapping("/status")
|
||||
@RequirePermission(menu = "BATCH_RUN", perm = "READ")
|
||||
public ApiResponse<BatchJobLogVO> latest(@RequestParam(defaultValue = "MONTHLY_SETTLEMENT") String jobName) {
|
||||
return ApiResponse.ok(jobLogMapper.selectLatest(jobName));
|
||||
}
|
||||
|
||||
@GetMapping("/jobs")
|
||||
@RequirePermission(menu = "BATCH_RUN", perm = "READ")
|
||||
public ApiResponse<List<BatchJobLogVO>> list(@RequestParam(required = false) String jobName,
|
||||
@RequestParam(required = false) String settleMonth) {
|
||||
return ApiResponse.ok(jobLogMapper.selectList(jobName, settleMonth));
|
||||
}
|
||||
|
||||
@GetMapping("/jobs/{jobId}")
|
||||
@RequirePermission(menu = "BATCH_RUN", perm = "READ")
|
||||
public ApiResponse<BatchJobLogVO> detail(@PathVariable Long jobId) {
|
||||
return ApiResponse.ok(jobLogMapper.selectById(jobId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.ga.api.controller.ledger;
|
||||
|
||||
import com.ga.api.service.ledger.LedgerService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.excel.ExcelService;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.ledger.MaintainLedgerMapper;
|
||||
import com.ga.core.mapper.ledger.RecruitLedgerMapper;
|
||||
import com.ga.core.vo.ledger.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "원장 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/ledger")
|
||||
@RequiredArgsConstructor
|
||||
public class LedgerController {
|
||||
|
||||
private final LedgerService service;
|
||||
private final RecruitLedgerMapper recruitMapper;
|
||||
private final MaintainLedgerMapper maintainMapper;
|
||||
private final ExcelService excelService;
|
||||
|
||||
// ===== 모집 =====
|
||||
@GetMapping("/recruit")
|
||||
@RequirePermission(menu = "LEDGER_RECRUIT", perm = "READ")
|
||||
public ApiResponse<PageResponse<LedgerResp>> listRecruit(@ModelAttribute LedgerSearchParam param) {
|
||||
return ApiResponse.ok(service.listRecruit(param));
|
||||
}
|
||||
|
||||
@GetMapping("/recruit/{ledgerId}")
|
||||
@RequirePermission(menu = "LEDGER_RECRUIT", perm = "READ")
|
||||
public ApiResponse<LedgerResp> detailRecruit(@PathVariable Long ledgerId) {
|
||||
return ApiResponse.ok(service.detailRecruit(ledgerId));
|
||||
}
|
||||
|
||||
@GetMapping("/recruit/export")
|
||||
@RequirePermission(menu = "LEDGER_RECRUIT", perm = "EXPORT")
|
||||
public void exportRecruit(@ModelAttribute LedgerSearchParam param, HttpServletResponse res) {
|
||||
excelService.exportLargeExcel("모집수수료원장", LedgerExcelVO.class,
|
||||
() -> recruitMapper.selectCursorForExcel(param), res);
|
||||
}
|
||||
|
||||
// ===== 유지 =====
|
||||
@GetMapping("/maintain")
|
||||
@RequirePermission(menu = "LEDGER_MAINTAIN", perm = "READ")
|
||||
public ApiResponse<PageResponse<LedgerResp>> listMaintain(@ModelAttribute LedgerSearchParam param) {
|
||||
return ApiResponse.ok(service.listMaintain(param));
|
||||
}
|
||||
|
||||
@GetMapping("/maintain/{ledgerId}")
|
||||
@RequirePermission(menu = "LEDGER_MAINTAIN", perm = "READ")
|
||||
public ApiResponse<LedgerResp> detailMaintain(@PathVariable Long ledgerId) {
|
||||
return ApiResponse.ok(service.detailMaintain(ledgerId));
|
||||
}
|
||||
|
||||
@GetMapping("/maintain/export")
|
||||
@RequirePermission(menu = "LEDGER_MAINTAIN", perm = "EXPORT")
|
||||
public void exportMaintain(@ModelAttribute LedgerSearchParam param, HttpServletResponse res) {
|
||||
excelService.exportLargeExcel("유지수수료원장", LedgerExcelVO.class,
|
||||
() -> maintainMapper.selectCursorForExcel(param), res);
|
||||
}
|
||||
|
||||
// ===== 예외 =====
|
||||
@GetMapping("/exception")
|
||||
@RequirePermission(menu = "LEDGER_EXCEPTION", perm = "READ")
|
||||
public ApiResponse<PageResponse<ExceptionLedgerResp>> listException(@ModelAttribute LedgerSearchParam param) {
|
||||
return ApiResponse.ok(service.listException(param));
|
||||
}
|
||||
|
||||
@GetMapping("/exception/{ledgerId}")
|
||||
@RequirePermission(menu = "LEDGER_EXCEPTION", perm = "READ")
|
||||
public ApiResponse<ExceptionLedgerResp> detailException(@PathVariable Long ledgerId) {
|
||||
return ApiResponse.ok(service.detailException(ledgerId));
|
||||
}
|
||||
|
||||
@PostMapping("/exception")
|
||||
@RequirePermission(menu = "LEDGER_EXCEPTION", perm = "CREATE")
|
||||
@DataChangeLog(menu = "LEDGER_EXCEPTION", table = "exception_ledger")
|
||||
public ApiResponse<Long> createException(@Valid @RequestBody ExceptionLedgerSaveReq req) {
|
||||
return ApiResponse.ok(service.createException(req));
|
||||
}
|
||||
|
||||
@PutMapping("/exception/{ledgerId}/approve")
|
||||
@RequirePermission(menu = "LEDGER_EXCEPTION", perm = "APPROVE")
|
||||
@DataChangeLog(menu = "LEDGER_EXCEPTION", table = "exception_ledger")
|
||||
public ApiResponse<Void> approveException(@PathVariable Long ledgerId,
|
||||
@RequestBody Map<String, String> body) {
|
||||
service.approveException(ledgerId, body.get("status"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.ga.api.controller.org;
|
||||
|
||||
import com.ga.api.service.org.AgentService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.excel.ExcelService;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.org.AgentMapper;
|
||||
import com.ga.core.vo.org.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
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/agents")
|
||||
@RequiredArgsConstructor
|
||||
public class AgentController {
|
||||
|
||||
private final AgentService agentService;
|
||||
private final AgentMapper agentMapper;
|
||||
private final ExcelService excelService;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "ORG_AGENT", perm = "READ")
|
||||
public ApiResponse<PageResponse<AgentResp>> list(@ModelAttribute AgentSearchParam param) {
|
||||
return ApiResponse.ok(agentService.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{agentId}")
|
||||
@RequirePermission(menu = "ORG_AGENT", perm = "READ")
|
||||
public ApiResponse<AgentResp> detail(@PathVariable Long agentId) {
|
||||
return ApiResponse.ok(agentService.detail(agentId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "ORG_AGENT", perm = "CREATE")
|
||||
@DataChangeLog(menu = "ORG_AGENT", table = "agent")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody AgentSaveReq req) {
|
||||
return ApiResponse.ok(agentService.create(req));
|
||||
}
|
||||
|
||||
@PutMapping("/{agentId}")
|
||||
@RequirePermission(menu = "ORG_AGENT", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "ORG_AGENT", table = "agent")
|
||||
public ApiResponse<Void> update(@PathVariable Long agentId, @Valid @RequestBody AgentSaveReq req) {
|
||||
agentService.update(agentId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PutMapping("/{agentId}/status")
|
||||
@RequirePermission(menu = "ORG_AGENT", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "ORG_AGENT", table = "agent")
|
||||
public ApiResponse<Void> changeStatus(@PathVariable Long agentId, @RequestBody Map<String, String> body) {
|
||||
agentService.changeStatus(agentId, body.get("status"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/{agentId}/history")
|
||||
@RequirePermission(menu = "ORG_AGENT", perm = "READ")
|
||||
public ApiResponse<List<AgentOrgHistoryVO>> history(@PathVariable Long agentId) {
|
||||
return ApiResponse.ok(agentService.history(agentId));
|
||||
}
|
||||
|
||||
@GetMapping("/export")
|
||||
@RequirePermission(menu = "ORG_AGENT", perm = "EXPORT")
|
||||
public void export(@ModelAttribute AgentSearchParam param, HttpServletResponse response) {
|
||||
excelService.exportLargeExcel("설계사목록", AgentExcelVO.class,
|
||||
() -> agentMapper.selectCursorForExcel(param), response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.ga.api.controller.org;
|
||||
|
||||
import com.ga.api.service.org.OrganizationService;
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.core.vo.org.OrganizationResp;
|
||||
import com.ga.core.vo.org.OrganizationVO;
|
||||
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/orgs")
|
||||
@RequiredArgsConstructor
|
||||
public class OrganizationController {
|
||||
|
||||
private final OrganizationService service;
|
||||
|
||||
@GetMapping("/tree")
|
||||
@RequirePermission(menu = "ORG_TREE", perm = "READ")
|
||||
public ApiResponse<List<OrganizationResp>> tree() {
|
||||
return ApiResponse.ok(service.getTree());
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "ORG_TREE", perm = "READ")
|
||||
public ApiResponse<List<OrganizationResp>> list(@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) String orgType,
|
||||
@RequestParam(required = false) String isActive) {
|
||||
return ApiResponse.ok(service.list(keyword, orgType, isActive));
|
||||
}
|
||||
|
||||
@GetMapping("/{orgId}")
|
||||
@RequirePermission(menu = "ORG_TREE", perm = "READ")
|
||||
public ApiResponse<OrganizationVO> detail(@PathVariable Long orgId) {
|
||||
return ApiResponse.ok(service.get(orgId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "ORG_TREE", perm = "CREATE")
|
||||
@DataChangeLog(menu = "ORG_TREE", table = "organization")
|
||||
public ApiResponse<Long> create(@RequestBody OrganizationVO vo) {
|
||||
return ApiResponse.ok(service.create(vo));
|
||||
}
|
||||
|
||||
@PutMapping("/{orgId}")
|
||||
@RequirePermission(menu = "ORG_TREE", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "ORG_TREE", table = "organization")
|
||||
public ApiResponse<Void> update(@PathVariable Long orgId, @RequestBody OrganizationVO vo) {
|
||||
service.update(orgId, vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{orgId}")
|
||||
@RequirePermission(menu = "ORG_TREE", perm = "DELETE")
|
||||
@DataChangeLog(menu = "ORG_TREE", table = "organization")
|
||||
public ApiResponse<Void> delete(@PathVariable Long orgId) {
|
||||
service.delete(orgId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.ga.api.controller.product;
|
||||
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.core.mapper.product.InsuranceCompanyMapper;
|
||||
import com.ga.core.vo.product.InsuranceCompanyVO;
|
||||
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/companies")
|
||||
@RequiredArgsConstructor
|
||||
public class CompanyController {
|
||||
|
||||
private final InsuranceCompanyMapper mapper;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "COMPANY", perm = "READ")
|
||||
public ApiResponse<List<InsuranceCompanyVO>> list(@RequestParam(required = false, defaultValue = "false") boolean activeOnly) {
|
||||
return ApiResponse.ok(activeOnly ? mapper.selectActive() : mapper.selectAll());
|
||||
}
|
||||
|
||||
@GetMapping("/{companyId}")
|
||||
@RequirePermission(menu = "COMPANY", perm = "READ")
|
||||
public ApiResponse<InsuranceCompanyVO> detail(@PathVariable Long companyId) {
|
||||
return ApiResponse.ok(mapper.selectById(companyId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "COMPANY", perm = "CREATE")
|
||||
@DataChangeLog(menu = "COMPANY", table = "insurance_company")
|
||||
public ApiResponse<Long> create(@RequestBody InsuranceCompanyVO vo) {
|
||||
mapper.insert(vo);
|
||||
return ApiResponse.ok(vo.getCompanyId());
|
||||
}
|
||||
|
||||
@PutMapping("/{companyId}")
|
||||
@RequirePermission(menu = "COMPANY", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "COMPANY", table = "insurance_company")
|
||||
public ApiResponse<Void> update(@PathVariable Long companyId, @RequestBody InsuranceCompanyVO vo) {
|
||||
vo.setCompanyId(companyId);
|
||||
mapper.update(vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.ga.api.controller.product;
|
||||
|
||||
import com.ga.api.service.product.ContractService;
|
||||
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.product.ContractResp;
|
||||
import com.ga.core.vo.product.ContractSaveReq;
|
||||
import com.ga.core.vo.product.ContractSearchParam;
|
||||
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/contracts")
|
||||
@RequiredArgsConstructor
|
||||
public class ContractController {
|
||||
|
||||
private final ContractService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "CONTRACT_LIST", perm = "READ")
|
||||
public ApiResponse<PageResponse<ContractResp>> list(@ModelAttribute ContractSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{contractId}")
|
||||
@RequirePermission(menu = "CONTRACT_LIST", perm = "READ")
|
||||
public ApiResponse<ContractResp> detail(@PathVariable Long contractId) {
|
||||
return ApiResponse.ok(service.detail(contractId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "CONTRACT_LIST", perm = "CREATE")
|
||||
@DataChangeLog(menu = "CONTRACT_LIST", table = "contract")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody ContractSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PutMapping("/{contractId}")
|
||||
@RequirePermission(menu = "CONTRACT_LIST", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "CONTRACT_LIST", table = "contract")
|
||||
public ApiResponse<Void> update(@PathVariable Long contractId, @Valid @RequestBody ContractSaveReq req) {
|
||||
service.update(contractId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PutMapping("/{contractId}/status")
|
||||
@RequirePermission(menu = "CONTRACT_LIST", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "CONTRACT_LIST", table = "contract")
|
||||
public ApiResponse<Void> changeStatus(@PathVariable Long contractId, @RequestBody Map<String, String> body) {
|
||||
service.changeStatus(contractId, body.get("status"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.ga.api.controller.product;
|
||||
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.core.mapper.product.ProductMapper;
|
||||
import com.ga.core.vo.product.ProductResp;
|
||||
import com.ga.core.vo.product.ProductVO;
|
||||
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/products")
|
||||
@RequiredArgsConstructor
|
||||
public class ProductController {
|
||||
|
||||
private final ProductMapper mapper;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "PRODUCT", perm = "READ")
|
||||
public ApiResponse<List<ProductResp>> list(@RequestParam(required = false) Long companyId,
|
||||
@RequestParam(required = false) String insuranceType,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) String isActive) {
|
||||
return ApiResponse.ok(mapper.selectList(companyId, insuranceType, keyword, isActive));
|
||||
}
|
||||
|
||||
@GetMapping("/{productId}")
|
||||
@RequirePermission(menu = "PRODUCT", perm = "READ")
|
||||
public ApiResponse<ProductResp> detail(@PathVariable Long productId) {
|
||||
ProductResp r = mapper.selectDetailById(productId);
|
||||
if (r == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return ApiResponse.ok(r);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "PRODUCT", perm = "CREATE")
|
||||
@DataChangeLog(menu = "PRODUCT", table = "product")
|
||||
public ApiResponse<Long> create(@RequestBody ProductVO vo) {
|
||||
if (mapper.existsByCode(vo.getCompanyId(), vo.getProductCode()) > 0) {
|
||||
throw new BizException(ErrorCode.DUPLICATE_DATA);
|
||||
}
|
||||
mapper.insert(vo);
|
||||
return ApiResponse.ok(vo.getProductId());
|
||||
}
|
||||
|
||||
@PutMapping("/{productId}")
|
||||
@RequirePermission(menu = "PRODUCT", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "PRODUCT", table = "product")
|
||||
public ApiResponse<Void> update(@PathVariable Long productId, @RequestBody ProductVO vo) {
|
||||
vo.setProductId(productId);
|
||||
mapper.update(vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{productId}")
|
||||
@RequirePermission(menu = "PRODUCT", perm = "DELETE")
|
||||
public ApiResponse<Void> delete(@PathVariable Long productId) {
|
||||
mapper.deleteById(productId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.ga.api.controller.receive;
|
||||
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.core.mapper.receive.ReceiveMapper;
|
||||
import com.ga.core.vo.receive.*;
|
||||
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/receive")
|
||||
@RequiredArgsConstructor
|
||||
public class ReceiveController {
|
||||
|
||||
private final ReceiveMapper mapper;
|
||||
|
||||
// 보험사 프로파일
|
||||
@GetMapping("/profiles")
|
||||
@RequirePermission(menu = "RECEIVE_MAPPING", perm = "READ")
|
||||
public ApiResponse<List<CompanyProfileVO>> profiles() {
|
||||
return ApiResponse.ok(mapper.selectAllProfiles());
|
||||
}
|
||||
|
||||
@PutMapping("/profiles/{companyCode}")
|
||||
@RequirePermission(menu = "RECEIVE_MAPPING", perm = "UPDATE")
|
||||
public ApiResponse<Void> updateProfile(@PathVariable String companyCode, @RequestBody CompanyProfileVO vo) {
|
||||
vo.setCompanyCode(companyCode);
|
||||
if (mapper.selectProfile(companyCode) == null) mapper.insertProfile(vo);
|
||||
else mapper.updateProfile(vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
// 필드 매핑
|
||||
@GetMapping("/mapping/{companyCode}/fields")
|
||||
@RequirePermission(menu = "RECEIVE_MAPPING", perm = "READ")
|
||||
public ApiResponse<List<CompanyFieldMappingVO>> fields(@PathVariable String companyCode,
|
||||
@RequestParam(required = false) String targetTable) {
|
||||
return ApiResponse.ok(mapper.selectFieldMappings(companyCode, targetTable));
|
||||
}
|
||||
|
||||
@PostMapping("/mapping/{companyCode}/fields")
|
||||
@RequirePermission(menu = "RECEIVE_MAPPING", perm = "CREATE")
|
||||
public ApiResponse<Long> createField(@PathVariable String companyCode, @RequestBody CompanyFieldMappingVO vo) {
|
||||
vo.setCompanyCode(companyCode);
|
||||
mapper.insertFieldMapping(vo);
|
||||
return ApiResponse.ok(vo.getMappingId());
|
||||
}
|
||||
|
||||
@PutMapping("/mapping/fields/{mappingId}")
|
||||
@RequirePermission(menu = "RECEIVE_MAPPING", perm = "UPDATE")
|
||||
public ApiResponse<Void> updateField(@PathVariable Long mappingId, @RequestBody CompanyFieldMappingVO vo) {
|
||||
vo.setMappingId(mappingId);
|
||||
mapper.updateFieldMapping(vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/mapping/fields/{mappingId}")
|
||||
@RequirePermission(menu = "RECEIVE_MAPPING", perm = "DELETE")
|
||||
public ApiResponse<Void> deleteField(@PathVariable Long mappingId) {
|
||||
mapper.deleteFieldMapping(mappingId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
// 코드 매핑
|
||||
@GetMapping("/mapping/{companyCode}/codes")
|
||||
@RequirePermission(menu = "RECEIVE_MAPPING", perm = "READ")
|
||||
public ApiResponse<List<CodeMappingVO>> codes(@PathVariable String companyCode,
|
||||
@RequestParam(required = false) String codeType) {
|
||||
return ApiResponse.ok(mapper.selectCodeMappings(companyCode, codeType));
|
||||
}
|
||||
|
||||
@PostMapping("/mapping/{companyCode}/codes")
|
||||
@RequirePermission(menu = "RECEIVE_MAPPING", perm = "CREATE")
|
||||
public ApiResponse<Long> createCode(@PathVariable String companyCode, @RequestBody CodeMappingVO vo) {
|
||||
vo.setCompanyCode(companyCode);
|
||||
mapper.insertCodeMapping(vo);
|
||||
return ApiResponse.ok(vo.getCodeId());
|
||||
}
|
||||
|
||||
// 원본 데이터 + 에러
|
||||
@GetMapping("/raw")
|
||||
@RequirePermission(menu = "RECEIVE_DATA", perm = "READ")
|
||||
public ApiResponse<List<RawCommissionDataVO>> rawList(@RequestParam(required = false) String companyCode,
|
||||
@RequestParam(required = false) String settleMonth,
|
||||
@RequestParam(required = false) String parseStatus) {
|
||||
return ApiResponse.ok(mapper.selectRawList(companyCode, settleMonth, parseStatus));
|
||||
}
|
||||
|
||||
@GetMapping("/errors")
|
||||
@RequirePermission(menu = "RECEIVE_DATA", perm = "READ")
|
||||
public ApiResponse<List<ParseErrorLogVO>> errors(@RequestParam(required = false) String companyCode,
|
||||
@RequestParam(required = false) String resolveStatus) {
|
||||
return ApiResponse.ok(mapper.selectErrors(companyCode, resolveStatus));
|
||||
}
|
||||
|
||||
@PutMapping("/errors/{errorId}/resolve")
|
||||
@RequirePermission(menu = "RECEIVE_DATA", perm = "UPDATE")
|
||||
public ApiResponse<Void> resolveError(@PathVariable Long errorId, @RequestBody Map<String, String> body) {
|
||||
mapper.resolveError(errorId,
|
||||
body.getOrDefault("status", "RESOLVED"),
|
||||
body.get("note"),
|
||||
com.ga.common.util.SecurityUtil.getCurrentUserId());
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package com.ga.api.controller.rule;
|
||||
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.core.mapper.rule.RuleMapper;
|
||||
import com.ga.core.vo.rule.*;
|
||||
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/rules")
|
||||
@RequiredArgsConstructor
|
||||
public class RuleController {
|
||||
|
||||
private final RuleMapper mapper;
|
||||
|
||||
// ========== commission_rate ==========
|
||||
@GetMapping("/commission-rates")
|
||||
@RequirePermission(menu = "RULE_COMMISSION", perm = "READ")
|
||||
public ApiResponse<List<CommissionRateVO>> listCommissionRates(@RequestParam(required = false) Long productId,
|
||||
@RequestParam(required = false) Integer year) {
|
||||
return ApiResponse.ok(mapper.selectCommissionRates(productId, year));
|
||||
}
|
||||
|
||||
@PostMapping("/commission-rates")
|
||||
@RequirePermission(menu = "RULE_COMMISSION", perm = "CREATE")
|
||||
@DataChangeLog(menu = "RULE_COMMISSION", table = "commission_rate")
|
||||
public ApiResponse<Long> createCommissionRate(@RequestBody CommissionRateVO vo) {
|
||||
mapper.insertCommissionRate(vo);
|
||||
return ApiResponse.ok(vo.getRateId());
|
||||
}
|
||||
|
||||
@PutMapping("/commission-rates/{rateId}")
|
||||
@RequirePermission(menu = "RULE_COMMISSION", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "RULE_COMMISSION", table = "commission_rate")
|
||||
public ApiResponse<Void> updateCommissionRate(@PathVariable Long rateId, @RequestBody CommissionRateVO vo) {
|
||||
vo.setRateId(rateId);
|
||||
mapper.updateCommissionRate(vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/commission-rates/{rateId}")
|
||||
@RequirePermission(menu = "RULE_COMMISSION", perm = "DELETE")
|
||||
public ApiResponse<Void> deleteCommissionRate(@PathVariable Long rateId) {
|
||||
mapper.deleteCommissionRate(rateId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
// ========== payout_rule ==========
|
||||
@GetMapping("/payout")
|
||||
@RequirePermission(menu = "RULE_PAYOUT", perm = "READ")
|
||||
public ApiResponse<List<PayoutRuleVO>> listPayoutRules(@RequestParam(required = false) Long gradeId,
|
||||
@RequestParam(required = false) String insuranceType) {
|
||||
return ApiResponse.ok(mapper.selectPayoutRules(gradeId, insuranceType));
|
||||
}
|
||||
|
||||
@PostMapping("/payout")
|
||||
@RequirePermission(menu = "RULE_PAYOUT", perm = "CREATE")
|
||||
@DataChangeLog(menu = "RULE_PAYOUT", table = "payout_rule")
|
||||
public ApiResponse<Long> createPayoutRule(@RequestBody PayoutRuleVO vo) {
|
||||
mapper.insertPayoutRule(vo);
|
||||
return ApiResponse.ok(vo.getRuleId());
|
||||
}
|
||||
|
||||
@PutMapping("/payout/{ruleId}")
|
||||
@RequirePermission(menu = "RULE_PAYOUT", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "RULE_PAYOUT", table = "payout_rule")
|
||||
public ApiResponse<Void> updatePayoutRule(@PathVariable Long ruleId, @RequestBody PayoutRuleVO vo) {
|
||||
vo.setRuleId(ruleId);
|
||||
mapper.updatePayoutRule(vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/payout/{ruleId}")
|
||||
@RequirePermission(menu = "RULE_PAYOUT", perm = "DELETE")
|
||||
public ApiResponse<Void> deletePayoutRule(@PathVariable Long ruleId) {
|
||||
mapper.deletePayoutRule(ruleId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
// ========== override_rule ==========
|
||||
@GetMapping("/override")
|
||||
@RequirePermission(menu = "RULE_OVERRIDE", perm = "READ")
|
||||
public ApiResponse<List<OverrideRuleVO>> listOverrideRules() {
|
||||
return ApiResponse.ok(mapper.selectOverrideRules());
|
||||
}
|
||||
|
||||
@PostMapping("/override")
|
||||
@RequirePermission(menu = "RULE_OVERRIDE", perm = "CREATE")
|
||||
public ApiResponse<Long> createOverrideRule(@RequestBody OverrideRuleVO vo) {
|
||||
mapper.insertOverrideRule(vo);
|
||||
return ApiResponse.ok(vo.getOverrideId());
|
||||
}
|
||||
|
||||
@PutMapping("/override/{overrideId}")
|
||||
@RequirePermission(menu = "RULE_OVERRIDE", perm = "UPDATE")
|
||||
public ApiResponse<Void> updateOverrideRule(@PathVariable Long overrideId, @RequestBody OverrideRuleVO vo) {
|
||||
vo.setOverrideId(overrideId);
|
||||
mapper.updateOverrideRule(vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/override/{overrideId}")
|
||||
@RequirePermission(menu = "RULE_OVERRIDE", perm = "DELETE")
|
||||
public ApiResponse<Void> deleteOverrideRule(@PathVariable Long overrideId) {
|
||||
mapper.deleteOverrideRule(overrideId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
// ========== chargeback_rule ==========
|
||||
@GetMapping("/chargeback")
|
||||
@RequirePermission(menu = "RULE_CHARGEBACK", perm = "READ")
|
||||
public ApiResponse<List<ChargebackRuleVO>> listChargebackRules(@RequestParam(required = false) String companyCode) {
|
||||
return ApiResponse.ok(mapper.selectChargebackRules(companyCode));
|
||||
}
|
||||
|
||||
@PostMapping("/chargeback")
|
||||
@RequirePermission(menu = "RULE_CHARGEBACK", perm = "CREATE")
|
||||
public ApiResponse<Long> createChargebackRule(@RequestBody ChargebackRuleVO vo) {
|
||||
mapper.insertChargebackRule(vo);
|
||||
return ApiResponse.ok(vo.getCbRuleId());
|
||||
}
|
||||
|
||||
@PutMapping("/chargeback/{cbRuleId}")
|
||||
@RequirePermission(menu = "RULE_CHARGEBACK", perm = "UPDATE")
|
||||
public ApiResponse<Void> updateChargebackRule(@PathVariable Long cbRuleId, @RequestBody ChargebackRuleVO vo) {
|
||||
vo.setCbRuleId(cbRuleId);
|
||||
mapper.updateChargebackRule(vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/chargeback/{cbRuleId}")
|
||||
@RequirePermission(menu = "RULE_CHARGEBACK", perm = "DELETE")
|
||||
public ApiResponse<Void> deleteChargebackRule(@PathVariable Long cbRuleId) {
|
||||
mapper.deleteChargebackRule(cbRuleId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
// ========== exception_type_code ==========
|
||||
@GetMapping("/exception-codes")
|
||||
@RequirePermission(menu = "RULE_EXCEPTION", perm = "READ")
|
||||
public ApiResponse<List<ExceptionTypeCodeVO>> listExceptionCodes() {
|
||||
return ApiResponse.ok(mapper.selectExceptionCodes());
|
||||
}
|
||||
|
||||
@PostMapping("/exception-codes")
|
||||
@RequirePermission(menu = "RULE_EXCEPTION", perm = "CREATE")
|
||||
public ApiResponse<Void> createExceptionCode(@RequestBody ExceptionTypeCodeVO vo) {
|
||||
mapper.insertExceptionCode(vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PutMapping("/exception-codes/{exceptionCode}")
|
||||
@RequirePermission(menu = "RULE_EXCEPTION", perm = "UPDATE")
|
||||
public ApiResponse<Void> updateExceptionCode(@PathVariable String exceptionCode,
|
||||
@RequestBody ExceptionTypeCodeVO vo) {
|
||||
vo.setExceptionCode(exceptionCode);
|
||||
mapper.updateExceptionCode(vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.ga.api.controller.settle;
|
||||
|
||||
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.mapper.settle.PaymentMapper;
|
||||
import com.ga.core.vo.settle.PaymentResp;
|
||||
import com.ga.core.vo.settle.SettleSearchParam;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "지급 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/payments")
|
||||
@RequiredArgsConstructor
|
||||
public class PaymentController {
|
||||
|
||||
private final PaymentMapper mapper;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "PAYMENT", perm = "READ")
|
||||
public ApiResponse<PageResponse<PaymentResp>> list(@ModelAttribute SettleSearchParam param) {
|
||||
param.startPage();
|
||||
return ApiResponse.ok(PageResponse.of(mapper.selectList(param)));
|
||||
}
|
||||
|
||||
@PutMapping("/{paymentId}/status")
|
||||
@RequirePermission(menu = "PAYMENT", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "PAYMENT", table = "payment")
|
||||
public ApiResponse<Void> updateStatus(@PathVariable Long paymentId, @RequestBody Map<String, String> body) {
|
||||
mapper.updateStatus(paymentId, body.get("status"), body.get("failReason"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.ga.api.controller.settle;
|
||||
|
||||
import com.ga.api.service.settle.SettleService;
|
||||
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.SettleMasterResp;
|
||||
import com.ga.core.vo.settle.SettleSearchParam;
|
||||
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/settle")
|
||||
@RequiredArgsConstructor
|
||||
public class SettleController {
|
||||
|
||||
private final SettleService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "SETTLE_LIST", perm = "READ")
|
||||
public ApiResponse<PageResponse<SettleMasterResp>> list(@ModelAttribute SettleSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{agentId}/months/{settleMonth}")
|
||||
@RequirePermission(menu = "SETTLE_LIST", perm = "READ")
|
||||
public ApiResponse<SettleMasterResp> detail(@PathVariable Long agentId,
|
||||
@PathVariable String settleMonth) {
|
||||
return ApiResponse.ok(service.detail(agentId, settleMonth));
|
||||
}
|
||||
|
||||
@GetMapping("/summary")
|
||||
@RequirePermission(menu = "SETTLE_LIST", perm = "READ")
|
||||
public ApiResponse<Map<String, Object>> summary(@RequestParam String settleMonth) {
|
||||
return ApiResponse.ok(service.summary(settleMonth));
|
||||
}
|
||||
|
||||
@GetMapping("/org-summary")
|
||||
@RequirePermission(menu = "SETTLE_LIST", perm = "READ")
|
||||
public ApiResponse<List<Map<String, Object>>> orgSummary(@RequestParam String settleMonth) {
|
||||
return ApiResponse.ok(service.orgSummary(settleMonth));
|
||||
}
|
||||
|
||||
@PutMapping("/{settleId}/confirm")
|
||||
@RequirePermission(menu = "SETTLE_LIST", perm = "APPROVE")
|
||||
@DataChangeLog(menu = "SETTLE_LIST", table = "settle_master")
|
||||
public ApiResponse<Void> confirm(@PathVariable Long settleId) {
|
||||
service.confirm(settleId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PutMapping("/{settleId}/hold")
|
||||
@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"));
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PutMapping("/{settleId}/release")
|
||||
@RequirePermission(menu = "SETTLE_LIST", perm = "APPROVE")
|
||||
@DataChangeLog(menu = "SETTLE_LIST", table = "settle_master")
|
||||
public ApiResponse<Void> release(@PathVariable Long settleId) {
|
||||
service.release(settleId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.ga.api.controller.system;
|
||||
|
||||
import com.ga.common.annotation.DataChangeLog;
|
||||
import com.ga.common.annotation.RequirePermission;
|
||||
import com.ga.common.model.ApiResponse;
|
||||
import com.ga.core.mapper.user.RoleMapper;
|
||||
import com.ga.core.vo.user.RoleVO;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "역할 관리")
|
||||
@RestController
|
||||
@RequestMapping("/api/system/roles")
|
||||
@RequiredArgsConstructor
|
||||
public class RoleController {
|
||||
|
||||
private final RoleMapper mapper;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "SYSTEM_ROLE", perm = "READ")
|
||||
public ApiResponse<List<RoleVO>> list() {
|
||||
return ApiResponse.ok(mapper.selectAll());
|
||||
}
|
||||
|
||||
@GetMapping("/{roleId}")
|
||||
@RequirePermission(menu = "SYSTEM_ROLE", perm = "READ")
|
||||
public ApiResponse<RoleVO> detail(@PathVariable Long roleId) {
|
||||
return ApiResponse.ok(mapper.selectById(roleId));
|
||||
}
|
||||
|
||||
@GetMapping("/{roleId}/permissions")
|
||||
@RequirePermission(menu = "SYSTEM_ROLE", perm = "READ")
|
||||
public ApiResponse<List<Map<String, Object>>> permissions(@PathVariable Long roleId) {
|
||||
return ApiResponse.ok(mapper.selectRolePermissions(roleId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "SYSTEM_ROLE", perm = "CREATE")
|
||||
@DataChangeLog(menu = "SYSTEM_ROLE", table = "role")
|
||||
public ApiResponse<Long> create(@RequestBody RoleVO vo) {
|
||||
mapper.insert(vo);
|
||||
return ApiResponse.ok(vo.getRoleId());
|
||||
}
|
||||
|
||||
@PutMapping("/{roleId}")
|
||||
@RequirePermission(menu = "SYSTEM_ROLE", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "SYSTEM_ROLE", table = "role")
|
||||
public ApiResponse<Void> update(@PathVariable Long roleId, @RequestBody RoleVO vo) {
|
||||
vo.setRoleId(roleId);
|
||||
mapper.update(vo);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{roleId}")
|
||||
@RequirePermission(menu = "SYSTEM_ROLE", perm = "DELETE")
|
||||
public ApiResponse<Void> delete(@PathVariable Long roleId) {
|
||||
mapper.deleteById(roleId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
/** 권한 매트릭스 일괄 저장 */
|
||||
@PutMapping("/{roleId}/permissions")
|
||||
@RequirePermission(menu = "SYSTEM_ROLE", perm = "UPDATE")
|
||||
@Transactional
|
||||
public ApiResponse<Void> savePermissions(@PathVariable Long roleId,
|
||||
@RequestBody List<Map<String, Object>> permissions) {
|
||||
mapper.deleteRolePermissions(roleId);
|
||||
for (Map<String, Object> p : permissions) {
|
||||
Long menuId = ((Number) p.get("menuId")).longValue();
|
||||
String permCode = (String) p.get("permCode");
|
||||
String isGranted = (String) p.getOrDefault("isGranted", "Y");
|
||||
mapper.insertRolePermission(roleId, menuId, permCode, isGranted);
|
||||
}
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.ga.api.controller.system;
|
||||
|
||||
import com.ga.api.service.system.UserService;
|
||||
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.user.UserResp;
|
||||
import com.ga.core.vo.user.UserSaveReq;
|
||||
import com.ga.core.vo.user.UserSearchParam;
|
||||
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/system/users")
|
||||
@RequiredArgsConstructor
|
||||
public class UserController {
|
||||
|
||||
private final UserService service;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(menu = "SYSTEM_USER", perm = "READ")
|
||||
public ApiResponse<PageResponse<UserResp>> list(@ModelAttribute UserSearchParam param) {
|
||||
return ApiResponse.ok(service.list(param));
|
||||
}
|
||||
|
||||
@GetMapping("/{userId}")
|
||||
@RequirePermission(menu = "SYSTEM_USER", perm = "READ")
|
||||
public ApiResponse<UserResp> detail(@PathVariable Long userId) {
|
||||
return ApiResponse.ok(service.detail(userId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@RequirePermission(menu = "SYSTEM_USER", perm = "CREATE")
|
||||
@DataChangeLog(menu = "SYSTEM_USER", table = "users")
|
||||
public ApiResponse<Long> create(@Valid @RequestBody UserSaveReq req) {
|
||||
return ApiResponse.ok(service.create(req));
|
||||
}
|
||||
|
||||
@PutMapping("/{userId}")
|
||||
@RequirePermission(menu = "SYSTEM_USER", perm = "UPDATE")
|
||||
@DataChangeLog(menu = "SYSTEM_USER", table = "users")
|
||||
public ApiResponse<Void> update(@PathVariable Long userId, @Valid @RequestBody UserSaveReq req) {
|
||||
service.update(userId, req);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PutMapping("/{userId}/reset-password")
|
||||
@RequirePermission(menu = "SYSTEM_USER", perm = "UPDATE")
|
||||
public ApiResponse<Void> resetPassword(@PathVariable Long userId) {
|
||||
service.resetPassword(userId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
|
||||
@PutMapping("/{userId}/unlock")
|
||||
@RequirePermission(menu = "SYSTEM_USER", perm = "UPDATE")
|
||||
public ApiResponse<Void> unlock(@PathVariable Long userId) {
|
||||
service.unlock(userId);
|
||||
return ApiResponse.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.ga.api.service.ledger;
|
||||
|
||||
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.ledger.ExceptionLedgerMapper;
|
||||
import com.ga.core.mapper.ledger.MaintainLedgerMapper;
|
||||
import com.ga.core.mapper.ledger.RecruitLedgerMapper;
|
||||
import com.ga.core.vo.ledger.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class LedgerService {
|
||||
|
||||
private final RecruitLedgerMapper recruitMapper;
|
||||
private final MaintainLedgerMapper maintainMapper;
|
||||
private final ExceptionLedgerMapper exceptionMapper;
|
||||
|
||||
public PageResponse<LedgerResp> listRecruit(LedgerSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(recruitMapper.selectList(param));
|
||||
}
|
||||
|
||||
public PageResponse<LedgerResp> listMaintain(LedgerSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(maintainMapper.selectList(param));
|
||||
}
|
||||
|
||||
public PageResponse<ExceptionLedgerResp> listException(LedgerSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(exceptionMapper.selectList(param));
|
||||
}
|
||||
|
||||
public LedgerResp detailRecruit(Long ledgerId) {
|
||||
LedgerResp r = recruitMapper.selectDetailById(ledgerId);
|
||||
if (r == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return r;
|
||||
}
|
||||
|
||||
public LedgerResp detailMaintain(Long ledgerId) {
|
||||
LedgerResp r = maintainMapper.selectDetailById(ledgerId);
|
||||
if (r == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return r;
|
||||
}
|
||||
|
||||
public ExceptionLedgerResp detailException(Long ledgerId) {
|
||||
ExceptionLedgerResp r = exceptionMapper.selectDetailById(ledgerId);
|
||||
if (r == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return r;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long createException(ExceptionLedgerSaveReq req) {
|
||||
ExceptionLedgerVO vo = new ExceptionLedgerVO();
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setExceptionCode(req.getExceptionCode());
|
||||
vo.setSettleMonth(req.getSettleMonth());
|
||||
vo.setAmount(req.getAmount());
|
||||
vo.setPolicyNo(req.getPolicyNo());
|
||||
vo.setCompanyCode(req.getCompanyCode());
|
||||
vo.setInsuranceType(req.getInsuranceType());
|
||||
vo.setDescription(req.getDescription());
|
||||
vo.setRecurringYn(req.getRecurringYn());
|
||||
vo.setRecurringMonths(req.getRecurringMonths());
|
||||
vo.setRecurringLeft(req.getRecurringMonths());
|
||||
vo.setApproveStatus("PENDING");
|
||||
vo.setStatus("NEW");
|
||||
exceptionMapper.insert(vo);
|
||||
return vo.getLedgerId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void approveException(Long ledgerId, String status) {
|
||||
if (!"APPROVED".equals(status) && !"REJECTED".equals(status)) {
|
||||
throw new BizException(ErrorCode.INVALID_PARAMETER, "status는 APPROVED/REJECTED만 가능합니다");
|
||||
}
|
||||
Long approverId = SecurityUtil.getCurrentUserId();
|
||||
if (approverId == null) throw new BizException(ErrorCode.UNAUTHORIZED);
|
||||
exceptionMapper.updateApprove(ledgerId, status, approverId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.ga.api.service.org;
|
||||
|
||||
import com.ga.common.code.CommonCodeService;
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.org.AgentMapper;
|
||||
import com.ga.core.vo.org.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AgentService {
|
||||
|
||||
private final AgentMapper mapper;
|
||||
private final CommonCodeService codeService;
|
||||
|
||||
public PageResponse<AgentResp> list(AgentSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(mapper.selectList(param));
|
||||
}
|
||||
|
||||
public AgentResp detail(Long agentId) {
|
||||
AgentResp resp = mapper.selectDetailById(agentId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(AgentSaveReq req) {
|
||||
if (req.getLicenseNo() != null && mapper.existsByLicenseNo(req.getLicenseNo()) > 0) {
|
||||
throw new BizException(ErrorCode.DUPLICATE_DATA, "이미 등록된 사번입니다");
|
||||
}
|
||||
AgentVO vo = toVO(req, null);
|
||||
vo.setStatus("ACTIVE");
|
||||
mapper.insert(vo);
|
||||
// 입사 이력 기록
|
||||
AgentOrgHistoryVO h = new AgentOrgHistoryVO();
|
||||
h.setAgentId(vo.getAgentId());
|
||||
h.setToOrgId(vo.getOrgId());
|
||||
h.setToGradeId(vo.getGradeId());
|
||||
h.setChangeType("JOIN");
|
||||
h.setChangeDate(req.getJoinDate() != null ? req.getJoinDate() : java.time.LocalDate.now());
|
||||
mapper.insertHistory(h);
|
||||
return vo.getAgentId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(Long agentId, AgentSaveReq req) {
|
||||
AgentVO old = mapper.selectById(agentId);
|
||||
if (old == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
AgentVO vo = toVO(req, agentId);
|
||||
vo.setStatus(old.getStatus());
|
||||
mapper.update(vo);
|
||||
|
||||
// 조직/직급 변경 시 이력
|
||||
if (!java.util.Objects.equals(old.getOrgId(), vo.getOrgId())
|
||||
|| !java.util.Objects.equals(old.getGradeId(), vo.getGradeId())) {
|
||||
AgentOrgHistoryVO h = new AgentOrgHistoryVO();
|
||||
h.setAgentId(agentId);
|
||||
h.setFromOrgId(old.getOrgId());
|
||||
h.setToOrgId(vo.getOrgId());
|
||||
h.setFromGradeId(old.getGradeId());
|
||||
h.setToGradeId(vo.getGradeId());
|
||||
h.setChangeType(!java.util.Objects.equals(old.getGradeId(), vo.getGradeId()) ? "PROMOTE" : "TRANSFER");
|
||||
h.setChangeDate(java.time.LocalDate.now());
|
||||
mapper.insertHistory(h);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void changeStatus(Long agentId, String status) {
|
||||
codeService.validateCode("AGENT_STATUS", status);
|
||||
mapper.updateStatus(agentId, status);
|
||||
}
|
||||
|
||||
public java.util.List<AgentOrgHistoryVO> history(Long agentId) {
|
||||
return mapper.selectHistory(agentId);
|
||||
}
|
||||
|
||||
private AgentVO toVO(AgentSaveReq req, Long agentId) {
|
||||
AgentVO vo = new AgentVO();
|
||||
vo.setAgentId(agentId);
|
||||
vo.setOrgId(req.getOrgId());
|
||||
vo.setGradeId(req.getGradeId());
|
||||
vo.setAgentName(req.getAgentName());
|
||||
vo.setResidentNo(req.getResidentNo());
|
||||
vo.setLicenseNo(req.getLicenseNo());
|
||||
vo.setPhone(req.getPhone());
|
||||
vo.setEmail(req.getEmail());
|
||||
vo.setBankCode(req.getBankCode());
|
||||
vo.setAccountNo(req.getAccountNo());
|
||||
vo.setJoinDate(req.getJoinDate());
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.ga.api.service.org;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.core.mapper.org.OrganizationMapper;
|
||||
import com.ga.core.vo.org.OrganizationResp;
|
||||
import com.ga.core.vo.org.OrganizationVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class OrganizationService {
|
||||
|
||||
private final OrganizationMapper mapper;
|
||||
|
||||
public List<OrganizationResp> getTree() {
|
||||
List<OrganizationResp> flat = mapper.selectAllForTree();
|
||||
return buildTree(flat);
|
||||
}
|
||||
|
||||
public List<OrganizationResp> list(String keyword, String orgType, String isActive) {
|
||||
return mapper.selectList(keyword, orgType, isActive);
|
||||
}
|
||||
|
||||
public OrganizationVO get(Long orgId) {
|
||||
OrganizationVO vo = mapper.selectById(orgId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(OrganizationVO vo) {
|
||||
mapper.insert(vo);
|
||||
return vo.getOrgId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(Long orgId, OrganizationVO vo) {
|
||||
get(orgId);
|
||||
vo.setOrgId(orgId);
|
||||
mapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Long orgId) {
|
||||
if (mapper.countChildren(orgId) > 0) {
|
||||
throw new BizException(ErrorCode.DEPENDENT_DATA, "하위 조직이 있어 삭제할 수 없습니다");
|
||||
}
|
||||
if (mapper.countAgents(orgId) > 0) {
|
||||
throw new BizException(ErrorCode.DEPENDENT_DATA, "소속 설계사가 있어 삭제할 수 없습니다");
|
||||
}
|
||||
mapper.deleteById(orgId);
|
||||
}
|
||||
|
||||
private List<OrganizationResp> buildTree(List<OrganizationResp> flat) {
|
||||
Map<Long, OrganizationResp> byId = new LinkedHashMap<>();
|
||||
for (OrganizationResp o : flat) byId.put(o.getOrgId(), o);
|
||||
List<OrganizationResp> roots = new ArrayList<>();
|
||||
for (OrganizationResp o : flat) {
|
||||
if (o.getParentOrgId() == null) {
|
||||
roots.add(o);
|
||||
} else {
|
||||
OrganizationResp parent = byId.get(o.getParentOrgId());
|
||||
if (parent != null) parent.getChildren().add(o);
|
||||
else roots.add(o);
|
||||
}
|
||||
}
|
||||
return roots;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.ga.api.service.product;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.core.mapper.product.ContractMapper;
|
||||
import com.ga.core.vo.product.ContractResp;
|
||||
import com.ga.core.vo.product.ContractSaveReq;
|
||||
import com.ga.core.vo.product.ContractSearchParam;
|
||||
import com.ga.core.vo.product.ContractVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ContractService {
|
||||
|
||||
private final ContractMapper mapper;
|
||||
|
||||
public PageResponse<ContractResp> list(ContractSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(mapper.selectList(param));
|
||||
}
|
||||
|
||||
public ContractResp detail(Long contractId) {
|
||||
ContractResp resp = mapper.selectDetailById(contractId);
|
||||
if (resp == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(ContractSaveReq req) {
|
||||
if (mapper.existsByPolicyNo(req.getPolicyNo()) > 0) {
|
||||
throw new BizException(ErrorCode.DUPLICATE_DATA, "이미 등록된 증권번호입니다");
|
||||
}
|
||||
ContractVO vo = new ContractVO();
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setProductId(req.getProductId());
|
||||
vo.setPolicyNo(req.getPolicyNo());
|
||||
vo.setContractorName(req.getContractorName());
|
||||
vo.setInsuredName(req.getInsuredName());
|
||||
vo.setPremium(req.getPremium());
|
||||
vo.setPayCycle(req.getPayCycle());
|
||||
vo.setPayPeriod(req.getPayPeriod());
|
||||
vo.setCoveragePeriod(req.getCoveragePeriod());
|
||||
vo.setStatus("ACTIVE");
|
||||
vo.setContractDate(req.getContractDate());
|
||||
vo.setEffectiveDate(req.getEffectiveDate());
|
||||
mapper.insert(vo);
|
||||
return vo.getContractId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(Long contractId, ContractSaveReq req) {
|
||||
ContractVO vo = mapper.selectById(contractId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setProductId(req.getProductId());
|
||||
vo.setContractorName(req.getContractorName());
|
||||
vo.setInsuredName(req.getInsuredName());
|
||||
vo.setPremium(req.getPremium());
|
||||
vo.setPayCycle(req.getPayCycle());
|
||||
vo.setPayPeriod(req.getPayPeriod());
|
||||
vo.setCoveragePeriod(req.getCoveragePeriod());
|
||||
vo.setEffectiveDate(req.getEffectiveDate());
|
||||
mapper.update(vo);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void changeStatus(Long contractId, String status) {
|
||||
mapper.updateStatus(contractId, status);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
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.SettleMasterMapper;
|
||||
import com.ga.core.vo.settle.SettleMasterResp;
|
||||
import com.ga.core.vo.settle.SettleMasterVO;
|
||||
import com.ga.core.vo.settle.SettleSearchParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SettleService {
|
||||
|
||||
private final SettleMasterMapper masterMapper;
|
||||
|
||||
public PageResponse<SettleMasterResp> list(SettleSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(masterMapper.selectList(param));
|
||||
}
|
||||
|
||||
public SettleMasterResp detail(Long agentId, String settleMonth) {
|
||||
SettleMasterResp r = masterMapper.selectDetail(agentId, settleMonth);
|
||||
if (r == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
return r;
|
||||
}
|
||||
|
||||
public Map<String, Object> summary(String settleMonth) {
|
||||
return masterMapper.selectMonthSummary(settleMonth);
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> orgSummary(String settleMonth) {
|
||||
return masterMapper.selectOrgSummary(settleMonth);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void confirm(Long settleId) {
|
||||
SettleMasterVO vo = masterMapper.selectById(settleId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if ("CONFIRMED".equals(vo.getStatus()) || "PAID".equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.ALREADY_CONFIRMED);
|
||||
}
|
||||
masterMapper.updateStatus(settleId, "CONFIRMED", SecurityUtil.getCurrentUserId());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void hold(Long settleId, String reason) {
|
||||
SettleMasterVO vo = masterMapper.selectById(settleId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if ("PAID".equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.NOT_PERMITTED, "지급완료된 정산은 보류할 수 없습니다");
|
||||
}
|
||||
masterMapper.updateHold(settleId, reason);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void release(Long settleId) {
|
||||
SettleMasterVO vo = masterMapper.selectById(settleId);
|
||||
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
if (!"HOLD".equals(vo.getStatus())) {
|
||||
throw new BizException(ErrorCode.INVALID_STATUS, "보류 상태가 아닙니다");
|
||||
}
|
||||
masterMapper.updateStatus(settleId, "CALCULATED", SecurityUtil.getCurrentUserId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.ga.api.service.system;
|
||||
|
||||
import com.ga.common.exception.BizException;
|
||||
import com.ga.common.exception.ErrorCode;
|
||||
import com.ga.common.model.PageResponse;
|
||||
import com.ga.common.system.SystemConfigService;
|
||||
import com.ga.core.mapper.user.UserMapper;
|
||||
import com.ga.core.vo.user.UserResp;
|
||||
import com.ga.core.vo.user.UserSaveReq;
|
||||
import com.ga.core.vo.user.UserSearchParam;
|
||||
import com.ga.core.vo.user.UserVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserService {
|
||||
|
||||
private final UserMapper mapper;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final SystemConfigService configService;
|
||||
|
||||
public PageResponse<UserResp> list(UserSearchParam param) {
|
||||
param.startPage();
|
||||
return PageResponse.of(mapper.selectList(param));
|
||||
}
|
||||
|
||||
public UserResp detail(Long userId) {
|
||||
UserResp r = mapper.selectDetailById(userId);
|
||||
if (r == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
r.setRoleCodes(mapper.selectRoleCodes(userId));
|
||||
return r;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long create(UserSaveReq req) {
|
||||
if (mapper.selectByLoginId(req.getLoginId()) != null) {
|
||||
throw new BizException(ErrorCode.DUPLICATE_DATA, "이미 사용 중인 로그인 ID입니다");
|
||||
}
|
||||
String initialPwd = req.getPassword();
|
||||
if (initialPwd == null || initialPwd.isBlank()) {
|
||||
initialPwd = "init1234!"; // 임시 — 로그인 후 변경 강제
|
||||
}
|
||||
UserVO vo = new UserVO();
|
||||
vo.setLoginId(req.getLoginId());
|
||||
vo.setPassword(passwordEncoder.encode(initialPwd));
|
||||
vo.setUserName(req.getUserName());
|
||||
vo.setEmail(req.getEmail());
|
||||
vo.setPhone(req.getPhone());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setStatus(req.getStatus() != null ? req.getStatus() : "ACTIVE");
|
||||
mapper.insert(vo);
|
||||
|
||||
if (req.getRoleIds() != null) {
|
||||
req.getRoleIds().forEach(rid -> mapper.insertUserRole(vo.getUserId(), rid));
|
||||
}
|
||||
return vo.getUserId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(Long userId, UserSaveReq req) {
|
||||
UserVO old = mapper.selectById(userId);
|
||||
if (old == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||
UserVO vo = new UserVO();
|
||||
vo.setUserId(userId);
|
||||
vo.setUserName(req.getUserName());
|
||||
vo.setEmail(req.getEmail());
|
||||
vo.setPhone(req.getPhone());
|
||||
vo.setAgentId(req.getAgentId());
|
||||
vo.setStatus(req.getStatus());
|
||||
mapper.update(vo);
|
||||
|
||||
if (req.getRoleIds() != null) {
|
||||
mapper.deleteUserRoles(userId);
|
||||
req.getRoleIds().forEach(rid -> mapper.insertUserRole(userId, rid));
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void resetPassword(Long userId) {
|
||||
int min = configService.getInt("PASSWORD_MIN_LEN", 8);
|
||||
String temp = "reset" + System.currentTimeMillis() % 1_000_000;
|
||||
if (temp.length() < min) temp = temp + "!@#";
|
||||
mapper.updatePassword(userId, passwordEncoder.encode(temp));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void unlock(Long userId) {
|
||||
mapper.resetFailCount(userId);
|
||||
mapper.updateStatus(userId, "ACTIVE");
|
||||
}
|
||||
|
||||
public List<String> roleCodes(Long userId) {
|
||||
return mapper.selectRoleCodes(userId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user