Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ad0e5a090 |
@@ -0,0 +1,57 @@
|
|||||||
|
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.InsuranceCompanyMapper;
|
||||||
|
import com.ga.core.mapstruct.ProductMapStruct;
|
||||||
|
import com.ga.core.vo.product.InsuranceCompanyResp;
|
||||||
|
import com.ga.core.vo.product.InsuranceCompanySaveReq;
|
||||||
|
import com.ga.core.vo.product.InsuranceCompanySearchParam;
|
||||||
|
import com.ga.core.vo.product.InsuranceCompanyVO;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CompanyService {
|
||||||
|
|
||||||
|
private final InsuranceCompanyMapper companyMapper;
|
||||||
|
private final ProductMapStruct mapStruct;
|
||||||
|
|
||||||
|
public PageResponse<InsuranceCompanyResp> list(InsuranceCompanySearchParam param) {
|
||||||
|
param.startPage();
|
||||||
|
return PageResponse.of(companyMapper.selectRespList(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
public InsuranceCompanyResp detail(Long companyId) {
|
||||||
|
InsuranceCompanyResp r = companyMapper.selectRespById(companyId);
|
||||||
|
if (r == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Long create(InsuranceCompanySaveReq req) {
|
||||||
|
if (companyMapper.existsByCode(req.getCompanyCode()) > 0) {
|
||||||
|
throw new BizException(ErrorCode.DUPLICATE_DATA, "이미 등록된 보험사 코드입니다");
|
||||||
|
}
|
||||||
|
InsuranceCompanyVO vo = mapStruct.toVO(req);
|
||||||
|
companyMapper.insert(vo);
|
||||||
|
return vo.getCompanyId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void update(Long companyId, InsuranceCompanySaveReq req) {
|
||||||
|
InsuranceCompanyVO vo = companyMapper.selectById(companyId);
|
||||||
|
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||||
|
mapStruct.copyToVO(req, vo);
|
||||||
|
vo.setCompanyId(companyId);
|
||||||
|
companyMapper.update(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void delete(Long companyId) {
|
||||||
|
companyMapper.deleteById(companyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
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.ProductMapper;
|
||||||
|
import com.ga.core.mapstruct.ProductMapStruct;
|
||||||
|
import com.ga.core.vo.product.ProductResp;
|
||||||
|
import com.ga.core.vo.product.ProductSaveReq;
|
||||||
|
import com.ga.core.vo.product.ProductSearchParam;
|
||||||
|
import com.ga.core.vo.product.ProductVO;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ProductService {
|
||||||
|
|
||||||
|
private final ProductMapper productMapper;
|
||||||
|
private final ProductMapStruct mapStruct;
|
||||||
|
|
||||||
|
public PageResponse<ProductResp> list(ProductSearchParam param) {
|
||||||
|
param.startPage();
|
||||||
|
return PageResponse.of(productMapper.selectByParam(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductResp detail(Long productId) {
|
||||||
|
ProductResp r = productMapper.selectDetailById(productId);
|
||||||
|
if (r == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Long create(ProductSaveReq req) {
|
||||||
|
if (productMapper.existsByCode(req.getCompanyId(), req.getProductCode()) > 0) {
|
||||||
|
throw new BizException(ErrorCode.DUPLICATE_DATA, "이미 등록된 상품 코드입니다");
|
||||||
|
}
|
||||||
|
ProductVO vo = mapStruct.toVO(req);
|
||||||
|
productMapper.insert(vo);
|
||||||
|
return vo.getProductId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void update(Long productId, ProductSaveReq req) {
|
||||||
|
ProductVO vo = productMapper.selectById(productId);
|
||||||
|
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||||
|
mapStruct.copyToVO(req, vo);
|
||||||
|
vo.setProductId(productId);
|
||||||
|
productMapper.update(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void delete(Long productId) {
|
||||||
|
productMapper.deleteById(productId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package com.ga.api.service.receive;
|
||||||
|
|
||||||
|
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.receive.ReceiveMapper;
|
||||||
|
import com.ga.core.vo.receive.*;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ReceiveService {
|
||||||
|
|
||||||
|
private final ReceiveMapper receiveMapper;
|
||||||
|
|
||||||
|
/* ========== company_profile ========== */
|
||||||
|
public PageResponse<CompanyProfileResp> listProfiles(CompanyProfileSearchParam p) {
|
||||||
|
p.startPage();
|
||||||
|
return PageResponse.of(receiveMapper.selectProfileResp(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompanyProfileResp profileDetail(String companyCode) {
|
||||||
|
CompanyProfileResp r = receiveMapper.selectProfileRespByCode(companyCode);
|
||||||
|
if (r == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void saveProfile(CompanyProfileSaveReq req) {
|
||||||
|
CompanyProfileVO existing = receiveMapper.selectProfile(req.getCompanyCode());
|
||||||
|
CompanyProfileVO vo = new CompanyProfileVO();
|
||||||
|
org.springframework.beans.BeanUtils.copyProperties(req, vo);
|
||||||
|
if (existing == null) receiveMapper.insertProfile(vo);
|
||||||
|
else receiveMapper.updateProfile(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== company_field_mapping ========== */
|
||||||
|
public List<CompanyFieldMappingResp> listFieldMappings(String companyCode, String targetTable) {
|
||||||
|
return receiveMapper.selectFieldMappingResp(companyCode, targetTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Long createFieldMapping(CompanyFieldMappingSaveReq req) {
|
||||||
|
CompanyFieldMappingVO vo = new CompanyFieldMappingVO();
|
||||||
|
org.springframework.beans.BeanUtils.copyProperties(req, vo);
|
||||||
|
receiveMapper.insertFieldMapping(vo);
|
||||||
|
return vo.getMappingId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateFieldMapping(Long mappingId, CompanyFieldMappingSaveReq req) {
|
||||||
|
CompanyFieldMappingVO vo = new CompanyFieldMappingVO();
|
||||||
|
org.springframework.beans.BeanUtils.copyProperties(req, vo);
|
||||||
|
vo.setMappingId(mappingId);
|
||||||
|
receiveMapper.updateFieldMapping(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void deleteFieldMapping(Long mappingId) {
|
||||||
|
receiveMapper.deleteFieldMapping(mappingId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== code_mapping ========== */
|
||||||
|
public PageResponse<CodeMappingResp> listCodeMappings(CodeMappingSearchParam p) {
|
||||||
|
p.startPage();
|
||||||
|
return PageResponse.of(receiveMapper.selectCodeMappingResp(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Long createCodeMapping(CodeMappingSaveReq req) {
|
||||||
|
CodeMappingVO vo = new CodeMappingVO();
|
||||||
|
org.springframework.beans.BeanUtils.copyProperties(req, vo);
|
||||||
|
receiveMapper.insertCodeMapping(vo);
|
||||||
|
return vo.getCodeId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateCodeMapping(Long codeId, CodeMappingSaveReq req) {
|
||||||
|
CodeMappingVO vo = new CodeMappingVO();
|
||||||
|
org.springframework.beans.BeanUtils.copyProperties(req, vo);
|
||||||
|
vo.setCodeId(codeId);
|
||||||
|
receiveMapper.updateCodeMapping(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void deleteCodeMapping(Long codeId) {
|
||||||
|
receiveMapper.deleteCodeMapping(codeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== raw_commission_data ========== */
|
||||||
|
public PageResponse<RawCommissionDataResp> listRaw(RawCommissionDataSearchParam p) {
|
||||||
|
p.startPage();
|
||||||
|
return PageResponse.of(receiveMapper.selectRawResp(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== parse_error_log ========== */
|
||||||
|
public PageResponse<ParseErrorLogResp> listErrors(ParseErrorLogSearchParam p) {
|
||||||
|
p.startPage();
|
||||||
|
return PageResponse.of(receiveMapper.selectErrorResp(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void resolveError(Long errorId, String status, String note) {
|
||||||
|
receiveMapper.resolveError(errorId, status, note, SecurityUtil.getCurrentUserId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
package com.ga.api.service.rule;
|
||||||
|
|
||||||
|
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.rule.RuleMapper;
|
||||||
|
import com.ga.core.mapstruct.RuleMapStruct;
|
||||||
|
import com.ga.core.vo.rule.*;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RuleService {
|
||||||
|
|
||||||
|
private final RuleMapper ruleMapper;
|
||||||
|
private final RuleMapStruct mapStruct;
|
||||||
|
|
||||||
|
/* ========== commission_rate ========== */
|
||||||
|
public PageResponse<CommissionRateResp> listCommission(CommissionRateSearchParam p) {
|
||||||
|
p.startPage();
|
||||||
|
return PageResponse.of(ruleMapper.selectCommissionRateResp(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Long createCommission(CommissionRateSaveReq req) {
|
||||||
|
CommissionRateVO vo = mapStruct.toVO(req);
|
||||||
|
vo.setCreatedBy(SecurityUtil.getCurrentUserId());
|
||||||
|
if (vo.getVersion() == null) vo.setVersion(1);
|
||||||
|
ruleMapper.insertCommissionRate(vo);
|
||||||
|
return vo.getRateId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateCommission(Long rateId, CommissionRateSaveReq req) {
|
||||||
|
CommissionRateVO vo = new CommissionRateVO();
|
||||||
|
mapStruct.copyToVO(req, vo);
|
||||||
|
vo.setRateId(rateId);
|
||||||
|
ruleMapper.updateCommissionRate(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== payout_rule ========== */
|
||||||
|
public PageResponse<PayoutRuleResp> listPayout(PayoutRuleSearchParam p) {
|
||||||
|
p.startPage();
|
||||||
|
return PageResponse.of(ruleMapper.selectPayoutRuleResp(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Long createPayout(PayoutRuleSaveReq req) {
|
||||||
|
PayoutRuleVO vo = mapStruct.toVO(req);
|
||||||
|
vo.setCreatedBy(SecurityUtil.getCurrentUserId());
|
||||||
|
if (vo.getVersion() == null) vo.setVersion(1);
|
||||||
|
ruleMapper.insertPayoutRule(vo);
|
||||||
|
return vo.getRuleId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updatePayout(Long ruleId, PayoutRuleSaveReq req) {
|
||||||
|
PayoutRuleVO vo = new PayoutRuleVO();
|
||||||
|
mapStruct.copyToVO(req, vo);
|
||||||
|
vo.setRuleId(ruleId);
|
||||||
|
ruleMapper.updatePayoutRule(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== override_rule ========== */
|
||||||
|
public PageResponse<OverrideRuleResp> listOverride(OverrideRuleSearchParam p) {
|
||||||
|
p.startPage();
|
||||||
|
return PageResponse.of(ruleMapper.selectOverrideRuleResp(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Long createOverride(OverrideRuleSaveReq req) {
|
||||||
|
OverrideRuleVO vo = mapStruct.toVO(req);
|
||||||
|
ruleMapper.insertOverrideRule(vo);
|
||||||
|
return vo.getOverrideId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateOverride(Long overrideId, OverrideRuleSaveReq req) {
|
||||||
|
OverrideRuleVO vo = new OverrideRuleVO();
|
||||||
|
mapStruct.copyToVO(req, vo);
|
||||||
|
vo.setOverrideId(overrideId);
|
||||||
|
ruleMapper.updateOverrideRule(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== chargeback_rule ========== */
|
||||||
|
public PageResponse<ChargebackRuleResp> listChargeback(ChargebackRuleSearchParam p) {
|
||||||
|
p.startPage();
|
||||||
|
return PageResponse.of(ruleMapper.selectChargebackRuleResp(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Long createChargeback(ChargebackRuleSaveReq req) {
|
||||||
|
ChargebackRuleVO vo = mapStruct.toVO(req);
|
||||||
|
ruleMapper.insertChargebackRule(vo);
|
||||||
|
return vo.getCbRuleId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateChargeback(Long cbRuleId, ChargebackRuleSaveReq req) {
|
||||||
|
ChargebackRuleVO vo = new ChargebackRuleVO();
|
||||||
|
mapStruct.copyToVO(req, vo);
|
||||||
|
vo.setCbRuleId(cbRuleId);
|
||||||
|
ruleMapper.updateChargebackRule(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== exception_type_code ========== */
|
||||||
|
public PageResponse<ExceptionTypeCodeResp> listExceptionCodes(ExceptionTypeCodeSearchParam p) {
|
||||||
|
p.startPage();
|
||||||
|
return PageResponse.of(ruleMapper.selectExceptionTypeCodeResp(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void createExceptionCode(ExceptionTypeCodeSaveReq req) {
|
||||||
|
if (ruleMapper.selectExceptionCode(req.getExceptionCode()) != null) {
|
||||||
|
throw new BizException(ErrorCode.DUPLICATE_DATA);
|
||||||
|
}
|
||||||
|
ExceptionTypeCodeVO vo = mapStruct.toVO(req);
|
||||||
|
ruleMapper.insertExceptionCode(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateExceptionCode(String exceptionCode, ExceptionTypeCodeSaveReq req) {
|
||||||
|
ExceptionTypeCodeVO vo = new ExceptionTypeCodeVO();
|
||||||
|
mapStruct.copyToVO(req, vo);
|
||||||
|
vo.setExceptionCode(exceptionCode);
|
||||||
|
ruleMapper.updateExceptionCode(vo);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
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.core.mapper.user.RoleMapper;
|
||||||
|
import com.ga.core.mapstruct.UserMapStruct;
|
||||||
|
import com.ga.core.vo.user.RoleResp;
|
||||||
|
import com.ga.core.vo.user.RoleSaveReq;
|
||||||
|
import com.ga.core.vo.user.RoleSearchParam;
|
||||||
|
import com.ga.core.vo.user.RoleVO;
|
||||||
|
import lombok.Data;
|
||||||
|
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 RoleService {
|
||||||
|
|
||||||
|
private final RoleMapper roleMapper;
|
||||||
|
private final UserMapStruct mapStruct;
|
||||||
|
|
||||||
|
public PageResponse<RoleResp> list(RoleSearchParam p) {
|
||||||
|
p.startPage();
|
||||||
|
return PageResponse.of(roleMapper.selectRespList(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleResp detail(Long roleId) {
|
||||||
|
RoleResp r = roleMapper.selectRespById(roleId);
|
||||||
|
if (r == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Long create(RoleSaveReq req) {
|
||||||
|
if (roleMapper.existsByCode(req.getRoleCode()) > 0) {
|
||||||
|
throw new BizException(ErrorCode.DUPLICATE_DATA, "이미 등록된 역할 코드입니다");
|
||||||
|
}
|
||||||
|
RoleVO vo = mapStruct.toVO(req);
|
||||||
|
roleMapper.insert(vo);
|
||||||
|
return vo.getRoleId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void update(Long roleId, RoleSaveReq req) {
|
||||||
|
RoleVO vo = roleMapper.selectById(roleId);
|
||||||
|
if (vo == null) throw new BizException(ErrorCode.NOT_FOUND);
|
||||||
|
if ("Y".equals(vo.getIsSystem())) {
|
||||||
|
throw new BizException(ErrorCode.NOT_PERMITTED, "시스템 역할은 수정할 수 없습니다");
|
||||||
|
}
|
||||||
|
mapStruct.copyToVO(req, vo);
|
||||||
|
vo.setRoleId(roleId);
|
||||||
|
roleMapper.update(vo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void delete(Long roleId) {
|
||||||
|
roleMapper.deleteById(roleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== 권한 ========== */
|
||||||
|
public List<Map<String, Object>> permissions(Long roleId) {
|
||||||
|
return roleMapper.selectRolePermissions(roleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void replacePermissions(Long roleId, List<PermissionEntry> entries) {
|
||||||
|
roleMapper.deleteRolePermissions(roleId);
|
||||||
|
if (entries == null) return;
|
||||||
|
for (PermissionEntry e : entries) {
|
||||||
|
roleMapper.insertRolePermission(roleId, e.getMenuId(), e.getPermCode(),
|
||||||
|
e.getIsGranted() == null ? "Y" : e.getIsGranted());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class PermissionEntry {
|
||||||
|
private Long menuId;
|
||||||
|
private String permCode;
|
||||||
|
private String isGranted;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
package com.ga.batch.settlement.receive;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.ga.common.exception.BizException;
|
|
||||||
import com.ga.common.exception.ErrorCode;
|
|
||||||
import com.ga.core.mapper.receive.ReceiveMapper;
|
|
||||||
import com.ga.core.vo.receive.CompanyProfileVO;
|
|
||||||
import com.ga.core.vo.receive.RawCommissionDataVO;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.client.RestClient;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 보험사 OpenAPI 호출하여 데이터 수신.
|
|
||||||
* - api_url 은 company_profile 에서 가져옴. {settleMonth} placeholder 치환 지원.
|
|
||||||
* - 응답은 JSON array 가정. 각 element 를 raw_content 에 적재.
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class ApiReceiver implements DataReceiver {
|
|
||||||
|
|
||||||
private final ReceiveMapper mapper;
|
|
||||||
private final RestClient restClient = RestClient.builder().build();
|
|
||||||
private static final ObjectMapper JSON = new ObjectMapper();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(String companyCode) {
|
|
||||||
CompanyProfileVO p = mapper.selectProfile(companyCode);
|
|
||||||
return p != null && "API".equalsIgnoreCase(p.getDataFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int receive(String companyCode, String settleMonth) {
|
|
||||||
CompanyProfileVO profile = mapper.selectProfile(companyCode);
|
|
||||||
if (profile == null || profile.getApiUrl() == null) {
|
|
||||||
log.warn("API profile not configured: {}", companyCode);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
String url = profile.getApiUrl().replace("{settleMonth}", settleMonth);
|
|
||||||
|
|
||||||
try {
|
|
||||||
String body = restClient.get().uri(url).retrieve().body(String.class);
|
|
||||||
if (body == null || body.isBlank()) return 0;
|
|
||||||
JsonNode arr = JSON.readTree(body);
|
|
||||||
if (!arr.isArray()) {
|
|
||||||
log.warn("API response is not array: {}", url);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
String batchId = UUID.randomUUID().toString();
|
|
||||||
List<RawCommissionDataVO> buf = new ArrayList<>(arr.size());
|
|
||||||
int rowNum = 0;
|
|
||||||
for (JsonNode item : arr) {
|
|
||||||
rowNum++;
|
|
||||||
RawCommissionDataVO raw = new RawCommissionDataVO();
|
|
||||||
raw.setCompanyCode(companyCode);
|
|
||||||
raw.setBatchId(batchId);
|
|
||||||
raw.setSettleMonth(settleMonth);
|
|
||||||
raw.setDataType("API");
|
|
||||||
raw.setRawContent(item.toString());
|
|
||||||
raw.setParseStatus("PENDING");
|
|
||||||
raw.setFileName(url);
|
|
||||||
raw.setRowNumber(rowNum);
|
|
||||||
buf.add(raw);
|
|
||||||
}
|
|
||||||
if (!buf.isEmpty()) mapper.insertRawBatch(buf);
|
|
||||||
log.info("ApiReceiver: company={}, url={}, rows={}", companyCode, url, buf.size());
|
|
||||||
return buf.size();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("API receive error: {}", url, e);
|
|
||||||
throw new BizException(ErrorCode.EXTERNAL_API_FAIL, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
package com.ga.batch.settlement.receive;
|
|
||||||
|
|
||||||
import com.ga.common.exception.BizException;
|
|
||||||
import com.ga.common.exception.ErrorCode;
|
|
||||||
import com.ga.core.mapper.receive.ReceiveMapper;
|
|
||||||
import com.ga.core.vo.receive.CompanyProfileVO;
|
|
||||||
import com.ga.core.vo.receive.RawCommissionDataVO;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CSV/TSV 파일 수신.
|
|
||||||
* file_encoding, delimiter 는 company_profile 에서 가져옴.
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class CsvReceiver implements DataReceiver {
|
|
||||||
|
|
||||||
private final ReceiveMapper mapper;
|
|
||||||
|
|
||||||
@Value("${ga.batch.receive.csv-dir:./data/receive/csv}")
|
|
||||||
private String csvDir;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(String companyCode) {
|
|
||||||
CompanyProfileVO p = mapper.selectProfile(companyCode);
|
|
||||||
return p != null && "CSV".equalsIgnoreCase(p.getDataFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int receive(String companyCode, String settleMonth) {
|
|
||||||
CompanyProfileVO profile = mapper.selectProfile(companyCode);
|
|
||||||
Path file = Paths.get(csvDir, settleMonth, companyCode + ".csv");
|
|
||||||
if (!Files.exists(file)) {
|
|
||||||
log.warn("CSV file not found: {}", file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Charset cs = profile.getFileEncoding() != null ? Charset.forName(profile.getFileEncoding()) : Charset.forName("UTF-8");
|
|
||||||
String delim = profile.getDelimiter() != null ? profile.getDelimiter() : ",";
|
|
||||||
int dataStart = profile.getDataStartRow() == null ? 2 : profile.getDataStartRow();
|
|
||||||
String batchId = UUID.randomUUID().toString();
|
|
||||||
int batchSize = 1000;
|
|
||||||
int total = 0;
|
|
||||||
List<RawCommissionDataVO> buf = new ArrayList<>(batchSize);
|
|
||||||
|
|
||||||
try (BufferedReader reader = Files.newBufferedReader(file, cs)) {
|
|
||||||
String line;
|
|
||||||
int rowNum = 0;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
rowNum++;
|
|
||||||
if (rowNum < dataStart) continue;
|
|
||||||
if (line.isBlank()) continue;
|
|
||||||
RawCommissionDataVO raw = new RawCommissionDataVO();
|
|
||||||
raw.setCompanyCode(companyCode);
|
|
||||||
raw.setBatchId(batchId);
|
|
||||||
raw.setSettleMonth(settleMonth);
|
|
||||||
raw.setDataType("CSV");
|
|
||||||
raw.setRawContent(toJsonArray(line.split(java.util.regex.Pattern.quote(delim), -1)));
|
|
||||||
raw.setParseStatus("PENDING");
|
|
||||||
raw.setFileName(file.getFileName().toString());
|
|
||||||
raw.setRowNumber(rowNum);
|
|
||||||
buf.add(raw);
|
|
||||||
if (buf.size() >= batchSize) {
|
|
||||||
mapper.insertRawBatch(buf);
|
|
||||||
total += buf.size();
|
|
||||||
buf.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!buf.isEmpty()) {
|
|
||||||
mapper.insertRawBatch(buf);
|
|
||||||
total += buf.size();
|
|
||||||
}
|
|
||||||
log.info("CsvReceiver: company={}, file={}, rows={}", companyCode, file, total);
|
|
||||||
return total;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("CSV receive error", e);
|
|
||||||
throw new BizException(ErrorCode.EXCEL_PARSE_FAIL, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String toJsonArray(String[] cols) {
|
|
||||||
StringBuilder sb = new StringBuilder("[");
|
|
||||||
for (int i = 0; i < cols.length; i++) {
|
|
||||||
if (i > 0) sb.append(',');
|
|
||||||
sb.append('"').append(cols[i].replace("\"", "\\\"")).append('"');
|
|
||||||
}
|
|
||||||
sb.append(']');
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
package com.ga.batch.settlement.receive;
|
|
||||||
|
|
||||||
import com.ga.common.exception.BizException;
|
|
||||||
import com.ga.common.exception.ErrorCode;
|
|
||||||
import com.ga.core.mapper.receive.ReceiveMapper;
|
|
||||||
import com.ga.core.vo.receive.CompanyProfileVO;
|
|
||||||
import com.ga.core.vo.receive.RawCommissionDataVO;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 보험사별 EDI(고정 폭) 텍스트 파일 수신.
|
|
||||||
* 각 행을 그대로 raw_content 에 적재 — 매핑은 transform 단계에서 company_field_mapping 의 sourceColIndex(시작/길이)로 분해.
|
|
||||||
*
|
|
||||||
* 보험사별 EDI 양식이 매우 다양하므로 여기서는 line 자체를 raw로 보존하고
|
|
||||||
* MappingEngine 이 sourceColIndex 기준으로 substring 처리.
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class EdiReceiver implements DataReceiver {
|
|
||||||
|
|
||||||
private final ReceiveMapper mapper;
|
|
||||||
|
|
||||||
@Value("${ga.batch.receive.edi-dir:./data/receive/edi}")
|
|
||||||
private String ediDir;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(String companyCode) {
|
|
||||||
CompanyProfileVO p = mapper.selectProfile(companyCode);
|
|
||||||
return p != null && "EDI".equalsIgnoreCase(p.getDataFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int receive(String companyCode, String settleMonth) {
|
|
||||||
CompanyProfileVO profile = mapper.selectProfile(companyCode);
|
|
||||||
Path file = Paths.get(ediDir, settleMonth, companyCode + ".dat");
|
|
||||||
if (!Files.exists(file)) {
|
|
||||||
log.warn("EDI file not found: {}", file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Charset cs = profile.getFileEncoding() != null ? Charset.forName(profile.getFileEncoding()) : Charset.forName("EUC-KR");
|
|
||||||
int dataStart = profile.getDataStartRow() == null ? 1 : profile.getDataStartRow();
|
|
||||||
String batchId = UUID.randomUUID().toString();
|
|
||||||
int batchSize = 1000;
|
|
||||||
int total = 0;
|
|
||||||
List<RawCommissionDataVO> buf = new ArrayList<>(batchSize);
|
|
||||||
|
|
||||||
try (BufferedReader reader = Files.newBufferedReader(file, cs)) {
|
|
||||||
String line;
|
|
||||||
int rowNum = 0;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
rowNum++;
|
|
||||||
if (rowNum < dataStart) continue;
|
|
||||||
if (line.isBlank()) continue;
|
|
||||||
RawCommissionDataVO raw = new RawCommissionDataVO();
|
|
||||||
raw.setCompanyCode(companyCode);
|
|
||||||
raw.setBatchId(batchId);
|
|
||||||
raw.setSettleMonth(settleMonth);
|
|
||||||
raw.setDataType("EDI");
|
|
||||||
raw.setRawContent(line); // 고정 폭 라인 그대로
|
|
||||||
raw.setParseStatus("PENDING");
|
|
||||||
raw.setFileName(file.getFileName().toString());
|
|
||||||
raw.setRowNumber(rowNum);
|
|
||||||
buf.add(raw);
|
|
||||||
if (buf.size() >= batchSize) {
|
|
||||||
mapper.insertRawBatch(buf);
|
|
||||||
total += buf.size();
|
|
||||||
buf.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!buf.isEmpty()) {
|
|
||||||
mapper.insertRawBatch(buf);
|
|
||||||
total += buf.size();
|
|
||||||
}
|
|
||||||
log.info("EdiReceiver: company={}, file={}, rows={}", companyCode, file, total);
|
|
||||||
return total;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("EDI receive error", e);
|
|
||||||
throw new BizException(ErrorCode.EXCEL_PARSE_FAIL, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
package com.ga.batch.settlement.receive;
|
|
||||||
|
|
||||||
import com.ga.common.exception.BizException;
|
|
||||||
import com.ga.common.exception.ErrorCode;
|
|
||||||
import com.ga.core.mapper.receive.ReceiveMapper;
|
|
||||||
import com.ga.core.vo.receive.CompanyProfileVO;
|
|
||||||
import com.ga.core.vo.receive.RawCommissionDataVO;
|
|
||||||
import com.monitorjbl.xlsx.StreamingReader;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 엑셀 파일을 읽어 raw_commission_data 에 적재.
|
|
||||||
* 보험사별 FTP 다운로드 폴더 또는 운영자가 미리 옮겨둔 폴더에서 읽음.
|
|
||||||
*
|
|
||||||
* - SAX 스트리밍으로 70만건 안전 처리
|
|
||||||
* - 컬럼 매핑은 ReceiveMapper.selectFieldMappings(companyCode, "raw") 의 정의를 따름
|
|
||||||
* - data_format = 'EXCEL' 인 보험사 지원
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class ExcelReceiver implements DataReceiver {
|
|
||||||
|
|
||||||
private final ReceiveMapper mapper;
|
|
||||||
|
|
||||||
@Value("${ga.batch.receive.excel-dir:./data/receive/excel}")
|
|
||||||
private String excelDir;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(String companyCode) {
|
|
||||||
CompanyProfileVO p = mapper.selectProfile(companyCode);
|
|
||||||
return p != null && "EXCEL".equalsIgnoreCase(p.getDataFormat());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int receive(String companyCode, String settleMonth) {
|
|
||||||
CompanyProfileVO profile = mapper.selectProfile(companyCode);
|
|
||||||
Path file = resolveFile(companyCode, settleMonth);
|
|
||||||
if (!Files.exists(file)) {
|
|
||||||
log.warn("Excel file not found: {}", file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
String batchId = UUID.randomUUID().toString();
|
|
||||||
int header = profile.getHeaderRow() == null ? 1 : profile.getHeaderRow();
|
|
||||||
int dataStart = profile.getDataStartRow() == null ? 2 : profile.getDataStartRow();
|
|
||||||
int batchSize = 1000;
|
|
||||||
int total = 0;
|
|
||||||
|
|
||||||
List<RawCommissionDataVO> buf = new ArrayList<>(batchSize);
|
|
||||||
try (var is = Files.newInputStream(file);
|
|
||||||
Workbook wb = StreamingReader.builder().rowCacheSize(100).bufferSize(4096).open(is)) {
|
|
||||||
|
|
||||||
Sheet sheet = profile.getSheetName() != null ? wb.getSheet(profile.getSheetName()) : wb.getSheetAt(0);
|
|
||||||
int rowNum = 0;
|
|
||||||
for (Row row : sheet) {
|
|
||||||
rowNum++;
|
|
||||||
if (rowNum < dataStart) continue;
|
|
||||||
RawCommissionDataVO raw = new RawCommissionDataVO();
|
|
||||||
raw.setCompanyCode(companyCode);
|
|
||||||
raw.setBatchId(batchId);
|
|
||||||
raw.setSettleMonth(settleMonth);
|
|
||||||
raw.setDataType("EXCEL");
|
|
||||||
raw.setRawContent(rowToJson(row));
|
|
||||||
raw.setParseStatus("PENDING");
|
|
||||||
raw.setFileName(file.getFileName().toString());
|
|
||||||
raw.setRowNumber(rowNum);
|
|
||||||
buf.add(raw);
|
|
||||||
if (buf.size() >= batchSize) {
|
|
||||||
mapper.insertRawBatch(buf);
|
|
||||||
total += buf.size();
|
|
||||||
buf.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!buf.isEmpty()) {
|
|
||||||
mapper.insertRawBatch(buf);
|
|
||||||
total += buf.size();
|
|
||||||
}
|
|
||||||
log.info("ExcelReceiver: company={}, file={}, rows={}", companyCode, file, total);
|
|
||||||
return total;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Excel receive error", e);
|
|
||||||
throw new BizException(ErrorCode.EXCEL_PARSE_FAIL, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Path resolveFile(String companyCode, String settleMonth) {
|
|
||||||
return Paths.get(excelDir, settleMonth, companyCode + ".xlsx");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Row 의 셀 값을 단순 JSON 배열 문자열로 직렬화. */
|
|
||||||
private String rowToJson(Row row) {
|
|
||||||
StringBuilder sb = new StringBuilder("[");
|
|
||||||
boolean first = true;
|
|
||||||
for (var cell : row) {
|
|
||||||
if (!first) sb.append(',');
|
|
||||||
sb.append('"').append(cell == null ? "" : cell.toString().replace("\"", "\\\"")).append('"');
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
sb.append(']');
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package com.ga.batch.settlement.receive;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 보험사별 적절한 Receiver 를 선택해 호출.
|
|
||||||
* 모든 DataReceiver 가 자동 주입되며, supports(companyCode) 가 true 인 첫 구현체를 사용.
|
|
||||||
*
|
|
||||||
* 우선순위는 List 주입 순서. ManualReceiver 는 fallback 역할이므로 마지막에 두는 것을 권장
|
|
||||||
* (현재는 supports 가 NULL 프로파일도 true로 하므로 우선순위 위에 있을 수 없음).
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class ReceiverDispatcher {
|
|
||||||
|
|
||||||
private final List<DataReceiver> receivers;
|
|
||||||
|
|
||||||
public int dispatch(String companyCode, String settleMonth) {
|
|
||||||
for (DataReceiver r : receivers) {
|
|
||||||
if (r == null) continue;
|
|
||||||
try {
|
|
||||||
if (r.supports(companyCode)) {
|
|
||||||
log.info("Dispatching {} -> {}", companyCode, r.getClass().getSimpleName());
|
|
||||||
return r.receive(companyCode, settleMonth);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("Receiver {} supports() error", r.getClass().getSimpleName(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.warn("No receiver supports company: {}", companyCode);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user