Browse Source

对接拼团数据1

master
wangfukang 1 month ago
parent
commit
601ce79a4f
  1. 16
      hiver-admin/test-output/test-report.html
  2. 171
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ReturnCommissionController.java
  3. 31
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java
  4. 4
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java

16
hiver-admin/test-output/test-report.html

@ -35,7 +35,7 @@
<a href="#"><span class="badge badge-primary">Hiver</span></a>
</li>
<li class="m-r-10">
<a href="#"><span class="badge badge-primary">六月 23, 2026 16:55:30</span></a>
<a href="#"><span class="badge badge-primary">六月 24, 2026 14:41:22</span></a>
</li>
</ul>
</div>
@ -84,7 +84,7 @@
<div class="test-detail">
<span class="meta text-white badge badge-sm"></span>
<p class="name">passTest</p>
<p class="text-sm"><span>16:55:31 下午</span> / <span>0.032 secs</span></p>
<p class="text-sm"><span>14:41:23 下午</span> / <span>0.026 secs</span></p>
</div>
<div class="test-contents d-none">
<div class="detail-head">
@ -92,9 +92,9 @@
<div class="info">
<div class='float-right'><span class='badge badge-default'>#test-id=1</span></div>
<h5 class="test-status text-pass">passTest</h5>
<span class='badge badge-success'>06.23.2026 16:55:31</span>
<span class='badge badge-danger'>06.23.2026 16:55:31</span>
<span class='badge badge-default'>0.032 secs</span>
<span class='badge badge-success'>06.24.2026 14:41:23</span>
<span class='badge badge-danger'>06.24.2026 14:41:23</span>
<span class='badge badge-default'>0.026 secs</span>
</div>
<div class="m-t-10 m-l-5"></div>
</div>
@ -104,7 +104,7 @@
<tbody>
<tr class="event-row">
<td><span class="badge log pass-bg">Pass</span></td>
<td>16:55:31</td>
<td>14:41:23</td>
<td>
Test passed
</td>
@ -128,13 +128,13 @@
<div class="col-md-3">
<div class="card"><div class="card-body">
<p class="m-b-0">Started</p>
<h3>六月 23, 2026 16:55:30</h3>
<h3>六月 24, 2026 14:41:22</h3>
</div></div>
</div>
<div class="col-md-3">
<div class="card"><div class="card-body">
<p class="m-b-0">Ended</p>
<h3>六月 23, 2026 16:55:31</h3>
<h3>六月 24, 2026 14:41:23</h3>
</div></div>
</div>
<div class="col-md-3">

171
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ReturnCommissionController.java

