From 92ba2b93a29d912b64a71c0038bcb3224307b36c Mon Sep 17 00:00:00 2001 From: dzq Date: Wed, 9 Apr 2025 16:41:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=AE=A1=E6=89=B9):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E7=8A=B6=E6=80=81=E9=AA=8C=E8=AF=81=E5=92=8C?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加审批状态验证方法`validateApprovalStatus`,确保审批状态合法。在`ReturnApprovalApplicationService`中实现审批通过和驳回的逻辑,包括退款金额验证、退款操作以及更新订单商品状态。同时,修复SQL查询中的空格问题。 --- .../api/controller/ApprovalApiController.java | 37 +++++- .../ReturnApprovalApplicationService.java | 106 ++++++++++++++++++ .../approval/db/ReturnApprovalMapper.java | 2 +- .../approval/model/ReturnApprovalModel.java | 10 ++ .../order/model/OrderGoodsModelFactory.java | 10 ++ .../payment/PaymentApplicationService.java | 5 +- 6 files changed, 165 insertions(+), 5 deletions(-) diff --git a/agileboot-api/src/main/java/com/agileboot/api/controller/ApprovalApiController.java b/agileboot-api/src/main/java/com/agileboot/api/controller/ApprovalApiController.java index 57ca528..25b2ff6 100644 --- a/agileboot-api/src/main/java/com/agileboot/api/controller/ApprovalApiController.java +++ b/agileboot-api/src/main/java/com/agileboot/api/controller/ApprovalApiController.java @@ -6,6 +6,7 @@ import com.agileboot.common.exception.ApiException; import com.agileboot.common.exception.error.ErrorCode; import com.agileboot.domain.shop.approval.ReturnApprovalApplicationService; import com.agileboot.domain.shop.approval.command.AddReturnApprovalCommand; +import com.agileboot.domain.shop.approval.command.UpdateReturnApprovalCommand; import com.agileboot.domain.shop.approval.db.ReturnApprovalEntity; import com.agileboot.domain.shop.approval.model.ReturnApprovalModel; import com.agileboot.domain.shop.approval.query.SearchApiReturnApprovalQuery; @@ -36,13 +37,45 @@ import java.util.Date; @Slf4j @Api(tags = "审批接口") public class ApprovalApiController { - + /** 退货审批应用服务,用于处理审批相关业务逻辑 */ private final ReturnApprovalApplicationService approvalApplicationService; - + /** 订单应用服务,用于处理订单相关查询操作 */ private final OrderApplicationService orderApplicationService; + /** + * 处理审批操作 + * + * @param command 包含审批操作信息的命令对象 + * @return 操作结果响应 + * @throws ApiException 当参数校验失败或业务逻辑出错时抛出 + */ + @PostMapping("/handle") + @ApiOperation(value = "处理审批操作") + public ResponseDTO handleApproval(@Valid @RequestBody UpdateReturnApprovalCommand command) { + if (command.getApprovalId() == null) { + return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "审批ID不能为空")); + } + if (command.getStatus() == null) { + return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "操作状态不能为空")); + } + + try { + if (command.getStatus() == 2) { + approvalApplicationService.approveApproval(command); + } else if (command.getStatus() == 3) { + approvalApplicationService.rejectApproval(command); + } else { + return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "无效的操作状态")); + } + return ResponseDTO.ok("操作成功"); + } catch (Exception e) { + log.error("审批操作失败", e); + return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, e.getMessage())); + } + } + /** * 提交退货审批申请 * diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/ReturnApprovalApplicationService.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/ReturnApprovalApplicationService.java index 9090fc2..9c51b02 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/ReturnApprovalApplicationService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/ReturnApprovalApplicationService.java @@ -1,5 +1,6 @@ package com.agileboot.domain.shop.approval; +import com.agileboot.common.constant.PayApiConstants; import com.agileboot.common.core.page.PageDTO; import com.agileboot.domain.common.command.BulkOperationCommand; import com.agileboot.domain.shop.approval.command.AddReturnApprovalCommand; @@ -14,8 +15,14 @@ import com.agileboot.domain.shop.approval.query.SearchReturnApprovalQuery; import com.agileboot.domain.shop.order.db.ShopOrderGoodsEntity; import com.agileboot.domain.shop.order.model.OrderGoodsModel; import com.agileboot.domain.shop.order.model.OrderGoodsModelFactory; +import com.agileboot.domain.shop.order.model.OrderModel; +import com.agileboot.domain.shop.order.model.OrderModelFactory; +import com.agileboot.domain.shop.payment.PaymentApplicationService; +import com.agileboot.domain.shop.payment.dto.RefundVO; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.Date; import java.util.List; import java.util.stream.Collectors; @@ -23,6 +30,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +/** + * 退货审批应用服务类,处理与退货审批相关的业务逻辑 + */ @Service @Slf4j @RequiredArgsConstructor @@ -31,7 +41,14 @@ public class ReturnApprovalApplicationService { private final ReturnApprovalService approvalService; private final ReturnApprovalModelFactory modelFactory; private final OrderGoodsModelFactory orderGoodsModelFactory; + private final OrderModelFactory orderModelFactory; + private final PaymentApplicationService paymentApplicationService; + /** + * 获取退货审批列表 + * @param query 查询条件 + * @return 分页的退货审批DTO列表 + */ public PageDTO getApprovalList(SearchReturnApprovalQuery query) { Page page = approvalService.getApprovalList(query); List dtoList = page.getRecords().stream() @@ -40,6 +57,11 @@ public class ReturnApprovalApplicationService { return new PageDTO<>(dtoList, page.getTotal()); } + /** + * 添加退货审批 + * @param command 添加退货审批命令 + * @return 创建的退货审批模型 + */ public ReturnApprovalModel addApproval(AddReturnApprovalCommand command) { ReturnApprovalModel model = modelFactory.create(); model.loadAddCommand(command); @@ -47,12 +69,20 @@ public class ReturnApprovalApplicationService { return model; } + /** + * 更新退货审批信息 + * @param command 更新退货审批命令 + */ public void updateApproval(UpdateReturnApprovalCommand command) { ReturnApprovalModel model = modelFactory.loadById(command.getApprovalId()); model.loadUpdateCommand(command); model.updateById(); } + /** + * 批量删除退货审批 + * @param command 批量操作命令,包含要删除的审批ID列表 + */ public void deleteApproval(BulkOperationCommand command) { for (Long approvalId : command.getIds()) { ReturnApprovalModel model = modelFactory.loadById(approvalId); @@ -60,6 +90,67 @@ public class ReturnApprovalApplicationService { } } + /** + * 审批通过退货申请 + * @param command 更新退货审批命令 + * @throws IllegalArgumentException 如果退款金额不合法 + * @throws RuntimeException 如果退款操作失败 + */ + public void approveApproval(UpdateReturnApprovalCommand command) { + ReturnApprovalModel model = modelFactory.loadById(command.getApprovalId()); + + + OrderModel orderModel = orderModelFactory.loadById(model.getOrderId()); + OrderGoodsModel orderGoodsModel = orderGoodsModelFactory.loadById(model.getOrderGoodsId()); + // 退款金额对比, 退款金额不能大于订单金额 + // 金额转换(元转分)并四舍五入 + BigDecimal amountInFen = orderGoodsModel.getTotalAmount() + .multiply(new BigDecimal("100")) + .setScale(0, RoundingMode.HALF_UP); + BigDecimal returnAmount = command.getReturnAmount(); + // 退款金额转换(元转分)并四舍五入 + returnAmount = returnAmount + .multiply(new BigDecimal("100")) + .setScale(0, RoundingMode.HALF_UP); + if (returnAmount.compareTo(BigDecimal.ZERO) <= 0) { + throw new IllegalArgumentException("退款金额必须大于0"); + } + if (returnAmount.compareTo(amountInFen) > 0) { + throw new IllegalArgumentException("退款金额不能超过订单总额"); + } + + RefundVO refundVO = null; + try { + refundVO = paymentApplicationService.refund( + PayApiConstants.biz_id, PayApiConstants.appkey, + orderModel.getBizOrderId(), orderModel.getUcid(), + "退还", returnAmount.intValue()); + } catch (Exception e) { + throw new RuntimeException("退款失败", e); + } + log.info("退款结果:{}", refundVO); + if (null == refundVO || !refundVO.getSuccess()) { + throw new RuntimeException("退款失败"); + } + + model.validateApprovalStatus(); + model.setAuditImages(command.getAuditImages()); + model.setAuditRemark(command.getAuditRemark()); + model.setReturnAmount(command.getReturnAmount()); + model.setStatus(2); // 2表示审核通过状态 + model.updateById(); + + // 更新关联订单商品状态 + orderGoodsModel.setStatus(2); // 6表示已完成退货 + orderGoodsModel.updateById(); + } + + /** + * 提交退货审批申请 + * @param command 添加退货审批命令 + * @param orderGoods 关联的订单商品实体 + * @return 创建的退货审批实体 + */ public ReturnApprovalEntity submitApproval(AddReturnApprovalCommand command, ShopOrderGoodsEntity orderGoods) { // 设置商品价格并初始化审批状态 command.setGoodsId(orderGoods.getGoodsId()); @@ -89,4 +180,19 @@ public class ReturnApprovalApplicationService { Page page = approvalService.selectApprovalWithGoodsInfo(query); return new PageDTO<>(page.getRecords(), page.getTotal()); } + + /** + * 审批驳回退货申请 + * @param command 更新退货审批命令(包含驳回原因) + */ + public void rejectApproval(UpdateReturnApprovalCommand command) { + ReturnApprovalModel model = modelFactory.loadById(command.getApprovalId()); + model.validateApprovalStatus(); + + // 更新审批状态为驳回 + model.setStatus(3); + model.setAuditImages(command.getAuditImages()); + model.setAuditRemark(command.getAuditRemark()); + model.updateById(); + } } \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/db/ReturnApprovalMapper.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/db/ReturnApprovalMapper.java index a80753b..a507c94 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/db/ReturnApprovalMapper.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/db/ReturnApprovalMapper.java @@ -20,7 +20,7 @@ public interface ReturnApprovalMapper extends BaseMapper { @Select("SELECT ra.*, sog.goods_name AS goodsName, sog.cover_img AS coverImg " + "FROM return_approval ra " + - "LEFT JOIN shop_order_goods sog ON ra.order_goods_id = sog.order_goods_id" + + "LEFT JOIN shop_order_goods sog ON ra.order_goods_id = sog.order_goods_id " + "${ew.customSqlSegment}") Page selectApprovalWithGoodsInfo(Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/model/ReturnApprovalModel.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/model/ReturnApprovalModel.java index c1a7084..77366df 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/model/ReturnApprovalModel.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/model/ReturnApprovalModel.java @@ -36,4 +36,14 @@ public class ReturnApprovalModel extends ReturnApprovalEntity { loadAddCommand(command); } } + + public void validateApprovalStatus() { + if (getStatus() == null || !isValidStatus(getStatus())) { + throw new RuntimeException("审批状态不合法"); + } + } + + private boolean isValidStatus(Integer status) { + return !status.equals(2); + } } \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/model/OrderGoodsModelFactory.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/model/OrderGoodsModelFactory.java index f6ab949..c938f0b 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/model/OrderGoodsModelFactory.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/order/model/OrderGoodsModelFactory.java @@ -1,5 +1,7 @@ package com.agileboot.domain.shop.order.model; +import com.agileboot.common.exception.ApiException; +import com.agileboot.common.exception.error.ErrorCode; import com.agileboot.domain.shop.goods.db.ShopGoodsService; import com.agileboot.domain.shop.order.db.ShopOrderGoodsEntity; import com.agileboot.domain.shop.order.db.ShopOrderGoodsService; @@ -13,6 +15,14 @@ public class OrderGoodsModelFactory { private final ShopOrderGoodsService orderGoodsService; private final ShopGoodsService goodsService; + public OrderGoodsModel loadById(Long orderGoodsId) { + ShopOrderGoodsEntity entity = orderGoodsService.getById(orderGoodsId); + if (entity == null) { + throw new ApiException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, orderGoodsId, "订单商品"); + } + return new OrderGoodsModel(entity, orderGoodsService, goodsService); + } + public OrderGoodsModel create(ShopOrderGoodsEntity entity) { return new OrderGoodsModel(entity, orderGoodsService, goodsService); } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/payment/PaymentApplicationService.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/payment/PaymentApplicationService.java index 95c59e6..422320b 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/payment/PaymentApplicationService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/payment/PaymentApplicationService.java @@ -214,8 +214,9 @@ public class PaymentApplicationService { if (orderNO.startsWith("wxshop-")) { // 订单号格式为 wxshop-1-time,提取中间的订单号 String orderId = orderNO.split("-")[1]; - OrderModel orderModel = orderModelFactory.loadById(Long.valueOf(orderId)); - orderModel.handleRefundSuccess(); + log.info("退款回调处理成功, 订单号:{}", orderId); +// OrderModel orderModel = orderModelFactory.loadById(Long.valueOf(orderId)); +// orderModel.handleRefundSuccess(); } } res.set("callback_code", 0);