Commit e350da83 by jianan

新单跟进135

parent 4a99383b
...@@ -28,6 +28,7 @@ import org.apache.commons.collections4.CollectionUtils; ...@@ -28,6 +28,7 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
...@@ -137,6 +138,28 @@ public class ApiCommissionController { ...@@ -137,6 +138,28 @@ public class ApiCommissionController {
entities.add(entity); entities.add(entity);
} }
// 保存来佣数据
commissionService.saveBatch(entities);
// todo 6. 异步触发比对任务(事务提交后执行)
// TransactionSynchronizationManager.registerSynchronization(
// new TransactionSynchronization() {
// @Override
// public void afterCommit() {
// // 主事务提交后再执行异步任务
// commissionComareBatch(entities);
// }
// }
// );
}
/**
* 异步执行来佣对比(有独立事务)
*/
@Async("commonAsyncExecutor")
@Transactional(rollbackFor = Exception.class)
public void commissionComareBatch(List<Commission> entities) {
// 根据导入的来佣获取保单号集合 // 根据导入的来佣获取保单号集合
List<String> policyNoList = entities.stream() List<String> policyNoList = entities.stream()
.map(Commission::getPolicyNo) .map(Commission::getPolicyNo)
...@@ -146,12 +169,7 @@ public class ApiCommissionController { ...@@ -146,12 +169,7 @@ public class ApiCommissionController {
.in(CommissionExpected::getPolicyNo, policyNoList) .in(CommissionExpected::getPolicyNo, policyNoList)
.list(); .list();
// 校验导入的来佣是否与预计来佣一致
for (Commission commission : entities) { for (Commission commission : entities) {
String policyNo = commission.getPolicyNo();
Integer commissionPeriod = commission.getCommissionPeriod();
String commissionName = commission.getCommissionName();
// 查询预计来佣 // 查询预计来佣
CommissionExpected commissionExpected; CommissionExpected commissionExpected;
try { try {
...@@ -165,22 +183,12 @@ public class ApiCommissionController { ...@@ -165,22 +183,12 @@ public class ApiCommissionController {
commission.setRemark(e.getMessage()); commission.setRemark(e.getMessage());
} }
} }
// 保存来佣数据 // 保存来佣数据
commissionService.saveBatch(entities); commissionService.saveBatch(entities);
// 更新预计来佣状态 // 更新预计来佣状态
commissionExpectedService.updateBatchById(expectedList); commissionExpectedService.updateBatchById(expectedList);
} }
private static CommissionExpected getCommissionExpected(List<CommissionExpected> expectedList, String policyNo, Integer commissionPeriod, String commissionName) {
return expectedList.stream()
.filter(item -> item.getPolicyNo().equals(policyNo)
&& commissionPeriod.equals(item.getCommissionPeriod())
&& commissionName.equals(item.getCommissionName()))
.findFirst()
.orElse(null);
}
/** /**
* 生成可出账(发佣)记录,支持手动复选框选择 * 生成可出账(发佣)记录,支持手动复选框选择
* *
......
package com.yd.csf.service.service;
import com.yd.csf.service.enums.CommissionStatusEnum;
import com.yd.csf.service.model.Commission;
import com.yd.csf.service.model.CommissionExpected;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Slf4j
public class CommissionAsyncService {
@Resource
private CommissionExpectedService commissionExpectedService;
@Resource
private CommissionService commissionService;
@Async("commonAsyncExecutor")
@Transactional(rollbackFor = Exception.class)
public void commissionCompareBatch(List<Commission> entities) {
// 比对逻辑...
log.info("开始异步比对,数据量:{}", entities.size());
List<String> policyNoList = entities.stream()
.map(Commission::getPolicyNo)
.collect(Collectors.toList());
List<CommissionExpected> expectedList = commissionExpectedService.lambdaQuery()
.in(CommissionExpected::getPolicyNo, policyNoList)
.list();
// 执行比对...
}
public void commissionCompare(Commission commission) {
log.info("开始执行比对事务,来佣ID: {}, 保单号: {}",
commission.getId(), commission.getPolicyNo());
CommissionExpected commissionExpected;
try {
commissionExpected = commissionService.queryByCommission(commission);
// 对比预计来佣
commissionService.compareWithExpected(commission.getPremium(), commission, commissionExpected);
commissionExpectedService.updateById(commissionExpected);
// 比对成功,更新状态
commission.setStatus(CommissionStatusEnum.COMPARE_SUCCESS.getItemValue());
} catch (Exception e) {
// 预计来佣不存在或比对失败
commission.setStatus(CommissionStatusEnum.COMPARE_FAIL.getItemValue());
commission.setRemark(e.getMessage());
log.warn("来佣比对失败,保单号: {},原因: {}",
commission.getPolicyNo(), e.getMessage());
}
// 更新来佣的比对状态(在比对事务中)
commissionService.updateById(commission);
}
}
...@@ -12,6 +12,7 @@ import com.yd.common.enums.CommonEnum; ...@@ -12,6 +12,7 @@ import com.yd.common.enums.CommonEnum;
import com.yd.common.enums.ResultCode; import com.yd.common.enums.ResultCode;
import com.yd.common.exception.BusinessException; import com.yd.common.exception.BusinessException;
import com.yd.common.utils.RandomStringGenerator; import com.yd.common.utils.RandomStringGenerator;
import com.yd.common.utils.RedisUtil;
import com.yd.csf.service.dto.*; import com.yd.csf.service.dto.*;
import com.yd.csf.service.enums.CommissionExpectedStatusEnum; import com.yd.csf.service.enums.CommissionExpectedStatusEnum;
import com.yd.csf.service.enums.CommissionStatusEnum; import com.yd.csf.service.enums.CommissionStatusEnum;
...@@ -25,14 +26,19 @@ import lombok.extern.slf4j.Slf4j; ...@@ -25,14 +26,19 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -62,7 +68,10 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss ...@@ -62,7 +68,10 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
private CommissionEditRecordService commissionEditRecordService; private CommissionEditRecordService commissionEditRecordService;
@Resource @Resource
private CommissionCompareRecordService commissionCompareRecordService; private CommissionCompareRecordService commissionCompareRecordService;
@Resource
private CommissionAsyncService commissionAsyncService;
@Resource
private RedissonClient redissonClient;
@Override @Override
public QueryWrapper<Commission> getQueryWrapper(CommissionQueryRequest commissionQueryRequest) { public QueryWrapper<Commission> getQueryWrapper(CommissionQueryRequest commissionQueryRequest) {
...@@ -110,13 +119,74 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss ...@@ -110,13 +119,74 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class) // 主事务
public Boolean updateCommission(CommissionUpdateRequest commissionUpdateRequest) { public Boolean updateCommission(CommissionUpdateRequest commissionUpdateRequest) {
String commissionBizId = commissionUpdateRequest.getCommissionBizId(); String lockKey = "COMMISSION_LOCK:" + commissionUpdateRequest.getCommissionBizId();
Commission commission = this.getOne(new QueryWrapper<Commission>().eq("commission_biz_id", commissionBizId)); RLock lock = redissonClient.getLock(lockKey);
if (commission == null) { try {
throw new BusinessException(ResultCode.NULL_ERROR.getCode(), "未找到该来佣记录"); // 竞争锁
boolean res = lock.tryLock(3, 15, TimeUnit.SECONDS);
if (!res) {
log.warn("获取分布式锁失败,commissionBizId: {}", commissionUpdateRequest.getCommissionBizId());
throw new BusinessException("系统繁忙,请稍后重试");
}
String commissionBizId = commissionUpdateRequest.getCommissionBizId();
Commission commission = this.getOne(new QueryWrapper<Commission>()
.eq("commission_biz_id", commissionBizId));
if (commission == null) {
throw new BusinessException(ResultCode.NULL_ERROR.getCode(), "未找到该来佣记录");
}
BigDecimal amount = commission.getAmount();
BigDecimal requestAmount = commissionUpdateRequest.getAmount();
// 1. 执行主更新事务(这个方法将在当前事务中执行)
Boolean updateResult = doUpdateCommissionInTransaction(commission, commissionUpdateRequest);
// 没改金额,则不比对
if (amount.compareTo(requestAmount) != 0) {
// 2. 注册事务同步器,在主事务提交后执行比对
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronization() {
@Override
public void afterCommit() {
try {
// 重新查询最新的来佣数据,确保获取已提交的数据
Commission freshCommission = getOne(new QueryWrapper<Commission>()
.eq("commission_biz_id", commissionUpdateRequest.getCommissionBizId()));
if (freshCommission != null) {
// 3. 执行独立的比对事务
commissionAsyncService.commissionCompare(freshCommission);
}
} catch (Exception e) {
// 比对失败不影响主事务,记录日志即可
log.error("主事务提交后,比对操作执行失败,commissionBizId: {}",
commissionUpdateRequest.getCommissionBizId(), e);
}
}
}
);
}
return updateResult;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("更新来佣记录时,获取锁被中断", e);
throw new BusinessException("操作被中断");
} finally {
if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
} }
}
/**
* 主事务中的更新操作
*/
private Boolean doUpdateCommissionInTransaction(Commission commission, CommissionUpdateRequest commissionUpdateRequest) {
// 获取当前登录用户 // 获取当前登录用户
AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser(); AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
String loginUserId = currentLoginUser.getId().toString(); String loginUserId = currentLoginUser.getId().toString();
...@@ -128,23 +198,12 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss ...@@ -128,23 +198,12 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
BeanUtils.copyProperties(commissionUpdateRequest, commission, "id", "commissionBizId"); BeanUtils.copyProperties(commissionUpdateRequest, commission, "id", "commissionBizId");
commission.setUpdaterId(loginUserId); commission.setUpdaterId(loginUserId);
commission.setUpdateTime(new Date()); commission.setUpdateTime(new Date());
// 先更新来佣属性
// 先更新来佣属性(在主事务中)
this.updateById(commission); this.updateById(commission);
// 查询预计来佣 // 返回true表示主事务成功
CommissionExpected commissionExpected; return true;
try {
commissionExpected = queryByCommission(commission);
// 对比预计来佣
compareWithExpected(commission.getPremium(), commission, commissionExpected);
commissionExpectedService.updateById(commissionExpected);
} catch (Exception e) {
// 预计来佣不存在,来佣状态设置为 比对失败
commission.setStatus(CommissionStatusEnum.COMPARE_FAIL.getItemValue());
commission.setRemark(e.getMessage());
}
// 更新比对信息
return this.updateById(commission);
} }
private void saveUpdateCommissionRecord(Commission commission, CommissionUpdateRequest commissionUpdateRequest, AuthUserDto currentLoginUser) { private void saveUpdateCommissionRecord(Commission commission, CommissionUpdateRequest commissionUpdateRequest, AuthUserDto currentLoginUser) {
...@@ -470,18 +529,17 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss ...@@ -470,18 +529,17 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
} }
} }
// 查询预计来佣 // 查询预计来佣
// 查询预计来佣 // CommissionExpected commissionExpected;
CommissionExpected commissionExpected; // try {
try { // commissionExpected = queryByCommission(commission);
commissionExpected = queryByCommission(commission); // // 对比预计来佣
// 对比预计来佣 // compareWithExpected(commission.getPremium(), commission, commissionExpected);
compareWithExpected(commission.getPremium(), commission, commissionExpected); // commissionExpectedService.updateById(commissionExpected);
commissionExpectedService.updateById(commissionExpected); // } catch (Exception e) {
} catch (Exception e) { // // 预计来佣不存在,来佣状态设置为 比对失败
// 预计来佣不存在,来佣状态设置为 比对失败 // commission.setStatus(CommissionStatusEnum.COMPARE_FAIL.getItemValue());
commission.setStatus(CommissionStatusEnum.COMPARE_FAIL.getItemValue()); // commission.setRemark(e.getMessage());
commission.setRemark(e.getMessage()); // }
}
commission.setCreatorId(loginUserId); commission.setCreatorId(loginUserId);
commission.setCreateTime(new Date()); commission.setCreateTime(new Date());
...@@ -528,7 +586,7 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss ...@@ -528,7 +586,7 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
// 当前来佣比例=当前入账金额/结算汇率/保费 * 100 // 当前来佣比例=当前入账金额/结算汇率/保费 * 100
BigDecimal currentCommissionRatio = commission.getAmount() BigDecimal currentCommissionRatio = commission.getAmount()
.divide(new BigDecimal(premium), 2, RoundingMode.HALF_UP) .divide(new BigDecimal(premium), 4, RoundingMode.HALF_UP)
.divide(new BigDecimal(commission.getExchangeRate()), 4, RoundingMode.HALF_UP) .divide(new BigDecimal(commission.getExchangeRate()), 4, RoundingMode.HALF_UP)
.multiply(new BigDecimal(100)) .multiply(new BigDecimal(100))
; ;
...@@ -558,9 +616,9 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss ...@@ -558,9 +616,9 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
// 当前来佣比例 // 当前来佣比例
commission.setCurrentCommissionRatio(currentCommissionRatio); commission.setCurrentCommissionRatio(currentCommissionRatio);
// 当期已入账来佣比例 = 当前来佣比例 + 已入账来佣比例 // 当期已入账来佣比例 = 当前来佣比例 + 已入账来佣比例
commission.setPeriodPaidRatio(currentCommissionRatio.add(ObjectUtils.defaultIfNull(expected.getPaidRatio(), BigDecimal.ZERO)).setScale(2, RoundingMode.HALF_UP)); // commission.setPeriodPaidRatio(currentCommissionRatio.add(ObjectUtils.defaultIfNull(expected.getPaidRatio(), BigDecimal.ZERO)).setScale(2, RoundingMode.HALF_UP));
// 当期剩余来佣比例 = 预计来佣来佣比例 - 当期已入账来佣比例 // // 当期剩余来佣比例 = 预计来佣来佣比例 - 当期已入账来佣比例
commission.setPeriodPendingRatio(expectedCommissionRatio.subtract(commission.getPeriodPaidRatio()).setScale(2, RoundingMode.HALF_UP)); // commission.setPeriodPendingRatio(expectedCommissionRatio.subtract(commission.getPeriodPaidRatio()).setScale(2, RoundingMode.HALF_UP));
// 达到预计比例时,待入账金额设置为 0 // 达到预计比例时,待入账金额设置为 0
if (commission.getPeriodPendingRatio().compareTo(BigDecimal.ZERO) == 0) { if (commission.getPeriodPendingRatio().compareTo(BigDecimal.ZERO) == 0) {
......
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