소스 검색

Merge remote-tracking branch 'origin/master' into prod

谭斌 1 년 전
부모
커밋
73be4c1062
31개의 변경된 파일1026개의 추가작업 그리고 17개의 파일을 삭제
  1. 24 6
      device-api-service-merc-mini/src/main/java/com/xy/controller/MercMiniDeviceController.java
  2. 2 2
      device-api-service-merc-mini/src/main/java/com/xy/controller/MercMiniDeviceHomePageController.java
  3. 5 2
      device-api-service/pom.xml
  4. 39 0
      device-api-service/src/main/java/com/xy/alipay/AliPay.java
  5. 133 0
      device-api-service/src/main/java/com/xy/alipay/AliPayAspet.java
  6. 61 0
      device-api-service/src/main/java/com/xy/alipay/AliPayUtils.java
  7. 24 0
      device-api-service/src/main/java/com/xy/consumer/connected/ConnectedMqttConfiguration.java
  8. 26 0
      device-api-service/src/main/java/com/xy/consumer/connected/ConnectedProducer.java
  9. 24 0
      device-api-service/src/main/java/com/xy/consumer/disconnect/DisconnectedMqttConfiguration.java
  10. 26 0
      device-api-service/src/main/java/com/xy/consumer/disconnect/DisconnectedProducer.java
  11. 45 0
      device-api-service/src/main/java/com/xy/entity/DeviceCharging.java
  12. 44 0
      device-api-service/src/main/java/com/xy/entity/DeviceChargingHistory.java
  13. 171 0
      device-api-service/src/main/java/com/xy/job/DeviceChargingJob.java
  14. 16 0
      device-api-service/src/main/java/com/xy/mapper/DeviceChargingHistoryMapper.java
  15. 24 0
      device-api-service/src/main/java/com/xy/mapper/DeviceChargingMapper.java
  16. 1 0
      device-api-service/src/main/java/com/xy/mapper/DeviceInfoMapper.java
  17. 18 0
      device-api-service/src/main/java/com/xy/mapper/mapper/DeviceChargingHistoryMapper.xml
  18. 18 0
      device-api-service/src/main/java/com/xy/mapper/mapper/DeviceChargingMapper.xml
  19. 24 0
      device-api-service/src/main/java/com/xy/service/DeviceChargingHistoryServiceImpl.java
  20. 44 0
      device-api-service/src/main/java/com/xy/service/DeviceChargingServiceImpl.java
  21. 2 2
      device-api-service/src/main/java/com/xy/service/DeviceCreateIdsServiceImpl.java
  22. 4 2
      device-api-service/src/main/java/com/xy/service/DeviceInfoServiceImpl.java
  23. 99 0
      device-api-service/src/main/java/com/xy/service/DeviceRegisterServiceImpl.java
  24. 2 1
      device-api-service/src/main/java/com/xy/service/MqttServiceImpl.java
  25. 5 0
      device-api-service/src/main/java/com/xy/utils/enums/DictEnum.java
  26. 10 0
      device-api-service/src/main/java/com/xy/utils/enums/DictSonEnum.java
  27. 55 0
      device-api/src/main/java/com/xy/dto/DeviceChargingDto.java
  28. 43 0
      device-api/src/main/java/com/xy/dto/DeviceChargingHistoryDto.java
  29. 16 0
      device-api/src/main/java/com/xy/service/DeviceChargingHistoryService.java
  30. 16 0
      device-api/src/main/java/com/xy/service/DeviceChargingService.java
  31. 5 2
      device-start/pom.xml

+ 24 - 6
device-api-service-merc-mini/src/main/java/com/xy/controller/MercMiniDeviceController.java

@@ -3,6 +3,7 @@ package com.xy.controller;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.xy.alipay.AliPay;
 import com.xy.annotate.RestMappingController;
 import com.xy.dto.DeviceBluetoothAuthDto;
 import com.xy.dto.DeviceInfoDto;
@@ -12,11 +13,10 @@ import com.xy.dto.be.MercDto;
 import com.xy.dto.common.MercLineDto;
 import com.xy.dto.common.MercPlaceDto;
 import com.xy.dto.mini.MiniMercRegionDto;
-import com.xy.entity.DeviceBluetoothAuth;
-import com.xy.entity.DeviceInfo;
-import com.xy.entity.DeviceSysinfo;
+import com.xy.entity.*;
 import com.xy.enums.MercStatus;
 import com.xy.service.DeviceBluetoothAuthServiceImpl;
+import com.xy.service.DeviceChargingServiceImpl;
 import com.xy.service.DeviceInfoServiceImpl;
 import com.xy.service.DeviceSysinfoServiceImpl;
 import com.xy.service.be.MercFeignService;
@@ -27,6 +27,7 @@ import com.xy.utils.enums.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -58,11 +59,14 @@ public class MercMiniDeviceController {
     private final DeviceInfoServiceImpl deviceInfoService;
 
     private final DeviceSysinfoServiceImpl deviceSysinfoService;
+
     private final MercPlaceService mercPlaceService;
+
     private final MercLineService mercLineService;
 
     private final DeviceBluetoothAuthServiceImpl deviceBluetoothAuthService;
 
+    private final DeviceChargingServiceImpl deviceChargingService;
 
     @ApiOperation("商户设备首页统计")
     @PostMapping("mercHomeStatistical")
@@ -177,25 +181,39 @@ public class MercMiniDeviceController {
 
     @PostMapping("active")
     @ApiOperation("激活设备")
+    @Transactional(rollbackFor = Exception.class)
     public R active(@RequestBody MercMiniDeviceDto.Active active) {
         R activeInfo = this.getActiveInfo(active);
+        //激活设备
         if (activeInfo.getCode() == R.Enum.SUCCESS.getCode()) {
-            //激活设备
+            LocalDateTime now = LocalDateTime.now();
             DeviceInfo updateDeviceInfo = new DeviceInfo()
                     .setDeviceId(active.getDeviceId())
                     .setActiveState(Integer.valueOf(DictSonEnum.DEVICE_ACTIVE_STATUS_1.getKey()))
                     .setBusyState(Integer.valueOf(DictSonEnum.DEVICE_BUSY_STATUS_1.getKey()))
-                    .setActiveTime(LocalDateTime.now())
+                    .setActiveTime(now)
                     .setShowStatus(true);
             deviceInfoService.updateById(updateDeviceInfo);
+            //首次激活可试用x天
+            DeviceCharging deviceCharging = deviceChargingService.getById(active.getDeviceId());
+            if (deviceCharging == null) {
+                SysDictRedis sysDictRedis = SysDictUtils.get(DictEnum.DEVICE_CHARGING.getKey(), DictSonEnum.DEVICE_CHARGING_X.getKey());
+                deviceChargingService.save(new DeviceCharging()
+                        .setDeviceId(active.getDeviceId())
+                        .setChargingX(Integer.valueOf(sysDictRedis.getValue()))
+                        .setTimeout(now)
+                        .setCreateTime(now)
+                );
+            }
             return R.ok();
         } else {
             return activeInfo;
         }
     }
 
-    @PostMapping("modifyBusyStage")
     @ApiOperation("运营状态修改")
+    @PostMapping("modifyBusyStage")
+    @AliPay(AliPay.Type.BUSY_STATE)
     public R modifyBusyStage(@RequestBody @Validated MercMiniDeviceDto.BusySate busySate) {
         Long mercId = MercAuthUtils.getMercId();
         Long deviceId = busySate.getDeviceId();

+ 2 - 2
device-api-service-merc-mini/src/main/java/com/xy/controller/MercMiniDeviceHomePageController.java

@@ -10,7 +10,6 @@ import com.xy.dto.MercMiniDeviceDto;
 import com.xy.dto.OrderRefundDto;
 import com.xy.service.DeviceDataServiceImpl;
 import com.xy.service.OrderRefundService;
-import com.xy.service.OrdersService;
 import com.xy.utils.MercAuthUtils;
 import com.xy.utils.R;
 import io.swagger.annotations.Api;
@@ -36,7 +35,7 @@ public class MercMiniDeviceHomePageController {
 
     private DeviceDataServiceImpl deviceDataService;
     private OrderRefundService refundService;
-    private OrdersService ordersService;
+
 
     @PostMapping("count")
     @ApiOperation("首页统计")
@@ -54,6 +53,7 @@ public class MercMiniDeviceHomePageController {
             //今日销售额 (扣除今日的订单的退款金额)
             day.setDayHisRefundMoney(hisRefundMoney);
             day.setDayRefundMoney(todayRefundMoney);
+            //改为和更多数据中的今日收益一样
             day.setSalesPrice(mercDataOneDay.stream().mapToInt(DeviceDataDto.Vo::getSalesMoney).sum() - todayRefundMoney);
             day.setOrderNum(mercDataOneDay.stream().mapToInt(DeviceDataDto.Vo::getSalesCount).sum());
             day.setRefundMoney(hisRefundMoney + todayRefundMoney);

+ 5 - 2
device-api-service/pom.xml

@@ -39,13 +39,16 @@
             <artifactId>goods-api</artifactId>
             <version>1.0</version>
         </dependency>
-
         <dependency>
             <groupId>com.xy</groupId>
             <artifactId>sys-api</artifactId>
             <version>1.0</version>
         </dependency>
-
+        <dependency>
+            <groupId>com.xy</groupId>
+            <artifactId>merc-api</artifactId>
+            <version>1.0</version>
+        </dependency>
 
         <dependency>
             <groupId>com.xy</groupId>

+ 39 - 0
device-api-service/src/main/java/com/xy/alipay/AliPay.java

@@ -0,0 +1,39 @@
+package com.xy.alipay;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.lang.annotation.*;
+
+/**
+ * 支付宝注解
+ *
+ * @author lijin
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface AliPay {
+
+    /**
+     * 类型
+     *
+     * @return
+     */
+    Type value();
+
+
+    @Getter
+    @AllArgsConstructor
+    enum Type {
+
+        RESTART("重启设备"),
+
+        BUSY_STATE("修改运营状态")
+
+        ;
+
+        private String type;
+    }
+
+}

+ 133 - 0
device-api-service/src/main/java/com/xy/alipay/AliPayAspet.java

@@ -0,0 +1,133 @@
+package com.xy.alipay;
+
+import cn.hutool.json.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.xy.collections.list.JArrayList;
+import com.xy.collections.map.JMap;
+import com.xy.dto.CommandMqtt;
+import com.xy.dto.MercMiniDeviceDto;
+import com.xy.entity.DeviceInfo;
+import com.xy.service.DeviceInfoServiceImpl;
+import com.xy.utils.FunctionUtils;
+import com.xy.utils.R;
+import com.xy.utils.enums.DictSonEnum;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Aspect
+@Component
+@AllArgsConstructor
+public class AliPayAspet {
+
+    private DeviceInfoServiceImpl deviceInfoService;
+
+    /**
+     * 支付宝设备
+     *
+     * @param joinPoint
+     * @param aliPay
+     * @return
+     * @throws Throwable
+     */
+    @Around("@annotation(aliPay)")
+    public Object timer(ProceedingJoinPoint joinPoint, AliPay aliPay) throws Throwable {
+        String type = aliPay.value().getType();
+        Object[] args = joinPoint.getArgs();
+        Object result = R.ok();
+        try {
+            boolean fal = before(type, args);
+            if (fal) {
+                result = joinPoint.proceed(args);
+            }
+        } catch (Exception e) {
+            throw e;
+        }
+        return result;
+    }
+
+    public boolean before(String type, Object[] args) {
+        boolean fal = true;
+        //重启设备
+        if (type.equals(AliPay.Type.RESTART.getType())) {
+            List<CommandMqtt> restart = restart(args);
+            if (restart.size() > 0) {
+                args[0] = restart;
+            } else {
+                fal = false;
+            }
+        }
+        //修改运营状态
+        if (type.equals(AliPay.Type.BUSY_STATE.getType())) {
+            fal = busyState(args);
+        }
+        return fal;
+    }
+
+    /**
+     * 重启设备
+     *
+     * @param args
+     */
+    private List<CommandMqtt> restart(Object[] args) {
+        List<CommandMqtt> result = new ArrayList<>();
+        List<CommandMqtt> commandMqtts = (List<CommandMqtt>) args[0];
+        //查询支付宝设备信息
+        List<DeviceInfo> deviceInfos = deviceInfoService.list(new LambdaQueryWrapper<DeviceInfo>()
+                .in(DeviceInfo::getDeviceId, new JArrayList<>(commandMqtts).comparing(CommandMqtt::getDeviceId).getProperty(CommandMqtt::getDeviceId))
+                .eq(DeviceInfo::getDeviceType, DictSonEnum.DEVICE_TYPE_5.getKey())
+        );
+        if (deviceInfos.size() == 0) {
+            return commandMqtts;
+        }
+        JMap<Long, DeviceInfo> deviceInfosJMaps = new JArrayList<>(deviceInfos).toMap(DeviceInfo::getDeviceId).cover();
+        commandMqtts.forEach(commandMqtt -> {
+            JSONObject templet = commandMqtt.getTemplet();
+            JSONObject data = templet.getJSONObject("data");
+            DeviceInfo deviceInfo = deviceInfosJMaps.get(commandMqtt.getDeviceId());
+            if (deviceInfo == null) {
+                result.add(commandMqtt);
+                return;
+            }
+            //todo 发送支付宝设备重启请求
+            if (data.getStr("type").equals("app") && data.getStr("task").equals("restart")) {
+                log.info("支付宝设备重启:{}", deviceInfo.getDeviceId());
+            }
+        });
+        return result;
+    }
+
+    /**
+     * 修改运营状态
+     *
+     * @param args
+     * @return
+     */
+    private boolean busyState(Object[] args) {
+        MercMiniDeviceDto.BusySate busySate = (MercMiniDeviceDto.BusySate) args[0];
+        //查询支付宝设备信息
+        DeviceInfo deviceInfo = deviceInfoService.getOne(new LambdaQueryWrapper<DeviceInfo>()
+                .eq(DeviceInfo::getDeviceId, busySate.getDeviceId())
+                .eq(DeviceInfo::getDeviceType, DictSonEnum.DEVICE_TYPE_5.getKey())
+        );
+        if (deviceInfo == null) {
+            return true;
+        }
+        Long deviceId = busySate.getDeviceId();
+        DeviceInfo updateDeviceInfo = new DeviceInfo()
+                .setDeviceId(deviceId)
+                .setBusyState(busySate.getBusyState())
+                .setFreezeStatus(busySate.getBusyState());
+        deviceInfoService.updateById(updateDeviceInfo);
+        //todo 发送支付宝设备修改运营状态请求
+
+        return false;
+    }
+}

+ 61 - 0
device-api-service/src/main/java/com/xy/alipay/AliPayUtils.java

@@ -0,0 +1,61 @@
+package com.xy.alipay;
+
+import cn.hutool.json.JSONObject;
+import com.xy.consumer.connected.ConnectedMqttConfiguration;
+import com.xy.consumer.connected.ConnectedProducer;
+import com.xy.consumer.disconnect.DisconnectedMqttConfiguration;
+import com.xy.consumer.disconnect.DisconnectedProducer;
+import com.xy.utils.SpringBeanUtils;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 支付宝设备工具类
+ */
+public class AliPayUtils {
+
+    /**
+     * 设备上线
+     *
+     * @param deviceId
+     */
+    public static void connectedNotify(Long deviceId) {
+        connectedNotify(Arrays.asList(deviceId));
+    }
+
+    /**
+     * 设备上线
+     *
+     * @param deviceIds
+     */
+    public static void connectedNotify(List<Long> deviceIds) {
+        ConnectedProducer connectedProducer = SpringBeanUtils.getBean(ConnectedProducer.class);
+        deviceIds.forEach(deviceId -> {
+            JSONObject jsonObject = new JSONObject().set("clientid", deviceId);
+            connectedProducer.sendToMqtt(jsonObject.toString(), ConnectedMqttConfiguration.TOPIC, 1);
+        });
+    }
+
+    /**
+     * 设备下线
+     *
+     * @param deviceId
+     */
+    public static void disConnectedNotify(Long deviceId) {
+        disConnectedNotify(Arrays.asList(deviceId));
+    }
+
+    /**
+     * 设备下线
+     *
+     * @param deviceIds
+     */
+    public static void disConnectedNotify(List<Long> deviceIds) {
+        DisconnectedProducer disconnectedProducer = SpringBeanUtils.getBean(DisconnectedProducer.class);
+        deviceIds.forEach(deviceId -> {
+            JSONObject jsonObject = new JSONObject().set("clientid", deviceId);
+            disconnectedProducer.sendToMqtt(jsonObject.toString(), DisconnectedMqttConfiguration.TOPIC, 1);
+        });
+    }
+}

+ 24 - 0
device-api-service/src/main/java/com/xy/consumer/connected/ConnectedMqttConfiguration.java

@@ -24,6 +24,30 @@ public class ConnectedMqttConfiguration {
      */
     public static final String CHANNEL_NAME_IN = TOPIC + "MqttInboundChannel";
 
+    /**
+     * 出站通道名(生产者)发布的bean名称
+     */
+    public static final String CHANNEL_NAME_OUT = TOPIC + "MqttOutboundChannel";
+
+    /*******************************生产者*******************************************/
+
+    /**
+     * MQTT信息通道(生产者)
+     */
+    @Bean(name = CHANNEL_NAME_OUT)
+    public MessageChannel mqttOutboundChannel() {
+        return new DirectChannel();
+    }
+
+    /**
+     * MQTT消息处理器(生产者)
+     */
+    @Bean(name = TOPIC + "MqttOutbound")
+    @ServiceActivator(inputChannel = CHANNEL_NAME_OUT)
+    public MessageHandler mqttOutbound() {
+        return MqttConfigUtils.mqttOutbound(TOPIC);
+    }
+
 
     /*******************************消费者*******************************************/
 

+ 26 - 0
device-api-service/src/main/java/com/xy/consumer/connected/ConnectedProducer.java

@@ -0,0 +1,26 @@
+package com.xy.consumer.connected;
+
+import org.springframework.integration.annotation.MessagingGateway;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+/**
+ * 生产者接口
+ */
+@Component
+@MessagingGateway(defaultRequestChannel = ConnectedMqttConfiguration.CHANNEL_NAME_OUT)
+public interface ConnectedProducer {
+
+    /**
+     * ata是发送消息的内容
+     * topic是消息发送的主题,就是配置文件的主题
+     * qos是mqtt 对消息处理机制分为0,1,2 其中0表示的是订阅者没收到消息不会再次发送,消息会丢失,1表示的是会尝试重试,一直到接收到消息,但这种情况可能导致订阅者收到多次重复消息,2相比多了一次去重的动作,确保订阅者收到的消息有一次
+     */
+
+    void sendToMqtt(String data);
+
+    void sendToMqtt(String data, @Header(MqttHeaders.TOPIC) String topic);
+
+    void sendToMqtt(String data, @Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos);
+}

+ 24 - 0
device-api-service/src/main/java/com/xy/consumer/disconnect/DisconnectedMqttConfiguration.java

@@ -24,6 +24,30 @@ public class DisconnectedMqttConfiguration {
      */
     public static final String CHANNEL_NAME_IN = TOPIC + "MqttInboundChannel";
 
+    /**
+     * 出站通道名(生产者)发布的bean名称
+     */
+    public static final String CHANNEL_NAME_OUT = TOPIC + "MqttOutboundChannel";
+
+    /*******************************生产者*******************************************/
+
+    /**
+     * MQTT信息通道(生产者)
+     */
+    @Bean(name = CHANNEL_NAME_OUT)
+    public MessageChannel mqttOutboundChannel() {
+        return new DirectChannel();
+    }
+
+    /**
+     * MQTT消息处理器(生产者)
+     */
+    @Bean(name = TOPIC + "MqttOutbound")
+    @ServiceActivator(inputChannel = CHANNEL_NAME_OUT)
+    public MessageHandler mqttOutbound() {
+        return MqttConfigUtils.mqttOutbound(TOPIC);
+    }
+
 
     /*******************************消费者*******************************************/
 

+ 26 - 0
device-api-service/src/main/java/com/xy/consumer/disconnect/DisconnectedProducer.java

@@ -0,0 +1,26 @@
+package com.xy.consumer.disconnect;
+
+import org.springframework.integration.annotation.MessagingGateway;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+/**
+ * 生产者接口
+ */
+@Component
+@MessagingGateway(defaultRequestChannel = DisconnectedMqttConfiguration.CHANNEL_NAME_OUT)
+public interface DisconnectedProducer {
+
+    /**
+     * ata是发送消息的内容
+     * topic是消息发送的主题,就是配置文件的主题
+     * qos是mqtt 对消息处理机制分为0,1,2 其中0表示的是订阅者没收到消息不会再次发送,消息会丢失,1表示的是会尝试重试,一直到接收到消息,但这种情况可能导致订阅者收到多次重复消息,2相比多了一次去重的动作,确保订阅者收到的消息有一次
+     */
+
+    void sendToMqtt(String data);
+
+    void sendToMqtt(String data, @Header(MqttHeaders.TOPIC) String topic);
+
+    void sendToMqtt(String data, @Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos);
+}

+ 45 - 0
device-api-service/src/main/java/com/xy/entity/DeviceCharging.java

@@ -0,0 +1,45 @@
+package com.xy.entity;
+
+import java.time.LocalDateTime;
+import java.io.Serializable;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 设备计费表
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="DeviceCharging对象", description="设备计费表")
+public class DeviceCharging implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId
+    @ApiModelProperty(value = "设备id")
+    private Long deviceId;
+
+    @ApiModelProperty(value = "累计续费金额")
+    private Integer chargingSumMoney;
+
+    @ApiModelProperty(value = "试用剩余天")
+    private Integer chargingX;
+
+    @ApiModelProperty(value = "过期时间")
+    private LocalDateTime timeout;
+
+    @ApiModelProperty(value = "创建时间")
+    private LocalDateTime createTime;
+
+}

+ 44 - 0
device-api-service/src/main/java/com/xy/entity/DeviceChargingHistory.java

@@ -0,0 +1,44 @@
+package com.xy.entity;
+
+import com.xy.base.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 设备计费历史表
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "DeviceChargingHistory对象", description = "设备计费历史表")
+public class DeviceChargingHistory extends BaseEntity<DeviceChargingHistory> implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "设备id")
+    private Long deviceId;
+
+    @ApiModelProperty(value = "续费金额")
+    private Integer chargingMoney;
+
+    @ApiModelProperty(value = "续费方式")
+    private Integer chargingType;
+
+    @ApiModelProperty(value = "续费有效期")
+    private LocalDateTime chargingDateTime;
+
+    @ApiModelProperty(value = "创建时间")
+    private LocalDateTime createTime;
+
+}

+ 171 - 0
device-api-service/src/main/java/com/xy/job/DeviceChargingJob.java

@@ -0,0 +1,171 @@
+package com.xy.job;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import com.xy.collections.list.JArrayList;
+import com.xy.collections.list.JList;
+import com.xy.collections.map.JMap;
+import com.xy.dto.DeviceInfoDto;
+import com.xy.dto.MercAccountDto;
+import com.xy.entity.DeviceCharging;
+import com.xy.entity.DeviceChargingHistory;
+import com.xy.entity.DeviceInfo;
+import com.xy.entity.SysDictRedis;
+import com.xy.mapper.DeviceChargingMapper;
+import com.xy.service.DeviceChargingHistoryServiceImpl;
+import com.xy.service.DeviceChargingServiceImpl;
+import com.xy.service.DeviceInfoServiceImpl;
+import com.xy.service.MercAccountService;
+import com.xy.utils.*;
+import com.xy.utils.enums.DictEnum;
+import com.xy.utils.enums.DictSonEnum;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 设备计费job
+ */
+@Slf4j
+@Component
+@AllArgsConstructor
+public class DeviceChargingJob {
+
+    private DeviceChargingServiceImpl deviceChargingService;
+
+    private DeviceChargingHistoryServiceImpl deviceChargingHistoryService;
+
+    private DeviceInfoServiceImpl deviceInfoService;
+
+    private MercAccountService mercAccountService;
+
+    private DeviceChargingMapper deviceChargingMapper;
+
+    /**
+     * 扣除设备服务费试用天数
+     *
+     * @return
+     */
+    @XxlJob("deviceChargingX")
+    public ReturnT<String> deviceChargingX() {
+        deviceChargingMapper.updateChargingX();
+        log.info("设备试用时间扣除完成~");
+        return ReturnT.SUCCESS;
+    }
+
+    /**
+     * 设备计费
+     *
+     * @return
+     */
+    @XxlJob("deviceCharging")
+    public ReturnT<String> deviceCharging() {
+        deviceCharging(1, 20, null);
+        log.info("设备计费完成~");
+        return ReturnT.SUCCESS;
+    }
+
+    /**
+     * 递归执行
+     *
+     * @param current
+     * @param size
+     * @param deviceIds
+     */
+    public void deviceCharging(int current, int size, List<Long> deviceIds) {
+        log.info("设备计费开始第{}页", current);
+        List<DeviceCharging> updateDeviceChargings = new ArrayList<>();
+        List<DeviceChargingHistory> deviceChargingHistories = new ArrayList<>();
+        List<DeviceInfoDto.Update> updateDeviceInfos = new ArrayList<>();
+        LocalDateTime now = LocalDateTime.now();
+        //查询已过期计费记录
+        PageBean<DeviceCharging> pageBean = new PageBean().setCurrent(current).setSize(size);
+        IPage<DeviceCharging> iPage = deviceChargingService.page(PlusBeans.toIPage(pageBean), new LambdaQueryWrapper<DeviceCharging>()
+                .le(DeviceCharging::getTimeout, now)
+                .in(Emptys.check(deviceIds), DeviceCharging::getDeviceId, deviceIds)
+        );
+        List<DeviceCharging> records = iPage.getRecords();
+        if (!Emptys.check(records)) {
+            return;
+        }
+        //查询设备信息
+        JList<DeviceCharging> deviceChargings = new JArrayList<>(records);
+        JMap<Long, DeviceCharging> deviceChargingsJMaps = deviceChargings.toMap(DeviceCharging::getDeviceId).cover();
+        List<DeviceInfo> deviceInfos = deviceInfoService.list(new LambdaQueryWrapper<DeviceInfo>()
+                .in(DeviceInfo::getDeviceId, deviceChargings.getProperty(DeviceCharging::getDeviceId))
+        );
+        JMap<Long, DeviceInfo> deviceInfosJMaps = new JArrayList<>(deviceInfos).toMap(DeviceInfo::getDeviceId).cover();
+        //字典
+        Map<String, SysDictRedis> stringSysDictRedisMap = SysDictUtils.get(DictEnum.DEVICE_CHARGING.getKey());
+        SysDictRedis sysDictRedisY = stringSysDictRedisMap.get(DictSonEnum.DEVICE_CHARGING_Y.getKey());
+        Integer y = Integer.valueOf(sysDictRedisY.getValue());
+        //开始计费
+        deviceChargingsJMaps.forEach((deviceId, deviceCharging) -> {
+            //发起扣款
+            DeviceInfo deviceInfo = deviceInfosJMaps.get(deviceId);
+            if (deviceInfo.getMercId() == -1) {
+                return;
+            }
+            SysDictRedis sysDictRedisBalance = stringSysDictRedisMap.get(String.valueOf(deviceInfo.getDeviceType()));
+            Integer balance = Integer.valueOf(sysDictRedisBalance.getValue());
+            R r = mercAccountService.updateBalance(new MercAccountDto.UpdateBalance()
+                    .setMercId(deviceInfo.getMercId())
+                    .setBalance(balance)
+                    .setResean("设备管理费")
+            );
+            //扣款成功
+            if (r.getCode() == R.Enum.SUCCESS.getCode()) {
+                LocalDateTime newTimeOut = DataTime.toLocal(DataTime.getStringAround(1, 0, 0, 0, 0, 0, DataTime.toString(deviceCharging.getTimeout())));
+                deviceCharging.setChargingSumMoney(deviceCharging.getChargingSumMoney() + balance)
+                        .setTimeout(newTimeOut);
+                DeviceChargingHistory deviceChargingHistory = new DeviceChargingHistory()
+                        .createId()
+                        .setDeviceId(deviceId)
+                        .setChargingMoney(balance)
+                        .setChargingType(DictSonEnum.DEVICE_CHARGING_100.getKeyInt())
+                        .setChargingDateTime(newTimeOut)
+                        .setCreateTime(now);
+                deviceChargingHistories.add(deviceChargingHistory);
+            }
+            //扣款失败
+            if (r.getCode() == R.Enum.FAIL.getCode()) {
+                //当前时间 - 过期时间 > y && 试用期 <= 0 则冻结设备
+                long day = DataTime.diff(now, deviceCharging.getTimeout(), "d");
+                if (day > y && deviceCharging.getChargingX() <= 0) {
+                    DeviceInfoDto.Update update = new DeviceInfoDto.Update()
+                            .setDeviceId(deviceId);
+                    update.setFreezeStatus(2);
+                    updateDeviceInfos.add(update);
+                }
+            }
+            updateDeviceChargings.add(deviceCharging);
+        });
+        //修改设备计费记录
+        if (Emptys.check(updateDeviceChargings)) {
+            deviceChargingService.updateBatchById(updateDeviceChargings);
+        }
+        //添加设备计费记录历史
+        if (Emptys.check(deviceChargingHistories)) {
+            deviceChargingHistoryService.saveBatch(deviceChargingHistories);
+        }
+        //冻结设备
+        if (Emptys.check(updateDeviceInfos)) {
+            deviceInfoService.updateBatch(updateDeviceInfos);
+        }
+
+        //判断是否继续下一页
+        if (iPage.getPages() <= current) {
+            return;
+        } else {
+            deviceCharging(current + 1, size, deviceIds);
+        }
+    }
+
+}

+ 16 - 0
device-api-service/src/main/java/com/xy/mapper/DeviceChargingHistoryMapper.java

@@ -0,0 +1,16 @@
+package com.xy.mapper;
+
+import com.xy.entity.DeviceChargingHistory;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 设备计费历史表 Mapper 接口
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+public interface DeviceChargingHistoryMapper extends BaseMapper<DeviceChargingHistory> {
+
+}

+ 24 - 0
device-api-service/src/main/java/com/xy/mapper/DeviceChargingMapper.java

@@ -0,0 +1,24 @@
+package com.xy.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.xy.entity.DeviceCharging;
+import org.apache.ibatis.annotations.Select;
+
+/**
+ * <p>
+ * 设备计费表 Mapper 接口
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+public interface DeviceChargingMapper extends BaseMapper<DeviceCharging> {
+
+    /**
+     * 扣除设备服务费试用天数
+     *
+     * @return
+     */
+    @Select("update device_charging set charging_x = charging_x - 1 where charging_x > 0")
+    int updateChargingX();
+}

+ 1 - 0
device-api-service/src/main/java/com/xy/mapper/DeviceInfoMapper.java

@@ -35,4 +35,5 @@ public interface DeviceInfoMapper extends BaseMapper<DeviceInfo> {
      * @return
      */
     List<DeviceInfoDto.MercHomeCountVO> merHomeCountList(@Param("query") DeviceInfoDto.MercHomeQueryDTO queryDTO);
+
 }

+ 18 - 0
device-api-service/src/main/java/com/xy/mapper/mapper/DeviceChargingHistoryMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xy.mapper.DeviceChargingHistoryMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.xy.entity.DeviceChargingHistory">
+        <id column="id" property="id" />
+        <result column="device_id" property="deviceId" />
+        <result column="device_type" property="deviceType" />
+        <result column="charging_money" property="chargingMoney" />
+        <result column="charging_sum_money" property="chargingSumMoney" />
+        <result column="charging_type" property="chargingType" />
+        <result column="status" property="status" />
+        <result column="timeout" property="timeout" />
+        <result column="create_time" property="createTime" />
+    </resultMap>
+
+</mapper>

+ 18 - 0
device-api-service/src/main/java/com/xy/mapper/mapper/DeviceChargingMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xy.mapper.DeviceChargingMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.xy.entity.DeviceCharging">
+        <id column="device_id" property="deviceId" />
+        <result column="device_type" property="deviceType" />
+        <result column="charging_money" property="chargingMoney" />
+        <result column="charging_sum_money" property="chargingSumMoney" />
+        <result column="charging_type" property="chargingType" />
+        <result column="status" property="status" />
+        <result column="timeout" property="timeout" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+    </resultMap>
+
+</mapper>

