|
|
|
@ -18,6 +18,7 @@ import cc.hiver.mall.pojo.dto.CreateOrderDTO; |
|
|
|
import cc.hiver.mall.pojo.dto.ShopCacheDTO; |
|
|
|
import cc.hiver.mall.pojo.query.CommentQuery; |
|
|
|
import cc.hiver.mall.pojo.query.MallOrderPageQuery; |
|
|
|
import cc.hiver.mall.pojo.vo.MallOrderFreeVO; |
|
|
|
import cc.hiver.mall.pojo.vo.MallOrderVO; |
|
|
|
import cc.hiver.mall.service.CommentService; |
|
|
|
import cc.hiver.mall.service.ShopService; |
|
|
|
@ -341,13 +342,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
order.setStatus(STATUS_WAIT_PAY); |
|
|
|
order.setRegionId(dto.getRegionId()); |
|
|
|
|
|
|
|
// 1. 【核心】调用判断脚本,看能不能免单(Key 按 regionId 隔离,避免多区域计数混乱)
|
|
|
|
String canFree = stringRedisTemplate.execute( |
|
|
|
redisLuaScripts.getCheckScript(), |
|
|
|
Collections.singletonList("free_order:flag:" + order.getRegionId()), // 检查免单开关
|
|
|
|
"" // 不需要额外参数
|
|
|
|
); |
|
|
|
boolean isFreeOrder = "true".equals(canFree); |
|
|
|
boolean isFreeOrder = canFreeOrder(order); |
|
|
|
order.setIsFreeOrder(isFreeOrder ? 1 : 0); |
|
|
|
if(isFreeOrder){ |
|
|
|
order.setFreeAmount(freeOrderCacheUtil.get(order.getRegionId()).getFreeAmount()); |
|
|
|
@ -356,7 +351,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
order.setTotalAmount(finalAmount.signum() <= 0 ? BigDecimal.valueOf(0.01) : finalAmount); |
|
|
|
//增加奖励记录
|
|
|
|
DealingsRecord dealingsRecord = new DealingsRecord(); |
|
|
|
dealingsRecord.setDealingsWay(DealingsRecordConstant.TYPE_REMARK[6]); |
|
|
|
dealingsRecord.setDealingsWay(DealingsRecordConstant.TYPE_REMARK[5]); |
|
|
|
dealingsRecord.setAmount(freeOrderCacheUtil.get(order.getRegionId()).getFreeAmount()); |
|
|
|
dealingsRecord.setDealingsTime(new Date()); |
|
|
|
dealingsRecord.setLinkId(order.getId()); |
|
|
|
@ -387,6 +382,27 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
return buildVO(order, goodsSnapshots, null, null); |
|
|
|
} |
|
|
|
|
|
|
|
private boolean canFreeOrder(MallOrder order) { |
|
|
|
if (order == null || StringUtils.isBlank(order.getRegionId())) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
MallOrderFreeVO freeOrder = freeOrderCacheUtil.get(order.getRegionId()); |
|
|
|
if (freeOrder == null || freeOrder.getOrderNumber() == null) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
if (freeOrder.getOrderNumber() == 0L) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
// 计数模式:只消费 Redis 中已经产生的本轮锦鲤名额。
|
|
|
|
String canFree = stringRedisTemplate.execute( |
|
|
|
redisLuaScripts.getCheckScript(), |
|
|
|
Collections.singletonList("free_order:flag:" + order.getRegionId()), |
|
|
|
"" |
|
|
|
); |
|
|
|
return "true".equals(canFree); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 发起拼团 |
|
|
|
*/ |
|
|
|
@ -437,13 +453,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
order.setSavedAmount(safeAmount(savedAmount)); |
|
|
|
order.setStatus(STATUS_WAIT_PAY); |
|
|
|
order.setRegionId(dto.getRegionId()); |
|
|
|
// 1. 【核心】调用判断脚本,看能不能免单(Key 按 regionId 隔离,避免多区域计数混乱)
|
|
|
|
String canFree = stringRedisTemplate.execute( |
|
|
|
redisLuaScripts.getCheckScript(), |
|
|
|
Collections.singletonList("free_order:flag:" + order.getRegionId()), // 检查免单开关
|
|
|
|
"" // 不需要额外参数
|
|
|
|
); |
|
|
|
boolean isFreeOrder = "true".equals(canFree); |
|
|
|
boolean isFreeOrder = canFreeOrder(order); |
|
|
|
order.setIsFreeOrder(isFreeOrder ? 1 : 0); |
|
|
|
if(isFreeOrder){ |
|
|
|
order.setFreeAmount(freeOrderCacheUtil.get(order.getRegionId()).getFreeAmount()); |
|
|
|
@ -452,7 +462,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
order.setTotalAmount(finalAmount.signum() <= 0 ? BigDecimal.valueOf(0.01) : finalAmount); |
|
|
|
//增加奖励记录
|
|
|
|
DealingsRecord dealingsRecord = new DealingsRecord(); |
|
|
|
dealingsRecord.setDealingsWay(DealingsRecordConstant.TYPE_REMARK[7]); |
|
|
|
dealingsRecord.setDealingsWay(DealingsRecordConstant.TYPE_REMARK[5]); |
|
|
|
dealingsRecord.setAmount(freeOrderCacheUtil.get(order.getRegionId()).getFreeAmount()); |
|
|
|
dealingsRecord.setDealingsTime(new Date()); |
|
|
|
dealingsRecord.setLinkId(order.getId()); |
|
|
|
@ -569,6 +579,9 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
// 面对面团:不再重新计算,直接使用根据 targetMembers 均摊的金额
|
|
|
|
BigDecimal deliveryFee = BigDecimal.ZERO; |
|
|
|
if (isFace2Face && DELIVERY_TYPE_EXPRESS == dto.getDeliveryType()) { |
|
|
|
if(group.getStatus() == GROUP_STATUS_SUCCESS){ |
|
|
|
throw new RuntimeException("面对面拼团已成团,不可加入"); |
|
|
|
} |
|
|
|
deliveryFee = calcPersonalFee(group.getTotalDeliveryFee(), group.getTargetMembers()); |
|
|
|
} else if (!isFace2Face && DELIVERY_TYPE_EXPRESS == dto.getDeliveryType()) { |
|
|
|
// 普通拼团参团时独立计算个人配送费
|
|
|
|
@ -590,13 +603,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
order.setStatus(STATUS_WAIT_PAY); |
|
|
|
order.setRegionId(dto.getRegionId()); |
|
|
|
|
|
|
|
// 1. 【核心】调用判断脚本,看能不能免单(Key 按 regionId 隔离,避免多区域计数混乱)
|
|
|
|
String canFree = stringRedisTemplate.execute( |
|
|
|
redisLuaScripts.getCheckScript(), |
|
|
|
Collections.singletonList("free_order:flag:" + order.getRegionId()), // 检查免单开关
|
|
|
|
"" // 不需要额外参数
|
|
|
|
); |
|
|
|
boolean isFreeOrder = "true".equals(canFree); |
|
|
|
boolean isFreeOrder = canFreeOrder(order); |
|
|
|
order.setIsFreeOrder(isFreeOrder ? 1 : 0); |
|
|
|
if(isFreeOrder){ |
|
|
|
order.setFreeAmount(freeOrderCacheUtil.get(order.getRegionId()).getFreeAmount()); |
|
|
|
@ -605,7 +612,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
order.setTotalAmount(finalAmount.signum() <= 0 ? BigDecimal.valueOf(0.01) : finalAmount); |
|
|
|
//增加奖励记录
|
|
|
|
DealingsRecord dealingsRecord = new DealingsRecord(); |
|
|
|
dealingsRecord.setDealingsWay(DealingsRecordConstant.TYPE_REMARK[6]); |
|
|
|
dealingsRecord.setDealingsWay(DealingsRecordConstant.TYPE_REMARK[5]); |
|
|
|
dealingsRecord.setAmount(freeOrderCacheUtil.get(order.getRegionId()).getFreeAmount()); |
|
|
|
dealingsRecord.setDealingsTime(new Date()); |
|
|
|
dealingsRecord.setLinkId(order.getId()); |
|
|
|
@ -714,8 +721,8 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
triggerDeliveryAsyncEvents(order, deliveryOrder); |
|
|
|
autoAcceptShopDeliveryOrder(order, deliveryOrder); |
|
|
|
} else { |
|
|
|
String latestSeq = String.format("%s%s", |
|
|
|
LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE), |
|
|
|
String latestSeq = String.format("%s-%s", |
|
|
|
LocalDate.now().format(DateTimeFormatter.ofPattern("MMdd")), |
|
|
|
merchantOrderSeqUtil.generateOrderSequence(order.getShopId(), 2)); |
|
|
|
LambdaUpdateWrapper<MallOrder> uw = new LambdaUpdateWrapper<>(); |
|
|
|
uw.eq(MallOrder::getId, orderId) |
|
|
|
@ -1261,6 +1268,231 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void adminForceRefundOrder(String orderId, Integer refundType, Integer refundTypeStatus, String reason, String pictures) { |
|
|
|
MallOrder order = getById(orderId); |
|
|
|
if (order == null) throw new RuntimeException("订单不存在"); |
|
|
|
|
|
|
|
if (order.getOrderType() == ORDER_TYPE_GROUP || order.getOrderType() == ORDER_TYPE_FACETOFACE) { |
|
|
|
adminHandleGroupCancel(order, refundType, refundTypeStatus, reason, pictures); |
|
|
|
} else { |
|
|
|
adminHandleDirectCancel(order, refundType, refundTypeStatus, reason, pictures); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// ================================================================
|
|
|
|
// 管理后台强制退款逻辑:复制用户端取消流程,不影响原 cancelOrder 链路
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
|
private void adminHandleGroupCancel(MallOrder order,Integer refundType,Integer refundTypeStatus, String reason, String pictures) { |
|
|
|
MallOrderGroup group = findGroupByOrderId(order.getId()); |
|
|
|
if (group == null) throw new RuntimeException("拼团信息不存在"); |
|
|
|
|
|
|
|
boolean isHead = order.getId().equals(group.getHeadOrderId()); |
|
|
|
if (isHead) { |
|
|
|
adminHandleGroupHeadCancel(order, group, refundType, refundTypeStatus, reason, pictures); |
|
|
|
} else { |
|
|
|
adminHandleGroupMemberCancel(order, group, refundType, refundTypeStatus, reason, pictures); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void adminHandleGroupHeadCancel(MallOrder order, MallOrderGroup group,Integer refundType,Integer refundTypeStatus, String reason, String pictures) { |
|
|
|
boolean isFace2Face = (order.getOrderType() == ORDER_TYPE_FACETOFACE); |
|
|
|
|
|
|
|
if (order.getStatus() == STATUS_WAIT_PAY) { |
|
|
|
updateOrderStatus(order.getId(), STATUS_CANCELLED); |
|
|
|
mallUserCouponService.refundCoupon(order.getId()); |
|
|
|
userPendingOrderCacheUtil.remove(order.getUserId(), order.getId()); |
|
|
|
|
|
|
|
LambdaUpdateWrapper<MallOrderGroup> guw = new LambdaUpdateWrapper<>(); |
|
|
|
guw.eq(MallOrderGroup::getId, group.getId()) |
|
|
|
.set(MallOrderGroup::getStatus, GROUP_STATUS_FAIL) |
|
|
|
.set(MallOrderGroup::getGroupOrderIds, ""); |
|
|
|
mallOrderGroupMapper.update(null, guw); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (order.getStatus() == STATUS_WAIT_GROUP) { |
|
|
|
if (group.getCurrentMembers() <= 1) { |
|
|
|
LambdaUpdateWrapper<MallOrderGroup> guw = new LambdaUpdateWrapper<>(); |
|
|
|
guw.eq(MallOrderGroup::getId, group.getId()) |
|
|
|
.set(MallOrderGroup::getStatus, GROUP_STATUS_FAIL) |
|
|
|
.set(MallOrderGroup::getCurrentMembers, 0); |
|
|
|
mallOrderGroupMapper.update(null, guw); |
|
|
|
shopGroupOrderCacheUtil.remove(group.getShopId(), group.getId()); |
|
|
|
if(order.getDeliveryType() != null && order.getDeliveryType() == DELIVERY_TYPE_EXPRESS){ |
|
|
|
adminForceCancelDeliveryOrderByOrderId(order.getId()); |
|
|
|
} |
|
|
|
autoRefund(order, appendCancelReason("后台强制取消拼团退款", reason)); |
|
|
|
restoreStock(order.getId()); |
|
|
|
} else { |
|
|
|
autoRefund(order, appendCancelReason("后台强制取消拼团退款", reason)); |
|
|
|
restoreStock(order.getId()); |
|
|
|
String remainingIds = removeOrderIdStr(group.getGroupOrderIds(), order.getId()); |
|
|
|
if (isFace2Face && order.getDeliveryType() != null |
|
|
|
&& order.getDeliveryType() == DELIVERY_TYPE_EXPRESS) { |
|
|
|
if (StringUtils.isNotBlank(remainingIds)) { |
|
|
|
List<String> memberOrderIds = Arrays.stream(remainingIds.split(",")) |
|
|
|
.map(String::trim).filter(s -> !s.isEmpty()).collect(Collectors.toList()); |
|
|
|
for (String memberOrderId : memberOrderIds) { |
|
|
|
MallOrder memberOrder = getById(memberOrderId); |
|
|
|
if (memberOrder != null && memberOrder.getStatus() != STATUS_CANCELLED |
|
|
|
&& memberOrder.getStatus() != STATUS_REFUNDED) { |
|
|
|
autoRefund(memberOrder, appendCancelReason("后台强制取消面对面团拼团退款", reason)); |
|
|
|
restoreStock(memberOrderId); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
adminForceCancelDeliveryOrderByOrderId(order.getId()); |
|
|
|
|
|
|
|
LambdaUpdateWrapper<MallOrderGroup> guw = new LambdaUpdateWrapper<>(); |
|
|
|
guw.eq(MallOrderGroup::getId, group.getId()) |
|
|
|
.set(MallOrderGroup::getStatus, GROUP_STATUS_FAIL) |
|
|
|
.set(MallOrderGroup::getGroupOrderIds, ""); |
|
|
|
mallOrderGroupMapper.update(null, guw); |
|
|
|
return; |
|
|
|
}else{ |
|
|
|
if(order.getDeliveryType() != null && order.getDeliveryType() == DELIVERY_TYPE_EXPRESS){ |
|
|
|
adminForceCancelDeliveryOrderByOrderId(order.getId()); |
|
|
|
} |
|
|
|
} |
|
|
|
transferGroupHead(group, order.getId(), remainingIds, true); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
adminHandlePostGroupCancel(order, group, refundType, refundTypeStatus, reason, pictures); |
|
|
|
} |
|
|
|
|
|
|
|
private void adminHandleGroupMemberCancel(MallOrder order, MallOrderGroup group,Integer refundType,Integer refundTypeStatus, String reason, String pictures) { |
|
|
|
if (order.getStatus() == STATUS_WAIT_PAY) { |
|
|
|
updateOrderStatus(order.getId(), STATUS_CANCELLED); |
|
|
|
mallUserCouponService.refundCoupon(order.getId()); |
|
|
|
userPendingOrderCacheUtil.remove(order.getUserId(), order.getId()); |
|
|
|
if(order.getDeliveryType() != null && order.getDeliveryType() == DELIVERY_TYPE_EXPRESS){ |
|
|
|
adminForceCancelDeliveryOrderByOrderId(order.getId()); |
|
|
|
} |
|
|
|
String remainingIds = removeOrderIdStr(group.getGroupOrderIds(), order.getId()); |
|
|
|
LambdaUpdateWrapper<MallOrderGroup> guw = new LambdaUpdateWrapper<>(); |
|
|
|
guw.eq(MallOrderGroup::getId, group.getId()) |
|
|
|
.set(MallOrderGroup::getGroupOrderIds, remainingIds); |
|
|
|
mallOrderGroupMapper.update(null, guw); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (order.getStatus() == STATUS_WAIT_GROUP) { |
|
|
|
if(order.getDeliveryType() != null && order.getDeliveryType() == DELIVERY_TYPE_EXPRESS){ |
|
|
|
adminForceCancelDeliveryOrderByOrderId(order.getId()); |
|
|
|
} |
|
|
|
autoRefund(order, appendCancelReason("后台强制取消拼团退款", reason)); |
|
|
|
restoreStock(order.getId()); |
|
|
|
String remainingIds = removeOrderIdStr(group.getGroupOrderIds(), order.getId()); |
|
|
|
LambdaUpdateWrapper<MallOrderGroup> guw = new LambdaUpdateWrapper<>(); |
|
|
|
guw.eq(MallOrderGroup::getId, group.getId()) |
|
|
|
.set(MallOrderGroup::getCurrentMembers, Math.max(group.getCurrentMembers() - 1, 0)) |
|
|
|
.set(MallOrderGroup::getGroupOrderIds, remainingIds); |
|
|
|
mallOrderGroupMapper.update(null, guw); |
|
|
|
group.setCurrentMembers(Math.max(group.getCurrentMembers() - 1, 0)); |
|
|
|
shopGroupOrderCacheUtil.update(group.getShopId(), group); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
adminHandlePostGroupCancel(order, group, refundType, refundTypeStatus, reason, pictures); |
|
|
|
} |
|
|
|
|
|
|
|
private void adminHandlePostGroupCancel(MallOrder order, MallOrderGroup group,Integer refundType,Integer refundTypeStatus, String reason, String pictures) { |
|
|
|
boolean isFace2Face = (order.getOrderType() == ORDER_TYPE_FACETOFACE); |
|
|
|
boolean isHead = order.getId().equals(group.getHeadOrderId()); |
|
|
|
|
|
|
|
if (isFace2Face && order.getDeliveryType() != null |
|
|
|
&& order.getDeliveryType() == DELIVERY_TYPE_EXPRESS) { |
|
|
|
if (!isHead) { |
|
|
|
throw new RuntimeException("面对面配送团只有团长可以取消订单"); |
|
|
|
} |
|
|
|
adminHandleFace2FaceDeliveryCancel(order, group, refundType, refundTypeStatus, reason, pictures); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (order.getDeliveryType() != null && order.getDeliveryType() == DELIVERY_TYPE_EXPRESS) { |
|
|
|
MallDeliveryOrder delivery = findDeliveryByOrderId(order.getId()); |
|
|
|
adminForceCancelDeliveryOrderByOrderId(order.getId()); |
|
|
|
adminRemoveDeliveryOrderCache(delivery); |
|
|
|
autoRefund(order, appendCancelReason("后台强制取消订单退款", reason)); |
|
|
|
restoreStock(order.getId()); |
|
|
|
} else { |
|
|
|
autoRefund(order, appendCancelReason("后台强制取消订单退款", reason)); |
|
|
|
restoreStock(order.getId()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void adminHandleFace2FaceDeliveryCancel(MallOrder order, MallOrderGroup group,Integer refundType,Integer refundTypeStatus, String reason, String pictures) { |
|
|
|
MallDeliveryOrder delivery = findDeliveryByOrderId(order.getId()); |
|
|
|
|
|
|
|
List<String> allOrderIds = Arrays.stream(group.getGroupOrderIds().split(",")) |
|
|
|
.map(String::trim).filter(s -> !s.isEmpty()).collect(Collectors.toList()); |
|
|
|
for (String oid : allOrderIds) { |
|
|
|
MallOrder subOrder = getById(oid); |
|
|
|
if (subOrder != null && subOrder.getStatus() != STATUS_CANCELLED |
|
|
|
&& subOrder.getStatus() != STATUS_REFUNDED) { |
|
|
|
subOrder.setGroupOrderIds(group.getGroupOrderIds()); |
|
|
|
autoRefund(subOrder, appendCancelReason("后台强制取消面对面团订单退款", reason)); |
|
|
|
restoreStock(oid); |
|
|
|
} |
|
|
|
} |
|
|
|
adminForceCancelDeliveryOrderByOrderId(order.getId()); |
|
|
|
adminRemoveDeliveryOrderCache(delivery); |
|
|
|
|
|
|
|
LambdaUpdateWrapper<MallOrderGroup> guw = new LambdaUpdateWrapper<>(); |
|
|
|
guw.eq(MallOrderGroup::getId, group.getId()) |
|
|
|
.set(MallOrderGroup::getStatus, GROUP_STATUS_FAIL); |
|
|
|
mallOrderGroupMapper.update(null, guw); |
|
|
|
} |
|
|
|
|
|
|
|
private void adminHandleDirectCancel(MallOrder order,Integer refundType,Integer refundTypeStatus, String reason, String pictures) { |
|
|
|
if (order.getStatus() == STATUS_WAIT_PAY) { |
|
|
|
updateOrderStatus(order.getId(), STATUS_CANCELLED); |
|
|
|
mallUserCouponService.refundCoupon(order.getId()); |
|
|
|
userPendingOrderCacheUtil.remove(order.getUserId(), order.getId()); |
|
|
|
if(order.getDeliveryType() != null && order.getDeliveryType() == DELIVERY_TYPE_EXPRESS){ |
|
|
|
adminForceCancelDeliveryOrderByOrderId(order.getId()); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (order.getDeliveryType() != null && order.getDeliveryType() == DELIVERY_TYPE_EXPRESS) { |
|
|
|
MallDeliveryOrder delivery = findDeliveryByOrderId(order.getId()); |
|
|
|
adminForceCancelDeliveryOrderByOrderId(order.getId()); |
|
|
|
adminRemoveDeliveryOrderCache(delivery); |
|
|
|
autoRefund(order, appendCancelReason("后台强制取消订单退款", reason)); |
|
|
|
restoreStock(order.getId()); |
|
|
|
} else { |
|
|
|
autoRefund(order, appendCancelReason("后台强制取消订单退款", reason)); |
|
|
|
restoreStock(order.getId()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void adminForceCancelDeliveryOrderByOrderId(String orderId) { |
|
|
|
MallDeliveryOrder delivery = findDeliveryByOrderId(orderId); |
|
|
|
LambdaUpdateWrapper<MallDeliveryOrder> duw = new LambdaUpdateWrapper<>(); |
|
|
|
duw.eq(MallDeliveryOrder::getOrderId, orderId) |
|
|
|
.set(MallDeliveryOrder::getStatus, 4); |
|
|
|
mallDeliveryOrderMapper.update(null, duw); |
|
|
|
adminRemoveDeliveryOrderCache(delivery); |
|
|
|
} |
|
|
|
|
|
|
|
private void adminRemoveDeliveryOrderCache(MallDeliveryOrder delivery) { |
|
|
|
if (delivery == null) { |
|
|
|
return; |
|
|
|
} |
|
|
|
if (StringUtils.isNotBlank(delivery.getRegionId())) { |
|
|
|
waitOrderCacheUtil.remove(delivery.getRegionId(), delivery.getId()); |
|
|
|
} |
|
|
|
if (StringUtils.isNotBlank(delivery.getWorkerId())) { |
|
|
|
workerOrderCacheUtil.remove(delivery.getWorkerId(), delivery.getId()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void applyRefund(String orderId, String userId, String reason, BigDecimal amount,Integer refundType,Integer refundTypeStatus) { |
|
|
|
@ -1292,6 +1524,24 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
this.update(uw); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void shopMakeTimeBatch(List<String> orderIdList) { |
|
|
|
if (orderIdList == null || orderIdList.isEmpty()) { |
|
|
|
throw new RuntimeException("订单列表不能为空"); |
|
|
|
} |
|
|
|
List<String> ids = orderIdList.stream() |
|
|
|
.filter(StringUtils::isNotBlank) |
|
|
|
.distinct() |
|
|
|
.collect(Collectors.toList()); |
|
|
|
if (ids.isEmpty()) { |
|
|
|
throw new RuntimeException("订单列表不能为空"); |
|
|
|
} |
|
|
|
LambdaUpdateWrapper<MallOrder> uw = new LambdaUpdateWrapper<>(); |
|
|
|
uw.in(MallOrder::getId, ids).set(MallOrder::getShopMakeTime, new Date()); |
|
|
|
this.update(uw); |
|
|
|
} |
|
|
|
|
|
|
|
//自取订单用户点击立即出餐
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
@ -1349,11 +1599,12 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
//更新缓存
|
|
|
|
userPendingOrderCacheUtil.remove(order.getUserId(),order.getId()); |
|
|
|
//免单计数(Key 按 regionId 隔离,避免多区域计数混乱)
|
|
|
|
if(freeOrderCacheUtil.exists(order.getRegionId())){ |
|
|
|
MallOrderFreeVO freeOrder = freeOrderCacheUtil.get(order.getRegionId()); |
|
|
|
if(freeOrder != null && freeOrder.getOrderNumber() != null && freeOrder.getOrderNumber() > 0){ |
|
|
|
stringRedisTemplate.execute( |
|
|
|
redisLuaScripts.getIncrementScript(), |
|
|
|
Arrays.asList("free_order:count:" + order.getRegionId(), "free_order:flag:" + order.getRegionId()), // 两个 key:计数器和免单开关
|
|
|
|
String.valueOf(freeOrderCacheUtil.get(order.getRegionId()).getOrderNumber()) |
|
|
|
String.valueOf(freeOrder.getOrderNumber()) |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1555,10 +1806,21 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
List<String> orderIds = records.stream() |
|
|
|
.map(MallOrderVO::getId) |
|
|
|
.collect(java.util.stream.Collectors.toList()); |
|
|
|
List<String> faceDeliveryOrderIds = records.stream() |
|
|
|
.filter(order -> Objects.equals(order.getOrderType(), ORDER_TYPE_FACETOFACE) |
|
|
|
&& Objects.equals(order.getDeliveryType(), DELIVERY_TYPE_EXPRESS)) |
|
|
|
.map(MallOrderVO::getId) |
|
|
|
.collect(java.util.stream.Collectors.toList()); |
|
|
|
java.util.Set<String> faceDeliveryOrderIdSet = new java.util.HashSet<>(faceDeliveryOrderIds); |
|
|
|
List<String> normalDeliveryOrderIds = orderIds.stream() |
|
|
|
.filter(orderId -> !faceDeliveryOrderIdSet.contains(orderId)) |
|
|
|
.collect(java.util.stream.Collectors.toList()); |
|
|
|
|
|
|
|
// 2. 一次 IN 查询所有商品明细
|
|
|
|
List<MallOrderGoods> allGoods = mallOrderGoodsMapper.selectPagesByOrderIds(orderIds); |
|
|
|
List<MallDeliveryOrder> allDeliveryOrders = mallDeliveryOrderMapper.selectByOrderIds(orderIds); |
|
|
|
List<MallDeliveryOrder> allDeliveryOrders = normalDeliveryOrderIds.isEmpty() |
|
|
|
? java.util.Collections.emptyList() |
|
|
|
: mallDeliveryOrderMapper.selectByOrderIds(normalDeliveryOrderIds); |
|
|
|
if (allGoods == null) { |
|
|
|
allGoods = java.util.Collections.emptyList(); |
|
|
|
} |
|
|
|
@ -1576,6 +1838,60 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
delivery -> delivery, |
|
|
|
(first, second) -> first |
|
|
|
)); |
|
|
|
if (!faceDeliveryOrderIds.isEmpty()) { |
|
|
|
LambdaQueryWrapper<MallOrderGroup> groupQuery = new LambdaQueryWrapper<>(); |
|
|
|
groupQuery.and(wrapper -> { |
|
|
|
boolean first = true; |
|
|
|
for (String orderId : faceDeliveryOrderIds) { |
|
|
|
if (!first) { |
|
|
|
wrapper.or(); |
|
|
|
} |
|
|
|
wrapper.eq(MallOrderGroup::getHeadOrderId, orderId) |
|
|
|
.or() |
|
|
|
.apply("FIND_IN_SET({0}, group_order_ids)", orderId); |
|
|
|
first = false; |
|
|
|
} |
|
|
|
}); |
|
|
|
List<MallOrderGroup> faceGroups = mallOrderGroupMapper.selectList(groupQuery); |
|
|
|
if (faceGroups != null && !faceGroups.isEmpty()) { |
|
|
|
List<String> groupIds = faceGroups.stream() |
|
|
|
.map(MallOrderGroup::getId) |
|
|
|
.filter(StringUtils::isNotBlank) |
|
|
|
.distinct() |
|
|
|
.collect(java.util.stream.Collectors.toList()); |
|
|
|
if (!groupIds.isEmpty()) { |
|
|
|
LambdaQueryWrapper<MallDeliveryOrder> deliveryQuery = new LambdaQueryWrapper<>(); |
|
|
|
deliveryQuery.in(MallDeliveryOrder::getGroupId, groupIds); |
|
|
|
List<MallDeliveryOrder> faceDeliveryOrders = mallDeliveryOrderMapper.selectList(deliveryQuery); |
|
|
|
java.util.Map<String, MallDeliveryOrder> groupDeliveryMap = faceDeliveryOrders == null |
|
|
|
? java.util.Collections.emptyMap() |
|
|
|
: faceDeliveryOrders.stream() |
|
|
|
.filter(delivery -> StringUtils.isNotBlank(delivery.getGroupId())) |
|
|
|
.collect(java.util.stream.Collectors.toMap( |
|
|
|
MallDeliveryOrder::getGroupId, |
|
|
|
delivery -> delivery, |
|
|
|
(first, second) -> first |
|
|
|
)); |
|
|
|
for (MallOrderGroup group : faceGroups) { |
|
|
|
MallDeliveryOrder delivery = groupDeliveryMap.get(group.getId()); |
|
|
|
if (delivery == null) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (faceDeliveryOrderIdSet.contains(group.getHeadOrderId())) { |
|
|
|
deliveryMap.put(group.getHeadOrderId(), delivery); |
|
|
|
} |
|
|
|
if (StringUtils.isNotBlank(group.getGroupOrderIds())) { |
|
|
|
for (String groupOrderId : group.getGroupOrderIds().split(",")) { |
|
|
|
String orderId = groupOrderId.trim(); |
|
|
|
if (faceDeliveryOrderIdSet.contains(orderId)) { |
|
|
|
deliveryMap.put(orderId, delivery); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 4. 组装到每个 VO
|
|
|
|
for (MallOrderVO vo : records) { |
|
|
|
|