feat(rental): 优化押金退还逻辑和订单相关功能
- 完善押金退还逻辑,增加对未归还物品的检查- 更新客户剩余押金金额 - 优化订单列表展示,增加剩余押金字段 - 修复订单号生成逻辑 - 新增根据订单号获取客户ID的功能
This commit is contained in:
parent
24ab5dd06a
commit
be9085e3ac
@ -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, "项目不存在!");
|
||||
|
@ -111,18 +111,22 @@ public class RentalOrderController {
|
||||
.filter(item -> Objects.equals(item.getStatus(), RentalOrderDO.WAITING_FOR_REFUND))
|
||||
.map(RentalOrderRespVO::getOrderNo)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 获取订单号对应的退款申请
|
||||
Map<String, BpmOARefundDTO> refundMap = refundApi.getListByOrderNo(orderNos).getCheckedData();
|
||||
|
||||
if (CollectionUtil.isNotEmpty(refundMap)) {
|
||||
// 设置对应的订单号中的 申请退款和扣款金额
|
||||
pageResult.getList().forEach(item -> {
|
||||
if (refundMap.get(item.getOrderNo()) != null) {
|
||||
|
||||
|
||||
// 设置剩余押金
|
||||
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);
|
||||
}
|
||||
|
@ -34,6 +34,9 @@ public class RentalOrderRespVO {
|
||||
@Schema(description = "押金金额")
|
||||
private BigDecimal depositAmount;
|
||||
|
||||
@Schema(description = "剩余押金")
|
||||
private BigDecimal remainingDeposit;
|
||||
|
||||
@Schema(description = "已收金额")
|
||||
private BigDecimal receivedAmount;
|
||||
|
||||
|
@ -27,8 +27,8 @@ public interface RentalOrderMapper extends BaseMapperX<RentalOrderDO> {
|
||||
MPJLambdaWrapperX<RentalOrderDO> 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);
|
||||
|
@ -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<RentalItemsCountReqVO> 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();
|
||||
}
|
||||
|
@ -42,6 +42,11 @@ public class RentalItemsRecordServiceImpl implements RentalItemsRecordService{
|
||||
List<RentalItemsCountReqVO> reqVOS = getRentalItemsCount(createReqVO.getOrderNo(), true);
|
||||
Map<Integer, RentalItemsCountReqVO> 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<RentalItemsCountReqVO> reqVOS = getRentalItemsCount(createReqVO.get(0).getOrderNo(), true);
|
||||
Map<Integer, RentalItemsCountReqVO> countMap = convertMap(reqVOS, RentalItemsCountReqVO::getRentalItemsType);
|
||||
|
||||
// 移除 数量为0的数据
|
||||
createReqVO.removeIf(vo -> vo.getNumber() == 0);
|
||||
for (RentalItemsRecordSaveReqVO vo : createReqVO) {
|
||||
|
||||
// 判断租借类型为归还时,检验归还数量是否大于剩余数量
|
||||
|
@ -74,4 +74,11 @@ public interface RentalOrderService {
|
||||
* @return 剩余押金金额
|
||||
*/
|
||||
BigDecimal getOrderAmount(String orderNo);
|
||||
|
||||
/**
|
||||
* 根据订单号获取客户id
|
||||
* @param orderNo 订单号
|
||||
* @return 客户id
|
||||
*/
|
||||
Long getCustomerIdByOrderNo(String orderNo);
|
||||
}
|
@ -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<RentalOrderDO>()
|
||||
.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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user