diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/bonus/service/impl/BonusConverterImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/bonus/service/impl/BonusConverterImpl.java index 21b8fd6..a0714ba 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/bonus/service/impl/BonusConverterImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/bonus/service/impl/BonusConverterImpl.java @@ -177,7 +177,7 @@ public class BonusConverterImpl implements BonusConverter { String reason = "卡券订单收入:" + order.getNo(); for (Bonus bonus : result) { bonus.setReason(reason); - bonus.setBstType(BonusBstType.ORDER.getType()); + bonus.setBstType(BonusBstType.VIP_ORDER.getType()); bonus.setBstId(order.getId()); bonus.setStatus(BonusStatus.INVALID.getStatus()); bonus.setToBalance(true); 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 4f90122..fb5bbaf 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 @@ -39,8 +39,8 @@ public class DeviceUtil { } // 转换经纬度坐标系并赋值 - // 只有定位是正常的才认为是有获取到定位 - if (DeviceUtil.validLocation(sys.getLon(), sys.getLat())) { + // 只有定位是正常的 && 卫星信号大于2颗 才认为是有获取到定位 + if (DeviceUtil.validLocation(sys.getLon(), sys.getLat()) && sys.getS() != null && sys.getS() > 2) { List coordinates = null; // 转换坐标 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 e41639b..05450bc 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 @@ -281,4 +281,8 @@ public class Order extends BaseEntity { @Excel(name = "卡券优惠值") @ApiModelProperty("卡券优惠值") private BigDecimal vipDiscountValue; + + @Excel(name = "卡券名称") + @ApiModelProperty("卡券名称") + private String vipName; } 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 01e1a88..ed95b30 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 @@ -65,5 +65,8 @@ public class OrderQuery extends OrderVO { @ApiModelProperty("骑行费支付日期范围") @DateTimeFormat(pattern = "yyyy-MM-dd") private List ridePayDateRange; + + @ApiModelProperty("VIP ID 为空") + private Boolean isNullVipUserId; } 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 7e09f0d..4937c0e 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 @@ -134,4 +134,9 @@ public class OrderVO extends Order implements IotDevice { public BigDecimal getActualReceivedAmount() { return MathUtils.subtractDecimal(this.getActualAmount(), this.getAdminRefundAmount()); } + + // 总优惠金额 + public BigDecimal getTotalDiscountAmount() { + return this.getRidingDiscount(); + } } 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/dto/OrderRidePaySuccessDTO.java similarity index 64% rename from ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/bo/OrderRidePaySuccessBO.java rename to ruoyi-service/src/main/java/com/ruoyi/bst/order/domain/dto/OrderRidePaySuccessDTO.java index a4a997f..479b9ad 100644 --- 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/dto/OrderRidePaySuccessDTO.java @@ -1,24 +1,27 @@ -package com.ruoyi.bst.order.domain.bo; +package com.ruoyi.bst.order.domain.dto; +import java.math.BigDecimal; import java.time.LocalDateTime; -import com.ruoyi.bst.order.domain.OrderVO; import com.ruoyi.bst.order.domain.enums.OrderPayType; import lombok.Data; @Data -public class OrderRidePaySuccessBO { - +public class OrderRidePaySuccessDTO { + // 订单数据 - private OrderVO order; + private Long orderId; // 支付方式 private OrderPayType payType; - + // 是否忽略审核 private Boolean ignoreVerify; + // 支付金额 + private BigDecimal payAmount; + // 支付ID private Long payId; 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 048ee74..67c6792 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 @@ -91,4 +91,9 @@ public enum OrderStatus { public static List canUpdatePrice() { return CollectionUtils.map(OrderStatus::getCode, RIDE_WAIT_PAY); } + + // 允许恢复VIP优惠次数的订单状态 + public static List canRecoverVipCount() { + 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 18a515b..823c785 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 @@ -206,7 +206,7 @@ public interface OrderMapper { * 押金抵扣 * @param data */ - int deductDeposit(@Param("data") Order data); + int deductDeposit(@Param("id") Long id, @Param("depositDeductionAmount") BigDecimal depositDeductionAmount); /** * 更新退款信息 @@ -216,4 +216,12 @@ public interface OrderMapper { */ int updateRefund(@Param("data") Order data, @Param("query") OrderQuery query); + /** + * 清空订单的VIP信息 + * @param orderId + * @param vipUserId + * @return + */ + int clearVipInfo(@Param("orderId") Long orderId, @Param("vipUserId") Long vipUserId); + } 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 70c135f..85578f0 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 @@ -75,6 +75,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" bo.riding_discount, bo.vip_type, bo.vip_discount_value, + bo.vip_name, as deposit_deduct_remain, ba.name as area_name, su.nick_name as user_name, @@ -167,6 +168,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and bo.admin_refund_count = #{query.adminRefundCount} and bo.admin_refund_amount = #{query.adminRefundAmount} and bo.price_changed = #{query.priceChanged} + and bo.vip_user_id is not null + and bo.vip_name like concat('%', #{query.vipName}, '%') and bo.id in ( select distinct bb.bst_id from bst_bonus bb @@ -299,6 +302,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" riding_discount, vip_type, vip_discount_value, + vip_name, #{no}, @@ -364,6 +368,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{ridingDiscount}, #{vipType}, #{vipDiscountValue}, + #{vipName}, @@ -439,6 +444,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" riding_discount = #{data.ridingDiscount}, vip_type = #{data.vipType}, vip_discount_value = #{data.vipDiscountValue}, + vip_name = #{data.vipName}, @@ -635,14 +641,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" update bst_order bo left join bst_pay bp on bp.id = bo.pay_id - set bo.deposit_deduction_amount = bo.deposit_deduction_amount + #{data.depositDeductionAmount}, - bo.actual_amount = #{data.actualAmount}, - bo.actual_riding_fee = #{data.actualRidingFee}, - bo.actual_dispatch_fee = #{data.actualDispatchFee}, - bo.actual_manage_fee = #{data.actualManageFee}, - bo.actual_deduction_fee = #{data.actualDeductionFee} - where bo.id = #{data.id} - and >= #{data.depositDeductionAmount} + set bo.deposit_deduction_amount = bo.deposit_deduction_amount + #{depositDeductionAmount} + where bo.id = #{id} + and >= #{depositDeductionAmount} @@ -701,5 +702,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + update bst_order bo + set bo.vip_user_id = null, + bo.vip_type = null, + bo.vip_discount_value = null, + bo.vip_name = null, + bo.riding_discount = 0 + where bo.id = #{orderId} + and bo.vip_user_id = #{vipUserId} + and bo.status = 'RIDE_WAIT_PAY' + 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 db04c9f..28028b3 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 @@ -7,7 +7,7 @@ import com.ruoyi.bst.device.domain.vo.DeviceIotVO; import com.ruoyi.bst.order.domain.Order; import com.ruoyi.bst.order.domain.OrderQuery; import com.ruoyi.bst.order.domain.OrderVO; -import com.ruoyi.bst.order.domain.bo.OrderRidePaySuccessBO; +import com.ruoyi.bst.order.domain.dto.OrderRidePaySuccessDTO; import com.ruoyi.bst.order.domain.dto.OrderCalcFeeDTO; import com.ruoyi.bst.order.domain.dto.OrderCalcRideFeeDTO; import com.ruoyi.bst.order.domain.dto.OrderChangeDeviceDTO; @@ -246,10 +246,9 @@ public interface OrderService { /** * 处理骑行费支付成功 - * @param bo - * @return + * @param dto @return */ - public int handleRidePaySuccess(OrderRidePaySuccessBO bo); + public int handleRidePaySuccess(OrderRidePaySuccessDTO dto); /** * 改价 diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderRidePayHandlerImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderRidePayHandlerImpl.java index 6f20daf..804be0f 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderRidePayHandlerImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderRidePayHandlerImpl.java @@ -3,35 +3,30 @@ package com.ruoyi.bst.order.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.ruoyi.bst.order.domain.OrderVO; -import com.ruoyi.bst.order.domain.bo.OrderRidePaySuccessBO; +import com.ruoyi.bst.order.domain.dto.OrderRidePaySuccessDTO; import com.ruoyi.bst.order.domain.enums.OrderPayType; import com.ruoyi.bst.order.service.OrderService; import com.ruoyi.bst.pay.domain.PayVO; import com.ruoyi.bst.pay.interfaces.PayHandler; -import com.ruoyi.common.utils.ServiceUtil; @Service public class OrderRidePayHandlerImpl implements PayHandler { - + @Autowired private OrderService orderService; @Override public boolean onPaySuccess(PayVO pay) { - // 查询订单 - OrderVO order = orderService.selectOrderById(pay.getBstId()); - ServiceUtil.assertion(order == null, "订单不存在"); // 处理骑行费支付成功 - OrderRidePaySuccessBO bo = new OrderRidePaySuccessBO(); - bo.setOrder(order); - bo.setPayType(OrderPayType.USER_PAY); - bo.setPayAmount(pay.getAmount()); - bo.setIgnoreVerify(false); - bo.setPayId(pay.getId()); - bo.setPayTime(pay.getPayTime()); - int rows = orderService.handleRidePaySuccess(bo); + OrderRidePaySuccessDTO dto = new OrderRidePaySuccessDTO(); + dto.setOrderId(pay.getBstId()); + dto.setPayType(OrderPayType.USER_PAY); + dto.setPayAmount(pay.getAmount()); + dto.setIgnoreVerify(false); + dto.setPayId(pay.getId()); + dto.setPayTime(pay.getPayTime()); + int rows = orderService.handleRidePaySuccess(dto); return rows == 1; } 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 d0be95b..8cd20c7 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 @@ -47,7 +47,7 @@ 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.OrderPayRideFeeBO; -import com.ruoyi.bst.order.domain.bo.OrderRidePaySuccessBO; +import com.ruoyi.bst.order.domain.dto.OrderRidePaySuccessDTO; import com.ruoyi.bst.order.domain.dto.OrderCalcFeeDTO; import com.ruoyi.bst.order.domain.dto.OrderCalcRideFeeDTO; import com.ruoyi.bst.order.domain.dto.OrderChangeDeviceDTO; @@ -592,7 +592,8 @@ public class OrderServiceImpl implements OrderService { BigDecimal remain = payAmount; data.setActualAmount(payAmount); // 骑行费实收 - data.setActualRidingFee(MathUtils.min(remain, old.getRidingFee())); + BigDecimal ridingFee = MathUtils.subtractDecimal(old.getRidingFee(), old.getRidingDiscount()); + data.setActualRidingFee(MathUtils.min(remain, ridingFee)); remain = MathUtils.subtractDecimal(remain, data.getActualRidingFee()); // 调度费实收 data.setActualDispatchFee(MathUtils.min(remain, old.getDispatchFee())); @@ -1048,22 +1049,22 @@ public class OrderServiceImpl implements OrderService { // 更新订单数据 Integer result = transactionTemplate.execute(status -> { + // 恢复旧优惠券次数,清空订单优惠券信息 + this.recoverVipCount(order); + // 押金抵扣,计算实收金额 - Order data = new Order(); - data.setId(order.getId()); - data.setDepositDeductionAmount(deductAmount); - this.setActualAmount(data, order, deductAmount); - int deduct = orderMapper.deductDeposit(data); + int deduct = orderMapper.deductDeposit(order.getId(), deductAmount); ServiceUtil.assertion(deduct != 1, "ID为%s的订单押金抵扣失败,剩余可抵扣押金不足%s元", order.getId(), deductAmount); // 处理抵扣成功 - OrderRidePaySuccessBO bo = new OrderRidePaySuccessBO(); - bo.setOrder(order); - bo.setPayType(OrderPayType.DEPOSIT_DEDUCTION); - bo.setIgnoreVerify(ignoreVerify); - bo.setPayId(null); - bo.setPayTime(LocalDateTime.now()); - return this.handleRidePaySuccess(bo); + OrderRidePaySuccessDTO dto = new OrderRidePaySuccessDTO(); + dto.setOrderId(order.getId()); + dto.setPayType(OrderPayType.DEPOSIT_DEDUCTION); + dto.setIgnoreVerify(ignoreVerify); + dto.setPayAmount(deductAmount); + dto.setPayId(null); + dto.setPayTime(LocalDateTime.now()); + return this.handleRidePaySuccess(dto); }); return result == null ? 0 : result; @@ -1076,18 +1077,21 @@ public class OrderServiceImpl implements OrderService { * 处理骑行费支付成功 */ @Override - public int handleRidePaySuccess(OrderRidePaySuccessBO bo) { - OrderVO order = bo.getOrder(); - OrderPayType payType = bo.getPayType(); + public int handleRidePaySuccess(OrderRidePaySuccessDTO dto) { + OrderVO order = selectOrderById(dto.getOrderId()); + ServiceUtil.assertion(order == null, "ID为%s的订单不存在", dto.getOrderId()); + + OrderPayType payType = dto.getPayType(); // 更新订单数据 Order data = new Order(); // 支付信息 data.setPayType(payType.getCode()); - data.setRidePayId(bo.getPayId()); - data.setRidePayTime(bo.getPayTime()); + data.setRidePayId(dto.getPayId()); + data.setRidePayTime(dto.getPayTime()); + this.setActualAmount(data, order, dto.getPayAmount()); // 设置订单状态 - boolean ignoreVerify = bo.getIgnoreVerify() != null && bo.getIgnoreVerify(); + boolean ignoreVerify = dto.getIgnoreVerify() != null && dto.getIgnoreVerify(); if (order.getAreaReturnVerify() != null && order.getAreaReturnVerify() && !ignoreVerify) { data.setStatus(OrderStatus.WAIT_VERIFY.getCode()); } else { @@ -1137,32 +1141,35 @@ public class OrderServiceImpl implements OrderService { OrderVO order = bo.getOrder(); VipUserVO vipUser = bo.getVipUser(); OrderCalcRideFeeVO fee = bo.getFee(); - - return transactionTemplate.execute(status -> { - // TODO 恢复旧优惠券次数,清空订单优惠券信息 - if (order.getVipUserId() != null) { - } - + return transactionTemplate.execute(status -> { + // 恢复旧优惠券次数,清空订单优惠券信息 + this.recoverVipCount(order); + // 更新订单信息 Order data = new Order(); if (vipUser != null) { data.setVipUserId(vipUser.getId()); data.setVipDiscountValue(vipUser.getDiscount()); data.setVipType(vipUser.getType()); - // TODO 卡名称 + data.setVipName(vipUser.getName()); } data.setRidingDiscount(fee.getRideFeeDiscount()); OrderQuery query = new OrderQuery(); query.setId(order.getId()); - query.setVipUserIdIsNull(true); - orderMapper.updateByQuery(data, query); + query.setIsNullVipUserId(true); + int rows = orderMapper.updateByQuery(data, query); + ServiceUtil.assertion(rows != 1, "ID为%s的订单更新失败", order.getId()); + + // 若有使用优惠券,则扣减优惠券次数 + if (vipUser != null) { + int deduct = vipUserService.deductVipCount(vipUser.getId(), 1); + ServiceUtil.assertion(deduct != 1, "优惠券可用次数不足"); + } - // TODO 若有使用优惠券,则扣减优惠券次数 - // 转为支付单 Pay pay = payConverter.toPayPO(bo); - + // 创建并调起支付 return payService.createPayBill(pay); @@ -1173,6 +1180,32 @@ public class OrderServiceImpl implements OrderService { } + /** + * 恢复VIP优惠次数 + */ + private int recoverVipCount(OrderVO order) { + ServiceUtil.assertion(order == null, "订单不存在"); + if (order.getVipUserId() == null) { + return 1; + } + ServiceUtil.assertion(!OrderStatus.canRecoverVipCount().contains(order.getStatus()), "ID为%s的订单当前状态不允许恢复VIP优惠次数", order.getId()); + + Integer result = transactionTemplate.execute(status -> { + // 清空订单的VIP信息 + int clear = orderMapper.clearVipInfo(order.getId(), order.getVipUserId()); + ServiceUtil.assertion(clear != 1, "ID为%s的订单清空VIP信息失败", order.getId()); + // 尝试恢复VIP优惠次数 + try { + vipUserService.recoverVipCount(order.getVipUserId(), 1); + } catch (Exception e) { + log.error("ID为{}的订单恢复VIP优惠次数失败", order.getId(), e); + } + return clear; + }); + + return result == null ? 0 : result; + } + @Override public int updatePrice(OrderUpdatePriceDTO dto) { // 查询订单 @@ -1235,7 +1268,7 @@ public class OrderServiceImpl implements OrderService { public OrderCalcRideFeeVO calcRideFee(OrderVO order, VipUserVO vipUser) { ServiceUtil.assertion(order == null, "订单不存在"); - // 计算应付费用 + // 计算应付费用 OrderCalcRideFeeVO vo = new OrderCalcRideFeeVO(); vo.setOriginalAmount(order.getRidingFee()); vo.setRideFeeDiscount(VipUserUtil.calcDiscountAmount(vo.getOriginalAmount(), vipUser)); // 骑行费优惠 @@ -1243,7 +1276,7 @@ public class OrderServiceImpl implements OrderService { vo.setDispatchFee(order.getDispatchFee()); // 调度费 vo.setManageFee(order.getManageFee()); // 管理费 vo.setDeductionFee(order.getDeductionFee()); // 车损费 - + return vo; } } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderValidatorImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderValidatorImpl.java index f597d3d..d069281 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderValidatorImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/order/service/impl/OrderValidatorImpl.java @@ -82,7 +82,6 @@ public class OrderValidatorImpl implements OrderValidator{ ModelVO model = bo.getModel(); ServiceUtil.assertion(model == null, "ID为%s的车型不存在", device.getModelId()); ServiceUtil.assertion(CollectionUtils.isEmptyElement(model.getSuitIds()) || !model.getSuitIds().contains(suit.getId()), "ID为%s的套餐不可在ID为%s的车辆使用", dto.getSuitId(), dto.getDeviceId()); - ServiceUtil.assertion(suit.getSeconds() == null || suit.getSeconds() <= 0, "ID为%s的套餐时长不能为0或小于0", dto.getSuitId()); // 用户 UserVO user = bo.getUser(); @@ -262,7 +261,12 @@ public class OrderValidatorImpl implements OrderValidator{ OrderCalcRideFeeVO fee = bo.getFee(); ServiceUtil.assertion(fee == null, "ID为%s的订单当前费用不存在", dto.getOrderId()); ServiceUtil.assertion(!OrderUtil.isEquals(fee, dto.getFee()), "ID为%s的订单当前费用已发生变化,请刷新后重新支付", dto.getOrderId()); - + + // 用户 + UserVO user = bo.getUser(); + ServiceUtil.assertion(user == null, "ID为%s的用户不存在", dto.getUserId()); + ServiceUtil.assertion(!Objects.equals(order.getUserId(), user.getUserId()), "ID为%s的用户无权限支付ID为%s的订单", dto.getUserId(), dto.getOrderId()); + // 优惠券 VipUserVO vipUser = bo.getVipUser(); if (vipUser != null) { @@ -274,15 +278,12 @@ public class OrderValidatorImpl implements OrderValidator{ int limitCount = MathUtils.dv(vipUser.getLimitCount()); ServiceUtil.assertion(roundCount >= limitCount, "ID为%s的卡券已达到本周期使用次数上限", vipUser.getId()); } + ServiceUtil.assertion(!Objects.equals(order.getAreaId(), vipUser.getAreaId()), "ID为%s的卡券不可在ID为%s的运营区使用", vipUser.getId(), order.getAreaId()); + ServiceUtil.assertion(!Objects.equals(vipUser.getUserId(), user.getUserId()), "ID为%s的用户无权使用ID为%s的卡券", user.getUserId(), vipUser.getId()); } - // 用户 - UserVO user = bo.getUser(); - ServiceUtil.assertion(user == null, "ID为%s的用户不存在", dto.getUserId()); - ServiceUtil.assertion(!Objects.equals(order.getUserId(), user.getUserId()), "ID为%s的用户无权限支付ID为%s的订单", dto.getUserId(), dto.getOrderId()); - // 支付校验 payValidator.checkPay(bo.getApp(), bo.getChannel(), bo.getUserApp()); } - + } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/pay/service/impl/PayConverterImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/pay/service/impl/PayConverterImpl.java index 74d6218..2900973 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/pay/service/impl/PayConverterImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/pay/service/impl/PayConverterImpl.java @@ -9,6 +9,7 @@ import com.ruoyi.bst.channel.domain.ChannelVO; import com.ruoyi.bst.order.domain.Order; import com.ruoyi.bst.order.domain.bo.OrderCreateBO; import com.ruoyi.bst.order.domain.bo.OrderPayRideFeeBO; +import com.ruoyi.bst.order.domain.vo.OrderCalcRideFeeVO; import com.ruoyi.bst.pay.domain.Pay; import com.ruoyi.bst.pay.domain.enums.PayBstType; import com.ruoyi.bst.pay.domain.enums.PayStatus; @@ -90,7 +91,8 @@ public class PayConverterImpl implements PayConverter { ChannelVO channel = bo.getChannel(); UserAppVO userApp = bo.getUserApp(); AppVO app = bo.getApp(); - if (order == null || user == null || channel == null || userApp == null || app == null) { + OrderCalcRideFeeVO fee = bo.getFee(); + if (order == null || user == null || channel == null || userApp == null || app == null || fee == null) { return null; } @@ -99,7 +101,7 @@ public class PayConverterImpl implements PayConverter { // 订单信息 pay.setBstType(PayBstType.ORDER_RIDE.getType()); pay.setBstId(order.getId()); - pay.setAmount(order.getTotalFee()); + pay.setAmount(fee.getPayAmount()); pay.setAreaId(order.getAreaId()); pay.setDescription("骑行费:" + order.getNo()); diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/mapper/VipUserMapper.java b/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/mapper/VipUserMapper.java index 88fdc29..262bed6 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/mapper/VipUserMapper.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/mapper/VipUserMapper.java @@ -96,4 +96,20 @@ public interface VipUserMapper * @return */ int logicDel(@Param("ids") List ids); + + /** + * 恢复VIP优惠次数 + * @param vipUserId + * @param count + * @return + */ + int recoverVipCount(@Param("vipUserId") Long vipUserId, @Param("count") int count); + + /** + * 扣减VIP优惠次数 + * @param id + * @param count + * @return + */ + int deductVipCount(@Param("id") Long id, @Param("count") int count); } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/mapper/VipUserMapper.xml b/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/mapper/VipUserMapper.xml index 524afdf..2457f18 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/mapper/VipUserMapper.xml +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/mapper/VipUserMapper.xml @@ -193,4 +193,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and bvu.deleted = false + + + + update bst_vip_user bvu + set bvu.round_count = if (bvu.round_count > 0, bvu.round_count - #{count}, 0), + bvu.surplus_total = bvu.surplus_total + #{count} + where bvu.id = #{vipUserId} + + + + + + update bst_vip_user bvu + set bvu.round_count = bvu.round_count + #{count}, + bvu.surplus_total = bvu.surplus_total - #{count} + where bvu.id = #{id} + and bvu.surplus_total >= #{count} + and bvu.round_count + #{count} <= bvu.limit_count + diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/service/VipUserService.java b/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/service/VipUserService.java index e380c41..63479fa 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/service/VipUserService.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/service/VipUserService.java @@ -74,4 +74,19 @@ public interface VipUserService */ public int logicDel(List ids); + /** + * 恢复VIP优惠次数 + * @param vipUserId + * @return + */ + public int recoverVipCount(Long vipUserId, int count); + + /** + * 扣减VIP优惠次数 + * @param id + * @param count + * @return + */ + public int deductVipCount(Long id, int count); + } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/service/impl/VipUserServiceImpl.java b/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/service/impl/VipUserServiceImpl.java index 6e95cf5..2f74cbf 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/service/impl/VipUserServiceImpl.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/service/impl/VipUserServiceImpl.java @@ -121,4 +121,19 @@ public class VipUserServiceImpl implements VipUserService return vipUserMapper.logicDel(ids); } + @Override + public int recoverVipCount(Long vipUserId, int count) { + if (vipUserId == null || count <= 0) { + return 0; + } + return vipUserMapper.recoverVipCount(vipUserId, count); + } + + @Override + public int deductVipCount(Long id, int count) { + if (id == null || count <= 0) { + return 0; + } + return vipUserMapper.deductVipCount(id, count); + } } diff --git a/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/utils/VipUserUtil.java b/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/utils/VipUserUtil.java index 34a5dde..da1d7e8 100644 --- a/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/utils/VipUserUtil.java +++ b/ruoyi-service/src/main/java/com/ruoyi/bst/vipUser/utils/VipUserUtil.java @@ -11,7 +11,7 @@ import com.ruoyi.bst.vipUser.domain.VipUserVO; import com.ruoyi.common.utils.MathUtils; public class VipUserUtil { - + public static LocalDateTime getNextResetTime(VipUser vip) { if (vip == null) { return null; @@ -32,9 +32,11 @@ public class VipUserUtil { if (vipUser == null || originalAmount == null) { return BigDecimal.ZERO; } - + if (VipType.DISCOUNT.getCode().equals(vipUser.getType())) { - return MathUtils.mulDecimal(originalAmount, vipUser.getDiscount()).divide(BigDecimal.valueOf(10), 2, RoundingMode.HALF_UP); + BigDecimal decimal10 = BigDecimal.valueOf(10); + return MathUtils.mulDecimal(originalAmount, MathUtils.subtractDecimal(decimal10, vipUser.getDiscount())) + .divide(decimal10, 2, RoundingMode.DOWN); } else if (VipType.DEDUCT.getCode().equals(vipUser.getType())) { return MathUtils.min(originalAmount, vipUser.getDiscount()); } else if (VipType.BALANCE.getCode().equals(vipUser.getType())) { diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java b/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java index 192486d..4d99453 100644 --- a/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java +++ b/ruoyi-web/src/main/java/com/ruoyi/web/app/AppOrderController.java @@ -149,7 +149,7 @@ public class AppOrderController extends BaseController { } return error("关闭订单失败"); } - + @ApiOperation("计算订单费用") @PostMapping("/calcFee") @Log(title = "计算订单费用", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.ORDER) @@ -174,7 +174,6 @@ public class AppOrderController extends BaseController { OrderVO order = orderService.selectOrderById(dto.getOrderId()); ServiceUtil.assertion(order == null, "订单不存在"); ServiceUtil.assertion(!orderValidator.canOpenDevice(order, getUserId()), "您无权操作ID为%s的订单设备开启", order.getId()); - ServiceUtil.assertion(orderValidator.isTimeout(order), "预存款已完用,请还车后再扫码骑行,或联系客服人员处理!"); if (dto.getRequiredIot() == null) { dto.setRequiredIot(true); } @@ -194,7 +193,6 @@ public class AppOrderController extends BaseController { OrderVO order = orderService.selectOrderById(dto.getOrderId()); ServiceUtil.assertion(order == null, "订单不存在"); ServiceUtil.assertion(!orderValidator.canCloseDevice(order, getUserId()), "您无权操作ID为%s的订单设备关闭", order.getId()); - ServiceUtil.assertion(orderValidator.isTimeout(order), "预存款已完用,请还车后再扫码骑行,或联系客服人员处理!"); if (dto.getRequiredIot() == null) { dto.setRequiredIot(true); } @@ -213,7 +211,6 @@ public class AppOrderController extends BaseController { OrderVO order = orderService.selectOrderById(dto.getOrderId()); ServiceUtil.assertion(!orderValidator.canChangeDevice(order, getUserId()), "您无权操作ID为%s的订单换车", order.getId()); - ServiceUtil.assertion(orderValidator.isTimeout(order), "预存款已完用,请还车后再扫码骑行,或联系客服人员处理!"); dto.setUserId(getUserId()); dto.setUserName(getNickName()); return toAjax(orderService.changeDevice(dto)); @@ -226,7 +223,7 @@ public class AppOrderController extends BaseController { // 设置日志参数 LogParamHolder.set(LogParamHolder.PARAM_LON, dto.getLon()); LogParamHolder.set(LogParamHolder.PARAM_LAT, dto.getLat()); - + OrderVO order = orderService.selectOrderById(dto.getOrderId()); ServiceUtil.assertion(!orderValidator.isUser(order, getUserId()), "您无权操作ID为%s的订单打开坐垫锁", order.getId()); if (dto.getRequiredIot() == null) {