diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/device/utils/DeviceUtil.java b/ruoyi-service/src/main/java/com/ruoyi/bst/device/utils/DeviceUtil.java index 57b9db9..5bfd97c 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/device/utils/DeviceUtil.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/device/utils/DeviceUtil.java @@ -205,4 +205,11 @@ public class DeviceUtil { device.setOnlineStatus(DeviceOnlineStatus.ONLINE.getStatus()); device.setLastOnlineTime(at); } + + /** + * 车辆是否离线 + */ + public static boolean isOffline(DeviceVO device) { + return device != null && device.getOnlineStatus() != null && DeviceOnlineStatus.OFFLINE.getStatus().equals(device.getOnlineStatus()); + } } \ No newline at end of file diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/Order.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/Order.java index 342a626..0f63637 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/Order.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/Order.java @@ -206,4 +206,24 @@ public class Order extends BaseEntity { @ApiModelProperty("实收车损费") private BigDecimal actualDeductionFee; + @Excel(name = "套餐是否自动押金抵扣") + @ApiModelProperty("套餐是否自动押金抵扣") + private Boolean suitDepositDeduction; + + @Excel(name = "订单版本号") + @ApiModelProperty("订单版本号") + private Integer version; + + @Excel(name = "支付方式") + @ApiModelProperty("支付方式(1押金抵扣 2用户支付)") + private String payType; + + @Excel(name = "押金抵扣金额") + @ApiModelProperty("押金抵扣金额") + private BigDecimal depositDeductionAmount; + + @Excel(name = "骑行支付ID") + @ApiModelProperty("骑行支付ID") + private Long ridePayId; + } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/OrderQuery.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/OrderQuery.java index e6a930b..6a4d0fa 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/OrderQuery.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/OrderQuery.java @@ -58,4 +58,7 @@ public class OrderQuery extends OrderVO { @ApiModelProperty("结束日期范围") @DateTimeFormat(pattern = "yyyy-MM-dd") private List endDateRange; + + @ApiModelProperty("是否为空支付类型") + private Boolean isNullPayType; } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/OrderVO.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/OrderVO.java index fe9a6e6..ac482c2 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/OrderVO.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/OrderVO.java @@ -75,6 +75,10 @@ public class OrderVO extends Order implements IotDevice { @ApiModelProperty("实收金额") private BigDecimal actualAmount; + // 剩余可抵扣押金 + @ApiModelProperty("剩余可抵扣押金") + private BigDecimal depositDeductRemain; + @Override public String mac() { return this.deviceMac; diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/bo/OrderRidePaySuccessBO.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/bo/OrderRidePaySuccessBO.java new file mode 100644 index 0000000..fed5c89 --- /dev/null +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/bo/OrderRidePaySuccessBO.java @@ -0,0 +1,24 @@ +package com.ruoyi.bst.order.domain.bo; + +import java.math.BigDecimal; + +import com.ruoyi.bst.order.domain.OrderVO; +import com.ruoyi.bst.order.domain.enums.OrderPayType; + +import lombok.Data; + +@Data +public class OrderRidePaySuccessBO { + + // 订单数据 + private OrderVO order; + + // 支付方式 + private OrderPayType payType; + + // 支付/抵扣金额 + private BigDecimal payAmount; + + // 是否需要审核 + private Boolean needVerify; +} diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/dto/OrderDeductDTO.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/dto/OrderDeductDTO.java new file mode 100644 index 0000000..48fbb40 --- /dev/null +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/dto/OrderDeductDTO.java @@ -0,0 +1,32 @@ +package com.ruoyi.bst.order.domain.dto; + +import java.math.BigDecimal; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 押金抵扣DTO + */ +@Data +public class OrderDeductDTO { + + @ApiModelProperty("订单ID") + @NotNull(message = "订单ID不能为空") + private Long id; + + @ApiModelProperty("抵扣金额") + @NotNull(message = "抵扣金额不能为空") + @Min(value = 0, message = "抵扣金额不能小于0") + private BigDecimal amount; + + @ApiModelProperty("是否需要审核") + private Boolean needVerify; + + @ApiModelProperty("当可抵扣金额不足时,是否减少抵扣金额") + private Boolean reduceAmountWhenNotEnough; + +} diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/enums/OrderPayType.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/enums/OrderPayType.java new file mode 100644 index 0000000..c106673 --- /dev/null +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/enums/OrderPayType.java @@ -0,0 +1,16 @@ +package com.ruoyi.bst.order.domain.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum OrderPayType { + + DEPOSIT_DEDUCTION("1", "押金抵扣"), + USER_PAY("2", "用户支付"); + + private String code; + private String name; + +} diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/enums/OrderStatus.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/enums/OrderStatus.java index 981c6dd..9d5d749 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/enums/OrderStatus.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/enums/OrderStatus.java @@ -11,11 +11,12 @@ import lombok.Getter; @AllArgsConstructor public enum OrderStatus { - WAIT_PAY("WAIT_PAY", "待支付"), + WAIT_PAY("WAIT_PAY", "押金待支付"), PROCESSING("PROCESSING", "进行中"), FINISHED("FINISHED", "已结束"), CANCELED("CANCELED", "已取消"), WAIT_VERIFY("WAIT_VERIFY", "待审核"), + RIDE_WAIT_PAY("RIDE_WAIT_PAY", "骑行费待支付"), REJECTED("REJECTED", "已驳回"), REFUNDED("REFUNDED", "已退款"); @@ -72,4 +73,14 @@ public enum OrderStatus { public static List finishedList() { return CollectionUtils.map(OrderStatus::getCode, FINISHED, WAIT_VERIFY, REJECTED, REFUNDED); } + + // 允许押金抵扣的订单状态 + public static List canDeduct() { + return CollectionUtils.map(OrderStatus::getCode, RIDE_WAIT_PAY); + } + + // 允许骑行支付成功的订单状态 + public static List canRidePaySuccess() { + return CollectionUtils.map(OrderStatus::getCode, RIDE_WAIT_PAY); + } } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/mapper/OrderMapper.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/mapper/OrderMapper.java index 42c5795..2fccd6c 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/mapper/OrderMapper.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/mapper/OrderMapper.java @@ -219,4 +219,11 @@ public interface OrderMapper { */ BigDecimal selectSumOfActualTotalAmount(@Param("query") OrderQuery query); + /** + * 押金抵扣 + * @param id + * @param amount + */ + int deductDeposit(@Param("id") Long id, @Param("amount") BigDecimal amount); + } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/mapper/OrderMapper.xml b/ruoyi-service/src/main/java/com/ruoyi/bst/order/mapper/OrderMapper.xml index 0118146..76d41ab 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/mapper/OrderMapper.xml +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/mapper/OrderMapper.xml @@ -60,7 +60,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" bo.actual_dispatch_fee, bo.actual_manage_fee, bo.actual_deduction_fee, + bo.suit_deposit_deduction, + bo.version, + bo.pay_type, + bo.deposit_deduction_amount, + bo.ride_pay_id, as actual_amount, + as deposit_deduct_remain, ba.name as area_name, su.nick_name as user_name, su.user_name as user_phone, @@ -140,6 +146,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and bp.channel_id = #{query.payChannelId} and bo.pay_expire_time <= #{query.payExpireTimeEnd} and bo.pay_expire_time >= #{query.payExpireTimeStart} + and bo.suit_deposit_deduction = #{query.suitDepositDeduction} + and bo.version = #{query.version} + and bo.pay_type = #{query.payType} + and bo.pay_type is not null and bo.id in ( select distinct bb.bst_id from bst_bonus bb @@ -249,6 +259,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" actual_dispatch_fee, actual_manage_fee, actual_deduction_fee, + suit_deposit_deduction, + version, + pay_type, + deposit_deduction_amount, + ride_pay_id, #{no}, @@ -295,6 +310,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{actualDispatchFee}, #{actualManageFee}, #{actualDeductionFee}, + #{suitDepositDeduction}, + #{version}, + #{payType}, + #{depositDeductionAmount}, + #{ridePayId}, @@ -351,6 +371,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" actual_dispatch_fee = #{data.actualDispatchFee}, actual_manage_fee = #{data.actualManageFee}, actual_deduction_fee = #{data.actualDeductionFee}, + suit_deposit_deduction = #{data.suitDepositDeduction}, + version = #{data.version}, + pay_type = #{data.payType}, + deposit_deduction_amount = #{data.depositDeductionAmount}, + ride_pay_id = #{data.ridePayId}, @@ -483,16 +508,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - - - - update bst_order bo - set bo.deduction_fee = bo.deduction_fee + #{deductionFee}, - bo.actual_deduction_fee = bo.actual_deduction_fee + #{deductionFee}, - bo.total_fee = bo.total_fee + #{deductionFee} - where bo.id = #{id} and bo.total_fee + #{deductionFee} <= bo.deposit_fee - - + + + update bst_order bo + left join bst_pay bp on bp.id = bo.pay_id + set bo.deposit_deduction_amount = bo.deposit_deduction_amount + #{amount} + where bo.id = #{id} + and >= #{amount} + + + + + bp.amount - IFNULL(bp.refunding, 0) - IFNULL(bp.refunded, 0) - IFNULL(bo.deposit_deduction_amount, 0) - IFNULL(bo.actual_deduction_fee, 0) + + + + + update bst_order bo + set bo.deduction_fee = bo.deduction_fee + #{deductionFee}, + bo.actual_deduction_fee = bo.actual_deduction_fee + #{deductionFee}, + bo.total_fee = bo.total_fee + #{deductionFee} + where bo.id = #{id} + and >= #{deductionFee} + + diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderService.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderService.java index 82e3c3c..9aa2ff8 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderService.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/OrderService.java @@ -11,6 +11,7 @@ import com.ruoyi.bst.order.domain.dto.OrderCalcFeeDTO; import com.ruoyi.bst.order.domain.dto.OrderChangeDeviceDTO; import com.ruoyi.bst.order.domain.dto.OrderCloseDeviceDTO; import com.ruoyi.bst.order.domain.dto.OrderCreateDTO; +import com.ruoyi.bst.order.domain.dto.OrderDeductDTO; import com.ruoyi.bst.order.domain.dto.OrderEndDTO; import com.ruoyi.bst.order.domain.dto.OrderOpenDeviceDTO; import com.ruoyi.bst.order.domain.dto.OrderRefundDTO; @@ -209,4 +210,13 @@ public interface OrderService { * @param distance 距离 */ public int updateDisatance(Long id, BigDecimal distance); + + /** + * 押金抵扣 + * + * @param dto 参数 + * @return 结果 + */ + public int deduct(OrderDeductDTO dto); + } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderConverterImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderConverterImpl.java index 1830abf..8b1a1d9 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderConverterImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderConverterImpl.java @@ -219,6 +219,7 @@ public class OrderConverterImpl implements OrderConverter{ Order order = new Order(); // 基础信息 order.setPayExpireTime(LocalDateTime.now().plusMinutes(3)); + order.setVersion(2); // 用户信息 UserVO user = bo.getUser(); @@ -247,6 +248,7 @@ public class OrderConverterImpl implements OrderConverter{ order.setSuitStartRule(suit.getStartRule()); order.setSuitIntervalRule(suit.getIntervalRule()); order.setSuitSeconds(suit.getSeconds()); + order.setSuitDepositDeduction(suit.getDepositDeduction()); } // 价格信息 @@ -337,9 +339,6 @@ public class OrderConverterImpl implements OrderConverter{ data.setReturnType(order.getReturnType()); data.setEndAreaSubName(order.getEndAreaSubName()); data.setEndReason(order.getEndReason()); - data.setActualRidingFee(order.getActualRidingFee()); - data.setActualDispatchFee(order.getActualDispatchFee()); - data.setActualManageFee(order.getActualManageFee()); return data; } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java index 9df764f..1773a3f 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderServiceImpl.java @@ -41,14 +41,17 @@ import com.ruoyi.bst.order.domain.OrderVO; import com.ruoyi.bst.order.domain.bo.OrderChangeBO; import com.ruoyi.bst.order.domain.bo.OrderCreateBO; import com.ruoyi.bst.order.domain.bo.OrderEndBO; +import com.ruoyi.bst.order.domain.bo.OrderRidePaySuccessBO; import com.ruoyi.bst.order.domain.dto.OrderCalcFeeDTO; import com.ruoyi.bst.order.domain.dto.OrderChangeDeviceDTO; import com.ruoyi.bst.order.domain.dto.OrderCloseDeviceDTO; import com.ruoyi.bst.order.domain.dto.OrderCreateDTO; +import com.ruoyi.bst.order.domain.dto.OrderDeductDTO; import com.ruoyi.bst.order.domain.dto.OrderEndDTO; import com.ruoyi.bst.order.domain.dto.OrderOpenDeviceDTO; import com.ruoyi.bst.order.domain.dto.OrderRefundDTO; import com.ruoyi.bst.order.domain.dto.OrderVerifyDTO; +import com.ruoyi.bst.order.domain.enums.OrderPayType; import com.ruoyi.bst.order.domain.enums.OrderReturnType; import com.ruoyi.bst.order.domain.enums.OrderStatus; import com.ruoyi.bst.order.domain.vo.OrderEndVO; @@ -427,15 +430,14 @@ public class OrderServiceImpl implements OrderService { order.setDuration(Duration.between(order.getStartTime(), order.getEndTime()).getSeconds()); order.setDistance(LocationLogUtil.calcDistance(bo.getPositionList())); order.setEndReason(dto.getEndReason()); - // 还车类型 order.setReturnType(returnType); - // 订单状态 - this.setOrderStatus(order, returnType); + order.setStatus(OrderStatus.RIDE_WAIT_PAY.getCode()); + // 订单费用 boolean needDispatchFee = dto.getNeedDispatchFee() != null && dto.getNeedDispatchFee(); this.setOrderFee(order, area, inParkingVO, needDispatchFee); - Integer result = transactionTemplate.execute(status -> { + transactionTemplate.execute(status -> { // 更新订单数据 Order data = orderConverter.toPOByEnd(order); OrderQuery query = new OrderQuery(); @@ -445,16 +447,6 @@ public class OrderServiceImpl implements OrderService { ServiceUtil.assertion(rows != 1, "ID为%s的订单更新失败", order.getId()); vo.setDb(rows); - // 当订单状态为已完成时,处理订单完成操作 - if (OrderStatus.FINISHED.getCode().equals(order.getStatus())) { - // 预分成 - boolean bonus = this.prepayBonus(order.getId()); - ServiceUtil.assertion(!bonus, "ID为%s的订单预分成失败", order.getId()); - } else if (OrderStatus.WAIT_VERIFY.getCode().equals(order.getStatus())) { - // 发送还车审核通知 - smsService.sendOrderWaitVerifyMsg(order); - } - // 结束订单设备 int finish = orderDeviceService.finish(orderDevice, dto.getPicture(), inParkingVO); ServiceUtil.assertion(finish != 1, "结束ID为%s的订单设备失败", orderDevice.getId()); @@ -468,14 +460,26 @@ public class OrderServiceImpl implements OrderService { return rows; }); - boolean isSuccess = result != null && result == 1; - if (isSuccess && OrderStatus.FINISHED.getCode().equals(order.getStatus())) { - this.handleFinished(order); + if (order.getSuitDepositDeduction() != null && order.getSuitDepositDeduction()) { + this.autoDeduct(order); } return vo; } + /** + * 自动押金抵扣 + * @param order + */ + private int autoDeduct(OrderVO order) { + OrderDeductDTO dto = new OrderDeductDTO(); + dto.setId(order.getId()); + dto.setAmount(order.getTotalFee()); + dto.setNeedVerify(true); + dto.setReduceAmountWhenNotEnough(true); + return this.deduct(dto); + } + /** * 设置日志参数 * @param lon 手机定位经度 @@ -501,8 +505,8 @@ public class OrderServiceImpl implements OrderService { device.setLocationType(DeviceLocationType.PHONE.getCode()); device.setLastLocationTime(LocalDateTime.now()); - // 若卫星信号弱,则更新设备定位 - if (DeviceUtil.isLowSatelliteSignal(device)) { + // 若卫星信号弱或者车辆离线,则更新设备定位 + if (DeviceUtil.isLowSatelliteSignal(device) || DeviceUtil.isOffline(device)) { Device data = new Device(); data.setMac(device.getMac()); data.setLongitude(device.getLongitude()); @@ -530,23 +534,13 @@ public class OrderServiceImpl implements OrderService { // 处理订单完成 private void handleFinished(OrderVO order) { - scheduledExecutorService.schedule(() -> { - int refund = this.refundRemainAmount(order); - ServiceUtil.assertion(refund != 1, "ID为%s的订单退还剩余金额失败", order.getId()); - }, 60, TimeUnit.SECONDS); - } + // 预分成 + boolean bonus = this.prepayBonus(order.getId()); + ServiceUtil.assertion(!bonus, "ID为%s的订单预分成失败", order.getId()); - // 设置订单状态 - private void setOrderStatus(OrderVO order, String returnType) { - // 根据是否需要审核,设置订单状态 - if (order.getAreaReturnVerify() != null && order.getAreaReturnVerify() - && OrderReturnType.needVerify().contains(returnType)) { - // 更新订单状态为待审核 - order.setStatus(OrderStatus.WAIT_VERIFY.getCode()); - } else { - // 更新订单状态为已完成 - order.setStatus(OrderStatus.FINISHED.getCode()); - } + // 剩余金额退款 + int refund = this.refundRemainAmount(order); + ServiceUtil.assertion(refund != 1, "ID为%s的订单退还剩余金额失败", order.getId()); } // 设置订单费用 @@ -556,9 +550,12 @@ public class OrderServiceImpl implements OrderService { order.setDispatchFee(orderFee.getDispatchFee()); order.setRidingFee(orderFee.getRidingFee()); order.setTotalFee(orderFee.getTotalFee()); + } + // 设置订单实收金额 + private void setActualAmount(Order order, BigDecimal payAmount) { // 实收金额 - BigDecimal remain = order.getPayedAmount(); + BigDecimal remain = payAmount; // 骑行费实收 order.setActualRidingFee(MathUtils.min(remain, order.getRidingFee())); remain = MathUtils.subtractDecimal(remain, order.getActualRidingFee()); @@ -574,8 +571,8 @@ public class OrderServiceImpl implements OrderService { return 0; } // 订单剩余金额退款 - // 退款金额 = 实付金额 - 实收金额 - BigDecimal refund = MathUtils.subtractDecimal(order.getPayedAmount(), order.getTotalFee()); + // 退款金额 = 押金支付金额 - 押金抵扣金额 - 车损费 + BigDecimal refund = MathUtils.subtractDecimal(order.getPayedAmount(), order.getDepositDeductionAmount(), order.getDeductionFee()); if (refund != null && refund.compareTo(BigDecimal.ZERO) > 0) { return this.refund(order, refund, null, null, "系统", RefundType.AUTO.getCode()); } @@ -584,13 +581,14 @@ public class OrderServiceImpl implements OrderService { } /** - * 退款 + * 押金退款 * * @param order 订单 * @param amount 退款金额 * @param reason 退款原因 * @param userId 操作人ID * @param userName 操作人名称 + * @param type 退款类型 * @return 结果 */ private int refund(OrderVO order, BigDecimal amount, String reason, Long userId, String userName, String type) { @@ -617,9 +615,11 @@ public class OrderServiceImpl implements OrderService { Integer result = transactionTemplate.execute(status -> { // 分成退款 - boolean bonusRefund = bonusService.refundByBst(BonusBstType.ORDER, order.getId(), amount, - order.getPayAmount(), finalRefundReason); - ServiceUtil.assertion(!bonusRefund, "ID为%s的订单分成退款失败", order.getId()); + if (RefundType.ADMIN.getCode().equals(type)) { + boolean bonusRefund = bonusService.refundByBst(BonusBstType.ORDER, order.getId(), amount, + order.getPayAmount(), finalRefundReason); + ServiceUtil.assertion(!bonusRefund, "ID为%s的订单分成退款失败", order.getId()); + } // 支付退款 PayRefundDTO dto = new PayRefundDTO(); @@ -832,7 +832,7 @@ public class OrderServiceImpl implements OrderService { Integer result = transactionTemplate.execute(status -> { // 更新订单状态 Order data = new Order(); - data.setStatus(pass ? OrderStatus.FINISHED.getCode() : OrderStatus.REJECTED.getCode()); + data.setStatus(OrderStatus.FINISHED.getCode()); data.setVerifyRemark(dto.getRemark()); OrderQuery query = new OrderQuery(); query.setId(dto.getId()); @@ -842,24 +842,21 @@ public class OrderServiceImpl implements OrderService { // 更新车损费 if (dto.getDeductionFee() != null && dto.getDeductionFee().compareTo(BigDecimal.ZERO) > 0) { - BigDecimal max = MathUtils.subtractDecimal(order.getDepositFee(), order.getTotalFee()); + BigDecimal max = OrderUtil.calcRemainCanDeductDeposit(order); ServiceUtil.assertion(MathUtils.biggerThan(dto.getDeductionFee(), max), "ID为%s的订单车损费不允许超过%s", dto.getId(), max); int add = orderMapper.addDeductionFee(order.getId(), dto.getDeductionFee()); ServiceUtil.assertion(add != 1, "ID为%s的订单增加车损费失败,请刷新后重试", order.getId()); } - // 预分成 - boolean bonus = this.prepayBonus(dto.getId()); - ServiceUtil.assertion(!bonus, "ID为%s的订单预分成失败", order.getId()); + // 订单结束操作 + if (pass) { + this.handleFinished(order); + } return rows; }); - // 若审核通过,则退还剩余金额 - if (pass && result != null && result > 0) { - this.handleFinished(order); - } return result == null ? 0 : result; } @@ -888,4 +885,90 @@ public class OrderServiceImpl implements OrderService { return orderMapper.updateOrder(data); } + @Override + public int deduct(OrderDeductDTO dto) { + + // 查询订单 + OrderVO order = this.selectOrderById(dto.getId()); + ServiceUtil.assertion(order == null, "ID为%s的订单不存在", dto.getId()); + + // 判断是否可以抵扣 + ServiceUtil.assertion(!OrderStatus.canDeduct().contains(order.getStatus()), "ID为%s的订单当前状态不允许抵扣", dto.getId()); + BigDecimal canDeductAmount = OrderUtil.calcRemainCanDeductDeposit(order); + + // 获取实际抵扣金额 + BigDecimal deductAmount; + if (MathUtils.biggerThan(dto.getAmount(), canDeductAmount)) { + // 抵扣金额不足时 + ServiceUtil.assertion(!dto.getReduceAmountWhenNotEnough(), "ID为%s的订单可抵扣押金不足,当前可抵扣金额为%s", dto.getId(), canDeductAmount); + deductAmount = canDeductAmount; + } else { + // 抵扣金额充足时 + deductAmount = dto.getAmount(); + } + + // 关闭订单的支付ID + boolean closePay = payService.closeByBstId(PayBstType.ORDER_RIDE.getType(), order.getId()); + ServiceUtil.assertion(!closePay, "ID为%s的订单骑行费支付关闭失败", dto.getId()); + + // 更新订单数据 + Integer result = transactionTemplate.execute(status -> { + // 押金抵扣 + int deduct = orderMapper.deductDeposit(order.getId(), deductAmount); + ServiceUtil.assertion(deduct != 1, "ID为%s的订单押金抵扣失败,剩余可抵扣押金不足", dto.getId()); + + OrderRidePaySuccessBO bo = new OrderRidePaySuccessBO(); + bo.setOrder(order); + bo.setPayType(OrderPayType.DEPOSIT_DEDUCTION); + bo.setPayAmount(deductAmount); + bo.setNeedVerify(dto.getNeedVerify()); + return this.handleRidePaySuccess(bo); + + }); + + return result == null ? 0 : result; + } + + private int handleRidePaySuccess(OrderRidePaySuccessBO bo) { + OrderVO order = bo.getOrder(); + OrderPayType payType = bo.getPayType(); + + // 更新订单数据 + Order data = new Order(); + data.setId(order.getId()); + data.setPayType(payType.getCode()); + // 计算实收金额 + this.setActualAmount(data, bo.getPayAmount()); + // 根据是否需要审核,设置订单状态 + if (order.getAreaReturnVerify() != null && order.getAreaReturnVerify() && bo.getNeedVerify()) { + data.setStatus(OrderStatus.WAIT_VERIFY.getCode()); + } else { + data.setStatus(OrderStatus.FINISHED.getCode()); + } + OrderQuery query = new OrderQuery(); + query.setId(order.getId()); + query.setStatusList(OrderStatus.canRidePaySuccess()); + query.setIsNullPayType(true); + + Integer result = transactionTemplate.execute(status -> { + int rows = orderMapper.updateByQuery(data, query); + ServiceUtil.assertion(rows != 1, "ID为%s的骑行支付更新失败", order.getId()); + + // 当订单状态为待审核时,发送还车审核通知 + if (OrderStatus.WAIT_VERIFY.getCode().equals(data.getStatus())) { + smsService.sendOrderWaitVerifyMsg(order); + } + + // 订单结束操作 + if (OrderStatus.FINISHED.getCode().equals(data.getStatus())) { + this.handleFinished(order); + } + + return rows; + }); + + + + return result == null ? 0 : result; + } } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java index 6f19b62..b9524e9 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/utils/OrderUtil.java @@ -198,4 +198,16 @@ public class OrderUtil { return query; } + /** + * 剩余可抵扣押金 + * @param order + * @return + */ + public static BigDecimal calcRemainCanDeductDeposit(OrderVO order) { + if (order == null) { + return BigDecimal.ZERO; + } + return MathUtils.dv(order.getDepositDeductRemain()); + } + } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/pay/domain/enums/PayBstType.java b/ruoyi-service/src/main/java/com/ruoyi/bst/pay/domain/enums/PayBstType.java index 5f0dccd..83031e2 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/pay/domain/enums/PayBstType.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/pay/domain/enums/PayBstType.java @@ -17,7 +17,8 @@ import lombok.Getter; @Getter @AllArgsConstructor public enum PayBstType { - ORDER("1", "订单", OrderPayHandlerImpl.class); + ORDER("1", "订单押金", OrderPayHandlerImpl.class), + ORDER_RIDE("2", "订单骑行费", null); private final String type; private final String msg; diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/suit/domain/Suit.java b/ruoyi-service/src/main/java/com/ruoyi/bst/suit/domain/Suit.java index d7ed800..f4d48ce 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/suit/domain/Suit.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/suit/domain/Suit.java @@ -103,6 +103,11 @@ public class Suit extends BaseEntity implements LogBizParam @ApiModelProperty("可用时长(秒)") private Long seconds; + @Excel(name = "自动押金抵扣") + @ApiModelProperty("自动押金抵扣") + @NotNull(message = "自动押金抵扣不能为空", groups = {ValidGroup.Create.class}) + private Boolean depositDeduction; + @Override public Object logBizId() { return id; diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/suit/mapper/SuitMapper.xml b/ruoyi-service/src/main/java/com/ruoyi/bst/suit/mapper/SuitMapper.xml index 7bf6061..46fbc7a 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/suit/mapper/SuitMapper.xml +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/suit/mapper/SuitMapper.xml @@ -27,6 +27,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" bs.deposit_amount, bs.type, bs.seconds, + bs.deposit_deduction, su.nick_name as user_name @@ -98,6 +99,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" deposit_amount, seconds, type, + deposit_deduction, #{userId}, @@ -115,6 +117,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{depositAmount}, #{seconds}, #{type}, + #{depositDeduction}, @@ -142,6 +145,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" deposit_amount = #{data.depositAmount}, type = #{data.type}, seconds = #{data.seconds}, + deposit_deduction = #{data.depositDeduction}, diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/bst/OrderController.java b/ruoyi-web/src/main/java/com/ruoyi/web/bst/OrderController.java index aec8d79..e18fdd1 100644 --- a/ruoyi-web/src/main/java/com/ruoyi/web/bst/OrderController.java +++ b/ruoyi-web/src/main/java/com/ruoyi/web/bst/OrderController.java @@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RestController; import com.ruoyi.bst.areaJoin.domain.enums.AreaJoinPermission; import com.ruoyi.bst.order.domain.OrderQuery; import com.ruoyi.bst.order.domain.OrderVO; +import com.ruoyi.bst.order.domain.dto.OrderDeductDTO; import com.ruoyi.bst.order.domain.dto.OrderEndDTO; import com.ruoyi.bst.order.domain.dto.OrderRefundDTO; import com.ruoyi.bst.order.domain.dto.OrderVerifyDTO; @@ -154,4 +155,19 @@ public class OrderController extends BaseController return toAjax(orderService.verify(dto)); } + /** + * 押金抵扣 + */ + @Log(title = "押金抵扣", businessType = BusinessType.UPDATE, bizIdName = "arg0", bizType = LogBizType.ORDER) + @PreAuthorize("@ss.hasPermi('bst:order:deduct')") + @PutMapping("/deduct") + public AjaxResult deduct(@RequestBody @Validated OrderDeductDTO dto) { + if (!orderValidator.canOperate(dto.getId())) { + return error("您无权押金抵扣ID为" + dto.getId() + "的订单"); + } + dto.setNeedVerify(false); + dto.setReduceAmountWhenNotEnough(false); + return toAjax(orderService.deduct(dto)); + } + }