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);
}
......@@ -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) {
......
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);
}
......@@ -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