设备租期(未测试)

This commit is contained in:
墨大叔 2024-08-05 17:55:44 +08:00
parent 7f49032338
commit 62d4326103
9 changed files with 143 additions and 52 deletions

View File

@ -184,4 +184,8 @@ public class Device extends BaseEntity
@Excel(name = "超出起步时长价格", readConverterExp = "元=") @Excel(name = "超出起步时长价格", readConverterExp = "元=")
@ApiModelProperty("超出起步时长价格") @ApiModelProperty("超出起步时长价格")
private BigDecimal overPrice; private BigDecimal overPrice;
@ApiModelProperty("设备租期到期时间")
@JsonView(JsonViewProfile.AppMch.class)
private LocalDateTime rentTime;
} }

View File

@ -180,4 +180,9 @@ public interface DeviceMapper
* 更新服务费 * 更新服务费
*/ */
int updateServiceRate(DeviceVO data); int updateServiceRate(DeviceVO data);
/**
* 续费时长
*/
int renewalRentTime(@Param("deviceId") Long deviceId, @Param("seconds") long seconds);
} }

View File

@ -99,6 +99,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
sd.over_time, sd.over_time,
sd.over_unit, sd.over_unit,
sd.over_price, sd.over_price,
sd.rent_time,
sm.model_name as model, sm.model_name as model,
sm.picture as picture, sm.picture as picture,
sm.tags as model_tags, sm.tags as model_tags,
@ -259,6 +260,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="overTime != null">over_time,</if> <if test="overTime != null">over_time,</if>
<if test="overUnit != null">over_unit,</if> <if test="overUnit != null">over_unit,</if>
<if test="overPrice != null">over_price,</if> <if test="overPrice != null">over_price,</if>
<if test="rentTime != null">rent_time,</if>
</trim> </trim>
<trim prefix="values (" suffix=")" suffixOverrides=","> <trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="storeId != null">#{storeId},</if> <if test="storeId != null">#{storeId},</if>
@ -296,6 +298,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="overTime != null">#{overTime},</if> <if test="overTime != null">#{overTime},</if>
<if test="overUnit != null">#{overUnit},</if> <if test="overUnit != null">#{overUnit},</if>
<if test="overPrice != null">#{overPrice},</if> <if test="overPrice != null">#{overPrice},</if>
<if test="rentTime != null">#{rentTime},</if>
</trim> </trim>
</insert> </insert>
@ -354,6 +357,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="overTime != null">over_time = #{overTime},</if> <if test="overTime != null">over_time = #{overTime},</if>
<if test="overUnit != null">over_unit = #{overUnit},</if> <if test="overUnit != null">over_unit = #{overUnit},</if>
<if test="overPrice != null">over_price = #{overPrice},</if> <if test="overPrice != null">over_price = #{overPrice},</if>
<if test="rentTime != null">rent_time = #{rentTime},</if>
</trim> </trim>
where device_id = #{deviceId} where device_id = #{deviceId}
</update> </update>
@ -457,6 +461,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where device_id = #{deviceId} where device_id = #{deviceId}
</update> </update>
<update id="renewalRentTime">
update sm_device
set rent_time = if(
now() > rent_time,
date_add(now(), interval #{seconds} second),
date_add(rent_time, interval #{seconds} second)
)
where device_id = #{deviceId}
</update>
<delete id="deleteSmDeviceByDeviceId" parameterType="Long"> <delete id="deleteSmDeviceByDeviceId" parameterType="Long">
delete from sm_device where device_id = #{deviceId} delete from sm_device where device_id = #{deviceId}
</delete> </delete>

View File

@ -12,6 +12,7 @@ import com.ruoyi.ss.device.domain.vo.DeviceVO;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
/** /**
@ -267,4 +268,12 @@ public interface DeviceService
* 更新服务费 * 更新服务费
*/ */
int updateServiceRate(DeviceVO data); int updateServiceRate(DeviceVO data);
/**
* 续费时长
* @param deviceId 设备ID
* @param time 时长
* @param timeUnit 时长单位
*/
int renewalRentTime(Long deviceId, int time, TimeUnit timeUnit);
} }

View File

