From be9085e3ac24924673a4c33109cf63c6f0339a16 Mon Sep 17 00:00:00 2001 From: furongxin <419481438@qq.com> Date: Fri, 20 Dec 2024 15:34:20 +0800 Subject: [PATCH] =?UTF-8?q?feat(rental):=20=E4=BC=98=E5=8C=96=E6=8A=BC?= =?UTF-8?q?=E9=87=91=E9=80=80=E8=BF=98=E9=80=BB=E8=BE=91=E5=92=8C=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 完善押金退还逻辑,增加对未归还物品的检查- 更新客户剩余押金金额 - 优化订单列表展示,增加剩余押金字段 - 修复订单号生成逻辑 - 新增根据订单号获取客户ID的功能 --- .../system/enums/ErrorCodeConstants.java | 2 ++ .../admin/rental/RentalOrderController.java | 22 ++++++++------ .../rental/vo/order/RentalOrderRespVO.java | 3 ++ .../dal/mysql/rental/RentalOrderMapper.java | 4 +-- .../RentalDepositRecordServiceImpl.java | 29 +++++++++++++++++++ .../rental/RentalItemsRecordServiceImpl.java | 7 +++++ .../service/rental/RentalOrderService.java | 7 +++++ .../rental/RentalOrderServiceImpl.java | 25 ++++++++++++++-- 8 files changed, 85 insertions(+), 14 deletions(-) diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index 155dc463..9a3180fc 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -280,6 +280,8 @@ public interface ErrorCodeConstants { ErrorCode RENTAL_ITEMS_NUMBER_EXCESS = new ErrorCode(1_013_001_005, "归还数量不能大于剩余租借数量!"); ErrorCode RENTAL_RECEIVED_AMOUNT_EXCESS = new ErrorCode(1_013_001_006, "收款金额不能大于押金金额!"); ErrorCode RENTAL_REFUND_AMOUNT_EXCESS = new ErrorCode(1_013_001_007, "退款金额不能大于收款金额!"); + ErrorCode RENTAL_ITEMS_NOT_REFUND = new ErrorCode(1_013_001_008, "物品还未全部退还,不能全额退款!"); + ErrorCode RENTAL_ORDER_CUSTOMER_EXISTS = new ErrorCode(1_013_001_009, "该客户已存在租赁订单!"); // ========== 项目管理相关 1-014-001-001 ========== ErrorCode PROJECT_NOT_EXISTS = new ErrorCode(1_014_001_001, "项目不存在!"); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/rental/RentalOrderController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/rental/RentalOrderController.java index 84dee273..a5b1c856 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/rental/RentalOrderController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/rental/RentalOrderController.java @@ -111,18 +111,22 @@ public class RentalOrderController { .filter(item -> Objects.equals(item.getStatus(), RentalOrderDO.WAITING_FOR_REFUND)) .map(RentalOrderRespVO::getOrderNo) .collect(Collectors.toList()); + // 获取订单号对应的退款申请 Map refundMap = refundApi.getListByOrderNo(orderNos).getCheckedData(); - if (CollectionUtil.isNotEmpty(refundMap)) { - // 设置对应的订单号中的 申请退款和扣款金额 - pageResult.getList().forEach(item -> { - if (refundMap.get(item.getOrderNo()) != null) { - item.setApplyRefundAmount(refundMap.get(item.getOrderNo()).getRefundAmount()); - item.setApplyChargebacksAmount(refundMap.get(item.getOrderNo()).getChargebacksAmount()); - } - }); - } + // 设置对应的订单号中的 申请退款和扣款金额 + pageResult.getList().forEach(item -> { + + + // 设置剩余押金 + item.setRemainingDeposit(item.getReceivedAmount().subtract(item.getRefundAmount().add(item.getChargebacksAmount()))); + + if (CollectionUtil.isNotEmpty(refundMap) && refundMap.get(item.getOrderNo()) != null) { + item.setApplyRefundAmount(refundMap.get(item.getOrderNo()).getRefundAmount()); + item.setApplyChargebacksAmount(refundMap.get(item.getOrderNo()).getChargebacksAmount()); + } + }); return success(pageResult); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/rental/vo/order/RentalOrderRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/rental/vo/order/RentalOrderRespVO.java index faa81133..8405e77e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/rental/vo/order/RentalOrderRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/rental/vo/order/RentalOrderRespVO.java @@ -34,6 +34,9 @@ public class RentalOrderRespVO { @Schema(description = "押金金额") private BigDecimal depositAmount; + @Schema(description = "剩余押金") + private BigDecimal remainingDeposit; + @Schema(description = "已收金额") private BigDecimal receivedAmount; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/rental/RentalOrderMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/rental/RentalOrderMapper.java index bfc9cd2b..d62779a9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/rental/RentalOrderMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/rental/RentalOrderMapper.java @@ -27,8 +27,8 @@ public interface RentalOrderMapper extends BaseMapperX { MPJLambdaWrapperX queryWrapper = new MPJLambdaWrapperX<>(); queryWrapper.selectAll(RentalOrderDO.class); queryWrapper.selectAs(RentalCustomerDO::getName, RentalOrderRespVO::getCustomerName); - queryWrapper.selectAs("SUM( CASE WHEN deposit.type = 1 THEN deposit.amount END )", RentalOrderRespVO::getReceivedAmount); - queryWrapper.selectAs("SUM( CASE WHEN deposit.type = 2 THEN deposit.amount END )", RentalOrderRespVO::getRefundAmount); + queryWrapper.selectAs("COALESCE( SUM( CASE WHEN deposit.type = 1 THEN deposit.amount END ), 0 )", RentalOrderRespVO::getReceivedAmount); + queryWrapper.selectAs("COALESCE( SUM( CASE WHEN deposit.type = 2 THEN deposit.amount END ), 0 )", RentalOrderRespVO::getRefundAmount); queryWrapper.selectAs(AdminUserDO::getNickname, RentalOrderRespVO::getCreatorName); queryWrapper.leftJoin(RentalDepositRecordDO.class, "deposit", RentalDepositRecordDO::getOrderNo, RentalOrderDO::getOrderNo); queryWrapper.leftJoin(AdminUserDO.class, AdminUserDO::getId, RentalOrderDO::getCreator); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalDepositRecordServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalDepositRecordServiceImpl.java index 1704780c..538f158b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalDepositRecordServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalDepositRecordServiceImpl.java @@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.bpm.api.oa.BpmOARefundApi; import cn.iocoder.yudao.module.infra.api.file.FileApi; +import cn.iocoder.yudao.module.system.controller.admin.rental.vo.customer.RentalCustomerSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.rental.vo.itemsrecord.RentalItemsCountReqVO; import cn.iocoder.yudao.module.system.controller.admin.rental.vo.rentaldepositrecord.RentalDepositAmountReqVO; import cn.iocoder.yudao.module.system.controller.admin.rental.vo.rentaldepositrecord.RentalDepositRecordPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.rental.vo.rentaldepositrecord.RentalDepositRecordSaveReqVO; @@ -46,6 +48,12 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic @Resource private BpmOARefundApi refundApi; + @Resource + private RentalCustomerService customerService; + + @Resource + private RentalItemsRecordService itemsRecordService; + @Override @Transactional(rollbackFor = Exception.class) public Long createRentalDepositRecord(RentalDepositRecordSaveReqVO createReqVO) { @@ -58,6 +66,8 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic // 已收金额 - 退款金额 BigDecimal amount = reqVO.getReceivedAmount().subtract(reqVO.getRefundAmount()); + // 客户剩余押金 金额 + BigDecimal customerDepositAmount = amount; switch (createReqVO.getType()) { case 1: // 押金收款 @@ -65,6 +75,7 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic if (amount.add(createReqVO.getAmount()).compareTo(depositAmount) > 0) { throw exception(RENTAL_RECEIVED_AMOUNT_EXCESS); } + customerDepositAmount = amount.add(createReqVO.getAmount()); break; case 2: RentalOrderDO updateOrder = new RentalOrderDO(); @@ -74,6 +85,13 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic if (amount.compareTo(refundAmount) < 0) { throw exception(RENTAL_REFUND_AMOUNT_EXCESS); } else if (amount.compareTo(refundAmount) == 0) { // 判断当前退款金额 是否等于 实际已收的金额 - 扣款金额时 + // 获取租赁物品信息 + List itemList = itemsRecordService.getRentalItemsCount(createReqVO.getOrderNo(), false); + // 判断租赁物品是否已经归还完毕 + boolean isReturned = itemList.stream().allMatch(item -> item.getNumber() == 0); + if (!isReturned) { + throw exception(RENTAL_ITEMS_NOT_REFUND); + } // 更新订单状态为 已退款 updateOrder.setOrderNo(createReqVO.getOrderNo()); updateOrder.setStatus(RentalOrderDO.REFUNDED); @@ -82,6 +100,7 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic updateOrder.setOrderNo(createReqVO.getOrderNo()); updateOrder.setStatus(RentalOrderDO.ON_LEASE); } + customerDepositAmount = customerDepositAmount.subtract(refundAmount); // 同步更新 退款申请流程中的 退款状态 refundApi.updateStatus(createReqVO.getOrderNo()); // 同步更新 租赁订单状态 @@ -95,6 +114,16 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic // 更新交易凭证附件 业务编号 UpdateBusinessFile(rentalDepositRecord); + + // 获取客户编号 + Long customerId = rentalOrderService.getCustomerIdByOrderNo(createReqVO.getOrderNo()); + if (customerId != null) { + // 同步更新客户剩余押金 金额 + customerService.updateRentalCustomer(new RentalCustomerSaveReqVO() + .setId(customerId) + .setAmount(customerDepositAmount)); + } + // 返回 return rentalDepositRecord.getId(); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalItemsRecordServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalItemsRecordServiceImpl.java index 0bfcab9f..73fadd55 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalItemsRecordServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalItemsRecordServiceImpl.java @@ -42,6 +42,11 @@ public class RentalItemsRecordServiceImpl implements RentalItemsRecordService{ List reqVOS = getRentalItemsCount(createReqVO.getOrderNo(), true); Map countMap = convertMap(reqVOS, RentalItemsCountReqVO::getRentalItemsType); + // 如果数量为0 则跳过 + if (createReqVO.getNumber() == 0) { + return 0L; + } + // 判断租借类型为归还时,检验归还数量是否大于剩余数量 if (createReqVO.getType() == 2 && countMap.get(createReqVO.getRentalItemsType()).getNumber() < createReqVO.getNumber()) { throw exception(RENTAL_ITEMS_NUMBER_EXCESS); @@ -61,6 +66,8 @@ public class RentalItemsRecordServiceImpl implements RentalItemsRecordService{ List reqVOS = getRentalItemsCount(createReqVO.get(0).getOrderNo(), true); Map countMap = convertMap(reqVOS, RentalItemsCountReqVO::getRentalItemsType); + // 移除 数量为0的数据 + createReqVO.removeIf(vo -> vo.getNumber() == 0); for (RentalItemsRecordSaveReqVO vo : createReqVO) { // 判断租借类型为归还时,检验归还数量是否大于剩余数量 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalOrderService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalOrderService.java index a27348a6..32010b70 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalOrderService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalOrderService.java @@ -74,4 +74,11 @@ public interface RentalOrderService { * @return 剩余押金金额 */ BigDecimal getOrderAmount(String orderNo); + + /** + * 根据订单号获取客户id + * @param orderNo 订单号 + * @return 客户id + */ + Long getCustomerIdByOrderNo(String orderNo); } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalOrderServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalOrderServiceImpl.java index 5145839b..355f8570 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalOrderServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/rental/RentalOrderServiceImpl.java @@ -27,6 +27,7 @@ import java.time.format.DateTimeFormatter; import java.util.concurrent.TimeUnit; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.RENTAL_ORDER_CUSTOMER_EXISTS; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.RENTAL_ORDER_NOT_EXISTS; /** @@ -58,26 +59,35 @@ public class RentalOrderServiceImpl implements RentalOrderService { @Override public Long createRentalOrder(RentalOrderSaveReqVO createReqVO) { + // 检验当前客户是否已存在订单 + Long count = rentalOrderMapper.selectCount(new LambdaQueryWrapperX() + .eq(RentalOrderDO::getCustomerId, createReqVO.getCustomerId()) + .ne(RentalOrderDO::getStatus, 4)); + if (count > 0L) { + throw exception(RENTAL_ORDER_CUSTOMER_EXISTS); + } + // 新增订单DO RentalOrderDO rentalOrder = BeanUtils.toBean(createReqVO, RentalOrderDO.class); // 获取当前日期 String now = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); + String key = "rental_order_no_" + now; // 获取分布式锁 String LOCK_KEY = "lock:rental:order:create"; RLock lock = redissonClient.getLock(LOCK_KEY); try { lock.lock(); // redis 获取当天订单号 - String no = stringRedisTemplate.opsForValue().get(now); + String no = stringRedisTemplate.opsForValue().get(key); if (no != null) { no = "ZL" + now + String.format("%03d", Integer.parseInt(no) + 1); // redis 缓存订单号 - stringRedisTemplate.opsForValue().increment(now, 1); + stringRedisTemplate.opsForValue().increment(key, 1); }else { no = "ZL" + now + String.format("%03d", 1); // redis 缓存订单号 - stringRedisTemplate.opsForValue().set(now, "1", 1, TimeUnit.DAYS); + stringRedisTemplate.opsForValue().set(key, "1", 1, TimeUnit.DAYS); } // 设置订单编号 rentalOrder.setOrderNo(no); @@ -164,4 +174,13 @@ public class RentalOrderServiceImpl implements RentalOrderService { return rentalOrderMapper.selectOrderAmount(orderNo); } + + @Override + public Long getCustomerIdByOrderNo(String orderNo) { + RentalOrderDO orderDO = rentalOrderMapper.selectOne(RentalOrderDO::getOrderNo, orderNo); + if (orderDO != null) { + return orderDO.getCustomerId(); + } + return null; + } } \ No newline at end of file