Commit d77df53c by zhangxingmin

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

parents c78f9964 6318f6a3
......@@ -397,7 +397,6 @@ public class ApiCommissionExpectedController {
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 +414,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不能为空");
}
......
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;
......
......@@ -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;
......@@ -100,6 +100,8 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
@Autowired
private RedisUtil redisUtil;
@Autowired
private DictCacheService dictCacheService;
@Autowired
private ApiExpectedFortuneLogService apiExpectedFortuneLogService;
@Autowired
private PolicyBrokerService policyBrokerService;
......@@ -438,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);
......@@ -472,57 +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 originalToHkdRate = queryExchangeRateByFeign(policyCurrency, "HKD");
log.info("结算汇率(原币种 -> 港币汇率):{}", originalToHkdRate);
BigDecimal hkdToPayoutRate = queryExchangeRateByFeign("HKD", currency);
log.info("港币 -> 发放币种汇率:{}", hkdToPayoutRate);
for (ExpectedFortune expectedFortune : expectedFortuneList) {
ExpectedFortune updateObj = new ExpectedFortune();
updateObj.setId(expectedFortune.getId());
//原币种
updateObj.setOriginalCurrency(policyCurrency);
//原币种金额
updateObj.setOriginalAmount(expectedFortune.getRuleAmount());
//原币种 -> 港币汇率
updateObj.setOriginalToHkdRate(originalToHkdRate);
//保单币种
updateObj.setRuleCurrency(policyCurrency);
//默认保单币种 -> 港币汇率
updateObj.setDefaultExchangeRate(originalToHkdRate);
//港币金额(标准发佣金额 * 默认保单币种 -> 港币汇率)
BigDecimal hkdAmount = expectedFortune.getRuleAmount().multiply(originalToHkdRate);
updateObj.setHkdAmount(hkdAmount);
//发放币种
updateObj.setPayoutCurrency(currency);
//发放币种金额
updateObj.setPayoutAmount(hkdAmount.multiply(hkdToPayoutRate));
//港币 -> 发放币种汇率
updateObj.setHkdToPayoutRate(hkdToPayoutRate);
//默认值
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;
......@@ -625,12 +573,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);
......@@ -676,31 +622,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;
}
/**
......@@ -770,6 +766,8 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
.insuranceCompanyBizId(brokerDto.getInsuranceCompanyBizId())
.brokerRatio(dto.getBrokerRatio())
.source(2)
.amountSourceId(brokerDto.getBrokerBizId())
.amountSourceName(brokerDto.getBrokerName())
.build());
return Result.success();
......@@ -912,6 +910,8 @@ 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();
......@@ -1209,11 +1209,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)
......@@ -1230,25 +1230,44 @@ public class ApiExpectedFortuneServiceImpl implements ApiExpectedFortuneService
@Override
public Result<PayableReportResponse> payableReport(ApiExpectedFortunePageRequest request) {
// 构建查询条件
// 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);
}
// 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();
// 查询统计数据(基于所有符合条件的记录
ExpectedFortuneStatisticsVO statisticsVO = this.getStatistics(allFortuneIdList);
// 4. 查询统计数据(直接传递 QueryWrapper,在 SQL 中聚合计算,不再加载明细到内存
ExpectedFortuneStatisticsVO statisticsVO = iExpectedFortuneService.queryListStatistics(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);
// 计算待出账金额和已出账比例
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 = iExpectedFortuneService.payableReportPage(reportPage, queryWrapper);
// 6. 数据补充(转介人等级、保单持有人、产品名称等信息)
payableReportPage = convertPayableReportVO(payableReportPage);
// 组装返回结果
// 7. 组装返回结果
PayableReportResponse response = new PayableReportResponse();
response.setStatisticsVO(statisticsVO);
response.setPage(payableReportPage);
......
......@@ -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,44 +34,65 @@ 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) {
//自动注入创建人和创建用户名
this.strictInsertFill(metaObject, "creatorId", String.class, authUserDto.getUserBizId());
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("creatorId", metaObject) == null) {
this.strictInsertFill(metaObject, "creatorId", String.class, authUserDto.getUserBizId());
}
if (getFieldValByName("creatorName", metaObject) == null) {
this.strictInsertFill(metaObject, "creatorName", 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) {
//自动注入更新人和更新用户名
this.strictUpdateFill(metaObject, "updaterId", String.class, authUserDto.getUserBizId());
this.strictUpdateFill(metaObject, "updaterName", String.class, authUserDto.getRealName());
// 仅当字段为空时才填充
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());
}
}
}
};
......
......@@ -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);
}
......@@ -26,11 +26,18 @@ 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;
}
......@@ -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")
......
......@@ -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;
/**
......@@ -41,11 +40,11 @@ public interface IExpectedFortuneService extends IService<ExpectedFortune> {
/**
* 应付款报表 - 按保单号和期数维度统计(分页)
*
* @param page 分页参数
* @param expectedFortuneIds 预计发佣ID列表
* @param page 分页参数
* @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);
}
......@@ -22,6 +22,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 +95,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,17 +880,22 @@ 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 (paidRatio.compareTo(commissionRatio) >= 0) {
//完成入账
commissionExpected.setStatus("1");
}else {
//部分入账
commissionExpected.setStatus("2");
if (count > 0){
//判断下面的前提是必须有实际的数据
//已入账比例 >= 预计入账比例 -> 入账状态置为完成入账。否则部分入账
if (paidRatio.compareTo(commissionRatio) >= 0) {
//完成入账
commissionExpected.setStatus("1");
}else {
//部分入账
commissionExpected.setStatus("2");
}
}
} else {
commissionExpected.setExpectedAmount(
......@@ -1024,7 +1032,7 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
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 +1043,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 +1103,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 +1174,8 @@ public class CommissionExpectedServiceImpl extends ServiceImpl<CommissionExpecte
commissionExpected.setUpdaterId("");
commissionExpected.setCreateTime(new Date());
commissionExpected.setUpdateTime(new Date());
commissionExpected.setCreatorName("系统生成");
commissionExpected.setUpdaterName("系统生成");
commissionExpectedList.add(commissionExpected);
}
......
......@@ -789,12 +789,11 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
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();
......@@ -803,9 +802,8 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
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 {
fortune.setExchangeRate(expectedFortune.getDefaultExchangeRate());
......@@ -1270,6 +1268,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,14 +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.getUnpaidAmount());
actual.setPaidRatio(expected.getPaidRatio());
actual.setUnpaidRatio(expected.getUnpaidRatio());
actual.setPaidAmount(expected.getPaidAmount());
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.setUnpaidRuleAmount(expected.getUnpaidRuleAmount());
actual.setUnpaidRuleAmounthHkd(expected.getUnpaidRuleAmounthHkd());
});
sortedList.addAll(matchedList);
......@@ -242,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);
......@@ -254,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) {
......@@ -268,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
......@@ -355,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,35 @@ 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.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 +140,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<>();
......@@ -169,13 +190,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 +204,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 +217,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) {
ExpectedFortune updateExpectedFortune = new ExpectedFortune();
updateExpectedFortune.setId(expectedFortune.getId());
updateExpectedFortune.setStatus(FortuneStatusEnum.CHECKED.getItemValue());
updateExpectedFortuneList.add(updateExpectedFortune);
// 如果状态是 待出账,才修改
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);
}
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 +432,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,44 +460,76 @@ 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));
// 4.4 反写 expected_fortune
for (ExpectedFortune ef : expectedList) {
BigDecimal totalPaid = paidMap.getOrDefault(ef.getExpectedFortuneBizId(), BigDecimal.ZERO);
BigDecimal totalAmount = ef.getHkdAmount();
BigDecimal unpaid = totalAmount.subtract(totalPaid);
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;
if (totalAmount.compareTo(BigDecimal.ZERO) > 0) {
paidRatio = totalPaid.divide(totalAmount, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
}
BigDecimal unpaidRatio = BigDecimal.ZERO;
if (totalAmount.compareTo(BigDecimal.ZERO) > 0) {
unpaidRatio = unpaid.divide(totalAmount, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
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
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 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, paidRatio)
.set(ExpectedFortune::getPaidRuleAmount, paidRule)
.set(ExpectedFortune::getUnpaidRuleAmount, unpaidRule)
.set(ExpectedFortune::getUnpaidRuleAmountHkd, unpaidRuleAmountHkd)
.set(ExpectedFortune::getHkdAmount, expectedHKD)
.set(ExpectedFortune::getPayoutAmount, expectedHKD)
.set(ExpectedFortune::getPaidAmount, paid)
.set(ExpectedFortune::getUnpaidAmount, unpaidRuleAmountHkd)
.set(ExpectedFortune::getPaidRatio, totalPaidRatio)
.set(ExpectedFortune::getUnpaidRatio, unpaidRatio)
.set(ExpectedFortune::getStatus, newStatus)
.set(ExpectedFortune::getUpdaterId, loginUserId.toString())
......
......@@ -979,10 +979,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 +989,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);
newExpectedFortune.setCreatorId(loginUserId);
newExpectedFortune.setCreatorName(realName);
newExpectedFortune.setCreateTime(localDateTime);
newExpectedFortune.setUpdaterId(loginUserId);
newExpectedFortune.setUpdateTime(localDateTime);
newExpectedFortuneList.add(newExpectedFortune);
String payableNo = originalFortune.getPayableNo() + "_" + (i + 1);
// 4.2 生成新的 Fortune
// 4.1 生成新的 Fortune
Fortune newFortune = new Fortune();
BeanUtils.copyProperties(originalFortune, newFortune,
......@@ -1047,8 +1002,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 +1018,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 +1037,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 +1076,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 +1129,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 +1191,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);
}
......
......@@ -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;
}
......@@ -157,4 +186,4 @@ public class ExpectedFortuneExportDTO {
}
return "未知";
}
}
\ No newline at end of file
}
......@@ -69,6 +69,11 @@ public class ReceivableReportVO {
private BigDecimal commissionRatio;
/**
* 实用率和值
*/
private BigDecimal paid;
/**
* 预估入账金额(原始币种)
*/
@Schema(description = "预估入账金额(原始币种)")
......
......@@ -83,6 +83,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 +130,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,
......
......@@ -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.hkd_amount - ef.paid_amount) as 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,36 +383,39 @@
</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)
AND ef.is_part IN (0, 1)
<if test="ew != null">
<if test="ew.sqlSegment != null and ew.sqlSegment != ''">
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">
......
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