@ -393,6 +393,12 @@ public class DeviceServiceImpl implements DeviceService
return deviceMapper.updateServiceRate(data); return deviceMapper.updateServiceRate(data);
} }
@Override
public int renewalRentTime(Long deviceId, int time, TimeUnit timeUnit) {
long seconds = timeUnit.toSeconds(time);
return deviceMapper.renewalRentTime(deviceId, seconds);
}
@Override @Override
public boolean addTime(Long deviceId, long seconds, boolean withIot) { public boolean addTime(Long deviceId, long seconds, boolean withIot) {

View File

@ -1,14 +1,12 @@
package com.ruoyi.ss.receiveBill.service; package com.ruoyi.ss.receiveBill.service;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.receiveBill.domain.ReceiveBill; import com.ruoyi.ss.receiveBill.domain.ReceiveBill;
import com.ruoyi.ss.receiveBill.domain.ReceiveBillVO; import com.ruoyi.ss.receiveBill.domain.ReceiveBillVO;
import com.ruoyi.ss.receiveBill.domain.ReceiveBillQuery; import com.ruoyi.ss.receiveBill.domain.ReceiveBillQuery;
import com.ruoyi.ss.user.domain.SmUserVo; import com.ruoyi.ss.transactionBill.domain.bo.RechargeBO;
/** /**
* 应收账单Service接口 * 应收账单Service接口
@ -69,12 +67,10 @@ public interface ReceiveBillService
/** /**
* 月费商户出账 * 月费商户出账
* *
* @param user 用户ID * @param bo 充值BO
* @param device * @param amount 收取的金额
* @param billTime 出账日期
* @param amount
*/ */
int genBillByMonthAndPay(SmUserVo user, DeviceVO device, LocalDateTime billTime, BigDecimal amount); int genBillByMonthAndPay(RechargeBO bo, BigDecimal amount);
/** /**
* 查询数量 * 查询数量

View File

@ -3,13 +3,16 @@ package com.ruoyi.ss.receiveBill.service.impl;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.ss.device.domain.vo.DeviceVO; import com.ruoyi.ss.device.domain.vo.DeviceVO;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.receiveBill.domain.enums.ReceiveBillStatus; import com.ruoyi.ss.receiveBill.domain.enums.ReceiveBillStatus;
import com.ruoyi.ss.receiveBill.domain.enums.ReceiveBillType; import com.ruoyi.ss.receiveBill.domain.enums.ReceiveBillType;
import com.ruoyi.ss.transactionBill.service.impl.TransactionBillServiceImpl; import com.ruoyi.ss.transactionBill.domain.TransactionBill;
import com.ruoyi.ss.transactionBill.domain.bo.RechargeBO;
import com.ruoyi.ss.user.domain.SmUserVo; import com.ruoyi.ss.user.domain.SmUserVo;
import com.ruoyi.ss.user.service.ISmUserService; import com.ruoyi.ss.user.service.ISmUserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -35,8 +38,10 @@ public class ReceiveBillServiceImpl implements ReceiveBillService
@Autowired @Autowired
private ISmUserService userService; private ISmUserService userService;
@Autowired @Autowired
private TransactionBillServiceImpl transactionBillService; private DeviceService deviceService;
@Autowired @Autowired
private TransactionTemplate transactionTemplate; private TransactionTemplate transactionTemplate;
@ -114,26 +119,37 @@ public class ReceiveBillServiceImpl implements ReceiveBillService
} }
@Override @Override
public int genBillByMonthAndPay(SmUserVo user, DeviceVO device, LocalDateTime billTime, BigDecimal amount) { public int genBillByMonthAndPay(RechargeBO bo, BigDecimal amount) {
ServiceUtil.assertion(user == null || user.getUserId() == null, "用户不存在"); SmUserVo mch = bo.getMch();
DeviceVO device = bo.getDevice();
TransactionBill order = bo.getOrder();
LocalDateTime billTime = LocalDateTime.now();
ServiceUtil.assertion(mch == null || mch.getUserId() == null, "用户不存在");
ServiceUtil.assertion(device == null || device.getDeviceId() == null, "设备不存在"); ServiceUtil.assertion(device == null || device.getDeviceId() == null, "设备不存在");
ServiceUtil.assertion(billTime == null, "请指定一个月份");
// 查询指定月份是否已出账 // 设备未过期则不生成账单
ReceiveBillQuery query = new ReceiveBillQuery(); if (device.getRentTime() != null && device.getRentTime().isAfter(LocalDateTime.now())) {
query.setBillYear(billTime.getYear()); return 1;
query.setBillMonth(billTime.getMonthValue());
query.setType(ReceiveBillType.MONTH.getType());
query.setUserId(user.getUserId());
query.setDeviceId(device.getDeviceId());
int count = this.selectCount(query);
if ( count > 0) {
return count;
} }
// 若未出账则生成账单 // 查询指定月份是否已出账已出账则不生成账单
// ReceiveBillQuery query = new ReceiveBillQuery();
// query.setBillYear(billTime.getYear());
// query.setBillMonth(billTime.getMonthValue());
// query.setType(ReceiveBillType.MONTH.getType());
// query.setUserId(mch.getUserId());
// query.setDeviceId(device.getDeviceId());
// int count = this.selectCount(query);
// if ( count > 0) {
// return count;
// }
// 判断商户余额 + 订单金额是否足够账单金额
ServiceUtil.assertion(mch.getBalance().add(order.getArrivalAmount()).compareTo(amount) < 0, "设备到期,商家余额不足,请联系商家处理");
// 生成账单
ReceiveBill bill = new ReceiveBill(); ReceiveBill bill = new ReceiveBill();
bill.setUserId(user.getUserId()); bill.setUserId(mch.getUserId());
bill.setDeviceId(device.getDeviceId()); bill.setDeviceId(device.getDeviceId());
bill.setType(ReceiveBillType.MONTH.getType()); bill.setType(ReceiveBillType.MONTH.getType());
bill.setStatus(ReceiveBillStatus.PAID.getStatus()); bill.setStatus(ReceiveBillStatus.PAID.getStatus());
@ -143,11 +159,18 @@ public class ReceiveBillServiceImpl implements ReceiveBillService
bill.setReceivedAmount(amount); bill.setReceivedAmount(amount);
Integer result = transactionTemplate.execute(status -> { Integer result = transactionTemplate.execute(status -> {
// 用户余额扣减 // 用户余额扣减
int subtract = userService.subtractBalance(user.getUserId(), amount, false, bill.getDescription()); int subtract = userService.subtractBalance(mch.getUserId(), amount, true, bill.getDescription());
ServiceUtil.assertion(subtract != 1, "扣减商户余额失败"); ServiceUtil.assertion(subtract != 1, "扣减商户余额失败");
// 插入账单 // 插入账单
return this.insertReceiveBill(bill); int insert = this.insertReceiveBill(bill);
ServiceUtil.assertion(insert != 1, "新增账单失败");
// 设备续费30天
int renewal = deviceService.renewalRentTime(device.getDeviceId(), 30, TimeUnit.DAYS);
ServiceUtil.assertion(renewal != 1, "设备续费失败");
return insert;
}); });
return result == null ? 0 : result; return result == null ? 0 : result;

View File

@ -0,0 +1,28 @@
package com.ruoyi.ss.transactionBill.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* 用户充值手续费
* @author wjh
* 2024/8/5
*/
@Data
public class UserRechargeServiceVO {
// 类型
private String serviceType;
// 手续费
private BigDecimal serviceRate;
public UserRechargeServiceVO() {
}
public UserRechargeServiceVO(String serviceType, BigDecimal serviceRate) {
this.serviceType = serviceType;
this.serviceRate = serviceRate;
}
}

View File

@ -27,6 +27,7 @@ import com.ruoyi.ss.transactionBill.domain.TransactionBill;
import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery; import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery;
import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO; import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO;
import com.ruoyi.ss.transactionBill.domain.bo.RechargeBO; import com.ruoyi.ss.transactionBill.domain.bo.RechargeBO;
import com.ruoyi.ss.transactionBill.domain.vo.UserRechargeServiceVO;
import com.ruoyi.ss.transactionBill.domain.vo.UserWithdrawServiceVO; import com.ruoyi.ss.transactionBill.domain.vo.UserWithdrawServiceVO;
import com.ruoyi.ss.transactionBill.domain.bo.WithdrawBO; import com.ruoyi.ss.transactionBill.domain.bo.WithdrawBO;
import com.ruoyi.ss.transactionBill.domain.dto.BillRefundDTO; import com.ruoyi.ss.transactionBill.domain.dto.BillRefundDTO;
@ -45,7 +46,6 @@ import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.task.bill.BillDelayedManager; import com.ruoyi.task.bill.BillDelayedManager;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse; import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.model.Transaction; import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -242,35 +242,23 @@ public class TransactionBillServiceImpl implements TransactionBillService {
} }
// 处理充值服务费 // 处理充值服务费
private void handleRechargeService(TransactionBill order, ChannelVO channel, SmUserVo mch, DeviceVO device) { private void handleRechargeService(RechargeBO bo) {
TransactionBill order = bo.getOrder();
ChannelVO channel = bo.getChannel();
SmUserVo mch = bo.getMch();
DeviceVO device = bo.getDevice();
ServiceUtil.assertion(mch == null, "商户不存在,不允许下单"); ServiceUtil.assertion(mch == null, "商户不存在,不允许下单");
ServiceUtil.assertion(device == null, "设备不存在,不允许下单"); ServiceUtil.assertion(device == null, "设备不存在,不允许下单");
String serviceType = null; // 服务费类型 // 获取商户的服务费配置
BigDecimal serviceRate = null; // 服务费 UserRechargeServiceVO userRechargeService = this.getUserRechargeService(channel, mch, device);
String serviceType = userRechargeService.getServiceType(); // 服务费类型
// 优先级 设备 > 商户 > 渠道 BigDecimal serviceRate = userRechargeService.getServiceRate(); // 服务费
if (device.getServiceRate() != null && StringUtils.hasText(device.getServiceType())) {
serviceType = device.getServiceType();
serviceRate = device.getServiceRate();
}
// 商户
else if (mch.getServiceRate() != null && StringUtils.hasText(mch.getServiceType())) {
serviceType = mch.getServiceType();
serviceRate = mch.getServiceRate();
}
// 渠道
else {
ServiceUtil.assertion(channel == null, "支付渠道不存在");
ServiceUtil.assertion(channel.getServiceRate() == null, "支付渠道服务费未配置,请联系管理员");
ServiceUtil.assertion(StringUtils.isBlank(channel.getServiceType()), "支付渠道服务费收取方式未配置,请联系管理员");
serviceType = channel.getServiceType();
serviceRate = channel.getServiceRate();
}
// 根据服务费类型进行对应操作
// 月费 // 月费
if (ServiceType.MONTH.getType().equals(serviceType)) { if (ServiceType.MONTH.getType().equals(serviceType)) {
int count = receiveBillService.genBillByMonthAndPay(mch, device, LocalDateTime.now(), serviceRate); int count = receiveBillService.genBillByMonthAndPay(bo, serviceRate);
ServiceUtil.assertion(count == 0, "商户出账失败,请刷新后重试"); ServiceUtil.assertion(count == 0, "商户出账失败,请刷新后重试");
// 服务费 = 0 // 服务费 = 0
order.setServiceCharge(BigDecimal.ZERO); order.setServiceCharge(BigDecimal.ZERO);
@ -290,6 +278,24 @@ public class TransactionBillServiceImpl implements TransactionBillService {
} }
private UserRechargeServiceVO getUserRechargeService(ChannelVO channel, SmUserVo mch, DeviceVO device) {
// 优先级 设备 > 商户 > 渠道
if (device.getServiceRate() != null && StringUtils.hasText(device.getServiceType())) {
return new UserRechargeServiceVO(device.getServiceType(), device.getServiceRate());
}
// 商户
else if (mch.getServiceRate() != null && StringUtils.hasText(mch.getServiceType())) {
return new UserRechargeServiceVO(mch.getServiceType(), mch.getServiceRate());
}
// 渠道
else {
ServiceUtil.assertion(channel == null, "支付渠道不存在");
ServiceUtil.assertion(channel.getServiceRate() == null, "支付渠道服务费未配置,请联系管理员");
ServiceUtil.assertion(StringUtils.isBlank(channel.getServiceType()), "支付渠道服务费收取方式未配置,请联系管理员");
return new UserRechargeServiceVO(channel.getServiceType(), channel.getServiceRate());
}
}
// 转换为订单所需的数据 // 转换为订单所需的数据
private TransactionBill parseToOrder(RechargeBO bo) { private TransactionBill parseToOrder(RechargeBO bo) {
// 校验 // 校验
@ -332,7 +338,7 @@ public class TransactionBillServiceImpl implements TransactionBillService {
// 渠道费用计算 // 渠道费用计算
order.setChannelCost(channel.getCostRate().multiply(order.getMoney()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP)); order.setChannelCost(channel.getCostRate().multiply(order.getMoney()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
// 充值服务费处理 // 充值服务费处理
this.handleRechargeService(order, channel, mch, device); this.handleRechargeService(bo);
// 支付过期时间 // 支付过期时间
long expireTime = TimeUnit.MILLISECONDS.convert(Constants.BILL_UNPAID_TIMEOUT, Constants.BILL_UNPAID_TIMEUNIT) + System.currentTimeMillis(); long expireTime = TimeUnit.MILLISECONDS.convert(Constants.BILL_UNPAID_TIMEOUT, Constants.BILL_UNPAID_TIMEUNIT) + System.currentTimeMillis();
order.setExpireTime(new Date(expireTime)); order.setExpireTime(new Date(expireTime));