Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-csf
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xingmin
yd-csf
Commits
8c3791e2
Commit
8c3791e2
authored
Dec 03, 2025
by
jianan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新单跟进136
parent
e350da83
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
413 additions
and
231 deletions
+413
-231
yd-csf-api/src/main/java/com/yd/csf/api/controller/ApiCommissionController.java
+54
-64
yd-csf-service/src/main/java/com/yd/csf/service/service/CommissionAsyncService.java
+188
-23
yd-csf-service/src/main/java/com/yd/csf/service/service/CommissionService.java
+13
-3
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/CommissionServiceImpl.java
+158
-141
No files found.
yd-csf-api/src/main/java/com/yd/csf/api/controller/ApiCommissionController.java
View file @
8c3791e2
...
...
@@ -12,24 +12,22 @@ import com.yd.common.result.Result;
import
com.yd.csf.api.dto.CommissionExcelDTO
;
import
com.yd.csf.service.common.ErrorCode
;
import
com.yd.csf.service.dto.*
;
import
com.yd.csf.service.enums.CommissionStatusEnum
;
import
com.yd.csf.service.model.Commission
;
import
com.yd.csf.service.model.CommissionCompareRecord
;
import
com.yd.csf.service.model.CommissionEditRecord
;
import
com.yd.csf.service.model.CommissionExpected
;
import
com.yd.csf.service.service.CommissionCompareRecordService
;
import
com.yd.csf.service.service.CommissionEditRecordService
;
import
com.yd.csf.service.service.CommissionExpectedService
;
import
com.yd.csf.service.service.CommissionService
;
import
com.yd.csf.service.service.*
;
import
com.yd.csf.service.vo.CommissionStatisticsVO
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.redisson.api.RLock
;
import
org.redisson.api.RedissonClient
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.scheduling.annotation.Async
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.transaction.support.TransactionSynchronization
;
import
org.springframework.transaction.support.TransactionSynchronizationManager
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.multipart.MultipartFile
;
...
...
@@ -37,10 +35,8 @@ import javax.annotation.Resource;
import
javax.servlet.http.HttpServletRequest
;
import
java.io.IOException
;
import
java.math.BigDecimal
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
import
java.util.stream.Collectors
;
/**
...
...
@@ -58,16 +54,16 @@ public class ApiCommissionController {
@Resource
private
CommissionService
commissionService
;
@Resource
private
CommissionExpectedService
commissionExpectedService
;
@Resource
private
CommissionEditRecordService
commissionEditRecordService
;
@Resource
private
CommissionCompareRecordService
commissionCompareRecordService
;
@Resource
private
RedissonClient
redissonClient
;
@Resource
private
CommissionAsyncService
commissionAsyncService
;
@PostMapping
(
"/upload/excel"
)
...
...
@@ -93,7 +89,23 @@ public class ApiCommissionController {
String
loginUserId
=
currentLoginUser
.
getId
().
toString
();
// 数据处理
processData
(
dataList
,
loginUserId
);
List
<
Commission
>
entities
=
processData
(
dataList
,
loginUserId
);
// 批量比对
TransactionSynchronizationManager
.
registerSynchronization
(
new
TransactionSynchronization
()
{
@Override
public
void
afterCommit
()
{
try
{
// 重新查询最新的数据,获取已提交的数据
commissionAsyncService
.
commissionCompareBatch
(
entities
);
}
catch
(
Exception
e
)
{
// 比对失败不影响主事务,记录日志即可
log
.
error
(
"批量导入, 比对操作执行失败, error: {}"
,
e
.
getMessage
());
}
}
}
);
return
Result
.
success
(
true
);
}
...
...
@@ -130,7 +142,7 @@ public class ApiCommissionController {
/**
* 1.处理导入的数据 2.比对预计来佣 3.保存到数据库
*/
private
void
processData
(
List
<
CommissionExcelDTO
>
dataList
,
String
loginUserId
)
{
private
List
<
Commission
>
processData
(
List
<
CommissionExcelDTO
>
dataList
,
String
loginUserId
)
{
List
<
Commission
>
entities
=
new
ArrayList
<>();
for
(
CommissionExcelDTO
data
:
dataList
)
{
// 数据验证
...
...
@@ -141,52 +153,7 @@ public class ApiCommissionController {
// 保存来佣数据
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
()
.
map
(
Commission:
:
getPolicyNo
)
.
collect
(
Collectors
.
toList
());
// 根据保单号查询预计来佣
List
<
CommissionExpected
>
expectedList
=
commissionExpectedService
.
lambdaQuery
()
.
in
(
CommissionExpected:
:
getPolicyNo
,
policyNoList
)
.
list
();
for
(
Commission
commission
:
entities
)
{
// 查询预计来佣
CommissionExpected
commissionExpected
;
try
{
commissionExpected
=
commissionService
.
queryByCommission
(
commission
);
// 对比预计来佣
commissionService
.
compareWithExpected
(
commission
.
getPremium
(),
commission
,
commissionExpected
);
commissionExpectedService
.
updateById
(
commissionExpected
);
}
catch
(
Exception
e
)
{
// 预计来佣不存在,来佣状态设置为 比对失败
commission
.
setStatus
(
CommissionStatusEnum
.
COMPARE_FAIL
.
getItemValue
());
commission
.
setRemark
(
e
.
getMessage
());
}
}
// 保存来佣数据
commissionService
.
saveBatch
(
entities
);
// 更新预计来佣状态
commissionExpectedService
.
updateBatchById
(
expectedList
);
return
entities
;
}
/**
...
...
@@ -288,7 +255,30 @@ public class ApiCommissionController {
if
(
commissionUpdateRequest
==
null
||
commissionUpdateRequest
.
getCommissionBizId
()
==
null
)
{
return
Result
.
fail
(
ErrorCode
.
PARAMS_ERROR
.
getCode
(),
ErrorCode
.
PARAMS_ERROR
.
getMessage
());
}
return
Result
.
success
(
commissionService
.
updateCommission
(
commissionUpdateRequest
));
// 校验入参
commissionService
.
validateCommissionUpdateRequest
(
commissionUpdateRequest
);
String
lockKey
=
"COMMISSION_LOCK:"
+
commissionUpdateRequest
.
getCommissionBizId
();
RLock
lock
=
redissonClient
.
getLock
(
lockKey
);
try
{
// 竞争锁
boolean
res
=
lock
.
tryLock
(
3
,
15
,
TimeUnit
.
SECONDS
);
if
(!
res
)
{
log
.
warn
(
"获取分布式锁失败,commissionBizId: {}"
,
commissionUpdateRequest
.
getCommissionBizId
());
throw
new
BusinessException
(
"系统繁忙,请稍后重试"
);
}
// 更新来佣记录
Result
.
success
(
commissionService
.
updateCommission
(
commissionUpdateRequest
));
}
catch
(
InterruptedException
e
)
{
Thread
.
currentThread
().
interrupt
();
log
.
error
(
"更新来佣记录时,获取锁被中断"
,
e
);
return
Result
.
fail
(
ErrorCode
.
OPERATION_ERROR
.
getCode
(),
"更新来佣记录时,获取锁被中断"
);
}
finally
{
if
(
lock
!=
null
&&
lock
.
isLocked
()
&&
lock
.
isHeldByCurrentThread
())
{
lock
.
unlock
();
}
}
return
Result
.
success
(
true
);
}
/**
...
...
yd-csf-service/src/main/java/com/yd/csf/service/service/CommissionAsyncService.java
View file @
8c3791e2
package
com
.
yd
.
csf
.
service
.
service
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.yd.auth.core.dto.AuthUserDto
;
import
com.yd.auth.core.utils.SecurityUtil
;
import
com.yd.common.enums.ResultCode
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.csf.service.enums.CommissionExpectedStatusEnum
;
import
com.yd.csf.service.enums.CommissionStatusEnum
;
import
com.yd.csf.service.model.Commission
;
import
com.yd.csf.service.model.CommissionCompareRecord
;
import
com.yd.csf.service.model.CommissionExpected
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.scheduling.annotation.Async
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
javax.annotation.Resource
;
import
java.math.BigDecimal
;
import
java.math.RoundingMode
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
@Service
...
...
@@ -19,47 +33,198 @@ public class CommissionAsyncService {
private
CommissionExpectedService
commissionExpectedService
;
@Resource
private
CommissionService
commissionService
;
@Resource
private
CommissionCompareRecordService
commissionCompareRecordService
;
@Async
(
"commonAsyncExecutor"
)
//
@Async("commonAsyncExecutor")
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
void
commissionCompareBatch
(
List
<
Commission
>
entities
)
{
// 比对逻辑...
log
.
info
(
"开始异步比对,数据量:{}"
,
entities
.
size
());
// 1.根据导入的来佣获取保单号集合
List
<
String
>
policyNoList
=
entities
.
stream
()
.
map
(
Commission:
:
getPolicyNo
)
.
collect
(
Collectors
.
toList
());
// 2.根据保单号查询已存在的来佣记录
List
<
Commission
>
existingCommissions
=
commissionService
.
lambdaQuery
()
.
in
(
Commission:
:
getPolicyNo
,
policyNoList
)
.
list
();
// 来佣根据 保单号、来佣名称、来佣周期、货币 进行分组
Map
<
String
,
List
<
Commission
>>
commissionMap
=
existingCommissions
.
stream
()
.
collect
(
Collectors
.
groupingBy
(
c
->
c
.
getPolicyNo
()
+
c
.
getCommissionName
()
+
c
.
getCommissionPeriod
()
+
c
.
getCurrency
()
));
// 3.根据保单号查询预计来佣
List
<
CommissionExpected
>
expectedList
=
commissionExpectedService
.
lambdaQuery
()
.
in
(
CommissionExpected:
:
getPolicyNo
,
policyNoList
)
.
list
();
// 预计来佣根据 保单号、来佣名称、来佣周期、货币 进行映射
Map
<
String
,
CommissionExpected
>
expectedMap
=
expectedList
.
stream
()
.
collect
(
Collectors
.
toMap
(
commissionExpected
->
commissionExpected
.
getPolicyNo
()
+
commissionExpected
.
getCommissionName
()
+
commissionExpected
.
getCommissionPeriod
()
+
commissionExpected
.
getCurrency
(),
commissionExpected
->
commissionExpected
));
// 执行比对...
// 4.遍历预计来佣,进行比对
for
(
Map
.
Entry
<
String
,
CommissionExpected
>
entry
:
expectedMap
.
entrySet
())
{
// 根据 保单号、来佣名称、来佣周期、货币 分组
String
key
=
entry
.
getKey
();
CommissionExpected
commissionExpected
=
entry
.
getValue
();
// 从已存在的来佣记录中获取当前来佣记录
List
<
Commission
>
existingCommissionsByKey
=
commissionMap
.
getOrDefault
(
key
,
new
ArrayList
<>());
// 进行比对
doCompareBatch
(
commissionExpected
,
existingCommissionsByKey
);
}
}
public
void
commissionCompare
(
Commission
commission
)
{
log
.
info
(
"开始执行比对事务,来佣ID: {}, 保单号: {}"
,
commission
.
getId
(),
commission
.
getPolicyNo
());
private
void
doCompareBatch
(
CommissionExpected
commissionExpected
,
List
<
Commission
>
existingCommissions
)
{
// region 计算预计来佣属性
// 统计已入账金额、已入账比例
BigDecimal
paidRatio
=
BigDecimal
.
ZERO
;
BigDecimal
paidAmount
=
BigDecimal
.
ZERO
;
for
(
Commission
item
:
existingCommissions
)
{
paidRatio
=
paidRatio
.
add
(
item
.
getCurrentCommissionRatio
());
paidAmount
=
paidAmount
.
add
(
item
.
getAmount
());
}
CommissionExpected
commissionExpected
;
try
{
commissionExpected
=
commissionService
.
queryByCommission
(
commission
);
// 对比预计来佣
commissionService
.
compareWithExpected
(
commission
.
getPremium
(),
commission
,
commissionExpected
);
// 更新预计来佣已入账金额、已入账比例
commissionExpected
.
setPaidAmount
(
paidAmount
);
commissionExpected
.
setPaidRatio
(
paidRatio
);
// endregion 计算预计来佣属性
// 获取当前登录用户
AuthUserDto
currentLoginUser
=
SecurityUtil
.
getCurrentLoginUser
();
String
loginUserId
=
currentLoginUser
.
getId
().
toString
();
// 比对记录
List
<
CommissionCompareRecord
>
compareRecords
=
new
ArrayList
<>();
// 计算比对状态
if
(
paidRatio
.
compareTo
(
commissionExpected
.
getCommissionRatio
())
==
0
)
{
// 等于预计比例时,所有来佣设置为比对成功
for
(
Commission
existingCommission
:
existingCommissions
)
{
existingCommission
.
setStatus
(
CommissionStatusEnum
.
COMPARE_SUCCESS
.
getItemValue
());
// 创建比对记录
compareRecords
.
add
(
commissionService
.
getNewCompareRecord
(
existingCommission
,
commissionExpected
,
currentLoginUser
));
}
// 对应预计来佣设置为已来佣
commissionExpected
.
setStatus
(
CommissionExpectedStatusEnum
.
COMPARED
.
getItemValue
());
// 待入账金额设置为 0
commissionExpected
.
setPaidAmount
(
paidAmount
.
setScale
(
2
,
RoundingMode
.
HALF_UP
));
commissionExpected
.
setPaidRatio
(
paidRatio
);
// 更新预计来佣
commissionExpectedService
.
updateById
(
commissionExpected
);
// 更新已比对来佣记录
if
(
CollectionUtils
.
isNotEmpty
(
existingCommissions
))
{
commissionService
.
updateBatchById
(
existingCommissions
);
}
// 保存比对记录
commissionCompareRecordService
.
saveBatch
(
compareRecords
);
}
else
{
// 比对失败时,所有来佣设置为比对失败
for
(
Commission
existingCommission
:
existingCommissions
)
{
existingCommission
.
setStatus
(
CommissionStatusEnum
.
COMPARE_FAIL
.
getItemValue
());
// 创建比对记录
compareRecords
.
add
(
commissionService
.
getNewCompareRecord
(
existingCommission
,
commissionExpected
,
currentLoginUser
));
}
// 对应预计来佣设置为部分来佣
commissionExpected
.
setStatus
(
CommissionExpectedStatusEnum
.
PARTIAL
.
getItemValue
());
// 更新预计来佣
commissionExpectedService
.
updateById
(
commissionExpected
);
// 更新已比对来佣记录
if
(
CollectionUtils
.
isNotEmpty
(
existingCommissions
))
{
commissionService
.
updateBatchById
(
existingCommissions
);
}
// 保存比对记录
commissionCompareRecordService
.
saveBatch
(
compareRecords
);
}
}
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
void
commissionCompare
(
String
commissionBizId
,
String
policyNo
,
String
commissionName
,
Integer
commissionPeriod
,
String
currency
,
String
premium
)
{
log
.
info
(
"开始执行比对事务,来佣ID: {}, 保单号: {}"
,
commissionBizId
,
policyNo
);
// 比对成功,更新状态
commission
.
setStatus
(
CommissionStatusEnum
.
COMPARE_SUCCESS
.
getItemValue
());
// 查询所有已存在的来佣记录
List
<
Commission
>
existingCommissions
=
commissionService
.
list
(
new
QueryWrapper
<
Commission
>()
.
eq
(
"policy_no"
,
policyNo
)
.
eq
(
"commission_name"
,
commissionName
)
.
eq
(
"commission_period"
,
commissionPeriod
)
.
eq
(
"currency"
,
currency
));
}
catch
(
Exception
e
)
{
// 预计来佣不存在或比对失败
commission
.
setStatus
(
CommissionStatusEnum
.
COMPARE_FAIL
.
getItemValue
());
commission
.
setRemark
(
e
.
getMessage
());
log
.
warn
(
"来佣比对失败,保单号: {},原因: {}"
,
commission
.
getPolicyNo
(),
e
.
getMessage
());
// 当前 commission 记录
Commission
commission
=
existingCommissions
.
stream
()
.
filter
(
c
->
c
.
getCommissionBizId
().
equals
(
commissionBizId
))
.
findFirst
()
.
orElse
(
null
);
if
(
commission
==
null
)
{
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"未找到该来佣记录"
);
}
// 查询对应预计来佣
CommissionExpected
commissionExpected
=
commissionService
.
queryByCommission
(
commission
.
getPolicyNo
(),
commission
.
getCommissionName
(),
commission
.
getCommissionPeriod
(),
commission
.
getCurrency
(),
premium
);
doCompare
(
existingCommissions
,
commissionExpected
,
commission
);
}
private
void
doCompare
(
List
<
Commission
>
existingCommissions
,
CommissionExpected
commissionExpected
,
Commission
commission
)
{
// region 计算预计来佣属性
// 统计已入账金额、已入账比例
BigDecimal
paidRatio
=
BigDecimal
.
ZERO
;
BigDecimal
paidAmount
=
BigDecimal
.
ZERO
;
for
(
Commission
item
:
existingCommissions
)
{
paidRatio
=
paidRatio
.
add
(
item
.
getCurrentCommissionRatio
());
paidAmount
=
paidAmount
.
add
(
item
.
getAmount
());
}
// 更新来佣的比对状态(在比对事务中)
commissionService
.
updateById
(
commission
);
// 更新预计来佣已入账金额、已入账比例
commissionExpected
.
setPaidAmount
(
paidAmount
);
commissionExpected
.
setPaidRatio
(
paidRatio
);
// endregion 计算预计来佣属性
// 获取当前登录用户
AuthUserDto
currentLoginUser
=
SecurityUtil
.
getCurrentLoginUser
();
String
loginUserId
=
currentLoginUser
.
getId
().
toString
();
// 计算比对状态
if
(
paidRatio
.
compareTo
(
commissionExpected
.
getCommissionRatio
())
==
0
)
{
// 等于预计比例时,所有来佣设置为比对成功
for
(
Commission
existingCommission
:
existingCommissions
)
{
existingCommission
.
setStatus
(
CommissionStatusEnum
.
COMPARE_SUCCESS
.
getItemValue
());
}
// 对应预计来佣设置为已来佣
commissionExpected
.
setStatus
(
CommissionExpectedStatusEnum
.
COMPARED
.
getItemValue
());
// 待入账金额设置为 0
commissionExpected
.
setPaidAmount
(
paidAmount
.
setScale
(
2
,
RoundingMode
.
HALF_UP
));
commissionExpected
.
setPaidRatio
(
paidRatio
);
// 更新预计来佣
commissionExpectedService
.
updateById
(
commissionExpected
);
// 更新已比对来佣记录
if
(
CollectionUtils
.
isNotEmpty
(
existingCommissions
))
{
commissionService
.
updateBatchById
(
existingCommissions
);
}
// 保存比对记录
commissionService
.
saveCompareRecord
(
commission
,
commissionExpected
,
currentLoginUser
);
}
else
{
// 不等于预计比例时,设置为比对失败
commission
.
setStatus
(
CommissionStatusEnum
.
COMPARE_FAIL
.
getItemValue
());
// 更新来佣
commissionService
.
updateById
(
commission
);
// 对应预计来佣设置为部分来佣
commissionExpected
.
setStatus
(
CommissionExpectedStatusEnum
.
PARTIAL
.
getItemValue
());
// 更新预计来佣
commissionExpectedService
.
updateById
(
commissionExpected
);
// 保存比对记录
commissionService
.
saveCompareRecord
(
commission
,
commissionExpected
,
currentLoginUser
);
}
}
}
yd-csf-service/src/main/java/com/yd/csf/service/service/CommissionService.java
View file @
8c3791e2
package
com
.
yd
.
csf
.
service
.
service
;
import
com.baomidou.mybatisplus.core.conditions.Wrapper
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.yd.auth.core.dto.AuthUserDto
;
import
com.yd.csf.service.dto.*
;
import
com.yd.csf.service.model.Commission
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.yd.csf.service.model.CommissionCompareRecord
;
import
com.yd.csf.service.model.CommissionExpected
;
import
com.yd.csf.service.vo.CommissionStatisticsVO
;
import
com.yd.csf.service.vo.CommissionVO
;
import
java.util.List
;
import
java.util.Map
;
/**
* @author Zhang Jianan
...
...
@@ -40,5 +40,15 @@ public interface CommissionService extends IService<Commission> {
CommissionStatisticsVO
getCommissionStatistics
(
List
<
Long
>
commissionIds
);
CommissionExpected
queryByCommission
(
Commission
commission
);
CommissionExpected
queryByCommission
(
String
policyNo
,
String
commissionName
,
Integer
commissionPeriod
,
String
currency
,
String
premium
);
void
calculatePaidAmountByCommissionList
(
Commission
commission
,
CommissionExpected
one
);
void
validateCommissionUpdateRequest
(
CommissionUpdateRequest
commissionUpdateRequest
);
void
saveUpdateCommissionRecord
(
Commission
commission
,
CommissionUpdateRequest
commissionUpdateRequest
,
AuthUserDto
currentLoginUser
);
void
saveCompareRecord
(
Commission
commission
,
CommissionExpected
commissionExpected
,
AuthUserDto
currentLoginUser
);
CommissionCompareRecord
getNewCompareRecord
(
Commission
existingCommission
,
CommissionExpected
commissionExpected
,
AuthUserDto
currentLoginUser
);
}
yd-csf-service/src/main/java/com/yd/csf/service/service/impl/CommissionServiceImpl.java
View file @
8c3791e2
...
...
@@ -12,7 +12,6 @@ import com.yd.common.enums.CommonEnum;
import
com.yd.common.enums.ResultCode
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.common.utils.RedisUtil
;
import
com.yd.csf.service.dto.*
;
import
com.yd.csf.service.enums.CommissionExpectedStatusEnum
;
import
com.yd.csf.service.enums.CommissionStatusEnum
;
...
...
@@ -26,8 +25,6 @@ import lombok.extern.slf4j.Slf4j;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.lang3.ObjectUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.redisson.api.RLock
;
import
org.redisson.api.RedissonClient
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
...
...
@@ -38,7 +35,6 @@ import javax.annotation.Resource;
import
java.math.BigDecimal
;
import
java.math.RoundingMode
;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
...
...
@@ -70,8 +66,7 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
private
CommissionCompareRecordService
commissionCompareRecordService
;
@Resource
private
CommissionAsyncService
commissionAsyncService
;
@Resource
private
RedissonClient
redissonClient
;
@Override
public
QueryWrapper
<
Commission
>
getQueryWrapper
(
CommissionQueryRequest
commissionQueryRequest
)
{
...
...
@@ -119,74 +114,26 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
}
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
// 主事务
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
Boolean
updateCommission
(
CommissionUpdateRequest
commissionUpdateRequest
)
{
String
lockKey
=
"COMMISSION_LOCK:"
+
commissionUpdateRequest
.
getCommissionBizId
();
RLock
lock
=
redissonClient
.
getLock
(
lockKey
);
try
{
// 竞争锁
boolean
res
=
lock
.
tryLock
(
3
,
15
,
TimeUnit
.
SECONDS
);
if
(!
res
)
{
log
.
warn
(
"获取分布式锁失败,commissionBizId: {}"
,
commissionUpdateRequest
.
getCommissionBizId
());
throw
new
BusinessException
(
"系统繁忙,请稍后重试"
);
}
String
commissionBizId
=
commissionUpdateRequest
.
getCommissionBizId
();
String
commissionBizId
=
commissionUpdateRequest
.
getCommissionBizId
();
Commission
commission
=
this
.
getOne
(
new
QueryWrapper
<
Commission
>()
.
eq
(
"commission_biz_id"
,
commissionBizId
));
// 查询旧数据
Commission
commission
=
this
.
getByCommissionBizId
(
commissionBizId
);
if
(
commission
==
null
)
{
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"未找到该来佣记录"
);
}
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
);
}
}
}
);
}
BigDecimal
amount
=
commission
.
getAmount
();
BigDecimal
requestAmount
=
commissionUpdateRequest
.
getAmount
();
return
updateResult
;
// 1. 执行主更新事务(这个方法将在当前事务中执行)
// 计算当前来佣比例
BigDecimal
currentCommissionRatio
=
this
.
calculateCurrentCommissionRatio
(
commissionUpdateRequest
.
getAmount
(),
commissionUpdateRequest
.
getPremium
(),
commissionUpdateRequest
.
getExchangeRate
());
}
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
();
String
loginUserId
=
currentLoginUser
.
getId
().
toString
();
...
...
@@ -195,18 +142,66 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
saveUpdateCommissionRecord
(
commission
,
commissionUpdateRequest
,
currentLoginUser
);
// 更新属性
BeanUtils
.
copyProperties
(
commissionUpdateRequest
,
commission
,
"id"
,
"commissionBizId"
);
BeanUtils
.
copyProperties
(
commissionUpdateRequest
,
commission
,
"commissionBizId"
);
commission
.
setCurrentCommissionRatio
(
currentCommissionRatio
);
commission
.
setUpdaterId
(
loginUserId
);
commission
.
setUpdateTime
(
new
Date
());
// 先更新来佣属性(在主事务中)
// 执行更新操作(这个方法将在当前事务中执行)
this
.
updateById
(
commission
);
// 返回true表示主事务成功
// 没改金额,则不比对
if
(
amount
.
compareTo
(
requestAmount
)
!=
0
)
{
// 2. 注册事务同步器,在主事务提交后执行比对
TransactionSynchronizationManager
.
registerSynchronization
(
new
TransactionSynchronization
()
{
@Override
public
void
afterCommit
()
{
try
{
// 重新查询最新的数据,获取已提交的数据
commissionAsyncService
.
commissionCompare
(
commission
.
getCommissionBizId
(),
commission
.
getPolicyNo
(),
commission
.
getCommissionName
(),
commission
.
getCommissionPeriod
(),
commission
.
getCurrency
(),
commissionUpdateRequest
.
getPremium
()
);
}
catch
(
Exception
e
)
{
// 比对失败不影响主事务,记录日志即可
log
.
error
(
"主事务提交后,比对操作执行失败,commissionBizId: {}"
,
commissionUpdateRequest
.
getCommissionBizId
(),
e
);
}
}
}
);
}
return
true
;
}
private
void
saveUpdateCommissionRecord
(
Commission
commission
,
CommissionUpdateRequest
commissionUpdateRequest
,
AuthUserDto
currentLoginUser
)
{
@Override
public
void
validateCommissionUpdateRequest
(
CommissionUpdateRequest
commissionUpdateRequest
)
{
// 校验入参
if
(
ObjectUtils
.
isEmpty
(
commissionUpdateRequest
.
getCommissionBizId
()))
{
log
.
error
(
"来佣业务id不能为空:{}"
,
commissionUpdateRequest
.
getCommissionBizId
());
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"来佣业务id不能为空"
);
}
if
(
ObjectUtils
.
isEmpty
(
commissionUpdateRequest
.
getPremium
()))
{
log
.
error
(
"保费不能为空:{}"
,
commissionUpdateRequest
.
getPremium
());
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"保费不能为空"
);
}
if
(
ObjectUtils
.
isEmpty
(
commissionUpdateRequest
.
getAmount
()))
{
log
.
error
(
"当前入账金额不能为空,来佣业务id:{}"
,
commissionUpdateRequest
.
getCommissionBizId
());
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"当前入账金额不能为空"
);
}
if
(
ObjectUtils
.
isEmpty
(
commissionUpdateRequest
.
getExchangeRate
()))
{
log
.
error
(
"当前结算汇率不能为空,来佣业务id:{}"
,
commissionUpdateRequest
.
getCommissionBizId
());
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"当前结算汇率不能为空"
);
}
}
@Override
public
void
saveUpdateCommissionRecord
(
Commission
commission
,
CommissionUpdateRequest
commissionUpdateRequest
,
AuthUserDto
currentLoginUser
)
{
// 保存修改记录
List
<
CommissionEditRecord
>
commissionEditRecords
=
new
ArrayList
<>();
...
...
@@ -279,18 +274,38 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
}
@Override
public
CommissionExpected
queryByCommission
(
Commission
commission
)
{
public
CommissionExpected
queryByCommission
(
String
policyNo
,
String
commissionName
,
Integer
commissionPeriod
,
String
currency
,
String
premium
)
{
QueryWrapper
<
CommissionExpected
>
queryWrapper
=
new
QueryWrapper
<>();
queryWrapper
.
eq
(
"policy_no"
,
commission
.
getPolicyNo
()
);
queryWrapper
.
eq
(
"commission_name"
,
commission
.
getCommissionName
()
);
queryWrapper
.
eq
(
"commission_period"
,
commission
.
getCommissionPeriod
()
);
queryWrapper
.
eq
(
"currency"
,
c
ommission
.
getCurrency
()
);
queryWrapper
.
eq
(
"policy_no"
,
policyNo
);
queryWrapper
.
eq
(
"commission_name"
,
commission
Name
);
queryWrapper
.
eq
(
"commission_period"
,
commission
Period
);
queryWrapper
.
eq
(
"currency"
,
c
urrency
);
CommissionExpected
one
=
commissionExpectedService
.
getOne
(
queryWrapper
);
if
(
ObjectUtils
.
isEmpty
(
one
))
{
String
errorMsg
=
String
.
format
(
"未找到当前来佣对应的预计来佣,保单号:%s, 来佣名称:%s, 来佣期数:%s, 币种:%s"
,
commission
.
getPolicyNo
(),
commission
.
getCommissionName
(),
commission
.
getCommissionPeriod
(),
commission
.
getCurrency
()
);
policyNo
,
commissionName
,
commissionPeriod
,
currency
);
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
errorMsg
);
}
// 计算预计来佣金额 (统一试算币种:HKD)
if
(
one
.
getExpectedAmount
()
==
null
)
{
BigDecimal
expectedAmount
=
new
BigDecimal
(
premium
)
.
multiply
(
one
.
getCommissionRatio
());
if
(
"USD"
.
equals
(
one
.
getCurrency
()))
{
expectedAmount
=
expectedAmount
.
multiply
(
one
.
getDefaultExchangeRate
());
}
one
.
setExpectedAmount
(
expectedAmount
.
divide
(
BigDecimal
.
valueOf
(
100
),
2
,
RoundingMode
.
HALF_UP
));
}
return
one
;
}
/**
* 根据对应的所有来佣记录,统计已入账金额、已入账比例
*
* @param commission
* @param one
*/
@Override
public
void
calculatePaidAmountByCommissionList
(
Commission
commission
,
CommissionExpected
one
)
{
// 查询当前来佣对应的所有来佣记录
QueryWrapper
<
Commission
>
queryWrapperCommission
=
new
QueryWrapper
<>();
queryWrapperCommission
.
eq
(
"policy_no"
,
commission
.
getPolicyNo
());
...
...
@@ -309,16 +324,6 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
one
.
setPaidRatio
(
paidRatio
);
}
}
// 计算预计来佣金额 (统一试算币种:HKD)
if
(
one
.
getExpectedAmount
()
==
null
)
{
BigDecimal
expectedAmount
=
new
BigDecimal
(
commission
.
getPremium
())
.
multiply
(
one
.
getCommissionRatio
());
if
(
"USD"
.
equals
(
one
.
getCurrency
()))
{
expectedAmount
=
expectedAmount
.
multiply
(
one
.
getDefaultExchangeRate
());
}
one
.
setExpectedAmount
(
expectedAmount
.
divide
(
BigDecimal
.
valueOf
(
100
),
2
,
RoundingMode
.
HALF_UP
));
}
return
one
;
}
@Override
...
...
@@ -519,34 +524,39 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
// 生成新单编号
String
commissionBizId
=
RandomStringGenerator
.
generateBizId16
(
CommonEnum
.
UID_TYPE_COMMISSION
.
getCode
());
commission
.
setCommissionBizId
(
commissionBizId
);
// 保费为空时,查询保单初始保费或支付保费,为空时默认0
if
(
ObjectUtils
.
isEmpty
(
commission
.
getPremium
()))
{
Object
object
=
policy
.
getInitialPremium
()
!=
null
?
policy
.
getInitialPremium
()
:
policy
.
getPaymentPremium
();
if
(
object
!=
null
)
{
commission
.
setPremium
(
object
.
toString
());
}
else
{
commission
.
setPremium
(
BigDecimal
.
ZERO
.
toString
());
}
}
// 查询预计来佣
// CommissionExpected commissionExpected;
// 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());
// }
commission
.
setCreatorId
(
loginUserId
);
commission
.
setCreateTime
(
new
Date
());
commission
.
setUpdaterId
(
loginUserId
);
commission
.
setUpdateTime
(
new
Date
());
// 保存来佣
this
.
save
(
commission
);
// 注册事务同步器,在主事务提交后执行比对
TransactionSynchronizationManager
.
registerSynchronization
(
new
TransactionSynchronization
()
{
@Override
public
void
afterCommit
()
{
try
{
// 重新查询最新的数据,获取已提交的数据
commissionAsyncService
.
commissionCompare
(
commission
.
getCommissionBizId
(),
commission
.
getPolicyNo
(),
commission
.
getCommissionName
(),
commission
.
getCommissionPeriod
(),
commission
.
getCurrency
(),
commissionAddRequest
.
getPremium
()
);
}
catch
(
Exception
e
)
{
// 比对失败不影响主事务,记录日志即可
log
.
error
(
"主事务提交后,比对操作执行失败,commissionBizId: {}"
,
commissionBizId
,
e
);
}
}
}
);
return
t
his
.
save
(
commission
)
;
return
t
rue
;
}
@Override
...
...
@@ -567,22 +577,7 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
log
.
error
(
"预计来佣的来佣比例不能为空,预计来佣业务id:{}"
,
expected
.
getCommissionExpectedBizId
());
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"预计来佣的来佣比例不能为空"
);
}
if
(
ObjectUtils
.
isEmpty
(
expected
.
getDefaultExchangeRate
()))
{
log
.
error
(
"预计来佣的默认汇率不能为空,预计来佣业务id:{}"
,
expected
.
getCommissionExpectedBizId
());
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"预计来佣的默认汇率不能为空"
);
}
if
(
ObjectUtils
.
isEmpty
(
premium
))
{
log
.
error
(
"保费不能为空,来佣业务id:{}"
,
commission
.
getCommissionBizId
());
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"保费不能为空"
);
}
if
(
ObjectUtils
.
isEmpty
(
commission
.
getAmount
()))
{
log
.
error
(
"当前入账金额不能为空,来佣业务id:{}"
,
commission
.
getCommissionBizId
());
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"当前入账金额不能为空"
);
}
if
(
ObjectUtils
.
isEmpty
(
commission
.
getExchangeRate
()))
{
log
.
error
(
"当前结算汇率不能为空,来佣业务id:{}"
,
commission
.
getCommissionBizId
());
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"当前结算汇率不能为空"
);
}
// 当前来佣比例=当前入账金额/结算汇率/保费 * 100
BigDecimal
currentCommissionRatio
=
commission
.
getAmount
()
...
...
@@ -592,10 +587,6 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
;
// 预计来佣比例
BigDecimal
expectedCommissionRatio
=
expected
.
getCommissionRatio
();
// 预计总金额
BigDecimal
expectedAmount
=
expected
.
getExpectedAmount
();
// 已入账金额
BigDecimal
paidAmount
=
expected
.
getPaidAmount
();
if
(
currentCommissionRatio
.
compareTo
(
expectedCommissionRatio
)
==
0
)
{
// 一致,来佣状态设置为 比对成功
...
...
@@ -620,19 +611,29 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
// // 当期剩余来佣比例 = 预计来佣来佣比例 - 当期已入账来佣比例
// commission.setPeriodPendingRatio(expectedCommissionRatio.subtract(commission.getPeriodPaidRatio()).setScale(2, RoundingMode.HALF_UP));
// 达到预计比例时,待入账金额设置为 0
if
(
commission
.
getPeriodPendingRatio
().
compareTo
(
BigDecimal
.
ZERO
)
==
0
)
{
commission
.
setPendingAmount
(
BigDecimal
.
ZERO
.
setScale
(
2
,
RoundingMode
.
HALF_UP
));
expected
.
setPaidAmount
(
paidAmount
.
setScale
(
2
,
RoundingMode
.
HALF_UP
));
expected
.
setPaidRatio
(
commission
.
getPeriodPaidRatio
());
}
// 保存比对记录
saveCompareRecord
(
commission
,
expected
);
//
saveCompareRecord(commission, expected);
}
}
private
void
saveCompareRecord
(
Commission
commission
,
CommissionExpected
expected
)
{
public
BigDecimal
calculateCurrentCommissionRatio
(
BigDecimal
amount
,
String
premium
,
String
exchangeRate
)
{
if
(
ObjectUtils
.
isEmpty
(
premium
))
{
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"保费不能为空"
);
}
if
(
ObjectUtils
.
isEmpty
(
amount
))
{
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"当前入账金额不能为空"
);
}
if
(
ObjectUtils
.
isEmpty
(
exchangeRate
))
{
throw
new
BusinessException
(
ResultCode
.
NULL_ERROR
.
getCode
(),
"当前结算汇率不能为空"
);
}
// 当前来佣比例=当前入账金额/结算汇率/保费 * 100
return
amount
.
divide
(
new
BigDecimal
(
premium
),
4
,
RoundingMode
.
HALF_UP
)
.
divide
(
new
BigDecimal
(
exchangeRate
),
4
,
RoundingMode
.
HALF_UP
)
.
multiply
(
new
BigDecimal
(
100
));
}
@Override
public
void
saveCompareRecord
(
Commission
commission
,
CommissionExpected
expected
,
AuthUserDto
currentLoginUser
)
{
CommissionCompareRecord
commissionCompareRecord
=
new
CommissionCompareRecord
();
commissionCompareRecord
.
setCommissionExpectedBizId
(
expected
.
getCommissionExpectedBizId
());
commissionCompareRecord
.
setCommissionBizId
(
commission
.
getCommissionBizId
());
...
...
@@ -647,6 +648,22 @@ public class CommissionServiceImpl extends ServiceImpl<CommissionMapper, Commiss
commissionCompareRecordService
.
save
(
commissionCompareRecord
);
}
@Override
public
CommissionCompareRecord
getNewCompareRecord
(
Commission
commission
,
CommissionExpected
expected
,
AuthUserDto
currentLoginUser
)
{
CommissionCompareRecord
commissionCompareRecord
=
new
CommissionCompareRecord
();
commissionCompareRecord
.
setCommissionExpectedBizId
(
expected
.
getCommissionExpectedBizId
());
commissionCompareRecord
.
setCommissionBizId
(
commission
.
getCommissionBizId
());
commissionCompareRecord
.
setCommissionPeriod
(
commission
.
getCommissionPeriod
());
commissionCompareRecord
.
setTotalPeriod
(
commission
.
getTotalPeriod
());
commissionCompareRecord
.
setAmount
(
commission
.
getAmount
());
commissionCompareRecord
.
setCurrency
(
commission
.
getCurrency
());
commissionCompareRecord
.
setExchangeRate
(
commission
.
getExchangeRate
());
commissionCompareRecord
.
setStatus
(
commission
.
getStatus
());
commissionCompareRecord
.
setRemark
(
commission
.
getRemark
());
commissionCompareRecord
.
setCreateTime
(
commission
.
getCreateTime
());
return
commissionCompareRecord
;
}
/**
* 查询列表
*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment