Commit 40a2f2a0 by zhangxingmin

Merge remote-tracking branch 'origin/test' into test_zxm_salary

parents df826574 adfd2990
......@@ -2,11 +2,13 @@
FROM openjdk:8
# 维护人
LABEL maintainer="zxm<2060197959@qq.com>"
# 创建目录
# 创建应用目录
RUN mkdir -p /home/app
# 拷贝项目jar - 使用可执行的 fat JAR
# 创建日志目录并授权(默认 root 可写)
RUN mkdir -p /var/log/yd-csf-api && chmod 755 /var/log/yd-csf-api
# 拷贝项目jar
COPY target/yd-csf-api-1.0-SNAPSHOT-exec.jar /home/app/yd-csf-api.jar
# 执行命令启动jar,并设置JVM内存参数
# 启动命令
ENTRYPOINT ["java", "-Duser.timezone=Asia/Shanghai", "-Xmx256m", "-Xms128m", "-jar", "/home/app/yd-csf-api.jar"]
# 暴露端口
EXPOSE 9202
......@@ -241,7 +241,7 @@ public class ApiCommissionExpectedController {
.map(CommissionExpected::getId)
.collect(Collectors.toList());
CommissionExpectedStatisticsVO statisticsNewVO = commissionExpectedService
.getExpectedStatisticsNew(expectedIds);
.getExpectedStatisticsNew(allExpectedList);
// 获取混合分页结果
Page<CommissionExpectedNewVO> mixedPage = commissionExpectedService
......@@ -375,12 +375,16 @@ public class ApiCommissionExpectedController {
commissionExpectedQueryRequest.setQueryFlag(queryFlag);
QueryWrapper<CommissionExpected> queryWrapper = commissionExpectedService.getQueryWrapper(commissionExpectedQueryRequest);
// List<Long> allExpectedIdList = new ArrayList<>();
// 先查询所有符合条件的记录ID(用于统计)
List<CommissionExpected> allCommissionExpectedList = commissionExpectedService.list(queryWrapper);
List<Long> allExpectedIdList = allCommissionExpectedList.stream().map(CommissionExpected::getId).collect(Collectors.toList());
// List<CommissionExpected> allCommissionExpectedList = commissionExpectedService.list(queryWrapper);
// List<Long> allExpectedIdList = allCommissionExpectedList.stream().map(CommissionExpected::getId).collect(Collectors.toList());
// 查询统计数据(基于所有符合条件的记录)
CommissionExpectedStatisticsVO statisticsVO = commissionExpectedService.getExpectedStatisticsNew(allExpectedIdList);
// CommissionExpectedStatisticsVO statisticsVO = commissionExpectedService.getExpectedStatisticsNew(allCommissionExpectedList);
queryWrapper.select("id");
List<Long> allExpectedIdList = commissionExpectedService.listObjs(queryWrapper, obj -> (Long) obj);
// 应收款报表分页查询 - 按保单号和期数维度统计
Page<ReceivableReportVO> reportPage = new Page<>(commissionExpectedQueryRequest.getPageNo(), commissionExpectedQueryRequest.getPageSize());
......@@ -392,12 +396,94 @@ public class ApiCommissionExpectedController {
receivableReportPage = convertReceivableReport(receivableReportPage);
// 组装返回结果
ReceivableReportResponse response = new ReceivableReportResponse();
response.setStatisticsVO(statisticsVO);
// response.setStatisticsVO(statisticsVO);
response.setPage(receivableReportPage);
return Result.success(response);
}
@PostMapping("/receivable_report/statistics")
@Operation(summary = "应收款报表统计")
public Result<ReceivableReportResponse> receivableReportStatistics(@RequestBody CommissionExpectedQueryRequest commissionExpectedQueryRequest) {
//保單持有人(中/英、繁简/大小写)、签单人、转介人名称(主)、受保人(中/英、繁简/大小写)、查询保单号列表
List<String> queryPolicyNoList = new ArrayList<>();
Boolean queryFlag = false;
if (StringUtils.isNotBlank(commissionExpectedQueryRequest.getPolicyHolder())
|| StringUtils.isNotBlank(commissionExpectedQueryRequest.getSigner())
|| StringUtils.isNotBlank(commissionExpectedQueryRequest.getBrokerName())
|| StringUtils.isNotBlank(commissionExpectedQueryRequest.getInsured())
){
queryPolicyNoList = policyFollowService.queryPolicyNoList(
commissionExpectedQueryRequest.getPolicyHolder(),
commissionExpectedQueryRequest.getSigner(),
commissionExpectedQueryRequest.getBrokerName(),
commissionExpectedQueryRequest.getInsured());
queryFlag = true;
}
log.info("应收款报表=>receivableReport=>queryPolicyNoList:{}",JSON.toJSONString(queryPolicyNoList));
// 构建查询条件
commissionExpectedQueryRequest.setPolicyNoList(queryPolicyNoList);
commissionExpectedQueryRequest.setQueryFlag(queryFlag);
QueryWrapper<CommissionExpected> queryWrapper = commissionExpectedService.getQueryWrapper(commissionExpectedQueryRequest);
//显式选择需要的字段
queryWrapper.select("expected_amount", "paid_amount","paid_ratio", "commission_ratio", "policy_no","status");
// 先查询所有符合条件的记录ID(用于统计)
List<CommissionExpected> allCommissionExpectedList = commissionExpectedService.list(queryWrapper);
// 查询统计数据(基于所有符合条件的记录)
CommissionExpectedStatisticsVO statisticsVO = commissionExpectedService.getExpectedStatisticsNew(allCommissionExpectedList);
// 应收款报表分页查询 - 按保单号和期数维度统计
// Page<ReceivableReportVO> reportPage = new Page<>(commissionExpectedQueryRequest.getPageNo(), commissionExpectedQueryRequest.getPageSize());
// IPage<ReceivableReportVO> receivableReportPage = new Page<>(commissionExpectedQueryRequest.getPageNo(), commissionExpectedQueryRequest.getPageSize());
// if (!CollectionUtils.isEmpty(allExpectedIdList)) {
// receivableReportPage = commissionExpectedService.receivableReportPage(reportPage, allExpectedIdList);
// }
// enrichReceivableReportWithCompanyName(receivableReportPage);
// receivableReportPage = convertReceivableReport(receivableReportPage);
// 组装返回结果
ReceivableReportResponse response = new ReceivableReportResponse();
response.setStatisticsVO(statisticsVO);
// response.setPage(receivableReportPage);
return Result.success(response);
}
// @PostMapping("/receivable_report")
// @Operation(summary = "应收款报表")
// public Result<ReceivableReportResponse> receivableReport(@RequestBody CommissionExpectedQueryRequest request) {
// // 1. 根据持有人、签单人等条件查询保单号列表
// List<String> queryPolicyNoList = new ArrayList<>();
// Boolean queryFlag = false;
// if (StringUtils.isNotBlank(request.getPolicyHolder())
// || StringUtils.isNotBlank(request.getSigner())
// || StringUtils.isNotBlank(request.getBrokerName())
// || StringUtils.isNotBlank(request.getInsured())) {
// queryPolicyNoList = policyFollowService.queryPolicyNoList(
// request.getPolicyHolder(),
// request.getSigner(),
// request.getBrokerName(),
// request.getInsured());
// queryFlag = true;
// }
// log.info("应收款报表=>receivableReport=>queryPolicyNoList:{}", JSON.toJSONString(queryPolicyNoList));
//
// // 2. 将保单号列表设回请求对象
// request.setPolicyNoList(queryPolicyNoList);
// request.setQueryFlag(queryFlag);
//
// // 3. 直接分页查询(无需先查 ID)
// Page<ReceivableReportVO> page = new Page<>(request.getPageNo(), request.getPageSize());
// IPage<ReceivableReportVO> receivableReportPage = commissionExpectedService.receivableReportPage(page, request);
//
// // 4. 后处理:补充产品名称等字段,以及待入账金额归零逻辑
// receivableReportPage = convertReceivableReport(receivableReportPage);
//
// // 5. 组装返回(统计信息暂不提供,如需可后续添加单独统计查询)
// ReceivableReportResponse response = new ReceivableReportResponse();
// response.setPage(receivableReportPage);
// return Result.success(response);
// }
public IPage<ReceivableReportVO> convertReceivableReport(IPage<ReceivableReportVO> receivableReportPage) {
if (!org.springframework.util.CollectionUtils.isEmpty(receivableReportPage.getRecords())) {
List<String> policyNoList = receivableReportPage.getRecords().stream().map(ReceivableReportVO::getPolicyNo).collect(Collectors.toList());
......@@ -415,12 +501,12 @@ public class ApiCommissionExpectedController {
vo.setProductName(policyFollow.getProductName());
vo.setProductLaunchBizId(policyFollow.getProductLaunchBizId());
}
//已入账比例(%)>= 预计入账比例(%) 待入账比例和待入账金额归零
//已入账比例(%)
BigDecimal paidRatio = ObjectUtils.defaultIfNull(vo.getPaidRatio(), BigDecimal.ZERO);
//实用率和值 >= 预计入账比例(%) 待入账比例和待入账金额归零
//实用率和值
BigDecimal paid = ObjectUtils.defaultIfNull(vo.getPaid(), BigDecimal.ZERO);
//预计入账比例(%)
BigDecimal commissionRatio = ObjectUtils.defaultIfNull(vo.getCommissionRatio(), BigDecimal.ZERO);
if (paidRatio.compareTo(commissionRatio) >= 0) {
if (paid.compareTo(commissionRatio) >= 0) {
//待入账金额(港币)
vo.setUnpaidAmount(BigDecimal.ZERO);
//待入账比例(%)
......
......@@ -429,13 +429,13 @@ public class ApiFortuneController {
}
/**
* 修改设置出账年月(实)),设置完成后,更新到应付款管理明细中
* 修改设置出账年月(实)
*
* @param editActualPayoutDateRequest
* @return
*/
@PostMapping("/edit/actual_payout_date")
@Operation(summary = "修改设置出账年月(实),设置完成后,更新到应付款管理明细中")
@Operation(summary = "修改设置出账年月(实)")
public Result<Boolean> editActualPayoutDate(@RequestBody EditActualPayoutDateRequest editActualPayoutDateRequest) {
if (editActualPayoutDateRequest == null || StringUtils.isBlank(editActualPayoutDateRequest.getFortuneBizId())) {
return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "fortuneBizId 不能为空");
......
......@@ -529,6 +529,9 @@ public class ApiPolicyFollowController {
if (policyFollow == null) {
return Result.fail(ResultCode.NULL_ERROR.getCode(), ResultCode.NULL_ERROR.getMessage());
}
if (ObjectUtils.isEmpty(policyFollow.getPolicyNo())) {
return Result.fail(ResultCode.NULL_ERROR.getCode(), "新单跟进记录中,保单号不能为空");
}
if (ObjectUtils.isEmpty(policyFollow.getReconciliationCompanyCode())) {
return Result.fail(ResultCode.NULL_ERROR.getCode(), "新单跟进记录中,reconciliationCompanyCode不能为空");
}
......
......@@ -16,6 +16,11 @@ import java.util.List;
public class AlgorithmDto {
/**
* 期数(数字代表第几年)
*/
private Integer issueNumber;
/**
* 保单发佣批次ID
*/
private String batchBizId;
......
package com.yd.csf.api.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
......@@ -121,6 +122,16 @@ public class GenerateExpectedFortuneDto {
private String brokerRatio;
/**
* 奖金来源id(类型:转介人等,如果是转介人,这里就是这个奖来自这个转介人身上的)
*/
private String amountSourceId;
/**
* 奖金来源名称(类型:转介人等)
*/
private String amountSourceName;
/**
* 获得积分业务员绑定的基本法列表对应计算值
*/
private List<AlgorithmResDto> algorithmResDtoList;
......
......@@ -17,6 +17,7 @@ import com.yd.csf.feign.request.basiclawcalculate.ApiGenerateBillingRequest;
import com.yd.csf.feign.response.basiclawcalculate.ApiGenerateBillingResponse;
import com.yd.csf.service.dto.*;
import com.yd.csf.service.enums.FortuneStatusEnum;
import com.yd.csf.service.enums.RuleItemConfigEnum;
import com.yd.csf.service.model.*;
import com.yd.csf.service.service.*;
import com.yd.insurance.base.feign.client.ApiRelProductAnnouncementFeignClient;
......@@ -407,6 +408,16 @@ public class ApiBasicLawCalculateServiceImpl implements ApiBasicLawCalculateServ
if (CollectionUtils.isEmpty(ruleItemConfigList)) {
throw new BusinessException("基本法项目列表不存在");
}
//根据期数字段,判断是否是续期(续年)来过滤对应的销售佣金项目,续期期数保留续期销售项目剔除首期的销售佣金项目,首期期数保留首期的销售佣金项目剔除续期销售佣金项目
if (algorithmDto.getIssueNumber() != null) {
if (algorithmDto.getIssueNumber() == 1) {
//首期->剔除非首期(续期)的销售佣金项目
ruleItemConfigList.removeIf(item -> RuleItemConfigEnum.XQ_XS_YJ.getItemCode().equals(item.getItemCode()));
}else {
//续期->剔除首期销售佣金项目
ruleItemConfigList.removeIf(item -> RuleItemConfigEnum.XS_YJ.getItemCode().equals(item.getItemCode()));
}
}
log.info("查询基本法类型绑定的基本法项目列表 - 执行顺序,数值越小越先执行,用于控制佣金项目的计算顺序->出参:{}", JSON.toJSONString(algorithmDto));
List<AlgorithmResDto> algorithmResDtoList = new ArrayList<>();
//遍历基本法项目 - 计算对应值
......
......@@ -25,12 +25,12 @@ import com.yd.csf.api.service.ApiBasicLawCalculateService;
import com.yd.csf.api.service.ApiCommissionConditionService;
import com.yd.csf.api.service.ApiExpectedFortuneLogService;
import com.yd.csf.api.service.ApiExpectedFortuneService;
import com.yd.csf.service.component.DictCacheService;
import com.yd.csf.feign.request.expectedfortune.*;
import com.yd.csf.feign.response.expectedfortune.ApiExpectedFortunePageResponse;
import com.yd.csf.feign.response.expectedfortune.ApiGenerateExpectedFortuneResponse;
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.dto.UserGradeDto;
import com.yd.csf.service.enums.CurrencyEnum;
import com.yd.csf.service.enums.FortuneStatusEnum;
......@@ -94,11 +94,14 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
private ApiExpectedFortuneService getSelf() {
return applicationContext.getBean(ApiExpectedFortuneService.class);
}
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private RedisUtil redisUtil;
@Autowired
private DictCacheService dictCacheService;
@Autowired
private ApiExpectedFortuneLogService apiExpectedFortuneLogService;
@Autowired
private PolicyBrokerService policyBrokerService;
......@@ -437,12 +440,9 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
}
}
}
//批量设置应付款编号、发佣类型
List<ExpectedFortune> expectedFortuneList = updatePayableNoBatch(policyNo);
//默认结算汇率、港币金额
//批量设置应付款编号、发佣类型、默认结算汇率、港币金额
String policyCurrency = queryPolicyAndBrokerDtoList.get(0).getCurrency();
updateHkdAmountBatch(expectedFortuneList, policyCurrency, announcementRatioList);
updatePayableNoAndHkdAmountBatch(policyNo, policyCurrency, announcementRatioList);
//执行成功完毕,也要销毁redis缓存
redisUtil.deleteObject(RedisConstants.EXPECTED_FORTUNE + policyNo);
......@@ -471,48 +471,6 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
});
}
@Transactional(rollbackFor = Exception.class)
public void updateHkdAmountBatch(List<ExpectedFortune> expectedFortuneList, String policyCurrency, List<ApiAnnouncementCommissionRatioListResponse> announcementRatioList) {
log.info("------------------------开始计算默认结算汇率、港币金额----------------------");
if (!CollectionUtils.isEmpty(announcementRatioList)) {
ApiAnnouncementCommissionRatioListResponse announcementRatio = announcementRatioList.get(0);
String currency = announcementRatio.getCurrency();
log.info("结算币种:{}", currency);
BigDecimal exchangeRate = queryExchangeRateByFeign(policyCurrency, currency);
log.info("结算汇率:{}", exchangeRate);
for (ExpectedFortune expectedFortune : expectedFortuneList) {
ExpectedFortune updateObj = new ExpectedFortune();
updateObj.setId(expectedFortune.getId());
//原币种
updateObj.setOriginalCurrency(currency);
//原币种金额
updateObj.setOriginalAmount(expectedFortune.getRuleAmount());
//原币种 -> 港币汇率
updateObj.setOriginalToHkdRate(exchangeRate);
//保单币种
updateObj.setRuleCurrency(currency);
//默认保单币种 -> 港币汇率
updateObj.setDefaultExchangeRate(exchangeRate);
//港币金额(标准发佣金额 * 默认保单币种 -> 港币汇率)
updateObj.setHkdAmount(expectedFortune.getRuleAmount().multiply(exchangeRate));
//默认值
updateObj.setPaidAmount(BigDecimal.ZERO);
updateObj.setPaidRatio(BigDecimal.ZERO);
updateObj.setUnpaidAmount(expectedFortune.getHkdAmount());
updateObj.setUnpaidRatio(BigDecimal.valueOf(100));
iExpectedFortuneService.updateById(updateObj);
}
}
}
@Override
public Result executeSync(List<QueryPolicyAndBrokerDto> queryPolicyAndBrokerDtoList, List<CommissionRuleBinding> commissionRuleBindingList, String policyNo) {
return null;
......@@ -588,7 +546,8 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
resDto.setAlgorithmResDtoList(result.getData());
collectResDtos.add(resDto);
if (!CollectionUtils.isEmpty(commissionRuleBindingList)) {
//续年度只发销售佣金,其他奖项均不发放
if (!CollectionUtils.isEmpty(commissionRuleBindingList) && i == 1) {
for (CommissionRuleBinding binding : commissionRuleBindingList) {
Result<List<AlgorithmResDto>> result1 = executeReward(ExecuteBillingDto.builder()
.clientUserBizId(binding.getTargetId())
......@@ -615,13 +574,10 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
}
}
}
//批量设置应付款编号
List<ExpectedFortune> expectedFortuneList = updatePayableNoBatch(policyNo);
//默认结算汇率、港币金额
//批量设置应付款编号、默认结算汇率、港币金额
String policyCurrency = queryPolicyAndBrokerDtoList.get(0).getCurrency();
updateHkdAmountBatch(expectedFortuneList, policyCurrency, announcementRatioList);
;
updatePayableNoAndHkdAmountBatch(policyNo, policyCurrency, announcementRatioList);
//执行成功完毕,也要销毁redis缓存
redisUtil.deleteObject(RedisConstants.EXPECTED_FORTUNE + policyNo);
......@@ -633,11 +589,6 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
.policyNo(policyNo)
.status(0)
.build());
//异步处理-构建冷静期定时任务
// log.info("异步处理-构建冷静期定时任务=>请求前入参:{}",JSON.toJSONString(collectResDtos));
// apiExpectedFortuneAsyncService.buildCalmDateTask(collectResDtos,policyNo,exchangeRate);
return Result.success();
} catch (Exception e) {
//抛出异常,销毁redis缓存
......@@ -672,31 +623,81 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
return commissionRuleBindingList;
}
@Transactional(rollbackFor = Exception.class)
private List<ExpectedFortune> updatePayableNoBatch(String policyNo) {
/**
* 批量更新应付款编号、发佣类型、默认结算汇率、港币金额
*/
private void updatePayableNoAndHkdAmountBatch(String policyNo, String policyCurrency,
List<ApiAnnouncementCommissionRatioListResponse> announcementRatioList) {
//查询当前保单号的所有预计发佣记录
List<ExpectedFortune> expectedFortuneList = iExpectedFortuneService.queryList(policyNo);
//查询redis缓存的字典列表信息
List<GetDictItemListByDictTypeResponse> dictTypeResponses = redisUtil.getCacheObject(RedisConstants.DICT_LIST);
List<GetDictItemListByDictTypeResponse> dictTypeResponses = dictCacheService.getDictList("csf_fortune_type");
//批量更新应付款编号,每个item递增
ExpectedFortune expectedFortune;
List<ExpectedFortune> updateList = new ArrayList<>();
for (int i = 0; i < expectedFortuneList.size(); i++) {
expectedFortune = expectedFortuneList.get(i);
log.info("------------------------开始计算默认结算汇率、港币金额----------------------");
//计算汇率(只在announcementRatioList非空时)
String currency = null;
BigDecimal originalToHkdRate = null;
BigDecimal hkdToPayoutRate = null;
if (!CollectionUtils.isEmpty(announcementRatioList)) {
ApiAnnouncementCommissionRatioListResponse announcementRatio = announcementRatioList.get(0);
currency = announcementRatio.getCurrency();
log.info("结算币种(发放币种):{}", currency);
originalToHkdRate = queryExchangeRateByFeign(policyCurrency, "HKD");
log.info("结算汇率(原币种 -> 港币汇率):{}", originalToHkdRate);
hkdToPayoutRate = queryExchangeRateByFeign("HKD", currency);
log.info("港币 -> 发放币种汇率:{}", hkdToPayoutRate);
}
List<ExpectedFortune> updateList = new ArrayList<>();
for (ExpectedFortune expectedFortune : expectedFortuneList) {
ExpectedFortune updateObj = new ExpectedFortune();
updateObj.setId(expectedFortune.getId());
//设置发佣类型
updateObj.setFortuneType(GetDictItemListByDictTypeResponse.getItemValue(dictTypeResponses,
"csf_fortune_type", expectedFortune.getFortuneName()));
//设置应付款编号
updateObj.setPayableNo(iExpectedFortuneService.getPayableNo(updateObj.getFortuneType(), policyNo, expectedFortune.getId()));
//设置默认结算汇率、港币金额
if (!CollectionUtils.isEmpty(announcementRatioList)) {
//原币种
updateObj.setOriginalCurrency(policyCurrency);
//原币种金额
BigDecimal ruleAmount = expectedFortune.getRuleAmount();
updateObj.setOriginalAmount(ruleAmount);
//原币种 -> 港币汇率
updateObj.setOriginalToHkdRate(originalToHkdRate);
//保单币种
updateObj.setRuleCurrency(policyCurrency);
//默认保单币种 -> 港币汇率
updateObj.setDefaultExchangeRate(originalToHkdRate);
//应发港币金额(估)(标准发佣金额 * 默认保单币种 -> 港币汇率)
BigDecimal hkdAmount = ruleAmount.multiply(originalToHkdRate);
updateObj.setHkdAmount(hkdAmount);
//发放币种
updateObj.setPayoutCurrency(currency);
//发放币种金额
updateObj.setPayoutAmount(hkdAmount.multiply(hkdToPayoutRate));
//港币 -> 发放币种汇率
updateObj.setHkdToPayoutRate(hkdToPayoutRate);
//默认值
updateObj.setPaidRuleAmount(BigDecimal.ZERO);
updateObj.setUnpaidRuleAmount(ruleAmount);
updateObj.setUnpaidRuleAmountHkd(hkdAmount);
updateObj.setPaidAmount(BigDecimal.ZERO);
updateObj.setPaidRatio(BigDecimal.ZERO);
updateObj.setUnpaidAmount(expectedFortune.getHkdAmount());
updateObj.setUnpaidRatio(BigDecimal.valueOf(100));
}
updateList.add(updateObj);
}
iExpectedFortuneService.updateBatchById(updateList);
return expectedFortuneList;
}
/**
......@@ -706,7 +707,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
* @return
*/
@Transactional(rollbackFor = Exception.class)
public Result<List<AlgorithmResDto>> executeReward(ExecuteBillingDto dto) {
public Result executeReward(ExecuteBillingDto dto) {
QueryPolicyAndBrokerDto brokerDto = dto.getPolicyAndBrokerDto();
//构造销售佣金基本法项目的顺序下标值执行
List<Integer> executionOrderList = new ArrayList<>();
......@@ -764,12 +765,13 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
.productLaunchBizId(brokerDto.getPlanBizId())
//保险公司业务id
.insuranceCompanyBizId(brokerDto.getInsuranceCompanyBizId())
.source(2)
//转介人的介绍费占比
.brokerRatio(dto.getBrokerRatio())
.source(2)
.amountSourceId(brokerDto.getBrokerBizId())
.amountSourceName(brokerDto.getBrokerName())
.build());
return Result.success(result.getData());
return Result.success();
}
private static LocalDate calculateExpectedPayoutDate(LocalDate effectiveDate, Integer issueNumber) {
......@@ -783,7 +785,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
* @return
*/
@Transactional(rollbackFor = Exception.class)
public Result<List<AlgorithmResDto>> executeBilling(ExecuteBillingDto dto) {
public Result executeBilling(ExecuteBillingDto dto) {
log.info("执行 - 销售佣金(销售佣金基本法)——>入参:{}", JSON.toJSONString(dto));
QueryPolicyAndBrokerDto brokerDto = dto.getPolicyAndBrokerDto();
//构造销售佣金基本法项目的顺序下标值执行
......@@ -792,6 +794,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
//保单出账先执行销售佣金基本法项目,入完到积分明细表里后,再执行保单绑定人的其他基本法项目
Result<List<AlgorithmResDto>> result = apiBasicLawCalculateService.policyBrokerAlgorithm(AlgorithmDto.builder()
.issueNumber(dto.getIssueNumber())
.brokerBizId(brokerDto.getBrokerBizId())
.clientUserBizId(brokerDto.getBrokerBizId())
.sqlTemplateParamDto(SqlTemplateParamDto.builder()
......@@ -842,11 +845,11 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
.productLaunchBizId(brokerDto.getPlanBizId())
//保险公司业务id
.insuranceCompanyBizId(brokerDto.getInsuranceCompanyBizId())
.source(1)
.brokerRatio(dto.getBrokerRatio())
.source(1)
.build());
return Result.success(result.getData());
return Result.success();
}
/**
......@@ -909,13 +912,14 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
fortune.setPolicyNo(fortuneDto.getPolicyNo());
//预计发佣日期
fortune.setPayoutDate(fortuneDto.getPayoutDate());
fortune.setAmountSourceId(fortuneDto.getAmountSourceId());
fortune.setAmountSourceName(fortuneDto.getAmountSourceName());
// 标准发佣金额 -> 计算值
BigDecimal standardAmount = algorithmResDto.getCalculatedValue();
fortune.setStandardAmount(standardAmount);
// 转介人介绍费占比
// String brokerRatioStr = !Objects.isNull(policyBroker) ? policyBroker.getBrokerRatio() : "100";
String brokerRatioStr = StringUtils.isNotBlank(fortuneDto.getBrokerRatio()) ? fortuneDto.getBrokerRatio() : "100";
fortune.setBrokerRatio(brokerRatioStr);
......@@ -1134,7 +1138,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
// 校验是否存在
for (ExpectedFortuneAddRequest request : fortuneAddRequestList) {
String key = String.format("%s_%s_%s", request.getPolicyNo(), request.getFortunePeriod(), request.getFortuneBizType());
String key = String.format("%s_%s_%s", request.getPolicyNo(), request.getFortunePeriod(), request.getFortuneType());
if (existingRecordsMap.containsKey(key)) {
throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "当前期数已存在: " + request.getFortuneName());
}
......@@ -1154,26 +1158,26 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
}
/**
* 保单币种对预计来佣的结算币种的默认汇率
* 查询币对的默认汇率
*
* @param policyCurrency 保单币种
* @param currency 预计来佣的结算币种
* @param sourceCurrency 源币种
* @param targetCurrency 目标币种
* @return 汇率
*/
private BigDecimal queryExchangeRateByFeign(String policyCurrency, String currency) {
private BigDecimal queryExchangeRateByFeign(String sourceCurrency, String targetCurrency) {
HttpServletRequest request2 = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token2 = request2.getHeader("Authorization");
log.info("保单币种对预计来佣的结算币种的默认汇率 token==============,{}", token2);
if (policyCurrency.equalsIgnoreCase(currency)) {
log.info("查询币对的默认汇率 token==============,{}", token2);
if (sourceCurrency.equalsIgnoreCase(targetCurrency)) {
return BigDecimal.ONE;
}
// 调用Feign客户端查询汇率
Result<BigDecimal> result = apiExchangeRateFeignClient.getExchangeRate(policyCurrency, currency, "");
Result<BigDecimal> result = apiExchangeRateFeignClient.getExchangeRate(sourceCurrency, targetCurrency, "");
if (result != null && result.getData() != null) {
return result.getData();
} else {
throw new BusinessException(ResultCode.PARAMS_ERROR.getCode(), "查询币对的默认汇率失败, 币种:" + sourceCurrency + " -> " + targetCurrency);
}
log.info("调用Feign客户端查询汇率=>,{}",JSON.toJSONString(result));
return null;
}
private void validateAdd(List<ExpectedFortuneAddRequest> fortuneAddRequestList) {
......@@ -1207,11 +1211,11 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
@Override
@Transactional(rollbackFor = Exception.class)
public void exportExpectedFortune(ApiExpectedFortunePageRequest request, HttpServletResponse response) {
// 查询数据
// 查询数据(复用 /list 的查询逻辑,UNION ALL 双表 + processData 排序 + 枚举补充)
QueryWrapper<ExpectedFortune> queryWrapper = this.getQueryWrapper(request);
List<ExpectedFortune> fortuneList = iExpectedFortuneService.list(queryWrapper);
// 先转换为VO, VO 补充了关联信息(产品计划、产品险种、保险公司、用户)
List<ApiExpectedFortunePageResponse> expectedFortuneVOList = iExpectedFortuneService.toVOList(fortuneList);
// 移除 QueryWrapper 中的排序,避免在 UNION ALL 的子查询中出现 ORDER BY
queryWrapper.getExpression().getOrderBy().clear();
List<ApiExpectedFortunePageResponse> expectedFortuneVOList = iExpectedFortuneService.queryListAll(queryWrapper);
// 转换为导出DTO
List<ExpectedFortuneExportDTO> exportDataList = expectedFortuneVOList.stream()
.map(ExpectedFortuneExportDTO::convertToExportDTO)
......@@ -1228,29 +1232,44 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
@Override
public Result<PayableReportResponse> payableReport(ApiExpectedFortunePageRequest request) {
//保單持有人(中/英)、签单人、转介人名称(主)查询保单号列表
List<String> queryPolicyNoList = policyFollowService.queryPolicyNoList(request.getPolicyHolder(),"","","");
// 1. 参数校验
if (request == null) {
return Result.fail(ResultCode.PARAMS_ERROR.getCode(), "查询参数不能为空");
}
if (request.getPageNo() == null || request.getPageNo() < 1) {
request.setPageNo(1);
}
if (request.getPageSize() == null || request.getPageSize() < 1) {
request.setPageSize(10);
}
// 构建查询条件
request.setPolicyNoList(queryPolicyNoList);
// 2. 构建查询条件(复用 getQueryWrapper,与 /list 共用同一套条件)
QueryWrapper<ExpectedFortune> queryWrapper = this.getQueryWrapper(request);
// 先查询所有符合条件的记录ID(用于统计)
List<ExpectedFortune> allFortuneList = iExpectedFortuneService.list(queryWrapper);
List<Long> allFortuneIdList = allFortuneList.stream().map(ExpectedFortune::getId).collect(Collectors.toList());
// 3. 移除 QueryWrapper 中的排序,避免在 UNION ALL 的子查询中出现 ORDER BY
queryWrapper.getExpression().getOrderBy().clear();
// 4. 查询统计数据(直接传递 QueryWrapper,在 SQL 中聚合计算,不再加载明细到内存)
ExpectedFortuneStatisticsVO statisticsVO = iExpectedFortuneService.queryListStatistics(queryWrapper);
// 查询统计数据(基于所有符合条件的记录)
ExpectedFortuneStatisticsVO statisticsVO = this.getStatistics(allFortuneIdList);
// 计算待出账金额和已出账比例
BigDecimal totalAmount = statisticsVO.getTotalExpectedAmount();
BigDecimal totalPaidAmount = statisticsVO.getTotalPaidAmount();
statisticsVO.setTotalUnpaidAmount(totalAmount.subtract(totalPaidAmount));
BigDecimal divided = BigDecimal.ZERO;
if (totalAmount.compareTo(BigDecimal.ZERO) > 0) {
divided = totalPaidAmount.divide(totalAmount, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
}
statisticsVO.setPaidAmountRatio(divided);
// 应付款报表分页查询 - 按保单号和期数维度统计
// 5. 应付款报表分页查询(按保单号和期数维度统计,直接传递 QueryWrapper)
Page<PayableReportVO> reportPage = new Page<>(request.getPageNo(), request.getPageSize());
IPage<PayableReportVO> payableReportPage = new Page<>(request.getPageNo(), request.getPageSize());
if (!CollectionUtils.isEmpty(allFortuneIdList)) {
payableReportPage = iExpectedFortuneService.payableReportPage(reportPage, allFortuneIdList);
}
IPage<PayableReportVO> payableReportPage = iExpectedFortuneService.payableReportPage(reportPage, queryWrapper);
// 6. 数据补充(转介人等级、保单持有人、产品名称等信息)
payableReportPage = convertPayableReportVO(payableReportPage);
// 组装返回结果
// 7. 组装返回结果
PayableReportResponse response = new PayableReportResponse();
response.setStatisticsVO(statisticsVO);
response.setPage(payableReportPage);
......@@ -1268,8 +1287,8 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
Map<String, PolicyFollow> policyFollowMap = policyFollowService.queryPolicyFollowMap(policyNoList);
List<PayableReportVO> voList = payableReportPage.getRecords().stream().map(vo -> {
PolicyFollow policyFollow= policyFollowMap.get(vo.getPolicyNo());
UserGradeDto userGradeDto= userGradeMap.get(vo.getBrokerBizId());
PolicyFollow policyFollow = policyFollowMap.get(vo.getPolicyNo());
UserGradeDto userGradeDto = userGradeMap.get(vo.getBrokerBizId());
vo.setCurrency(CurrencyEnum.toLabel(vo.getCurrency()));
if (userGradeDto != null) {
......@@ -1355,7 +1374,7 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
String brokerIds = brokerBizIdList.stream()
.map(id -> "'" + id + "'")
.collect(Collectors.joining(","));
queryWrapper.apply("EXISTS (SELECT 1 FROM policy_follow f WHERE f.policy_no = expected_fortune.policy_no AND f.first_broker_biz_id in (" + brokerIds + "))");
queryWrapper.apply("EXISTS (SELECT 1 FROM policy_broker pb WHERE pb.policy_no = expected_fortune.policy_no AND pb.broker_biz_id in (" + brokerIds + "))");
}
queryWrapper.in(ObjectUtils.isNotEmpty(signerBizIdList), "signer_biz_id", signerBizIdList);
queryWrapper.eq(StringUtils.isNotBlank(fortuneBizType), "fortune_biz_type", fortuneBizType);
......@@ -1365,7 +1384,6 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
policyHolder);
}
queryWrapper.in(ObjectUtils.isNotEmpty(request.getPolicyNoList()), "policy_no", request.getPolicyNoList());
// 按id升序排序
queryWrapper.orderByAsc("id");
return queryWrapper;
......
......@@ -90,9 +90,23 @@ public class ApiPremiumRemittanceServiceImpl implements ApiPremiumRemittanceServ
PremiumRemittance premiumRemittance = result.getData();
BeanUtils.copyProperties(request,premiumRemittance);
//支付凭证
premiumRemittance.setPaymentVoucher(!CollectionUtils.isEmpty(request.getPaymentVoucherList()) ? String.join(";",request.getPaymentVoucherList()) : "");
List<String> paymentVoucherList = new ArrayList<>();
if (!CollectionUtils.isEmpty(request.getPaymentVoucherDtoList())) {
paymentVoucherList = request.getPaymentVoucherDtoList().stream()
.filter(dto -> StringUtils.isNotBlank(dto.getFileUrl()))
.map(ApiPremiumRemittanceFileDto::getFileUrl)
.collect(Collectors.toList());
}
premiumRemittance.setPaymentVoucher(!CollectionUtils.isEmpty(paymentVoucherList) ? String.join(";",paymentVoucherList) : "");
//账户证明
premiumRemittance.setAccountVerification(!CollectionUtils.isEmpty(request.getAccountVerificationList()) ? String.join(";",request.getAccountVerificationList()) : "");
List<String> accountVerificationList = new ArrayList<>();
if (!CollectionUtils.isEmpty(request.getAccountVerificationDtoList())) {
accountVerificationList = request.getAccountVerificationDtoList().stream()
.filter(dto -> StringUtils.isNotBlank(dto.getFileUrl()))
.map(ApiPremiumRemittanceFileDto::getFileUrl)
.collect(Collectors.toList());
}
premiumRemittance.setAccountVerification(!CollectionUtils.isEmpty(accountVerificationList) ? String.join(";",accountVerificationList) : "");
iPremiumRemittanceService.saveOrUpdate(premiumRemittance);
//保存-保费对账汇款记录附件列表
apiPremiumRemittanceFileService.savePremiumRemittanceFileList(request.getApiPremiumRemittanceFileDtoList(),request.getPremiumRemittanceBizId());
......@@ -154,9 +168,23 @@ public class ApiPremiumRemittanceServiceImpl implements ApiPremiumRemittanceServ
//保费对账-汇款记录表唯一业务ID
premiumRemittance.setPremiumRemittanceBizId(RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_PREMIUM_REMITTANCE.getCode()));
//支付凭证
premiumRemittance.setPaymentVoucher(!CollectionUtils.isEmpty(dto.getPaymentVoucherList()) ? String.join(";",dto.getPaymentVoucherList()) : "");
List<String> paymentVoucherList = new ArrayList<>();
if (!CollectionUtils.isEmpty(dto.getPaymentVoucherDtoList())) {
paymentVoucherList = dto.getPaymentVoucherDtoList().stream()
.filter(dto1 -> StringUtils.isNotBlank(dto1.getFileUrl()))
.map(ApiPremiumRemittanceFileDto::getFileUrl)
.collect(Collectors.toList());
}
premiumRemittance.setPaymentVoucher(!CollectionUtils.isEmpty(paymentVoucherList) ? String.join(";",paymentVoucherList) : "");
//账户证明
premiumRemittance.setAccountVerification(!CollectionUtils.isEmpty(dto.getAccountVerificationList()) ? String.join(";",dto.getAccountVerificationList()) : "");
List<String> accountVerificationList = new ArrayList<>();
if (!CollectionUtils.isEmpty(dto.getAccountVerificationDtoList())) {
accountVerificationList = dto.getAccountVerificationDtoList().stream()
.filter(dto1 -> StringUtils.isNotBlank(dto1.getFileUrl()))
.map(ApiPremiumRemittanceFileDto::getFileUrl)
.collect(Collectors.toList());
}
premiumRemittance.setAccountVerification(!CollectionUtils.isEmpty(accountVerificationList) ? String.join(";",accountVerificationList) : "");
iPremiumRemittanceService.saveOrUpdate(premiumRemittance);
//添加-保费对账汇款记录附件列表
......
......@@ -106,7 +106,7 @@ public class ApiSalaryServiceImpl implements ApiSalaryService {
ApiUserSaleExpandListRequest request = new ApiUserSaleExpandListRequest();
request.setClientUserBizIdList(clientUserBizIdList);
Result<List<ApiUserSaleExpandDetailResponse>> result = apiUserSaleExpandFeignClient.list(request);
if (CollectionUtils.isEmpty(request.getClientUserBizIdList())) {
if (CollectionUtils.isEmpty(result.getData())) {
return iPage;
}
Map<String, ApiUserSaleExpandDetailResponse> policyFollowMap = result.getData().stream()
......
......@@ -133,8 +133,8 @@ public class ApiSalarySplitServiceImpl implements ApiSalarySplitService {
// 查询统计信息
ApiSalarySplitStatisticsDto statisticsDto = new ApiSalarySplitStatisticsDto();
FortuneAccount fortuneAccount = fortuneAccountService.queryOne(request.getFortuneAccountBizId());
// 出账币种
statisticsDto.setBeSplitCurrency(fortuneAccount != null ? fortuneAccount.getCurrency() : "");
// 发放币种
statisticsDto.setBeSplitCurrency(fortuneAccount != null ? fortuneAccount.getPayoutCurrency() : "");
BigDecimal beSplitAmount = BigDecimal.ZERO;
if (fortuneAccount != null) {
......@@ -147,7 +147,7 @@ public class ApiSalarySplitServiceImpl implements ApiSalarySplitService {
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal fortuneAmount = fortuneAccount.getHkdAmount() != null ? fortuneAccount.getHkdAmount() : BigDecimal.ZERO;
BigDecimal fortuneAmount = fortuneAccount.getPayoutAmount() != null ? fortuneAccount.getPayoutAmount() : BigDecimal.ZERO;
beSplitAmount = fortuneAmount.subtract(splitTotal);
if (beSplitAmount.compareTo(BigDecimal.ZERO) < 0) {
beSplitAmount = BigDecimal.ZERO; // 防止负数
......@@ -231,7 +231,7 @@ public class ApiSalarySplitServiceImpl implements ApiSalarySplitService {
}
// 3. 计算剩余可拆金额(账户总额 - 本次拟拆分总额)
BigDecimal fortuneAmount = fortuneAccount.getHkdAmount() != null ? fortuneAccount.getHkdAmount() : BigDecimal.ZERO;
BigDecimal fortuneAmount = fortuneAccount.getPayoutAmount() != null ? fortuneAccount.getPayoutAmount() : BigDecimal.ZERO;
BigDecimal beSplitAmount = fortuneAmount.subtract(splitTotal);
if (beSplitAmount.compareTo(BigDecimal.ZERO) < 0) {
beSplitAmount = BigDecimal.ZERO; // 防止负数
......@@ -239,7 +239,7 @@ public class ApiSalarySplitServiceImpl implements ApiSalarySplitService {
// 4. 封装响应
ApiQueryRemainingResponse response = new ApiQueryRemainingResponse();
response.setCurrency(fortuneAccount.getCurrency());
response.setCurrency(fortuneAccount.getPayoutCurrency());
response.setFromAmount(beSplitAmount);
return Result.success(response);
}
......@@ -260,7 +260,7 @@ public class ApiSalarySplitServiceImpl implements ApiSalarySplitService {
//原币种金额
convertRequest.setAmount(request.getFromAmount());
//原币种
convertRequest.setFromCurrency(fortuneAccount.getCurrency());
convertRequest.setFromCurrency(fortuneAccount.getPayoutCurrency());
//目标币种
convertRequest.setToCurrency(request.getToCurrency());
//调用远程转换接口
......@@ -296,11 +296,13 @@ public class ApiSalarySplitServiceImpl implements ApiSalarySplitService {
// 查询数据
List<ApiSalarySplitSummaryPageDto> dataList = iSalarySplitService.summaryList(request);
log.info("导出-薪资拆分应发信息汇总列表:dataList,{}", JSON.toJSONString(dataList));
Map<String, String> map = getBillOrgDict();
List<ApiSalarySplitSummaryExcelDto> excelDtoList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(dataList)) {
excelDtoList = dataList.stream().map(dto -> {
ApiSalarySplitSummaryExcelDto excelDto = new ApiSalarySplitSummaryExcelDto();
BeanUtils.copyProperties(dto,excelDto);
excelDto.setBillOrg(map != null ? map.get(dto.getBillOrg()) : "");
return excelDto;
}).collect(Collectors.toList());
}
......@@ -309,9 +311,9 @@ public class ApiSalarySplitServiceImpl implements ApiSalarySplitService {
ExportParam exportParam = new ExportParam();
// 指定需要导出的字段(字段名必须与 DTO 中的属性名一致)
exportParam.setFieldNames(Arrays.asList(
"salarySplitNo","businessNo","brokerName","team","fromAmount",
"salarySplitNo","businessNo","brokerName","internalNumber","team","fromAmount",
"currency","exchangeRate","toAmount","toCurrency",
"fortuneAccountMonth","billOrg","hkdAmount"
"fortuneAccountMonth","billOrg","amount"
));
exportParam.setFileName("薪资拆分应发信息汇总");
exportParam.setUploadToOss(true);
......
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="BASE_LOG_DIR" value="/var/log/yd-csf-api" />
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 不指定固定 file,让 fileNamePattern 完全控制 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${BASE_LOG_DIR}/%d{yyyy-MM-dd}/app.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
\ No newline at end of file
#3.2.1\u4EE5\u4E0A\u4F7F\u7528
# p6spy 配置文件
# 注意:需要配合 application.yml 中修改 driver 和 url 使用
# 3.2.1 及以上版本使用 Mybatis-Plus 的工厂类(输出可执行 SQL)
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1\u4EE5\u4E0B\u4F7F\u7528\u6216\u8005\u4E0D\u914D\u7F6E
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# \u81EA\u5B9A\u4E49\u65E5\u5FD7\u6253\u5370
# 使用 Mybatis-Plus 提供的日志格式(参数已替换,排版清晰)
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#\u65E5\u5FD7\u8F93\u51FA\u5230\u63A7\u5236\u53F0
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# \u4F7F\u7528\u65E5\u5FD7\u7CFB\u7EDF\u8BB0\u5F55 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# \u8BBE\u7F6E p6spy driver \u4EE3\u7406
deregisterdrivers=true
# \u53D6\u6D88JDBC URL\u524D\u7F00
# 关键:使用 SLF4J 输出,让日志完全由 Logback 管理
appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 取消 JDBC URL 前缀(保持原 URL 可用)
useprefix=true
# \u914D\u7F6E\u8BB0\u5F55 Log \u4F8B\u5916,\u53EF\u53BB\u6389\u7684\u7ED3\u679C\u96C6\u6709error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# \u65E5\u671F\u683C\u5F0F
# 注销不必要的 JDBC 驱动
deregisterdrivers=true
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# \u5B9E\u9645\u9A71\u52A8\u53EF\u591A\u4E2A
#driverlist=org.h2.Driver
# \u662F\u5426\u5F00\u542F\u6162SQL\u8BB0\u5F55
# 排除不输出的类别,减少日志噪音
# 可选值:info, debug, result, commit, batch, resultset
excludecategories=info,debug,result,commit,resultset
# 是否开启慢 SQL 记录
outagedetection=true
# \u6162SQL\u8BB0\u5F55\u6807\u51C6 2 \u79D2
outagedetectioninterval=2
# 慢 SQL 阈值(单位:秒),超过此值会单独记录(输出 WARN 级别)
outagedetectioninterval=1
# 可选:自定义日志输出格式(如果不需要 Mybatis-Plus 格式,可启用以下行)
# 但建议保留上面的 Mybatis-Plus 格式,效果更好
# customLogMessageFormat=%(executionTime)ms | %(category) | %(sqlSingleLine)
# 可选:记录执行时间超过阈值的 SQL 到单独的日志类别(配合 outage detection)
# 无需额外配置,P6OutageFactory 已自动处理
# 注意:不需要配置 driverlist,p6spy 会自动读取原数据源的驱动
\ No newline at end of file
......@@ -10,40 +10,40 @@ public class ApiSalarySplitSummaryExcelDto {
@Excel(name = "发放编号", orderNum = "1")
private String salarySplitNo;
@Excel(name = "业务编号", orderNum = "1")
@Excel(name = "业务编号", orderNum = "2")
private String businessNo;
@Excel(name = "转介人", orderNum = "2")
@Excel(name = "转介人", orderNum = "3")
private String brokerName;
@Excel(name = "内部编号", orderNum = "3")
@Excel(name = "内部编号", orderNum = "4")
private String internalNumber;
@Excel(name = "所属团队", orderNum = "4")
@Excel(name = "所属团队", orderNum = "5")
private String team;
@Excel(name = "原币种金额", orderNum = "5")
@Excel(name = "原币种金额", orderNum = "6")
private BigDecimal fromAmount;
@Excel(name = "原币种", orderNum = "6")
@Excel(name = "原币种", orderNum = "7")
private String currency;
@Excel(name = "汇率(原币种->目标币种)", orderNum = "7")
@Excel(name = "汇率(原币种->目标币种)", orderNum = "8")
private BigDecimal exchangeRate;
@Excel(name = "目标金额", orderNum = "8")
@Excel(name = "目标金额", orderNum = "9")
private BigDecimal toAmount;
@Excel(name = "目标币种", orderNum = "9")
@Excel(name = "目标币种", orderNum = "10")
private String toCurrency;
@Excel(name = "出账月(实)", orderNum = "10")
@Excel(name = "出账月(实)", orderNum = "11")
private String fortuneAccountMonth;
@Excel(name = "出账机构", orderNum = "11")
@Excel(name = "出账机构", orderNum = "12")
private String billOrg;
@Excel(name = "本期总出账金额(原币种)", orderNum = "12")
private BigDecimal hkdAmount;
@Excel(name = "本期总出账金额(原币种)", orderNum = "13")
private BigDecimal amount;
}
......@@ -73,17 +73,17 @@ public class ApiPremiumRemittanceDto {
@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
private LocalDateTime paymentDate;
/**
* 支付凭证列表
*/
@NotEmpty(message = "支付凭证列表不能为空")
private List<String> paymentVoucherList;
/**
* 账户证明列表
*/
@NotEmpty(message = "账户证明列表不能为空")
private List<String> accountVerificationList;
// /**
// * 支付凭证列表
// */
// @NotEmpty(message = "支付凭证列表不能为空")
// private List<String> paymentVoucherList;
//
// /**
// * 账户证明列表
// */
// @NotEmpty(message = "账户证明列表不能为空")
// private List<String> accountVerificationList;
/**
* 支付凭证列表
......
......@@ -94,7 +94,7 @@ public class ApiSalarySplitSummaryPageDto {
private String status;
/**
* 出账总额
* 出账总额(发放币种金额总额)
*/
private BigDecimal amount;
......@@ -104,7 +104,7 @@ public class ApiSalarySplitSummaryPageDto {
private BigDecimal hkdAmount;
/**
* 出账币种(币种)
* 出账币种(发放币种)
*/
private String currency;
......
......@@ -35,246 +35,136 @@ public class ApiExpectedFortunePageResponse {
@Schema(description = "应付款类型 R-关联保单应付款 U-非关联保单应付款")
private String fortuneBizType;
/**
* 应付款编号
*/
@Schema(description = "应付款编号(业务编号)")
@Schema(description = "业务编号")
private String payableNo;
/**
* 保单号
*/
@Schema(description = "policy no")
private String policyNo;
/**
* 期交保费
*/
@Schema(description = "期交保费")
private BigDecimal premium;
/**
* 保险公司 ID
*/
@Schema(description = "保险公司 ID")
private String insuranceCompanyBizId;
/**
* 保险公司
*/
@Schema(description = "保险公司")
private String insuranceCompany;
/**
* 产品计划 ID
*/
@Schema(description = "产品计划 ID")
private String productLaunchBizId;
/**
* 产品计划
*/
@Schema(description = "产品计划")
private String productName;
/**
* 出账期数(1=第一年; 2=第二年; 3=第三年; 4=第四年; 5=第五年)
*/
@Schema(description = "出账期数")
private Integer fortunePeriod;
/**
* 总期数
*/
@Schema(description = "总期数")
private Integer fortuneTotalPeriod;
/**
* 转介人
*/
@Schema(description = "转介人")
private String broker;
/**
* 转介人业务ID
*/
@Schema(description = "转介人业务ID")
private String brokerBizId;
/**
* 转介人等级名称
*/
@Schema(description = "转介人等级名称")
@Schema(description = "职级")
private String brokerGradeName;
/**
* 团队名称
*/
@Schema(description = "关联人员")
private String amountSourceName;
@Schema(description = "团队名称")
private String team;
/**
* 所属团队业务ID
*/
@Schema(description = "所属团队业务ID")
private String teamBizId;
/**
* 出账项目
*/
@Schema(description = "出账项目")
private String fortuneName;
/**
* 出账项目类型
*/
@Schema(description = "出账项目类型 字典值: csf_fortune_type")
private String fortuneType;
/**
* 持有比例
*/
@Schema(description = "持有比例")
private String brokerRatio;
@Schema(description = "出账状态 0=待出账 1=可出帐,待检核 2=完成出账 3=部分出账 4=保留 5=已失效 6=可出账, 已检核 7=未找到当前预计出账对应的来佣 字典值: csf_expected_fortune_status")
private String status;
@Schema(description = "出账期数")
private Integer fortunePeriod;
// ========== 保单币种及金额(基本法币种) ==========
/**
* 保单币种金额(保单币种金额 = 标准发佣金额 * 转介人介绍费占比)
*/
@Schema(description = "保单币种金额(保单币种金额 = 标准发佣金额 * 转介人介绍费占比)")
private BigDecimal ruleAmount;
@Schema(description = "总期数")
private Integer fortuneTotalPeriod;
/**
* 保单币种
*/
@Schema(description = "保单币种")
private String ruleCurrency;
@Schema(description = "出账年月(估)")
@JsonFormat(pattern = "yyyy-MM", timezone = "GMT+8")
private LocalDate payoutDate;
/**
* 预计出账-默认保单币种汇率(保单币种 -> 港币汇率)
*/
@Schema(description = "预计出账-默认保单币种汇率(保单币种 -> 港币汇率)")
private BigDecimal defaultExchangeRate;
@Schema(description = "出账年月(实)")
@JsonFormat(pattern = "yyyy-MM", timezone = "GMT+8")
private LocalDate actualPayoutDate;
/**
* 预计出账-HKD应出账金额
*/
@Schema(description = "预计出账-HKD应出账金额")
private BigDecimal hkdAmount;
@Schema(description = "入账检核汇率")
private BigDecimal exchangeRate;
@Schema(description = "保单币种->HKD汇率")
private BigDecimal originalToHkdRate;
@Schema(description = "HKD->发放币种汇率")
private BigDecimal hkdToPayoutRate;
@Schema(description = "保单币种")
private String ruleCurrency;
// ========== 原币种及金额 ==========
@Schema(description = "原币种")
private String originalCurrency;
@Schema(description = "发放币种")
private String payoutCurrency;
@Schema(description = "原币种金额")
private BigDecimal originalAmount;
@Schema(description = "原币→港币汇率")
private BigDecimal originalToHkdRate;
@Schema(description = "应发港币金额(估)")
private BigDecimal hkdAmount;
@Schema(description = "应发保单记账金额")
private BigDecimal ruleAmount;
// ========== 发放币种及金额 ==========
@Schema(description = "发放币种")
private String payoutCurrency;
@Schema(description = "发放币种金额")
private BigDecimal payoutAmount;
@Schema(description = "港币→发放币汇率")
private BigDecimal hkdToPayoutRate;
@Schema(description = "本次发放保单记账金额")
private BigDecimal currentPaymentRuleAmount;
@Schema(description = "本次发放金额")
private BigDecimal currentPayoutAmount;
/**
* 实际出账-本次出账金额(HKD)
*/
@Schema(description = "实际出账-本次出账金额(HKD)")
@Schema(description = "本次发放折合港币金额")
private BigDecimal currentPaymentHkdAmount;
/**
* 实际出账-本期结算汇率
*/
@Schema(description = "实际出账-本期结算汇率")
private BigDecimal exchangeRate;
@Schema(description = "本次发放比例")
private BigDecimal currentPaymentRatio;
/**
* 出账币种名称
*/
@Schema(description = "出账币种名称")
private String currencyName;
@Schema(description = "累积已发放保单记账金额")
private BigDecimal paidRuleAmount;
/**
* 出账状态
*/
@Schema(description = "出账状态 0=待出账 1=可出帐,待检核 2=完成出账 3=部分出账 4=保留 5=已失效 6=可出账, 已检核 7=未找到当前预计出账对应的来佣 字典值: csf_expected_fortune_status")
private String status;
@Schema(description = "累积已发放港币金额")
private BigDecimal paidAmount;
/**
* 出账状态-修改理由
*/
@Schema(description = "出账状态-修改理由")
private String statusDesc;
@Schema(description = "累积已发放比例")
private BigDecimal paidRatio;
/**
* 出账年月(估)
*/
@Schema(description = "出账年月(估)")
@JsonFormat(pattern = "yyyy-MM", timezone = "GMT+8")
private LocalDate payoutDate;
@Schema(description = "剩余发放比例")
private BigDecimal unpaidRatio;
/**
* 出账年月(实)
*/
@Schema(description = "出账年月(实)")
@JsonFormat(pattern = "yyyy-MM", timezone = "GMT+8")
private LocalDate actualPayoutDate;
@Schema(description = "剩余保单记账金额")
private BigDecimal unpaidRuleAmount;
/**
* 预计出账-已出账金额(HKD)
*/
@Schema(description = "预计出账-已出账金额(HKD)")
private BigDecimal paidAmount;
@Schema(description = "剩余发放折合港币金额")
private BigDecimal unpaidRuleAmounthHkd;
/**
* 预计出账-待出账金额
*/
@Schema(description = "预计出账-待出账金额")
private BigDecimal unpaidAmount;
@Schema(description = "发放币种金额")
private BigDecimal payoutAmount;
/**
* 预计出账-已出账金额比例 已出账金额/应出账金额
*/
@Schema(description = "预计出账-已出账金额比例 已出账金额/应出账金额")
private BigDecimal paidRatio;
@Schema(description = "期交保费")
private BigDecimal premium;
/**
* 预计出账-待出账比例 待出账金额/应出账金额
*/
@Schema(description = "预计出账-待出账比例 待出账金额/应出账金额")
private BigDecimal unpaidRatio;
@Schema(description = "产品计划 ID")
private String productLaunchBizId;
@Schema(description = "产品计划")
private String productName;
@Schema(description = "持有比例")
private String brokerRatio;
/**
* 备注
*/
@Schema(description = "备注")
private String remark;
/**
* 创建人
*/
@Schema(description = "创建人")
private String creatorName;
/**
* 创建时间
*/
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createTime;
/**
* 更新时间(操作时间)
*/
@Schema(description = "更新时间")
@Schema(description = "更新时间(操作时间)")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime updateTime;
......
package com.yd.csf.service.component;
import com.yd.common.constant.RedisConstants;
import com.yd.common.utils.RedisUtil;
import com.yd.user.feign.client.sysdict.ApiSysDictFeignClient;
import com.yd.user.feign.request.sysdict.GetDictTypeListRequest;
import com.yd.user.feign.response.sysdict.GetDictItemListByDictTypeResponse;
import com.yd.user.feign.response.sysdict.GetDictTypeListResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Component
public class DictCacheService {
@Resource
private RedisUtil redisUtil;
@Resource
private ApiSysDictFeignClient apiSysDictFeignClient;
/**
* 获取字典列表,缓存未命中或缺少指定类型时,按需从Feign拉取并合并写入Redis
*
* @param dictTypes 需要的字典类型编码
*/
public List<GetDictItemListByDictTypeResponse> getDictList(String... dictTypes) {
if (dictTypes == null || dictTypes.length == 0) {
return Collections.emptyList();
}
// 快速路径:从Redis获取缓存
List<GetDictItemListByDictTypeResponse> cached = redisUtil.getCacheObject(RedisConstants.DICT_LIST);
// 收集需要拉取的dictType
Set<String> neededTypes = new HashSet<>(Arrays.asList(dictTypes));
if (CollectionUtils.isEmpty(cached)) {
// 缓存完全为空
return fetchAndCache(neededTypes, Collections.emptyList());
} else {
// 检查缓存中已有哪些类型
Set<String> cachedTypes = cached.stream()
.filter(Objects::nonNull)
.map(GetDictItemListByDictTypeResponse::getDictType)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Set<String> missingTypes = new HashSet<>(neededTypes);
missingTypes.removeAll(cachedTypes);
if (missingTypes.isEmpty()) {
return cached;
}
return fetchAndCache(missingTypes, cached);
}
}
/**
* 加锁从Feign拉取缺失的字典类型,合并到已有缓存并写回Redis
*/
private List<GetDictItemListByDictTypeResponse> fetchAndCache(Set<String> missingTypes, List<GetDictItemListByDictTypeResponse> existingCache) {
synchronized (this) {
// 双重检查:再次从Redis读取,防止并发时重复拉取
List<GetDictItemListByDictTypeResponse> cached = redisUtil.getCacheObject(RedisConstants.DICT_LIST);
if (!CollectionUtils.isEmpty(cached)) {
Set<String> cachedTypes = cached.stream()
.filter(Objects::nonNull)
.map(GetDictItemListByDictTypeResponse::getDictType)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
missingTypes.removeAll(cachedTypes);
if (missingTypes.isEmpty()) {
return cached;
}
existingCache = cached;
}
// 从Feign拉取缺失类型
List<GetDictItemListByDictTypeResponse> fetched = fetchFromFeign(missingTypes);
// 合并并去重
List<GetDictItemListByDictTypeResponse> merged = mergeCache(existingCache, fetched);
if (!CollectionUtils.isEmpty(merged)) {
redisUtil.setCacheObject(RedisConstants.DICT_LIST, merged);
}
return merged;
}
}
/**
* 调用Feign拉取指定字典类型的数据
*/
private List<GetDictItemListByDictTypeResponse> fetchFromFeign(Set<String> dictTypes) {
try {
GetDictTypeListRequest request = new GetDictTypeListRequest();
request.setTypeList(new ArrayList<>(dictTypes));
List<GetDictTypeListResponse> dictTypeResponses = apiSysDictFeignClient.getByDictTypeList(request).getData();
if (CollectionUtils.isEmpty(dictTypeResponses)) {
log.warn("Feign返回空字典列表, 请求类型: {}", dictTypes);
return Collections.emptyList();
}
return dictTypeResponses.stream()
.filter(Objects::nonNull)
.filter(dtr -> dtr.getDictItemList() != null)
.flatMap(dtr -> dtr.getDictItemList().stream())
.collect(Collectors.toList());
} catch (Exception e) {
log.error("从Feign拉取字典数据失败, 请求类型: {}", dictTypes, e);
return Collections.emptyList();
}
}
/**
* 合并已有缓存与新拉取数据,按 dictType + itemValue 去重
*/
private List<GetDictItemListByDictTypeResponse> mergeCache(
List<GetDictItemListByDictTypeResponse> existing,
List<GetDictItemListByDictTypeResponse> fetched) {
Map<String, GetDictItemListByDictTypeResponse> merged = new LinkedHashMap<>();
// 先放入已有缓存
for (GetDictItemListByDictTypeResponse item : existing) {
if (item != null && item.getDictType() != null && item.getItemValue() != null) {
String key = item.getDictType() + ":" + item.getItemValue();
merged.put(key, item);
}
}
// 再放入新拉取数据(覆盖相同key的旧值)
for (GetDictItemListByDictTypeResponse item : fetched) {
if (item != null && item.getDictType() != null && item.getItemValue() != null) {
String key = item.getDictType() + ":" + item.getItemValue();
merged.put(key, item);
}
}
return new ArrayList<>(merged.values());
}
}
......@@ -14,6 +14,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.time.LocalDateTime;
import java.util.Date;
@Slf4j
@Configuration
......@@ -33,45 +34,66 @@ public class CsfMybatisPlusConfig {
/**
* 自动填充字段配置(如创建人、更新人等)
*/
/**
* 自动填充字段配置(如创建人、更新人等)
*/
@Bean
@Primary
public MetaObjectHandler metaObjectHandler() {
log.info("MetaObjectHandler Bean 正在创建...","MetaObjectHandler Bean 正在创建==========");
return new MetaObjectHandler() {
@Override
public void insertFill(MetaObject metaObject) {
//获取Security上下文当前用户的登录信息
AuthUserDto authUserDto = null;
try {
authUserDto = SecurityUtil.getCurrentLoginUser();
}catch (Exception e) {
log.info("获取Security上下文当前用户的登录信息失败,{}",e.getMessage());
} catch (Exception e) {
log.info("获取Security上下文当前用户的登录信息失败,{}", e.getMessage());
}
log.info("metaObjectHandler=======insertFill自动填充获取用户信息:{}", JSON.toJSONString(authUserDto));
log.info("metaObjectHandler insertFill 获取用户信息:{}", JSON.toJSONString(authUserDto));
if (authUserDto != null) {
//自动注入创建人和创建用户名
// 仅当字段为空时才填充
if (getFieldValByName("creatorId", metaObject) == null) {
this.strictInsertFill(metaObject, "creatorId", String.class, authUserDto.getUserBizId());
}
if (getFieldValByName("creatorName", metaObject) == null) {
this.strictInsertFill(metaObject, "creatorName", String.class, authUserDto.getRealName());
this.strictUpdateFill(metaObject, "updaterId", String.class, authUserDto.getUserBizId());
this.strictUpdateFill(metaObject, "updaterName", String.class, authUserDto.getRealName());
}
if (getFieldValByName("createTime", metaObject) == null) {
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
}
if (getFieldValByName("updaterId", metaObject) == null) {
this.strictInsertFill(metaObject, "updaterId", String.class, authUserDto.getUserBizId());
}
if (getFieldValByName("updaterName", metaObject) == null) {
this.strictInsertFill(metaObject, "updaterName", String.class, authUserDto.getRealName());
}
if (getFieldValByName("updateTime", metaObject) == null) {
this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
}
}
}
@Override
public void updateFill(MetaObject metaObject) {
//获取Security上下文当前用户的登录信息
AuthUserDto authUserDto = null;
try {
authUserDto = SecurityUtil.getCurrentLoginUser();
}catch (Exception e) {
log.info("获取Security上下文当前用户的登录信息失败,{}",e.getMessage());
} catch (Exception e) {
log.info("获取Security上下文当前用户的登录信息失败,{}", e.getMessage());
}
log.info("metaObjectHandler=======updateFill自动填充获取用户信息:{}", JSON.toJSONString(authUserDto));
log.info("metaObjectHandler updateFill 获取用户信息:{}", JSON.toJSONString(authUserDto));
if (authUserDto != null) {
//自动注入更新人和更新用户名
// 仅当字段为空时才填充
if (getFieldValByName("updaterId", metaObject) == null) {
this.strictUpdateFill(metaObject, "updaterId", String.class, authUserDto.getUserBizId());
}
if (getFieldValByName("updaterName", metaObject) == null) {
this.strictUpdateFill(metaObject, "updaterName", String.class, authUserDto.getRealName());
}
if (getFieldValByName("updateTime", metaObject) == null) {
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
}
}
}
};
}
......
package com.yd.csf.service.config;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class MethodTimeAspect {
@Around("execution(* com.yd.csf.service..*.*(..))")
public Object measure(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed();
long cost = System.currentTimeMillis() - start;
log.info("【性能】{}.{} 耗时 {} ms",
pjp.getTarget().getClass().getSimpleName(),
pjp.getSignature().getName(),
cost);
return result;
}
}
\ No newline at end of file
package com.yd.csf.service.dao;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yd.csf.service.dto.CommissionExpectedQueryRequest;
import com.yd.csf.service.model.CommissionExpected;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yd.csf.service.vo.CommissionExpectedStatisticsVO;
......@@ -28,6 +31,9 @@ public interface CommissionExpectedMapper extends BaseMapper<CommissionExpected>
*/
IPage<ReceivableReportVO> receivableReportPage(@Param("page") Page<ReceivableReportVO> page,
@Param("expectedIds") List<Long> expectedIds);
// IPage<ReceivableReportVO> receivableReportPage(Page<ReceivableReportVO> page,
// @Param("query") CommissionExpectedQueryRequest query);
}
......
......@@ -33,11 +33,11 @@ public interface ExpectedFortuneMapper extends BaseMapper<ExpectedFortune> {
/**
* 应付款报表 - 按保单号和期数维度统计(分页)
* @param page 分页参数
* @param expectedFortuneIds 预计发佣ID列表
* @param queryWrapper 查询条件
* @return 应付款报表VO分页列表
*/
IPage<PayableReportVO> payableReportPage(@Param("page") Page<PayableReportVO> page,
@Param("expectedFortuneIds") List<Long> expectedFortuneIds);
@Param("ew") QueryWrapper<ExpectedFortune> queryWrapper);
/**
* 更新预计发佣记录的出账状态
......@@ -68,4 +68,11 @@ public interface ExpectedFortuneMapper extends BaseMapper<ExpectedFortune> {
* @return 统计信息
*/
ExpectedFortuneStatisticsVO queryListStatistics(@Param("ew") QueryWrapper<ExpectedFortune> queryWrapper);
/**
* 查询预计发佣和实际发佣的全部列表(无分页,用于导出)
* @param queryWrapper 查询条件
* @return 全部列表数据
*/
List<ApiExpectedFortunePageResponse> queryListAll(@Param("ew") QueryWrapper<ExpectedFortune> queryWrapper);
}
......@@ -25,11 +25,14 @@ public class FortuneAccountExportDTO implements Serializable {
private String teamBizId;
@ExcelProperty("出账币种")
private String currency;
@ExcelProperty("发放币种")
private String payoutCurrency;
@ExcelProperty("出账总额")
private BigDecimal amount;
@ExcelProperty("发放金额")
private BigDecimal payoutAmount;
@ExcelProperty("出账港币总额")
private BigDecimal hkdAmount;
private List<Fortune> fortuneList;
......
......@@ -26,11 +26,20 @@ public class FortuneAccountQueryRequest extends PageDto {
@Schema(description = "出账状态, 可多选 字典值:csf_fortune_account_status")
private List<String> statusList;
@Schema(description = "出账日期开始", format = "date")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date accountDateStart;
@Schema(description = "出账日期结束", format = "date")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date accountDateEnd;
//这样前端传 accountDateStart = 2026-09吗
// @Schema(description = "出账日期开始", format = "date")
// @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
// private Date accountDateStart;
//
// @Schema(description = "出账日期结束", format = "date")
// @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
// private Date accountDateEnd;
@Schema(description = "出账日期开始")
private String accountDateStart;
@Schema(description = "出账日期结束")
private String accountDateEnd;
private String businessNo;
}
......@@ -42,9 +42,9 @@ public class FortuneQueryRequest extends PageDto implements Serializable {
private List<String> commissionStatusList;
/**
* 转介人(主)
* 转介人
*/
@Schema(description = "转介人(主)")
@Schema(description = "转介人")
private String brokerName;
/**
......
package com.yd.csf.service.enums;
/**
* 基本法类型枚举
*/
public enum CommissionRuleConfigEnum {
BZ_JBF("commission_rule_config_dJea6a7rM8j38zK5","RULE6623256596","标准基本法"),
;
/**
* 基本法配置表唯一业务ID
*/
private String ruleBizId;
/**
* 基本法编码
*/
private String ruleCode;
/**
* 基本法名称
*/
private String ruleName;
//构造函数
CommissionRuleConfigEnum(String ruleBizId, String ruleCode,String ruleName) {
this.ruleBizId = ruleBizId;
this.ruleCode = ruleCode;
this.ruleName = ruleName;
}
public String getRuleBizId() {
return ruleBizId;
}
public String getRuleCode() {
return ruleCode;
}
public String getRuleName() {
return ruleName;
}
}
package com.yd.csf.service.enums;
/**
* 基本法项目枚举
*/
public enum RuleItemConfigEnum {
XS_YJ("rule_item_config_FePX0vpJQ9bU1vEo","commission_rule_config_dJea6a7rM8j38zK5","ITEM4736190590","销售佣金"),
XQ_XS_YJ("rule_item_config_Gxw21FGdwg29RFz","commission_rule_config_dJea6a7rM8j38zK5","ITEM4570368732","续期销售佣金"),
;
/**
* 基本法项目配置表唯一业务ID
*/
private String ruleItemBizId;
/**
* 基本法配置表唯一业务ID
*/
private String ruleBizId;
/**
* 基本法项目编码
*/
private String itemCode;
/**
* 基本法项目名称
*/
private String itemName;
//构造函数
RuleItemConfigEnum(String ruleItemBizId, String ruleBizId,String itemCode,String itemName) {
this.ruleItemBizId = ruleItemBizId;
this.ruleBizId = ruleBizId;
this.itemCode = itemCode;
this.itemName = itemName;
}
public String getRuleItemBizId() {
return ruleItemBizId;
}
public String getRuleBizId() {
return ruleBizId;
}
public String getItemCode() {
return itemCode;
}
public String getItemName() {
return itemName;
}
}
......@@ -189,11 +189,13 @@ public class Commission implements Serializable {
/**
* 创建时间
*/
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
/**
* 更新时间
*/
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
@TableField(exist = false)
......
......@@ -133,6 +133,18 @@ public class ExpectedFortune implements Serializable {
private String fortuneType;
/**
* 奖金来源人id(类型:转介人等,如果是转介人,这里就是这个奖来自这个转介人身上的)
*/
@TableField("amount_source_id")
private String amountSourceId;
/**
* 奖金来源人名称(类型:转介人等)
*/
@TableField("amount_source_name")
private String amountSourceName;
/**
* 转介人介绍费占比
*/
@TableField("broker_ratio")
......@@ -164,6 +176,24 @@ public class ExpectedFortune implements Serializable {
private String ruleCurrency;
/**
* 累积已发放保单记账金额
*/
@TableField("paid_rule_amount")
private BigDecimal paidRuleAmount;
/**
* 剩余保单记账金额
*/
@TableField("unpaid_rule_amount")
private BigDecimal unpaidRuleAmount;
/**
* 剩余发放折合港币金额
*/
@TableField("unpaid_rule_amount_hkd")
private BigDecimal unpaidRuleAmountHkd;
/**
* 出账状态 0=待出账 1=可出帐 2=可出帐,待检核 3=部分出账 4=保留 5=已失效 6=可出账, 已检核 7=未找到当前预计发佣对应的来佣 字典值: csf_expected_fortune_status
*/
@TableField("status")
......
......@@ -54,17 +54,17 @@ public class FortuneAccount implements Serializable {
private String teamBizId;
/**
* 出账币种
* 发放币种
*/
private String currency;
private String payoutCurrency;
/**
* 出账总
* 发放金
*/
private BigDecimal amount;
private BigDecimal payoutAmount;
/**
* 港币出账金额
* 港币金额
*/
private BigDecimal hkdAmount;
......
......@@ -60,7 +60,7 @@ public interface CommissionExpectedService extends IService<CommissionExpected>
CommissionExpectedStatisticsVO getExpectedStatistics(List<Long> expectedIds);
CommissionExpectedStatisticsVO getExpectedStatisticsNew(List<Long> expectedIds);
CommissionExpectedStatisticsVO getExpectedStatisticsNew(List<CommissionExpected> allExpectedList);
CommissionExpected getByBizId(String commissionExpectedBizId);
......@@ -84,7 +84,10 @@ public interface CommissionExpectedService extends IService<CommissionExpected>
*/
IPage<ReceivableReportVO> receivableReportPage(Page<ReceivableReportVO> page, List<Long> expectedIds);
void testExpectedCommission(String policyNo,String effectiveDate,String coolingOffEndDate) throws IOException;
// IPage<ReceivableReportVO> receivableReportPage(Page<ReceivableReportVO> page,
// CommissionExpectedQueryRequest query);
void testExpectedCommission(String policyNo, String effectiveDate, String coolingOffEndDate) throws IOException;
Boolean changeStatus(CommissionExpectedChangeStatusRequest commissionExpectedChangeStatusRequest);
......
......@@ -70,5 +70,5 @@ public interface CommissionService extends IService<Commission> {
*/
BigDecimal queryCommissionExchangeRate(String policyNo, Integer commissionPeriod);
Long queryCount(String commissionExpectedBizId);
}
......@@ -10,7 +10,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.yd.csf.service.vo.ExpectedFortuneStatisticsVO;
import com.yd.csf.service.vo.PayableReportVO;
import java.time.LocalDate;
import java.util.List;
/**
......@@ -42,10 +41,10 @@ public interface IExpectedFortuneService extends IService<ExpectedFortune> {
* 应付款报表 - 按保单号和期数维度统计(分页)
*
* @param page 分页参数
* @param expectedFortuneIds 预计发佣ID列表
* @param queryWrapper 查询条件
* @return 应付款报表VO分页列表
*/
IPage<PayableReportVO> payableReportPage(Page<PayableReportVO> page, List<Long> expectedFortuneIds);
IPage<PayableReportVO> payableReportPage(Page<PayableReportVO> page, QueryWrapper<ExpectedFortune> queryWrapper);
void updateBatchByBizId(List<String> expectedFortuneBizIdList, String status);
......@@ -80,4 +79,12 @@ public interface IExpectedFortuneService extends IService<ExpectedFortune> {
* @return 统计信息
*/
ExpectedFortuneStatisticsVO queryListStatistics(QueryWrapper<ExpectedFortune> queryWrapper);
/**
* 查询预计发佣和实际发佣的全部列表(无分页,用于导出)
*
* @param queryWrapper 查询条件
* @return 全部列表数据
*/
List<ApiExpectedFortunePageResponse> queryListAll(QueryWrapper<ExpectedFortune> queryWrapper);
}
......@@ -15,6 +15,9 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yd.base.feign.client.exchangerate.ApiExchangeRateFeignClient;
import com.yd.base.feign.dto.ApiQueryBatchExchangeRateDTO;
import com.yd.base.feign.request.exchangerate.ApiQueryBatchExchangeRateRequest;
import com.yd.base.feign.response.exchangerate.ApiQueryBatchExchangeRateResponse;
import com.yd.common.constant.CommonConstant;
import com.yd.common.constant.RedisConstants;
import com.yd.common.enums.ResultCode;
......@@ -22,6 +25,7 @@ import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import com.yd.common.utils.RandomStringGenerator;
import com.yd.common.utils.RedisUtil;
import com.yd.csf.service.component.DictCacheService;
import com.yd.csf.service.component.ReceivableService;
import com.yd.csf.service.dto.*;
import com.yd.csf.service.enums.CommissionExpectedStatusEnum;
......@@ -94,6 +98,8 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
private CustomerService customerService;
@Resource
private CommissionExpectedService commissionExpectedService;
@Resource
private DictCacheService dictCacheService;
// 用于对象转换的ObjectMapper
private static final ObjectMapper objectMapper = new ObjectMapper();
......@@ -877,10 +883,14 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP)
);
commissionExpected.setPremium(policy.getPaymentPremium());
//查询实际来用数据量
Long count = commissionService.queryCount(commissionExpected.getCommissionExpectedBizId());
//已入账比例
BigDecimal paidRatio = ObjectUtils.defaultIfNull(commissionExpected.getPaidRatio(), BigDecimal.ZERO);
//预计入账比例(保单产品来佣金率)
BigDecimal commissionRatio = ObjectUtils.defaultIfNull(commissionExpected.getCommissionRatio(), BigDecimal.ZERO);
if (count > 0){
//判断下面的前提是必须有实际的数据
//已入账比例 >= 预计入账比例 -> 入账状态置为完成入账。否则部分入账
if (paidRatio.compareTo(commissionRatio) >= 0) {
//完成入账
......@@ -889,6 +899,7 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
//部分入账
commissionExpected.setStatus("2");
}
}
} else {
commissionExpected.setExpectedAmount(
commissionExpectedUpdateRequest.getAmount()
......@@ -961,34 +972,118 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
return commissionStatistics;
}
// @Override
// public CommissionExpectedStatisticsVO getExpectedStatisticsNew(List<CommissionExpected> allExpectedList) {
// // 空集合直接返回空统计
// if (CollectionUtils.isEmpty(allExpectedList)) {
// return emptyStatistics();
// }
//
// // 查询所有记录(包含失效状态)
//// List<CommissionExpected> allExpectedList = this.listByIds(expectedIds);
//// if (CollectionUtils.isEmpty(allExpectedList)) {
//// return emptyStatistics();
//// }
//
// // 过滤掉已失效的记录(status = "3")
// List<CommissionExpected> validList = allExpectedList.stream()
// .filter(e -> !"3".equals(e.getStatus()))
// .collect(Collectors.toList());
//
// if (validList.isEmpty()) {
// return emptyStatistics();
// }
//
// // 手动聚合计算
// BigDecimal totalAmount = BigDecimal.ZERO;
// BigDecimal totalPaidAmount = BigDecimal.ZERO;
// //累计已入账来佣比例(同保单多个入账项目累计的实佣率)
// BigDecimal totalPaidRatio = BigDecimal.ZERO;
// //累计来佣比例(同保单多个入账项目累计的产品来佣率)
// BigDecimal totalCommissionRatio = BigDecimal.ZERO;
// Set<String> policyNoSet = new HashSet<>();
//
// for (CommissionExpected expected : validList) {
// totalAmount = totalAmount.add(ObjectUtils.defaultIfNull(expected.getExpectedAmount(), BigDecimal.ZERO));
// totalPaidAmount = totalPaidAmount.add(ObjectUtils.defaultIfNull(expected.getPaidAmount(), BigDecimal.ZERO));
// totalPaidRatio = totalPaidRatio.add(ObjectUtils.defaultIfNull(expected.getPaidRatio(), BigDecimal.ZERO));
// totalCommissionRatio = totalCommissionRatio.add(ObjectUtils.defaultIfNull(expected.getCommissionRatio(), BigDecimal.ZERO));
// if (StringUtils.isNotBlank(expected.getPolicyNo())) {
// policyNoSet.add(expected.getPolicyNo());
// }
// }
//
// // 计算总保费(HKD)
// BigDecimal totalPremium = BigDecimal.ZERO;
// BigDecimal fromTotalPremium = BigDecimal.ZERO;
// if (CollectionUtils.isNotEmpty(policyNoSet)) {
// List<Policy> policyList = policyService.lambdaQuery()
// .select(Policy::getPolicyNo,
// Policy::getTotalPaymentPremium,
// Policy::getCurrency)
// .in(Policy::getPolicyNo, policyNoSet)
// .list();
// if (CollectionUtils.isNotEmpty(policyList)) {
// for (Policy policy : policyList) {
// // 获取保单币种到港币的汇率
// BigDecimal rate = queryExchangeRateByFeign(policy.getCurrency(), "HKD");
// if (rate == null) rate = BigDecimal.ONE;
// totalPremium = totalPremium.add(policy.getTotalPaymentPremium().multiply(rate));
// fromTotalPremium = fromTotalPremium.add(policy.getTotalPaymentPremium());
// }
// }
// }
//
// // 组装返回对象
// CommissionExpectedStatisticsVO vo = new CommissionExpectedStatisticsVO();
// vo.setTotalAmount(totalAmount);
// vo.setTotalPaidAmount(totalPaidAmount);
// vo.setPendingPaidAmountS(totalAmount.subtract(totalPaidAmount));
//
// if (totalAmount.compareTo(BigDecimal.ZERO) > 0) {
// BigDecimal ratio = totalPaidAmount.divide(totalAmount, 4, RoundingMode.HALF_UP)
// .multiply(BigDecimal.valueOf(100));
// vo.setPaidAmountRatio(ratio);
// } else {
// vo.setPaidAmountRatio(BigDecimal.ZERO);
// }
//
// // 待入账金额归零 = 已入账来佣比例(累计实佣率)>= 累计产品来佣率
//// if (totalPaidRatio.compareTo(totalCommissionRatio) >= 0){
//// vo.setPendingPaidAmount(BigDecimal.ZERO);
//// }
// vo.setPendingPaidAmount(totalAmount);
// vo.setTotalPolicyCount(policyNoSet.size());
// vo.setTotalPremium(totalPremium);
// vo.setFromTotalPremium(fromTotalPremium);
// vo.setPolicyNos(null); // 原字段可能用于其他逻辑,此处置空
// return vo;
// }
@Override
public CommissionExpectedStatisticsVO getExpectedStatisticsNew(List<Long> expectedIds) {
// 空集合直接返回空统计
if (CollectionUtils.isEmpty(expectedIds)) {
return emptyStatistics();
}
public CommissionExpectedStatisticsVO getExpectedStatisticsNew(List<CommissionExpected> allExpectedList) {
long t0 = System.currentTimeMillis();
log.info("getExpectedStatisticsNew 开始, 输入大小: {}", allExpectedList == null ? 0 : allExpectedList.size());
// 查询所有记录(包含失效状态)
List<CommissionExpected> allExpectedList = this.listByIds(expectedIds);
if (CollectionUtils.isEmpty(allExpectedList)) {
return emptyStatistics();
}
// 过滤掉已失效的记录(status = "3")
long t1 = System.currentTimeMillis();
List<CommissionExpected> validList = allExpectedList.stream()
.filter(e -> !"3".equals(e.getStatus()))
.collect(Collectors.toList());
log.info("过滤 status=3 耗时: {} ms, 有效数量: {}", System.currentTimeMillis() - t1, validList.size());
if (validList.isEmpty()) {
return emptyStatistics();
}
long t2 = System.currentTimeMillis();
// 手动聚合计算
BigDecimal totalAmount = BigDecimal.ZERO;
BigDecimal totalPaidAmount = BigDecimal.ZERO;
//累计已入账来佣比例(同保单多个入账项目累计的实佣率)
BigDecimal totalPaidRatio = BigDecimal.ZERO;
//累计来佣比例(同保单多个入账项目累计的产品来佣率)
BigDecimal totalCommissionRatio = BigDecimal.ZERO;
Set<String> policyNoSet = new HashSet<>();
......@@ -1001,30 +1096,69 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
policyNoSet.add(expected.getPolicyNo());
}
}
log.info("内存聚合耗时: {} ms, 保单数: {}", System.currentTimeMillis() - t2, policyNoSet.size());
// 计算总保费(HKD)
long t3 = System.currentTimeMillis();
// 计算总保费
BigDecimal totalPremium = BigDecimal.ZERO;
BigDecimal fromTotalPremium = BigDecimal.ZERO;
if (CollectionUtils.isNotEmpty(policyNoSet)) {
List<Policy> policyList = policyService.lambdaQuery()
.select(Policy::getPolicyNo,
Policy::getTotalPaymentPremium,
Policy::getCurrency)
.in(Policy::getPolicyNo, policyNoSet)
.list();
log.info("查询保单信息耗时: {} ms, 结果数量: {}", System.currentTimeMillis() - t3, policyList.size());
if (CollectionUtils.isNotEmpty(policyList)) {
// 1. 收集所有需要查询的币种(去重)
Set<String> currencies = policyList.stream()
.map(Policy::getCurrency)
.filter(StringUtils::isNotBlank)
.collect(Collectors.toSet());
// 2. 构建批量查询请求(币种 -> HKD)
ApiQueryBatchExchangeRateRequest batchRequest = new ApiQueryBatchExchangeRateRequest();
List<ApiQueryBatchExchangeRateDTO> dtoList = new ArrayList<>();
for (String currency : currencies) {
ApiQueryBatchExchangeRateDTO dto = new ApiQueryBatchExchangeRateDTO();
dto.setBaseCurrency(currency);
dto.setTargetCurrency("HKD");
dtoList.add(dto);
}
batchRequest.setRateDTOList(dtoList);
// 3. 调用批量汇率接口
Result<ApiQueryBatchExchangeRateResponse> batchResult = apiExchangeRateFeignClient.queryBatchExchangeRate(batchRequest);
Map<String, BigDecimal> rateMap = new HashMap<>();
if (batchResult != null && batchResult.getCode() == 200 && batchResult.getData() != null) {
List<ApiQueryBatchExchangeRateDTO> resultList = batchResult.getData().getRateDTOList();
for (ApiQueryBatchExchangeRateDTO result : resultList) {
if (result.getExchangeRate() != null) {
rateMap.put(result.getBaseCurrency(), result.getExchangeRate());
}
}
}
// 4. 循环计算总保费,从 map 中取汇率
long t4 = System.currentTimeMillis();
for (Policy policy : policyList) {
// 获取保单币种到港币的汇率
BigDecimal rate = queryExchangeRateByFeign(policy.getCurrency(), "HKD");
if (rate == null) rate = BigDecimal.ONE;
BigDecimal rate = rateMap.getOrDefault(policy.getCurrency(), BigDecimal.ONE);
totalPremium = totalPremium.add(policy.getTotalPaymentPremium().multiply(rate));
fromTotalPremium = fromTotalPremium.add(policy.getTotalPaymentPremium());
}
log.info("汇率计算及保费累加耗时: {} ms", System.currentTimeMillis() - t4);
}
}
// 组装返回对象
CommissionExpectedStatisticsVO vo = new CommissionExpectedStatisticsVO();
vo.setTotalAmount(totalAmount);
vo.setTotalPaidAmount(totalPaidAmount);
vo.setPendingPaidAmount(totalAmount.subtract(totalPaidAmount));
vo.setPendingPaidAmountS(totalAmount.subtract(totalPaidAmount));
if (totalAmount.compareTo(BigDecimal.ZERO) > 0) {
BigDecimal ratio = totalPaidAmount.divide(totalAmount, 4, RoundingMode.HALF_UP)
......@@ -1035,9 +1169,10 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
}
// 待入账金额归零 = 已入账来佣比例(累计实佣率)>= 累计产品来佣率
if (totalPaidRatio.compareTo(totalCommissionRatio) >= 0){
vo.setPendingPaidAmount(BigDecimal.ZERO);
}
// if (totalPaidRatio.compareTo(totalCommissionRatio) >= 0){
// vo.setPendingPaidAmount(BigDecimal.ZERO);
// }
vo.setPendingPaidAmount(totalAmount);
vo.setTotalPolicyCount(policyNoSet.size());
vo.setTotalPremium(totalPremium);
vo.setFromTotalPremium(fromTotalPremium);
......@@ -1094,7 +1229,7 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
throw new BusinessException("保单供款年期不能为空");
}
//查询redis缓存的字典列表信息
List<GetDictItemListByDictTypeResponse> dictTypeResponses = redisUtil.getCacheObject(RedisConstants.DICT_LIST);
List<GetDictItemListByDictTypeResponse> dictTypeResponses = dictCacheService.getDictList("csf_commission_type");
if (StringUtils.isNotBlank(productLaunchBizId)) {
List<ApiExpectedSpeciesListResponse> expectedSpeciesList = queryExpectedSpeciesByFeign(productLaunchBizId);
......@@ -1165,6 +1300,8 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
commissionExpected.setUpdaterId("");
commissionExpected.setCreateTime(new Date());
commissionExpected.setUpdateTime(new Date());
commissionExpected.setCreatorName("系统生成");
commissionExpected.setUpdaterName("系统生成");
commissionExpectedList.add(commissionExpected);
}
......@@ -1475,6 +1612,12 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
return baseMapper.receivableReportPage(page, expectedIds);
}
// @Override
// public IPage<ReceivableReportVO> receivableReportPage(Page<ReceivableReportVO> page,
// CommissionExpectedQueryRequest query){
// return baseMapper.receivableReportPage(page, query);
// };
@Override
public void testExpectedCommission(String policyNo,String effectiveDate,String coolingOffEndDate) throws IOException {
PolicyFollow policyFollow = policyFollowService.queryOneByPolicyNo(policyNo);
......
......@@ -648,7 +648,7 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
// 2. 根据本次发佣期数,删除未出账的记录
List<Fortune> fortuneList = fortuneService.lambdaQuery()
.eq(Fortune::getStatus, FortuneStatusEnum.CAN_SEND.getItemValue())
.in(Fortune::getStatus, FortuneStatusEnum.CAN_SEND.getItemValue(), FortuneStatusEnum.WAIT.getItemValue())
.in(Fortune::getExpectedFortuneBizId, filteredExpectedFortuneList1.stream().map(ExpectedFortune::getExpectedFortuneBizId).collect(Collectors.toList()))
.list();
......@@ -779,31 +779,41 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
String key = buildPolicyPeriodKey(expectedFortune.getPolicyNo(), expectedFortune.getFortunePeriod());
BigDecimal exchangeRate = exchangeRateMap.get(key);
if (exchangeRate != null) {
// 入账检核汇率 — 仅审计追溯,始终写入
fortune.setExchangeRate(exchangeRate);
// 判断 expectedFortune.originalCurrency 、入账币种-fortune.currency 是否都等于 HKD
Commission matchedCommission = commissionByPolicyPeriod.get(key);
boolean isAllHkd = matchedCommission != null
&& "HKD".equalsIgnoreCase(expectedFortune.getOriginalCurrency())
&& "HKD".equalsIgnoreCase(matchedCommission.getCurrency());
if (isAllHkd) {
// 原币种 = HKD 时,exchangeRate = 保单币种 → 港币,可安全使用
fortune.setOriginalToHkdRate(exchangeRate);
// 重新计算港币金额
BigDecimal hkdAmount = fortune.getRuleAmount().multiply(exchangeRate);
fortune.setHkdAmount(hkdAmount);
fortune.setCurrentPaymentAmount(hkdAmount);
fortune.setCurrentPaymentAmount(fortune.getRuleAmount());
fortune.setCurrentPaymentHkdAmount(hkdAmount);
// 默认发放币种、汇率、发放币种金额
fortune.setPayoutCurrency("HKD");
fortune.setHkdToPayoutRate(BigDecimal.ONE);
fortune.setPayoutAmount(hkdAmount);
BigDecimal payoutAmount = hkdAmount.multiply(expectedFortune.getHkdToPayoutRate());
fortune.setPayoutAmount(payoutAmount);
// 更新预计发佣记录的港币金额
ExpectedFortune update = new ExpectedFortune();
update.setId(expectedFortune.getId());
update.setDefaultExchangeRate(exchangeRate);
update.setOriginalToHkdRate(exchangeRate);
update.setHkdAmount(hkdAmount);
update.setUnpaidAmount(hkdAmount);
update.setPayoutCurrency("HKD");
update.setHkdToPayoutRate(BigDecimal.ONE);
update.setPayoutAmount(hkdAmount);
update.setUnpaidRuleAmountHkd(hkdAmount);
update.setPayoutAmount(payoutAmount);
updatedExpectedFortuneList.add(update);
} else {
// 入账币种 ≠ HKD,无法推导保单币种 → 港币,用 ExpectedFortune 已有默认值
fortune.setExchangeRate(expectedFortune.getDefaultExchangeRate());
fortune.setCurrentPaymentAmount(expectedFortune.getOriginalAmount());
fortune.setCurrentPaymentHkdAmount(expectedFortune.getHkdAmount());
}
} else {
fortune.setExchangeRate(expectedFortune.getDefaultExchangeRate());
fortune.setCurrentPaymentAmount(expectedFortune.getOriginalAmount());
fortune.setCurrentPaymentHkdAmount(expectedFortune.getHkdAmount());
......@@ -1265,6 +1275,14 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
return commissionRecord.getExchangeRate();
}
@Override
public Long queryCount(String commissionExpectedBizId) {
return this.baseMapper.selectCount(new LambdaQueryWrapper<Commission>()
.eq(Commission::getCommissionExpectedBizId,commissionExpectedBizId)
.eq(Commission::getIsDeleted,0)
);
}
/**
* 查询列表
......
......@@ -105,8 +105,6 @@ public class ExpectedFortuneServiceImpl extends ServiceImpl<ExpectedFortuneMappe
Map<String, PolicyFollow> policyFollowMap = policyFollowService.queryPolicyFollowMap(policyNoList);
for (ApiExpectedFortunePageResponse vo : expectedFortuneList) {
// 出账币种名称
vo.setCurrencyName("港币");
UserGradeDto userGradeDto = userGradeMap.get(vo.getBrokerBizId());
if (userGradeDto != null) {
......@@ -115,7 +113,6 @@ public class ExpectedFortuneServiceImpl extends ServiceImpl<ExpectedFortuneMappe
PolicyFollow policyFollow = policyFollowMap.get(vo.getPolicyNo());
if (policyFollow != null) {
vo.setInsuranceCompany(policyFollow.getInsuranceCompany());
vo.setProductName(policyFollow.getProductName());
}
}
......@@ -159,12 +156,18 @@ public class ExpectedFortuneServiceImpl extends ServiceImpl<ExpectedFortuneMappe
// 查找对应的实际发佣
List<ApiExpectedFortunePageResponse> matchedList = actualMap.get(expected.getExpectedFortuneBizId());
if (CollUtil.isNotEmpty(matchedList)) {
// 设置实际出账记录的字段:待出账金额(估)、已出账比例、未出账比例、已出账金额
// 设置实际出账记录的字段:持有比例、保费、关联人员、累积已发放保单记账金额、累积已发放港币金额、累积已发放比例%、剩余发放比例%、剩余保单记账金额、剩余发放折合港币金额
matchedList.forEach(actual -> {
actual.setUnpaidAmount(expected.getHkdAmount());
actual.setBrokerRatio(expected.getBrokerRatio());
actual.setPremium(expected.getPremium());
actual.setAmountSourceName(expected.getAmountSourceName());
actual.setPaidRuleAmount(expected.getPaidRuleAmount());
actual.setPaidAmount(expected.getPaidAmount());
actual.setPaidRatio(expected.getPaidRatio());
actual.setUnpaidRatio(expected.getUnpaidRatio());
actual.setPaidAmount(expected.getPaidAmount());
actual.setUnpaidRuleAmount(expected.getUnpaidRuleAmount());
actual.setUnpaidRuleAmounthHkd(expected.getUnpaidRuleAmounthHkd());
});
sortedList.addAll(matchedList);
......@@ -240,8 +243,6 @@ public class ExpectedFortuneServiceImpl extends ServiceImpl<ExpectedFortuneMappe
ApiExpectedFortunePageResponse vo = new ApiExpectedFortunePageResponse();
BeanUtils.copyProperties(ef, vo);
vo.setCurrencyName("港币");
String ratio = finalBrokerRatioMap.get(ef.getBrokerBizId());
vo.setCommissionRatio(ratio);
......@@ -252,7 +253,6 @@ public class ExpectedFortuneServiceImpl extends ServiceImpl<ExpectedFortuneMappe
vo.setBrokerGradeName(userGradeDto.getGradeName());
}
if (policy != null) {
vo.setInsuranceCompany(policy.getInsuranceCompany());
vo.setPremium(policy.getPaymentPremium());
}
if (follow != null) {
......@@ -266,8 +266,8 @@ public class ExpectedFortuneServiceImpl extends ServiceImpl<ExpectedFortuneMappe
}
@Override
public IPage<PayableReportVO> payableReportPage(Page<PayableReportVO> page, List<Long> expectedFortuneIds) {
return baseMapper.payableReportPage(page, expectedFortuneIds);
public IPage<PayableReportVO> payableReportPage(Page<PayableReportVO> page, QueryWrapper<ExpectedFortune> queryWrapper) {
return baseMapper.payableReportPage(page, queryWrapper);
}
@Override
......@@ -353,4 +353,39 @@ public class ExpectedFortuneServiceImpl extends ServiceImpl<ExpectedFortuneMappe
return statistics;
}
@Override
public List<ApiExpectedFortunePageResponse> queryListAll(QueryWrapper<ExpectedFortune> queryWrapper) {
// 1. 查询全量数据
List<ApiExpectedFortunePageResponse> records = this.baseMapper.queryListAll(queryWrapper);
if (CollUtil.isEmpty(records)) {
return Collections.emptyList();
}
// 2. 调整数据顺序、格式(与 /list 一致)
processData(records);
// 3. 补充转介人职级信息
List<String> brokerBizIds = records.stream().map(ApiExpectedFortunePageResponse::getBrokerBizId).collect(Collectors.toList());
Map<String, UserGradeDto> userGradeMap = iAgentAccumulatedFycService.queryUserGradeMap(brokerBizIds);
// 4. 补充产品计划信息
Set<String> policyNoList = records.stream().map(ApiExpectedFortunePageResponse::getPolicyNo).collect(Collectors.toSet());
Map<String, PolicyFollow> policyFollowMap = policyFollowService.queryPolicyFollowMap(policyNoList);
// 5. 补充关联人员信息
for (ApiExpectedFortunePageResponse vo : records) {
UserGradeDto userGradeDto = userGradeMap.get(vo.getBrokerBizId());
if (userGradeDto != null) {
vo.setBrokerGradeName(userGradeDto.getGradeName());
}
PolicyFollow policyFollow = policyFollowMap.get(vo.getPolicyNo());
if (policyFollow != null) {
vo.setProductName(policyFollow.getProductName());
}
}
return records;
}
}
......@@ -80,14 +80,36 @@ public class FortuneAccountServiceImpl extends ServiceImpl<FortuneAccountMapper,
queryWrapper.eq(StringUtils.isNotBlank(fortuneAccountQueryRequest.getBroker()), "broker", fortuneAccountQueryRequest.getBroker());
queryWrapper.eq(StringUtils.isNotBlank(fortuneAccountQueryRequest.getTeam()), "team", fortuneAccountQueryRequest.getTeam());
queryWrapper.in(CollectionUtils.isNotEmpty(statusList), "status", statusList);
queryWrapper.ge(fortuneAccountQueryRequest.getAccountDateStart() != null, "fortune_account_date", fortuneAccountQueryRequest.getAccountDateStart());
queryWrapper.le(fortuneAccountQueryRequest.getAccountDateEnd() != null, "fortune_account_date", fortuneAccountQueryRequest.getAccountDateEnd());
// queryWrapper.ge(fortuneAccountQueryRequest.getAccountDateStart() != null, "fortune_account_date", fortuneAccountQueryRequest.getAccountDateStart());
// queryWrapper.le(fortuneAccountQueryRequest.getAccountDateEnd() != null, "fortune_account_date", fortuneAccountQueryRequest.getAccountDateEnd());
Date start = parseStartDate(fortuneAccountQueryRequest.getAccountDateStart());
Date end = parseEndDate(fortuneAccountQueryRequest.getAccountDateEnd());
queryWrapper.ge(start != null, "fortune_account_date", start);
queryWrapper.le(end != null, "fortune_account_date", end);
queryWrapper.like(StringUtils.isNotBlank(fortuneAccountQueryRequest.getBusinessNo()),"business_no",fortuneAccountQueryRequest.getBusinessNo());
// 默认排序
queryWrapper.orderByDesc("fortune_account_date");
return queryWrapper;
}
private Date parseStartDate(String dateStr) {
if (StringUtils.isBlank(dateStr)) return null;
if (dateStr.length() == 7) { // yyyy-MM
return Date.from(YearMonth.parse(dateStr).atDay(1)
.atStartOfDay(ZoneId.systemDefault()).toInstant());
}
return Date.from(LocalDate.parse(dateStr).atStartOfDay(ZoneId.systemDefault()).toInstant());
}
private Date parseEndDate(String dateStr) {
if (StringUtils.isBlank(dateStr)) return null;
if (dateStr.length() == 7) { // yyyy-MM
return Date.from(YearMonth.parse(dateStr).atEndOfMonth()
.atStartOfDay(ZoneId.systemDefault()).toInstant());
}
return Date.from(LocalDate.parse(dateStr).plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
}
@Override
public Page<FortuneAccountVO> getFortuneAccountVOPage(Page<FortuneAccount> fortunePage) {
List<FortuneAccount> fortuneAccountList = fortunePage.getRecords();
......@@ -119,7 +141,7 @@ public class FortuneAccountServiceImpl extends ServiceImpl<FortuneAccountMapper,
AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
Long loginUserId = currentLoginUser.getId();
//查询转介人的内部编号列表信息
// 查询转介人的内部编号列表信息
List<String> brokerBizIdList = accountExportDTOList.stream().map(FortuneAccountExportDTO::getBrokerBizId).collect(Collectors.toList());
Map<String, String> map = policyBrokerService.queryInternalCodeMap(brokerBizIdList);
List<FortuneAccount> fortuneAccountList = new ArrayList<>();
......@@ -145,8 +167,9 @@ public class FortuneAccountServiceImpl extends ServiceImpl<FortuneAccountMapper,
fortuneAccount.setBrokerBizId(accountExportDTO.getBrokerBizId());
fortuneAccount.setTeam(accountExportDTO.getTeam());
fortuneAccount.setTeamBizId(accountExportDTO.getTeamBizId());
fortuneAccount.setCurrency(accountExportDTO.getCurrency());
fortuneAccount.setHkdAmount(accountExportDTO.getAmount());
fortuneAccount.setPayoutCurrency(accountExportDTO.getPayoutCurrency());
fortuneAccount.setPayoutAmount(accountExportDTO.getPayoutAmount());
fortuneAccount.setHkdAmount(accountExportDTO.getHkdAmount());
fortuneAccount.setFortuneAccountDate(this.getActualPayoutDate(accountExportDTO.getActualPayoutDate()));
// 出账状态默认待出账
fortuneAccount.setStatus(FortuneStatusEnum.CHECKED.getItemValue());
......@@ -169,13 +192,13 @@ public class FortuneAccountServiceImpl extends ServiceImpl<FortuneAccountMapper,
fortuneAccountList.add(fortuneAccount);
}
// 保存出账记录
// 1. 保存薪资记录
this.saveBatch(fortuneAccountList);
// 处理关联发佣记录
List<Fortune> updateFortuneList = new ArrayList<>();
// 处理关联预计发佣记录
List<String> expectedFortuneBizIdList = new ArrayList<>();
Set<String> expectedFortuneBizIdList = new HashSet<>();
for (FortuneAccount fortuneAccount : fortuneAccountList) {
String fortuneAccountBizId = fortuneAccount.getFortuneAccountBizId();
List<Fortune> fortuneList = fortuneAccount.getFortuneList();
......@@ -183,15 +206,12 @@ public class FortuneAccountServiceImpl extends ServiceImpl<FortuneAccountMapper,
for (Fortune item : fortuneList) {
Fortune updateFortune = new Fortune();
updateFortune.setId(item.getId());
updateFortune.setExpectedFortuneBizId(item.getExpectedFortuneBizId());
updateFortune.setRuleAmount(item.getRuleAmount());
updateFortune.setFortuneAccountBizId(fortuneAccountBizId);
updateFortune.setStatus(FortuneStatusEnum.CHECKED.getItemValue());
// 处理金额字段
if (BigDecimal.ZERO.compareTo(item.getHkdAmount()) != 0) {
updateFortune.setCurrentPaymentHkdAmount(item.getCurrentPaymentHkdAmount());
updateFortune.setCurrentPaymentRatio(item.getCurrentPaymentHkdAmount()
.divide(item.getHkdAmount(), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
}
updateFortune.setReconciliationOperator(currentLoginUser.getRealName());
updateFortuneList.add(updateFortune);
// 处理关联预计发佣记录
expectedFortuneBizIdList.add(item.getExpectedFortuneBizId());
......@@ -199,27 +219,46 @@ public class FortuneAccountServiceImpl extends ServiceImpl<FortuneAccountMapper,
}
}
// 更新发佣记录的出账记录id
if (CollectionUtils.isNotEmpty(updateFortuneList)) {
fortuneService.updateBatchById(updateFortuneList);
}
// 更新预计发佣记录的出账状态
// 2. 更新预计发佣记录的出账状态
Map<String, ExpectedFortune> expectedFortuneMap = new HashMap<>();
if (CollectionUtils.isNotEmpty(expectedFortuneBizIdList)) {
// 查询预计发佣记录
List<ExpectedFortune> expectedFortuneList = expectedFortuneService.list(new QueryWrapper<ExpectedFortune>()
.in("expected_fortune_biz_id", expectedFortuneBizIdList));
// 转为 Map
expectedFortuneMap = expectedFortuneList.stream()
.collect(Collectors.toMap(ExpectedFortune::getExpectedFortuneBizId, Function.identity()));
List<ExpectedFortune> updateExpectedFortuneList = new ArrayList<>();
for (ExpectedFortune expectedFortune : expectedFortuneList) {
// 如果状态是 待出账,才修改
if (FortuneStatusEnum.WAIT.getItemValue().equals(expectedFortune.getStatus())) {
ExpectedFortune updateExpectedFortune = new ExpectedFortune();
updateExpectedFortune.setId(expectedFortune.getId());
updateExpectedFortune.setStatus(FortuneStatusEnum.CHECKED.getItemValue());
updateExpectedFortuneList.add(updateExpectedFortune);
}
}
if (CollectionUtils.isNotEmpty(updateExpectedFortuneList)) {
expectedFortuneService.updateBatchById(updateExpectedFortuneList);
}
}
// 3. 计算本次出账比例
for (Fortune f : updateFortuneList) {
ExpectedFortune ef = expectedFortuneMap.get(f.getExpectedFortuneBizId());
if (ef != null) {
BigDecimal currentPaymentRatio = BigDecimal.ZERO;
if (BigDecimal.ZERO.compareTo(ef.getRuleAmount()) != 0) {
currentPaymentRatio = f.getRuleAmount()
.divide(ef.getRuleAmount(), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
}
f.setCurrentPaymentRatio(currentPaymentRatio);
}
}
fortuneService.updateBatchById(updateFortuneList);
}
/**
......@@ -395,17 +434,17 @@ public class FortuneAccountServiceImpl extends ServiceImpl<FortuneAccountMapper,
.eq(Fortune::getStatus, FortuneStatusEnum.CHECKED.getItemValue())
.list();
if (CollectionUtils.isNotEmpty(fortunes)) {
fortunes.forEach(f -> {
if (f.getCurrentPaymentHkdAmount() == null) {
f.setCurrentPaymentHkdAmount(f.getHkdAmount());
f.setCurrentPaymentRatio(BigDecimal.valueOf(100));
}
f.setStatus(FortuneStatusEnum.SENT.getItemValue());
// f.setActualPayoutDate(new Date());
f.setUpdaterId(loginUserId.toString());
f.setUpdateTime(new Date());
});
fortuneService.updateBatchById(fortunes);
List<Fortune> fortuneUpdateList = new ArrayList<>();
for (Fortune f : fortunes) {
Fortune fortune = new Fortune();
fortune.setId(f.getId());
fortune.setStatus(FortuneStatusEnum.SENT.getItemValue());
fortune.setUpdaterId(loginUserId.toString());
fortune.setUpdateTime(new Date());
fortuneUpdateList.add(fortune);
}
fortuneService.updateBatchById(fortuneUpdateList);
}
/* 4. 按 expected_fortune 维度重新汇总已出账金额 --------------------------*/
......@@ -423,45 +462,85 @@ public class FortuneAccountServiceImpl extends ServiceImpl<FortuneAccountMapper,
.last("FOR UPDATE")
.list();
// 4.3 全量汇总:把同一 expected_fortune 下所有 fortune 的 current_payment_hkd_amount 求和
Map<String, BigDecimal> paidMap = fortuneService.lambdaQuery()
// 4.3 全量汇总:把同一 expected_fortune 下所有 fortune 的 current_payment_ratio 求和
Map<String, List<Fortune>> fortuneMap = fortuneService.lambdaQuery()
.in(Fortune::getExpectedFortuneBizId, expectedIds)
.eq(Fortune::getStatus, FortuneStatusEnum.SENT.getItemValue())
.list()
.stream()
.collect(Collectors.groupingBy(Fortune::getExpectedFortuneBizId,
Collectors.mapping(Fortune::getCurrentPaymentHkdAmount,
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
.collect(Collectors.groupingBy(Fortune::getExpectedFortuneBizId));
Map<String, BigDecimal> paidRatioMap = new HashMap<>();
Map<String, BigDecimal> paidMap = new HashMap<>();
Map<String, BigDecimal> paidRuleMap = new HashMap<>();
Map<String, BigDecimal> hkdAmountMap = new HashMap<>();
Set<String> keySet = fortuneMap.keySet();
for (String expectedFortuneBizId : keySet) {
List<Fortune> list = fortuneMap.get(expectedFortuneBizId);
BigDecimal paidRatio = BigDecimal.ZERO;
BigDecimal paid = BigDecimal.ZERO;
BigDecimal paidRule = BigDecimal.ZERO;
BigDecimal hkdAmount = BigDecimal.ZERO;
for (Fortune f : list) {
paidRatio = paidRatio.add(f.getCurrentPaymentRatio());
paid = paid.add(f.getCurrentPaymentHkdAmount());
paidRule = paidRule.add(f.getRuleAmount());
hkdAmount = hkdAmount.add(f.getCurrentPaymentHkdAmount());
}
paidRatioMap.put(expectedFortuneBizId, paidRatio);
paidMap.put(expectedFortuneBizId, paid);
paidRuleMap.put(expectedFortuneBizId, paidRule);
hkdAmountMap.put(expectedFortuneBizId, hkdAmount);
}
// 4.4 反写 expected_fortune
expectedList.forEach(ef -> {
BigDecimal totalPaid = paidMap.getOrDefault(ef.getExpectedFortuneBizId(), BigDecimal.ZERO);
BigDecimal totalAmount = ef.getHkdAmount();
BigDecimal unpaid = totalAmount.subtract(totalPaid);
for (ExpectedFortune ef : expectedList) {
// 累积已发放保单记账金额
BigDecimal paidRule = paidRuleMap.getOrDefault(ef.getExpectedFortuneBizId(), BigDecimal.ZERO);
BigDecimal unpaidRule = ef.getRuleAmount().subtract(paidRule);
// 剩余发放折合港币金额
BigDecimal unpaidRuleAmountHkd = unpaidRule.multiply(ef.getDefaultExchangeRate());
// 应发港币金额(估)
BigDecimal hkdAmount = hkdAmountMap.getOrDefault(ef.getExpectedFortuneBizId(), BigDecimal.ZERO);
BigDecimal expectedHKD = hkdAmount.add(unpaidRuleAmountHkd);
// 发放币种金额 = 港币 × 港币兑发放币种汇率
BigDecimal expectedPayout = expectedHKD.multiply(ef.getHkdToPayoutRate());
// 累计出账港币金额
BigDecimal paid = paidMap.getOrDefault(ef.getExpectedFortuneBizId(), BigDecimal.ZERO);
// 累积已发放比例 = 累积:已发放保单记账金额/应发保单记账金额
BigDecimal totalPaidRatio = paidRatioMap.getOrDefault(ef.getExpectedFortuneBizId(), BigDecimal.ZERO);
BigDecimal unpaidRatio = BigDecimal.valueOf(100).subtract(totalPaidRatio);
String newStatus;
if (unpaid.compareTo(BigDecimal.ZERO) == 0) {
if (unpaidRatio.compareTo(BigDecimal.ZERO) == 0) {
newStatus = FortuneStatusEnum.SENT.getItemValue(); // 全部完成
} else if (totalPaid.compareTo(BigDecimal.ZERO) > 0) {
} else if (totalPaidRatio.compareTo(BigDecimal.ZERO) > 0) {
newStatus = FortuneStatusEnum.PARTIAL_SENT.getItemValue(); // 部分完成
} else {
newStatus = ef.getStatus(); // 无变化
}
expectedFortuneService.lambdaUpdate()
.set(ExpectedFortune::getPaidAmount, totalPaid)
.set(ExpectedFortune::getUnpaidAmount, unpaid)
.set(ExpectedFortune::getPaidRatio,
totalPaid.divide(totalAmount, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)))
.set(ExpectedFortune::getUnpaidRatio,
unpaid.divide(totalAmount, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)))
.set(ExpectedFortune::getPaidRuleAmount, paidRule)
.set(ExpectedFortune::getUnpaidRuleAmount, unpaidRule)
.set(ExpectedFortune::getUnpaidRuleAmountHkd, unpaidRuleAmountHkd)
.set(ExpectedFortune::getHkdAmount, expectedHKD)
.set(ExpectedFortune::getPayoutAmount, expectedPayout)
.set(ExpectedFortune::getPaidAmount, paid)
.set(ExpectedFortune::getUnpaidAmount, unpaidRuleAmountHkd)
.set(ExpectedFortune::getPaidRatio, totalPaidRatio)
.set(ExpectedFortune::getUnpaidRatio, unpaidRatio)
.set(ExpectedFortune::getStatus, newStatus)
// .set(ExpectedFortune::getActualPayoutDate, new Date())
.set(ExpectedFortune::getUpdaterId, loginUserId.toString())
.set(ExpectedFortune::getUpdateTime, LocalDateTime.now())
.eq(ExpectedFortune::getId, ef.getId())
.update();
});
}
return true;
}
......
......@@ -116,9 +116,9 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
queryWrapper.in(CollUtil.isNotEmpty(insuranceCompanyBizIdList), "insurance_company_biz_id", insuranceCompanyBizIdList);
queryWrapper.in(CollUtil.isNotEmpty(productLaunchBizIdList), "product_launch_biz_id", productLaunchBizIdList);
queryWrapper.gt(ObjectUtils.isNotEmpty(payoutDateStart), "payout_date", payoutDateStart);
queryWrapper.lt(ObjectUtils.isNotEmpty(payoutDateEnd), "payout_date", payoutDateEnd);
queryWrapper.eq(StringUtils.isNotBlank(brokerName), "broker", brokerName);
queryWrapper.ge(ObjectUtils.isNotEmpty(payoutDateStart), "payout_date", payoutDateStart);
queryWrapper.le(ObjectUtils.isNotEmpty(payoutDateEnd), "payout_date", payoutDateEnd);
queryWrapper.like(StringUtils.isNotBlank(brokerName), "broker", "%" + brokerName + "%");
// 入账状态, 关联查询 commission_expected 表
if (CollUtil.isNotEmpty(commissionStatusList)) {
......@@ -431,7 +431,7 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
for (Map.Entry<String, List<Fortune>> entry : fortuneMap.entrySet()) {
String broker = entry.getKey().split("_")[0];
String actualPayoutDate = entry.getKey().split("_")[1];
String currency = entry.getKey().split("_")[2];
String payoutCurrency = entry.getKey().split("_")[2];
List<Fortune> brokerFortunes = entry.getValue();
FortuneAccountExportDTO accountDTO = new FortuneAccountExportDTO();
......@@ -443,15 +443,19 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
if (CollUtil.isNotEmpty(brokerFortunes)) {
accountDTO.setTeam(brokerFortunes.get(0).getTeam());
accountDTO.setTeamBizId(brokerFortunes.get(0).getTeamBizId());
accountDTO.setCurrency(currency);
accountDTO.setPayoutCurrency(payoutCurrency);
accountDTO.setActualPayoutDate(LocalDate.parse(actualPayoutDate));
}
// 计算出账总额
BigDecimal totalAmount = brokerFortunes.stream()
.map(Fortune::getCurrentPaymentHkdAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
accountDTO.setAmount(totalAmount);
// 计算出账港币总额、发放币种总额
BigDecimal totalHkdAmount = BigDecimal.ZERO;
BigDecimal totalPayoutAmount = BigDecimal.ZERO;
for (Fortune fortune : brokerFortunes) {
totalHkdAmount = totalHkdAmount.add(fortune.getCurrentPaymentHkdAmount());
totalPayoutAmount = totalPayoutAmount.add(fortune.getPayoutAmount());
}
accountDTO.setHkdAmount(totalHkdAmount);
accountDTO.setPayoutAmount(totalPayoutAmount);
// 按fortune项目分组并累加金额
Map<String, BigDecimal> fortuneAmountMap = brokerFortunes.stream()
......@@ -979,10 +983,8 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
// 4. 生成新记录
List<Fortune> newFortuneList = new ArrayList<>();
List<ExpectedFortune> newExpectedFortuneList = new ArrayList<>();
Date now = new Date();
LocalDateTime localDateTime = LocalDateTime.now();
AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
String loginUserId = currentLoginUser.getId().toString();
......@@ -991,53 +993,10 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
for (int i = 0; i < splitList.size(); i++) {
FortuneSplitDto splitDto = splitList.get(i);
// 4.1 生成新的 ExpectedFortune
ExpectedFortune newExpectedFortune = new ExpectedFortune();
BeanUtils.copyProperties(originalExpectedFortune, newExpectedFortune,
"id", "expectedFortuneBizId", "amount", "hkdAmount",
"paidAmount", "unpaidAmount", "paidRatio", "unpaidRatio",
"status", "payoutDate", "actualPayoutDate", "remark");
String newExpectedFortuneBizId = RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_EXPECTED_FORTUNE.getCode());
newExpectedFortune.setExpectedFortuneBizId(newExpectedFortuneBizId);
// 赋值分期出账信息
BeanUtils.copyProperties(splitDto, newExpectedFortune);
// 生成应付款编号
String payableNo = originalExpectedFortune.getPayableNo() + "_" + (i + 1);
newExpectedFortune.setPayableNo(payableNo);
newExpectedFortune.setIsPart(1);
newExpectedFortune.setDefaultExchangeRate(splitDto.getExchangeRate());
newExpectedFortune.setPaidAmount(BigDecimal.ZERO);
newExpectedFortune.setUnpaidAmount(splitDto.getHkdAmount());
newExpectedFortune.setPaidRatio(BigDecimal.ZERO);
newExpectedFortune.setUnpaidRatio(BigDecimal.valueOf(100));
newExpectedFortune.setStatus(FortuneStatusEnum.CAN_SEND.getItemValue());
newExpectedFortune.setPayoutDate(LocalDate.parse(splitDto.getPayoutYearMonth() + "-01"));
String expectedRemark = StringUtils.isBlank(splitDto.getRemark()) ? "" : splitDto.getRemark();
if (StringUtils.isNotBlank(originalExpectedFortune.getRemark())) {
expectedRemark = StringUtils.isBlank(expectedRemark) ?
originalExpectedFortune.getRemark() :
originalExpectedFortune.getRemark() + "; " + expectedRemark;
}
newExpectedFortune.setRemark(expectedRemark);
String payableNo = originalFortune.getPayableNo() + "_" + (i + 1);
newExpectedFortune.setCreatorId(loginUserId);
newExpectedFortune.setCreatorName(realName);
newExpectedFortune.setCreateTime(localDateTime);
newExpectedFortune.setUpdaterId(loginUserId);
newExpectedFortune.setUpdateTime(localDateTime);
newExpectedFortuneList.add(newExpectedFortune);
// 4.2 生成新的 Fortune
// 4.1 生成新的 Fortune
Fortune newFortune = new Fortune();
BeanUtils.copyProperties(originalFortune, newFortune,
......@@ -1047,8 +1006,8 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
"payoutDate", "actualPayoutDate", "remark");
newFortune.setFortuneBizId(RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_FORTUNE.getCode()));
newFortune.setExpectedFortuneBizId(newExpectedFortuneBizId);
// 新记录的预计出账记录业务 id 与原记录相同
newFortune.setExpectedFortuneBizId(originalFortune.getExpectedFortuneBizId());
// 应付款编号
newFortune.setPayableNo(payableNo);
......@@ -1063,7 +1022,7 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
newFortune.setStatus(FortuneStatusEnum.CAN_SEND.getItemValue());
newFortune.setIsPart(1);
newFortune.setPayoutDate(newExpectedFortune.getPayoutDate());
newFortune.setPayoutDate(LocalDate.parse(splitDto.getPayoutYearMonth() + "-01"));
String fortuneRemark = StringUtils.isBlank(splitDto.getRemark()) ? "" : splitDto.getRemark();
if (StringUtils.isNotBlank(originalFortune.getRemark())) {
......@@ -1082,24 +1041,13 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
newFortuneList.add(newFortune);
}
// 5.1 设置原始 fortune记录 is_part 为 2,表示该记录已被分期
// 5. 设置原始 fortune记录 is_part 为 2,表示该记录已被分期
this.lambdaUpdate()
.set(Fortune::getIsPart, 2)
.eq(Fortune::getId, originalFortune.getId())
.update();
// 5.2 设置原始 expected fortune记录 is_part 为 2,表示该记录已被分期
expectedFortuneService.lambdaUpdate()
.set(ExpectedFortune::getIsPart, 2)
.eq(ExpectedFortune::getId, originalExpectedFortune.getId())
.update();
// 6. 批量保存新记录
boolean expectedSaveSuccess = expectedFortuneService.saveBatch(newExpectedFortuneList);
if (!expectedSaveSuccess) {
throw new BusinessException(ResultCode.FAIL.getCode(), "分期预计出账记录保存失败");
}
boolean fortuneSaveSuccess = this.saveBatch(newFortuneList);
if (!fortuneSaveSuccess) {
throw new BusinessException(ResultCode.FAIL.getCode(), "分期出账记录保存失败");
......@@ -1132,10 +1080,10 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
.eq(Fortune::getId, fortune.getId())
.update();
expectedFortuneService.lambdaUpdate()
.set(ExpectedFortune::getActualPayoutDate, actualPayoutDate)
.eq(ExpectedFortune::getId, originalExpectedFortune.getId())
.update();
// expectedFortuneService.lambdaUpdate()
// .set(ExpectedFortune::getActualPayoutDate, actualPayoutDate)
// .eq(ExpectedFortune::getId, originalExpectedFortune.getId())
// .update();
return true;
}
......@@ -1185,24 +1133,26 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
.set(Fortune::getPayoutAmount, payoutAmount)
.set(Fortune::getHkdToPayoutRate, hkdToPayoutRate)
.set(Fortune::getHkdAmount, hkdAmount)
.set(Fortune::getCurrentPaymentAmount, originalAmount)
.set(Fortune::getCurrentPaymentHkdAmount, hkdAmount)
.eq(Fortune::getId, fortune.getId())
.update();
// 更新 expected fortune 的字段
expectedFortuneService.lambdaUpdate()
.set(ExpectedFortune::getRuleAmount, ruleAmount)
.set(ExpectedFortune::getRuleCurrency, ruleCurrency)
.set(ExpectedFortune::getDefaultExchangeRate, exchangeRate)
.set(ExpectedFortune::getOriginalCurrency, originalCurrency)
.set(ExpectedFortune::getOriginalAmount, originalAmount)
.set(ExpectedFortune::getOriginalToHkdRate, originalToHkdRate)
.set(ExpectedFortune::getPayoutCurrency, payoutCurrency)
.set(ExpectedFortune::getPayoutAmount, payoutAmount)
.set(ExpectedFortune::getHkdToPayoutRate, hkdToPayoutRate)
.set(ExpectedFortune::getHkdAmount, hkdAmount)
.set(ExpectedFortune::getUnpaidAmount, hkdAmount)
.eq(ExpectedFortune::getId, originalExpectedFortune.getId())
.update();
// expectedFortuneService.lambdaUpdate()
// .set(ExpectedFortune::getRuleAmount, ruleAmount)
// .set(ExpectedFortune::getRuleCurrency, ruleCurrency)
// .set(ExpectedFortune::getDefaultExchangeRate, exchangeRate)
// .set(ExpectedFortune::getOriginalCurrency, originalCurrency)
// .set(ExpectedFortune::getOriginalAmount, originalAmount)
// .set(ExpectedFortune::getOriginalToHkdRate, originalToHkdRate)
// .set(ExpectedFortune::getPayoutCurrency, payoutCurrency)
// .set(ExpectedFortune::getPayoutAmount, payoutAmount)
// .set(ExpectedFortune::getHkdToPayoutRate, hkdToPayoutRate)
// .set(ExpectedFortune::getHkdAmount, hkdAmount)
// .set(ExpectedFortune::getUnpaidAmount, hkdAmount)
// .eq(ExpectedFortune::getId, originalExpectedFortune.getId())
// .update();
return true;
}
......@@ -1245,10 +1195,10 @@ public class FortuneServiceImpl extends ServiceImpl<FortuneMapper, Fortune>
this.updateBatchById(updateFortuneList);
// 更新预计 fortune 的字段
expectedFortuneService.lambdaUpdate()
.set(ExpectedFortune::getActualPayoutDate, actualPayoutDate)
.in(ExpectedFortune::getExpectedFortuneBizId, expectedFortuneBizIdList)
.update();
// expectedFortuneService.lambdaUpdate()
// .set(ExpectedFortune::getActualPayoutDate, actualPayoutDate)
// .in(ExpectedFortune::getExpectedFortuneBizId, expectedFortuneBizIdList)
// .update();
return String.format("设置成功。已更新 %d 条数据,跳过 %d 条(已有实际出账年月)", updateCount, skipCount);
}
......
......@@ -59,13 +59,30 @@ public class PolicyBrokerServiceImpl extends ServiceImpl<PolicyBrokerMapper, Pol
return baseMapper.selectRelatedBrokerBizIds(clientUserId);
}
// @Override
// public Map<String, PolicyBroker> queryPolicyBrokerMap(Collection<String> policyNoSet) {
// if (CollectionUtils.isEmpty(policyNoSet)) {
// return Collections.emptyMap();
// }
// List<PolicyBroker> list = this.lambdaQuery().in(PolicyBroker::getPolicyNo, policyNoSet).list();
// return list.stream().collect(Collectors.toMap(PolicyBroker::getPolicyNo, Function.identity(), (oldValue, newValue) -> newValue));
// }
@Override
public Map<String, PolicyBroker> queryPolicyBrokerMap(Collection<String> policyNoSet) {
if (CollectionUtils.isEmpty(policyNoSet)) {
return Collections.emptyMap();
}
List<PolicyBroker> list = this.lambdaQuery().in(PolicyBroker::getPolicyNo, policyNoSet).list();
return list.stream().collect(Collectors.toMap(PolicyBroker::getPolicyNo, Function.identity(), (oldValue, newValue) -> newValue));
List<PolicyBroker> list = this.lambdaQuery()
.in(PolicyBroker::getPolicyNo, policyNoSet)
.orderByAsc(PolicyBroker::getId)
.list();
return list.stream().collect(Collectors.toMap(
PolicyBroker::getPolicyNo,
Function.identity(),
(existing, replacement) -> existing
));
}
@Override
......
......@@ -409,7 +409,7 @@ public class PolicyFollowServiceImpl extends ServiceImpl<PolicyFollowMapper, Pol
//更新新单投保人表信息
policyPolicyholderService.updateName(policyBizId,policyFollowDto.getPolicyHolder());
//更新新单受保人表信息
policyInsurantService.updateName(policyBizId,policyFollowDto.getPolicyHolder());
policyInsurantService.updateName(policyBizId,policyFollowDto.getInsured());
return true;
}
......
......@@ -24,12 +24,18 @@ public class CommissionExpectedStatisticsVO {
private BigDecimal totalPaidAmount;
/**
* 待入账金额(HKD)
* 待入账金额(HKD)(估)
*/
// @Schema(description = "待入账金额(HKD)")
private BigDecimal pendingPaidAmount;
/**
* 待入账金额(HKD)(实)
*/
// @Schema(description = "待入账金额(HKD)")
private BigDecimal pendingPaidAmountS;
/**
* 已入账比例 %(已入账金额/总金额)
*/
// @Schema(description = "已入账比例 %(已入账金额/总金额)")
......
......@@ -8,7 +8,7 @@ import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.yd.csf.feign.response.expectedfortune.ApiExpectedFortunePageResponse;
import com.yd.csf.service.enums.FortuneStatusEnum;
import com.yd.csf.service.model.ExpectedFortune;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
......@@ -33,6 +33,9 @@ public class ExpectedFortuneExportDTO {
@ExcelProperty("保单号")
private String policyNo;
@ExcelProperty("类型")
private String type;
@ExcelProperty("出账状态")
private String status;
......@@ -57,13 +60,16 @@ public class ExpectedFortuneExportDTO {
@ExcelProperty("出账项目")
private String fortuneName;
@ExcelProperty("出账日(估)")
@DateTimeFormat("yyyy-MM-dd")
@ExcelProperty("关联人员")
private String amountSourceName;
@ExcelProperty("出账年月(估)")
@DateTimeFormat("yyyy-MM")
@ColumnWidth(25)
private Date payoutDate;
@ExcelProperty("出账(实)")
@DateTimeFormat("yyyy-MM-dd")
@ExcelProperty("出账年月(实)")
@DateTimeFormat("yyyy-MM")
@ColumnWidth(25)
private Date actualPayoutDate;
......@@ -79,29 +85,43 @@ public class ExpectedFortuneExportDTO {
@ExcelProperty("待出账比例(%)")
private BigDecimal unpaidRatio;
@ExcelProperty("待出账金额")
private BigDecimal unpaidAmount;
@ExcelProperty("本次发放保单记账金额")
private BigDecimal currentPaymentRuleAmount;
@ExcelProperty("本次发放金额")
private BigDecimal currentPayoutAmount;
@ExcelProperty("本次发放折合港币金额")
private BigDecimal currentPaymentHkdAmount;
@ExcelProperty("本次发放比例")
private BigDecimal currentPaymentRatio;
@ExcelProperty("累积已发放保单记账金额")
private BigDecimal paidRuleAmount;
@ExcelProperty("剩余保单记账金额")
private BigDecimal unpaidRuleAmount;
@ExcelProperty("剩余发放折合港币金额")
private BigDecimal unpaidRuleAmounthHkd;
@ExcelProperty("持有比例")
private String brokerRatio;
@ExcelProperty("保险公司")
private String insuranceCompany;
@ExcelProperty("产品计划")
private String productName;
@ExcelProperty("期交保费")
private BigDecimal premium;
@ExcelProperty("出账状态-修改理由")
@ColumnWidth(30)
private String statusDesc;
@ExcelProperty("备注")
@ColumnWidth(30)
private String remark;
@ExcelProperty("创建人")
private String creatorName;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
@ColumnWidth(25)
......@@ -121,26 +141,35 @@ public class ExpectedFortuneExportDTO {
dto.setPayableNo(vo.getPayableNo());
dto.setFortuneBizType("R".equals(vo.getFortuneBizType()) ? "关联保单应付款" : "非关联保单应付款");
dto.setPolicyNo(vo.getPolicyNo());
dto.setType(vo.getType() != null ? (vo.getType() == 1 ? "预计出账" : "实际出账") : null);
dto.setPremium(vo.getPremium());
dto.setFortunePeriod(vo.getFortunePeriod());
dto.setFortuneTotalPeriod(vo.getFortuneTotalPeriod());
dto.setBroker(vo.getBroker());
dto.setTeam(vo.getTeam());
dto.setFortuneName(vo.getFortuneName());
dto.setAmountSourceName(vo.getAmountSourceName());
dto.setBrokerRatio(vo.getBrokerRatio());
dto.setAmount(vo.getHkdAmount());
dto.setCurrency("港币");
dto.setStatus(getStatusText(vo.getStatus()));
dto.setStatusDesc(vo.getStatusDesc());
dto.setInsuranceCompany(vo.getInsuranceCompany());
dto.setProductName(vo.getProductName());
dto.setPayoutDate(Convert.toDate(vo.getPayoutDate()));
dto.setActualPayoutDate(Convert.toDate(vo.getActualPayoutDate()));
dto.setPaidAmount(vo.getPaidAmount());
dto.setUnpaidAmount(vo.getUnpaidAmount());
dto.setPaidRatio(vo.getPaidRatio());
dto.setUnpaidRatio(vo.getUnpaidRatio());
dto.setCurrentPaymentRuleAmount(vo.getCurrentPaymentRuleAmount());
dto.setCurrentPayoutAmount(vo.getCurrentPayoutAmount());
dto.setCurrentPaymentHkdAmount(vo.getCurrentPaymentHkdAmount());
dto.setCurrentPaymentRatio(vo.getCurrentPaymentRatio());
dto.setPaidRuleAmount(vo.getPaidRuleAmount());
dto.setUnpaidRuleAmount(vo.getUnpaidRuleAmount());
dto.setUnpaidRuleAmounthHkd(vo.getUnpaidRuleAmounthHkd());
dto.setRemark(vo.getRemark());
dto.setCreatorName(vo.getCreatorName());
dto.setCreateTime(vo.getCreateTime());
dto.setUpdateTime(vo.getUpdateTime());
dto.setBrokerGradeName(vo.getBrokerGradeName());
return dto;
}
......
......@@ -51,10 +51,16 @@ public class FortuneAccountVO {
private String team;
/**
* 出账币种
* 发放币种
*/
@Schema(description = "出账币种")
private String currency;
@Schema(description = "发放币种")
private String payoutCurrency;
/**
* 发放金额
*/
@Schema(description = "发放金额")
private BigDecimal payoutAmount;
/**
* 港币出账金额
......
......@@ -69,6 +69,11 @@ public class ReceivableReportVO {
private BigDecimal commissionRatio;
/**
* 实用率和值
*/
private BigDecimal paid;
/**
* 预估入账金额(原始币种)
*/
@Schema(description = "预估入账金额(原始币种)")
......
......@@ -56,8 +56,7 @@
IFNULL(SUM(paid_amount),0) AS totalPaidAmount,
COUNT(DISTINCT policy_no) AS totalPolicyCount,
GROUP_CONCAT(DISTINCT policy_no) AS policyNos
FROM
commission_expected ce
FROM commission_expected ce
<where>
<if test="expectedIds != null and expectedIds.size > 0">
id IN
......@@ -83,6 +82,7 @@
MAX(ce.total_period) as totalPeriod,
MAX(ce.commission_date) as commissionDate,
ifnull(sum(ce.commission_ratio), 0) as commissionRatio,
ifnull(sum(ce.paid_ratio), 0) as paid,
ifnull(sum(ce.amount), 0) as amount,
MAX(ce.currency) as currency,
ifnull(sum(ce.expected_amount), 0) as hkdAmount,
......@@ -129,6 +129,7 @@
ce.total_period as totalPeriod,
ce.commission_date as commissionDate,
null as commissionRatio,
null as paid,
ifnull(ce.amount, 0) as amount,
ce.currency as currency,
ifnull(ce.expected_amount, 0) as hkdAmount,
......@@ -160,4 +161,5 @@
and ce.is_deleted = 0
</where>
</select>
</mapper>
\ No newline at end of file
......@@ -56,8 +56,7 @@
<foreach collection="list" item="item">
WHEN #{item.id} THEN #{item.status}
</foreach>
END,
update_time = NOW()
END
</set>
WHERE id IN
<foreach collection="list" item="item" open="(" separator="," close=")">
......
......@@ -56,7 +56,7 @@
select
null as payable_no,
ef.policy_no as policyNo,
ef.policy_currency as policyCurrency,
MAX(ef.policy_currency) as policyCurrency,
(select pp.name from policy_policyholder pp where pp.policy_biz_id = p.policy_biz_id limit 1) as policyHolder,
(select pp.name_en from policy_policyholder pp where pp.policy_biz_id = p.policy_biz_id limit 1) as policyHolderEn,
MAX(ef.premium) as premium,
......@@ -68,7 +68,7 @@
MAX(ef.fortune_total_period) as fortuneTotalPeriod,
ifnull(sum(ef.original_amount), 0) as amount,
ifnull(sum(ef.hkd_amount), 0) as hkdAmount,
MAX(ef.original_currency) as currency,
MAX(ef.payout_currency) as currency,
ifnull(sum(ef.paid_amount), 0) as paidAmount,
ifnull(sum(ef.unpaid_amount), 0) as unpaidAmount,
case when ifnull(sum(ef.hkd_amount), 0) > 0
......@@ -79,21 +79,22 @@
then round(100 - (ifnull(sum(ef.paid_amount), 0) / ifnull(sum(ef.hkd_amount), 0) * 100), 2)
else 100
end as unpaidRatio,
pf.first_broker as broker,
pf.first_broker_biz_id as brokerBizId,
DATE_ADD(DATE_ADD(MAX(p.effective_date), INTERVAL 2 MONTH), INTERVAL (ef.fortune_period - 1) YEAR) as payoutDate
MAX(pf.first_broker) as broker,
MAX(pf.first_broker_biz_id) as brokerBizId,
MAX(ef.payout_date) as payoutDate
from expected_fortune ef
left join policy p on ef.policy_no = p.policy_no
left join policy_follow pf on ef.policy_no = pf.policy_no
<where>
ef.fortune_biz_type = 'R'
<if test="expectedFortuneIds != null and expectedFortuneIds.size > 0">
and ef.id in
<foreach collection="expectedFortuneIds" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</if>
and ef.is_deleted = 0
AND ef.is_part in (0,1)
<if test="ew != null and ew.sqlSegment != null and ew.sqlSegment != ''">
AND ef.id IN (
SELECT ef2.id FROM expected_fortune ef2
WHERE ${ew.sqlSegment}
)
</if>
</where>
group by ef.policy_no, ef.fortune_period
union all
......@@ -112,7 +113,7 @@
ef.fortune_total_period as fortuneTotalPeriod,
ifnull(ef.original_amount, 0) as amount,
ifnull(ef.hkd_amount, 0) as hkdAmount,
ef.original_currency as currency,
ef.payout_currency as currency,
ifnull(ef.paid_amount, 0) as paidAmount,
ifnull(ef.unpaid_amount, 0) as unpaidAmount,
case when ifnull(ef.hkd_amount, 0) > 0
......@@ -130,13 +131,14 @@
left join policy p on ef.policy_no = p.policy_no
<where>
ef.fortune_biz_type = 'U'
<if test="expectedFortuneIds != null and expectedFortuneIds.size > 0">
and ef.id in
<foreach collection="expectedFortuneIds" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</if>
and ef.is_deleted = 0
AND ef.is_part in (0,1)
<if test="ew != null and ew.sqlSegment != null and ew.sqlSegment != ''">
AND ef.id IN (
SELECT ef2.id FROM expected_fortune ef2
WHERE ${ew.sqlSegment}
)
</if>
</where>
</select>
......@@ -148,12 +150,12 @@
ef.id,
ef.expected_fortune_biz_id,
ef.fortune_biz_type,
ef.is_part,
NULL as currentPaymentRuleAmount,
NULL as currentPayoutAmount,
NULL as currentPaymentRatio,
ef.payable_no,
ef.policy_no,
ef.premium,
ef.policy_currency,
ef.insurance_company_biz_id,
ef.product_launch_biz_id,
ef.fortune_period,
ef.fortune_total_period,
......@@ -161,15 +163,15 @@
ef.broker_biz_id,
ef.team,
ef.team_biz_id,
ef.amount_source_name,
ef.fortune_name,
ef.fortune_type,
ef.broker_ratio,
ef.rule_amount,
ef.rule_currency,
ef.status,
ef.status_desc,
ef.payout_date,
ef.actual_payout_date,
NULL as actual_payout_date,
ef.default_exchange_rate as exchangeRate,
ef.original_currency,
ef.original_amount,
......@@ -179,15 +181,12 @@
ef.hkd_to_payout_rate,
ef.hkd_amount,
ef.hkd_amount as current_payment_hkd_amount,
ef.default_exchange_rate as exchange_rate,
ef.paid_amount,
ef.unpaid_amount,
ef.paid_ratio,
ef.unpaid_ratio,
ef.is_tax,
ef.tax_amount,
ef.net_amount,
ef.rule_item_biz_id,
ef.paid_rule_amount as paidRuleAmount,
ef.unpaid_rule_amount as unpaidRuleAmount,
ef.unpaid_rule_amount_hkd as unpaidRuleAmounthHkd,
ef.remark,
ef.create_time,
ef.creator_name,
......@@ -210,12 +209,12 @@
f.id,
f.expected_fortune_biz_id,
f.fortune_biz_type,
f.is_part,
f.rule_amount as currentPaymentRuleAmount,
f.current_payment_amount as currentPayoutAmount,
f.current_payment_ratio as currentPaymentRatio,
f.payable_no,
f.policy_no,
NULL as premium,
f.policy_currency,
NULL as insurance_company_biz_id,
NULL as product_launch_biz_id,
f.fortune_period,
f.fortune_total_period,
......@@ -223,16 +222,16 @@
f.broker_biz_id,
f.team,
f.team_biz_id,
NULL as amount_source_name,
f.fortune_name,
f.fortune_type,
NULL as broker_ratio,
f.rule_amount,
f.rule_currency,
f.status,
NULL as status_desc,
f.payout_date,
f.actual_payout_date,
NUll as default_exchange_rate,
f.exchange_rate,
f.original_currency,
f.original_amount,
f.original_to_hkd_rate,
......@@ -240,16 +239,134 @@
f.payout_amount,
f.hkd_to_payout_rate,
f.hkd_amount,
f.current_payment_hkd_amount,
NULL as paid_amount,
NULL as paid_ratio,
NULL as unpaid_ratio,
NULL as paidRuleAmount,
NULL as unpaidRuleAmount,
NULL as unpaidRuleAmounthHkd,
f.remark,
f.create_time,
f.reconciliation_operator as creator_name,
f.update_time,
2 as type
FROM fortune f
<where>
f.is_deleted = 0
AND f.is_part IN (0, 1)
<if test="ew != null">
<if test="ew.sqlSegment != null and ew.sqlSegment != ''">
AND ${ew.sqlSegment}
</if>
</if>
</where>
ORDER BY fortune_type ASC, type ASC
LIMIT #{pageSize} OFFSET #{offset}
</select>
<select id="queryListAll"
resultType="com.yd.csf.feign.response.expectedfortune.ApiExpectedFortunePageResponse">
SELECT
ef.id,
ef.expected_fortune_biz_id,
ef.fortune_biz_type,
NULL as currentPaymentRuleAmount,
NULL as currentPayoutAmount,
NULL as currentPaymentRatio,
ef.payable_no,
ef.policy_no,
ef.premium,
ef.product_launch_biz_id,
ef.fortune_period,
ef.fortune_total_period,
ef.broker,
ef.broker_biz_id,
ef.team,
ef.team_biz_id,
ef.fortune_name,
ef.fortune_type,
ef.broker_ratio,
ef.rule_amount,
ef.rule_currency,
ef.status,
ef.payout_date,
ef.actual_payout_date,
ef.default_exchange_rate as exchangeRate,
ef.original_currency,
ef.original_amount,
ef.original_to_hkd_rate,
ef.payout_currency,
ef.payout_amount,
ef.hkd_to_payout_rate,
ef.hkd_amount,
NULL as current_payment_hkd_amount,
ef.paid_amount,
ef.paid_ratio,
ef.unpaid_ratio,
ef.paid_rule_amount as paidRuleAmount,
ef.unpaid_rule_amount as unpaidRuleAmount,
ef.unpaid_rule_amount_hkd as unpaidRuleAmounthHkd,
ef.remark,
ef.create_time,
ef.creator_name,
ef.update_time,
1 as type
FROM expected_fortune ef
<where>
ef.is_deleted = 0
AND ef.is_part IN (0, 1)
<if test="ew != null">
<if test="ew.sqlSegment != null and ew.sqlSegment != ''">
AND ${ew.sqlSegment}
</if>
</if>
</where>
UNION ALL
SELECT
f.id,
f.expected_fortune_biz_id,
f.fortune_biz_type,
f.rule_amount as currentPaymentRuleAmount,
f.current_payment_amount as currentPayoutAmount,
f.current_payment_ratio as currentPaymentRatio,
f.payable_no,
f.policy_no,
NULL as premium,
NULL as product_launch_biz_id,
f.fortune_period,
f.fortune_total_period,
f.broker,
f.broker_biz_id,
f.team,
f.team_biz_id,
f.fortune_name,
f.fortune_type,
NULL as broker_ratio,
f.rule_amount,
f.rule_currency,
f.status,
f.payout_date,
f.actual_payout_date,
f.exchange_rate,
f.original_currency,
f.original_amount,
f.original_to_hkd_rate,
f.payout_currency,
f.payout_amount,
f.hkd_to_payout_rate,
f.hkd_amount,
f.current_payment_hkd_amount,
NULL as paid_amount,
NULL as unpaid_amount,
NULL as paid_ratio,
NULL as unpaid_ratio,
f.is_tax,
f.tax_amount,
f.net_amount,
NULL as rule_item_biz_id,
NULL as paidRuleAmount,
NULL as unpaidRuleAmount,
NULL as unpaidRuleAmounthHkd,
f.remark,
f.create_time,
f.reconciliation_operator as creator_name,
......@@ -266,27 +383,17 @@
</if>
</where>
ORDER BY payable_no ASC, type ASC
LIMIT #{pageSize} OFFSET #{offset}
ORDER BY fortune_type ASC, type ASC
</select>
<select id="queryListStatistics" resultType="com.yd.csf.service.vo.ExpectedFortuneStatisticsVO">
SELECT
COALESCE(SUM(hkd_amount), 0) AS totalExpectedAmount,
COALESCE(SUM(paid_amount), 0) AS totalPaidAmount,
COALESCE(SUM(unpaid_amount), 0) AS totalUnpaidAmount,
COALESCE(totalPremiumAmount, 0) AS totalPremiumAmount,
COUNT(DISTINCT policy_no) AS totalPolicyCount
FROM (
WITH filtered_data AS (
SELECT
ef.hkd_amount,
ef.paid_amount,
ef.unpaid_amount,
ef.policy_no,
(SELECT p.total_payment_premium * ef.default_exchange_rate
FROM policy p
WHERE p.policy_no = ef.policy_no
) AS totalPremiumAmount
ef.default_exchange_rate
FROM expected_fortune ef
WHERE ef.is_deleted = 0
AND ef.is_part IN (0, 1)
......@@ -295,7 +402,20 @@
AND ${ew.sqlSegment}
</if>
</if>
) AS statistics
),
premium_total AS (
SELECT SUM(p.total_payment_premium * dp.default_exchange_rate) AS total_premium
FROM (SELECT DISTINCT policy_no, default_exchange_rate FROM filtered_data) dp
INNER JOIN policy p ON p.policy_no = dp.policy_no
)
SELECT
COALESCE(SUM(fd.hkd_amount), 0) AS totalExpectedAmount,
COALESCE(SUM(fd.paid_amount), 0) AS totalPaidAmount,
COALESCE(SUM(fd.unpaid_amount), 0) AS totalUnpaidAmount,
COALESCE(pt.total_premium, 0) AS totalPremiumAmount,
COUNT(DISTINCT fd.policy_no) AS totalPolicyCount
FROM filtered_data fd
CROSS JOIN premium_total pt
</select>
<select id="queryListNewCount" resultType="java.lang.Long">
......
......@@ -11,8 +11,8 @@
<result property="brokerBizId" column="broker_biz_id" />
<result property="team" column="team" />
<result property="teamBizId" column="team_biz_id" />
<result property="currency" column="currency" />
<result property="amount" column="amount" />
<result property="payoutCurrency" column="payout_currency" />
<result property="payoutAmount" column="payout_amount" />
<result property="hkdAmount" column="hkd_amount" />
<result property="status" column="status" />
<result property="fortuneAccountDate" column="fortune_account_date" />
......@@ -27,7 +27,7 @@
<sql id="Base_Column_List">
id,fortune_account_biz_id,broker,broker_biz_id,team,team_biz_id,
currency,amount,hkd_amount,status,fortune_account_date,content,remark,
payout_currency,payout_amount,hkd_amount,status,fortune_account_date,content,remark,
is_deleted,creator_id,updater_id,create_time,update_time
</sql>
</mapper>
......@@ -26,9 +26,9 @@
fa.fortune_account_date,
ss.bill_org,
fa.status,
fa.amount,
fa.payout_amount as amount,
fa.hkd_amount,
fa.currency,
fa.payout_currency as currency,
DATE_FORMAT(fa.fortune_account_date, '%Y%m') as fortune_account_month,
fa.business_no
from salary_split ss
......@@ -109,9 +109,9 @@
fa.fortune_account_date,
ss.bill_org,
fa.status,
fa.amount,
fa.payout_amount as amount,
fa.hkd_amount,
fa.currency,
fa.payout_currency as currency,
DATE_FORMAT(fa.fortune_account_date, '%Y%m') as fortune_account_month,
fa.business_no
from salary_split ss
......
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