Commit 47d3161a by zhangxingmin

Merge remote-tracking branch 'origin/dev' into prod

parents 4f42beb3 24017a14
......@@ -3,6 +3,8 @@ package com.yd.csf.api.controller;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
......@@ -14,14 +16,17 @@ import com.yd.csf.service.common.ErrorCode;
import com.yd.csf.service.dto.*;
import com.yd.csf.service.model.CommissionExpected;
import com.yd.csf.service.model.Policy;
import com.yd.csf.service.model.PolicyFollow;
import com.yd.csf.service.service.CommissionExpectedService;
import com.yd.csf.service.service.PolicyFollowService;
import com.yd.csf.service.service.PolicyService;
import com.yd.csf.service.vo.CommissionExpectedExportDTO;
import com.yd.csf.service.vo.CommissionExpectedStatisticsVO;
import com.yd.csf.service.vo.CommissionExpectedVO;
import com.yd.csf.service.vo.ReceivableReportVO;
import com.yd.csf.service.vo.*;
import com.yd.insurance.base.feign.client.insurancereconciliationcompany.ApiInsuranceReconciliationCompanyFeignClient;
import com.yd.insurance.base.feign.request.insurancereconciliationcompany.ApiInsuranceReconciliationCompanyPageRequest;
import com.yd.insurance.base.feign.response.insurancereconciliationcompany.ApiInsuranceReconciliationCompanyPageResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
......@@ -31,7 +36,11 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
......@@ -40,6 +49,7 @@ import java.util.stream.Collectors;
* @author jianan
* @since 2025-08-31
*/
@Slf4j
@RestController
@RequestMapping("/CommissionExpected")
@Tag(name = "预计入账接口")
......@@ -49,6 +59,10 @@ public class ApiCommissionExpectedController {
private CommissionExpectedService commissionExpectedService;
@Resource
private PolicyService policyService;
@Resource
private PolicyFollowService policyFollowService;
@Resource
private ApiInsuranceReconciliationCompanyFeignClient companyFeignClient;
/**
* 批量新增预计入账
......@@ -269,11 +283,110 @@ public class ApiCommissionExpectedController {
if (!CollectionUtils.isEmpty(allExpectedIdList)) {
receivableReportPage = commissionExpectedService.receivableReportPage(reportPage, allExpectedIdList);
}
enrichReceivableReportWithCompanyName(receivableReportPage);
receivableReportPage = convertProductName(receivableReportPage);
// 组装返回结果
ReceivableReportResponse response = new ReceivableReportResponse();
response.setStatisticsVO(statisticsVO);
response.setPage(receivableReportPage);
return Result.success(response);
}
public IPage<ReceivableReportVO> convertProductName(IPage<ReceivableReportVO> receivableReportPage) {
if (!org.springframework.util.CollectionUtils.isEmpty(receivableReportPage.getRecords())) {
List<String> policyNoList = receivableReportPage.getRecords().stream().map(ReceivableReportVO::getPolicyNo).collect(Collectors.toList());
List<PolicyFollow> policyFollowList = new ArrayList<>();
if (!org.springframework.util.CollectionUtils.isEmpty(policyNoList)) {
policyFollowList = policyFollowService.lambdaQuery()
.in(PolicyFollow::getPolicyNo, policyNoList)
.list();
}
Map<String, PolicyFollow> policyFollowMap = policyFollowList.stream()
.collect(Collectors.toMap(PolicyFollow::getPolicyNo, Function.identity()));
List<ReceivableReportVO> voList = receivableReportPage.getRecords().stream().map(vo -> {
PolicyFollow policyFollow= policyFollowMap.get(vo.getPolicyNo());
if (policyFollow != null) {
vo.setProductName(policyFollow.getProductName());
vo.setProductLaunchBizId(policyFollow.getProductLaunchBizId());
}
return vo;
}).collect(Collectors.toList());
receivableReportPage.setRecords(voList);
}
return receivableReportPage;
}
private void enrichReceivableReportWithCompanyName(IPage<ReceivableReportVO> page) {
if (page == null || CollectionUtils.isEmpty(page.getRecords())) {
return;
}
// 收集所有非空的对账公司 bizId(去重)
List<String> bizIdList = page.getRecords().stream()
.map(ReceivableReportVO::getReconciliationCompanyBizId)
.filter(StringUtils::isNotBlank)
.distinct()
.collect(Collectors.toList());
if (bizIdList.isEmpty()) {
return;
}
// 调用 Feign 批量查询对账公司信息
ApiInsuranceReconciliationCompanyPageRequest request = new ApiInsuranceReconciliationCompanyPageRequest();
request.setReconciliationCompanyBizIdList(bizIdList);
request.setPageNo(1);
request.setPageSize(bizIdList.size());
Result result = companyFeignClient.page(request);
List<ApiInsuranceReconciliationCompanyPageResponse> companyList = extractCompanyListFromResult(result);
if (companyList.isEmpty()) {
return;
}
// 构建 bizId -> name 映射
Map<String, String> nameMap = companyList.stream()
.filter(c -> StringUtils.isNotBlank(c.getReconciliationCompanyBizId()))
.collect(Collectors.toMap(
ApiInsuranceReconciliationCompanyPageResponse::getReconciliationCompanyBizId,
ApiInsuranceReconciliationCompanyPageResponse::getName,
(v1, v2) -> v1 // 重复时保留第一个
));
// 回填名称
page.getRecords().forEach(vo -> {
if (StringUtils.isNotBlank(vo.getReconciliationCompanyBizId())) {
String name = nameMap.get(vo.getReconciliationCompanyBizId());
if (StringUtils.isNotBlank(name) && !"CSF".equals(name)) {
vo.setReconciliationCompany(name);
}
}
});
}
private List<ApiInsuranceReconciliationCompanyPageResponse> extractCompanyListFromResult(Result result) {
if (result == null || result.getCode() != 200 || result.getData() == null) {
return Collections.emptyList();
}
Object data = result.getData();
try {
// 将 data 转为 JSON 字符串再解析为 Map,以便提取 records
Map<String, Object> dataMap = JSON.parseObject(JSON.toJSONString(data), new TypeReference<Map<String, Object>>() {});
Object recordsObj = dataMap.get("records");
if (recordsObj instanceof List) {
List<?> recordsList = (List<?>) recordsObj;
List<ApiInsuranceReconciliationCompanyPageResponse> companyList = new ArrayList<>();
for (Object item : recordsList) {
// 将每个元素转换为目标类型
ApiInsuranceReconciliationCompanyPageResponse company = JSON.parseObject(
JSON.toJSONString(item),
ApiInsuranceReconciliationCompanyPageResponse.class
);
companyList.add(company);
}
return companyList;
}
} catch (Exception e) {
log.error("解析公司列表失败", e);
}
return Collections.emptyList();
}
}
......@@ -21,6 +21,7 @@ import com.yd.csf.api.dto.PolicyExcelDTO;
import com.yd.csf.api.dto.PolicyFollowDTO;
import com.yd.csf.api.listener.PolicyDataListener;
import com.yd.csf.api.service.ApiExpectedFortuneService;
import com.yd.csf.api.service.ApiPolicyFollowService;
import com.yd.csf.feign.request.expectedfortune.ApiGenerateExpectedFortuneRequest;
import com.yd.csf.feign.response.expectedfortune.ApiGenerateExpectedFortuneResponse;
import com.yd.csf.service.common.ErrorCode;
......@@ -45,6 +46,7 @@ import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
......@@ -86,9 +88,12 @@ public class ApiPolicyFollowController {
@Resource
private ApiInsuranceReconciliationCompanyFeignClient apiInsuranceReconciliationCompanyFeignClient;
@Resource
private ApiExpectedFortuneService apiExpectedFortuneService;
@Resource
private CommissionExpectedService commissionExpectedService;
@Resource
private ApiPolicyFollowService apiPolicyFollowService;
@Resource
private ApiExpectedFortuneService apiExpectedFortuneService;
@PostMapping("/upload/excel")
......@@ -506,6 +511,9 @@ public class ApiPolicyFollowController {
if (ObjectUtils.isEmpty(policyFollow.getReconciliationCompanyCode())) {
return Result.fail(ResultCode.NULL_ERROR.getCode(), "新单跟进记录中,reconciliationCompanyCode不能为空");
}
if (ObjectUtils.isEmpty(policyFollow.getReconciliationCompanyBizId())) {
return Result.fail(ResultCode.NULL_ERROR.getCode(), "新单跟进记录中,reconciliationCompanyBizId不能为空");
}
PolicyFollowStatusEnum currentStatusEnum = PolicyFollowStatusEnum.getEnumByValue(changePolicyFollowStatusRequest.getStatus());
// 修改为生效时需要校验、同步预计发佣
......@@ -541,12 +549,29 @@ public class ApiPolicyFollowController {
String token = request.getHeader("Authorization");
log.info("修改跟进状态获取token:{}", token);
// 同步:根据保单生成预计出账记录
generateExpectedFortuneSync(token, policyFollow.getPolicyNo());
execute(token, policyFollow.getPolicyNo());
}
return Result.success(true);
}
/**
* 异步处理
*
* @return
*/
public Result execute(String token, String policyNo) {
// 调用 ApiExpectedFortuneService 的 generateSyncWithLogAndRedis(同步版本,包含日志和Redis处理)
ApiGenerateExpectedFortuneRequest generateExpectedFortuneRequest = new ApiGenerateExpectedFortuneRequest();
generateExpectedFortuneRequest.setPolicyNo(policyNo);
log.info("生成预计发佣generateSyncWithLogAndRedis——>PolicyNo:{}", policyNo);
Result<ApiGenerateExpectedFortuneResponse> result = apiExpectedFortuneService.generateSyncWithLogAndRedis(generateExpectedFortuneRequest);
if (result != null && result.getCode() == 200) {
log.info("新单跟进-同步生成预计出账记录成功:保单号={}", policyNo);
}
return Result.success();
}
/**
* 新单跟进状态列表查询
*
* @param policyBizId
......@@ -687,26 +712,6 @@ public class ApiPolicyFollowController {
}
/**
* 同步生成预计出账记录
*
* @param token 认证Token
* @param policyNo 保单号
*/
private void generateExpectedFortuneSync(String token, String policyNo) {
// 设置ThreadLocal Token
FeignTokenInterceptor.setThreadLocalToken(token);
// 调用 ApiExpectedFortuneService 的 generateSyncWithLogAndRedis(同步版本,包含日志和Redis处理)
ApiGenerateExpectedFortuneRequest generateExpectedFortuneRequest = new ApiGenerateExpectedFortuneRequest();
generateExpectedFortuneRequest.setPolicyNo(policyNo);
log.info("生成预计发佣generateSyncWithLogAndRedis——>PolicyNo:{}", policyNo);
Result<ApiGenerateExpectedFortuneResponse> result = apiExpectedFortuneService.generateSyncWithLogAndRedis(generateExpectedFortuneRequest);
if (result != null && result.getCode() == 200) {
log.info("新单跟进-同步生成预计出账记录成功:保单号={}", policyNo);
}
}
/**
* 查询产品计划信息
*
* @param policyBizId 新单跟进业务ID
......
package com.yd.csf.api.service;
import com.yd.common.result.Result;
import org.springframework.scheduling.annotation.Async;
public interface ApiPolicyFollowService {
void generateExpectedFortuneSync(String token, String policyNo);
@Async("asyncQueryExecutor")
Result execute(String token, String policyNo);
}
......@@ -28,6 +28,7 @@ import com.yd.csf.service.dto.BeneficiaryDto;
import com.yd.csf.feign.dto.appointmentfile.ItineraryDto;
import com.yd.csf.service.model.*;
import com.yd.csf.service.service.*;
import com.yd.insurance.base.feign.client.insurancecompany.ApiInsuranceCompanyFeignClient;
import com.yd.oss.feign.client.ApiExcelFeignClient;
import com.yd.oss.feign.client.ApiPdfFeignClient;
import com.yd.oss.feign.enums.TemplateTypeEnum;
......@@ -94,6 +95,9 @@ public class ApiAppointmentFileServiceImpl implements ApiAppointmentFileService
private ApiProductLaunchFeignClient apiProductLaunchFeignClient;
@Autowired
private ApiInsuranceCompanyFeignClient apiInsuranceCompanyFeignClient;
@Autowired
private RedisUtil redisUtil;
/**
......@@ -386,12 +390,16 @@ public class ApiAppointmentFileServiceImpl implements ApiAppointmentFileService
response.setApiAppointmentInfoDto(apiAppointmentInfoDto);
//设置产品计划主信息
//调用 convertExcelPlanName 获取产品ID映射
List<ApiConvertExcelPlanNameDto> convertList = convertExcelPlanName(appointmentDto);
ApiProductPlanInfoDto apiProductPlanInfoDto = new ApiProductPlanInfoDto();
ApiProductPlanMainInfoDto apiProductPlanMainInfoDto = new ApiProductPlanMainInfoDto();
apiProductPlanMainInfoDto = ApiExcelImportAppointmentDto.buildApiProductPlanMainInfoDto(appointmentDto,apiProductPlanMainInfoDto,dictTypeResponses);
apiProductPlanInfoDto.setApiProductPlanMainInfoDto(apiProductPlanMainInfoDto);
//设置产品附加计划(附加险列表)
List<ApiProductPlanAdditionalInfoDto> apiProductPlanAdditionalInfoDtoList = ApiExcelImportAppointmentDto.buildApiProductPlanAdditionalInfoDto(appointmentDto.getAdditionalDtoList(),dictTypeResponses);
settingProductId(apiProductPlanMainInfoDto,apiProductPlanAdditionalInfoDtoList,convertList);
apiProductPlanInfoDto.setApiProductPlanMainInfoDto(apiProductPlanMainInfoDto);
apiProductPlanInfoDto.setApiProductPlanAdditionalInfoDtoList(apiProductPlanAdditionalInfoDtoList);
response.setApiProductPlanInfoDto(apiProductPlanInfoDto);
......@@ -425,37 +433,159 @@ public class ApiAppointmentFileServiceImpl implements ApiAppointmentFileService
}
}
public void settingProductId(ApiProductPlanMainInfoDto apiProductPlanMainInfoDto,
List<ApiProductPlanAdditionalInfoDto> apiProductPlanAdditionalInfoDtoList,
List<ApiConvertExcelPlanNameDto> convertList) {
if (!CollectionUtils.isEmpty(convertList)) {
ApiConvertExcelPlanNameDto convertDto = convertList.get(0); // 只有一个元素
// 2. 更新主计划信息中的 productLaunchBizId
if (StringUtils.isNotBlank(convertDto.getMainPlanId())) {
apiProductPlanMainInfoDto.setProductLaunchBizId(convertDto.getMainPlanId());
// 也可以将产品名称设置为原始名称(或转换后的名称)
apiProductPlanMainInfoDto.setProductLaunchMainName(convertDto.getMainPlanName());
}
// 3. 更新附加计划列表中的 productLaunchBizId(假设有附加险列表)
if (!CollectionUtils.isEmpty(apiProductPlanAdditionalInfoDtoList)) {
// 第一个附加险
if (apiProductPlanAdditionalInfoDtoList.size() >= 1 && StringUtils.isNotBlank(convertDto.getAddPlanId1())) {
apiProductPlanAdditionalInfoDtoList.get(0).setProductLaunchBizId(convertDto.getAddPlanId1());
apiProductPlanAdditionalInfoDtoList.get(0).setProductLaunchName(convertDto.getAddPlanName1());
}
// 第二个附加险
if (apiProductPlanAdditionalInfoDtoList.size() >= 2 && StringUtils.isNotBlank(convertDto.getAddPlanId2())) {
apiProductPlanAdditionalInfoDtoList.get(1).setProductLaunchBizId(convertDto.getAddPlanId2());
apiProductPlanAdditionalInfoDtoList.get(1).setProductLaunchName(convertDto.getAddPlanName2());
}
}
}
}
/**
* 远程调用feign-根据Excel解析的数据-转换产品计划名称和ID
* @param appointmentDto
* @return
*/
// public List<ApiConvertExcelPlanNameDto> convertExcelPlanName(ApiExcelImportAppointmentDto appointmentDto) {
// List<String> reqNameList = new ArrayList<>();
// if (StringUtils.isNotBlank(appointmentDto.getPlanProductName())){
// //主计划产品名称
// //繁转简
// reqNameList.add(ChineseTextConverter.traditionalToSimplified(appointmentDto.getPlanProductName()));
// //简转繁
// reqNameList.add(ChineseTextConverter.simplifiedToTraditional(appointmentDto.getPlanProductName()));
// }
// if (CollectionUtils.isEmpty(appointmentDto.getAdditionalDtoList())){
// for (ApiExcelImportAdditionalDto additionalDto : appointmentDto.getAdditionalDtoList()) {
// //附加计划产品名称
// //繁转简
// reqNameList.add(ChineseTextConverter.traditionalToSimplified(additionalDto.getAddProductName()));
// //简转繁
// reqNameList.add(ChineseTextConverter.simplifiedToTraditional(additionalDto.getAddProductName()));
// }
// }
// ApiProductLaunchPageRequest request = new ApiProductLaunchPageRequest();
// request.setNameList(reqNameList);
// Result<IPage<ApiProductLaunchPageResponse>> result = apiProductLaunchFeignClient.page(request);
// if (!Objects.isNull(result.getData()) && !CollectionUtils.isEmpty(result.getData().getRecords())) {
// List<ApiProductLaunchPageResponse> responses = result.getData().getRecords();
//
// }
// }
public List<ApiConvertExcelPlanNameDto> convertExcelPlanName(ApiExcelImportAppointmentDto appointmentDto) {
// 1. 收集所有需要查询的产品名称(去重)
Set<String> queryNameSet = new HashSet<>();
// 主计划名称
if (StringUtils.isNotBlank(appointmentDto.getPlanProductName())) {
queryNameSet.add(ChineseTextConverter.traditionalToSimplified(appointmentDto.getPlanProductName()));
queryNameSet.add(ChineseTextConverter.simplifiedToTraditional(appointmentDto.getPlanProductName()));
}
// 附加计划名称
if (!CollectionUtils.isEmpty(appointmentDto.getAdditionalDtoList())) {
for (ApiExcelImportAdditionalDto additionalDto : appointmentDto.getAdditionalDtoList()) {
if (StringUtils.isNotBlank(additionalDto.getAddProductName())) {
queryNameSet.add(ChineseTextConverter.traditionalToSimplified(additionalDto.getAddProductName()));
queryNameSet.add(ChineseTextConverter.simplifiedToTraditional(additionalDto.getAddProductName()));
}
}
}
// 如果没有需要查询的名称,直接返回空
if (queryNameSet.isEmpty()) {
return Collections.emptyList();
}
// 2. 调用 Feign 批量查询产品上架信息
ApiProductLaunchPageRequest pageRequest = new ApiProductLaunchPageRequest();
pageRequest.setTitleList(new ArrayList<>(queryNameSet));
// 设置分页参数,尽可能大一些以获取全部数据
pageRequest.setPageNo(1);
pageRequest.setPageSize(1000);
Result<IPage<ApiProductLaunchPageResponse>> result = apiProductLaunchFeignClient.page(pageRequest);
if (result == null || result.getData() == null || CollectionUtils.isEmpty(result.getData().getRecords())) {
log.warn("未找到匹配的产品计划,查询名称列表:{}", queryNameSet);
return Collections.emptyList();
}
// 3. 建立标题 -> 产品ID的映射(注意:标题可能因繁简不同而重复,这里使用原始返回的标题作为key)
Map<String, String> titleToIdMap = result.getData().getRecords().stream()
.filter(record -> StringUtils.isNotBlank(record.getTitle()))
.collect(Collectors.toMap(
ApiProductLaunchPageResponse::getTitle,
ApiProductLaunchPageResponse::getProductLaunchBizId,
(v1, v2) -> v1 // 如果标题重复,取第一个(实际不会重复)
));
// 4. 构建返回的 DTO
ApiConvertExcelPlanNameDto dto = new ApiConvertExcelPlanNameDto();
// 处理主计划
String mainPlanOriginal = appointmentDto.getPlanProductName();
if (StringUtils.isNotBlank(mainPlanOriginal)) {
dto.setMainPlanName(mainPlanOriginal);
// 优先用原始名称精确匹配,否则尝试用转换后的名称匹配
String mainId = titleToIdMap.get(mainPlanOriginal);
if (mainId == null) {
// 尝试繁体/简体转换后的名称
mainId = titleToIdMap.get(ChineseTextConverter.traditionalToSimplified(mainPlanOriginal));
if (mainId == null) {
mainId = titleToIdMap.get(ChineseTextConverter.simplifiedToTraditional(mainPlanOriginal));
}
}
dto.setMainPlanId(mainId);
// 设置查询时使用的名称列表(繁简体)
dto.setMainPlanNameList(Arrays.asList(
ChineseTextConverter.traditionalToSimplified(mainPlanOriginal),
ChineseTextConverter.simplifiedToTraditional(mainPlanOriginal)
));
}
// 处理附加计划(最多支持两个,根据 DTO 定义)
if (!CollectionUtils.isEmpty(appointmentDto.getAdditionalDtoList())) {
int size = appointmentDto.getAdditionalDtoList().size();
// 第一个附加计划
if (size >= 1) {
ApiExcelImportAdditionalDto add1 = appointmentDto.getAdditionalDtoList().get(0);
String addName1 = add1.getAddProductName();
dto.setAddPlanName1(addName1);
// 查找ID
String addId1 = titleToIdMap.get(addName1);
if (addId1 == null) {
addId1 = titleToIdMap.get(ChineseTextConverter.traditionalToSimplified(addName1));
if (addId1 == null) {
addId1 = titleToIdMap.get(ChineseTextConverter.simplifiedToTraditional(addName1));
}
}
dto.setAddPlanId1(addId1);
dto.setAddPlanName1List(Arrays.asList(
ChineseTextConverter.traditionalToSimplified(addName1),
ChineseTextConverter.simplifiedToTraditional(addName1)
));
}
// 第二个附加计划
if (size >= 2) {
ApiExcelImportAdditionalDto add2 = appointmentDto.getAdditionalDtoList().get(1);
String addName2 = add2.getAddProductName();
dto.setAddPlanName2(addName2);
String addId2 = titleToIdMap.get(addName2);
if (addId2 == null) {
addId2 = titleToIdMap.get(ChineseTextConverter.traditionalToSimplified(addName2));
if (addId2 == null) {
addId2 = titleToIdMap.get(ChineseTextConverter.simplifiedToTraditional(addName2));
}
}
dto.setAddPlanId2(addId2);
dto.setAddPlanName2List(Arrays.asList(
ChineseTextConverter.traditionalToSimplified(addName2),
ChineseTextConverter.simplifiedToTraditional(addName2)
));
}
// 如果超过两个,可以打印日志提示,但根据 DTO 设计只取前两个
if (size > 2) {
log.warn("附加计划数量超过2个,只处理前两个,总数:{}", size);
}
}
return Collections.singletonList(dto);
}
/**
......
......@@ -762,7 +762,7 @@ public class ApiAppointmentServiceImpl implements ApiAppointmentService {
// 同步转介人
savePolicyBroker(appointment.getFnaBizId(), policyBizId);
// 同步保存保单(产品计划)
savePolicy(productPlan, apiPolicyholderInfoDto, apiInsurantInfoDto, apiProductPlanMainInfoDto, policyBizId, policyTransfer);
savePolicy(productPlan, apiPolicyholderInfoDto, apiInsurantInfoDto, policyBizId, policyTransfer);
// 同步保存保单投保人
savePolicyPolicyholder(apiPolicyholderInfoDto, policyBizId);
// 同步保存保单受保人
......@@ -958,12 +958,9 @@ public class ApiAppointmentServiceImpl implements ApiAppointmentService {
private boolean savePolicy(ProductPlan productPlan,
ApiPolicyholderInfoDto apiPolicyholderInfoDto,
ApiInsurantInfoDto apiInsurantInfoDto,
ApiProductPlanMainInfoDto apiProductPlanMainInfoDto,
String policyBizId,
String policyTransfer
) {
// String appointmentBizId = apiProductPlanMainInfoDto.getAppointmentBizId();
String planBizId = apiProductPlanMainInfoDto.getPlanBizId();
if (productPlan == null) {
return false;
}
......@@ -973,7 +970,7 @@ public class ApiAppointmentServiceImpl implements ApiAppointmentService {
policy.setId(null);
policy.setPolicyBizId(policyBizId);
policy.setProductLaunchBizId(planBizId);
policy.setProductLaunchBizId(productPlan.getProductLaunchBizId());
policy.setStatus(PolicyStatusEnum.INFORCE.getItemValue());
// 投保人姓名
if (Objects.nonNull(apiPolicyholderInfoDto)) {
......
package com.yd.csf.api.service.impl;
import com.alibaba.fastjson.JSON;
import com.yd.common.constant.CodeGeneratorConstants;
import com.yd.common.enums.CommonEnum;
import com.yd.common.enums.ProjectEnum;
......@@ -368,6 +369,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
*/
@Override
public Result<List<AlgorithmResDto>> policyBrokerAlgorithm(AlgorithmDto algorithmDto) {
log.info("算法-计算-转介人(销售业务员)绑定的基本法类型(基本法项目列表)对应的积分值->入参:{}", JSON.toJSONString(algorithmDto));
List<AlgorithmResDto> algorithmResDtoList = new ArrayList<>();
//校验 - 转介人业务ID(客户端用户表唯一业务ID)不能为空
if (StringUtils.isBlank(algorithmDto.getBrokerBizId())) {
......@@ -377,6 +379,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
if (CollectionUtils.isEmpty(commissionRuleBindingList)) {
throw new BusinessException("获得积分的用户所绑定的基本法信息不存在");
}
log.info("执行获得积分的用户绑定的多个基本法类型 (一个基本法类型又有多个基本法项目)->入参:{}", JSON.toJSONString(commissionRuleBindingList));
//执行获得积分的用户绑定的多个基本法类型 (一个基本法类型又有多个基本法项目)
for (CommissionRuleBinding commissionRuleBinding : commissionRuleBindingList) {
algorithmDto.setRuleBizId(commissionRuleBinding.getRuleBizId());
......@@ -384,6 +387,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
//多个基本法类型执行结果列表汇总
algorithmResDtoList.addAll(result.getData());
}
log.info("算法-计算-转介人(销售业务员)绑定的基本法类型(基本法项目列表)对应的积分值->出参:{}", JSON.toJSONString(algorithmResDtoList));
return Result.success(algorithmResDtoList);
}
......@@ -393,6 +397,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
* @return
*/
public Result<List<AlgorithmResDto>> commissionRuleAlgorithm(AlgorithmDto algorithmDto) {
log.info("算法-计算-基本法类型->入参:{}", JSON.toJSONString(algorithmDto));
//校验 - 基本法配置表唯一业务ID不能为空
if (StringUtils.isBlank(algorithmDto.getRuleBizId())) {
throw new BusinessException("基本法配置表唯一业务ID不能为空");
......@@ -402,6 +407,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
if (CollectionUtils.isEmpty(ruleItemConfigList)) {
throw new BusinessException("基本法项目列表不存在");
}
log.info("查询基本法类型绑定的基本法项目列表 - 执行顺序,数值越小越先执行,用于控制佣金项目的计算顺序->出参:{}", JSON.toJSONString(algorithmDto));
List<AlgorithmResDto> algorithmResDtoList = new ArrayList<>();
//遍历基本法项目 - 计算对应值
for (RuleItemConfig ruleItemConfig : ruleItemConfigList) {
......@@ -418,9 +424,11 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
continue;
}
}
log.info("遍历基本法项目 - 计算对应值->入参:{}", JSON.toJSONString(ruleItemConfig));
algorithmDto.setRuleItemBizId(ruleItemConfig.getRuleItemBizId());
//算法-计算-基本法项目
Result<AlgorithmResDto> result = ruleItemAlgorithm(algorithmDto);
log.info("算法-计算-基本法项目->出参:{}", JSON.toJSONString(result));
AlgorithmResDto algorithmResDto = result.getData();
if (!Objects.isNull(algorithmResDto)) {
//基本法项目名称
......@@ -437,6 +445,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
* @return
*/
public Result<AlgorithmResDto> ruleItemAlgorithm(AlgorithmDto algorithmDto) {
log.info("算法-计算-基本法项目->入参:{}", JSON.toJSONString(algorithmDto));
//校验 - 基本法项目配置表唯一业务ID不能为空
if (StringUtils.isBlank(algorithmDto.getRuleItemBizId())) {
throw new BusinessException("基本法项目配置表唯一业务ID不能为空");
......@@ -446,11 +455,13 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
if (CollectionUtils.isEmpty(relObjectFormulaList)) {
throw new BusinessException("基本法项目和公式关系数据不存在");
}
log.info("查询对象公式关系 - 即基本法项目和公式关系数据->出参:{}", JSON.toJSONString(relObjectFormulaList));
RelObjectFormula relObjectFormula = relObjectFormulaList.get(0);
//公式配置表唯一业务ID
algorithmDto.setFormulaBizId(relObjectFormula.getFormulaBizId());
//算法-计算-公式
Result<AlgorithmResDto> result = calculationFormulaAlgorithm(algorithmDto);
log.info("算法-计算-公式->出参:{}", JSON.toJSONString(result));
AlgorithmResDto dto = result.getData();
dto.setRuleBizId(algorithmDto.getRuleBizId());
dto.setRuleItemBizId(algorithmDto.getRuleItemBizId());
......@@ -463,6 +474,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
* @return
*/
public Result<AlgorithmResDto> calculationFormulaAlgorithm(AlgorithmDto algorithmDto) {
log.info("算法-计算-公式->入参:{}", JSON.toJSONString(algorithmDto));
AlgorithmResDto resDto = new AlgorithmResDto();
//校验算法DTO入参
checkAlgorithmDto(algorithmDto);
......@@ -503,7 +515,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
BigDecimal result = evaluateFormula(calculationFormulaBizId, variableValues);
resDto.setCalculatedValue(result);
log.info("算法-计算-公式->出参参:{}", JSON.toJSONString(resDto));
//通过计算公式-计算变量绑定的SQL模板计算结果集合列表
// Result<List<SqlAlgorithmResultDto>> listResult = calculateSqlAlgorithmResultDtoList(calculationFormulaBizId,variableValues);
// resDto.setSqlAlgorithmResultDtoList(listResult.getData());
......@@ -654,6 +666,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
* @return
*/
public Result<List<VariableAlgorithmDto>> variableAlgorithm(AlgorithmDto algorithmDto) {
log.info("算法-计算-变量->入参:{}", JSON.toJSONString(algorithmDto));
//校验算法DTO入参
checkAlgorithmDto(algorithmDto);
//查询变量表列表信息
......@@ -663,6 +676,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
if (CollectionUtils.isEmpty(variableList)) {
throw new BusinessException("变量表列表信息不存在");
}
log.info("查询变量表列表信息->出参:{}", JSON.toJSONString(variableList));
List<VariableAlgorithmDto> variableAlgorithmDtoList = new ArrayList<>();
//遍历变量列表 - 计算对应的值
for (Variable variable : variableList) {
......@@ -698,7 +712,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
//执行 - 算法 - SQL模板
Result<List<SqlAlgorithmResultDto>> result = sqlAlgorithm(algorithmDto);
log.info("执行 - 算法 - SQL模板->出参:{}", JSON.toJSONString(result));
// 设置SQL模板计算结果列表
dto.setSqlAlgorithmResultDtoList(result.getData());
......@@ -722,6 +736,7 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
}
variableAlgorithmDtoList.add(dto);
}
log.info("算法-计算-变量->出参:{}", JSON.toJSONString(variableAlgorithmDtoList));
return Result.success(variableAlgorithmDtoList);
}
......@@ -750,13 +765,15 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
//构建SQL模板入参参数Map
Map<String, Object> paramMap = buildParamMap(algorithmDto);
log.info("执行SQL查询->入参sqlTemplate,{}",JSON.toJSONString(sqlTemplate));
log.info("执行SQL查询->入参paramMap,{}",JSON.toJSONString(paramMap));
//执行SQL查询
Object result = executeParameterizedQuery(sqlTemplate, paramMap);
log.info("执行SQL查询->出参,{}",JSON.toJSONString(result));
//将查询结果转换为 List<SqlAlgorithmResultDto>
List<SqlAlgorithmResultDto> resultDtoList = convertToSqlAlgorithmResultDto(result);
log.info("将查询结果转换为 List<SqlAlgorithmResultDto>->出参,{}",JSON.toJSONString(resultDtoList));
return Result.success(resultDtoList);
} catch (Exception e) {
......
......@@ -29,14 +29,8 @@ import com.yd.csf.service.dto.CommissionRuleBindingDto;
import com.yd.csf.service.dto.QueryPolicyAndBrokerDto;
import com.yd.csf.service.dto.QueryPolicyBrokerDto;
import com.yd.csf.service.enums.FortuneStatusEnum;
import com.yd.csf.service.model.CommissionRuleBinding;
import com.yd.csf.service.model.ExpectedFortune;
import com.yd.csf.service.model.Policy;
import com.yd.csf.service.model.PolicyBroker;
import com.yd.csf.service.service.ICommissionRuleBindingService;
import com.yd.csf.service.service.IExpectedFortuneService;
import com.yd.csf.service.service.PolicyBrokerService;
import com.yd.csf.service.service.PolicyService;
import com.yd.csf.service.model.*;
import com.yd.csf.service.service.*;
import com.yd.csf.service.vo.ExpectedFortuneExportDTO;
import com.yd.csf.service.vo.ExpectedFortuneStatisticsVO;
import com.yd.csf.service.vo.PayableReportVO;
......@@ -56,6 +50,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
......@@ -94,6 +89,8 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
private PolicyBrokerService policyBrokerService;
@Autowired
private ApiSysDictFeignClient apiSysDictFeignClient;
@Resource
private PolicyFollowService policyFollowService;
/**
* 生成预计发佣
......@@ -168,21 +165,21 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
throw new BusinessException("保单和转介人信息不存在");
}
//查询所有绑定基本法的业务员(客户端用户表用户), 计算业务员绑定的所有基本法对应的计算值, 新增积分明细和发佣记录
List<CommissionRuleBinding> commissionRuleBindingList = new ArrayList<>();
//根据租户ID和项目ID查询客户端用户ID列表
Result<List<String>> result = apiClientUserFeignClient.clientUserBizIdList(TenantEnum.YD.getTenantBizId(), ProjectEnum.CSF_MINI_PROGRAM.getProjectBizId());
if (!CollectionUtils.isEmpty(result.getData())) {
commissionRuleBindingList = iCommissionRuleBindingService.queryList(CommissionRuleBindingDto.builder()
.targetIdList(result.getData())
.build());
}
if (CollectionUtils.isEmpty(commissionRuleBindingList)) {
throw new BusinessException("绑定基本法数据不存在");
}
// //查询所有绑定基本法的业务员(客户端用户表用户), 计算业务员绑定的所有基本法对应的计算值, 新增积分明细和发佣记录
// List<CommissionRuleBinding> commissionRuleBindingList = new ArrayList<>();
// //根据租户ID和项目ID查询客户端用户ID列表
// Result<List<String>> result = apiClientUserFeignClient.clientUserBizIdList(TenantEnum.YD.getTenantBizId(), ProjectEnum.CSF_MINI_PROGRAM.getProjectBizId());
// if (!CollectionUtils.isEmpty(result.getData())) {
// commissionRuleBindingList = iCommissionRuleBindingService.queryList(CommissionRuleBindingDto.builder()
// .targetIdList(result.getData())
// .build());
// }
// if (CollectionUtils.isEmpty(commissionRuleBindingList)) {
// throw new BusinessException("绑定基本法数据不存在");
// }
//遍历保单转介人列表信息 -> 调用基本法算出预计发佣列表(同步执行)
executeSync(queryPolicyAndBrokerDtoList, commissionRuleBindingList, request.getPolicyNo());
executeSync(queryPolicyAndBrokerDtoList, request.getPolicyNo());
return Result.success(null, "生成预计发佣成功");
}
......@@ -336,18 +333,22 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
});
}
@Override
public Result executeSync(List<QueryPolicyAndBrokerDto> queryPolicyAndBrokerDtoList, List<CommissionRuleBinding> commissionRuleBindingList, String policyNo) {
return null;
}
/**
* 同步处理-> 遍历保单转介人列表信息 -> 调用基本法算出预计发佣列表
*
* @param queryPolicyAndBrokerDtoList
* @param commissionRuleBindingList
* @param policyNo
* @return
*/
public Result executeSync(List<QueryPolicyAndBrokerDto> queryPolicyAndBrokerDtoList,
List<CommissionRuleBinding> commissionRuleBindingList,
String policyNo) {
log.info("同步处理-> 遍历保单转介人列表信息 -> 调用基本法算出预计发佣列表->入参queryPolicyAndBrokerDtoList:{}",JSON.toJSONString(queryPolicyAndBrokerDtoList));
log.info("同步处理-> 遍历保单转介人列表信息 -> 调用基本法算出预计发佣列表->入参policyNo:{}",policyNo);
// 使用编程式事务,确保方法内的事务一致性
return transactionTemplate.execute(status -> {
try {
......@@ -357,6 +358,8 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
throw new BusinessException("保单的供款年期不存在");
}
List<CommissionRuleBinding> commissionRuleBindingList = brokerRelUserIdList(brokerDto);
log.info("同步处理-> 遍历保单转介人列表信息 -> 调用基本法算出预计发佣列表->commissionRuleBindingList:{}",JSON.toJSONString(commissionRuleBindingList));
for (int i = 1; i <= paymentTerm; i++) {
executeBilling(ExecuteBillingDto.builder()
.name(brokerDto.getBrokerName())
......@@ -364,6 +367,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
.issueNumber(i)
.build());
if (!CollectionUtils.isEmpty(commissionRuleBindingList)) {
for (CommissionRuleBinding binding : commissionRuleBindingList) {
executeReward(ExecuteBillingDto.builder()
.clientUserBizId(binding.getTargetId())
......@@ -374,6 +378,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
}
}
}
}
//批量设置应付款编号
updatePayableNoBatch(policyNo);
......@@ -404,6 +409,22 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
});
}
/**
* 查询和当前转介人相关关系(推荐,一级管理,二级管理,辅导)的客户端用户ID列表数据
* @param brokerDto
* @return
*/
public List<CommissionRuleBinding> brokerRelUserIdList(QueryPolicyAndBrokerDto brokerDto) {
List<CommissionRuleBinding> commissionRuleBindingList = new ArrayList<>();
List<String> userIdList = policyBrokerService.selectRelatedBrokerBizIds(brokerDto.getBrokerBizId());
if (!CollectionUtils.isEmpty(userIdList)) {
commissionRuleBindingList = iCommissionRuleBindingService.queryList(CommissionRuleBindingDto.builder()
.targetIdList(userIdList)
.build());
}
return commissionRuleBindingList;
}
private void updatePayableNoBatch(String policyNo) {
// 查询最新一条有 payableNo 记录
ExpectedFortune latest = iExpectedFortuneService.getOne(
......@@ -445,7 +466,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
//构造销售佣金基本法项目的顺序下标值执行
List<Integer> executionOrderList = new ArrayList<>();
executionOrderList.add(1);
log.info("执行获得积分用户的非销售佣金基本法项目->入参:{}",JSON.toJSONString(dto));
//执行获得积分用户的非销售佣金基本法项目
Result<List<AlgorithmResDto>> result = apiBasicLawCalculateService.policyBrokerAlgorithm(AlgorithmDto.builder()
.brokerBizId(brokerDto.getBrokerBizId())
......@@ -462,6 +483,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
.executionOrderList(executionOrderList)
.isNegateExecutionOrderList(true)
.build());
log.info("执行获得积分用户的非销售佣金基本法项目->出参:{}",JSON.toJSONString(result));
//生成保单预计发佣表记录 (非销售佣金基本法)
generateExpectedFortune(GenerateExpectedFortuneDto.builder()
......@@ -497,8 +519,8 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
return Result.success();
}
private static LocalDate calculateExpectedPayoutDate(LocalDate coolingOffEndDate, Integer issueNumber) {
return coolingOffEndDate.plusMonths(2).plusYears(issueNumber - 1);
private static LocalDate calculateExpectedPayoutDate(LocalDate effectiveDate, Integer issueNumber) {
return effectiveDate.plusMonths(2).plusYears(issueNumber - 1);
}
/**
......@@ -509,6 +531,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
*/
@Transactional(rollbackFor = Exception.class)
public Result executeBilling(ExecuteBillingDto dto) {
log.info("执行 - 销售佣金(销售佣金基本法)——>入参:{}", JSON.toJSONString(dto));
QueryPolicyAndBrokerDto brokerDto = dto.getPolicyAndBrokerDto();
//构造销售佣金基本法项目的顺序下标值执行
List<Integer> executionOrderList = new ArrayList<>();
......@@ -550,7 +573,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
//发佣类型 TODO
// .fortuneType()
//发佣日期
.payoutDate(calculateExpectedPayoutDate(brokerDto.getCoolingOffEndDate(), dto.getIssueNumber()))
.payoutDate(calculateExpectedPayoutDate(brokerDto.getEffectiveDate(), dto.getIssueNumber()))
//保单号
.policyNo(brokerDto.getPolicyNo())
//佣金发放状态 0=待出账 1=可出账 2=已出账
......@@ -573,6 +596,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
*/
@Transactional(rollbackFor = Exception.class)
public Result generateExpectedFortune(GenerateExpectedFortuneDto fortuneDto) {
log.info("生成保单预计发佣表记录——>入参:{}", JSON.toJSONString(fortuneDto));
List<ExpectedFortune> fortuneList = new ArrayList<>();
if (!CollectionUtils.isEmpty(fortuneDto.getAlgorithmResDtoList())) {
//获得积分业务员绑定的基本法列表对应计算值结果集合
......@@ -582,6 +606,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
//判空判0
continue;
}
log.info("生成保单预计发佣表记录——>入参algorithmResDto:{}", JSON.toJSONString(algorithmResDto));
PolicyBroker policyBroker = policyBrokerService.queryOne(QueryPolicyBrokerDto.builder()
.policyNo(fortuneDto.getPolicyNo())
.brokerBizId(fortuneDto.getBrokerBizId())
......@@ -650,6 +675,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
}
}
log.info("生成保单预计发佣表记录——>出参fortuneList:{}", JSON.toJSONString(fortuneList));
if (!CollectionUtils.isEmpty(fortuneList)) {
iExpectedFortuneService.saveOrUpdateBatch(fortuneList);
}
......@@ -838,6 +864,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
payableReportPage = iExpectedFortuneService.payableReportPage(reportPage, allFortuneIdList);
}
payableReportPage = convertPayableReportVO(payableReportPage);
// 组装返回结果
PayableReportResponse response = new PayableReportResponse();
response.setStatisticsVO(statisticsVO);
......@@ -845,6 +872,40 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
return Result.success(response);
}
public IPage<PayableReportVO> convertPayableReportVO(IPage<PayableReportVO> payableReportPage) {
if (!CollectionUtils.isEmpty(payableReportPage.getRecords())) {
List<String> policyNoList = payableReportPage.getRecords().stream().map(PayableReportVO::getPolicyNo).collect(Collectors.toList());
List<Policy> policyList = new ArrayList<>();
List<PolicyFollow> policyFollowList = new ArrayList<>();
if (!CollectionUtils.isEmpty(policyNoList)) {
policyList = policyService.lambdaQuery()
.in(Policy::getPolicyNo, policyNoList)
.list();
policyFollowList = policyFollowService.lambdaQuery()
.in(PolicyFollow::getPolicyNo, policyNoList)
.list();
}
Map<String, Policy> policyMap = policyList.stream()
.collect(Collectors.toMap(Policy::getPolicyNo, Function.identity()));
Map<String, PolicyFollow> policyFollowMap = policyFollowList.stream()
.collect(Collectors.toMap(PolicyFollow::getPolicyNo, Function.identity()));
List<PayableReportVO> voList = payableReportPage.getRecords().stream().map(vo -> {
Policy policy = policyMap.get(vo.getPolicyNo());
PolicyFollow policyFollow= policyFollowMap.get(vo.getPolicyNo());
if (policy != null) {
vo.setPolicyCurrency(policy.getCurrency());
}
if (policyFollow != null) {
vo.setProductName(policyFollow.getProductName());
vo.setProductLaunchBizId(policyFollow.getProductLaunchBizId());
}
return vo;
}).collect(Collectors.toList());
payableReportPage.setRecords(voList);
}
return payableReportPage;
}
/**
* 创建应付款编号 应付款类型-CSF-年份后两位-6位数字(不重复)
*
......
package com.yd.csf.api.service.impl;
import com.yd.common.result.Result;
import com.yd.csf.api.service.ApiExpectedFortuneService;
import com.yd.csf.api.service.ApiPolicyFollowService;
import com.yd.csf.feign.request.expectedfortune.ApiGenerateExpectedFortuneRequest;
import com.yd.csf.feign.response.expectedfortune.ApiGenerateExpectedFortuneResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Slf4j
@Service
public class ApiPolicyFollowServiceImpl implements ApiPolicyFollowService {
@Autowired
private ApplicationContext applicationContext;
private ApiPolicyFollowService getSelf() {
return applicationContext.getBean(ApiPolicyFollowService.class);
}
@Resource
private ApiExpectedFortuneService apiExpectedFortuneService;
/**
* 同步生成预计出账记录
*
* @param token 认证Token
* @param policyNo 保单号
*/
@Override
public void generateExpectedFortuneSync(String token, String policyNo) {
// 设置ThreadLocal Token
// FeignTokenInterceptor.setThreadLocalToken(token);
getSelf().execute(token,policyNo);
}
/**
* 异步处理
*
* @return
*/
@Override
@Async("commonAsyncExecutor")
public Result execute(String token, String policyNo) {
// 调用 ApiExpectedFortuneService 的 generateSyncWithLogAndRedis(同步版本,包含日志和Redis处理)
ApiGenerateExpectedFortuneRequest generateExpectedFortuneRequest = new ApiGenerateExpectedFortuneRequest();
generateExpectedFortuneRequest.setPolicyNo(policyNo);
log.info("生成预计发佣generateSyncWithLogAndRedis——>PolicyNo:{}", policyNo);
Result<ApiGenerateExpectedFortuneResponse> result = apiExpectedFortuneService.generateSyncWithLogAndRedis(generateExpectedFortuneRequest);
if (result != null && result.getCode() == 200) {
log.info("新单跟进-同步生成预计出账记录成功:保单号={}", policyNo);
}
return Result.success();
}
}
......@@ -144,6 +144,18 @@ public class ApiExpectedFortunePageResponse {
private String currency;
/**
* 默认结算汇率
*/
@Schema(description = "默认结算汇率")
private BigDecimal defaultExchangeRate;
/**
* 港币预计出账金额
*/
@Schema(description = "港币预计出账金额")
private BigDecimal hkdAmount;
/**
* 出账状态
*/
@Schema(description = "出账状态 0=待出账 1=可出帐,待检核 2=完成出账 3=部分出账 4=保留 5=已失效 6=可出账, 已检核 7=未找到当前预计出账对应的来佣 字典值: csf_expected_fortune_status")
......
......@@ -2,6 +2,9 @@ package com.yd.csf.service.dao;
import com.yd.csf.service.model.PolicyBroker;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author Zhang Jianan
......@@ -11,6 +14,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
public interface PolicyBrokerMapper extends BaseMapper<PolicyBroker> {
List<String> selectRelatedBrokerBizIds(@Param("clientUserId") String clientUserId);
}
......
......@@ -93,6 +93,11 @@ public class Policy implements Serializable {
private String insured;
/**
* 保障年期
*/
private String guaranteePeriod;
/**
* 保额
*/
private Object sumInsured;
......@@ -113,6 +118,11 @@ public class Policy implements Serializable {
private BigDecimal paymentPremium;
/**
* 总保费
*/
private BigDecimal totalPaymentPremium;
/**
* 保单状态
*/
private String status;
......
......@@ -18,4 +18,6 @@ public interface PolicyBrokerService extends IService<PolicyBroker> {
PolicyBroker queryOne(QueryPolicyBrokerDto dto);
void removeByPolicyBizId(String policyBizId);
List<String> selectRelatedBrokerBizIds(String clientUserId);
}
......@@ -2,6 +2,7 @@ package com.yd.csf.service.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
......@@ -22,11 +23,15 @@ import com.yd.csf.service.enums.CommissionExpectedStatusEnum;
import com.yd.csf.service.model.Commission;
import com.yd.csf.service.model.CommissionExpected;
import com.yd.csf.service.model.Policy;
import com.yd.csf.service.model.PolicyFollow;
import com.yd.csf.service.service.*;
import com.yd.csf.service.dao.CommissionExpectedMapper;
import com.yd.csf.service.vo.CommissionExpectedStatisticsVO;
import com.yd.csf.service.vo.CommissionExpectedVO;
import com.yd.csf.service.vo.ReceivableReportVO;
import com.yd.insurance.base.feign.client.insurancereconciliationcompany.ApiInsuranceReconciliationCompanyFeignClient;
import com.yd.insurance.base.feign.request.insurancereconciliationcompany.ApiInsuranceReconciliationCompanyPageRequest;
import com.yd.insurance.base.feign.response.insurancereconciliationcompany.ApiInsuranceReconciliationCompanyPageResponse;
import com.yd.product.feign.client.announcementcommissionratio.ApiAnnouncementCommissionRatioFeignClient;
import com.yd.product.feign.client.expectedspecies.ApiExpectedSpeciesFeignClient;
import com.yd.product.feign.request.expectedspecies.ApiExpectedSpeciesListRequest;
......@@ -47,6 +52,8 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
......@@ -79,6 +86,8 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
private RedisUtil redisUtil;
@Resource
private ApiExchangeRateFeignClient apiExchangeRateFeignClient;
@Resource
private ApiInsuranceReconciliationCompanyFeignClient companyFeignClient;
// 用于对象转换的ObjectMapper
private static final ObjectMapper objectMapper = new ObjectMapper();
......@@ -92,6 +101,7 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
return CommissionExpectedVOPage;
}
// 关联查询保单信息
Set<String> policyNoSet = CommissionExpectedList.stream().map(CommissionExpected::getPolicyNo).collect(Collectors.toSet());
QueryWrapper<Policy> queryWrapper = new QueryWrapper<Policy>();
......@@ -100,6 +110,15 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
List<Policy> policyList = policyService.list(queryWrapper);
Map<String, Policy> policyMap = policyList.stream().collect(Collectors.toMap(Policy::getPolicyNo, a -> a, (oldValue, newValue) -> newValue));
List<String> policyNoList = policyList.stream().map(Policy::getPolicyNo).collect(Collectors.toList());
List<PolicyFollow> policyFollowList = new ArrayList<>();
if (!org.springframework.util.CollectionUtils.isEmpty(policyNoList)) {
policyFollowList = policyFollowService.lambdaQuery()
.in(PolicyFollow::getPolicyNo, policyNoList)
.list();
}
Map<String, PolicyFollow> policyFollowMap = policyFollowList.stream()
.collect(Collectors.toMap(PolicyFollow::getPolicyNo, Function.identity()));
// 填充信息
List<CommissionExpectedVO> CommissionExpectedVOList = CommissionExpectedList.stream().map(commissionExpected -> {
CommissionExpectedVO commissionExpectedVO = CommissionExpectedVO.objToVo(commissionExpected);
......@@ -112,12 +131,93 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
commissionExpectedVO.setReconciliationCompany(policy.getReconciliationCompany());
commissionExpectedVO.setPolicyCurrency(policy.getCurrency());
}
PolicyFollow policyFollow= policyFollowMap.get(commissionExpected.getPolicyNo());
if (policyFollow != null) {
commissionExpectedVO.setProductName(policyFollow.getProductName());
commissionExpectedVO.setProductLaunchBizId(policyFollow.getProductLaunchBizId());
}
return commissionExpectedVO;
}).collect(Collectors.toList());
CommissionExpectedVOPage.setRecords(CommissionExpectedVOList);
enrichReceivableReportWithCompanyName(CommissionExpectedVOPage);
return CommissionExpectedVOPage;
}
private void enrichReceivableReportWithCompanyName(IPage<CommissionExpectedVO> page) {
if (page == null || CollectionUtils.isEmpty(page.getRecords())) {
return;
}
// 收集所有非空的对账公司 bizId(去重)
List<String> bizIdList = page.getRecords().stream()
.map(CommissionExpectedVO::getReconciliationCompanyBizId)
.filter(StringUtils::isNotBlank)
.distinct()
.collect(Collectors.toList());
if (bizIdList.isEmpty()) {
return;
}
// 调用 Feign 批量查询对账公司信息
ApiInsuranceReconciliationCompanyPageRequest request = new ApiInsuranceReconciliationCompanyPageRequest();
request.setReconciliationCompanyBizIdList(bizIdList);
request.setPageNo(1);
request.setPageSize(bizIdList.size());
Result result = companyFeignClient.page(request);
List<ApiInsuranceReconciliationCompanyPageResponse> companyList = extractCompanyListFromResult(result);
if (companyList.isEmpty()) {
return;
}
// 构建 bizId -> name 映射
Map<String, String> nameMap = companyList.stream()
.filter(c -> StringUtils.isNotBlank(c.getReconciliationCompanyBizId()))
.collect(Collectors.toMap(
ApiInsuranceReconciliationCompanyPageResponse::getReconciliationCompanyBizId,
ApiInsuranceReconciliationCompanyPageResponse::getName,
(v1, v2) -> v1 // 重复时保留第一个
));
// 回填名称
page.getRecords().forEach(vo -> {
if (StringUtils.isNotBlank(vo.getReconciliationCompanyBizId())) {
String name = nameMap.get(vo.getReconciliationCompanyBizId());
if (StringUtils.isNotBlank(name) && !"CSF".equals(name)) {
vo.setReconciliationCompany(name);
}
}
});
}
private List<ApiInsuranceReconciliationCompanyPageResponse> extractCompanyListFromResult(Result result) {
if (result == null || result.getCode() != 200 || result.getData() == null) {
return Collections.emptyList();
}
Object data = result.getData();
try {
// 将 data 转为 JSON 字符串再解析为 Map,以便提取 records
Map<String, Object> dataMap = JSON.parseObject(JSON.toJSONString(data), new com.alibaba.fastjson.TypeReference<Map<String, Object>>() {});
Object recordsObj = dataMap.get("records");
if (recordsObj instanceof List) {
List<?> recordsList = (List<?>) recordsObj;
List<ApiInsuranceReconciliationCompanyPageResponse> companyList = new ArrayList<>();
for (Object item : recordsList) {
// 将每个元素转换为目标类型
ApiInsuranceReconciliationCompanyPageResponse company = JSON.parseObject(
JSON.toJSONString(item),
ApiInsuranceReconciliationCompanyPageResponse.class
);
companyList.add(company);
}
return companyList;
}
} catch (Exception e) {
log.error("解析公司列表失败", e);
}
return Collections.emptyList();
}
/**
* 校验数据
*
......@@ -287,10 +387,6 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
commissionExpected.setPaidRatio(BigDecimal.ZERO);
// 校验参数
validCommissionExpected(commissionExpected, true);
// 结算汇率初始值为 1
commissionExpected.setDefaultExchangeRate(BigDecimal.valueOf(1));
// 查询默认结算汇率
commissionExpected.setDefaultExchangeRate(queryDefaultExchangeRate(addDto.getCurrency()));
// 预计总金额
if ("R".equals(addDto.getCommissionBizType())) {
......@@ -298,9 +394,17 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
if (ObjectUtils.isEmpty(policy)) {
throw new BusinessException(ResultCode.PARAMS_ERROR.getCode(), "保单号为" + addDto.getPolicyNo() + "的保单不存在");
}
// 结算汇率初始值为 1
commissionExpected.setDefaultExchangeRate(BigDecimal.valueOf(1));
// 查询默认结算汇率
commissionExpected.setDefaultExchangeRate(queryExchangeRateByFeign(policy.getCurrency(), addDto.getCurrency()));
// 查询港币汇率
BigDecimal exchangeRateHkd = queryExchangeRateByFeign(addDto.getCurrency(), "HKD");
// 转换为港币金额
BigDecimal expectedAmount = policy.getPaymentPremium()
.multiply(commissionExpected.getCommissionRatio())
.multiply(commissionExpected.getDefaultExchangeRate())
.multiply(exchangeRateHkd)
.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);
commissionExpected.setExpectedAmount(expectedAmount);
......@@ -368,21 +472,6 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
}
}
private BigDecimal queryDefaultExchangeRate(String currency) {
if ("HKD".equalsIgnoreCase(currency)) {
return BigDecimal.valueOf(1);
}
Result<List<GetDictItemListByDictTypeResponse>> result = apiSysDictFeignClient.getDictItemListByDictType("csf_exchange_rate_hkd");
if (CollectionUtils.isNotEmpty(result.getData())) {
for (GetDictItemListByDictTypeResponse dictItem : result.getData()) {
if (StringUtils.equalsIgnoreCase(dictItem.getItemLabel(), currency)) {
return new BigDecimal(dictItem.getItemValue());
}
}
}
return BigDecimal.ONE;
}
@Override
public Boolean deleteCommissionExpected(String commissionExpectedBizId) {
if (StringUtils.isBlank(commissionExpectedBizId)) {
......@@ -408,8 +497,7 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
validCommissionExpected(commissionExpected, false);
// 转换为实体类
BeanUtils.copyProperties(commissionExpectedUpdateRequest, commissionExpected, "id", "commissionBizId");
// 更新默认结算汇率
commissionExpected.setDefaultExchangeRate(queryDefaultExchangeRate(commissionExpectedUpdateRequest.getCurrency()));
// 更新预计入账金额
if ("R".equals(commissionExpectedUpdateRequest.getCommissionBizType())) {
// 查询保单
......@@ -417,10 +505,16 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
if (policy == null) {
throw new BusinessException(ResultCode.NULL_ERROR.getCode(), "保单不存在");
}
// 更新默认结算汇率
commissionExpected.setDefaultExchangeRate(queryExchangeRateByFeign(policy.getCurrency(), commissionExpectedUpdateRequest.getCurrency()));
// 查询港币汇率
BigDecimal exchangeRateHkd = queryExchangeRateByFeign(commissionExpectedUpdateRequest.getCurrency(), "HKD");
// 转换为港币金额
commissionExpected.setExpectedAmount(
policy.getPaymentPremium()
.multiply(commissionExpectedUpdateRequest.getCommissionRatio())
.multiply(commissionExpected.getDefaultExchangeRate())
.multiply(exchangeRateHkd)
.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP)
);
commissionExpected.setPremium(policy.getPaymentPremium());
......@@ -514,7 +608,7 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
// 匹配规格并获取不匹配的条件
MatchResult matchResult = matchExpectedSpecies(
expectedSpeciesList, paymentTerm, reconciliationCompanyBizId,
policyHolderAge, paymentPremium);
policyHolderAge, paymentPremium, effectiveDate);
if (matchResult.getMatchedList().isEmpty()) {
String errorMsg = matchResult.getUnmatchedConditions().isEmpty()
......@@ -611,7 +705,7 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
*/
private MatchResult matchExpectedSpecies(List<ApiExpectedSpeciesListResponse> expectedSpeciesList,
String paymentTerm, String reconciliationCompanyId,
Integer policyHolderAge, BigDecimal paymentPremium) {
Integer policyHolderAge, BigDecimal paymentPremium, Date effectiveDate) {
List<String> unmatchedConditions = new ArrayList<>();
List<ApiExpectedSpeciesListResponse> currentList = expectedSpeciesList;
......@@ -644,9 +738,22 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
i -> containsValue(i.getSpeciesJson(), "PREMIUM", Convert.toStr(paymentPremium)),
unmatchedConditions, "保费[" + paymentPremium + "]");
// 检查生效日期
currentList = filterAndCheck(currentList,
i -> isEffective(i.getEffectiveStart(), i.getEffectiveEnd(), effectiveDate),
unmatchedConditions, "生效日期[" + effectiveDate + "]");
if (unmatchedConditions.size() > 0) {
return new MatchResult(Collections.emptyList(), unmatchedConditions);
}
return new MatchResult(currentList, unmatchedConditions);
}
private boolean isEffective(LocalDateTime effectiveStart, LocalDateTime effectiveEnd, Date effectiveDate) {
LocalDateTime effectiveDateLocal = effectiveDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
return effectiveDateLocal.isAfter(effectiveStart) && effectiveDateLocal.isBefore(effectiveEnd);
}
/**
* 过滤列表并检查是否为空
*
......@@ -751,7 +858,7 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
if ("R".equals(commissionBizType)) {
// 关联保单应收单:保费 × 佣金比例 × 默认结算汇率 ÷ 100
BigDecimal exchangeRate = defaultExchangeRate;
BigDecimal exchangeRateHkd = queryDefaultExchangeRate(currency);
BigDecimal exchangeRateHkd = queryExchangeRateByFeign(currency, "HKD");
if (exchangeRate == null) {
// 这里获取保单币种对预计来佣的结算币种的默认汇率
exchangeRate = queryExchangeRateByFeign(policyCurrency, currency);
......@@ -765,7 +872,7 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
// 非关联保单应收单:金额 × 默认结算汇率
BigDecimal exchangeRate = defaultExchangeRate;
if (exchangeRate == null) {
exchangeRate = queryDefaultExchangeRate(currency);
exchangeRate = queryExchangeRateByFeign(policyCurrency, currency);
}
return amount.multiply(exchangeRate);
}
......@@ -778,6 +885,9 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
* @return 汇率
*/
private BigDecimal queryExchangeRateByFeign(String policyCurrency, String currency) {
if (policyCurrency.equalsIgnoreCase(currency)) {
return BigDecimal.valueOf(1);
}
// 调用Feign客户端查询汇率
Result<BigDecimal> result = apiExchangeRateFeignClient.getExchangeRate(policyCurrency, currency, "");
if (result != null && result.getData() != null) {
......@@ -787,20 +897,20 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
}
/**
* 根据保单冷静期到期日和佣金期数计算预计来佣日期,首期为冷静期到期日的2个月,后续期数为首期的次年
* 根据保单生效日和佣金期数计算预计来佣日期,首期为生效日的1个月,后续期数为首期的次年
* @param endPeriod 佣金期数
* @param coolingOffEndDate 保单冷静期到期
* @param effectiveDate 保单生效
* @return 预计来佣日期
*/
private Date calculateCommissionDate(String endPeriod, Date coolingOffEndDate) {
if (coolingOffEndDate == null || StringUtils.isBlank(endPeriod)) {
private Date calculateCommissionDate(String endPeriod, Date effectiveDate) {
if (effectiveDate == null || StringUtils.isBlank(endPeriod)) {
return null;
}
Calendar cal = Calendar.getInstance();
cal.setTime(coolingOffEndDate);
// 首期:保单冷静期到期日的2个月
cal.add(Calendar.MONTH, 2);
cal.setTime(effectiveDate);
// 首期:保单生效日的1个月
cal.add(Calendar.MONTH, 1);
Integer period = Convert.toInt(endPeriod);
if (period == null || period <= 0) {
......
......@@ -9,8 +9,10 @@ import com.yd.csf.feign.response.expectedfortune.ApiExpectedFortunePageResponse;
import com.yd.csf.service.model.ExpectedFortune;
import com.yd.csf.service.dao.ExpectedFortuneMapper;
import com.yd.csf.service.model.Policy;
import com.yd.csf.service.model.PolicyFollow;
import com.yd.csf.service.service.IExpectedFortuneService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yd.csf.service.service.PolicyFollowService;
import com.yd.csf.service.service.PolicyService;
import com.yd.csf.service.vo.ExpectedFortuneStatisticsVO;
import com.yd.csf.service.vo.PayableReportVO;
......@@ -37,6 +39,9 @@ public class ExpectedFortuneServiceImpl extends ServiceImpl<ExpectedFortuneMappe
@Resource
private PolicyService policyService;
@Resource
private PolicyFollowService policyFollowService;
@Override
public IPage<ApiExpectedFortunePageResponse> page(Page<ApiExpectedFortunePageResponse> page,
ApiExpectedFortunePageRequest request) {
......@@ -87,19 +92,28 @@ public class ExpectedFortuneServiceImpl extends ServiceImpl<ExpectedFortuneMappe
List<Policy> policyList = policyService.lambdaQuery()
.in(Policy::getPolicyNo, expectedFortuneList.stream().map(ExpectedFortune::getPolicyNo).collect(Collectors.toList()))
.list();
List<PolicyFollow> policyFollowList = policyFollowService.lambdaQuery()
.in(PolicyFollow::getPolicyNo, expectedFortuneList.stream().map(ExpectedFortune::getPolicyNo).collect(Collectors.toList()))
.list();
Map<String, Policy> policyMap = policyList.stream()
.collect(Collectors.toMap(Policy::getPolicyNo, Function.identity()));
Map<String, PolicyFollow> policyFollowMap = policyFollowList.stream()
.collect(Collectors.toMap(PolicyFollow::getPolicyNo, Function.identity()));
List<ApiExpectedFortunePageResponse> expectedFortuneVOList = expectedFortuneList.stream().map(expectedFortune -> {
ApiExpectedFortunePageResponse expectedFortuneVO = new ApiExpectedFortunePageResponse();
BeanUtils.copyProperties(expectedFortune, expectedFortuneVO);
Policy policy = policyMap.get(expectedFortune.getPolicyNo());
PolicyFollow policyFollow= policyFollowMap.get(expectedFortune.getPolicyNo());
if (policy != null) {
expectedFortuneVO.setInsuranceCompany(policy.getInsuranceCompany());
expectedFortuneVO.setProductName(policy.getProductName());
expectedFortuneVO.setPremium(policy.getPaymentPremium());
}
if (policyFollow != null) {
expectedFortuneVO.setProductName(policyFollow.getProductName());
expectedFortuneVO.setProductLaunchBizId(policyFollow.getProductLaunchBizId());
}
return expectedFortuneVO;
}).collect(Collectors.toList());
return expectedFortuneVOList;
......
......@@ -49,6 +49,11 @@ public class PolicyBrokerServiceImpl extends ServiceImpl<PolicyBrokerMapper, Pol
.eq(PolicyBroker::getPolicyBizId, policyBizId)
);
}
@Override
public List<String> selectRelatedBrokerBizIds(String clientUserId) {
return baseMapper.selectRelatedBrokerBizIds(clientUserId);
}
}
......
package com.yd.csf.service.service.impl;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
......@@ -496,16 +499,28 @@ public class PolicyFollowServiceImpl extends ServiceImpl<PolicyFollowMapper, Pol
if (policy == null) {
throw new BusinessException(ErrorCode.NOT_FOUND_ERROR.getCode(), "policy不存在");
}
BigDecimal paymentPremium = policy.getPaymentPremium();
if (paymentPremium == null) {
throw new BusinessException("期交保费不能为空");
}
Object paymentTerm = policy.getPaymentTerm();
if (paymentTerm == null) {
throw new BusinessException("供款期数不能为空");
}
policy.setPolicyNo(policyFollow.getPolicyNo());
policy.setPolicyHolderAge(calculatePolicyHolderAge(policyFollow.getCustomerBizId()));
policy.setCoolingOffEndDate(policyFollow.getCoolingOffEndDate());
policy.setReconciliationCompanyBizId(policyFollow.getReconciliationCompanyBizId());
policy.setReconciliationCompanyCode(policyFollow.getReconciliationCompanyCode());
// 更新保单状态为生效
policy.setStatus(PolicyStatusEnum.INFORCE.getItemValue());
// 手动映射不同名的字段
policy.setPaymentPremium(policyFollow.getInitialPremium());
policy.setCurrency(policyFollow.getPolicyCurrency());
policy.setPaymentTerm(policyFollow.getIssueNumber());
policy.setTotalPaymentPremium(calculateTotalPaymentPremium(policy));
policy.setUnderwritingDate(changePolicyFollowStatusRequest.getUnderwritingDate());
policy.setEffectiveDate(changePolicyFollowStatusRequest.getEffectiveDate());
policy.setPolicyHolderAge(calculatePolicyHolderAge(policyFollow.getCustomerBizId()));
if (ObjectUtils.isEmpty(policy.getInsuranceCompany()) || ObjectUtils.isEmpty(policy.getInsuranceCompany())) {
// 获取保单产品信息,填充对账公司相关字段
......@@ -551,6 +566,13 @@ public class PolicyFollowServiceImpl extends ServiceImpl<PolicyFollowMapper, Pol
return true;
}
private BigDecimal calculateTotalPaymentPremium(Policy policy) {
BigDecimal paymentPremium = policy.getPaymentPremium();
Object paymentTerm = policy.getPaymentTerm();
// 计算总保费 = 每期保费 * 供款期数
return paymentPremium.multiply(Convert.toBigDecimal(paymentTerm)).setScale(4, RoundingMode.HALF_UP);
}
private Integer calculatePolicyHolderAge(String customerBizId) {
Customer customer = customerService.getByCustomerBizId(customerBizId);
if (customer == null) {
......
package com.yd.csf.service.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yd.common.enums.ResultCode;
......@@ -23,11 +21,7 @@ import com.yd.csf.service.service.PolicyService;
import com.yd.csf.service.dao.PolicyMapper;
import com.yd.csf.service.vo.PolicyVO;
import com.yd.product.feign.client.relprojectproductlaunch.ApiRelProjectProductLaunchFeignClient;
import com.yd.product.feign.request.productlaunch.ApiProductLaunchParameterPageRequest;
import com.yd.product.feign.request.relprojectproductlaunch.ApiRelProjectProductLaunchPageRequest;
import com.yd.product.feign.response.productlaunch.ApiAttributeSettingDto;
import com.yd.product.feign.response.relprojectproductlaunch.ApiRelProjectProductLaunchPageResponse;
import io.swagger.v3.core.util.Json;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
......@@ -37,6 +31,8 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
......@@ -114,12 +110,22 @@ public class PolicyServiceImpl extends ServiceImpl<PolicyMapper, Policy>
if (policy == null) {
throw new BusinessException(ResultCode.NULL_ERROR.getCode(), "保单不存在");
}
BigDecimal paymentPremium = policy.getPaymentPremium();
if (paymentPremium == null) {
throw new BusinessException("期交保费不能为空");
}
Object paymentTerm = policy.getPaymentTerm();
if (paymentTerm == null) {
throw new BusinessException("供款期数不能为空");
}
Date now = new Date();
// 保单信息
ApiProductPlanMainInfoDto apiProductPlanMainInfoDto = policyUpdateRequest.getApiProductPlanMainInfoDto();
if (apiProductPlanMainInfoDto != null) {
BeanUtils.copyProperties(apiProductPlanMainInfoDto, policy, "policyBizId", "id");
policy.setPaymentPremium(apiProductPlanMainInfoDto.getEachIssuePremium());
policy.setTotalPaymentPremium(calculateTotalPaymentPremium(apiProductPlanMainInfoDto));
policy.setIsPrepaid(apiProductPlanMainInfoDto.getIsPrepay());
policy.setUpdateTime(now);
// 更新保单
......@@ -150,6 +156,13 @@ public class PolicyServiceImpl extends ServiceImpl<PolicyMapper, Policy>
return true;
}
private BigDecimal calculateTotalPaymentPremium(ApiProductPlanMainInfoDto apiProductPlanMainInfoDto) {
// 计算总保费
return apiProductPlanMainInfoDto.getEachIssuePremium()
.multiply(new BigDecimal(apiProductPlanMainInfoDto.getPaymentFrequency()))
.setScale(4, RoundingMode.HALF_UP);
}
/**
* 查询列表
......
......@@ -89,6 +89,12 @@ public class PayableReportVO {
private String currency;
/**
* 保单币种
*/
@Schema(description = "保单币种")
private String policyCurrency;
/**
* 应出账金额(港币)
*/
@Schema(description = "应出账金额(港币)")
......
......@@ -31,6 +31,18 @@ public class ReceivableReportVO {
private String reconciliationCompany;
/**
* 对账公司Id
*/
@Schema(description = "对账公司Id")
private String reconciliationCompanyBizId;
/**
* 产品上架信息表唯一业务ID
*/
@Schema(description = "产品上架信息表唯一业务ID")
private String productLaunchBizId;
/**
* 入账期数(1=第一年; 2=第二年; 3=第三年; 4=第四年; 5=第五年)
*/
@Schema(description = "入账期数")
......
......@@ -70,6 +70,7 @@
null as receivableNo,
ce.policy_no as policyNo,
MAX(ce.reconciliation_company) as reconciliationCompany,
MAX(ce.reconciliation_company_biz_id) as reconciliationCompanyBizId,
ce.commission_period as commissionPeriod,
MAX(ce.total_period) as totalPeriod,
DATE_ADD(DATE_ADD(MAX(p.effective_date), INTERVAL 2 MONTH), INTERVAL (ce.commission_period - 1) YEAR) as commissionDate,
......@@ -87,7 +88,7 @@
then round((ifnull(sum(ce.expected_amount), 0) - ifnull(sum(ce.paid_amount), 0)) / ifnull(sum(ce.expected_amount), 0) * 100, 2)
else 0
end as unpaidRatio,
ifnull(avg(ce.default_exchange_rate), 0) as exchangeRate,
MAX(ce.default_exchange_rate) as exchangeRate,
MAX(p.insurance_company) as insuranceCompany,
MAX(p.product_name) as productName,
ifnull(avg(ce.premium), 0) as premium,
......@@ -110,6 +111,7 @@
ce.receivable_no as receivableNo,
ce.policy_no as policyNo,
ce.reconciliation_company as reconciliationCompany,
ce.reconciliation_company_biz_id as reconciliationCompanyBizId,
ce.commission_period as commissionPeriod,
ce.total_period as totalPeriod,
ce.commission_date as commissionDate,
......
......@@ -29,11 +29,11 @@
ifnull(sum(ef.hkd_amount),0) as totalExpectedAmount,
ifnull(sum(ef.paid_amount),0) as totalPaidAmount,
ifnull(sum(ef.unpaid_amount),0) as totalUnpaidAmount,
ifnull(sum(e.totalPremiumAmount),0) as totalPremiumAmount,
MAX(e.total_payment_premium) * MAX(ef.default_exchange_rate) as totalPremiumAmount,
count(distinct ef.policy_no) as totalPolicyCount
from expected_fortune ef
LEFT JOIN (
SELECT p.policy_no, SUM(p.payment_premium*p.payment_term) as totalPremiumAmount
SELECT p.policy_no, p.total_payment_premium
FROM policy p
GROUP BY policy_no
) e ON ef.policy_no = e.policy_no
......
......@@ -22,10 +22,51 @@
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
</resultMap>
<!-- 在PolicyBrokerMapper.xml里面写个SQL,通过传入的客户端用户ID字段,查询该客户端用户ID在三张关系表里面的,推荐人的客户端用户ID, 一级管理人客户端用户ID,二级管理人客户端用户ID,辅导人客户端用户ID,这些客户端用户ID整合返回List<String>客户端用户ID列表-->
<sql id="Base_Column_List">
id,policy_biz_id,policy_no,broker_name,broker_biz_id,gender,internal_code,
team,broker_ratio,team_biz_id,remark,is_deleted,creator_id,updater_id,
create_time,update_time
</sql>
<!-- 根据客户端用户ID查询关联的推荐人、管理人(一级、二级)、辅导人ID列表 -->
<select id="selectRelatedBrokerBizIds" parameterType="java.lang.String" resultType="java.lang.String">
SELECT DISTINCT related_user_id FROM (
-- 推荐人
SELECT referrer_id AS related_user_id
FROM agent_referral_relation
WHERE agent_id = #{clientUserId}
AND is_deleted = 0
AND is_active = 1
UNION
-- 一级管理人
SELECT manage_id AS related_user_id
FROM agent_manage_relation
WHERE agent_id = #{clientUserId}
AND is_deleted = 0
AND is_active = 1
UNION
-- 二级管理人:通过一级管理人关联查询
SELECT m2.manage_id AS related_user_id
FROM agent_manage_relation m1
JOIN agent_manage_relation m2 ON m1.manage_id = m2.agent_id
WHERE m1.agent_id = #{clientUserId}
AND m1.is_deleted = 0 AND m1.is_active = 1
AND m2.is_deleted = 0 AND m2.is_active = 1
UNION
-- 辅导人
SELECT tutor_id AS related_user_id
FROM agent_tutoring_relation
WHERE agent_id = #{clientUserId}
AND is_deleted = 0
AND is_active = 1
) AS t
WHERE related_user_id IS NOT NULL
</select>
</mapper>
......@@ -19,10 +19,12 @@
<result property="policyHolder" column="policy_holder" />
<result property="policyHolderAge" column="policy_holder_age" />
<result property="insured" column="insured" />
<result property="guaranteePeriod" column="guarantee_period" />
<result property="sumInsured" column="sum_insured" />
<result property="paymentTerm" column="payment_term" />
<result property="paymentFrequency" column="payment_frequency" />
<result property="paymentPremium" column="payment_premium" />
<result property="totalPaymentPremium" column="total_payment_premium" />
<result property="status" column="status" />
<result property="currency" column="currency" />
<result property="initialPremium" column="initial_premium" />
......@@ -56,7 +58,7 @@
<sql id="Base_Column_List">
id,policy_biz_id,policy_no,user_biz_id,product_launch_biz_id,product_code,
product_name,product_cate,insurance_company,insurance_company_biz_id,region,
policy_holder,policy_holder_age,insured,sum_insured,payment_term,payment_frequency,payment_premium,
policy_holder,policy_holder_age,insured,guarantee_period,sum_insured,payment_term,payment_frequency,payment_premium,total_payment_premium,
status,currency,initial_premium,sign_date,issue_date,
effective_date,cooling_off_end_date,cooling_off_days,renewal_date,is_prepaid,deductibles,prepaid_term,
initial_payment_method,renewal_payment_method,dividend_distribution_method,is_backtrack,is_join,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment