设备租期(未测试)

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 = "元=")
@ApiModelProperty("超出起步时长价格")
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 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_unit,
sd.over_price,
sd.rent_time,
sm.model_name as model,
sm.picture as picture,
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="overUnit != null">over_unit,</if>
<if test="overPrice != null">over_price,</if>
<if test="rentTime != null">rent_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<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="overUnit != null">#{overUnit},</if>
<if test="overPrice != null">#{overPrice},</if>
<if test="rentTime != null">#{rentTime},</if>
</trim>
</insert>
@ -354,6 +357,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="overTime != null">over_time = #{overTime},</if>
<if test="overUnit != null">over_unit = #{overUnit},</if>
<if test="overPrice != null">over_price = #{overPrice},</if>
<if test="rentTime != null">rent_time = #{rentTime},</if>
</trim>
where device_id = #{deviceId}
</update>
@ -457,6 +461,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where device_id = #{deviceId}
</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 from sm_device where device_id = #{deviceId}
</delete>

View File

@ -12,6 +12,7 @@ import com.ruoyi.ss.device.domain.vo.DeviceVO;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
/**
@ -267,4 +268,12 @@ public interface DeviceService
* 更新服务费
*/
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);
}
@Override
public int renewalRentTime(Long deviceId, int time, TimeUnit timeUnit) {
long seconds = timeUnit.toSeconds(time);
return deviceMapper.renewalRentTime(deviceId, seconds);
}
@Override
public boolean addTime(Long deviceId, long seconds, boolean withIot) {

View File

@ -1,14 +1,12 @@
package com.ruoyi.ss.receiveBill.service;
import java.math.BigDecimal;
import java.time.LocalDateTime;
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.ReceiveBillVO;
import com.ruoyi.ss.receiveBill.domain.ReceiveBillQuery;
import com.ruoyi.ss.user.domain.SmUserVo;
import com.ruoyi.ss.transactionBill.domain.bo.RechargeBO;
/**
* 应收账单Service接口
@ -69,12 +67,10 @@ public interface ReceiveBillService
/**
* 月费商户出账
*
* @param user 用户ID
* @param device
* @param billTime 出账日期
* @param amount
* @param bo 充值BO
* @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.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
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.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.service.ISmUserService;
import org.springframework.beans.factory.annotation.Autowired;
@ -35,8 +38,10 @@ public class ReceiveBillServiceImpl implements ReceiveBillService
@Autowired
private ISmUserService userService;
@Autowired
private TransactionBillServiceImpl transactionBillService;
private DeviceService deviceService;
@Autowired
private TransactionTemplate transactionTemplate;
@ -114,26 +119,37 @@ public class ReceiveBillServiceImpl implements ReceiveBillService
}
@Override
public int genBillByMonthAndPay(SmUserVo user, DeviceVO device, LocalDateTime billTime, BigDecimal amount) {
ServiceUtil.assertion(user == null || user.getUserId() == null, "用户不存在");
public int genBillByMonthAndPay(RechargeBO bo, BigDecimal amount) {
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(billTime == null, "请指定一个月份");
// 查询指定月份是否已出账
ReceiveBillQuery query = new ReceiveBillQuery();
query.setBillYear(billTime.getYear());
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;
// 设备未过期则不生成账单
if (device.getRentTime() != null && device.getRentTime().isAfter(LocalDateTime.now())) {
return 1;
}
// 若未出账则生成账单
// 查询指定月份是否已出账已出账则不生成账单
// 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();
bill.setUserId(user.getUserId());
bill.setUserId(mch.getUserId());
bill.setDeviceId(device.getDeviceId());
bill.setType(ReceiveBillType.MONTH.getType());
bill.setStatus(ReceiveBillStatus.PAID.getStatus());
@ -143,11 +159,18 @@ public class ReceiveBillServiceImpl implements ReceiveBillService
bill.setReceivedAmount(amount);
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, "扣减商户余额失败");
// 插入账单
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;

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.vo.TransactionBillVO;
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.bo.WithdrawBO;
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.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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(device == null, "设备不存在,不允许下单");
String serviceType = null; // 服务费类型
BigDecimal serviceRate = null; // 服务费
// 优先级 设备 > 商户 > 渠道
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();
}
// 获取商户的服务费配置
UserRechargeServiceVO userRechargeService = this.getUserRechargeService(channel, mch, device);
String serviceType = userRechargeService.getServiceType(); // 服务费类型
BigDecimal serviceRate = userRechargeService.getServiceRate(); // 服务费
// 根据服务费类型进行对应操作
// 月费
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, "商户出账失败,请刷新后重试");
// 服务费 = 0
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) {
// 校验
@ -332,7 +338,7 @@ public class TransactionBillServiceImpl implements TransactionBillService {
// 渠道费用计算
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();
order.setExpireTime(new Date(expireTime));