+ 24 - 0
device-api-service/src/main/java/com/xy/service/DeviceChargingHistoryServiceImpl.java

@@ -0,0 +1,24 @@
+package com.xy.service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.entity.DeviceChargingHistory;
+import com.xy.mapper.DeviceChargingHistoryMapper;
+import io.swagger.annotations.Api;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * <p>
+ * 设备计费历史表 服务实现类
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@Service
+@AllArgsConstructor
+@Api(tags = "设备计费历史表")
+public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceChargingHistoryMapper, DeviceChargingHistory> implements DeviceChargingHistoryService {
+
+}

+ 44 - 0
device-api-service/src/main/java/com/xy/service/DeviceChargingServiceImpl.java

@@ -0,0 +1,44 @@
+package com.xy.service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.dto.DeviceChargingDto;
+import com.xy.entity.DeviceCharging;
+import com.xy.job.DeviceChargingJob;
+import com.xy.mapper.DeviceChargingMapper;
+import com.xy.utils.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+
+/**
+ * <p>
+ * 设备计费表 服务实现类
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@Service
+@Api(tags = "设备计费表")
+@AllArgsConstructor(onConstructor_ = @Lazy)
+public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper, DeviceCharging> implements DeviceChargingService {
+
+    private DeviceChargingJob deviceChargingJob;
+
+    @ApiOperation("手动计费")
+    @PostMapping("charging")
+    public R charging(@RequestBody @Validated DeviceChargingDto.Charging charging) {
+        List<Long> deviceIds = charging.getDeviceIds();
+        deviceChargingJob.deviceCharging(1, deviceIds.size(), deviceIds);
+        return R.ok();
+    }
+}

+ 2 - 2
device-api-service/src/main/java/com/xy/service/DeviceCreateIdsServiceImpl.java

@@ -58,7 +58,7 @@ public class DeviceCreateIdsServiceImpl extends ServiceImpl<DeviceCreateIdsMappe
     @PostMapping("save")
     @ApiOperation("添加")
     @Lock("device-create-ids-save")
-    public R save(@RequestBody @Validated DeviceCreateIdsDto.Save save) {
+    public R<JList<DeviceCreateIds>> save(@RequestBody @Validated DeviceCreateIdsDto.Save save) {
         LocalDate localDate = LocalDate.now();
         String year = String.valueOf(localDate.getYear());
         String month = String.valueOf(localDate.getMonthValue());
@@ -94,7 +94,7 @@ public class DeviceCreateIdsServiceImpl extends ServiceImpl<DeviceCreateIdsMappe
         ThreadPoolUtils.Execute execute = ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, partition.size());
         partition.forEach(createIds -> execute.execute(() -> saveBatch(createIds)));
         execute.end();
-        return R.ok();
+        return R.ok(deviceCreateIdss);
     }
 
     @PostMapping("page")

+ 4 - 2
device-api-service/src/main/java/com/xy/service/DeviceInfoServiceImpl.java

@@ -219,7 +219,8 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @ApiOperation("修改")
     @PostMapping("update")
     public R update(@RequestBody @Validated DeviceInfoDto.Update update) {
-        DeviceInfo deviceInfo = copy(DeviceInfo.class, update);
+        DeviceInfo deviceInfo = copy(DeviceInfo.class, update)
+                .setUpdateTime(LocalDateTime.now());
         updateById(deviceInfo);
         return R.ok();
     }
@@ -227,8 +228,9 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @ApiOperation("批量修改")
     @PostMapping("updateBatch")
     public R updateBatch(@RequestBody List<DeviceInfoDto.Update> updates) {
+        LocalDateTime now = LocalDateTime.now();
         List<DeviceInfo> deviceInfos = new ArrayList<>(updates.size());
-        updates.forEach(update -> deviceInfos.add(copy(DeviceInfo.class, update)));
+        updates.forEach(update -> deviceInfos.add(copy(DeviceInfo.class, update).setUpdateTime(now)));
         updateBatchById(deviceInfos);
         return R.ok();
     }

+ 99 - 0
device-api-service/src/main/java/com/xy/service/DeviceRegisterServiceImpl.java

@@ -1,5 +1,8 @@
 package com.xy.service;
 
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.read.listener.ReadListener;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -9,6 +12,8 @@ import com.xy.annotation.Lock;
 import com.xy.collections.list.JArrayList;
 import com.xy.collections.list.JList;
 import com.xy.collections.map.JMap;
+import com.xy.config.DeviceThreadPoolConfig;
+import com.xy.dto.DeviceCreateIdsDto;
 import com.xy.dto.DeviceQualityDto;
 import com.xy.dto.DeviceRegisterDto;
 import com.xy.dto.MqttUserDto;
@@ -17,15 +22,24 @@ import com.xy.mapper.*;
 import com.xy.utils.*;
 import com.xy.utils.consts.CommConsts;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.validation.constraints.NotBlank;
+import java.io.IOException;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
 import java.util.List;
 
 import static com.xy.utils.PlusBeans.*;
@@ -245,4 +259,89 @@ public class DeviceRegisterServiceImpl extends ServiceImpl<DeviceRegisterMapper,
         }
         return R.ok();
     }
+
+    @ApiOperation("上传sn注册设备")
+    @PostMapping("uploadSaveBySn")
+    public R uploadSaveBySn(@RequestParam("file") MultipartFile file, @RequestParam("deviceType") Integer deviceType, @RequestParam("devicePc") String devicePc, @RequestParam("assetNo") String assetNo) {
+        ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, 1)
+                .execute(() -> {
+                    try {
+                        EasyExcel.read(file.getInputStream(), UploadSaveBySn.class, new UploadSaveBySnListener(deviceCreateIdsService, this, deviceType, devicePc, assetNo)).sheet().doRead();
+                    } catch (IOException e) {
+                        log.error("", e);
+                    }
+                });
+        return R.ok();
+    }
+
+    @Slf4j
+    @RequiredArgsConstructor
+    public static class UploadSaveBySnListener implements ReadListener<UploadSaveBySn> {
+
+        private final DeviceCreateIdsServiceImpl deviceCreateIdsService;
+
+        private final DeviceRegisterServiceImpl deviceRegisterService;
+
+        private final Integer deviceType;
+
+        private final String devicePc;
+
+        private final String assetNo;
+
+        private List<UploadSaveBySn> sns = new ArrayList<>();
+
+        /**
+         * 这个每一条数据解析都会来调用
+         *
+         * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
+         * @param context
+         */
+        @Override
+        public void invoke(UploadSaveBySn data, AnalysisContext context) {
+            sns.add(data);
+        }
+
+        /**
+         * 所有数据解析完成了 都会来调用
+         *
+         * @param context
+         */
+        @Override
+        public void doAfterAllAnalysed(AnalysisContext context) {
+            log.info("上传sn注册设备文件解析完毕,总数量:{},批次:{}", sns.size(), devicePc);
+            //生成设备号
+            JList<DeviceCreateIds> deviceCreateIds = deviceCreateIdsService.save(new DeviceCreateIdsDto.Save()
+                    .setDeviceType(deviceType)
+                    .setDoorType("1")
+                    .setCreatePc(devicePc)
+                    .setNum(sns.size())
+            ).getData();
+            JList<Long> deviceIds = deviceCreateIds.getProperty(DeviceCreateIds::getDeviceId);
+            //注册设备
+            ThreadPoolUtils.Execute execute = ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, sns.size());
+            for (int i = 0; i < sns.size(); i++) {
+                UploadSaveBySn sn = sns.get(i);
+                Long deviceId = deviceIds.get(i);
+                execute.execute(() -> {
+                    DeviceRegisterDto.Save save = new DeviceRegisterDto.Save()
+                            .setDeviceId(deviceId)
+                            .setDeviceSn(sn.getSn())
+                            .setDevicePc(devicePc)
+                            .setAssetNo(assetNo);
+                    R r = deviceRegisterService.save(save);
+                    if (r.getCode() == R.Enum.FAIL.getCode()) {
+                        log.error("{},{}", sn.getSn(), r.getMsg());
+                    }
+                });
+            }
+            execute.end();
+            log.info("上传sn注册设备注册完毕,批次:{}", devicePc);
+        }
+    }
+
+    @Data
+    public static class UploadSaveBySn {
+
+        private String sn;
+    }
 }

