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_ITEMS_NUMBER_EXCESS = new ErrorCode(1_013_001_005, "归还数量不能大于剩余租借数量!");
|
||||||
ErrorCode RENTAL_RECEIVED_AMOUNT_EXCESS = new ErrorCode(1_013_001_006, "收款金额不能大于押金金额!");
|
ErrorCode RENTAL_RECEIVED_AMOUNT_EXCESS = new ErrorCode(1_013_001_006, "收款金额不能大于押金金额!");
|
||||||
ErrorCode RENTAL_REFUND_AMOUNT_EXCESS = new ErrorCode(1_013_001_007, "退款金额不能大于收款金额!");
|
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 ==========
|
// ========== 项目管理相关 1-014-001-001 ==========
|
||||||
ErrorCode PROJECT_NOT_EXISTS = new ErrorCode(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))
|
.filter(item -> Objects.equals(item.getStatus(), RentalOrderDO.WAITING_FOR_REFUND))
|
||||||
.map(RentalOrderRespVO::getOrderNo)
|
.map(RentalOrderRespVO::getOrderNo)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
// 获取订单号对应的退款申请
|
// 获取订单号对应的退款申请
|
||||||
Map<String, BpmOARefundDTO> refundMap = refundApi.getListByOrderNo(orderNos).getCheckedData();
|
Map<String, BpmOARefundDTO> refundMap = refundApi.getListByOrderNo(orderNos).getCheckedData();
|
||||||
|
|
||||||
if (CollectionUtil.isNotEmpty(refundMap)) {
|
// 设置对应的订单号中的 申请退款和扣款金额
|
||||||
// 设置对应的订单号中的 申请退款和扣款金额
|
pageResult.getList().forEach(item -> {
|
||||||
pageResult.getList().forEach(item -> {
|
|
||||||
if (refundMap.get(item.getOrderNo()) != null) {
|
|
||||||
item.setApplyRefundAmount(refundMap.get(item.getOrderNo()).getRefundAmount());
|
// 设置剩余押金
|
||||||
item.setApplyChargebacksAmount(refundMap.get(item.getOrderNo()).getChargebacksAmount());
|
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);
|
return success(pageResult);
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,9 @@ public class RentalOrderRespVO {
|
|||||||
@Schema(description = "押金金额")
|
@Schema(description = "押金金额")
|
||||||
private BigDecimal depositAmount;
|
private BigDecimal depositAmount;
|
||||||
|
|
||||||
|
@Schema(description = "剩余押金")
|
||||||
|
private BigDecimal remainingDeposit;
|
||||||
|
|
||||||
@Schema(description = "已收金额")
|
@Schema(description = "已收金额")
|
||||||
private BigDecimal receivedAmount;
|
private BigDecimal receivedAmount;
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ public interface RentalOrderMapper extends BaseMapperX<RentalOrderDO> {
|
|||||||
MPJLambdaWrapperX<RentalOrderDO> queryWrapper = new MPJLambdaWrapperX<>();
|
MPJLambdaWrapperX<RentalOrderDO> queryWrapper = new MPJLambdaWrapperX<>();
|
||||||
queryWrapper.selectAll(RentalOrderDO.class);
|
queryWrapper.selectAll(RentalOrderDO.class);
|
||||||
queryWrapper.selectAs(RentalCustomerDO::getName, RentalOrderRespVO::getCustomerName);
|
queryWrapper.selectAs(RentalCustomerDO::getName, RentalOrderRespVO::getCustomerName);
|
||||||
queryWrapper.selectAs("SUM( CASE WHEN deposit.type = 1 THEN deposit.amount END )", RentalOrderRespVO::getReceivedAmount);
|
queryWrapper.selectAs("COALESCE( SUM( CASE WHEN deposit.type = 1 THEN deposit.amount END ), 0 )", RentalOrderRespVO::getReceivedAmount);
|
||||||
queryWrapper.selectAs("SUM( CASE WHEN deposit.type = 2 THEN deposit.amount END )", RentalOrderRespVO::getRefundAmount);
|
queryWrapper.selectAs("COALESCE( SUM( CASE WHEN deposit.type = 2 THEN deposit.amount END ), 0 )", RentalOrderRespVO::getRefundAmount);
|
||||||
queryWrapper.selectAs(AdminUserDO::getNickname, RentalOrderRespVO::getCreatorName);
|
queryWrapper.selectAs(AdminUserDO::getNickname, RentalOrderRespVO::getCreatorName);
|
||||||
queryWrapper.leftJoin(RentalDepositRecordDO.class, "deposit", RentalDepositRecordDO::getOrderNo, RentalOrderDO::getOrderNo);
|
queryWrapper.leftJoin(RentalDepositRecordDO.class, "deposit", RentalDepositRecordDO::getOrderNo, RentalOrderDO::getOrderNo);
|
||||||
queryWrapper.leftJoin(AdminUserDO.class, AdminUserDO::getId, RentalOrderDO::getCreator);
|
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.framework.common.util.object.BeanUtils;
|
||||||
import cn.iocoder.yudao.module.bpm.api.oa.BpmOARefundApi;
|
import cn.iocoder.yudao.module.bpm.api.oa.BpmOARefundApi;
|
||||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
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.RentalDepositAmountReqVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.rental.vo.rentaldepositrecord.RentalDepositRecordPageReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.rental.vo.rentaldepositrecord.RentalDepositRecordPageReqVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.rental.vo.rentaldepositrecord.RentalDepositRecordSaveReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.rental.vo.rentaldepositrecord.RentalDepositRecordSaveReqVO;
|
||||||
@ -46,6 +48,12 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic
|
|||||||
@Resource
|
@Resource
|
||||||
private BpmOARefundApi refundApi;
|
private BpmOARefundApi refundApi;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RentalCustomerService customerService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RentalItemsRecordService itemsRecordService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Long createRentalDepositRecord(RentalDepositRecordSaveReqVO createReqVO) {
|
public Long createRentalDepositRecord(RentalDepositRecordSaveReqVO createReqVO) {
|
||||||
@ -58,6 +66,8 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic
|
|||||||
// 已收金额 - 退款金额
|
// 已收金额 - 退款金额
|
||||||
BigDecimal amount = reqVO.getReceivedAmount().subtract(reqVO.getRefundAmount());
|
BigDecimal amount = reqVO.getReceivedAmount().subtract(reqVO.getRefundAmount());
|
||||||
|
|
||||||
|
// 客户剩余押金 金额
|
||||||
|
BigDecimal customerDepositAmount = amount;
|
||||||
switch (createReqVO.getType()) {
|
switch (createReqVO.getType()) {
|
||||||
case 1:
|
case 1:
|
||||||
// 押金收款
|
// 押金收款
|
||||||
@ -65,6 +75,7 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic
|
|||||||
if (amount.add(createReqVO.getAmount()).compareTo(depositAmount) > 0) {
|
if (amount.add(createReqVO.getAmount()).compareTo(depositAmount) > 0) {
|
||||||
throw exception(RENTAL_RECEIVED_AMOUNT_EXCESS);
|
throw exception(RENTAL_RECEIVED_AMOUNT_EXCESS);
|
||||||
}
|
}
|
||||||
|
customerDepositAmount = amount.add(createReqVO.getAmount());
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
RentalOrderDO updateOrder = new RentalOrderDO();
|
RentalOrderDO updateOrder = new RentalOrderDO();
|
||||||
@ -74,6 +85,13 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic
|
|||||||
if (amount.compareTo(refundAmount) < 0) {
|
if (amount.compareTo(refundAmount) < 0) {
|
||||||
throw exception(RENTAL_REFUND_AMOUNT_EXCESS);
|
throw exception(RENTAL_REFUND_AMOUNT_EXCESS);
|
||||||
} else if (amount.compareTo(refundAmount) == 0) { // 判断当前退款金额 是否等于 实际已收的金额 - 扣款金额时
|
} 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.setOrderNo(createReqVO.getOrderNo());
|
||||||
updateOrder.setStatus(RentalOrderDO.REFUNDED);
|
updateOrder.setStatus(RentalOrderDO.REFUNDED);
|
||||||
@ -82,6 +100,7 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic
|
|||||||
updateOrder.setOrderNo(createReqVO.getOrderNo());
|
updateOrder.setOrderNo(createReqVO.getOrderNo());
|
||||||
updateOrder.setStatus(RentalOrderDO.ON_LEASE);
|
updateOrder.setStatus(RentalOrderDO.ON_LEASE);
|
||||||
}
|
}
|
||||||
|
customerDepositAmount = customerDepositAmount.subtract(refundAmount);
|
||||||
// 同步更新 退款申请流程中的 退款状态
|
// 同步更新 退款申请流程中的 退款状态
|
||||||
refundApi.updateStatus(createReqVO.getOrderNo());
|
refundApi.updateStatus(createReqVO.getOrderNo());
|
||||||
// 同步更新 租赁订单状态
|
// 同步更新 租赁订单状态
|
||||||
@ -95,6 +114,16 @@ public class RentalDepositRecordServiceImpl implements RentalDepositRecordServic
|
|||||||
|
|
||||||
// 更新交易凭证附件 业务编号
|
// 更新交易凭证附件 业务编号
|
||||||
UpdateBusinessFile(rentalDepositRecord);
|
UpdateBusinessFile(rentalDepositRecord);
|
||||||
|
|
||||||
|
// 获取客户编号
|
||||||
|
Long customerId = rentalOrderService.getCustomerIdByOrderNo(createReqVO.getOrderNo());
|
||||||
|
if (customerId != null) {
|
||||||
|
// 同步更新客户剩余押金 金额
|
||||||
|
customerService.updateRentalCustomer(new RentalCustomerSaveReqVO()
|
||||||
|
.setId(customerId)
|
||||||
|
.setAmount(customerDepositAmount));
|
||||||
|
}
|
||||||
|
|
||||||
// 返回
|
// 返回
|
||||||
return rentalDepositRecord.getId();
|
return rentalDepositRecord.getId();
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,11 @@ public class RentalItemsRecordServiceImpl implements RentalItemsRecordService{
|
|||||||
List<RentalItemsCountReqVO> reqVOS = getRentalItemsCount(createReqVO.getOrderNo(), true);
|
List<RentalItemsCountReqVO> reqVOS = getRentalItemsCount(createReqVO.getOrderNo(), true);
|
||||||
Map<Integer, RentalItemsCountReqVO> countMap = convertMap(reqVOS, RentalItemsCountReqVO::getRentalItemsType);
|
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()) {
|
if (createReqVO.getType() == 2 && countMap.get(createReqVO.getRentalItemsType()).getNumber() < createReqVO.getNumber()) {
|
||||||
throw exception(RENTAL_ITEMS_NUMBER_EXCESS);
|
throw exception(RENTAL_ITEMS_NUMBER_EXCESS);
|
||||||
@ -61,6 +66,8 @@ public class RentalItemsRecordServiceImpl implements RentalItemsRecordService{
|
|||||||
List<RentalItemsCountReqVO> reqVOS = getRentalItemsCount(createReqVO.get(0).getOrderNo(), true);
|
List<RentalItemsCountReqVO> reqVOS = getRentalItemsCount(createReqVO.get(0).getOrderNo(), true);
|
||||||
Map<Integer, RentalItemsCountReqVO> countMap = convertMap(reqVOS, RentalItemsCountReqVO::getRentalItemsType);
|
Map<Integer, RentalItemsCountReqVO> countMap = convertMap(reqVOS, RentalItemsCountReqVO::getRentalItemsType);
|
||||||
|
|
||||||
|
// 移除 数量为0的数据
|
||||||
|
createReqVO.removeIf(vo -> vo.getNumber() == 0);
|
||||||
for (RentalItemsRecordSaveReqVO vo : createReqVO) {
|
for (RentalItemsRecordSaveReqVO vo : createReqVO) {
|
||||||
|
|
||||||
// 判断租借类型为归还时,检验归还数量是否大于剩余数量
|
// 判断租借类型为归还时,检验归还数量是否大于剩余数量
|
||||||
|
@ -74,4 +74,11 @@ public interface RentalOrderService {
|
|||||||
* @return 剩余押金金额
|
* @return 剩余押金金额
|
||||||
*/
|
*/
|
||||||
BigDecimal getOrderAmount(String orderNo);
|
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 java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
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;
|
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.RENTAL_ORDER_NOT_EXISTS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,26 +59,35 @@ public class RentalOrderServiceImpl implements RentalOrderService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createRentalOrder(RentalOrderSaveReqVO createReqVO) {
|
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
|
// 新增订单DO
|
||||||
RentalOrderDO rentalOrder = BeanUtils.toBean(createReqVO, RentalOrderDO.class);
|
RentalOrderDO rentalOrder = BeanUtils.toBean(createReqVO, RentalOrderDO.class);
|
||||||
|
|
||||||
// 获取当前日期
|
// 获取当前日期
|
||||||
String now = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
String now = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||||
|
String key = "rental_order_no_" + now;
|
||||||
// 获取分布式锁
|
// 获取分布式锁
|
||||||
String LOCK_KEY = "lock:rental:order:create";
|
String LOCK_KEY = "lock:rental:order:create";
|
||||||
RLock lock = redissonClient.getLock(LOCK_KEY);
|
RLock lock = redissonClient.getLock(LOCK_KEY);
|
||||||
try {
|
try {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
// redis 获取当天订单号
|
// redis 获取当天订单号
|
||||||
String no = stringRedisTemplate.opsForValue().get(now);
|
String no = stringRedisTemplate.opsForValue().get(key);
|
||||||
if (no != null) {
|
if (no != null) {
|
||||||
no = "ZL" + now + String.format("%03d", Integer.parseInt(no) + 1);
|
no = "ZL" + now + String.format("%03d", Integer.parseInt(no) + 1);
|
||||||
// redis 缓存订单号
|
// redis 缓存订单号
|
||||||
stringRedisTemplate.opsForValue().increment(now, 1);
|
stringRedisTemplate.opsForValue().increment(key, 1);
|
||||||
}else {
|
}else {
|
||||||
no = "ZL" + now + String.format("%03d", 1);
|
no = "ZL" + now + String.format("%03d", 1);
|
||||||
// redis 缓存订单号
|
// redis 缓存订单号
|
||||||
stringRedisTemplate.opsForValue().set(now, "1", 1, TimeUnit.DAYS);
|
stringRedisTemplate.opsForValue().set(key, "1", 1, TimeUnit.DAYS);
|
||||||
}
|
}
|
||||||
// 设置订单编号
|
// 设置订单编号
|
||||||
rentalOrder.setOrderNo(no);
|
rentalOrder.setOrderNo(no);
|
||||||
@ -164,4 +174,13 @@ public class RentalOrderServiceImpl implements RentalOrderService {
|
|||||||
|
|
||||||
return rentalOrderMapper.selectOrderAmount(orderNo);
|
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