@ -3,6 +3,7 @@ package cc.hiver.mall.controller;
import cc.hiver.core.common.constant.DealingsRecordConstant;
import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.utils.SecurityUtil;
import cc.hiver.core.common.utils.SnowFlakeUtil;
import cc.hiver.core.common.utils.StringUtils;
import cc.hiver.core.common.vo.Result;
import cc.hiver.core.entity.User;
@ -24,19 +25,24 @@ import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Slf4j
@RestController
@Api(tags = "店铺提现接口")
@Api(tags = "提现接口")
@RequestMapping("/hiver/app/returnCommission/")
@Transactional
public class ReturnCommissionController {
private static final long WITHDRAW_REQUEST_LOCK_MINUTES = 30L;
private static final long WITHDRAW_ACCOUNT_LOCK_SECONDS = 120L;
@Autowired
private ReturnCommissionService returnCommissionService;
@ -55,6 +61,9 @@ public class ReturnCommissionController {
@Autowired
private DealingsRecordService dealingsRecordService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@RequestMapping(value = "/save", method = RequestMethod.POST)
@ApiOperation("新增店铺提现")
public Result save(ReturnCommission returnCommission) {
@ -113,26 +122,40 @@ public class ReturnCommissionController {
@Transactional
@RequestMapping(value = "/handleReturn", method = RequestMethod.POST)
@ApiOperation("提现处理")
@ApiOperation("店铺提现处理")
public Result handleReturn(@RequestBody ReturnCommission returnCommission) {
//final String shopId = securityUtil.getShopId();
if(returnCommission.getCommission() == null ){
return ResultUtil.error("提现金额不能为空!");
final Result validateResult = validateReturnCommission(returnCommission);
if (validateResult != null) {
return validateResult;
}
if(returnCommission.getCommission().compareTo(BigDecimal.ZERO) == 0){
return ResultUtil.error("提现金额不能为0!");
if (StringUtils.isEmpty(returnCommission.getShopId())) {
return ResultUtil.error("商铺id不能为空!");
}
if(StringUtils.isEmpty(returnCommission.getAliName())){
return ResultUtil.error("支付宝实名名称不能为空!");
final String withdrawId = ensureWithdrawId(returnCommission);
final String requestLockKey = buildRequestLockKey(withdrawId);
if (!tryLock(requestLockKey, WITHDRAW_REQUEST_LOCK_MINUTES, TimeUnit.MINUTES)) {
return ResultUtil.error("提现处理中,请勿重复提交!");
}
if(StringUtils.isEmpty(returnCommission.getAliAccount())){
return ResultUtil.error("支付宝手机号不能为空!");
String accountLockKey = null;
boolean keepRequestLock = false;
try {
if (returnCommissionService.getById(withdrawId) != null) {
keepRequestLock = true;
return ResultUtil.error("请勿重复提交提现申请!");
}
accountLockKey = buildAccountLockKey("shop", returnCommission.getShopId());
if (!tryLock(accountLockKey, WITHDRAW_ACCOUNT_LOCK_SECONDS, TimeUnit.SECONDS)) {
return ResultUtil.error("当前账户已有提现处理中,请稍后再试!");
}
boolean result = false;
String aliResult = "";
final Shop shop = shopService.findById(returnCommission.getShopId());
if (shop == null) {
return ResultUtil.error("商铺不存在!");
}
returnCommission.setRemark("商家" + shop.getShopName() + "提现");
if (shop.getBalance().compareTo(returnCommission.getCommission()) < 0) {
// 如果提现金额大于余额,则不允许提现
@ -153,6 +176,7 @@ public class ReturnCommissionController {
return ResultUtil.error("提现金额不可大于佣金余额!");
}*/
try {
keepRequestLock = true;
final AlipayFundTransUniTransferResponse payResult = AliPayNewUtil.pay(phoneNumber, name, String.valueOf(commission), returnCommission.getId());
if ("SUCCESS".equals(payResult.getStatus())) {
returnCommission.setStatus("1");
@ -191,10 +215,17 @@ public class ReturnCommissionController {
//2.修改提现记录
result = returnCommissionService.save(returnCommission);
if (result) {
keepRequestLock = true;
return ResultUtil.success("处理完成," + aliResult);
} else {
return ResultUtil.error("修改提现数据失败," + aliResult);
}
} finally {
releaseLock(accountLockKey);
if (!keepRequestLock) {
releaseLock(requestLockKey);
}
}
}
@ -204,22 +235,36 @@ public class ReturnCommissionController {
public Result handleReturnUser(@RequestBody ReturnCommission returnCommission) {
//final String shopId = securityUtil.getShopId();
if(returnCommission.getCommission() == null ){
return ResultUtil.error("提现金额不能为空!");
final Result validateResult = validateReturnCommission(returnCommission);
if (validateResult != null) {
return validateResult;
}
if(returnCommission.getCommission().compareTo(BigDecimal.ZERO) == 0){
return ResultUtil.error("提现金额不能为0!");
if (StringUtils.isEmpty(returnCommission.getUserId())) {
return ResultUtil.error("用户id不能为空!");
}
if(StringUtils.isEmpty(returnCommission.getAliName())){
return ResultUtil.error("支付宝实名名称不能为空!");
final String withdrawId = ensureWithdrawId(returnCommission);
final String requestLockKey = buildRequestLockKey(withdrawId);
if (!tryLock(requestLockKey, WITHDRAW_REQUEST_LOCK_MINUTES, TimeUnit.MINUTES)) {
return ResultUtil.error("提现处理中,请勿重复提交!");
}
if(StringUtils.isEmpty(returnCommission.getAliAccount())){
return ResultUtil.error("支付宝手机号不能为空!");
String accountLockKey = null;
boolean keepRequestLock = false;
try {
if (returnCommissionService.getById(withdrawId) != null) {
keepRequestLock = true;
return ResultUtil.error("请勿重复提交提现申请!");
}
accountLockKey = buildAccountLockKey("user", returnCommission.getUserId());
if (!tryLock(accountLockKey, WITHDRAW_ACCOUNT_LOCK_SECONDS, TimeUnit.SECONDS)) {
return ResultUtil.error("当前账户已有提现处理中,请稍后再试!");
}
boolean result = false;
String aliResult = "";
final User user = userService.findById(returnCommission.getUserId());
if (user == null) {
return ResultUtil.error("用户不存在!");
}
returnCommission.setRemark("用户" + user.getUsername() + "提现");
if (user.getDepoBal().compareTo(returnCommission.getCommission()) < 0) {
// 如果提现金额大于余额,则不允许提现
@ -240,6 +285,7 @@ public class ReturnCommissionController {
return ResultUtil.error("提现金额不可大于佣金余额!");
}*/
try {
keepRequestLock = true;
final AlipayFundTransUniTransferResponse payResult = AliPayNewUtil.pay(phoneNumber, name, String.valueOf(commission), returnCommission.getId());
if ("SUCCESS".equals(payResult.getStatus())) {
returnCommission.setStatus("1");
@ -278,10 +324,17 @@ public class ReturnCommissionController {
//2.修改提现记录
result = returnCommissionService.save(returnCommission);
if (result) {
keepRequestLock = true;
return ResultUtil.success("处理完成," + aliResult);
} else {
return ResultUtil.error("修改提现数据失败," + aliResult);
}
} finally {
releaseLock(accountLockKey);
if (!keepRequestLock) {
releaseLock(requestLockKey);
}
}
}
@ -291,22 +344,36 @@ public class ReturnCommissionController {
public Result handleReturnWorker(@RequestBody ReturnCommission returnCommission) {
//final String shopId = securityUtil.getShopId();
if(returnCommission.getCommission() == null ){
return ResultUtil.error("提现金额不能为空!");
final Result validateResult = validateReturnCommission(returnCommission);
if (validateResult != null) {
return validateResult;
}
if(returnCommission.getCommission().compareTo(BigDecimal.ZERO) == 0){
return ResultUtil.error("提现金额不能为0!");
if (StringUtils.isEmpty(returnCommission.getWorkerId())) {
return ResultUtil.error("配送员id不能为空!");
}
if(StringUtils.isEmpty(returnCommission.getAliName())){
return ResultUtil.error("支付宝实名名称不能为空!");
final String withdrawId = ensureWithdrawId(returnCommission);
final String requestLockKey = buildRequestLockKey(withdrawId);
if (!tryLock(requestLockKey, WITHDRAW_REQUEST_LOCK_MINUTES, TimeUnit.MINUTES)) {
return ResultUtil.error("提现处理中,请勿重复提交!");
}
if(StringUtils.isEmpty(returnCommission.getAliAccount())){
return ResultUtil.error("支付宝手机号不能为空!");
String accountLockKey = null;
boolean keepRequestLock = false;
try {
if (returnCommissionService.getById(withdrawId) != null) {
keepRequestLock = true;
return ResultUtil.error("请勿重复提交提现申请!");
}
accountLockKey = buildAccountLockKey("worker", returnCommission.getWorkerId());
if (!tryLock(accountLockKey, WITHDRAW_ACCOUNT_LOCK_SECONDS, TimeUnit.SECONDS)) {
return ResultUtil.error("当前账户已有提现处理中,请稍后再试!");
}
boolean result = false;
String aliResult = "";
Worker worker = workerServiceImpl.findByWorkerId(returnCommission.getWorkerId());
if (worker == null) {
return ResultUtil.error("配送员不存在!");
}
returnCommission.setRemark("配送员" + worker.getWorkerName() + "提现");
if (worker.getDepoBalRel().compareTo(returnCommission.getCommission()) < 0) {
// 如果提现金额大于余额,则不允许提现
@ -327,6 +394,7 @@ public class ReturnCommissionController {
return ResultUtil.error("提现金额不可大于佣金余额!");
}*/
try {
keepRequestLock = true;
final AlipayFundTransUniTransferResponse payResult = AliPayNewUtil.pay(phoneNumber, name, String.valueOf(commission), returnCommission.getId());
if ("SUCCESS".equals(payResult.getStatus())) {
returnCommission.setStatus("1");
@ -365,11 +433,62 @@ public class ReturnCommissionController {
//2.修改提现记录
result = returnCommissionService.save(returnCommission);
if (result) {
keepRequestLock = true;
return ResultUtil.success("处理完成," + aliResult);
} else {
return ResultUtil.error("修改提现数据失败," + aliResult);
}
} finally {
releaseLock(accountLockKey);
if (!keepRequestLock) {
releaseLock(requestLockKey);
}
}
}
private Result validateReturnCommission(ReturnCommission returnCommission) {
if (returnCommission == null) {
return ResultUtil.error("提现参数不能为空!");
}
if (returnCommission.getCommission() == null) {
return ResultUtil.error("提现金额不能为空!");
}
if (returnCommission.getCommission().compareTo(BigDecimal.ZERO) <= 0) {
return ResultUtil.error("提现金额必须大于0!");
}
if (StringUtils.isEmpty(returnCommission.getAliName())) {
return ResultUtil.error("支付宝实名名称不能为空!");
}
if (StringUtils.isEmpty(returnCommission.getAliAccount())) {
return ResultUtil.error("支付宝手机号不能为空!");
}
return null;
}
private String ensureWithdrawId(ReturnCommission returnCommission) {
if (StringUtils.isEmpty(returnCommission.getId())) {
returnCommission.setId(SnowFlakeUtil.nextId().toString());
}
return returnCommission.getId();
}
private String buildRequestLockKey(String withdrawId) {
return "return_commission:request:" + withdrawId;
}
private String buildAccountLockKey(String accountType, String accountId) {
return "return_commission:account:" + accountType + ":" + accountId;
}
private boolean tryLock(String key, long timeout, TimeUnit timeUnit) {
return Boolean.TRUE.equals(stringRedisTemplate.opsForValue().setIfAbsent(key, "1", timeout, timeUnit));
}
private void releaseLock(String key) {
if (!StringUtils.isEmpty(key)) {
stringRedisTemplate.delete(key);
}
}
}

31
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java

@ -41,6 +41,7 @@ import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@ -65,6 +66,7 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
private static final int ORDER_STATUS_RETURN = 7; // 已完成
private static final int PAGE_SIZE = 100;
private static final int PAGE_SIZE_TWENTY = 20;
private static final long COMPLETE_LOCK_SECONDS = 60L;
@Autowired
@Lazy
@ -628,13 +630,23 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
@Override
@Transactional(rollbackFor = Exception.class)
public void workerComplete(String deliveryId, String workerId) {
String completeLockKey = buildCompleteLockKey(deliveryId);
if (!tryCompleteLock(completeLockKey)) {
throw new RuntimeException("送达处理中,请勿重复提交");
}
try {
MallDeliveryOrder delivery = checkWorkerAndStatus(deliveryId, workerId, STATUS_DELIVERING);
LambdaUpdateWrapper<MallDeliveryOrder> uw = new LambdaUpdateWrapper<>();
uw.eq(MallDeliveryOrder::getId, deliveryId)
.eq(MallDeliveryOrder::getWorkerId, workerId)
.eq(MallDeliveryOrder::getStatus, STATUS_DELIVERING)
.set(MallDeliveryOrder::getStatus, STATUS_DONE)
.set(MallDeliveryOrder::getFinishTime, new Date());
this.update(uw);
int updated = this.baseMapper.update(null, uw);
if (updated <= 0) {
throw new RuntimeException("订单已送达,请勿重复操作");
}
Boolean isFantuan = true;
int freeOrderCount = 0;
@ -746,6 +758,23 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
dealingsRecord.setCreateBy(worker.getWorkerId());
dealingsRecordService.save(dealingsRecord);
sendWorkerCompleteAsyncAfterCommit(delivery, worker, completedOrders, freeOrderCount);
} finally {
releaseCompleteLock(completeLockKey);
}
}
private String buildCompleteLockKey(String deliveryId) {
return "mall_delivery:complete:" + deliveryId;
}
private boolean tryCompleteLock(String key) {
return Boolean.TRUE.equals(stringRedisTemplate.opsForValue().setIfAbsent(key, "1", COMPLETE_LOCK_SECONDS, TimeUnit.SECONDS));
}
private void releaseCompleteLock(String key) {
if (StringUtils.isNotBlank(key)) {
stringRedisTemplate.delete(key);
}
}
private void sendWorkerCompleteAsyncAfterCommit(MallDeliveryOrder delivery, Worker worker, List<MallOrder> completedOrders, int freeOrderCount) {

4
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java

@ -1974,7 +1974,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
//商家、配送员都加一条
record.setLinkId(order.getShopId());
if(ratio != null){
record.setRefundAmount(order.getGoodsAmount().add(order.getPackageFee()).multiply(ratio).setScale(2, RoundingMode.HALF_UP));
record.setRefundAmount(order.getGoodsAmount().add(order.getPackageFee()).subtract(order.getGoodsAmount().add(order.getPackageFee()).multiply(ratio)).setScale(2, RoundingMode.HALF_UP));
}else{
record.setRefundAmount(order.getGoodsAmount().add(order.getPackageFee()).setScale(2, RoundingMode.HALF_UP));
}
@ -1994,7 +1994,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
mallRefundRecord1.setId(SnowFlakeUtil.nextId().toString());
mallRefundRecord1.setLinkId(workerId);
if(ratio != null){
mallRefundRecord1.setRefundAmount(order.getDeliveryFee().multiply(ratio).setScale(2, RoundingMode.HALF_UP));
mallRefundRecord1.setRefundAmount(order.getDeliveryFee().subtract(order.getDeliveryFee().multiply(ratio)).setScale(2, RoundingMode.HALF_UP));
}else{
mallRefundRecord1.setRefundAmount(order.getDeliveryFee());
}

Loading…
Cancel
Save