Compare commits
3 Commits
7771b30366
...
03e9ceee5b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03e9ceee5b | ||
|
|
8ece45da28 | ||
|
|
5b18f72ae8 |
@@ -17,6 +17,7 @@ import com.starry.admin.modules.clerk.module.vo.PlayClerkUserReviewStateEditVo;
|
|||||||
import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService;
|
import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService;
|
||||||
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
|
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
|
||||||
import com.starry.admin.modules.clerk.service.IPlayClerkUserReviewInfoService;
|
import com.starry.admin.modules.clerk.service.IPlayClerkUserReviewInfoService;
|
||||||
|
import com.starry.admin.modules.order.module.constant.OrderConstant;
|
||||||
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
||||||
import com.starry.common.utils.IdUtils;
|
import com.starry.common.utils.IdUtils;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -172,8 +173,8 @@ public class PlayClerkUserReviewInfoServiceImpl
|
|||||||
userInfo.setClerkState("1");
|
userInfo.setClerkState("1");
|
||||||
userInfo.setId(entity.getClerkId());
|
userInfo.setId(entity.getClerkId());
|
||||||
userInfo.setAlbum(entity.getAlbum());
|
userInfo.setAlbum(entity.getAlbum());
|
||||||
if(entity.getSex().equals("0")){
|
if(OrderConstant.Gender.UNKNOWN.getCode().equals(entity.getSex())){
|
||||||
userInfo.setSex("2");
|
userInfo.setSex(OrderConstant.Gender.FEMALE.getCode());
|
||||||
}
|
}
|
||||||
playClerkUserInfoService.update(userInfo);
|
playClerkUserInfoService.update(userInfo);
|
||||||
clerkCommodityService.initClerkCommodity(userInfo.getId());
|
clerkCommodityService.initClerkCommodity(userInfo.getId());
|
||||||
|
|||||||
@@ -124,6 +124,18 @@ public class PlayOrderInfoController {
|
|||||||
return R.ok("退款成功");
|
return R.ok("退款成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理后台强制取消进行中订单
|
||||||
|
*/
|
||||||
|
@ApiOperation(value = "强制取消订单", notes = "管理员强制取消已接单或服务中的订单")
|
||||||
|
@ApiResponses({@ApiResponse(code = 200, message = "操作成功"), @ApiResponse(code = 500, message = "操作失败")})
|
||||||
|
@PostMapping("/forceCancel")
|
||||||
|
public R forceCancel(@ApiParam(value = "取消参数", required = true) @Validated @RequestBody PlayOrderForceCancelVo vo) {
|
||||||
|
orderInfoService.forceCancelOngoingOrder("2", CustomSecurityContextHolder.getUserId(), vo.getOrderId(),
|
||||||
|
vo.getRefundAmount(), vo.getRefundReason(), vo.getImages());
|
||||||
|
return R.ok("操作成功");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更换店员
|
* 更换店员
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -180,6 +180,37 @@ public class OrderConstant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作人类型枚举
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public enum OperatorType {
|
||||||
|
CUSTOMER("0", "顾客"),
|
||||||
|
CLERK("1", "店员"),
|
||||||
|
ADMIN("2", "管理员");
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
OperatorType(String code, String description) {
|
||||||
|
this.code = code;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OperatorType fromCode(String code) {
|
||||||
|
for (OperatorType type : values()) {
|
||||||
|
if (type.code.equals(code)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unknown operator type code: " + code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排除历史记录常量
|
||||||
|
public static final String EXCLUDE_HISTORY_NO = "0";
|
||||||
|
public static final String EXCLUDE_HISTORY_YES = "1";
|
||||||
|
|
||||||
// Legacy constants for backward compatibility - consider deprecating
|
// Legacy constants for backward compatibility - consider deprecating
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public final static String ORDER_STATUS_0 = "0";
|
public final static String ORDER_STATUS_0 = "0";
|
||||||
|
|||||||
@@ -126,6 +126,11 @@ public class PlayOrderDetailsReturnVo {
|
|||||||
*/
|
*/
|
||||||
private String placeType;
|
private String placeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 要求店员性别(0:未知;1:男;2:女)- 仅随机单有效
|
||||||
|
*/
|
||||||
|
private String sex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信号码
|
* 微信号码
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.starry.admin.modules.order.module.vo;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.validation.constraints.DecimalMin;
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强制取消订单请求对象
|
||||||
|
*
|
||||||
|
* <p>用于管理员或店员在订单已接单/服务中时发起取消操作。</p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class PlayOrderForceCancelVo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单ID
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "订单ID不能为空")
|
||||||
|
private String orderId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退款原因
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "请填写退款原因")
|
||||||
|
@Size(max = 200, message = "退款原因不能超过200个字符")
|
||||||
|
private String refundReason;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退款金额,可选。不填默认退回订单支付金额
|
||||||
|
*/
|
||||||
|
@DecimalMin(value = "0.00", message = "退款金额不能小于0")
|
||||||
|
private BigDecimal refundAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退款凭证图片
|
||||||
|
*/
|
||||||
|
private List<String> images = new ArrayList<>();
|
||||||
|
}
|
||||||
@@ -271,6 +271,19 @@ public interface IPlayOrderInfoService extends IService<PlayOrderInfoEntity> {
|
|||||||
void updateStateTo4(String operatorByType, String operatorBy, String orderId, String refundReason,
|
void updateStateTo4(String operatorByType, String operatorBy, String orderId, String refundReason,
|
||||||
List<String> images);
|
List<String> images);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已接单/服务中的订单强制取消
|
||||||
|
*
|
||||||
|
* @param operatorByType 操作人类型(1:店员;2:管理员)
|
||||||
|
* @param operatorBy 操作人ID
|
||||||
|
* @param orderId 订单ID
|
||||||
|
* @param refundAmount 退款金额(为空则退回实际支付金额)
|
||||||
|
* @param refundReason 取消原因
|
||||||
|
* @param images 退款凭证图片
|
||||||
|
*/
|
||||||
|
void forceCancelOngoingOrder(String operatorByType, String operatorBy, String orderId, BigDecimal refundAmount,
|
||||||
|
String refundReason, List<String> images);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改订单
|
* 修改订单
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -672,7 +672,16 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
|
|||||||
PlayClerkUserInfoEntity::getId, PlayOrderInfoEntity::getAcceptBy);
|
PlayClerkUserInfoEntity::getId, PlayOrderInfoEntity::getAcceptBy);
|
||||||
lambdaQueryWrapper.eq(PlayOrderInfoEntity::getId, orderId);
|
lambdaQueryWrapper.eq(PlayOrderInfoEntity::getId, orderId);
|
||||||
lambdaQueryWrapper.orderByDesc(PlayOrderInfoEntity::getPurchaserTime);
|
lambdaQueryWrapper.orderByDesc(PlayOrderInfoEntity::getPurchaserTime);
|
||||||
return this.baseMapper.selectJoinOne(PlayOrderDetailsReturnVo.class, lambdaQueryWrapper);
|
PlayOrderDetailsReturnVo vo = this.baseMapper.selectJoinOne(PlayOrderDetailsReturnVo.class, lambdaQueryWrapper);
|
||||||
|
|
||||||
|
// Privacy protection: Hide customer info for pending random orders
|
||||||
|
if (vo != null && OrderConstant.PlaceType.RANDOM.getCode().equals(vo.getPlaceType()) && OrderConstant.OrderStatus.PENDING.getCode().equals(vo.getOrderStatus())) {
|
||||||
|
vo.setCustomNickname("匿名用户");
|
||||||
|
vo.setCustomAvatar("");
|
||||||
|
vo.setCustomId("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return vo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -833,13 +842,15 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
|
|||||||
**/
|
**/
|
||||||
@Override
|
@Override
|
||||||
public void updateStateTo1(String operatorByType, String operatorBy, String acceptBy, String orderId) {
|
public void updateStateTo1(String operatorByType, String operatorBy, String acceptBy, String orderId) {
|
||||||
if (!"1".equals(operatorByType) && !"2".equals(operatorByType)) {
|
if (!OrderConstant.OperatorType.CLERK.getCode().equals(operatorByType)
|
||||||
|
&& !OrderConstant.OperatorType.ADMIN.getCode().equals(operatorByType)) {
|
||||||
throw new CustomException("禁止操作");
|
throw new CustomException("禁止操作");
|
||||||
}
|
}
|
||||||
PlayOrderInfoEntity orderInfo = this.selectOrderInfoById(orderId);
|
PlayOrderInfoEntity orderInfo = this.selectOrderInfoById(orderId);
|
||||||
PlayClerkUserInfoEntity clerkUserInfoEntity = playClerkUserInfoService.selectById(acceptBy);
|
PlayClerkUserInfoEntity clerkUserInfoEntity = playClerkUserInfoService.selectById(acceptBy);
|
||||||
// 店员接单时,判断店员是否符合资格
|
// 店员接单时,判断店员是否符合资格
|
||||||
if ("1".equals(operatorByType) && "1".equals(orderInfo.getPlaceType())) {
|
if (OrderConstant.OperatorType.CLERK.getCode().equals(operatorByType)
|
||||||
|
&& OrderConstant.PlaceType.RANDOM.getCode().equals(orderInfo.getPlaceType())) {
|
||||||
// 判断店员等级是否符合规则
|
// 判断店员等级是否符合规则
|
||||||
if (orderInfo.getLevelId().equals(clerkUserInfoEntity.getLevelId())) {
|
if (orderInfo.getLevelId().equals(clerkUserInfoEntity.getLevelId())) {
|
||||||
PlayClerkLevelInfoEntity levelInfo = playClerkLevelInfoService
|
PlayClerkLevelInfoEntity levelInfo = playClerkLevelInfoService
|
||||||
@@ -848,13 +859,14 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
|
|||||||
}
|
}
|
||||||
// 判断店员性别是否符合规则
|
// 判断店员性别是否符合规则
|
||||||
if (!orderInfo.getSex().equals(clerkUserInfoEntity.getSex())) {
|
if (!orderInfo.getSex().equals(clerkUserInfoEntity.getSex())) {
|
||||||
String sex = "0".equals(orderInfo.getSex()) ? "未知" : "1".equals(orderInfo.getSex()) ? "男" : "女";
|
OrderConstant.Gender requiredGender = OrderConstant.Gender.fromCode(orderInfo.getSex());
|
||||||
throw new CustomException("性别为" + sex + "的店员才可接单");
|
throw new CustomException("性别为" + requiredGender.getDescription() + "的店员才可接单");
|
||||||
}
|
}
|
||||||
// 如果排除已下单的店员
|
// 如果排除已下单的店员
|
||||||
LambdaQueryWrapper<PlayOrderInfoEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<PlayOrderInfoEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||||
lambdaQueryWrapper.eq(PlayOrderInfoEntity::getAcceptBy, acceptBy);
|
lambdaQueryWrapper.eq(PlayOrderInfoEntity::getAcceptBy, acceptBy);
|
||||||
if ("1".equals(orderInfo.getExcludeHistory()) && this.baseMapper.selectOne(lambdaQueryWrapper) != null) {
|
if (OrderConstant.EXCLUDE_HISTORY_YES.equals(orderInfo.getExcludeHistory())
|
||||||
|
&& this.baseMapper.selectOne(lambdaQueryWrapper) != null) {
|
||||||
// throw new CustomException("只有未接单的店员才可接单");
|
// throw new CustomException("只有未接单的店员才可接单");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -867,7 +879,9 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
|
|||||||
entity.setEstimatedRevenueRatio(estimatedRevenueVo.getRevenueRatio());
|
entity.setEstimatedRevenueRatio(estimatedRevenueVo.getRevenueRatio());
|
||||||
this.baseMapper.updateById(entity);
|
this.baseMapper.updateById(entity);
|
||||||
|
|
||||||
wxCustomMpService.sendOrderMessage(orderInfo);
|
// Set acceptBy on orderInfo for notification
|
||||||
|
orderInfo.setAcceptBy(acceptBy);
|
||||||
|
wxCustomMpService.sendOrderMessageAsync(orderInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -967,7 +981,7 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
|
|||||||
entity2.setOrderEndTime(LocalDateTime.now());
|
entity2.setOrderEndTime(LocalDateTime.now());
|
||||||
this.baseMapper.updateById(entity2);
|
this.baseMapper.updateById(entity2);
|
||||||
PlayOrderInfoEntity latest = this.selectOrderInfoById(orderId);
|
PlayOrderInfoEntity latest = this.selectOrderInfoById(orderId);
|
||||||
wxCustomMpService.sendOrderFinishMessage(latest);
|
wxCustomMpService.sendOrderFinishMessageAsync(latest);
|
||||||
earningsService.createFromOrder(latest);
|
earningsService.createFromOrder(latest);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1012,7 +1026,57 @@ public class PlayOrderInfoServiceImpl extends ServiceImpl<PlayOrderInfoMapper, P
|
|||||||
playOrderRefundInfoService.add(orderId, orderInfo.getPurchaserBy(), orderInfo.getAcceptBy(),
|
playOrderRefundInfoService.add(orderId, orderInfo.getPurchaserBy(), orderInfo.getAcceptBy(),
|
||||||
orderInfo.getPayMethod(), "0", orderInfo.getFinalAmount(), refundReason, operatorByType, operatorBy,
|
orderInfo.getPayMethod(), "0", orderInfo.getFinalAmount(), refundReason, operatorByType, operatorBy,
|
||||||
"0", "0");
|
"0", "0");
|
||||||
wxCustomMpService.sendOrderCancelMessage(orderInfo, refundReason);
|
wxCustomMpService.sendOrderCancelMessageAsync(orderInfo, refundReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已接单/服务中的订单强制取消,仅允许店员本人或管理员操作
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void forceCancelOngoingOrder(String operatorByType, String operatorBy, String orderId, BigDecimal refundAmount,
|
||||||
|
String refundReason, List<String> images) {
|
||||||
|
if (!"2".equals(operatorByType)) {
|
||||||
|
throw new CustomException("禁止操作");
|
||||||
|
}
|
||||||
|
PlayOrderInfoEntity orderInfo = this.selectOrderInfoById(orderId);
|
||||||
|
if (!OrderConstant.ORDER_STATUS_1.equals(orderInfo.getOrderStatus())
|
||||||
|
&& !OrderConstant.ORDER_STATUS_2.equals(orderInfo.getOrderStatus())) {
|
||||||
|
throw new CustomException("订单状态异常,无法取消");
|
||||||
|
}
|
||||||
|
BigDecimal actualRefundAmount = refundAmount != null ? refundAmount : orderInfo.getFinalAmount();
|
||||||
|
if (actualRefundAmount.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
|
throw new CustomException("退款金额不能小于0");
|
||||||
|
}
|
||||||
|
if (actualRefundAmount.compareTo(orderInfo.getFinalAmount()) > 0) {
|
||||||
|
throw new CustomException("退款金额不能大于支付金额");
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
PlayOrderInfoEntity updateEntity = new PlayOrderInfoEntity(orderId, OrderConstant.ORDER_STATUS_4);
|
||||||
|
updateEntity.setRefundAmount(actualRefundAmount);
|
||||||
|
updateEntity.setRefundReason(refundReason);
|
||||||
|
updateEntity.setRefundType("1");
|
||||||
|
updateEntity.setOrderCancelTime(now);
|
||||||
|
if (OrderConstant.ORDER_STATUS_2.equals(orderInfo.getOrderStatus())) {
|
||||||
|
updateEntity.setOrderEndTime(now);
|
||||||
|
}
|
||||||
|
this.baseMapper.updateById(updateEntity);
|
||||||
|
|
||||||
|
PlayCustomUserInfoEntity customUserInfo = customUserInfoService.getById(orderInfo.getPurchaserBy());
|
||||||
|
if (customUserInfo == null) {
|
||||||
|
throw new CustomException("顾客信息不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(),
|
||||||
|
customUserInfo.getAccountBalance().add(actualRefundAmount), "3", "订单取消退款",
|
||||||
|
actualRefundAmount, BigDecimal.ZERO, orderId);
|
||||||
|
|
||||||
|
playOrderRefundInfoService.add(orderId, orderInfo.getPurchaserBy(), orderInfo.getAcceptBy(),
|
||||||
|
orderInfo.getPayMethod(), "0", actualRefundAmount, refundReason, operatorByType, operatorBy, "0", "0");
|
||||||
|
|
||||||
|
PlayOrderInfoEntity latest = this.selectOrderInfoById(orderId);
|
||||||
|
wxCustomMpService.sendOrderCancelMessageAsync(latest, refundReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -479,7 +479,8 @@ public class WxCustomController {
|
|||||||
// 顾客减少余额
|
// 顾客减少余额
|
||||||
customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), customUserInfo.getAccountBalance().subtract(money), "1", "下单-随机单", money, BigDecimal.ZERO, orderId);
|
customUserInfoService.updateAccountBalanceById(customUserInfo.getId(), customUserInfo.getAccountBalance(), customUserInfo.getAccountBalance().subtract(money), "1", "下单-随机单", money, BigDecimal.ZERO, orderId);
|
||||||
// 给全部店员发送通知
|
// 给全部店员发送通知
|
||||||
List<PlayClerkUserInfoEntity> clerkList = clerkUserInfoService.list(Wrappers.lambdaQuery(PlayClerkUserInfoEntity.class).isNotNull(PlayClerkUserInfoEntity::getOpenid).eq(PlayClerkUserInfoEntity::getClerkState, "1").eq(PlayClerkUserInfoEntity::getSex, vo.getSex()));
|
List<PlayClerkUserInfoEntity> clerkList = clerkUserInfoService.list(Wrappers.lambdaQuery(PlayClerkUserInfoEntity.class).isNotNull(PlayClerkUserInfoEntity::getOpenid).eq(PlayClerkUserInfoEntity::getClerkState, "1")
|
||||||
|
.eq(PlayClerkUserInfoEntity::getOnlineState, "1").eq(PlayClerkUserInfoEntity::getSex, vo.getSex()));
|
||||||
wxCustomMpService.sendCreateOrderMessageBatch(clerkList, orderNo, money.toString(), commodityInfo.getCommodityName(),orderId);
|
wxCustomMpService.sendCreateOrderMessageBatch(clerkList, orderNo, money.toString(), commodityInfo.getCommodityName(),orderId);
|
||||||
// 记录订单,指定指定未接单后,进行退款处理
|
// 记录订单,指定指定未接单后,进行退款处理
|
||||||
overdueOrderHandlerTask.enqueue(orderId + "_" + SecurityUtils.getTenantId());
|
overdueOrderHandlerTask.enqueue(orderId + "_" + SecurityUtils.getTenantId());
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.starry.admin.common.aspect.ClerkUserLogin;
|
|||||||
import com.starry.admin.common.aspect.CustomUserLogin;
|
import com.starry.admin.common.aspect.CustomUserLogin;
|
||||||
import com.starry.admin.common.conf.ThreadLocalRequestDetail;
|
import com.starry.admin.common.conf.ThreadLocalRequestDetail;
|
||||||
import com.starry.admin.common.exception.CustomException;
|
import com.starry.admin.common.exception.CustomException;
|
||||||
|
import com.starry.admin.modules.order.module.constant.OrderConstant;
|
||||||
import com.starry.admin.modules.order.module.entity.PlayOrderContinueInfoEntity;
|
import com.starry.admin.modules.order.module.entity.PlayOrderContinueInfoEntity;
|
||||||
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
||||||
import com.starry.admin.modules.order.module.vo.PlayOrderContinueQueryVo;
|
import com.starry.admin.modules.order.module.vo.PlayOrderContinueQueryVo;
|
||||||
@@ -121,9 +122,19 @@ public class WxOrderInfoController {
|
|||||||
if (vo == null) {
|
if (vo == null) {
|
||||||
throw new CustomException("订单不存在");
|
throw new CustomException("订单不存在");
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotEmpty(vo.getAcceptBy()) && !vo.getAcceptBy().equals(ThreadLocalRequestDetail.getClerkUserInfo().getId())) {
|
// Privacy protection: Hide customer info for pending random orders that current clerk hasn't accepted
|
||||||
|
String currentClerkId = ThreadLocalRequestDetail.getClerkUserInfo().getId();
|
||||||
|
if (OrderConstant.PlaceType.RANDOM.getCode().equals(vo.getPlaceType()) && OrderConstant.OrderStatus.PENDING.getCode().equals(vo.getOrderStatus())) {
|
||||||
|
// Random order pending - customer info already hidden by service layer
|
||||||
vo.setWeiChatCode("");
|
vo.setWeiChatCode("");
|
||||||
|
} else if (StringUtils.isNotEmpty(vo.getAcceptBy()) && !vo.getAcceptBy().equals(currentClerkId)) {
|
||||||
|
// Order accepted by another clerk - hide WeChat and customer info
|
||||||
|
vo.setWeiChatCode("");
|
||||||
|
vo.setCustomNickname("匿名用户");
|
||||||
|
vo.setCustomAvatar("");
|
||||||
|
vo.setCustomId("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(vo.getOrderStatus().equals("4")){
|
if(vo.getOrderStatus().equals("4")){
|
||||||
vo.setWeiChatCode("");
|
vo.setWeiChatCode("");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -407,6 +407,45 @@ public class WxCustomMpService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步发送订单接单通知
|
||||||
|
*/
|
||||||
|
public void sendOrderMessageAsync(PlayOrderInfoEntity order) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
try {
|
||||||
|
sendOrderMessage(order);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("发送订单接单通知失败,orderId={}", order.getId(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步发送订单完成通知
|
||||||
|
*/
|
||||||
|
public void sendOrderFinishMessageAsync(PlayOrderInfoEntity order) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
try {
|
||||||
|
sendOrderFinishMessage(order);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("发送订单完成通知失败,orderId={}", order.getId(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步发送订单取消通知
|
||||||
|
*/
|
||||||
|
public void sendOrderCancelMessageAsync(PlayOrderInfoEntity order, String refundReason) {
|
||||||
|
executor.execute(() -> {
|
||||||
|
try {
|
||||||
|
sendOrderCancelMessage(order, refundReason);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("发送订单取消通知失败,orderId={}", order.getId(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void checkSubscribeThrowsExp(String openId, String tenantId) {
|
public void checkSubscribeThrowsExp(String openId, String tenantId) {
|
||||||
if (StrUtil.isBlankIfStr(openId)) {
|
if (StrUtil.isBlankIfStr(openId)) {
|
||||||
throw new ServiceException("openId不能为空");
|
throw new ServiceException("openId不能为空");
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import static org.mockito.Mockito.*;
|
|||||||
import com.starry.admin.common.exception.CustomException;
|
import com.starry.admin.common.exception.CustomException;
|
||||||
import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService;
|
import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService;
|
||||||
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
|
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
|
||||||
|
import com.starry.admin.modules.custom.module.entity.PlayCustomUserInfoEntity;
|
||||||
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
|
import com.starry.admin.modules.custom.service.IPlayCustomUserInfoService;
|
||||||
import com.starry.admin.modules.order.mapper.PlayOrderInfoMapper;
|
import com.starry.admin.modules.order.mapper.PlayOrderInfoMapper;
|
||||||
import com.starry.admin.modules.order.module.constant.OrderConstant;
|
import com.starry.admin.modules.order.module.constant.OrderConstant;
|
||||||
@@ -15,10 +16,12 @@ import com.starry.admin.modules.order.module.dto.OrderCreationRequest;
|
|||||||
import com.starry.admin.modules.order.module.dto.PaymentInfo;
|
import com.starry.admin.modules.order.module.dto.PaymentInfo;
|
||||||
import com.starry.admin.modules.order.module.dto.RandomOrderRequirements;
|
import com.starry.admin.modules.order.module.dto.RandomOrderRequirements;
|
||||||
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
||||||
|
import com.starry.admin.modules.order.service.IPlayOrderRefundInfoService;
|
||||||
import com.starry.admin.modules.order.service.impl.PlayOrderInfoServiceImpl;
|
import com.starry.admin.modules.order.service.impl.PlayOrderInfoServiceImpl;
|
||||||
import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService;
|
import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService;
|
||||||
import com.starry.admin.modules.shop.service.IPlayCouponDetailsService;
|
import com.starry.admin.modules.shop.service.IPlayCouponDetailsService;
|
||||||
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
||||||
|
import com.starry.admin.modules.withdraw.service.IEarningsService;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -64,6 +67,12 @@ class PlayOrderInfoServiceTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private IPlayPersonnelGroupInfoService playClerkGroupInfoService;
|
private IPlayPersonnelGroupInfoService playClerkGroupInfoService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private IPlayOrderRefundInfoService playOrderRefundInfoService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private IEarningsService earningsService;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private PlayOrderInfoServiceImpl orderService;
|
private PlayOrderInfoServiceImpl orderService;
|
||||||
|
|
||||||
@@ -434,4 +443,65 @@ class PlayOrderInfoServiceTest {
|
|||||||
// 3. 复杂业务流程的正确执行
|
// 3. 复杂业务流程的正确执行
|
||||||
// 实际收入计算:185元 * 20% = 37元,但由于优惠券由店员承担,需要减去15元,最终收入22元
|
// 实际收入计算:185元 * 20% = 37元,但由于优惠券由店员承担,需要减去15元,最终收入22元
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("管理员强制取消已接单/服务中订单 - 成功流程")
|
||||||
|
void testForceCancelOngoingOrderByAdminSuccess() {
|
||||||
|
String orderId = "order_force_cancel";
|
||||||
|
PlayOrderInfoEntity inProgressOrder = new PlayOrderInfoEntity();
|
||||||
|
inProgressOrder.setId(orderId);
|
||||||
|
inProgressOrder.setOrderStatus(OrderConstant.ORDER_STATUS_2);
|
||||||
|
inProgressOrder.setAcceptBy("clerk-1");
|
||||||
|
inProgressOrder.setPurchaserBy("customer-1");
|
||||||
|
inProgressOrder.setFinalAmount(BigDecimal.valueOf(100));
|
||||||
|
inProgressOrder.setPayMethod("1");
|
||||||
|
|
||||||
|
PlayOrderInfoEntity cancelledOrder = new PlayOrderInfoEntity();
|
||||||
|
cancelledOrder.setId(orderId);
|
||||||
|
cancelledOrder.setOrderStatus(OrderConstant.ORDER_STATUS_4);
|
||||||
|
|
||||||
|
PlayCustomUserInfoEntity customUserInfo = new PlayCustomUserInfoEntity();
|
||||||
|
customUserInfo.setId("customer-1");
|
||||||
|
customUserInfo.setAccountBalance(BigDecimal.valueOf(200));
|
||||||
|
|
||||||
|
when(orderInfoMapper.selectById(orderId)).thenReturn(inProgressOrder, cancelledOrder);
|
||||||
|
when(orderInfoMapper.updateById(any(PlayOrderInfoEntity.class))).thenReturn(1);
|
||||||
|
when(customUserInfoService.getById("customer-1")).thenReturn(customUserInfo);
|
||||||
|
|
||||||
|
doNothing().when(customUserInfoService).updateAccountBalanceById(eq("customer-1"), any(BigDecimal.class),
|
||||||
|
any(BigDecimal.class), anyString(), anyString(), any(BigDecimal.class), any(BigDecimal.class), eq(orderId));
|
||||||
|
doNothing().when(playOrderRefundInfoService).add(eq(orderId), eq("customer-1"), eq("clerk-1"), anyString(),
|
||||||
|
anyString(), any(BigDecimal.class), anyString(), anyString(), anyString(), anyString(), anyString());
|
||||||
|
doNothing().when(wxCustomMpService).sendOrderCancelMessage(any(PlayOrderInfoEntity.class), anyString());
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> orderService.forceCancelOngoingOrder("2", "admin-1", orderId,
|
||||||
|
BigDecimal.valueOf(80), "管理员取消测试", Collections.emptyList()));
|
||||||
|
|
||||||
|
verify(orderInfoMapper, times(1)).updateById(any(PlayOrderInfoEntity.class));
|
||||||
|
verify(customUserInfoService, times(1)).updateAccountBalanceById(eq("customer-1"), any(BigDecimal.class),
|
||||||
|
any(BigDecimal.class), anyString(), anyString(), eq(BigDecimal.valueOf(80)), eq(BigDecimal.ZERO),
|
||||||
|
eq(orderId));
|
||||||
|
verify(playOrderRefundInfoService, times(1)).add(eq(orderId), eq("customer-1"), eq("clerk-1"), anyString(),
|
||||||
|
eq("0"), eq(BigDecimal.valueOf(80)), eq("管理员取消测试"), eq("2"), eq("admin-1"), eq("0"), eq("0"));
|
||||||
|
verify(wxCustomMpService, times(1)).sendOrderCancelMessage(any(PlayOrderInfoEntity.class),
|
||||||
|
eq("管理员取消测试"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("强制取消订单 - 非进行中状态抛出异常")
|
||||||
|
void testForceCancelOngoingOrderInvalidStatus() {
|
||||||
|
String orderId = "order_invalid_force_cancel";
|
||||||
|
PlayOrderInfoEntity pendingOrder = new PlayOrderInfoEntity();
|
||||||
|
pendingOrder.setId(orderId);
|
||||||
|
pendingOrder.setOrderStatus(OrderConstant.ORDER_STATUS_0);
|
||||||
|
pendingOrder.setAcceptBy("clerk-1");
|
||||||
|
pendingOrder.setPurchaserBy("customer-1");
|
||||||
|
pendingOrder.setFinalAmount(BigDecimal.valueOf(50));
|
||||||
|
|
||||||
|
when(orderInfoMapper.selectById(orderId)).thenReturn(pendingOrder);
|
||||||
|
|
||||||
|
assertThrows(CustomException.class, () -> orderService.forceCancelOngoingOrder("2", "admin-1", orderId,
|
||||||
|
null, "原因", Collections.emptyList()));
|
||||||
|
verify(orderInfoMapper, never()).updateById(any(PlayOrderInfoEntity.class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user