+ 2 - 1
device-api-service/src/main/java/com/xy/service/MqttServiceImpl.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.alipay.AliPay;
 import com.xy.annotate.Runners;
 import com.xy.annotate.Timer;
 import com.xy.collections.map.JHashMap;
@@ -123,9 +124,9 @@ public class MqttServiceImpl extends ServiceImpl<MqttCommandMapper, MqttCommand>
         snInit = true;
     }
 
-    @Timer
     @Override
     @ApiOperation("指令发送")
+    @AliPay(AliPay.Type.RESTART)
     public R<List<Tuple.Tuple3<Long, Long, Boolean>>> senCommand(List<CommandMqtt> commandMqtts) {
         //发送指令
         List<MqttDto> mqttDtos = new ArrayList<>();

+ 5 - 0
device-api-service/src/main/java/com/xy/utils/enums/DictEnum.java

@@ -30,6 +30,11 @@ public enum DictEnum {
     ENV("env", "环境标识"),
 
     ENV_PARAMS("env_params", "环境参数"),
+
+    DEVICE_CHARGING("device_charging", "设备计费标准"),
+
+    DEVICE_TYPE("device_type", "设备-机器类型"),
+
     ;
 
     private String key;

+ 10 - 0
device-api-service/src/main/java/com/xy/utils/enums/DictSonEnum.java

@@ -52,6 +52,16 @@ public enum DictSonEnum {
 
     ENV_PROD("prod", "环境标识-生产环境"),
 
+    DEVICE_CHARGING_X("x", "设备计费标准-机器激活后可使用天数"),
+
+    DEVICE_CHARGING_Y("y", "设备计费标准-机器欠费后可使用天数"),
+
+    DEVICE_CHARGING_100("100", "设备计费标准-余额续费方式"),
+
+    DEVICE_CHARGING_101("101", "设备计费标准-其他续费方式"),
+
+    DEVICE_TYPE_5("5", "设备-机器类型-支付宝视动态觉柜"),
+
     ;
 
     private String key;

+ 55 - 0
device-api/src/main/java/com/xy/dto/DeviceChargingDto.java

@@ -0,0 +1,55 @@
+package com.xy.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotEmpty;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * <p>
+ * 设备计费表
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+public class DeviceChargingDto {
+
+    @Data
+    @Accessors(chain = true)
+    public static class Charging {
+
+        @NotEmpty(message = "设备id不能为空")
+        @ApiModelProperty(value = "设备id集合")
+        private List<Long> deviceIds;
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class Vo {
+
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "累计续费金额")
+        private Integer chargingSumMoney;
+
+        @ApiModelProperty(value = "试用剩余天")
+        private Integer chargingX;
+
+        @ApiModelProperty(value = "过期时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime timeout;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+    }
+
+}

+ 43 - 0
device-api/src/main/java/com/xy/dto/DeviceChargingHistoryDto.java

@@ -0,0 +1,43 @@
+package com.xy.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 设备计费历史表
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+public class DeviceChargingHistoryDto {
+
+    @Data
+    @Accessors(chain = true)
+    public static class Vo {
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "续费金额")
+        private Integer chargingMoney;
+
+        @ApiModelProperty(value = "续费方式")
+        private Integer chargingType;
+
+        @ApiModelProperty(value = "续费有效期")
+        private LocalDateTime chargingDateTime;
+
+        @ApiModelProperty(value = "创建时间")
+        private LocalDateTime createTime;
+
+    }
+
+}

+ 16 - 0
device-api/src/main/java/com/xy/service/DeviceChargingHistoryService.java

@@ -0,0 +1,16 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+
+/**
+ * <p>
+ * 设备计费历史表 服务类
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@RestMappingController("/device-charging-history")
+public interface DeviceChargingHistoryService {
+
+}

+ 16 - 0
device-api/src/main/java/com/xy/service/DeviceChargingService.java

@@ -0,0 +1,16 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+
+/**
+ * <p>
+ * 设备计费表 服务类
+ * </p>
+ *
+ * @author lijin
+ * @since 2023-04-14
+ */
+@RestMappingController("/device-charging")
+public interface DeviceChargingService {
+
+}

+ 5 - 2
device-start/pom.xml

@@ -29,7 +29,6 @@
             <artifactId>device-api-service-merc-mini</artifactId>
             <version>1.0</version>
         </dependency>
-
         <dependency>
             <groupId>com.xy</groupId>
             <artifactId>device-api-service-member</artifactId>
@@ -56,12 +55,16 @@
             <artifactId>merc-api-cloud</artifactId>
             <version>1.0</version>
         </dependency>
-
         <dependency>
             <groupId>com.xy</groupId>
             <artifactId>sys-api-feign</artifactId>
             <version>1.0</version>
         </dependency>
+        <dependency>
+            <groupId>com.xy</groupId>
+            <artifactId>merc-api-cloud</artifactId>
+            <version>1.0</version>
+        </dependency>
 
         <dependency>
             <groupId>com.xy</groupId>