feat(审批): 添加审批状态验证和审批处理逻辑

添加审批状态验证方法`validateApprovalStatus`,确保审批状态合法。在`ReturnApprovalApplicationService`中实现审批通过和驳回的逻辑,包括退款金额验证、退款操作以及更新订单商品状态。同时,修复SQL查询中的空格问题。
This commit is contained in:
dzq 2025-04-09 16:41:36 +08:00
parent 980d279ba9
commit 92ba2b93a2
6 changed files with 165 additions and 5 deletions

View File

@ -6,6 +6,7 @@ import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode; import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.shop.approval.ReturnApprovalApplicationService; import com.agileboot.domain.shop.approval.ReturnApprovalApplicationService;
import com.agileboot.domain.shop.approval.command.AddReturnApprovalCommand; 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.db.ReturnApprovalEntity;
import com.agileboot.domain.shop.approval.model.ReturnApprovalModel; import com.agileboot.domain.shop.approval.model.ReturnApprovalModel;
import com.agileboot.domain.shop.approval.query.SearchApiReturnApprovalQuery; import com.agileboot.domain.shop.approval.query.SearchApiReturnApprovalQuery;
@ -43,6 +44,38 @@ public class ApprovalApiController {
/** 订单应用服务,用于处理订单相关查询操作 */ /** 订单应用服务,用于处理订单相关查询操作 */
private final OrderApplicationService orderApplicationService; private final OrderApplicationService orderApplicationService;
/**
* 处理审批操作
*
* @param command 包含审批操作信息的命令对象
* @return 操作结果响应
* @throws ApiException 当参数校验失败或业务逻辑出错时抛出
*/
@PostMapping("/handle")
@ApiOperation(value = "处理审批操作")
public ResponseDTO<String> 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()));
}
}
/** /**
* 提交退货审批申请 * 提交退货审批申请
* *

View File

@ -1,5 +1,6 @@
package com.agileboot.domain.shop.approval; package com.agileboot.domain.shop.approval;
import com.agileboot.common.constant.PayApiConstants;
import com.agileboot.common.core.page.PageDTO; import com.agileboot.common.core.page.PageDTO;
import com.agileboot.domain.common.command.BulkOperationCommand; import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.shop.approval.command.AddReturnApprovalCommand; 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.db.ShopOrderGoodsEntity;
import com.agileboot.domain.shop.order.model.OrderGoodsModel; import com.agileboot.domain.shop.order.model.OrderGoodsModel;
import com.agileboot.domain.shop.order.model.OrderGoodsModelFactory; 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 com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -23,6 +30,9 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/**
* 退货审批应用服务类处理与退货审批相关的业务逻辑
*/
@Service @Service
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
@ -31,7 +41,14 @@ public class ReturnApprovalApplicationService {
private final ReturnApprovalService approvalService; private final ReturnApprovalService approvalService;
private final ReturnApprovalModelFactory modelFactory; private final ReturnApprovalModelFactory modelFactory;
private final OrderGoodsModelFactory orderGoodsModelFactory; private final OrderGoodsModelFactory orderGoodsModelFactory;
private final OrderModelFactory orderModelFactory;
private final PaymentApplicationService paymentApplicationService;
/**
* 获取退货审批列表
* @param query 查询条件
* @return 分页的退货审批DTO列表
*/
public PageDTO<ReturnApprovalDTO> getApprovalList(SearchReturnApprovalQuery<ReturnApprovalEntity> query) { public PageDTO<ReturnApprovalDTO> getApprovalList(SearchReturnApprovalQuery<ReturnApprovalEntity> query) {
Page<ReturnApprovalEntity> page = approvalService.getApprovalList(query); Page<ReturnApprovalEntity> page = approvalService.getApprovalList(query);
List<ReturnApprovalDTO> dtoList = page.getRecords().stream() List<ReturnApprovalDTO> dtoList = page.getRecords().stream()
@ -40,6 +57,11 @@ public class ReturnApprovalApplicationService {
return new PageDTO<>(dtoList, page.getTotal()); return new PageDTO<>(dtoList, page.getTotal());
} }
/**
* 添加退货审批
* @param command 添加退货审批命令
* @return 创建的退货审批模型
*/
public ReturnApprovalModel addApproval(AddReturnApprovalCommand command) { public ReturnApprovalModel addApproval(AddReturnApprovalCommand command) {
ReturnApprovalModel model = modelFactory.create(); ReturnApprovalModel model = modelFactory.create();
model.loadAddCommand(command); model.loadAddCommand(command);
@ -47,12 +69,20 @@ public class ReturnApprovalApplicationService {
return model; return model;
} }
/**
* 更新退货审批信息
* @param command 更新退货审批命令
*/
public void updateApproval(UpdateReturnApprovalCommand command) { public void updateApproval(UpdateReturnApprovalCommand command) {
ReturnApprovalModel model = modelFactory.loadById(command.getApprovalId()); ReturnApprovalModel model = modelFactory.loadById(command.getApprovalId());
model.loadUpdateCommand(command); model.loadUpdateCommand(command);
model.updateById(); model.updateById();
} }
/**
* 批量删除退货审批
* @param command 批量操作命令包含要删除的审批ID列表
*/
public void deleteApproval(BulkOperationCommand<Long> command) { public void deleteApproval(BulkOperationCommand<Long> command) {
for (Long approvalId : command.getIds()) { for (Long approvalId : command.getIds()) {
ReturnApprovalModel model = modelFactory.loadById(approvalId); 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) { public ReturnApprovalEntity submitApproval(AddReturnApprovalCommand command, ShopOrderGoodsEntity orderGoods) {
// 设置商品价格并初始化审批状态 // 设置商品价格并初始化审批状态
command.setGoodsId(orderGoods.getGoodsId()); command.setGoodsId(orderGoods.getGoodsId());
@ -89,4 +180,19 @@ public class ReturnApprovalApplicationService {
Page<ReturnApprovalEntity> page = approvalService.selectApprovalWithGoodsInfo(query); Page<ReturnApprovalEntity> page = approvalService.selectApprovalWithGoodsInfo(query);
return new PageDTO<>(page.getRecords(), page.getTotal()); 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();
}
} }

View File

@ -36,4 +36,14 @@ public class ReturnApprovalModel extends ReturnApprovalEntity {
loadAddCommand(command); loadAddCommand(command);
} }
} }
public void validateApprovalStatus() {
if (getStatus() == null || !isValidStatus(getStatus())) {
throw new RuntimeException("审批状态不合法");
}
}
private boolean isValidStatus(Integer status) {
return !status.equals(2);
}
} }

View File

@ -1,5 +1,7 @@
package com.agileboot.domain.shop.order.model; 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.goods.db.ShopGoodsService;
import com.agileboot.domain.shop.order.db.ShopOrderGoodsEntity; import com.agileboot.domain.shop.order.db.ShopOrderGoodsEntity;
import com.agileboot.domain.shop.order.db.ShopOrderGoodsService; import com.agileboot.domain.shop.order.db.ShopOrderGoodsService;
@ -13,6 +15,14 @@ public class OrderGoodsModelFactory {
private final ShopOrderGoodsService orderGoodsService; private final ShopOrderGoodsService orderGoodsService;
private final ShopGoodsService goodsService; 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) { public OrderGoodsModel create(ShopOrderGoodsEntity entity) {
return new OrderGoodsModel(entity, orderGoodsService, goodsService); return new OrderGoodsModel(entity, orderGoodsService, goodsService);
} }

View File

@ -214,8 +214,9 @@ public class PaymentApplicationService {
if (orderNO.startsWith("wxshop-")) { if (orderNO.startsWith("wxshop-")) {
// 订单号格式为 wxshop-1-time提取中间的订单号 // 订单号格式为 wxshop-1-time提取中间的订单号
String orderId = orderNO.split("-")[1]; String orderId = orderNO.split("-")[1];
OrderModel orderModel = orderModelFactory.loadById(Long.valueOf(orderId)); log.info("退款回调处理成功, 订单号:{}", orderId);
orderModel.handleRefundSuccess(); // OrderModel orderModel = orderModelFactory.loadById(Long.valueOf(orderId));
// orderModel.handleRefundSuccess();
} }
} }
res.set("callback_code", 0); res.set("callback_code", 0);