|
|
|
@ -1,5 +1,6 @@ |
|
|
|
package cc.hiver.mall.serviceimpl.mybatis; |
|
|
|
|
|
|
|
import cc.hiver.core.common.utils.SnowFlakeUtil; |
|
|
|
import cc.hiver.mall.dao.mapper.*; |
|
|
|
import cc.hiver.mall.entity.*; |
|
|
|
import cc.hiver.mall.pojo.dto.CreateOrderDTO; |
|
|
|
@ -26,6 +27,8 @@ import org.springframework.transaction.annotation.Transactional; |
|
|
|
import java.math.BigDecimal; |
|
|
|
import java.math.RoundingMode; |
|
|
|
import java.sql.Timestamp; |
|
|
|
import java.time.LocalDateTime; |
|
|
|
import java.time.ZoneId; |
|
|
|
import java.util.*; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
@ -47,6 +50,8 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
private static final int STATUS_CANCELLED = 6; |
|
|
|
private static final int STATUS_WAIT_REFUND = 7; |
|
|
|
private static final int STATUS_REFUNDED = 8; |
|
|
|
private static final int STATUS_WAIT_RETURN = 11;//售后中
|
|
|
|
private static final int STATUS__RETURNED = 12;//已售后
|
|
|
|
|
|
|
|
// 配送方式常量
|
|
|
|
private static final int DELIVERY_TYPE_EXPRESS = 1; // 外卖
|
|
|
|
@ -56,6 +61,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
// 订单类型常量
|
|
|
|
private static final int ORDER_TYPE_NORMAL = 1; // 直接购买
|
|
|
|
private static final int ORDER_TYPE_GROUP = 2; // 拼团购买
|
|
|
|
private static final int ORDER_TYPE_FACETOFACE = 3; // 拼团购买
|
|
|
|
|
|
|
|
// 拼团状态常量
|
|
|
|
private static final int GROUP_STATUS_FORMING = 0; // 拼团中
|
|
|
|
@ -404,9 +410,15 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
updateOrderStatus(orderId, STATUS_WAIT_DELIVERY); |
|
|
|
// 激活配送单,状态改为待接单(0)
|
|
|
|
Date createTime = new Timestamp(System.currentTimeMillis()); |
|
|
|
// 1. 获取当前时间 (LocalDateTime)
|
|
|
|
LocalDateTime now = LocalDateTime.now(); |
|
|
|
// 2. 加40分钟
|
|
|
|
LocalDateTime futureTime = now.plusMinutes(40); |
|
|
|
// 3. 如果需要转回 java.util.Date (为了兼容旧代码)
|
|
|
|
Date mustFinishTime = Date.from(futureTime.atZone(ZoneId.systemDefault()).toInstant()); |
|
|
|
LambdaUpdateWrapper<MallDeliveryOrder> duw = new LambdaUpdateWrapper<>(); |
|
|
|
duw.eq(MallDeliveryOrder::getOrderId, orderId) |
|
|
|
.set(MallDeliveryOrder::getStatus, 0).set(MallDeliveryOrder::getCreateTime, createTime); |
|
|
|
.set(MallDeliveryOrder::getStatus, 0).set(MallDeliveryOrder::getCreateTime, createTime).set(MallDeliveryOrder::getMustFinishTime, mustFinishTime); |
|
|
|
mallDeliveryOrderMapper.update(null, duw); |
|
|
|
} else { |
|
|
|
String latestSeq = merchantOrderSeqUtil.generateOrderSequence(order.getShopId(), 2); |
|
|
|
@ -414,7 +426,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
uw.eq(MallOrder::getId, orderId).set(MallOrder::getStatus, STATUS_WAIT_PICKUP).set(MallOrder::getNumberCode, latestSeq); |
|
|
|
this.update(uw); |
|
|
|
} |
|
|
|
} else if (order.getOrderType() == ORDER_TYPE_GROUP) { |
|
|
|
} else if (order.getOrderType() == ORDER_TYPE_GROUP || order.getOrderType() == ORDER_TYPE_FACETOFACE) { |
|
|
|
// 拼团订单支付成功 -> 改为待成团
|
|
|
|
updateOrderStatus(orderId, STATUS_WAIT_GROUP); |
|
|
|
|
|
|
|
@ -469,12 +481,12 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
.set(MallDeliveryOrder::getStatus, 4); |
|
|
|
mallDeliveryOrderMapper.update(null, duw); |
|
|
|
// 自动生成退款记录
|
|
|
|
createRefundRecord(order, order.getTotalAmount(), "商家拒单: " + reason); |
|
|
|
createRefundRecord(null,order, order.getTotalAmount(), "商家拒单: " + reason,3,1); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void cancelOrder(String orderId, String userId) { |
|
|
|
public void cancelOrder(String orderId, String userId,Integer refundType,Integer refundTypeStatus) { |
|
|
|
MallOrder order = getById(orderId); |
|
|
|
if (order == null) throw new RuntimeException("订单不存在"); |
|
|
|
if (!userId.equals(order.getUserId())) throw new RuntimeException("无权操作该订单"); |
|
|
|
@ -487,10 +499,10 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
|
|
|
|
// 拼团 / 面对面团
|
|
|
|
if (order.getOrderType() == ORDER_TYPE_GROUP || order.getOrderType() == 3) { |
|
|
|
handleGroupCancel(order); |
|
|
|
handleGroupCancel(order,refundType,refundTypeStatus); |
|
|
|
} else { |
|
|
|
// 直接购买
|
|
|
|
handleDirectCancel(order); |
|
|
|
handleDirectCancel(order, refundType,refundTypeStatus); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -501,22 +513,22 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
/** |
|
|
|
* 拼团取消总调度:判断团长/团员后分流 |
|
|
|
*/ |
|
|
|
private void handleGroupCancel(MallOrder order) { |
|
|
|
private void handleGroupCancel(MallOrder order,Integer refundType,Integer refundTypeStatus) { |
|
|
|
MallOrderGroup group = findGroupByOrderId(order.getId()); |
|
|
|
if (group == null) throw new RuntimeException("拼团信息不存在"); |
|
|
|
|
|
|
|
boolean isHead = order.getId().equals(group.getHeadOrderId()); |
|
|
|
if (isHead) { |
|
|
|
handleGroupHeadCancel(order, group); |
|
|
|
handleGroupHeadCancel(order, group,refundType,refundTypeStatus); |
|
|
|
} else { |
|
|
|
handleGroupMemberCancel(order, group); |
|
|
|
handleGroupMemberCancel(order, group,refundType,refundTypeStatus); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 团长取消订单 |
|
|
|
*/ |
|
|
|
private void handleGroupHeadCancel(MallOrder order, MallOrderGroup group) { |
|
|
|
private void handleGroupHeadCancel(MallOrder order, MallOrderGroup group,Integer refundType,Integer refundTypeStatus) { |
|
|
|
boolean isFace2Face = (order.getOrderType() == 3); |
|
|
|
|
|
|
|
// ---- 1. 未支付 ----
|
|
|
|
@ -601,13 +613,13 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
} |
|
|
|
|
|
|
|
// ---- 3. 已成团后 ----
|
|
|
|
handlePostGroupCancel(order, group); |
|
|
|
handlePostGroupCancel(order, group,refundType,refundTypeStatus); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 团员取消订单 |
|
|
|
*/ |
|
|
|
private void handleGroupMemberCancel(MallOrder order, MallOrderGroup group) { |
|
|
|
private void handleGroupMemberCancel(MallOrder order, MallOrderGroup group,Integer refundType,Integer refundTypeStatus) { |
|
|
|
// ---- 1. 未支付 ----
|
|
|
|
if (order.getStatus() == STATUS_WAIT_PAY) { |
|
|
|
updateOrderStatus(order.getId(), STATUS_CANCELLED); |
|
|
|
@ -640,21 +652,21 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
} |
|
|
|
|
|
|
|
// ---- 3. 已成团后 ----
|
|
|
|
handlePostGroupCancel(order, group); |
|
|
|
handlePostGroupCancel(order, group,refundType,refundTypeStatus); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 成团后取消逻辑(团长和团员共用) |
|
|
|
*/ |
|
|
|
private void handlePostGroupCancel(MallOrder order, MallOrderGroup group) { |
|
|
|
private void handlePostGroupCancel(MallOrder order, MallOrderGroup group,Integer refundType,Integer refundTypeStatus) { |
|
|
|
boolean isFace2Face = (order.getOrderType() == 3); |
|
|
|
boolean isHead = order.getId().equals(group.getHeadOrderId()); |
|
|
|
|
|
|
|
// 已完成订单 → 申请售后(待商家同意)
|
|
|
|
if (order.getStatus() == STATUS_DONE) { |
|
|
|
applyMerchantRefund(order, "用户申请售后退款"); |
|
|
|
/*if (order.getStatus() == STATUS_DONE) { |
|
|
|
applyMerchantRefund(order, "用户申请售后退款", refundType,refundTypeStatus); |
|
|
|
return; |
|
|
|
} |
|
|
|
}*/ |
|
|
|
|
|
|
|
// ---- 面对面团 + 配送 特殊处理 ----
|
|
|
|
if (isFace2Face && order.getDeliveryType() != null |
|
|
|
@ -662,7 +674,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
if (!isHead) { |
|
|
|
throw new RuntimeException("面对面配送团只有团长可以取消订单"); |
|
|
|
} |
|
|
|
handleFace2FaceDeliveryCancel(order, group); |
|
|
|
handleFace2FaceDeliveryCancel(order, group, refundType,refundTypeStatus); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
@ -671,7 +683,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
// 配送方式
|
|
|
|
MallDeliveryOrder delivery = findDeliveryByOrderId(order.getId()); |
|
|
|
if (delivery != null && delivery.getStatus() != null && delivery.getStatus() >= 1) { |
|
|
|
applyMerchantRefund(order, "用户申请取消订单退款"); |
|
|
|
applyMerchantRefund(delivery.getWorkerId(),order, "用户申请取消订单退款",refundType,refundTypeStatus); |
|
|
|
} |
|
|
|
// 10分钟冷却期
|
|
|
|
if (group.getSuccessTime() != null) { |
|
|
|
@ -686,14 +698,14 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
restoreStock(order.getId()); |
|
|
|
} else { |
|
|
|
// 自取(待消费)→ 待商家同意退款
|
|
|
|
applyMerchantRefund(order, "用户申请取消订单退款"); |
|
|
|
applyMerchantRefund(null,order, "用户申请取消订单退款",refundType,refundTypeStatus); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 面对面团 + 配送 成团后团长取消(批量操作所有子订单) |
|
|
|
*/ |
|
|
|
private void handleFace2FaceDeliveryCancel(MallOrder order, MallOrderGroup group) { |
|
|
|
private void handleFace2FaceDeliveryCancel(MallOrder order, MallOrderGroup group,Integer refundType,Integer refundTypeStatus) { |
|
|
|
MallDeliveryOrder delivery = findDeliveryByOrderId(order.getId()); |
|
|
|
|
|
|
|
if (delivery != null && delivery.getStatus() != null && delivery.getStatus() == 0) { |
|
|
|
@ -724,7 +736,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
if (subOrder != null && subOrder.getStatus() != STATUS_CANCELLED |
|
|
|
&& subOrder.getStatus() != STATUS_REFUNDED |
|
|
|
&& subOrder.getStatus() != STATUS_WAIT_REFUND) { |
|
|
|
applyMerchantRefund(subOrder, "面对面团团长申请取消,待商家同意"); |
|
|
|
applyMerchantRefund(delivery.getWorkerId(),subOrder, "面对面团团长申请取消,待商家同意",refundType,refundTypeStatus); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -737,7 +749,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
/** |
|
|
|
* 直接购买订单取消 |
|
|
|
*/ |
|
|
|
private void handleDirectCancel(MallOrder order) { |
|
|
|
private void handleDirectCancel(MallOrder order,Integer refundType,Integer refundTypeStatus) { |
|
|
|
// ---- 1. 未支付 ----
|
|
|
|
if (order.getStatus() == STATUS_WAIT_PAY) { |
|
|
|
updateOrderStatus(order.getId(), STATUS_CANCELLED); |
|
|
|
@ -748,18 +760,18 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
} |
|
|
|
|
|
|
|
// ---- 2. 已完成 → 申请售后 ----
|
|
|
|
if (order.getStatus() == STATUS_DONE) { |
|
|
|
applyMerchantRefund(order, "用户申请售后退款"); |
|
|
|
/*if (order.getStatus() == STATUS_DONE) { |
|
|
|
applyMerchantRefund(order, "用户申请售后退款",refundType,refundTypeStatus); |
|
|
|
return; |
|
|
|
} |
|
|
|
}*/ |
|
|
|
|
|
|
|
// ---- 3. 已支付 ----
|
|
|
|
if (order.getDeliveryType() != null && order.getDeliveryType() == DELIVERY_TYPE_EXPRESS) { |
|
|
|
// 外卖配送
|
|
|
|
MallDeliveryOrder delivery = findDeliveryByOrderId(order.getId()); |
|
|
|
if (delivery != null && delivery.getStatus() != null && delivery.getStatus() >= 1) { |
|
|
|
// 配送员已接单 → 走商家同意流程
|
|
|
|
applyMerchantRefund(order, "用户申请取消订单,待商家同意"); |
|
|
|
// 配送员已接单 → 走商家或者配送员同意流程
|
|
|
|
applyMerchantRefund(delivery.getWorkerId(),order, "用户申请取消订单,待同意", refundType, refundTypeStatus); |
|
|
|
} else { |
|
|
|
// 未接单 → 直接取消并退款
|
|
|
|
cancelDeliveryOrderByOrderId(order.getId()); |
|
|
|
@ -775,12 +787,12 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void applyRefund(String orderId, String userId, String reason, BigDecimal amount) { |
|
|
|
public void applyRefund(String orderId, String userId, String reason, BigDecimal amount,Integer refundType,Integer refundTypeStatus) { |
|
|
|
MallOrder order = getById(orderId); |
|
|
|
if (order == null) throw new RuntimeException("订单不存在"); |
|
|
|
if (!userId.equals(order.getUserId())) throw new RuntimeException("无权操作该订单"); |
|
|
|
updateOrderStatus(orderId, STATUS_WAIT_REFUND); |
|
|
|
createRefundRecord(order, amount, reason); |
|
|
|
createRefundRecord(null,order, amount, reason,refundType,refundTypeStatus); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@ -891,7 +903,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
vo.setDeliveryInfo(mallDeliveryOrderMapper.selectOne(dq)); |
|
|
|
|
|
|
|
// 拼团信息(拼团订单才查)
|
|
|
|
if (ORDER_TYPE_GROUP == order.getOrderType()) { |
|
|
|
if (ORDER_TYPE_GROUP == order.getOrderType() || GROUP_STATUS_FACE2FACE == order.getOrderType()) { |
|
|
|
// 通过 headOrderId 或 groupUserIds 中包含此 userId 查找拼团
|
|
|
|
// 参团人:通过 userId + shopId 匹配
|
|
|
|
LambdaQueryWrapper<MallOrderGroup> gq2 = new LambdaQueryWrapper<>(); |
|
|
|
@ -901,6 +913,22 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
MallOrderGroup group = mallOrderGroupMapper.selectOne(gq2); |
|
|
|
vo.setGroupInfo(group); |
|
|
|
} |
|
|
|
// 售后信息
|
|
|
|
if(order.getStatus() == STATUS_WAIT_RETURN || order.getStatus() == STATUS__RETURNED){ |
|
|
|
LambdaQueryWrapper<MallRefundRecord> rq = new LambdaQueryWrapper<>(); |
|
|
|
rq.eq(MallRefundRecord::getOrderId, orderId) |
|
|
|
.last("LIMIT 1"); |
|
|
|
MallRefundRecord sallRefundRecord = mallRefundRecordMapper.selectOne(rq); |
|
|
|
if(sallRefundRecord != null){ |
|
|
|
if(sallRefundRecord.getRefundType() == 1){ |
|
|
|
//售后商品详情
|
|
|
|
sallRefundRecord.setItems(mallReturnOrderGoodsMapper.selectList(new LambdaQueryWrapper<MallReturnOrderGoods>() |
|
|
|
.eq(MallReturnOrderGoods::getOrderId, orderId))); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
vo.setMallRefundRecord(sallRefundRecord); |
|
|
|
} |
|
|
|
return vo; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1122,17 +1150,36 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
/** |
|
|
|
* 创建退款记录 |
|
|
|
*/ |
|
|
|
private void createRefundRecord(MallOrder order, BigDecimal amount, String reason) { |
|
|
|
private void createRefundRecord(String workerId,MallOrder order, BigDecimal amount, String reason,Integer refundType,Integer refundTypeStatus) { |
|
|
|
MallRefundRecord record = new MallRefundRecord(); |
|
|
|
record.setOrderId(order.getId()); |
|
|
|
record.setUserId(order.getUserId()); |
|
|
|
record.setRefundAmount(amount); |
|
|
|
record.setReason(reason); |
|
|
|
record.setStatus(0); // 待商家同意
|
|
|
|
record.setStatus(0); // 待同意
|
|
|
|
record.setCreateTime(new Date()); |
|
|
|
record.setRefundType(3); |
|
|
|
record.setRefundTypeStatus(4); |
|
|
|
mallRefundRecordMapper.insert(record); |
|
|
|
record.setRefundType(refundType); |
|
|
|
record.setRefundTypeStatus(refundTypeStatus); |
|
|
|
// 全额退款
|
|
|
|
if(refundType == 3){ |
|
|
|
if(refundTypeStatus == 1){ |
|
|
|
record.setLinkId(order.getShopId()); |
|
|
|
mallRefundRecordMapper.insert(record); |
|
|
|
}else if(refundTypeStatus == 2){ |
|
|
|
record.setLinkId(workerId); |
|
|
|
mallRefundRecordMapper.insert(record); |
|
|
|
}else if(refundTypeStatus == 3){ |
|
|
|
//商家、配送员都加一条
|
|
|
|
record.setLinkId(order.getShopId()); |
|
|
|
record.setRefundAmount(order.getGoodsAmount().add(order.getPackageFee())); |
|
|
|
mallRefundRecordMapper.insert(record); |
|
|
|
MallRefundRecord mallRefundRecord1 = record; |
|
|
|
mallRefundRecord1.setId(SnowFlakeUtil.nextId().toString()); |
|
|
|
mallRefundRecord1.setLinkId(workerId); |
|
|
|
mallRefundRecord1.setRefundAmount(order.getDeliveryFee()); |
|
|
|
mallRefundRecordMapper.insert(mallRefundRecord1); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
@ -1258,7 +1305,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
/** |
|
|
|
* 申请商家同意退款:订单状态 → 待商家同意退款(7),退款记录状态 → 待商家同意(0) |
|
|
|
*/ |
|
|
|
private void applyMerchantRefund(MallOrder order, String reason) { |
|
|
|
private void applyMerchantRefund(String workerId, MallOrder order, String reason,Integer refundType,Integer refundTypeStatus) { |
|
|
|
updateOrderStatus(order.getId(), STATUS_WAIT_REFUND); |
|
|
|
//如果是外卖,更新配送单状态
|
|
|
|
if(order.getDeliveryType() == DELIVERY_TYPE_EXPRESS){ |
|
|
|
@ -1267,7 +1314,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder |
|
|
|
.set(MallDeliveryOrder::getIsReturn, IS_RETURN_EXPRESS); |
|
|
|
mallDeliveryOrderMapper.update(null, duw); |
|
|
|
} |
|
|
|
createRefundRecord(order, order.getTotalAmount(), reason); |
|
|
|
createRefundRecord(workerId,order, order.getTotalAmount(), reason,refundType,refundTypeStatus); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
|