diff --git a/smart-switch-ruoyi/smart-switch-system/src/main/java/com/ruoyi/system/valid/DictValid.java b/smart-switch-ruoyi/smart-switch-system/src/main/java/com/ruoyi/system/valid/DictValid.java new file mode 100644 index 00000000..5a3e57bb --- /dev/null +++ b/smart-switch-ruoyi/smart-switch-system/src/main/java/com/ruoyi/system/valid/DictValid.java @@ -0,0 +1,42 @@ +package com.ruoyi.system.valid; + + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +/** + * 枚举值校验注解 + * @author wjh + * 2023/10/20 + */ +@Documented +@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE }) +@Retention(RetentionPolicy.RUNTIME) +@Repeatable(DictValid.List.class) +@Constraint(validatedBy = { DictValidator.class }) +public @interface DictValid { + + String message() default "{*.validation.constraint.Enum.message}"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + /** + * 字典类型 + */ + String type(); + + /** + * 是否允许null值,默认是允许 + */ + boolean allowNull() default true; + + @Documented + @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE }) + @Retention(RetentionPolicy.RUNTIME) + @interface List { + DictValid[] value(); + } +} diff --git a/smart-switch-ruoyi/smart-switch-system/src/main/java/com/ruoyi/system/valid/DictValidator.java b/smart-switch-ruoyi/smart-switch-system/src/main/java/com/ruoyi/system/valid/DictValidator.java new file mode 100644 index 00000000..74e24037 --- /dev/null +++ b/smart-switch-ruoyi/smart-switch-system/src/main/java/com/ruoyi/system/valid/DictValidator.java @@ -0,0 +1,55 @@ +package com.ruoyi.system.valid; + +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.collection.CollectionUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.service.ISysDictTypeService; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 2023/10/20 + * 枚举值校验 + */ +public class DictValidator implements ConstraintValidator { + + private DictValid annotation; + + @Override + public void initialize(DictValid constraintAnnotation) { + this.annotation = constraintAnnotation; + } + + /** + * 判断是否校验成功 + * @param value 待校验的值 + * @return 校验结果 + */ + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + // 如果待校验的值为null,是否校验通过 + if (value == null) { + return annotation.allowNull(); + } + try { + // 判断是否存在类型 + if (StringUtils.hasText(annotation.type())) { + ISysDictTypeService service = SpringUtils.getBean(ISysDictTypeService.class); + List dictList = service.selectDictDataByType(annotation.type()); + if (CollectionUtils.isNotEmptyElement(dictList)) { + List values = dictList.stream().map(SysDictData::getDictValue).collect(Collectors.toList()); + return values.contains(value); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + // 如果value没有在枚举值中,校验失败 + return false; + } +} + diff --git a/smart-switch-service/src/main/java/com/ruoyi/common/constants/DictTypeConstants.java b/smart-switch-service/src/main/java/com/ruoyi/common/constants/DictTypeConstants.java new file mode 100644 index 00000000..f5533fdb --- /dev/null +++ b/smart-switch-service/src/main/java/com/ruoyi/common/constants/DictTypeConstants.java @@ -0,0 +1,12 @@ +package com.ruoyi.common.constants; + +/** + * 字典类型 + * @author wjh + * 2024/7/17 + */ +public class DictTypeConstants { + + // 套餐时长单位 + public static final String SUIT_TIME_UNIT = "suit_time_unit"; +} diff --git a/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java b/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java index 2216674f..801f88ff 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java +++ b/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotService.java @@ -9,7 +9,6 @@ import com.ruoyi.iot.domain.response.CommandResponse; import com.ruoyi.ss.device.domain.SmDevice; import com.ruoyi.ss.device.domain.enums.DeviceOnlineStatus; -import java.math.BigDecimal; import java.util.List; /** @@ -76,7 +75,7 @@ public interface IotService { * @param deviceName 设备名称 * @param seconds 时长(秒) */ - CommandResponse setTime(String deviceName, BigDecimal seconds); + CommandResponse setTime(String deviceName, long seconds); /** * 更新设备信息 diff --git a/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotServiceImpl.java index 56aff563..2ca19c25 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotServiceImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/iot/service/IotServiceImpl.java @@ -180,9 +180,9 @@ public class IotServiceImpl implements IotService { */ @Override @Transactional - public CommandResponse setTime(String deviceName, BigDecimal seconds) { - if (seconds == null || BigDecimal.ZERO.compareTo(seconds) > 0) { - throw new ServiceException("设置剩余时长参数错误:读数不允许为空或者小于0"); + public CommandResponse setTime(String deviceName, long seconds) { + if (seconds < 0) { + throw new ServiceException("设置剩余时长参数错误:读数不允许小于0"); } return sendCommand(deviceName, IotConstants.COMMAND_RECHARGE + seconds + IotConstants.COMMAND_SEPARATOR); } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/SmDeviceMapper.java b/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/SmDeviceMapper.java index f1849f8c..64f29e6e 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/SmDeviceMapper.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/SmDeviceMapper.java @@ -74,10 +74,11 @@ public interface SmDeviceMapper /** * 增加设备时长 + * * @param deviceId 设备 - * @param num 增加的量 + * @param time 增加的量 */ - int addTime(@Param("deviceId") Long deviceId, @Param("num") BigDecimal num); + int addTime(@Param("deviceId") Long deviceId, @Param("num") long time); /** * 逻辑删除 diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/SmDeviceMapper.xml b/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/SmDeviceMapper.xml index c0acd5ad..89136308 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/SmDeviceMapper.xml +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/mapper/SmDeviceMapper.xml @@ -281,8 +281,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" update sm_device set expire_time = IF ( (expire_time is null) or (now() > expire_time), - DATE_ADD(now(),INTERVAL #{num} MINUTE), - DATE_ADD(expire_time,INTERVAL #{num} MINUTE) + DATE_ADD(now(),INTERVAL #{num} SECOND), + DATE_ADD(expire_time,INTERVAL #{num} SECOND) ) where device_id = #{deviceId} and deleted = false diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/DeviceService.java b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/DeviceService.java index a5233192..241b713a 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/DeviceService.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/DeviceService.java @@ -78,10 +78,10 @@ public interface DeviceService * 增加时间 * * @param deviceId 设备id - * @param num 电量 - * @param withIot + * @param seconds 时长(秒) + * @param withIot 是否充值物联网设备 */ - boolean addTime(Long deviceId, BigDecimal num, boolean withIot); + boolean addTime(Long deviceId, long seconds, boolean withIot); /** * 逻辑删除 @@ -213,7 +213,7 @@ public interface DeviceService */ void deviceHeartBeat(); - boolean addTimeByUser(Long deviceId, BigDecimal amount, boolean b, String reason); + boolean addTimeByUser(Long deviceId, long seconds, boolean b, String reason); /** * 设备注册 diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java index 51d339c7..90892ea1 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/device/service/impl/DeviceServiceImpl.java @@ -1,6 +1,8 @@ package com.ruoyi.ss.device.service.impl; import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.core.redis.RedisLock; import com.ruoyi.common.enums.LoginType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.*; @@ -28,7 +30,6 @@ import com.ruoyi.ss.record.time.service.RecordTimeConverter; import com.ruoyi.ss.store.domain.StoreVo; import com.ruoyi.ss.store.service.IStoreService; import com.ruoyi.ss.suit.service.SuitService; -import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery; import com.ruoyi.ss.transactionBill.domain.TransactionBillVo; import com.ruoyi.ss.transactionBill.service.TransactionBillService; import com.ruoyi.ss.user.domain.SmUserVo; @@ -99,6 +100,9 @@ public class DeviceServiceImpl implements DeviceService @Autowired private TransactionBillService transactionBillService; + @Autowired + private RedisLock redisLock; + /** * 查询设备 * @@ -139,7 +143,25 @@ public class DeviceServiceImpl implements DeviceService data.setCreateTime(DateUtils.getNowDate()); data.setStatus(DeviceStatus.NORMAL.getStatus()); - return smDeviceMapper.insertSmDevice(data); + + Integer result = transactionTemplate.execute(status -> { + int insert = smDeviceMapper.insertSmDevice(data); + ServiceUtil.assertion(insert != 1, "新增设备失败"); + + SmDeviceQuery snQuery = new SmDeviceQuery(); + snQuery.setDeviceNo(data.getDeviceNo()); + int snCount = selectCount(snQuery); + ServiceUtil.assertion(snCount != 1, "SN重复"); + + SmDeviceQuery macQuery = new SmDeviceQuery(); + macQuery.setMac(data.getMac()); + int macCount = selectCount(macQuery); + ServiceUtil.assertion(macCount != 1, "MAC重复"); + + return insert; + }); + + return result == null ? 0 : result; } /** @@ -243,14 +265,14 @@ public class DeviceServiceImpl implements DeviceService @Override @Transactional(propagation = Propagation.REQUIRES_NEW) - public boolean addTimeByUser(Long deviceId, BigDecimal amount, boolean withIot, String reason) { - boolean b = this.addTime(deviceId, amount, withIot); + public boolean addTimeByUser(Long deviceId, long seconds, boolean withIot, String reason) { + boolean b = this.addTime(deviceId, seconds, withIot); // 记录下操作日志 LoginUser loginUser = SecurityUtils.getLoginUser(); scheduledExecutorService.schedule(() -> { SmDeviceVO device = smDeviceMapper.selectSmDeviceByDeviceId(deviceId); - recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, amount, reason, loginUser)); + recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, seconds, reason, loginUser)); }, 0, TimeUnit.SECONDS); return b; @@ -307,8 +329,8 @@ public class DeviceServiceImpl implements DeviceService @Override @Transactional(propagation = Propagation.REQUIRES_NEW) - public boolean addTime(Long deviceId, BigDecimal num, boolean withIot) { - ServiceUtil.assertion(num.compareTo(BigDecimal.ZERO) < 0, "增加的时长不允许小于0"); + public boolean addTime(Long deviceId, long seconds, boolean withIot) { + ServiceUtil.assertion( seconds < 0, "增加的时长不允许小于0"); SmDeviceVO device = smDeviceMapper.selectSmDeviceByDeviceId(deviceId); ServiceUtil.assertion(device == null, "设备不存在"); @@ -316,7 +338,7 @@ public class DeviceServiceImpl implements DeviceService ServiceUtil.assertion(DeviceStatus.FIXING.getStatus().equals(device.getStatus()), "设备正在维修中,无法使用"); // 更新数据库时长 - int updateCount = smDeviceMapper.addTime(deviceId, num); + int updateCount = smDeviceMapper.addTime(deviceId, seconds); ServiceUtil.assertion(updateCount != 1, "增加时长失败,请刷新后重试"); // 修改状态为使用中 @@ -325,9 +347,9 @@ public class DeviceServiceImpl implements DeviceService // 物联网设备增加时长 if (withIot) { SmDeviceVO newDevice = selectSmDeviceByDeviceId(deviceId); - long seconds = Duration.between(LocalDateTime.now(), newDevice.getExpireTime()).getSeconds(); - if (seconds > 0) { - CommandResponse rechargeResult = iotService.setTime(device.getMac(), new BigDecimal(seconds)); + long betweenSeconds = Duration.between(LocalDateTime.now(), newDevice.getExpireTime()).getSeconds(); + if (betweenSeconds > 0) { + CommandResponse rechargeResult = iotService.setTime(device.getMac(), betweenSeconds); ServiceUtil.assertion(!rechargeResult.isSuccess(), "设备充值失败,请检查设备是否在线或联系管理员"); } } @@ -338,7 +360,7 @@ public class DeviceServiceImpl implements DeviceService // 时长结束后修改设备状态 scheduledExecutorService.schedule(()-> { freshStatus(deviceId); - }, num.intValue(), TimeUnit.MINUTES); + }, seconds, TimeUnit.MINUTES); return true; } @@ -609,7 +631,7 @@ public class DeviceServiceImpl implements DeviceService transactionBillService.batchEndBillByDevice(deviceId); // 物联网设备归零 - CommandResponse commandResponse = iotService.setTime(device.getMac(), BigDecimal.ONE); + CommandResponse commandResponse = iotService.setTime(device.getMac(), 0L); ServiceUtil.assertion(!commandResponse.isSuccess(), "设备归零失败,请检查设备是否在线或联系管理员"); // 归零记录 @@ -617,8 +639,7 @@ public class DeviceServiceImpl implements DeviceService scheduledExecutorService.schedule(() -> { // 设备剩余时长 Duration duration = Duration.between(now, device.getExpireTime()); - BigDecimal surplusTime = new BigDecimal(-duration.toMinutes()); - recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, surplusTime, "设备归零", loginUser)); + recordTimeService.insertRecordTime(recordTimeConverter.toRecordTime(device, -duration.toMinutes(), "设备归零", loginUser)); }, 0, TimeUnit.SECONDS); return true; diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/domain/RecordTime.java b/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/domain/RecordTime.java index c6ecab86..9bf14da5 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/domain/RecordTime.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/domain/RecordTime.java @@ -28,9 +28,9 @@ public class RecordTime extends BaseEntity @Excel(name = "设备id") private Long deviceId; - /** 时长变化量(分钟) */ - @Excel(name = "时长变化量", readConverterExp = "分=钟") - private BigDecimal amount; + /** 时长变化量(秒) */ + @Excel(name = "时长变化量(秒)") + private Long amount; /** 变化原因 */ @Excel(name = "变化原因") diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/service/RecordTimeConverter.java b/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/service/RecordTimeConverter.java index b42bfa9b..783f33c5 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/service/RecordTimeConverter.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/service/RecordTimeConverter.java @@ -4,14 +4,12 @@ import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.ss.device.domain.SmDevice; import com.ruoyi.ss.record.time.domain.RecordTime; -import java.math.BigDecimal; - /** * @author wjh * 2024/6/6 */ public interface RecordTimeConverter { - RecordTime toRecordTime(SmDevice device, BigDecimal time, String reason, LoginUser loginUser); + RecordTime toRecordTime(SmDevice device, long seconds, String reason, LoginUser loginUser); } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/service/impl/RecordTimeConverterImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/service/impl/RecordTimeConverterImpl.java index a7d1ed40..ec220874 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/service/impl/RecordTimeConverterImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/record/time/service/impl/RecordTimeConverterImpl.java @@ -2,14 +2,12 @@ package com.ruoyi.ss.record.time.service.impl; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.enums.LoginType; -import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.ss.device.domain.SmDevice; import com.ruoyi.ss.record.time.domain.RecordTime; import com.ruoyi.ss.record.time.domain.enums.OperatorType; import com.ruoyi.ss.record.time.service.RecordTimeConverter; import org.springframework.stereotype.Service; -import java.math.BigDecimal; import java.time.LocalDateTime; /** @@ -19,10 +17,10 @@ import java.time.LocalDateTime; @Service public class RecordTimeConverterImpl implements RecordTimeConverter { @Override - public RecordTime toRecordTime(SmDevice device, BigDecimal time, String reason, LoginUser loginUser) { + public RecordTime toRecordTime(SmDevice device, long seconds, String reason, LoginUser loginUser) { RecordTime record = new RecordTime(); record.setDeviceId(device == null ? null : device.getDeviceId()); - record.setAmount(time); + record.setAmount(seconds); record.setReason(reason); record.setOperatorId(loginUser.getUserId()); record.setOperatorName(loginUser.getUsername()); diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/Suit.java b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/Suit.java index 6fec6189..f301999f 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/Suit.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/Suit.java @@ -2,15 +2,18 @@ package com.ruoyi.ss.suit.domain; import com.fasterxml.jackson.annotation.JsonView; import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.constants.DictTypeConstants; import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.JsonViewProfile; import com.ruoyi.common.core.domain.ValidGroup; +import com.ruoyi.system.valid.DictValid; import com.ruoyi.common.validRule.suitExist.SuitExist; import com.ruoyi.ss.device.domain.DeviceView; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import java.math.BigDecimal; @@ -45,11 +48,11 @@ public class Suit extends BaseEntity private String name; /** 通电时间(分) */ - @Excel(name = "通电时间(分钟)") + @Excel(name = "通电时间") @JsonView({DeviceView.SuitList.class, JsonViewProfile.AppMch.class}) @NotNull(message = "通电时间不允许为空", groups = {ValidGroup.Create.class, ValidGroup.FrontCreate.class}) - @Min(value = 1, message = "通电时间不允许小于1分钟") - private BigDecimal value; + @Min(value = 1, message = "通电时间不允许小于1") + private Long value; /** 价格(元) */ @Excel(name = "价格(元)") @@ -68,4 +71,10 @@ public class Suit extends BaseEntity @JsonView({JsonViewProfile.AppMch.class}) @SuitExist(message = "来源套餐不存在", checkBelong = true, groups = {ValidGroup.FrontCreate.class}) private Long sourceId; + + @ApiModelProperty("套餐时长单位") + @JsonView({DeviceView.SuitList.class, JsonViewProfile.AppMch.class}) + @NotBlank(message = "套餐时长单位不允许为空", groups = {ValidGroup.Create.class, ValidGroup.FrontCreate.class}) + @DictValid(type = DictTypeConstants.SUIT_TIME_UNIT, message = "非法的套餐时长单位") + private String timeUnit; } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/SuitBO.java b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/SuitBO.java index 9f52d300..3c4c9172 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/SuitBO.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/SuitBO.java @@ -20,6 +20,7 @@ public class SuitBO extends Suit { bo.setValue(getValue()); bo.setPrice(getPrice()); bo.setDescription(getDescription()); + bo.setTimeUnit(getTimeUnit()); return bo; } @@ -35,6 +36,7 @@ public class SuitBO extends Suit { bo.setValue(getValue()); bo.setPrice(getPrice()); bo.setDescription(getDescription()); + bo.setTimeUnit(getTimeUnit()); return bo; } } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/enums/SuitTimeUnit.java b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/enums/SuitTimeUnit.java new file mode 100644 index 00000000..3252ba87 --- /dev/null +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/domain/enums/SuitTimeUnit.java @@ -0,0 +1,33 @@ +package com.ruoyi.ss.suit.domain.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Objects; + +/** + * @author wjh + * 2024/7/17 + */ +@Getter +@AllArgsConstructor +public enum SuitTimeUnit { + + DAY("1", 86400L), + HOUR("2", 3600L), + MINUTE("3", 60L), + SECOND("4", 1L); + + private final String value; + private final Long conversion; + + public static SuitTimeUnit getByValue(String value) { + for (SuitTimeUnit suit : SuitTimeUnit.values()) { + if (Objects.equals(suit.getValue(), value)) { + return suit; + } + } + return null; + } + +} diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/mapper/SuitMapper.xml b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/mapper/SuitMapper.xml index f3c8e7eb..4bbdaab5 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/suit/mapper/SuitMapper.xml +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/suit/mapper/SuitMapper.xml @@ -20,6 +20,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ss.update_by, ss.deleted, ss.source_id, + ss.time_unit, sd.device_name as device_name, su.user_name as user_name, store.name as store_name @@ -102,6 +103,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" update_by, deleted, source_id, + time_unit, #{deviceId}, @@ -115,6 +117,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{updateBy}, #{deleted}, #{sourceId}, + #{timeUnit}, @@ -157,6 +160,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" default, #{i.sourceId} default, + #{i.timeUnit} + default, @@ -179,6 +184,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" update_time = #{updateTime}, update_by = #{updateBy}, source_id = #{sourceId}, + time_unit = #{timeUnit}, diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBill.java b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBill.java index 3244756b..ea345579 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBill.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBill.java @@ -3,13 +3,16 @@ package com.ruoyi.ss.transactionBill.domain; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonView; import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.constants.DictTypeConstants; import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.JsonViewProfile; import com.ruoyi.common.core.domain.ValidGroup; +import com.ruoyi.system.valid.DictValid; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -125,10 +128,15 @@ public class TransactionBill extends BaseEntity @JsonView(JsonViewProfile.App.class) private Long suitId; - @ApiModelProperty("套餐时长(分钟)") + @ApiModelProperty("套餐时长(秒)") @NotNull(message = "套餐时长不允许为空", groups = {ValidGroup.Recharge.class}) @JsonView(JsonViewProfile.App.class) - private BigDecimal suitTime; + private Long suitTime; + + @ApiModelProperty("套餐时长单位") + @NotBlank(message = "套餐时长单位不允许为空", groups = {ValidGroup.Recharge.class}) + @DictValid(type = DictTypeConstants.SUIT_TIME_UNIT, message = "非法的套餐时长单位", groups = {ValidGroup.Recharge.class}) + private String suitTimeUnit; @ApiModelProperty("套餐开始使用时间") private LocalDateTime suitStartTime; @@ -171,5 +179,4 @@ public class TransactionBill extends BaseEntity @ApiModelProperty("服务费退款金额") private BigDecimal refundServiceAmount; - } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBillVo.java b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBillVo.java index 14b68713..4247b4c4 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBillVo.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/domain/TransactionBillVo.java @@ -2,6 +2,7 @@ package com.ruoyi.ss.transactionBill.domain; import com.fasterxml.jackson.annotation.JsonView; import com.ruoyi.common.core.domain.JsonViewProfile; +import com.ruoyi.ss.suit.domain.enums.SuitTimeUnit; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -27,4 +28,16 @@ public class TransactionBillVo extends TransactionBill { @ApiModelProperty("商户手机号") private String mchMobile; + + /** + * 获取套餐时长(秒) + */ + public long toSecondSuitTime() { + SuitTimeUnit unit = SuitTimeUnit.getByValue(this.getSuitTimeUnit()); + if (unit == null) { + unit = SuitTimeUnit.MINUTE; + } + long time = this.getSuitTime() == null ? 0 : this.getSuitTime(); + return time * unit.getConversion(); + } } diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java index 08e31f7b..8f43523b 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillServiceImpl.java @@ -217,9 +217,6 @@ public class TransactionBillServiceImpl implements TransactionBillService { @Override @Transactional(rollbackFor = Exception.class) public String addOrder(TransactionBill data) { - // 校验 - ServiceUtil.assertion(transactionBillValidator.preAddOrder(data)); - // 下单 TransactionBill order = parseToOrder(data); ServiceUtil.assertion(this.insertSmTransactionBill(order) != 1, "下单失败"); @@ -232,11 +229,15 @@ public class TransactionBillServiceImpl implements TransactionBillService { // 转换为订单所需的数据 private TransactionBill parseToOrder(TransactionBill data) { + // 校验 + ServiceUtil.assertion(transactionBillValidator.preAddOrder(data)); + TransactionBill order = new TransactionBill(); // 基础信息 order.setUserId(data.getUserId()); order.setSuitTime(data.getSuitTime()); - order.setDeviceNo(data.getDeviceNo()); // 设备ID + order.setSuitTimeUnit(data.getSuitTimeUnit()); + order.setDeviceNo(data.getDeviceNo()); // 设备编号 order.setChannelId(data.getChannelId()); order.setMoney(data.getMoney()); order.setSuitId(data.getSuitId()); @@ -246,21 +247,25 @@ public class TransactionBillServiceImpl implements TransactionBillService { // 设备信息 SmDeviceVO device = deviceService.selectByDeviceNo(order.getDeviceNo()); - if (device != null) { - order.setDeviceId(device.getDeviceId()); - order.setMchId(device.getUserId()); // 到账人ID - order.setDeviceName(device.getDeviceName()); - order.setDeviceMac(device.getMac()); + ServiceUtil.assertion(device == null, "设备不存在"); + order.setDeviceId(device.getDeviceId()); + order.setMchId(device.getUserId()); // 到账人ID + order.setDeviceName(device.getDeviceName()); + order.setDeviceMac(device.getMac()); - // 店铺信息 - order.setStoreId(device.getStoreId()); - StoreVo store = storeService.selectSmStoreById(device.getStoreId()); - if (store != null) { - order.setStoreName(store.getName()); - order.setStoreAddress(String.format("%s%s%s%s", store.getProvince(), store.getCity(), store.getCounty(), store.getAddress())); - } + // 店铺信息 + order.setStoreId(device.getStoreId()); + StoreVo store = storeService.selectSmStoreById(device.getStoreId()); + if (store != null) { + order.setStoreName(store.getName()); + order.setStoreAddress(String.format("%s%s%s%s", store.getProvince(), store.getCity(), store.getCounty(), store.getAddress())); } + // 套餐信息 + SuitVo suit = suitService.selectSuitBySuitId(order.getSuitId()); + ServiceUtil.assertion(suit == null, "套餐不存在"); + order.setSuitName(suit.getName()); + // 支付过期时间 long expireTime = TimeUnit.MILLISECONDS.convert(Constants.BILL_UNPAID_TIMEOUT, Constants.BILL_UNPAID_TIMEUNIT) + System.currentTimeMillis(); order.setExpireTime(new Date(expireTime)); @@ -274,12 +279,6 @@ public class TransactionBillServiceImpl implements TransactionBillService { order.setArrivalAmount(arrivalAmount); order.setServiceCharge(serviceCharge); - // 套餐信息 - SuitVo suit = suitService.selectSuitBySuitId(order.getSuitId()); - if (suit != null) { - order.setSuitName(suit.getName()); - } - return order; } @@ -307,10 +306,8 @@ public class TransactionBillServiceImpl implements TransactionBillService { // 返回渠道服务费 SmChannel channel = channelService.selectSmChannelByChannelId(channelId); - if (channel != null) { - return channel.getServiceRate(); - } - return BigDecimal.ZERO; + ServiceUtil.assertion(channel == null, "支付渠道不存在"); + return channel.getServiceRate(); } @Override @@ -554,7 +551,7 @@ public class TransactionBillServiceImpl implements TransactionBillService { public boolean rechargeDevice(Long billId) { ServiceUtil.assertion(billId == null, "参数错误,billId不允许为空"); - TransactionBill bill = transactionBillMapper.selectSmTransactionBillByBillId(billId); + TransactionBillVo bill = transactionBillMapper.selectSmTransactionBillByBillId(billId); ServiceUtil.assertion(bill == null || !TransactionBillType.RECHARGE.getType().equals(bill.getType()), "不存在的充值订单"); ServiceUtil.assertion(!TransactionBillStatus.SUCCESS.getStatus().equals(bill.getStatus()), "订单未支付"); @@ -564,7 +561,7 @@ public class TransactionBillServiceImpl implements TransactionBillService { // 电表时长增加,四舍五入,保留1位小数 boolean success = false; try { - success = deviceService.addTime(bill.getDeviceId(), bill.getSuitTime(), true); + success = deviceService.addTime(bill.getDeviceId(), bill.toSecondSuitTime(), true); } catch (Exception e) { this.handleDeviceRechargeFail(billId); } @@ -593,7 +590,7 @@ public class TransactionBillServiceImpl implements TransactionBillService { LocalDateTime now = LocalDateTime.now(); LocalDateTime startTime = now.isAfter(deviceExpireTime) ? now : deviceExpireTime; - LocalDateTime endTime = startTime.plusMinutes(bill.getSuitTime().longValue()); + LocalDateTime endTime = startTime.plusSeconds(bill.toSecondSuitTime()); TransactionBill data = new TransactionBill(); data.setBillId(billId); data.setSuitStartTime(startTime); @@ -839,7 +836,7 @@ public class TransactionBillServiceImpl implements TransactionBillService { @Transactional public boolean bluetoothRechargeSuccess(String billNo) { Boolean execute = transactionTemplate.execute(status -> { - TransactionBill bill = selectSmTransactionBillByBillNo(billNo); + TransactionBillVo bill = selectSmTransactionBillByBillNo(billNo); ServiceUtil.assertion(bill == null, "订单不存在", 10001); ServiceUtil.assertion(!TransactionBillType.RECHARGE.getType().equals(bill.getType()), "该订单不是充值订单", 10002); ServiceUtil.assertion(TransactionBillDeviceRechargeStatus.SUCCESS.getStatus().equals(bill.getDeviceRechargeStatus()), "设备已充值成功,请勿重复充值", 10003); @@ -851,7 +848,7 @@ public class TransactionBillServiceImpl implements TransactionBillService { SmDeviceVO afterDevice = deviceService.selectSmDeviceByDeviceId(bill.getDeviceId()); this.updateSuitTimeBeforeDevice(bill.getBillId(), afterDevice.getExpireTime()); - boolean addTime = deviceService.addTime(bill.getDeviceId(), bill.getSuitTime(), false); + boolean addTime = deviceService.addTime(bill.getDeviceId(), bill.toSecondSuitTime(), false); ServiceUtil.assertion(!addTime, "修改剩余时间失败"); // 时长变化记录 diff --git a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillValidatorImpl.java b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillValidatorImpl.java index f61e3934..d96020a5 100644 --- a/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillValidatorImpl.java +++ b/smart-switch-service/src/main/java/com/ruoyi/ss/transactionBill/service/impl/TransactionBillValidatorImpl.java @@ -86,10 +86,13 @@ public class TransactionBillValidatorImpl extends BaseValidator implements Trans if (suit.getPrice().compareTo(data.getMoney()) != 0) { return error("当前套餐价格已发生变化,请重新下单"); } - if (suit.getValue() == null) { + if (suit.getValue() == null || suit.getTimeUnit() == null) { return error("当前套餐未配置时间,请联系商户处理"); } - if (suit.getValue().compareTo(data.getSuitTime()) != 0) { + if (!suit.getValue().equals(data.getSuitTime())) { + return error("当前套餐时间已发生变化,请重新下单"); + } + if (!suit.getTimeUnit().equals(data.getSuitTimeUnit())) { return error("当前套餐时间已发生变化,请重新下单"); } diff --git a/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppDeviceController.java b/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppDeviceController.java index 1f88e1ac..f0fde233 100644 --- a/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppDeviceController.java +++ b/smart-switch-web/src/main/java/com/ruoyi/web/controller/app/AppDeviceController.java @@ -137,7 +137,7 @@ public class AppDeviceController extends BaseController { @ApiOperation("设备充值时长") @PutMapping("/addTime/{deviceId}") - public AjaxResult addTime(@PathVariable @ApiParam("设备id") Long deviceId, @ApiParam("电量(度)") BigDecimal amount) + public AjaxResult addTime(@PathVariable @ApiParam("设备id") Long deviceId, @ApiParam("电量(度)") Long amount) { ServiceUtil.assertion(!deviceValidator.isBelong(deviceId, getUserId()), "这不是您的设备"); SmDeviceVO device = smDeviceService.selectSmDeviceByDeviceId(deviceId); diff --git a/smart-switch-web/src/main/java/com/ruoyi/web/controller/ss/SmDeviceController.java b/smart-switch-web/src/main/java/com/ruoyi/web/controller/ss/SmDeviceController.java index 9b1bf857..61a163e3 100644 --- a/smart-switch-web/src/main/java/com/ruoyi/web/controller/ss/SmDeviceController.java +++ b/smart-switch-web/src/main/java/com/ruoyi/web/controller/ss/SmDeviceController.java @@ -153,7 +153,7 @@ public class SmDeviceController extends BaseController @ApiOperation("设备充值时长") @PreAuthorize("@ss.hasPermi('system:device:addTime')") @PutMapping("/addTime/{deviceId}") - public AjaxResult addTime(@PathVariable @ApiParam("设备id") Long deviceId, @ApiParam("电量(度)") BigDecimal amount) { + public AjaxResult addTime(@PathVariable @ApiParam("设备id") Long deviceId, @ApiParam("时长(秒)") Long amount) { return toAjax(smDeviceService.addTimeByUser(deviceId, amount, true, "管理员手动充值")); }