用户勾选多个商品退款接口开发,整单取消逻辑修改

This commit is contained in:
Jack 2025-12-09 00:25:31 +08:00
parent eb8fb4a4e9
commit 8bd8c49f38
4 changed files with 355 additions and 14 deletions

View File

@ -1,6 +1,8 @@
package com.suisung.mall.shop.order.controller.mobile;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.api.ResultCode;
@ -15,10 +17,7 @@ import com.suisung.mall.shop.order.vo.OrderReturnVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* <p>
@ -57,7 +56,7 @@ public class UserReturnController extends BaseControllerImpl {
return shopOrderReturnService.returnItem();
}
@ApiOperation(value = "添加退款退货-部分退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。", notes = "添加退款退货-发货退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。")
@ApiOperation(value = "添加退款退货-部分退货", notes = "添加退款退货-发货退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。")
@RequestMapping(value = "/addItem", method = RequestMethod.GET)
public CommonResult addItem(OrderReturnVo orderReturnVo) {
UserDto user = getCurrentUser();
@ -77,6 +76,26 @@ public class UserReturnController extends BaseControllerImpl {
return shopOrderReturnService.addItem(orderReturnInputVo, true);
}
@ApiOperation(value = "批量添加退款退货(支持多个商品)", notes = "添加退款退货-发货退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。")
@RequestMapping(value = "/addItemBatch", method = RequestMethod.POST)
public CommonResult addItemBatch(@RequestBody JSONObject orderReturnVoJSON) {
if (orderReturnVoJSON == null) {
return CommonResult.failed("请求参数不能为空");
}
OrderReturnInputVo orderReturnInputVo = JSONUtil.toBean(orderReturnVoJSON, OrderReturnInputVo.class);
if (orderReturnInputVo == null) {
return CommonResult.failed("请求参数格式不正确");
}
UserDto user = getCurrentUser();
if (user == null) {
return CommonResult.failed(ResultCode.NEED_LOGIN);
}
return shopOrderReturnService.tryAddItemBatch(orderReturnInputVo);
}
@ApiOperation(value = "添加退款退货-整单退货", notes = "添加退款退货-整单退货")
@RequestMapping(value = "/addWholeItems", method = RequestMethod.POST)
public CommonResult addWholeItems(@RequestParam(name = "order_id") String order_id) {

View File

@ -50,6 +50,14 @@ public interface ShopOrderReturnService extends IBaseService<ShopOrderReturn> {
*/
CommonResult addItem(OrderReturnInputVo orderReturnInputVo, Boolean needSendMsg);
/**
* 尝试批量添加退款退货申请自动使用最大可退数量和金额等待商家审核处理同意或不同意
*
* @param orderReturnInputVo 退款申请输入参数支持订单多个商品退款
* @return CommonResult 退款申请结果
*/
CommonResult tryAddItemBatch(OrderReturnInputVo orderReturnInputVo);
Map getReturnDetail(String return_id);
boolean processReviewList(ShopOrderReturn shopOrderReturn, Integer receiving_address);

View File

@ -4167,11 +4167,12 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
if (!isOrderDenyReturn) {
// 支付的订单允许退款立即发起退款流程再由商家审核
CommonResult refundResult = shopOrderReturnService.addRemainingItems(orderId, false, "用户取消订单");
if (refundResult == null || refundResult.getStatus() != 200) {
logger.error("提交订单审核失败!");
if (refundResult == null || refundResult.getStatus() != 200L) {
logger.error("用户提交取消订单失败!");
return false;
}
// 提交成功之后再由商家审核通过之后会继续完成以下的操作
return true;
}
}

View File

@ -74,6 +74,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
@ -488,7 +489,6 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
returnItemQueryWrapper.in("order_item_id", order_item_ids)
.in("return_id", return_ids);
List<ShopOrderReturnItem> order_return_items = orderReturnItemService.find(returnItemQueryWrapper);
if (CollUtil.isNotEmpty(order_return_items)) {
throw new ApiException(I18nUtil._("此订单商品正在退款审核!"));
}
@ -568,17 +568,16 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
// 构建退款单明细
ShopOrderReturnItem orderReturnItem = new ShopOrderReturnItem();
Integer return_item_num = returnItemInputVo.getReturn_item_num();
Integer return_item_num = returnItemInputVo.getReturn_item_num(); //用户当前申请退款的商品数量
if (return_item_num <= 0) {
throw new ApiException("退款数量必须大于0请检查商品 " + shopOrderItem.getItem_name() + " 的退款数量");
}
// 检查退款数量是否超过可退数量
Integer order_item_quantity = shopOrderItem.getOrder_item_quantity();
Integer order_item_return_agree_num = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_num(), 0);
Integer available_return_num = order_item_quantity - order_item_return_agree_num;
Integer order_item_quantity = shopOrderItem.getOrder_item_quantity(); // 订单中该商品的原始购买数量
Integer order_item_return_agree_num = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_num(), 0); // 订单中该商品已经同意退货的数量
Integer available_return_num = order_item_quantity - order_item_return_agree_num; // 当前还可以申请退款的商品数量
if (return_item_num > available_return_num) {
throw new ApiException(String.format("商品 %s 的退款数量超过可退数量,最多可退 %d 件",
shopOrderItem.getItem_name(), available_return_num));
@ -650,6 +649,208 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
return CommonResult.success(data);
}
// @Override
/**
* 尝试批量添加退款退货申请自动使用最大可退数量和金额
*
* @param orderReturnInputVo 退款申请输入参数支持订单多个商品退款
* @return CommonResult 退款申请结果
*/
@Override
@Transactional
public CommonResult tryAddItemBatch(OrderReturnInputVo orderReturnInputVo) {
Map<String, Object> data = new HashMap<>();
// 获取用户ID
Integer user_id = orderReturnInputVo.getUser_id();
if (CheckUtil.isEmpty(user_id)) {
UserDto user = getCurrentUser();
if (user == null) {
throw new ApiUserException(I18nUtil._("用户信息异常!"));
}
user_id = user.getId();
}
// 获取买家店铺ID如果有
Integer buyer_store_id = shopStoreBaseService.getStoreId(user_id);
// 获取订单信息
String order_id = orderReturnInputVo.getOrder_id();
List<Long> order_item_ids = orderReturnInputVo.getReturn_items().stream()
.map(OrderReturnItemInputVo::getOrder_item_id)
.distinct()
.collect(Collectors.toList());
ShopOrderInfo shopOrderInfo = shopOrderInfoService.get(order_id);
if (shopOrderInfo == null) {
throw new ApiException(I18nUtil._("此订单信息数据有误!"));
}
ShopOrderBase orderBase = shopOrderBaseService.get(order_id);
if (orderBase == null) {
throw new ApiException(I18nUtil._("此订单详细信息数据有误!"));
}
// 判断此订单商品是否有正在审核的退款单
QueryWrapper<ShopOrderReturn> returnQueryWrapper = new QueryWrapper<>();
returnQueryWrapper.eq("order_id", order_id)
.eq("return_state_id", StateCode.RETURN_PROCESS_CHECK);
List<ShopOrderReturn> order_return_rows = find(returnQueryWrapper);
if (CollUtil.isNotEmpty(order_return_rows)) {
List<String> return_ids = order_return_rows.stream()
.map(ShopOrderReturn::getReturn_id)
.collect(Collectors.toList());
QueryWrapper<ShopOrderReturnItem> returnItemQueryWrapper = new QueryWrapper<>();
returnItemQueryWrapper.in("order_item_id", order_item_ids)
.in("return_id", return_ids);
List<ShopOrderReturnItem> order_return_items = orderReturnItemService.find(returnItemQueryWrapper);
if (CollUtil.isNotEmpty(order_return_items)) {
throw new ApiException(I18nUtil._("此订单商品正在退款审核!"));
}
}
// 检查数据权限
if (!CheckUtil.checkDataRights(user_id, orderBase, ShopOrderBase::getBuyer_user_id)) {
throw new ApiException(ResultCode.FORBIDDEN);
}
// 获取退款申请参数
String return_id = orderReturnInputVo.getReturn_id();
Integer return_reason_id = orderReturnInputVo.getReturn_reason_id() == null ? 0 : orderReturnInputVo.getReturn_reason_id();
String return_buyer_message = orderReturnInputVo.getReturn_buyer_message();
Integer store_id = Convert.toInt(orderBase.getStore_id());
String return_tel = orderReturnInputVo.getReturn_tel();
// 手机号验证
if (StrUtil.isNotBlank(return_tel) && !PhoneUtil.isMobile(return_tel)) {
throw new ApiException(I18nUtil._("手机号输入有误!"));
}
Date curTime = new Date();
// 构建退款单主表信息
ShopOrderReturn orderReturn = new ShopOrderReturn();
orderReturn.setReturn_id(return_id);
orderReturn.setOrder_id(order_id);
orderReturn.setBuyer_user_id(user_id);
orderReturn.setBuyer_store_id(buyer_store_id);
orderReturn.setReturn_reason_id(return_reason_id);
orderReturn.setReturn_buyer_message(return_buyer_message);
orderReturn.setStore_id(store_id);
orderReturn.setReturn_refund_amount(BigDecimal.ZERO);
orderReturn.setReturn_commision_fee(BigDecimal.ZERO);
orderReturn.setReturn_state_id(StateCode.RETURN_PROCESS_CHECK);
orderReturn.setReturn_tel(return_tel);
orderReturn.setReturn_year(DateUtil.year(curTime)); // 退单年份-索引查询
orderReturn.setReturn_month(DateUtil.month(curTime) + 1); // 退单月份-索引查询
orderReturn.setReturn_day(DateUtil.dayOfMonth(curTime)); // 退单日-索引查询
orderReturn.setReturn_reason_id(0); // 注意这里覆盖了前面设置的return_reason_id
orderReturn.setReturn_store_user_id(0);
orderReturn.setReturn_mobile(0L);
orderReturn.setReturn_telephone("");
orderReturn.setSubsite_id(shopOrderInfo.getSubsite_id());
// 构建退款单明细信息
List<ShopOrderReturnItem> shopOrderReturnItems = new ArrayList<>();
for (OrderReturnItemInputVo returnItemInputVo : orderReturnInputVo.getReturn_items()) {
// 获取订单商品信息
ShopOrderItem shopOrderItem = shopOrderItemService.get(returnItemInputVo.getOrder_item_id());
if (shopOrderItem == null) {
throw new ApiException("订单商品不存在请检查商品ID是否正确: " + returnItemInputVo.getOrder_item_id());
}
// 验证是否为当前订单的商品
if (!order_id.equals(shopOrderItem.getOrder_id())) {
throw new ApiException("商品ID " + returnItemInputVo.getOrder_item_id() + " 不属于订单 " + order_id);
}
// 获取商品索引信息
ShopProductIndex shopProductIndex = shopProductIndexService.get(shopOrderItem.getProduct_id());
if (shopProductIndex == null) {
throw new ApiException("商品信息不存在请检查商品ID是否正确: " + shopOrderItem.getProduct_id());
}
// 检查是否允许退货
boolean is_denyreturn = ifDenyReturn(shopOrderInfo, shopOrderItem, shopProductIndex);
if (is_denyreturn) {
// 获取更详细的拒绝退货原因
String denyReason = getDenyReturnReason(shopOrderInfo, shopOrderItem, shopProductIndex);
if (StrUtil.isBlank(denyReason)) {
denyReason = "此商品不允许退货!";
}
throw new ApiException(denyReason);
}
// 构建退款单明细
ShopOrderReturnItem orderReturnItem = new ShopOrderReturnItem();
// 检查退款数量是否超过可退数量
Integer order_item_quantity = shopOrderItem.getOrder_item_quantity(); // 订单中该商品的原始购买数量
Integer order_item_return_agree_num = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_num(), 0); // 订单中该商品已经同意退货的数量
Integer available_return_num = order_item_quantity - order_item_return_agree_num; // 当前还可以申请退款的商品数量
if (available_return_num <= 0) {
throw new ApiException(String.format("商品 %s 已无可退数量", shopOrderItem.getItem_name()));
}
// 检查退款金额是否合理
BigDecimal order_item_payment_amount = shopOrderItem.getOrder_item_payment_amount();
BigDecimal order_item_return_agree_amount = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_amount(), BigDecimal.ZERO);
BigDecimal available_return_amount = order_item_payment_amount.subtract(order_item_return_agree_amount);
if (available_return_amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new ApiException(String.format("商品 %s 已无可退金额", shopOrderItem.getItem_name()));
}
String return_item_image = ObjectUtil.defaultIfBlank(
orderReturnInputVo.getRefund_pic(),
orderReturnInputVo.getUpload_img());
orderReturnItem.setOrder_item_id(returnItemInputVo.getOrder_item_id());
orderReturnItem.setOrder_id(order_id);
orderReturnItem.setReturn_item_num(available_return_num);
orderReturnItem.setReturn_item_subtotal(available_return_amount);
orderReturnItem.setReturn_reason_id(return_reason_id);
orderReturnItem.setReturn_item_note(return_buyer_message);
orderReturnItem.setReturn_item_image(return_item_image);
orderReturnItem.setReturn_state_id(StateCode.RETURN_PROCESS_CHECK);
shopOrderReturnItems.add(orderReturnItem);
}
// 保存退款单
if (!addReturnByItem(orderReturn, shopOrderReturnItems)) {
throw new ApiException(ResultCode.FAILED);
}
data.put("return", orderReturn);
data.put("items", shopOrderReturnItems);
// 打票机打印退款订单到店(异步执行)
shopStorePrinterService.printShopStoreReturnOrder(return_id);
// 发送消息通知, 退款提醒商家
String message_id = "refund-reminder";
Map<String, Object> args = new HashMap<>();
args.put("order_id", orderReturn.getReturn_id());
messageService.sendNoticeMsg(0, store_id, message_id, args);
// 发送unipush消息
String title = "您有一个退款的订单,请及时前往后台审核!";
String content = String.format("订单号:%s 退单号:[%s],时间:%s请及时前往后台审核",
order_id, orderReturn.getReturn_id(),
DateTimeUtils.formatDateTime(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss"));
JSONObject payload = JSONUtil.createObj();
payload.set("category", CommonConstant.PUSH_MSG_CATE_MCH_RETURN_ORDER_LIST);
payload.set("orderId", order_id);
payload.set("returnId", orderReturn.getReturn_id());
pushMessageService.noticeMerchantEmployeeOrderAction(store_id, order_id, title, content, payload);
data.put("order_item_ids", order_item_ids);
return CommonResult.success(data);
}
/**
* 取消退货
@ -3099,4 +3300,116 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
return "商品不支持退货";
}
/**
* 校验退款商品数量和金额是否有效
*
* @param shopOrderItem 订单商品项
* @param requestReturnNum 请求退款数量
* @param requestRefundAmount 请求退款金额
* @param autoCorrect 是否自动纠正(false:超出时抛出异常, true:超出时自动调整为最大可退数量/金额)
* @return 校验后的有效退款信息数组[0]为数量[1]为金额
* @throws ApiException 当autoCorrect为false且请求数量或金额超出可退范围时抛出异常
*/
private BigDecimal[] validateReturnInfo(ShopOrderItem shopOrderItem, Integer requestReturnNum, BigDecimal requestRefundAmount, boolean autoCorrect) {
// 校验请求参数有效性
if (requestReturnNum <= 0) {
throw new ApiException("退款数量必须大于0请检查商品 " + shopOrderItem.getItem_name() + " 的退款数量");
}
if (requestRefundAmount == null || requestRefundAmount.compareTo(BigDecimal.ZERO) <= 0) {
throw new ApiException("退款金额必须大于0请检查商品 " + shopOrderItem.getItem_name() + " 的退款金额");
}
// 计算可退数量和金额
Integer orderItemQuantity = shopOrderItem.getOrder_item_quantity();
Integer orderItemReturnAgreeNum = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_num(), 0);
Integer availableReturnNum = orderItemQuantity - orderItemReturnAgreeNum;
BigDecimal orderItemPaymentAmount = shopOrderItem.getOrder_item_payment_amount();
BigDecimal orderItemReturnAgreeAmount = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_amount(), BigDecimal.ZERO);
BigDecimal availableReturnAmount = orderItemPaymentAmount.subtract(orderItemReturnAgreeAmount);
// 检查是否还有可退数量
if (availableReturnNum <= 0) {
if (autoCorrect) {
return new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO};
}
throw new ApiException(String.format("商品 %s 已无可退数量,无法申请退款", shopOrderItem.getItem_name()));
}
// 检查是否还有可退金额
if (availableReturnAmount.compareTo(BigDecimal.ZERO) <= 0) {
if (autoCorrect) {
return new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO};
}
throw new ApiException(String.format("商品 %s 已无可退款金额,无法申请退款", shopOrderItem.getItem_name()));
}
// 校验并处理请求退款数量是否超过可退数量
if (requestReturnNum > availableReturnNum) {
if (!autoCorrect) {
throw new ApiException(String.format("商品 %s 的退款数量超过可退数量,最多可退 %d 件",
shopOrderItem.getItem_name(), availableReturnNum));
}
// 按比例调整退款金额
BigDecimal ratio = BigDecimal.valueOf(availableReturnNum)
.divide(BigDecimal.valueOf(requestReturnNum), 6, RoundingMode.HALF_UP);
BigDecimal correctedAmount = requestRefundAmount.multiply(ratio);
return new BigDecimal[]{BigDecimal.valueOf(availableReturnNum), correctedAmount};
}
// 校验并处理请求退款金额是否超过可退金额
if (requestRefundAmount.compareTo(availableReturnAmount) > 0) {
if (!autoCorrect) {
throw new ApiException(String.format("商品 %s 的退款金额超过可退金额,最多可退 %.2f 元",
shopOrderItem.getItem_name(), availableReturnAmount));
}
return new BigDecimal[]{BigDecimal.valueOf(requestReturnNum), availableReturnAmount};
}
return new BigDecimal[]{BigDecimal.valueOf(requestReturnNum), requestRefundAmount};
}
/**
* 校验退款商品数量是否有效专用于仅校验数量的场景
*
* @param shopOrderItem 订单商品项
* @param requestReturnNum 请求退款数量
* @param autoCorrect 是否自动纠正数量(false:超出时抛出异常, true:超出时自动调整为最大可退数量)
* @return 校验后的有效退款数量
* @throws ApiException 当autoCorrect为false且请求数量超出可退数量时抛出异常
*/
private Integer validateReturnQuantity(ShopOrderItem shopOrderItem, Integer requestReturnNum, boolean autoCorrect) {
// 校验请求参数有效性
if (requestReturnNum <= 0) {
throw new ApiException("退款数量必须大于0请检查商品 " + shopOrderItem.getItem_name() + " 的退款数量");
}
// 计算可退数量
Integer orderItemQuantity = shopOrderItem.getOrder_item_quantity();
Integer orderItemReturnAgreeNum = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_num(), 0);
Integer availableReturnNum = orderItemQuantity - orderItemReturnAgreeNum;
// 检查是否还有可退数量
if (availableReturnNum <= 0) {
if (autoCorrect) {
return 0;
}
throw new ApiException(String.format("商品 %s 已无可退数量,无法申请退款", shopOrderItem.getItem_name()));
}
// 校验并处理请求退款数量是否超过可退数量
if (requestReturnNum > availableReturnNum) {
if (!autoCorrect) {
throw new ApiException(String.format("商品 %s 的退款数量超过可退数量,最多可退 %d 件",
shopOrderItem.getItem_name(), availableReturnNum));
}
return availableReturnNum;
}
return requestReturnNum;
}
}