套餐、订单修改
This commit is contained in:
parent
1ae280ad0d
commit
a1204272be
|
@ -50,14 +50,10 @@ public class ReceiveController {
|
|||
@PostMapping(value = "/receive")
|
||||
@Anonymous
|
||||
public ResponseEntity<String> receive(@RequestBody String body){
|
||||
log.info("receive方法接收到参数: body String --- {}", body);
|
||||
ReceiveBody obj = IotUtil.resolveBody(body, false);
|
||||
log.info("receive方法解析对象: body Object --- {}", JSON.toJSONString(obj));
|
||||
if (obj != null){
|
||||
if (IotUtil.checkSignature(obj, token)){
|
||||
log.info("receive方法验证签名正确: content {}", JSON.toJSONString(obj));
|
||||
Object msg = obj.getMsg();
|
||||
log.info("receive方法-获取到消息体: msg--- {}", JSON.toJSONString(msg));
|
||||
// 接收到msg
|
||||
if (msg instanceof String) {
|
||||
iotReceiveService.handleReceive(JSON.parseObject((String) msg, ReceiveMsg.class));
|
||||
|
|
|
@ -298,13 +298,10 @@ public interface DeviceService
|
|||
*/
|
||||
void pullDeviceInfo(Long deviceId);
|
||||
|
||||
/**
|
||||
* 清空设备时长、电量
|
||||
*/
|
||||
int clearTimeAndEle(DeviceVO device, boolean required);
|
||||
|
||||
/**
|
||||
* 设备归零时长
|
||||
* @param device 设备
|
||||
* @param required 是否必须成功
|
||||
*/
|
||||
int resetTime(DeviceVO device, boolean required);
|
||||
|
||||
|
@ -353,4 +350,8 @@ public interface DeviceService
|
|||
*/
|
||||
DeviceVO selectByAnyMac(String mac);
|
||||
|
||||
/**
|
||||
* 拉取最新设备数据
|
||||
*/
|
||||
void pullDeviceInfo(DeviceVO device);
|
||||
}
|
||||
|
|
|
@ -438,21 +438,6 @@ public class DeviceServiceImpl implements DeviceService
|
|||
pullDeviceInfo(Collections.singletonList(deviceId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clearTimeAndEle(DeviceVO device, boolean required) {
|
||||
if (device == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 归零时长
|
||||
int resetTime = this.resetTime(device, required);
|
||||
|
||||
// 归零剩余电量
|
||||
int resetEle = this.resetEle(device, required);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int resetTime(DeviceVO device, boolean required) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
@ -645,6 +630,11 @@ public class DeviceServiceImpl implements DeviceService
|
|||
return deviceMapper.selectByAnyMac(mac);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pullDeviceInfo(DeviceVO device) {
|
||||
this.pullDeviceInfoList(Collections.singletonList(device));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean addTime(Long deviceId, long seconds, boolean withIot) {
|
||||
|
|
|
@ -211,16 +211,19 @@ public class SuitValidatorImpl extends BaseValidator implements SuitValidator {
|
|||
}
|
||||
|
||||
// 一次性充值的套餐,价格不允许低于最低服务费
|
||||
BigDecimal minService = sysConfigService.getBigDecimal(ConfigKey.RECHARGE_MIN_SERVICE);
|
||||
if (SuitFeeType.singleList().contains(feeType)) {
|
||||
ServiceUtil.assertion(vo.getPrice() == null, "价格不允许为空");
|
||||
BigDecimal minService = sysConfigService.getBigDecimal(ConfigKey.RECHARGE_MIN_SERVICE);
|
||||
if (vo.getPrice().compareTo(minService) < 0) {
|
||||
throw new ServiceException("价格不允许低于" + minService + "元");
|
||||
}
|
||||
ServiceUtil.assertion(vo.getPrice().compareTo(minService) < 0, "价格不允许低于" + minService + "元");
|
||||
}
|
||||
|
||||
// 判断押金是否设置
|
||||
if (SuitFeeMode.SMART.getMode().equals(feeMode)) {
|
||||
ServiceUtil.assertion(vo.getDeposit() == null, "押金不允许为空");
|
||||
ServiceUtil.assertion(vo.getDeposit().compareTo(minService) < 0, "押金不允许低于" + minService + "元");
|
||||
|
||||
// 若为智能计时、智能按量,则押金不允许低于价格,且必须为价格的整数倍
|
||||
if (SuitFeeMode.SMART.getMode().equals(feeMode)) {
|
||||
ServiceUtil.assertion(vo.getDeposit() == null, "押金不允许为空");
|
||||
if (SuitFeeType.singleList().contains(feeType)) {
|
||||
ServiceUtil.assertion(vo.getDeposit().compareTo(vo.getPrice()) < 0, "押金不允许低于价格");
|
||||
|
||||
// 取模,判断余数
|
||||
|
|
|
@ -61,7 +61,6 @@ public class RechargeDTO {
|
|||
private BigDecimal suitPrice;
|
||||
|
||||
@ApiModelProperty("套餐押金")
|
||||
@NotNull(message = "套餐押金不允许为空")
|
||||
@Min(value = 0, message = "套餐押金不允许小于0")
|
||||
private BigDecimal suitDeposit;
|
||||
|
||||
|
|
|
@ -66,26 +66,6 @@ public class TransactionBillVO extends TransactionBill implements IotDevice {
|
|||
@ApiModelProperty("总用电量(度)/时长(秒)")
|
||||
private BigDecimal totalUse;
|
||||
|
||||
/**
|
||||
* 获取套餐时长(秒)
|
||||
*/
|
||||
public long toSecondSuitTime() {
|
||||
SuitTimeUnit unit = SuitTimeUnit.getByValue(this.getSuitTimeUnit());
|
||||
if (unit == null) {
|
||||
unit = SuitTimeUnit.MINUTE;
|
||||
}
|
||||
long time = this.getSuitTime() == null ? 0 : this.getSuitTime();
|
||||
|
||||
// 计算周期数
|
||||
int round = 1;
|
||||
// 若为智能模式,则计算出押金最大支持多少次,向上取整
|
||||
if (SuitFeeMode.SMART.getMode().equals(this.getSuitFeeMode())) {
|
||||
round = this.getSuitDeposit().divide(this.getSuitPrice(), 0, RoundingMode.UP).intValue();
|
||||
}
|
||||
|
||||
return time * unit.getConversion() * round;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String iotMac1() {
|
||||
return getDeviceMac();
|
||||
|
|
|
@ -4,6 +4,8 @@ import com.ruoyi.ss.transactionBill.domain.bo.*;
|
|||
import com.ruoyi.ss.transactionBill.domain.dto.*;
|
||||
import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author wjh
|
||||
* 2024/7/28
|
||||
|
@ -28,4 +30,22 @@ public interface TransactionBillConverter {
|
|||
RechargePayDepositBO toRechargePayDepositBO(PayDepositDTO dto);
|
||||
|
||||
EndUseBO toEndUseBO(EndUseDTO dto);
|
||||
|
||||
/**
|
||||
* 获取充值的电量(度)
|
||||
*
|
||||
* @param bill 订单
|
||||
*/
|
||||
BigDecimal toRechargeEle(TransactionBillVO bill);
|
||||
|
||||
/**
|
||||
* 获取充值的时长(秒)
|
||||
*/
|
||||
long toRechargeSeconds(TransactionBillVO bill);
|
||||
|
||||
/**
|
||||
* 获取订单套餐时长的秒数
|
||||
*/
|
||||
long toSecondSuitTime(TransactionBillVO bill);
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ import com.ruoyi.ss.device.service.DeviceService;
|
|||
import com.ruoyi.ss.store.domain.StoreVo;
|
||||
import com.ruoyi.ss.store.service.StoreService;
|
||||
import com.ruoyi.ss.suit.domain.SuitVO;
|
||||
import com.ruoyi.ss.suit.domain.enums.SuitFeeMode;
|
||||
import com.ruoyi.ss.suit.domain.enums.SuitTimeUnit;
|
||||
import com.ruoyi.ss.suit.service.SuitAssembler;
|
||||
import com.ruoyi.ss.suit.service.SuitService;
|
||||
import com.ruoyi.ss.transactionBill.domain.bo.*;
|
||||
|
@ -27,6 +29,8 @@ import com.ruoyi.system.service.ISysDeptService;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
|
@ -191,4 +195,42 @@ public class TransactionBillConverterImpl implements TransactionBillConverter {
|
|||
}
|
||||
return bo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal toRechargeEle(TransactionBillVO bill) {
|
||||
if (bill == null) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
// 计算周期数
|
||||
long round = this.calcRound(bill);
|
||||
return BigDecimal.valueOf(bill.getSuitTime() * round);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long toRechargeSeconds(TransactionBillVO bill) {
|
||||
long round = this.calcRound(bill);
|
||||
return this.toSecondSuitTime(bill) * round;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long toSecondSuitTime(TransactionBillVO bill) {
|
||||
SuitTimeUnit unit = SuitTimeUnit.getByValue(bill.getSuitTimeUnit());
|
||||
if (unit == null) {
|
||||
unit = SuitTimeUnit.MINUTE;
|
||||
}
|
||||
long time = bill.getSuitTime() == null ? 0 : bill.getSuitTime();
|
||||
return time * unit.getConversion();
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算周期数
|
||||
*/
|
||||
private long calcRound(TransactionBillVO bill) {
|
||||
int round = 1;
|
||||
// 若为智能模式,则计算出押金最大支持多少次,向上取整
|
||||
if (SuitFeeMode.SMART.getMode().equals(bill.getSuitFeeMode())) {
|
||||
round = bill.getSuitDeposit().divide(bill.getSuitPrice(), 0, RoundingMode.UP).intValue();
|
||||
}
|
||||
return round;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -868,15 +868,15 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
|
|||
try {
|
||||
if (SuitFeeType.TIME.getType().equals(bill.getSuitFeeType())) {
|
||||
// 设备充值时长
|
||||
return deviceService.addTime(bill.getDeviceId(), bill.toSecondSuitTime(), true);
|
||||
return deviceService.addTime(bill.getDeviceId(), transactionBillConverter.toRechargeSeconds(bill), true);
|
||||
} else if (SuitFeeType.COUNT.getType().equals(bill.getSuitFeeType())) {
|
||||
// 若设备剩余时长为负数,则补偿设备时长
|
||||
BigDecimal openTime = BigDecimal.valueOf(bill.getSuitTime());
|
||||
// 若设备剩余电量为负数,则补偿设备电量
|
||||
BigDecimal ele = transactionBillConverter.toRechargeEle(bill);
|
||||
if (device.getSurplusEle() != null && device.getSurplusEle().compareTo(BigDecimal.ZERO) < 0) {
|
||||
openTime = openTime.add(device.getSurplusEle().abs());
|
||||
ele = ele.add(device.getSurplusEle().abs());
|
||||
}
|
||||
// 设备充值电量
|
||||
CommandResponse res = iotService.addEle(device, openTime);
|
||||
CommandResponse res = iotService.addEle(device, ele);
|
||||
ServiceUtil.assertion(res == null, "设备充值失败,返回数据为空");
|
||||
ServiceUtil.assertion(!res.isSuccess(), "设备充值失败:" + res.getMsg());
|
||||
return true;
|
||||
|
@ -927,13 +927,13 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
|
|||
// 充值时长
|
||||
if (SuitFeeType.TIME.getType().equals(bill.getSuitFeeType())) {
|
||||
// 计算开始使用的时间
|
||||
LocalDateTime endTime = startTime.plusSeconds(bill.toSecondSuitTime());
|
||||
LocalDateTime endTime = startTime.plusSeconds(transactionBillConverter.toRechargeSeconds(bill));
|
||||
data.setSuitEndTime(endTime);
|
||||
data.setSuitExpireTime(endTime);
|
||||
}
|
||||
// 充值电量
|
||||
else if (SuitFeeType.COUNT.getType().equals(bill.getSuitFeeType())) {
|
||||
data.setSuitEndEle(device.getTotalElectriQuantity().add(BigDecimal.valueOf(bill.getSuitTime())));
|
||||
data.setSuitEndEle(device.getTotalElectriQuantity().add(transactionBillConverter.toRechargeEle(bill)));
|
||||
}
|
||||
return transactionBillMapper.updateSmTransactionBill(data);
|
||||
}
|
||||
|
@ -1169,8 +1169,11 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
|
|||
|
||||
// 尝试设备清零时长、电量
|
||||
if (withDevice) {
|
||||
int clear = deviceService.clearTimeAndEle(device, false);
|
||||
ServiceUtil.assertion(clear != 1, "设备归零失败");
|
||||
if (SuitFeeType.TIME.getType().equals(order.getSuitFeeType())) {
|
||||
deviceService.resetTime(device, true);
|
||||
} else if (SuitFeeType.COUNT.getType().equals(order.getSuitFeeType())) {
|
||||
deviceService.resetEle(device, true);
|
||||
}
|
||||
}
|
||||
|
||||
return update;
|
||||
|
@ -1199,29 +1202,27 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
|
|||
TransactionBillVO bill = selectSmTransactionBillByBillId(billId);
|
||||
ServiceUtil.assertion(bill == null, "计算金额出错,订单不存在");
|
||||
|
||||
// 计量收费,则获取最新的设备信息
|
||||
if(SuitFeeType.COUNT.getType().equals(bill.getSuitFeeType()) || SuitFeeType.TIMING_COUNT.getType().equals(bill.getSuitFeeType())) {
|
||||
DeviceVO device = deviceService.selectById(bill.getDeviceId());
|
||||
deviceService.pullDeviceInfo(device);
|
||||
totalEle = this.calcTotalEle(device, totalEle);
|
||||
}
|
||||
|
||||
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||
// 智能计费
|
||||
if (SuitFeeMode.SMART.getMode().equals(bill.getSuitFeeMode())) {
|
||||
if (SuitFeeType.timingList().contains(bill.getSuitFeeType())) {
|
||||
// 分时段计费
|
||||
totalAmount = this.calcTimingAmount(bill, endTime, totalEle);
|
||||
return this.calcTimingAmount(bill, endTime, totalEle);
|
||||
} else {
|
||||
// 非分时段计费
|
||||
BigDecimal refundAmount = this.calcRefundAmount(bill, endTime, totalEle);
|
||||
totalAmount = bill.getMoney().subtract(refundAmount);
|
||||
return this.calcSmartAmount(bill, endTime, totalEle);
|
||||
}
|
||||
}
|
||||
// 非智能计费
|
||||
else {
|
||||
totalAmount = bill.getMoney();
|
||||
return bill.getMoney();
|
||||
}
|
||||
|
||||
return totalAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1295,26 +1296,38 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
|
|||
return EndUseVO.toResult(result, true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算退款金额
|
||||
*/
|
||||
private BigDecimal calcRefundAmount(TransactionBillVO order, LocalDateTime endTime, BigDecimal totalEle) {
|
||||
BigDecimal refund = BigDecimal.ZERO;
|
||||
BigDecimal refund = order.getMoney().subtract(this.calcSmartAmount(order, endTime, totalEle));
|
||||
|
||||
// 退款金额不允许大于订单金额
|
||||
if (refund.compareTo(order.getMoney()) > 0) {
|
||||
return order.getMoney();
|
||||
}
|
||||
// 退款金额不允许小于0
|
||||
if (refund.compareTo(BigDecimal.ZERO) < 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return refund;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算智能收费实际使用金额
|
||||
*/
|
||||
private BigDecimal calcSmartAmount(TransactionBillVO order, LocalDateTime endTime, BigDecimal totalEle) {
|
||||
// 智能收费时长计费
|
||||
if (SuitFeeType.TIME.getType().equals(order.getSuitFeeType())) {
|
||||
refund = this.calcTimeRefund(order, endTime);
|
||||
return this.calcSmartTimeAmount(order, endTime);
|
||||
}
|
||||
// 智能收费计量收费
|
||||
else if (SuitFeeType.COUNT.getType().equals(order.getSuitFeeType())) {
|
||||
refund = this.calcCountRefund(order, totalEle);
|
||||
return this.calcSmartCountAmount(order, totalEle);
|
||||
}
|
||||
else {
|
||||
throw new ServiceException("不支持的智能收费方式");
|
||||
}
|
||||
|
||||
// 退款金额不允许大于订单金额
|
||||
if (refund.compareTo(order.getMoney()) > 0) {
|
||||
refund = order.getMoney();
|
||||
}
|
||||
|
||||
return refund;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1325,40 +1338,39 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
|
|||
return this.selectSmTransactionBillList(query);
|
||||
}
|
||||
|
||||
// 计算智能计量收费需要退款的金额
|
||||
private BigDecimal calcCountRefund(TransactionBillVO order, BigDecimal totalEle) {
|
||||
// 计算智能计量使用金额
|
||||
private BigDecimal calcSmartCountAmount(TransactionBillVO order, BigDecimal totalEle) {
|
||||
BigDecimal startEle = order.getSuitStartEle();
|
||||
BigDecimal usedEle = totalEle.subtract(startEle); // 已使用的电量
|
||||
BigDecimal suitTotalEle = BigDecimal.valueOf(order.getSuitTime()); // 套餐总电量
|
||||
BigDecimal suitTotalEle = transactionBillConverter.toRechargeEle(order); // 套餐总电量
|
||||
|
||||
// 计算总使用的周期数,不满足一个周期也算一个周期
|
||||
BigDecimal totalRound = usedEle.divide(suitTotalEle, 0, RoundingMode.UP);
|
||||
|
||||
// 退款金额 = 订单金额 - 使用周期数 * 单价
|
||||
return order.getMoney()
|
||||
.subtract(
|
||||
totalRound.multiply(order.getSuitPrice())
|
||||
);
|
||||
if (totalRound.compareTo(BigDecimal.ZERO) <= 0 ) {
|
||||
totalRound = BigDecimal.ONE;
|
||||
}
|
||||
// 使用金额 = 使用周期数 * 单价
|
||||
return totalRound.multiply(order.getSuitPrice());
|
||||
}
|
||||
|
||||
// 计算智能时长收费需要退款的金额
|
||||
private BigDecimal calcTimeRefund(TransactionBillVO order, LocalDateTime endTime) {
|
||||
// 计算智能时长的使用金额
|
||||
private BigDecimal calcSmartTimeAmount(TransactionBillVO order, LocalDateTime endTime) {
|
||||
LocalDateTime startTime = order.getSuitStartTime();
|
||||
Duration between = Duration.between(startTime, endTime);
|
||||
|
||||
SuitTimeUnit unit = SuitTimeUnit.getByValue(order.getSuitTimeUnit());
|
||||
ServiceUtil.assertion(unit == null, "订单套餐单位无效");
|
||||
|
||||
long totalSeconds = unit.getConversion() * order.getSuitTime(); // 总时长
|
||||
|
||||
// 计算总使用的周期数,不满足一个周期也算一个周期
|
||||
long totalRound = totalSeconds / order.getSuitTime() + (totalSeconds % order.getSuitTime() != 0 ? 1 : 0);
|
||||
long totalSeconds = between.getSeconds(); // 总使用时长
|
||||
long secondSuitTime = transactionBillConverter.toSecondSuitTime(order);
|
||||
long totalRound = totalSeconds / secondSuitTime + (totalSeconds % secondSuitTime != 0 ? 1 : 0);
|
||||
if (totalRound <= 0) {
|
||||
totalRound = 1;
|
||||
}
|
||||
|
||||
// 退款金额 = 订单金额 - 使用周期数 * 单价
|
||||
return order.getMoney()
|
||||
.subtract(
|
||||
BigDecimal.valueOf(totalRound).multiply(order.getSuitPrice())
|
||||
);
|
||||
// 使用金额 = 使用周期数 * 单价
|
||||
return BigDecimal.valueOf(totalRound).multiply(order.getSuitPrice());
|
||||
}
|
||||
|
||||
// 计算分时段计量金额
|
||||
|
@ -1616,7 +1628,7 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
|
|||
ServiceUtil.assertion(updateInfo != 1, "更新套餐使用信息失败");
|
||||
|
||||
// 修改剩余时间失败
|
||||
boolean addTime = deviceService.addTime(bill.getDeviceId(), bill.toSecondSuitTime(), false);
|
||||
boolean addTime = deviceService.addTime(bill.getDeviceId(), transactionBillConverter.toRechargeSeconds(bill), false);
|
||||
ServiceUtil.assertion(!addTime, "修改剩余时间失败");
|
||||
|
||||
return result;
|
||||
|
@ -1643,7 +1655,7 @@ public class TransactionBillServiceImpl implements TransactionBillService, After
|
|||
SmUserVo user = userService.selectSmUserByUserId(bill.getUserId());
|
||||
// 根据订单套餐类型记录
|
||||
if (SuitFeeType.TIME.getType().equals(bill.getSuitFeeType())) {
|
||||
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, bill.toSecondSuitTime(), reason, user, RecordTimeType.TIME.getType()));
|
||||
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, transactionBillConverter.toRechargeSeconds(bill), reason, user, RecordTimeType.TIME.getType()));
|
||||
} else if (SuitFeeType.COUNT.getType().equals(bill.getSuitFeeType())) {
|
||||
recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, bill.getSuitTime(), reason, user, RecordTimeType.ELE.getType()));
|
||||
}
|
||||
|
|
|
@ -127,8 +127,10 @@ public class TransactionBillValidatorImpl extends BaseValidator implements Trans
|
|||
if (suit.getPrice().compareTo(dto.getSuitPrice()) != 0) {
|
||||
return error("当前套餐价格已发生变化,请重新下单");
|
||||
}
|
||||
if (suit.getDeposit().compareTo(dto.getSuitDeposit()) != 0) {
|
||||
return error("当前套餐押金已发生变化,请重新下单");
|
||||
if (SuitFeeMode.SMART.getMode().equals(suit.getFeeMode())) {
|
||||
if (suit.getDeposit().compareTo(dto.getSuitDeposit()) != 0) {
|
||||
return error("当前套餐押金已发生变化,请重新下单");
|
||||
}
|
||||
}
|
||||
if (!suit.getFeeMode().equals(dto.getSuitFeeMode())) {
|
||||
return error("当前套餐收费模式发生变化,请重新下单");
|
||||
|
|
Loading…
Reference in New Issue
Block a user