tanbin преди 1 година
родител
ревизия
260e601a93
променени са 73 файла, в които са добавени 6088 реда и са изтрити 244 реда
  1. 19 0
      device-api-cloud/src/main/java/com/xy/feign/MercFeeConfigAlgorithmTypeFeign.java
  2. 19 0
      device-api-cloud/src/main/java/com/xy/feign/MercFeeConfigSimCardFeign.java
  3. 19 0
      device-api-cloud/src/main/java/com/xy/feign/MercFeeCountDayFeign.java
  4. 19 0
      device-api-cloud/src/main/java/com/xy/feign/MercFeeCountMonthFeign.java
  5. 19 0
      device-api-cloud/src/main/java/com/xy/feign/MercFeeSettleFeign.java
  6. 19 0
      device-api-cloud/src/main/java/com/xy/feign/MercFeeStatisticFeign.java
  7. 118 0
      device-api-service-merc-mini/src/main/java/com/xy/controller/DeviceAlgorithmChargingHisController.java
  8. 79 0
      device-api-service-merc-mini/src/main/java/com/xy/controller/DeviceChargingHistoryController.java
  9. 95 0
      device-api-service-merc-mini/src/main/java/com/xy/controller/DeviceSimChargeController.java
  10. 40 0
      device-api-service-merc-mini/src/main/java/com/xy/controller/DeviceSimPayController.java
  11. 93 0
      device-api-service-merc-mini/src/main/java/com/xy/controller/MercFeeCountController.java
  12. 5 5
      device-api-service/src/main/java/com/xy/entity/DeviceAdminActivate.java
  13. 7 3
      device-api-service/src/main/java/com/xy/entity/DeviceChargingConfig.java
  14. 11 4
      device-api-service/src/main/java/com/xy/entity/DeviceTypeAlgorithmBeforConfig.java
  15. 67 0
      device-api-service/src/main/java/com/xy/entity/MercFeeConfigAlgorithmType.java
  16. 64 0
      device-api-service/src/main/java/com/xy/entity/MercFeeConfigDevice.java
  17. 61 0
      device-api-service/src/main/java/com/xy/entity/MercFeeConfigSimCard.java
  18. 66 0
      device-api-service/src/main/java/com/xy/entity/MercFeeCountDay.java
  19. 69 0
      device-api-service/src/main/java/com/xy/entity/MercFeeCountMonth.java
  20. 67 0
      device-api-service/src/main/java/com/xy/entity/MercFeeSettle.java
  21. 53 0
      device-api-service/src/main/java/com/xy/entity/MercFeeStatistic.java
  22. 418 0
      device-api-service/src/main/java/com/xy/job/MercFeeCountDayJob.java
  23. 86 0
      device-api-service/src/main/java/com/xy/job/MercFeeCountMonthJob.java
  24. 16 0
      device-api-service/src/main/java/com/xy/mapper/MercFeeConfigAlgorithmTypeMapper.java
  25. 16 0
      device-api-service/src/main/java/com/xy/mapper/MercFeeConfigSimCardMapper.java
  26. 27 0
      device-api-service/src/main/java/com/xy/mapper/MercFeeCountDayMapper.java
  27. 16 0
      device-api-service/src/main/java/com/xy/mapper/MercFeeCountMonthMapper.java
  28. 16 0
      device-api-service/src/main/java/com/xy/mapper/MercFeeSettleMapper.java
  29. 16 0
      device-api-service/src/main/java/com/xy/mapper/MercFeeStatisticMapper.java
  30. 19 0
      device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeConfigAlgorithmTypeMapper.xml
  31. 17 0
      device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeConfigSimCardMapper.xml
  32. 33 0
      device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeCountDayMapper.xml
  33. 20 0
      device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeCountMonthMapper.xml
  34. 19 0
      device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeSettleMapper.xml
  35. 15 0
      device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeStatisticMapper.xml
  36. 113 1
      device-api-service/src/main/java/com/xy/service/DeviceAlgorithmChargingHistoryServiceImpl.java
  37. 134 1
      device-api-service/src/main/java/com/xy/service/DeviceChargingConfigServiceImpl.java
  38. 171 11
      device-api-service/src/main/java/com/xy/service/DeviceChargingHistoryServiceImpl.java
  39. 64 42
      device-api-service/src/main/java/com/xy/service/DeviceChargingServiceImpl.java
  40. 179 128
      device-api-service/src/main/java/com/xy/service/DeviceInfoServiceImpl.java
  41. 177 11
      device-api-service/src/main/java/com/xy/service/DeviceSimChargeServiceImpl.java
  42. 42 26
      device-api-service/src/main/java/com/xy/service/DeviceSimServiceImpl.java
  43. 107 3
      device-api-service/src/main/java/com/xy/service/DeviceTypeAlgorithmBeforConfigServiceImpl.java
  44. 37 0
      device-api-service/src/main/java/com/xy/service/MercExtraFeeService.java
  45. 174 0
      device-api-service/src/main/java/com/xy/service/MercFeeConfigAlgorithmTypeServiceImpl.java
  46. 212 0
      device-api-service/src/main/java/com/xy/service/MercFeeConfigSimCardServiceImpl.java
  47. 94 0
      device-api-service/src/main/java/com/xy/service/MercFeeCountDayServiceImpl.java
  48. 160 0
      device-api-service/src/main/java/com/xy/service/MercFeeCountMonthServiceImpl.java
  49. 145 0
      device-api-service/src/main/java/com/xy/service/MercFeeSettleServiceImpl.java
  50. 133 0
      device-api-service/src/main/java/com/xy/service/MercFeeStatisticServiceImpl.java
  51. 9 6
      device-api-service/src/main/resources/mapper/DeviceChargingMapper.xml
  52. 9 0
      device-api/src/main/java/com/xy/consts/DictConsts.java
  53. 293 1
      device-api/src/main/java/com/xy/dto/DeviceAlgorithmChargingHistoryDto.java
  54. 185 1
      device-api/src/main/java/com/xy/dto/DeviceChargingConfigDto.java
  55. 266 1
      device-api/src/main/java/com/xy/dto/DeviceChargingHistoryDto.java
  56. 212 0
      device-api/src/main/java/com/xy/dto/DeviceDataDto.java
  57. 287 0
      device-api/src/main/java/com/xy/dto/DeviceSimChargeDto.java
  58. 104 0
      device-api/src/main/java/com/xy/dto/DeviceTypeAlgorithmBeforConfigDto.java
  59. 179 0
      device-api/src/main/java/com/xy/dto/MercFeeConfigAlgorithmTypeDto.java
  60. 165 0
      device-api/src/main/java/com/xy/dto/MercFeeConfigSimCardDto.java
  61. 125 0
      device-api/src/main/java/com/xy/dto/MercFeeCountDayDto.java
  62. 125 0
      device-api/src/main/java/com/xy/dto/MercFeeCountMonthDto.java
  63. 36 0
      device-api/src/main/java/com/xy/dto/MercFeeExtraDTO.java
  64. 127 0
      device-api/src/main/java/com/xy/dto/MercFeeSettleDto.java
  65. 97 0
      device-api/src/main/java/com/xy/dto/MercFeeStatisticDto.java
  66. 14 0
      device-api/src/main/java/com/xy/service/DeviceInfoService.java
  67. 24 0
      device-api/src/main/java/com/xy/service/MercFeeConfigAlgorithmTypeService.java
  68. 34 0
      device-api/src/main/java/com/xy/service/MercFeeConfigSimCardService.java
  69. 16 0
      device-api/src/main/java/com/xy/service/MercFeeCountDayService.java
  70. 16 0
      device-api/src/main/java/com/xy/service/MercFeeCountMonthService.java
  71. 16 0
      device-api/src/main/java/com/xy/service/MercFeeSettleService.java
  72. 16 0
      device-api/src/main/java/com/xy/service/MercFeeStatisticService.java
  73. 48 0
      device-api/src/main/java/com/xy/utils/enums/MercFeeSettleSate.java

+ 19 - 0
device-api-cloud/src/main/java/com/xy/feign/MercFeeConfigAlgorithmTypeFeign.java

@@ -0,0 +1,19 @@
+package com.xy.feign;
+
+import com.xy.service.MercFeeConfigAlgorithmTypeService;
+import com.xy.FeignInterceptor;
+import com.xy.consts.ServiceConsts;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * <p>
+ * 商户算法扣费标准配置扩展 feign
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+@FeignClient(value = ServiceConsts.SERVICE_NAME, configuration = FeignInterceptor.class)
+public interface MercFeeConfigAlgorithmTypeFeign extends MercFeeConfigAlgorithmTypeService {
+
+}

+ 19 - 0
device-api-cloud/src/main/java/com/xy/feign/MercFeeConfigSimCardFeign.java

@@ -0,0 +1,19 @@
+package com.xy.feign;
+
+import com.xy.service.MercFeeConfigSimCardService;
+import com.xy.FeignInterceptor;
+import com.xy.consts.ServiceConsts;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * <p>
+ * 商户流量卡费配置扩展 feign
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+@FeignClient(value = ServiceConsts.SERVICE_NAME, configuration = FeignInterceptor.class)
+public interface MercFeeConfigSimCardFeign extends MercFeeConfigSimCardService {
+
+}

+ 19 - 0
device-api-cloud/src/main/java/com/xy/feign/MercFeeCountDayFeign.java

@@ -0,0 +1,19 @@
+package com.xy.feign;
+
+import com.xy.service.MercFeeCountDayService;
+import com.xy.FeignInterceptor;
+import com.xy.consts.ServiceConsts;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * <p>
+ * 商户佣金费用收益每日统计(不含今天) feign
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@FeignClient(value = ServiceConsts.SERVICE_NAME, configuration = FeignInterceptor.class)
+public interface MercFeeCountDayFeign extends MercFeeCountDayService {
+
+}

+ 19 - 0
device-api-cloud/src/main/java/com/xy/feign/MercFeeCountMonthFeign.java

@@ -0,0 +1,19 @@
+package com.xy.feign;
+
+import com.xy.service.MercFeeCountMonthService;
+import com.xy.FeignInterceptor;
+import com.xy.consts.ServiceConsts;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * <p>
+ * 商户佣金费用收益每月统计(不含本月) feign
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@FeignClient(value = ServiceConsts.SERVICE_NAME, configuration = FeignInterceptor.class)
+public interface MercFeeCountMonthFeign extends MercFeeCountMonthService {
+
+}

+ 19 - 0
device-api-cloud/src/main/java/com/xy/feign/MercFeeSettleFeign.java

@@ -0,0 +1,19 @@
+package com.xy.feign;
+
+import com.xy.service.MercFeeSettleService;
+import com.xy.FeignInterceptor;
+import com.xy.consts.ServiceConsts;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * <p>
+ * 商户佣金费用结算 feign
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@FeignClient(value = ServiceConsts.SERVICE_NAME, configuration = FeignInterceptor.class)
+public interface MercFeeSettleFeign extends MercFeeSettleService {
+
+}

+ 19 - 0
device-api-cloud/src/main/java/com/xy/feign/MercFeeStatisticFeign.java

@@ -0,0 +1,19 @@
+package com.xy.feign;
+
+import com.xy.service.MercFeeStatisticService;
+import com.xy.FeignInterceptor;
+import com.xy.consts.ServiceConsts;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * <p>
+ * 商户佣金费用统计 feign
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-24
+ */
+@FeignClient(value = ServiceConsts.SERVICE_NAME, configuration = FeignInterceptor.class)
+public interface MercFeeStatisticFeign extends MercFeeStatisticService {
+
+}

+ 118 - 0
device-api-service-merc-mini/src/main/java/com/xy/controller/DeviceAlgorithmChargingHisController.java

@@ -0,0 +1,118 @@
+package com.xy.controller;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import com.xy.annotate.RestMappingController;
+import com.xy.dto.DeviceAlgorithmChargingHistoryDto;
+import com.xy.service.DeviceAlgorithmChargingHistoryServiceImpl;
+import com.xy.util.ExcelUtils;
+import com.xy.utils.MercAuthUtils;
+import com.xy.utils.PageBean;
+import com.xy.utils.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+@AllArgsConstructor
+@Api(tags = "小程序-设备算法计费表")
+@RestMappingController("merc-mini/deviceAlgorithmChargingHis")
+public class DeviceAlgorithmChargingHisController {
+
+    private DeviceAlgorithmChargingHistoryServiceImpl deviceAlgorithmChargingHistoryService;
+
+
+    @PostMapping("mySpendPage")
+    @ApiOperation("财务管理-支出管理-设备激活费明细")
+    public R<PageBean<DeviceAlgorithmChargingHistoryDto.MySpendPageVO>> mySpendPage(@RequestBody @Validated DeviceAlgorithmChargingHistoryDto.PageByTopMerc page) {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        return deviceAlgorithmChargingHistoryService.mySpendPage(page);
+    }
+
+    @PostMapping("mySpendPageCount")
+    @ApiOperation("财务管理-支出管理-设备激活费统计")
+    public R<Integer> mySpendPageCount(@RequestBody @Validated DeviceAlgorithmChargingHistoryDto.PageByTopMerc page) {
+        page.getPage().setSize(-1);
+        page.setCurMercId(MercAuthUtils.getMercId());
+        PageBean<DeviceAlgorithmChargingHistoryDto.MySpendPageVO> pageVoPageBean = R.feignCheckData(deviceAlgorithmChargingHistoryService.mySpendPage(page));
+        List<DeviceAlgorithmChargingHistoryDto.MySpendPageVO> records = pageVoPageBean.getRecords();
+        int totalMoney = 0;
+        if (CollUtil.isNotEmpty(records)) {
+            for (DeviceAlgorithmChargingHistoryDto.MySpendPageVO r : records) {
+                totalMoney += r.getChargingMoney();
+            }
+        }
+        return R.ok(totalMoney);
+    }
+
+    @ApiOperation("财务管理-支出管理-设备激活费明细导出")
+    @PostMapping("exportMySpendPage")
+    public void exportMySpendPage(HttpServletResponse response, @RequestBody @Valid DeviceAlgorithmChargingHistoryDto.PageByTopMerc page) throws IOException {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        R<PageBean<DeviceAlgorithmChargingHistoryDto.MySpendPageVO>> data = deviceAlgorithmChargingHistoryService.mySpendPage(page);
+        List<DeviceAlgorithmChargingHistoryDto.MySpendPageVO> records = data.getData().getRecords();
+        if (CollUtil.isNotEmpty(records)) {
+            for (DeviceAlgorithmChargingHistoryDto.MySpendPageVO record : records) {
+                Integer status = record.getStatus();
+                if (status.intValue() != 2) {
+                    record.setCreateTime(null);
+                }
+            }
+        }
+        List<DeviceAlgorithmChargingHistoryDto.SpendPageExcelVo> deviceExcelVOS = BeanUtil.copyToList(records, DeviceAlgorithmChargingHistoryDto.SpendPageExcelVo.class);
+        // 输出
+        ExcelUtils.write(response, "设备激活费用明细.xls", "设备激活费明细", DeviceAlgorithmChargingHistoryDto.SpendPageExcelVo.class, deviceExcelVOS);
+    }
+
+
+    @PostMapping("pageByTopMerc")
+    @ApiOperation("加盟商-服务费管理-设备激活费明细")
+    public R<PageBean<DeviceAlgorithmChargingHistoryDto.PageByTopMercVO>> pageByTopMerc(@RequestBody @Validated DeviceAlgorithmChargingHistoryDto.PageByTopMerc page) {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        return deviceAlgorithmChargingHistoryService.pageByTopMerc(page);
+    }
+
+    @PostMapping("pageByTopMercCount")
+    @ApiOperation("加盟商-服务费管理-设备激活费佣金统计")
+    public R<Integer> pageByTopMercCount(@RequestBody @Validated DeviceAlgorithmChargingHistoryDto.PageByTopMerc page) {
+        page.getPage().setSize(-1);
+        page.setCurMercId(MercAuthUtils.getMercId());
+        PageBean<DeviceAlgorithmChargingHistoryDto.PageByTopMercVO> pageVoPageBean = R.feignCheckData(deviceAlgorithmChargingHistoryService.pageByTopMerc(page));
+        List<DeviceAlgorithmChargingHistoryDto.PageByTopMercVO> records = pageVoPageBean.getRecords();
+        int totalAgentMoney = 0;
+        if (CollUtil.isNotEmpty(records)) {
+            for (DeviceAlgorithmChargingHistoryDto.PageByTopMercVO r : records) {
+                totalAgentMoney += r.getAgentMoney();
+            }
+        }
+        return R.ok(totalAgentMoney);
+    }
+
+
+    @ApiOperation("加盟商-服务费管理-设备激活费明细导出")
+    @PostMapping("exportPageByTopMerc")
+    public void exportPageByTopMerc(HttpServletResponse response, @RequestBody @Valid DeviceAlgorithmChargingHistoryDto.PageByTopMerc page) throws IOException {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        R<PageBean<DeviceAlgorithmChargingHistoryDto.PageByTopMercVO>> data = deviceAlgorithmChargingHistoryService.pageByTopMerc(page);
+        List<DeviceAlgorithmChargingHistoryDto.PageByTopMercVO> records = data.getData().getRecords();
+        if (CollUtil.isNotEmpty(records)) {
+            for (DeviceAlgorithmChargingHistoryDto.PageByTopMercVO record : records) {
+                Integer status = record.getStatus();
+                if (status.intValue() != 2) {
+                    record.setCreateTime(null);
+                }
+            }
+        }
+        List<DeviceAlgorithmChargingHistoryDto.PageExcelVo> deviceExcelVOS = BeanUtil.copyToList(records, DeviceAlgorithmChargingHistoryDto.PageExcelVo.class);
+        // 输出
+        ExcelUtils.write(response, "设备激活费用明细.xls", "设备激活费明细", DeviceAlgorithmChargingHistoryDto.PageExcelVo.class, deviceExcelVOS);
+    }
+
+}

+ 79 - 0
device-api-service-merc-mini/src/main/java/com/xy/controller/DeviceChargingHistoryController.java

@@ -1,8 +1,11 @@
 package com.xy.controller;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
 import com.xy.annotate.RestMappingController;
 import com.xy.dto.DeviceChargingHistoryDto;
 import com.xy.service.DeviceChargingHistoryServiceImpl;
+import com.xy.util.ExcelUtils;
 import com.xy.utils.MercAuthUtils;
 import com.xy.utils.PageBean;
 import com.xy.utils.R;
@@ -13,6 +16,11 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
 @AllArgsConstructor
 @Api(tags = "小程序-设备计费历史表")
 @RestMappingController("merc-mini/device-charging-history")
@@ -26,4 +34,75 @@ public class DeviceChargingHistoryController {
         page.setMercId(MercAuthUtils.getMercId());
         return deviceChargingHistoryService.page(page);
     }
+
+    @PostMapping("mySpendPage")
+    @ApiOperation("财务管理-支出管理-设备管理费")
+    public R<PageBean<DeviceChargingHistoryDto.MySpendPageVO>> mySpendPage(@RequestBody DeviceChargingHistoryDto.PageByTopMerc page) {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        return deviceChargingHistoryService.mySpendPage(page);
+    }
+
+    @ApiOperation("财务管理-支出管理-设备管理费导出")
+    @PostMapping("exportMySpendPage")
+    public void exportMySpendPage(HttpServletResponse response, @RequestBody @Valid DeviceChargingHistoryDto.PageByTopMerc page) throws IOException {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        R<PageBean<DeviceChargingHistoryDto.MySpendPageVO>> data = deviceChargingHistoryService.mySpendPage(page);
+        List<DeviceChargingHistoryDto.MySpendPageVO> records = data.getData().getRecords();
+        List<DeviceChargingHistoryDto.SpendPageExcelVo> deviceExcelVOS = BeanUtil.copyToList(records, DeviceChargingHistoryDto.SpendPageExcelVo.class);
+        // 输出
+        ExcelUtils.write(response, "设备管理费缴费记录明细.xls", "设备管理费缴费记录明细", DeviceChargingHistoryDto.SpendPageExcelVo.class, deviceExcelVOS);
+    }
+
+
+    @PostMapping("mySpendPageCount")
+    @ApiOperation("财务管理-支出管理-设备管理费缴费统计")
+    public R<Integer> mySpendPageCount(@RequestBody DeviceChargingHistoryDto.PageByTopMerc page) {
+        page.getPage().setSize(-1);
+        page.setCurMercId(MercAuthUtils.getMercId());
+        PageBean<DeviceChargingHistoryDto.MySpendPageVO> pageVoPageBean = R.feignCheckData(deviceChargingHistoryService.mySpendPage(page));
+        List<DeviceChargingHistoryDto.MySpendPageVO> records = pageVoPageBean.getRecords();
+        int totalMoney = 0;
+        if (CollUtil.isNotEmpty(records)) {
+            for (DeviceChargingHistoryDto.MySpendPageVO r : records) {
+                totalMoney += r.getChargingMoney();
+            }
+        }
+        return R.ok(totalMoney);
+    }
+
+
+    @PostMapping("pageByTopMerc")
+    @ApiOperation("加盟商-服务费管理-设备管理费")
+    public R<PageBean<DeviceChargingHistoryDto.PageVo>> pageByTopMerc(@RequestBody @Validated DeviceChargingHistoryDto.PageByTopMerc page) {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        return deviceChargingHistoryService.pageByTopMerc(page);
+    }
+
+    @PostMapping("pageByTopMercCount")
+    @ApiOperation("加盟商-服务费管理-设备管理费佣金统计")
+    public R<Integer> pageByTopMercCount(@RequestBody @Validated DeviceChargingHistoryDto.PageByTopMerc page) {
+        page.getPage().setSize(-1);
+        page.setCurMercId(MercAuthUtils.getMercId());
+        PageBean<DeviceChargingHistoryDto.PageVo> pageVoPageBean = R.feignCheckData(deviceChargingHistoryService.pageByTopMerc(page));
+        List<DeviceChargingHistoryDto.PageVo> records = pageVoPageBean.getRecords();
+        int totalAgentMoney = 0;
+        if (CollUtil.isNotEmpty(records)) {
+            for (DeviceChargingHistoryDto.PageVo r : records) {
+                totalAgentMoney += r.getAgentMoney();
+            }
+        }
+        return R.ok(totalAgentMoney);
+    }
+
+
+    @ApiOperation("加盟商-服务费管理-设备管理费明细")
+    @PostMapping("exportPageByTopMerc")
+    public void exportPageByTopMerc(HttpServletResponse response, @RequestBody @Valid DeviceChargingHistoryDto.PageByTopMerc page) throws IOException {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        R<PageBean<DeviceChargingHistoryDto.PageVo>> data = deviceChargingHistoryService.pageByTopMerc(page);
+        List<DeviceChargingHistoryDto.PageVo> records = data.getData().getRecords();
+        List<DeviceChargingHistoryDto.PageExcelVo> deviceExcelVOS = BeanUtil.copyToList(records, DeviceChargingHistoryDto.PageExcelVo.class);
+        // 输出
+        ExcelUtils.write(response, "设备管理费明细.xls", "设备管理费明细", DeviceChargingHistoryDto.PageExcelVo.class, deviceExcelVOS);
+    }
 }

+ 95 - 0
device-api-service-merc-mini/src/main/java/com/xy/controller/DeviceSimChargeController.java

@@ -1,11 +1,13 @@
 package com.xy.controller;
 
+import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import com.xy.annotate.RestMappingController;
 import com.xy.dto.DeviceSimChargeDto;
 import com.xy.dto.DeviceSimDto;
 import com.xy.service.DeviceSimChargeServiceImpl;
 import com.xy.service.DeviceSimServiceImpl;
+import com.xy.util.ExcelUtils;
 import com.xy.utils.MercAuthUtils;
 import com.xy.utils.PageBean;
 import com.xy.utils.R;
@@ -17,6 +19,11 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
 @Service
 @AllArgsConstructor
 @Api(tags = "小程序-设备流量卡充值表")
@@ -46,4 +53,92 @@ public class DeviceSimChargeController {
         page.setMercId(MercAuthUtils.getMercId());
         return deviceSimService.page(page);
     }
+
+    @PostMapping("mySpendPage")
+    @ApiOperation("财务管理-支出管理-流量卡费明细")
+    public R<PageBean<DeviceSimChargeDto.MySpendPageVO>> mySpendPage(@RequestBody @Validated DeviceSimChargeDto.PageByTopMerc page) {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        return deviceSimChargeService.mySpendPage(page);
+    }
+
+
+    @ApiOperation("财务管理-支出管理-流量卡费明细")
+    @PostMapping("exportMySpendPage")
+    public void exportMySpendPage(HttpServletResponse response, @RequestBody @Valid DeviceSimChargeDto.PageByTopMerc page) throws IOException {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        R<PageBean<DeviceSimChargeDto.MySpendPageVO>> data = deviceSimChargeService.mySpendPage(page);
+        List<DeviceSimChargeDto.MySpendPageVO> records = data.getData().getRecords();
+        if (CollUtil.isNotEmpty(records)) {
+            for (DeviceSimChargeDto.MySpendPageVO record : records) {
+                Integer status = record.getStatus();
+                if (status.intValue() != 2) {
+                    record.setCreateTime(null);
+                }
+            }
+        }
+        List<DeviceSimChargeDto.SpendPageExcelVo> deviceExcelVOS = BeanUtil.copyToList(records, DeviceSimChargeDto.SpendPageExcelVo.class);
+        // 输出
+        ExcelUtils.write(response, "流量卡费用明细.xls", "流量卡费用明细", DeviceSimChargeDto.SpendPageExcelVo.class, deviceExcelVOS);
+    }
+
+    @PostMapping("mySpendPageCount")
+    @ApiOperation("财务管理-支出管理-流量卡费统计")
+    public R<Integer> mySpendPageCount(@RequestBody @Validated DeviceSimChargeDto.PageByTopMerc page) {
+        page.getPage().setSize(-1);
+        page.setCurMercId(MercAuthUtils.getMercId());
+        PageBean<DeviceSimChargeDto.MySpendPageVO> pageVoPageBean = R.feignCheckData(deviceSimChargeService.mySpendPage(page));
+        List<DeviceSimChargeDto.MySpendPageVO> records = pageVoPageBean.getRecords();
+        int totaMoney = 0;
+        if (CollUtil.isNotEmpty(records)) {
+            for (DeviceSimChargeDto.MySpendPageVO r : records) {
+                totaMoney += r.getMoney();
+            }
+        }
+        return R.ok(totaMoney);
+    }
+
+
+    @PostMapping("pageByTopMerc")
+    @ApiOperation("加盟商-服务费管理-流量卡费明细")
+    public R<PageBean<DeviceSimChargeDto.PageByTopMercVO>> pageByTopMerc(@RequestBody @Validated DeviceSimChargeDto.PageByTopMerc page) {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        return deviceSimChargeService.pageByTopMerc(page);
+    }
+
+    @PostMapping("pageByTopMercCount")
+    @ApiOperation("加盟商-服务费管理-流量卡费佣金统计")
+    public R<Integer> pageByTopMercCount(@RequestBody @Validated DeviceSimChargeDto.PageByTopMerc page) {
+        page.getPage().setSize(-1);
+        page.setCurMercId(MercAuthUtils.getMercId());
+        PageBean<DeviceSimChargeDto.PageByTopMercVO> pageVoPageBean = R.feignCheckData(deviceSimChargeService.pageByTopMerc(page));
+        List<DeviceSimChargeDto.PageByTopMercVO> records = pageVoPageBean.getRecords();
+        int totalAgentMoney = 0;
+        if (CollUtil.isNotEmpty(records)) {
+            for (DeviceSimChargeDto.PageByTopMercVO r : records) {
+                totalAgentMoney += r.getAgentMoney();
+            }
+        }
+        return R.ok(totalAgentMoney);
+    }
+
+
+    @ApiOperation("加盟商-服务费管理-流量卡明细导出")
+    @PostMapping("exportPageByTopMerc")
+    public void exportPageByTopMerc(HttpServletResponse response, @RequestBody @Valid DeviceSimChargeDto.PageByTopMerc page) throws IOException {
+        page.setCurMercId(MercAuthUtils.getMercId());
+        R<PageBean<DeviceSimChargeDto.PageByTopMercVO>> data = deviceSimChargeService.pageByTopMerc(page);
+        List<DeviceSimChargeDto.PageByTopMercVO> records = data.getData().getRecords();
+        if (CollUtil.isNotEmpty(records)) {
+            for (DeviceSimChargeDto.PageByTopMercVO record : records) {
+                Integer status = record.getStatus();
+                if (status.intValue() != 2) {
+                    record.setCreateTime(null);
+                }
+            }
+        }
+        List<DeviceSimChargeDto.PageExcelVo> deviceExcelVOS = BeanUtil.copyToList(records, DeviceSimChargeDto.PageExcelVo.class);
+        // 输出
+        ExcelUtils.write(response, "流量卡费用明细.xls", "流量卡费用明细", DeviceSimChargeDto.PageExcelVo.class, deviceExcelVOS);
+    }
+
 }

+ 40 - 0
device-api-service-merc-mini/src/main/java/com/xy/controller/DeviceSimPayController.java

@@ -0,0 +1,40 @@
+package com.xy.controller;
+
+import cn.hutool.core.collection.CollUtil;
+import com.xy.annotate.RestMappingController;
+import com.xy.dto.DeviceSimChargeDto;
+import com.xy.dto.DeviceSimDto;
+import com.xy.dto.MercFeeConfigAlgorithmTypeDto;
+import com.xy.dto.MercFeeConfigSimCardDto;
+import com.xy.service.DeviceSimChargeServiceImpl;
+import com.xy.service.DeviceSimServiceImpl;
+import com.xy.service.MercFeeConfigSimCardServiceImpl;
+import com.xy.utils.MercAuthUtils;
+import com.xy.utils.PageBean;
+import com.xy.utils.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+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 java.util.List;
+
+@Service
+@AllArgsConstructor
+@Api(tags = "小程序-设备流量卡费用")
+@RestMappingController("merc-mini/deviceSimPay")
+public class DeviceSimPayController {
+
+    private MercFeeConfigSimCardServiceImpl mercFeeConfigSimCardService;
+
+
+    @PostMapping("query")
+    @ApiOperation("流量卡支付费用查询")
+    public R<List<MercFeeConfigSimCardDto.DeviceSimPayVO>> query(@RequestBody @Validated MercFeeConfigAlgorithmTypeDto.SimPayQueryDTO dto) {
+        dto.setMercId(MercAuthUtils.getMercId());
+        return mercFeeConfigSimCardService.paySimCardFee(dto);
+    }
+}

+ 93 - 0
device-api-service-merc-mini/src/main/java/com/xy/controller/MercFeeCountController.java

@@ -0,0 +1,93 @@
+package com.xy.controller;
+
+import cn.hutool.core.util.BooleanUtil;
+import com.xy.annotate.RestMappingController;
+import com.xy.dto.MercFeeCountMonthDto;
+import com.xy.dto.MercFeeSettleDto;
+import com.xy.dto.MercFeeStatisticDto;
+import com.xy.entity.MercFeeStatistic;
+import com.xy.error.CommRuntimeException;
+import com.xy.service.MercFeeCountMonthServiceImpl;
+import com.xy.service.MercFeeSettleServiceImpl;
+import com.xy.service.MercFeeStatisticServiceImpl;
+import com.xy.utils.MercAuthUtils;
+import com.xy.utils.PageBean;
+import com.xy.utils.R;
+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;
+
+@AllArgsConstructor
+@Api(tags = "商户-收益概览")
+@RestMappingController("merc-api/fee")
+public class MercFeeCountController {
+
+    private MercFeeCountMonthServiceImpl mercFeeCountMonthService;
+    private MercFeeStatisticServiceImpl mercFeeStatisticService;
+    private MercFeeSettleServiceImpl mercFeeSettleService;
+
+
+    @PostMapping("page")
+    @ApiOperation("收益概览-分页")
+    public R<PageBean<MercFeeCountMonthDto.Vo>> page(@RequestBody MercFeeCountMonthDto.Page page) {
+        page.setParentMercId(MercAuthUtils.getMercId());
+        return mercFeeCountMonthService.page(page);
+    }
+
+    @PostMapping("confirm")
+    @ApiOperation("确认佣金")
+    public R confirm(@RequestBody @Validated MercFeeCountMonthDto.ConfirmDTO dto) {
+        dto.setParentMercId(MercAuthUtils.getMercId());
+        return mercFeeCountMonthService.confirm(dto);
+    }
+
+    @PostMapping("info")
+    @ApiOperation("总览")
+    public R<MercFeeStatisticDto.InFoVO> info() {
+        return mercFeeStatisticService.info(MercAuthUtils.getMercId());
+    }
+
+
+    @PostMapping("applySettle")
+    @ApiOperation("结算申请")
+    @Transactional(rollbackFor = Exception.class)
+    public R applySettle(@RequestBody @Validated MercFeeSettleDto.ApplyDTO dto) {
+        Long mercId = MercAuthUtils.getMercId();
+        dto.setMercId(mercId);
+        // 验证结算金额是否在可结算金额范围内
+        Integer settleMoney = dto.getSettleMoney();
+        if (settleMoney.intValue() <= 0) {
+            throw new CommRuntimeException("申请结算金额填写有误,必须大于0");
+        }
+        // 可结算金额查看
+        MercFeeStatisticDto.InFoVO inFoVO = R.feignCheckData(mercFeeStatisticService.info(mercId));
+        Integer unSettleMoney = inFoVO.getUnSettleMoney();
+        if (settleMoney > unSettleMoney) {
+            throw new CommRuntimeException("申请结算金额填写有误,不可大于可结算金额:" + unSettleMoney);
+        }
+
+        Boolean b = R.feignCheckData(mercFeeSettleService.applySettle(dto));
+        if (BooleanUtil.isTrue(b)) {
+            // 成功申请,统计表中的可结算佣金扣除申请结算金额
+            unSettleMoney = unSettleMoney - settleMoney;
+            MercFeeStatistic mercFeeStatistic = new MercFeeStatistic();
+            mercFeeStatistic.setMercId(mercId);
+            mercFeeStatistic.setUnSettleMoney(unSettleMoney);
+            mercFeeStatisticService.updateById(mercFeeStatistic);
+        }
+        return R.ok();
+    }
+
+    @PostMapping("settlePage")
+    @ApiOperation("收益概览-结算记录")
+    public R<PageBean<MercFeeSettleDto.Vo>> settlePage(@RequestBody MercFeeSettleDto.Page page) {
+        page.setMercId(MercAuthUtils.getMercId());
+        return mercFeeSettleService.page(page);
+    }
+
+
+}

+ 5 - 5
device-api-service/src/main/java/com/xy/entity/DeviceAdminActivate.java

@@ -1,8 +1,5 @@
 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;
@@ -10,9 +7,12 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
 /**
  * <p>
- * 管理员设备激活记录表
+ * 管理员设备激活记录表1
  * </p>
  *
  * @author lijin
@@ -21,7 +21,7 @@ import lombok.experimental.Accessors;
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
-@ApiModel(value="DeviceAdminActivate对象", description="管理员设备激活记录表")
+@ApiModel(value = "DeviceAdminActivate对象", description = "管理员设备激活记录表")
 public class DeviceAdminActivate implements Serializable {
 
     private static final long serialVersionUID = 1L;

+ 7 - 3
device-api-service/src/main/java/com/xy/entity/DeviceChargingConfig.java

@@ -1,13 +1,14 @@
 package com.xy.entity;
 
-import java.time.LocalDateTime;
-import java.io.Serializable;
 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>
  * 设备计费配置表
@@ -19,7 +20,7 @@ import lombok.experimental.Accessors;
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
-@ApiModel(value="DeviceChargingConfig对象", description="设备计费配置表")
+@ApiModel(value = "DeviceChargingConfig对象", description = "设备计费配置表")
 public class DeviceChargingConfig implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -36,6 +37,9 @@ public class DeviceChargingConfig implements Serializable {
     @ApiModelProperty(value = "赠送天数/预充金额")
     private Integer configValue;
 
+    @ApiModelProperty(value = "代理商额外费用")
+    private Integer extraMoney;
+
     @ApiModelProperty(value = "类型")
     private Integer type;
 

+ 11 - 4
device-api-service/src/main/java/com/xy/entity/DeviceTypeAlgorithmBeforConfig.java

@@ -1,8 +1,5 @@
 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;
@@ -10,6 +7,9 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
 /**
  * <p>
  * 设备类型算法预充配置
@@ -21,7 +21,7 @@ import lombok.experimental.Accessors;
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
-@ApiModel(value="DeviceTypeAlgorithmBeforConfig对象", description="设备类型算法预充配置")
+@ApiModel(value = "DeviceTypeAlgorithmBeforConfig对象", description = "设备类型算法预充配置")
 public class DeviceTypeAlgorithmBeforConfig implements Serializable {
 
     private static final long serialVersionUID = 1L;
@@ -33,6 +33,12 @@ public class DeviceTypeAlgorithmBeforConfig implements Serializable {
     @ApiModelProperty(value = "商户id")
     private Long mercId;
 
+    @ApiModelProperty(value = "商户编码")
+    private String mercCode;
+
+    @ApiModelProperty(value = "代理商额外收取金额;单位:分")
+    private Integer extraMoney;
+
     @ApiModelProperty(value = "设备类型")
     private Integer deviceType;
 
@@ -42,6 +48,7 @@ public class DeviceTypeAlgorithmBeforConfig implements Serializable {
     @ApiModelProperty(value = "预充金额;单位:分")
     private Integer money;
 
+
     @ApiModelProperty(value = "创建时间")
     private LocalDateTime createTime;
 

+ 67 - 0
device-api-service/src/main/java/com/xy/entity/MercFeeConfigAlgorithmType.java

@@ -0,0 +1,67 @@
+package com.xy.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 商户算法扣费标准配置扩展
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="MercFeeConfigAlgorithmType对象", description="商户算法扣费标准配置扩展")
+public class MercFeeConfigAlgorithmType implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "ID")
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private Long id;
+
+    @ApiModelProperty(value = "商户编码")
+    private String mercCode;
+
+    @ApiModelProperty(value = "商户id")
+    private Long mercId;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "创建人")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @ApiModelProperty(value = "更新人")
+    @TableField(fill = FieldFill.UPDATE)
+    private Long updateUser;
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(fill = FieldFill.UPDATE)
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty(value = "算法ID")
+    private Long algorithmId;
+
+    @ApiModelProperty(value = "包月费用(比平台多收的金额)")
+    private Integer extraMonthMoney;
+
+    @ApiModelProperty(value = "算法单笔金额(比平台多收的金额)")
+    private Integer extraSingleMoney;
+
+
+}

+ 64 - 0
device-api-service/src/main/java/com/xy/entity/MercFeeConfigDevice.java

@@ -0,0 +1,64 @@
+package com.xy.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 商户设备管理费配置扩展
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="MercFeeConfigDevice对象", description="商户设备管理费配置扩展")
+public class MercFeeConfigDevice implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "ID")
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private Long id;
+
+    @ApiModelProperty(value = "商户编码")
+    private String mercCode;
+
+    @ApiModelProperty(value = "商户id")
+    private Long mercId;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "创建人")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @ApiModelProperty(value = "更新人")
+    @TableField(fill = FieldFill.UPDATE)
+    private Long updateUser;
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(fill = FieldFill.UPDATE)
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty(value = "设备类型")
+    private Integer deviceType;
+
+    @ApiModelProperty(value = "设备管理费金额(比平台多收的金额)")
+    private Integer extraMoney;
+
+
+}

+ 61 - 0
device-api-service/src/main/java/com/xy/entity/MercFeeConfigSimCard.java

@@ -0,0 +1,61 @@
+package com.xy.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 商户流量卡费配置扩展
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="MercFeeConfigSimCard对象", description="商户流量卡费配置扩展")
+public class MercFeeConfigSimCard implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "ID")
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private Long id;
+
+    @ApiModelProperty(value = "商户编码")
+    private String mercCode;
+
+    @ApiModelProperty(value = "商户id")
+    private Long mercId;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "创建人")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @ApiModelProperty(value = "更新人")
+    @TableField(fill = FieldFill.UPDATE)
+    private Long updateUser;
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(fill = FieldFill.UPDATE)
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty(value = "流量卡费金额(比平台多收的金额)")
+    private Integer extraMoney;
+
+
+}

+ 66 - 0
device-api-service/src/main/java/com/xy/entity/MercFeeCountDay.java

@@ -0,0 +1,66 @@
+package com.xy.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+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;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 商户佣金费用收益每日统计(不含今天)
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "MercFeeCountDay对象", description = "商户佣金费用收益每日统计(不含今天)")
+public class MercFeeCountDay implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "id")
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private Long id;
+
+    @ApiModelProperty(value = "商户ID")
+    private Long mercId;
+
+    @ApiModelProperty(value = "父商户ID")
+    private Long parentMercId;
+
+    @ApiModelProperty(value = "统计日期20220603")
+    private Integer dateValue;
+
+    @ApiModelProperty(value = "统计日期202206")
+    private Integer monthValue;
+
+    @ApiModelProperty(value = "缴费金额")
+    private Integer payMoney;
+
+    @ApiModelProperty(value = "佣金")
+    private Integer brokerage;
+
+    @ApiModelProperty(value = "缴费类型")
+    private Integer feeType;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(fill = FieldFill.UPDATE)
+    private LocalDateTime updateTime;
+
+
+}

+ 69 - 0
device-api-service/src/main/java/com/xy/entity/MercFeeCountMonth.java

@@ -0,0 +1,69 @@
+package com.xy.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+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;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 商户佣金费用收益每月统计(不含本月)
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "MercFeeCountMonth对象", description = "商户佣金费用收益每月统计(不含本月)")
+public class MercFeeCountMonth implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "id")
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private Long id;
+    @ApiModelProperty(value = "商户ID")
+    private Long mercId;
+
+    @ApiModelProperty(value = "父商户ID")
+    private Long parentMercId;
+
+
+    @ApiModelProperty(value = "统计日期202206")
+    private Integer dateValue;
+
+    @ApiModelProperty(value = "缴费金额")
+    private Integer payMoney;
+
+    @ApiModelProperty(value = "佣金")
+    private Integer brokerage;
+
+    @ApiModelProperty(value = "缴费类型")
+    private Integer feeType;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(fill = FieldFill.UPDATE)
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty(value = "是否确认")
+    private Boolean verify;
+
+    @ApiModelProperty(value = "确认时间")
+    private LocalDateTime verifyTime;
+
+
+}

+ 67 - 0
device-api-service/src/main/java/com/xy/entity/MercFeeSettle.java

@@ -0,0 +1,67 @@
+package com.xy.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 商户佣金费用结算
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="MercFeeSettle对象", description="商户佣金费用结算")
+public class MercFeeSettle implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "id")
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private Long id;
+
+    @ApiModelProperty(value = "商户ID")
+    private Long mercId;
+
+    @ApiModelProperty(value = "结算金额")
+    private Integer settleMoney;
+
+    @ApiModelProperty(value = "申请时间")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "申请人")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(fill = FieldFill.UPDATE)
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty(value = "结算状态(1未结算、结算中、2已结算)")
+    private Integer settleState;
+
+    @ApiModelProperty(value = "结算完成时间")
+    private LocalDateTime finishSettleTime;
+
+    @ApiModelProperty(value = "发票图片(最多支持4个,|分隔)")
+    private String titleImg;
+
+    @ApiModelProperty(value = "结算人")
+    @TableField(fill = FieldFill.UPDATE)
+    private Long updateUser;
+
+
+}

+ 53 - 0
device-api-service/src/main/java/com/xy/entity/MercFeeStatistic.java

@@ -0,0 +1,53 @@
+package com.xy.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 商户佣金费用统计
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-24
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="MercFeeStatistic对象", description="商户佣金费用统计")
+public class MercFeeStatistic implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "商户ID")
+    @TableId(value = "merc_id", type = IdType.ASSIGN_ID)
+    private Long mercId;
+
+    @ApiModelProperty(value = "累计已结算佣金")
+    private Integer settleMoney;
+
+    @ApiModelProperty(value = "可结算佣金")
+    private Integer unSettleMoney;
+
+    @ApiModelProperty(value = "累计已确认佣金")
+    private Integer verifyMoney;
+
+    @ApiModelProperty(value = "申请时间")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(fill = FieldFill.UPDATE)
+    private LocalDateTime updateTime;
+
+
+}

+ 418 - 0
device-api-service/src/main/java/com/xy/job/MercFeeCountDayJob.java

@@ -0,0 +1,418 @@
+package com.xy.job;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.util.StrUtil;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import com.xy.annotate.RestMappingController;
+import com.xy.device.EnumDeviceActiveStatus;
+import com.xy.dto.*;
+import com.xy.dto.be.MercDto;
+import com.xy.entity.MercFeeCountDay;
+import com.xy.enums.MercStatus;
+import com.xy.error.CommRuntimeException;
+import com.xy.merc.EnumMercDeviceAlgorithmChargingPayType;
+import com.xy.service.*;
+import com.xy.service.be.MercFeignService;
+import com.xy.service.be.MercService;
+import com.xy.sys.EnumMercFeeType;
+import com.xy.utils.LambdaUtils;
+import com.xy.utils.PageBean;
+import com.xy.utils.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+/**
+ * 商户佣金费用收益每日统计任务(不含今天) 每日凌晨1点执行
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+@Api(tags = "商户佣金费用收益每日统计任务")
+@RestMappingController("job/feeCountDay")
+public class MercFeeCountDayJob {
+
+
+    private final DeviceInfoService deviceInfoService;
+
+    private final MercFeignService mercFeignService;
+
+    private final DeviceChargingHistoryServiceImpl deviceChargingHistoryService;
+
+    private final MercFeeCountDayServiceImpl mercFeeCountDayService;
+
+    private final DeviceAlgorithmChargingHistoryServiceImpl deviceAlgorithmChargingHistoryService;
+
+    private final MercDeviceAlgorithmChargingService mercDeviceAlgorithmChargingService;
+
+    private final DeviceSimChargeServiceImpl deviceSimChargeService;
+
+    private final MercService mercService;
+
+
+    @PostMapping("excuteJob")
+    @ApiOperation("指定日期执行")
+    public R excuteJob(@RequestBody @Validated MercFeeCountDayDto.ExcuteDayDTO dto) {
+        return R.ok(dayJob(dto.getDate()));
+    }
+
+    /**
+     * 商户佣金费用收益每日统计(不含今天)
+     * 类型 1设备管理费。2设备激活费。3算法扣费标准。4流量卡费
+     *
+     * @param date yyyyMMdd
+     * @return
+     */
+    @XxlJob("mercFeeCountDayJob")
+    public ReturnT<String> dayJob(String date) {
+        log.info("-----------商户佣金费用收益每日统计 开始-----------");
+//        long startTime = System.currentTimeMillis();
+        DateTime yesterday = DateUtil.yesterday();
+        String queryDay = DateUtil.format(yesterday, DatePattern.PURE_DATE_PATTERN);
+        if (StrUtil.isNotEmpty(date)) {
+            queryDay = date;
+
+            //指定日期需要判断是否重复执行
+            MercFeeCountDayDto.SelectList selectList = new MercFeeCountDayDto.SelectList();
+            selectList.setDateValue(Integer.valueOf(queryDay));
+            List<MercFeeCountDayDto.Vo> vos = R.feignCheckData(mercFeeCountDayService.list(selectList));
+            if (CollUtil.isNotEmpty(vos)) {
+                throw new CommRuntimeException("已存在日期【" + date + "】的数据,请勿重复执行!");
+            }
+        }
+        String monthValue = StrUtil.sub(queryDay, 0, 6);
+        Integer dateValue = Integer.valueOf(queryDay);
+        LocalDate dayDate = LocalDate.parse(queryDay, DateTimeFormatter.BASIC_ISO_DATE);
+        LocalDateTime dayTime = dayDate.atStartOfDay();
+        LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(dayTime);
+        LocalDateTime endTime = LocalDateTimeUtil.endOfDay(dayTime);
+
+        List<String> columnsMerc = Arrays.asList(LambdaUtils.getUnderlineCaseName(MercDto.Vo::getId));
+
+        List<MercDto.Vo> approvedMercList = getApprovedMercList(columnsMerc);
+        if (CollUtil.isEmpty(approvedMercList)) {
+            return ReturnT.SUCCESS;
+        }
+
+
+        for (MercDto.Vo merc : approvedMercList) {
+            Long parentMercId = merc.getId();
+            List<Long> mercIds = R.feignCheckData(mercService.getChildMercIds(new MercDto.QuerySubDTO().setParentMercID(parentMercId)));
+            if (CollUtil.isEmpty(mercIds)) {
+                //子商户都没有,就不用查分佣收益了
+                continue;
+            }
+            //~~~~~~~~~~~~~1设备管理费
+            PageBean<DeviceChargingHistoryDto.PageVo> pageVoPageBean = getDeviceManagerFeeMerc(parentMercId, beginTime, endTime);
+            List<DeviceChargingHistoryDto.PageVo> records = pageVoPageBean == null ? null : pageVoPageBean.getRecords();
+            if (CollUtil.isNotEmpty(records)) {
+                //根据设备分组获取,每台设备缴费金额
+                Map<Long, Integer> devicePayMoneyMap = records.stream()
+                        .collect(Collectors.groupingBy(DeviceChargingHistoryDto.PageVo::getMercId,
+                                Collectors.summingInt(DeviceChargingHistoryDto.PageVo::getChargingMoney)));
+                //根据设备分组获取,每台设备佣金金额
+                Map<Long, Integer> deviceAgentMoneyMap = records.stream()
+                        .collect(Collectors.groupingBy(DeviceChargingHistoryDto.PageVo::getMercId,
+                                Collectors.summingInt(DeviceChargingHistoryDto.PageVo::getAgentMoney)));
+                Set<Long> subMercIdSet = devicePayMoneyMap.keySet();
+                List<MercFeeCountDay> saveMercFeeCountList = new ArrayList<>();
+                for (Long mercId : subMercIdSet) {
+                    Integer payMoney = devicePayMoneyMap.get(mercId);
+                    Integer brokerage = deviceAgentMoneyMap.get(mercId);
+                    MercFeeCountDay deviceDayFee = new MercFeeCountDay();
+                    deviceDayFee.setFeeType(EnumMercFeeType.T1.getIntCode());
+                    deviceDayFee.setParentMercId(parentMercId);
+                    deviceDayFee.setDateValue(dateValue);
+                    deviceDayFee.setPayMoney(payMoney);
+                    deviceDayFee.setMonthValue(Integer.valueOf(monthValue));
+                    deviceDayFee.setBrokerage(brokerage);
+                    deviceDayFee.setMercId(mercId);
+                    deviceDayFee.setParentMercId(parentMercId);
+                    saveMercFeeCountList.add(deviceDayFee);
+                }
+                mercFeeCountDayService.saveBatch(saveMercFeeCountList);
+            } else {
+                //没有费用的也要记录,为了前端收益概览的展示
+                List<MercFeeCountDay> saveMercFeeCountList = new ArrayList<>();
+                for (Long mercId : mercIds) {
+
+                    MercFeeCountDay deviceDayFee = new MercFeeCountDay();
+                    deviceDayFee.setFeeType(EnumMercFeeType.T1.getIntCode());
+                    deviceDayFee.setParentMercId(parentMercId);
+                    deviceDayFee.setDateValue(dateValue);
+                    deviceDayFee.setPayMoney(0);
+                    deviceDayFee.setMonthValue(Integer.valueOf(monthValue));
+                    deviceDayFee.setBrokerage(0);
+                    deviceDayFee.setMercId(mercId);
+                    deviceDayFee.setParentMercId(parentMercId);
+                    saveMercFeeCountList.add(deviceDayFee);
+                }
+                mercFeeCountDayService.saveBatch(saveMercFeeCountList);
+            }
+
+            //~~~~~~~~~~~~~1设备管理费
+
+            //~~~~~~~~~~~~~2设备激活费
+            PageBean<DeviceAlgorithmChargingHistoryDto.PageByTopMercVO> deviceActiveFeeByMerc = getDeviceActiveFeeByMerc(parentMercId, beginTime, endTime);
+            List<DeviceAlgorithmChargingHistoryDto.PageByTopMercVO> deviceActiveFeeList = deviceActiveFeeByMerc == null ? null : deviceActiveFeeByMerc.getRecords();
+            if (CollUtil.isNotEmpty(deviceActiveFeeList)) {
+                //根据设备分组获取,每台设备缴费金额
+                Map<Long, Integer> devicePayMoneyMap = deviceActiveFeeList.stream()
+                        .collect(Collectors.groupingBy(DeviceAlgorithmChargingHistoryDto.PageByTopMercVO::getMercId,
+                                Collectors.summingInt(DeviceAlgorithmChargingHistoryDto.PageByTopMercVO::getChargingMoney)));
+                //根据设备分组获取,每台设备佣金金额
+                Map<Long, Integer> deviceAgentMoneyMap = deviceActiveFeeList.stream()
+                        .collect(Collectors.groupingBy(DeviceAlgorithmChargingHistoryDto.PageByTopMercVO::getMercId,
+                                Collectors.summingInt(DeviceAlgorithmChargingHistoryDto.PageByTopMercVO::getAgentMoney)));
+                Set<Long> subMercIdSet = devicePayMoneyMap.keySet();
+                List<MercFeeCountDay> saveMercFeeCountList = new ArrayList<>();
+                for (Long mercId : subMercIdSet) {
+                    Integer payMoney = devicePayMoneyMap.get(mercId);
+                    Integer brokerage = deviceAgentMoneyMap.get(mercId);
+                    MercFeeCountDay deviceDayFee = new MercFeeCountDay();
+                    deviceDayFee.setFeeType(EnumMercFeeType.T2.getIntCode());
+                    deviceDayFee.setParentMercId(parentMercId);
+                    deviceDayFee.setDateValue(dateValue);
+                    deviceDayFee.setPayMoney(payMoney);
+                    deviceDayFee.setMonthValue(Integer.valueOf(monthValue));
+                    deviceDayFee.setBrokerage(brokerage);
+                    deviceDayFee.setMercId(mercId);
+                    deviceDayFee.setParentMercId(parentMercId);
+                    saveMercFeeCountList.add(deviceDayFee);
+                }
+                mercFeeCountDayService.saveBatch(saveMercFeeCountList);
+            } else {
+                //没有费用的也要记录,为了前端收益概览的展示
+                List<MercFeeCountDay> saveMercFeeCountList = new ArrayList<>();
+                for (Long mercId : mercIds) {
+
+                    MercFeeCountDay deviceDayFee = new MercFeeCountDay();
+                    deviceDayFee.setFeeType(EnumMercFeeType.T2.getIntCode());
+                    deviceDayFee.setParentMercId(parentMercId);
+                    deviceDayFee.setDateValue(dateValue);
+                    deviceDayFee.setPayMoney(0);
+                    deviceDayFee.setMonthValue(Integer.valueOf(monthValue));
+                    deviceDayFee.setBrokerage(0);
+                    deviceDayFee.setMercId(mercId);
+                    deviceDayFee.setParentMercId(parentMercId);
+                    saveMercFeeCountList.add(deviceDayFee);
+                }
+                mercFeeCountDayService.saveBatch(saveMercFeeCountList);
+            }
+
+            //~~~~~~~~~~~~~2设备激活费
+
+            //~~~~~~~~~~~~~3算法服务费
+            PageBean<MercDeviceAlgorithmChargingDto.PageByTopMercVO> deviceAgFeeByMerc = getDeviceAgFeeByMerc(parentMercId, beginTime, endTime);
+            List<MercDeviceAlgorithmChargingDto.PageByTopMercVO> deviceAgFeeList = deviceAgFeeByMerc == null ? null : deviceAgFeeByMerc.getRecords();
+            if (CollUtil.isNotEmpty(deviceAgFeeList)) {
+                //根据设备分组获取,每台设备缴费金额
+                Map<Long, Integer> devicePayMoneyMap = deviceAgFeeList.stream()
+                        .collect(Collectors.groupingBy(MercDeviceAlgorithmChargingDto.PageByTopMercVO::getMercId,
+                                Collectors.summingInt(MercDeviceAlgorithmChargingDto.PageByTopMercVO::getFeeBalance)));
+                //根据设备分组获取,每台设备佣金金额
+                Map<Long, Integer> deviceAgentMoneyMap = deviceAgFeeList.stream()
+                        .collect(Collectors.groupingBy(MercDeviceAlgorithmChargingDto.PageByTopMercVO::getMercId,
+                                Collectors.summingInt(MercDeviceAlgorithmChargingDto.PageByTopMercVO::getAgentMoney)));
+                Set<Long> subMercIdSet = devicePayMoneyMap.keySet();
+                List<MercFeeCountDay> saveMercFeeCountList = new ArrayList<>();
+                for (Long mercId : subMercIdSet) {
+                    Integer payMoney = devicePayMoneyMap.get(mercId);
+                    Integer brokerage = deviceAgentMoneyMap.get(mercId);
+                    MercFeeCountDay deviceDayFee = new MercFeeCountDay();
+                    deviceDayFee.setFeeType(EnumMercFeeType.T3.getIntCode());
+                    deviceDayFee.setParentMercId(parentMercId);
+                    deviceDayFee.setDateValue(dateValue);
+                    deviceDayFee.setPayMoney(payMoney);
+                    deviceDayFee.setBrokerage(brokerage);
+                    deviceDayFee.setMercId(mercId);
+                    deviceDayFee.setParentMercId(parentMercId);
+                    saveMercFeeCountList.add(deviceDayFee);
+                }
+                mercFeeCountDayService.saveBatch(saveMercFeeCountList);
+            } else {
+                //没有费用的也要记录,为了前端收益概览的展示
+                List<MercFeeCountDay> saveMercFeeCountList = new ArrayList<>();
+                for (Long mercId : mercIds) {
+
+                    MercFeeCountDay deviceDayFee = new MercFeeCountDay();
+                    deviceDayFee.setFeeType(EnumMercFeeType.T3.getIntCode());
+                    deviceDayFee.setParentMercId(parentMercId);
+                    deviceDayFee.setDateValue(dateValue);
+                    deviceDayFee.setPayMoney(0);
+                    deviceDayFee.setMonthValue(Integer.valueOf(monthValue));
+                    deviceDayFee.setBrokerage(0);
+                    deviceDayFee.setMercId(mercId);
+                    deviceDayFee.setParentMercId(parentMercId);
+                    saveMercFeeCountList.add(deviceDayFee);
+                }
+                mercFeeCountDayService.saveBatch(saveMercFeeCountList);
+            }
+            //~~~~~~~~~~~~~3算法服务费
+
+            //~~~~~~~~~~~~~4流量卡费
+            PageBean<DeviceSimChargeDto.PageByTopMercVO> simFeeByMerc = getSimFeeByMerc(parentMercId, beginTime, endTime);
+            List<DeviceSimChargeDto.PageByTopMercVO> simFeeList = simFeeByMerc == null ? null : simFeeByMerc.getRecords();
+            if (CollUtil.isNotEmpty(simFeeList)) {
+                //根据设备分组获取,每台设备缴费金额
+                Map<Long, Integer> devicePayMoneyMap = simFeeList.stream()
+                        .collect(Collectors.groupingBy(DeviceSimChargeDto.PageByTopMercVO::getMercId,
+                                Collectors.summingInt(DeviceSimChargeDto.PageByTopMercVO::getMoney)));
+                //根据设备分组获取,每台设备佣金金额
+                Map<Long, Integer> deviceAgentMoneyMap = simFeeList.stream()
+                        .collect(Collectors.groupingBy(DeviceSimChargeDto.PageByTopMercVO::getMercId,
+                                Collectors.summingInt(DeviceSimChargeDto.PageByTopMercVO::getAgentMoney)));
+                Set<Long> subMercIdSet = devicePayMoneyMap.keySet();
+                List<MercFeeCountDay> saveMercFeeCountList = new ArrayList<>();
+                for (Long mercId : subMercIdSet) {
+                    Integer payMoney = devicePayMoneyMap.get(mercId);
+                    Integer brokerage = deviceAgentMoneyMap.get(mercId);
+                    MercFeeCountDay deviceDayFee = new MercFeeCountDay();
+                    deviceDayFee.setFeeType(EnumMercFeeType.T4.getIntCode());
+                    deviceDayFee.setParentMercId(parentMercId);
+                    deviceDayFee.setDateValue(dateValue);
+                    deviceDayFee.setPayMoney(payMoney);
+                    deviceDayFee.setBrokerage(brokerage);
+                    deviceDayFee.setMercId(mercId);
+                    deviceDayFee.setParentMercId(parentMercId);
+                    saveMercFeeCountList.add(deviceDayFee);
+                }
+                mercFeeCountDayService.saveBatch(saveMercFeeCountList);
+            } else {
+                //没有费用的也要记录,为了前端收益概览的展示
+                List<MercFeeCountDay> saveMercFeeCountList = new ArrayList<>();
+                for (Long mercId : mercIds) {
+
+                    MercFeeCountDay deviceDayFee = new MercFeeCountDay();
+                    deviceDayFee.setFeeType(EnumMercFeeType.T4.getIntCode());
+                    deviceDayFee.setParentMercId(parentMercId);
+                    deviceDayFee.setDateValue(dateValue);
+                    deviceDayFee.setPayMoney(0);
+                    deviceDayFee.setMonthValue(Integer.valueOf(monthValue));
+                    deviceDayFee.setBrokerage(0);
+                    deviceDayFee.setMercId(mercId);
+                    deviceDayFee.setParentMercId(parentMercId);
+                    saveMercFeeCountList.add(deviceDayFee);
+                }
+                mercFeeCountDayService.saveBatch(saveMercFeeCountList);
+            }
+            //~~~~~~~~~~~~~4流量卡费
+        }
+        return ReturnT.SUCCESS;
+    }
+
+    private List<MercDto.Vo> getApprovedMercList(List<String> columnsMerc) {
+        return R.feignCheckData(mercFeignService.listMerc(new MercDto.ListDTO().setStatus(String.valueOf(MercStatus.APPROVED.getCode())).setColumnList(columnsMerc)));
+    }
+
+    /**
+     * 指定商户已激活设备
+     *
+     * @param mercId
+     * @return
+     */
+    private List<DeviceInfoDto.Vo> getActiveDevicesByMercId(Long mercId) {
+        DeviceInfoDto.ListCommon listCommon = new DeviceInfoDto.ListCommon().setVo(new DeviceInfoDto.Vo().setActiveState(EnumDeviceActiveStatus.N_1.getIntCode()).setMercId(mercId));
+        return R.feignCheckData(deviceInfoService.listCommon(listCommon));
+    }
+
+    /**
+     * 获取指定商户的子商户设备管理费缴纳记录
+     *
+     * @param mercId
+     * @param beginCreateTime 开始时间
+     * @param endCreateTime   结束时间
+     * @return
+     */
+    private PageBean<DeviceChargingHistoryDto.PageVo> getDeviceManagerFeeMerc(Long mercId, LocalDateTime beginCreateTime, LocalDateTime endCreateTime) {
+        DeviceChargingHistoryDto.PageByTopMerc pageByTopMerc = new DeviceChargingHistoryDto.PageByTopMerc();
+        PageBean page = new PageBean();
+        page.setSize(-1);
+        pageByTopMerc.setCurMercId(mercId);
+        pageByTopMerc.setBeginCreateTime(beginCreateTime);
+        pageByTopMerc.setEndCreateTime(endCreateTime);
+        pageByTopMerc.setPage(page);
+        return R.feignCheckData(deviceChargingHistoryService.pageByTopMerc(pageByTopMerc));
+    }
+
+    /**
+     * 获取指定商户的子商户设备激活费缴纳记录
+     *
+     * @param mercId
+     * @param beginCreateTime
+     * @param endCreateTime
+     * @return
+     */
+    private PageBean<DeviceAlgorithmChargingHistoryDto.PageByTopMercVO> getDeviceActiveFeeByMerc(Long mercId, LocalDateTime beginCreateTime, LocalDateTime endCreateTime) {
+
+        DeviceAlgorithmChargingHistoryDto.PageByTopMerc pageByTopMerc = new DeviceAlgorithmChargingHistoryDto.PageByTopMerc();
+        PageBean page = new PageBean();
+        page.setSize(-1);
+        pageByTopMerc.setCurMercId(mercId);
+        pageByTopMerc.setBeginCreateTime(beginCreateTime);
+        pageByTopMerc.setEndCreateTime(endCreateTime);
+        pageByTopMerc.setPage(page);
+        return R.feignCheckData(deviceAlgorithmChargingHistoryService.pageByTopMerc(pageByTopMerc));
+    }
+
+    /**
+     * 获取指定商户的子商户设备算法服务费缴纳记录
+     *
+     * @param mercId
+     * @param beginCreateTime
+     * @param endCreateTime
+     * @return
+     */
+    private PageBean<MercDeviceAlgorithmChargingDto.PageByTopMercVO> getDeviceAgFeeByMerc(Long mercId, LocalDateTime beginCreateTime, LocalDateTime endCreateTime) {
+
+        MercDeviceAlgorithmChargingDto.PageByTopMerc pageByTopMerc = new MercDeviceAlgorithmChargingDto.PageByTopMerc();
+        PageBean page = new PageBean();
+        page.setSize(-1);
+        String payType = EnumMercDeviceAlgorithmChargingPayType.N_2.getCode();
+        pageByTopMerc.setPayType(Integer.valueOf(payType));
+        pageByTopMerc.setCurMercId(mercId);
+        pageByTopMerc.setBeginCreateTime(beginCreateTime);
+        pageByTopMerc.setEndCreateTime(endCreateTime);
+        pageByTopMerc.setPage(page);
+        return R.feignCheckData(mercDeviceAlgorithmChargingService.pageByMerc(pageByTopMerc));
+    }
+
+    /**
+     * 获取指定商户的子商户流量卡缴纳记录
+     *
+     * @param mercId
+     * @param beginCreateTime
+     * @param endCreateTime
+     * @return
+     */
+    private PageBean<DeviceSimChargeDto.PageByTopMercVO> getSimFeeByMerc(Long mercId, LocalDateTime beginCreateTime, LocalDateTime endCreateTime) {
+
+        DeviceSimChargeDto.PageByTopMerc pageByTopMerc = new DeviceSimChargeDto.PageByTopMerc();
+        PageBean page = new PageBean();
+        page.setSize(-1);
+        pageByTopMerc.setStatus(2);
+        pageByTopMerc.setCurMercId(mercId);
+        pageByTopMerc.setBeginCreateTime(beginCreateTime);
+        pageByTopMerc.setEndCreateTime(endCreateTime);
+        pageByTopMerc.setPage(page);
+        return R.feignCheckData(deviceSimChargeService.pageByTopMerc(pageByTopMerc));
+    }
+
+}

+ 86 - 0
device-api-service/src/main/java/com/xy/job/MercFeeCountMonthJob.java

@@ -0,0 +1,86 @@
+package com.xy.job;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import com.xy.annotate.RestMappingController;
+import com.xy.dto.MercFeeCountDayDto;
+import com.xy.dto.MercFeeCountMonthDto;
+import com.xy.entity.MercFeeCountMonth;
+import com.xy.error.CommRuntimeException;
+import com.xy.service.MercFeeCountDayServiceImpl;
+import com.xy.service.MercFeeCountMonthServiceImpl;
+import com.xy.utils.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+
+
+/**
+ * 商户佣金费用收益每月统计任务(不含本月) 每月1号凌晨2点执行
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+@Api(tags = "商户佣金费用收益每月统计任务")
+@RestMappingController("job/feeCountMonth")
+public class MercFeeCountMonthJob {
+
+    private final MercFeeCountDayServiceImpl mercFeeCountDayService;
+    private final MercFeeCountMonthServiceImpl mercFeeCountMonthService;
+
+    @PostMapping("excuteJob")
+    @ApiOperation("指定日期执行")
+    public R excuteJob(@RequestBody @Validated MercFeeCountMonthDto.ExcuteDayDTO dto) {
+        return R.ok(monthJob(dto.getDate()));
+    }
+
+    /**
+     * 商户佣金费用收益每月统计任务(不含今天)
+     * 类型 1设备管理费。2设备激活费。3算法扣费标准。4流量卡费
+     *
+     * @param date yyyyMM
+     * @return
+     */
+    @XxlJob("mercFeeCountMonthJob")
+    public ReturnT<String> monthJob(String date) {
+        //获取上个月
+        DateTime lastMonth = DateUtil.lastMonth();
+        String queryDay = DateUtil.format(lastMonth, DatePattern.SIMPLE_MONTH_PATTERN);
+        if (StrUtil.isNotEmpty(date)) {
+            queryDay = date;
+            //指定日期需要判断是否重复执行
+            MercFeeCountMonthDto.SelectList selectList = new MercFeeCountMonthDto.SelectList();
+            selectList.setDateValue(Integer.valueOf(DateUtil.format(lastMonth, DatePattern.PURE_DATE_PATTERN)));
+            List<MercFeeCountMonthDto.Vo> vos = R.feignCheckData(mercFeeCountMonthService.list(selectList));
+            if (CollUtil.isNotEmpty(vos)) {
+                throw new CommRuntimeException("已存在日期【" + date + "】的数据,请勿重复执行!");
+            }
+        }
+        //年月
+        Integer monthValue = Integer.valueOf(queryDay);
+        // 按商户id,父商户ID,缴费类型  统计指定月份 缴费总和、佣金总和
+        List<MercFeeCountDayDto.CountByMonthVO> countByMonthVOS = mercFeeCountDayService.countByMonth(new MercFeeCountDayDto.CountByMonth().setMonthValue(monthValue));
+        if (CollUtil.isNotEmpty(countByMonthVOS)) {
+            List<MercFeeCountMonth> mercFeeCountMonths = BeanUtil.copyToList(countByMonthVOS, MercFeeCountMonth.class);
+            mercFeeCountMonths.forEach(mfm -> {
+                mfm.setDateValue(monthValue);
+            });
+            mercFeeCountMonthService.saveBatch(mercFeeCountMonths);
+        }
+
+        return ReturnT.SUCCESS;
+    }
+}

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

@@ -0,0 +1,16 @@
+package com.xy.mapper;
+
+import com.xy.entity.MercFeeConfigAlgorithmType;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 商户算法扣费标准配置扩展 Mapper 接口
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+public interface MercFeeConfigAlgorithmTypeMapper extends BaseMapper<MercFeeConfigAlgorithmType> {
+
+}

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

@@ -0,0 +1,16 @@
+package com.xy.mapper;
+
+import com.xy.entity.MercFeeConfigSimCard;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 商户流量卡费配置扩展 Mapper 接口
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+public interface MercFeeConfigSimCardMapper extends BaseMapper<MercFeeConfigSimCard> {
+
+}

+ 27 - 0
device-api-service/src/main/java/com/xy/mapper/MercFeeCountDayMapper.java

@@ -0,0 +1,27 @@
+package com.xy.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.xy.dto.MercFeeCountDayDto;
+import com.xy.entity.MercFeeCountDay;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 商户佣金费用收益每日统计(不含今天) Mapper 接口
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+public interface MercFeeCountDayMapper extends BaseMapper<MercFeeCountDay> {
+
+    /**
+     * 查询指定月份费用总和
+     *
+     * @param countByMonth
+     * @return
+     */
+    List<MercFeeCountDayDto.CountByMonthVO> countByMonth(@Param("query") MercFeeCountDayDto.CountByMonth countByMonth);
+}

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

@@ -0,0 +1,16 @@
+package com.xy.mapper;
+
+import com.xy.entity.MercFeeCountMonth;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 商户佣金费用收益每月统计(不含本月) Mapper 接口
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+public interface MercFeeCountMonthMapper extends BaseMapper<MercFeeCountMonth> {
+
+}

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

@@ -0,0 +1,16 @@
+package com.xy.mapper;
+
+import com.xy.entity.MercFeeSettle;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 商户佣金费用结算 Mapper 接口
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+public interface MercFeeSettleMapper extends BaseMapper<MercFeeSettle> {
+
+}

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

@@ -0,0 +1,16 @@
+package com.xy.mapper;
+
+import com.xy.entity.MercFeeStatistic;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 商户佣金费用统计 Mapper 接口
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-24
+ */
+public interface MercFeeStatisticMapper extends BaseMapper<MercFeeStatistic> {
+
+}

+ 19 - 0
device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeConfigAlgorithmTypeMapper.xml

@@ -0,0 +1,19 @@
+<?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.MercFeeConfigAlgorithmTypeMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.xy.entity.MercFeeConfigAlgorithmType">
+        <id column="id" property="id" />
+        <result column="merc_code" property="mercCode" />
+        <result column="merc_id" property="mercId" />
+        <result column="create_time" property="createTime" />
+        <result column="create_user" property="createUser" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="algorithm_id" property="algorithmId" />
+        <result column="extra_month_money" property="extraMonthMoney" />
+        <result column="extra_single_money" property="extraSingleMoney" />
+    </resultMap>
+
+</mapper>

+ 17 - 0
device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeConfigSimCardMapper.xml

@@ -0,0 +1,17 @@
+<?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.MercFeeConfigSimCardMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.xy.entity.MercFeeConfigSimCard">
+        <id column="id" property="id" />
+        <result column="merc_code" property="mercCode" />
+        <result column="merc_id" property="mercId" />
+        <result column="create_time" property="createTime" />
+        <result column="create_user" property="createUser" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="extra_money" property="extraMoney" />
+    </resultMap>
+
+</mapper>

+ 33 - 0
device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeCountDayMapper.xml

@@ -0,0 +1,33 @@
+<?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.MercFeeCountDayMapper">
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.xy.entity.MercFeeCountDay">
+        <id column="id" property="id"/>
+        <result column="merc_id" property="mercId"/>
+        <result column="device_id" property="deviceId"/>
+        <result column="date_value" property="dateValue"/>
+        <result column="pay_money" property="payMoney"/>
+        <result column="brokerage" property="brokerage"/>
+        <result column="fee_type" property="feeType"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+    </resultMap>
+
+    <select id="countByMonth" resultType="com.xy.dto.MercFeeCountDayDto$CountByMonthVO">
+        SELECT parent_merc_id,
+               merc_id,
+               fee_type,
+               SUM(pay_money) AS pay_money,
+               SUM(brokerage) AS brokerage
+        FROM merc_fee_count_day
+        WHERE month_value = #{query.monthValue}
+        GROUP BY parent_merc_id,
+                 merc_id,
+                 fee_type
+    </select>
+</mapper>
+
+
+
+

+ 20 - 0
device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeCountMonthMapper.xml

@@ -0,0 +1,20 @@
+<?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.MercFeeCountMonthMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.xy.entity.MercFeeCountMonth">
+        <id column="id" property="id" />
+        <result column="merc_id" property="mercId" />
+        <result column="device_id" property="deviceId" />
+        <result column="date_value" property="dateValue" />
+        <result column="pay_money" property="payMoney" />
+        <result column="brokerage" property="brokerage" />
+        <result column="fee_type" property="feeType" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="verify" property="verify" />
+        <result column="verify_time" property="verifyTime" />
+    </resultMap>
+
+</mapper>

+ 19 - 0
device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeSettleMapper.xml

@@ -0,0 +1,19 @@
+<?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.MercFeeSettleMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.xy.entity.MercFeeSettle">
+        <id column="id" property="id" />
+        <result column="merc_id" property="mercId" />
+        <result column="settle_money" property="settleMoney" />
+        <result column="create_time" property="createTime" />
+        <result column="create_user" property="createUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="settle_state" property="settleState" />
+        <result column="finish_settle_time" property="finishSettleTime" />
+        <result column="title_img" property="titleImg" />
+        <result column="update_user" property="updateUser" />
+    </resultMap>
+
+</mapper>

+ 15 - 0
device-api-service/src/main/java/com/xy/mapper/mapper/MercFeeStatisticMapper.xml

@@ -0,0 +1,15 @@
+<?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.MercFeeStatisticMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.xy.entity.MercFeeStatistic">
+        <id column="merc_id" property="mercId" />
+        <result column="settle_money" property="settleMoney" />
+        <result column="un_settle_money" property="unSettleMoney" />
+        <result column="verify_money" property="verifyMoney" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+    </resultMap>
+
+</mapper>

+ 113 - 1
device-api-service/src/main/java/com/xy/service/DeviceAlgorithmChargingHistoryServiceImpl.java

@@ -1,13 +1,19 @@
 package com.xy.service;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.xy.collections.list.JArrayList;
 import com.xy.dto.DeviceAlgorithmChargingHistoryDto;
+import com.xy.dto.DeviceInfoDto;
+import com.xy.dto.MercFeeConfigDto;
 import com.xy.dto.OrderMercManageDto;
+import com.xy.dto.be.MercDto;
 import com.xy.entity.DeviceAlgorithmChargingHistory;
 import com.xy.mapper.DeviceAlgorithmChargingHistoryMapper;
+import com.xy.service.be.MercService;
 import com.xy.utils.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -15,9 +21,13 @@ import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.web.bind.annotation.RequestBody;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import static com.xy.utils.Beans.copy;
+import static com.xy.utils.PlusBeans.toIPage;
 import static com.xy.utils.PlusBeans.toPageBean;
 
 /**
@@ -34,6 +44,11 @@ import static com.xy.utils.PlusBeans.toPageBean;
 public class DeviceAlgorithmChargingHistoryServiceImpl extends ServiceImpl<DeviceAlgorithmChargingHistoryMapper, DeviceAlgorithmChargingHistory> implements DeviceAlgorithmChargingHistoryService {
 
     private OrderMercManageService orderMercManageService;
+    private MercService mercService;
+    private DeviceTypeAlgorithmBeforConfigServiceImpl deviceTypeAlgorithmBeforConfigService;
+    private DeviceInfoService deviceInfoService;
+    private MercFeeConfigService mercFeeConfigService;
+
 
     @Override
     @ApiOperation("分页查询")
@@ -50,4 +65,101 @@ public class DeviceAlgorithmChargingHistoryServiceImpl extends ServiceImpl<Devic
         }
         return R.ok(pageBean);
     }
-}
+
+    public R<PageBean<DeviceAlgorithmChargingHistoryDto.PageByTopMercVO>> pageByTopMerc(DeviceAlgorithmChargingHistoryDto.PageByTopMerc page) {
+        Long curMercId = page.getCurMercId();
+        Long chooseMercId = page.getChooseMercId();
+        List<Long> mercIds = new ArrayList<>();
+        if (chooseMercId == null) {
+            mercIds = R.feignCheckData(mercService.getChildMercIds(new MercDto.QuerySubDTO().setParentMercID(curMercId)));
+        } else {
+            // 指定商户ID
+            mercIds.add(chooseMercId);
+        }
+        if (CollUtil.isEmpty(mercIds)) {
+            return R.ok();
+        }
+        PageBean pageBean = page.getPage();
+        LambdaQueryWrapper<DeviceAlgorithmChargingHistory> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, DeviceAlgorithmChargingHistory.class)
+                .ge(DeviceAlgorithmChargingHistory::getCreateTime, page.getBeginCreateTime())
+                .le(DeviceAlgorithmChargingHistory::getCreateTime, page.getEndCreateTime())
+                .in(DeviceAlgorithmChargingHistory::getMercId, mercIds)
+                .build()
+                .orderByDesc(!Emptys.check(pageBean.getOrders()), DeviceAlgorithmChargingHistory::getCreateTime);
+        IPage<DeviceAlgorithmChargingHistory> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
+        PageBean<DeviceAlgorithmChargingHistoryDto.PageByTopMercVO> voPageBean = toPageBean(DeviceAlgorithmChargingHistoryDto.PageByTopMercVO.class, iPage);
+        List<DeviceAlgorithmChargingHistoryDto.PageByTopMercVO> records = voPageBean.getRecords();
+        if (Emptys.check(records)) {
+            // 佣金配置查询
+            List<MercFeeConfigDto.ListFeeConfigByMercVO> feeConfigByMercVOS = R.feignCheckData(mercFeeConfigService.listFeeConfigByMerc(new MercFeeConfigDto.ListFeeConfigByMercDTO().setMercId(curMercId)));
+            Map<Long, MercFeeConfigDto.ListFeeConfigByMercVO> configByMercVOMap = MapUtil.newHashMap();
+            if (CollUtil.isNotEmpty(feeConfigByMercVOS)) {
+                configByMercVOMap = feeConfigByMercVOS.stream().collect(Collectors.toMap(MercFeeConfigDto.ListFeeConfigByMercVO::getMercId, f -> f));
+            }
+
+
+            List<Long> deviceIds = records.stream().map(DeviceAlgorithmChargingHistoryDto.PageByTopMercVO::getDeviceId).distinct().collect(Collectors.toList());
+
+            List<DeviceInfoDto.Vo> deviceList = R.feignCheckData(deviceInfoService.listCommon(new DeviceInfoDto.ListCommon().setDeviceIds(deviceIds)));
+            Map<Long, DeviceInfoDto.Vo> devcieMap = deviceList.stream().collect(Collectors.toMap(DeviceInfoDto.Vo::getDeviceId, d -> d));
+            copy(records)
+                    .target(() -> orderMercManageService.list(new OrderMercManageDto.SelectList().setId(new JArrayList<>(records).getProperty(DeviceAlgorithmChargingHistoryDto.PageByTopMercVO::getOrderId))).getData()
+                            , DeviceAlgorithmChargingHistoryDto.PageByTopMercVO::getOrderId, DeviceAlgorithmChargingHistoryDto.PageByTopMercVO::getFiles, OrderMercManageDto.Vo::getId, OrderMercManageDto.Vo::getFiles
+                    ).target(() -> mercService.list(new MercDto.SelectList().setMercIds(new JArrayList<>(records).getProperty(DeviceAlgorithmChargingHistoryDto.PageByTopMercVO::getMercId).comparing())).getData()
+                            , DeviceAlgorithmChargingHistoryDto.PageByTopMercVO::getMercId, DeviceAlgorithmChargingHistoryDto.PageByTopMercVO::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
+                    .builder();
+            for (DeviceAlgorithmChargingHistoryDto.PageByTopMercVO record : records) {
+                // 初始0 佣金费用
+                int extraMoney = 0;
+                Long mercId = record.getMercId();
+                MercFeeConfigDto.ListFeeConfigByMercVO listFeeConfigByMercVO = configByMercVOMap.get(mercId);
+                if (listFeeConfigByMercVO != null) {
+                    extraMoney = listFeeConfigByMercVO.getFeeConfig().getFeeActive();
+                }
+                record.setAgentMoney(extraMoney);
+            }
+        }
+        return R.ok(voPageBean);
+
+    }
+
+    /**
+     * 财务管理-支出管理-设备激活费明细
+     *
+     * @param page
+     * @return
+     */
+    public R<PageBean<DeviceAlgorithmChargingHistoryDto.MySpendPageVO>> mySpendPage(DeviceAlgorithmChargingHistoryDto.PageByTopMerc page) {
+        Long curMercId = page.getCurMercId();
+        List<Long> mercIds = new ArrayList<>();
+        // 指定商户ID
+        mercIds.add(curMercId);
+        PageBean pageBean = page.getPage();
+        LambdaQueryWrapper<DeviceAlgorithmChargingHistory> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, DeviceAlgorithmChargingHistory.class)
+                .ge(DeviceAlgorithmChargingHistory::getCreateTime, page.getBeginCreateTime())
+                .le(DeviceAlgorithmChargingHistory::getCreateTime, page.getEndCreateTime())
+                .in(DeviceAlgorithmChargingHistory::getMercId, mercIds)
+                .build()
+                .orderByDesc(!Emptys.check(pageBean.getOrders()), DeviceAlgorithmChargingHistory::getCreateTime);
+        IPage<DeviceAlgorithmChargingHistory> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
+        PageBean<DeviceAlgorithmChargingHistoryDto.MySpendPageVO> voPageBean = toPageBean(DeviceAlgorithmChargingHistoryDto.MySpendPageVO.class, iPage);
+        List<DeviceAlgorithmChargingHistoryDto.MySpendPageVO> records = voPageBean.getRecords();
+        if (Emptys.check(records)) {
+
+
+            List<Long> deviceIds = records.stream().map(DeviceAlgorithmChargingHistoryDto.MySpendPageVO::getDeviceId).distinct().collect(Collectors.toList());
+
+            List<DeviceInfoDto.Vo> deviceList = R.feignCheckData(deviceInfoService.listCommon(new DeviceInfoDto.ListCommon().setDeviceIds(deviceIds)));
+            Map<Long, DeviceInfoDto.Vo> devcieMap = deviceList.stream().collect(Collectors.toMap(DeviceInfoDto.Vo::getDeviceId, d -> d));
+            copy(records)
+                    .target(() -> orderMercManageService.list(new OrderMercManageDto.SelectList().setId(new JArrayList<>(records).getProperty(DeviceAlgorithmChargingHistoryDto.MySpendPageVO::getOrderId))).getData()
+                            , DeviceAlgorithmChargingHistoryDto.MySpendPageVO::getOrderId, DeviceAlgorithmChargingHistoryDto.MySpendPageVO::getFiles, OrderMercManageDto.Vo::getId, OrderMercManageDto.Vo::getFiles
+                    ).target(() -> mercService.list(new MercDto.SelectList().setMercIds(new JArrayList<>(records).getProperty(DeviceAlgorithmChargingHistoryDto.MySpendPageVO::getMercId).comparing())).getData()
+                            , DeviceAlgorithmChargingHistoryDto.MySpendPageVO::getMercId, DeviceAlgorithmChargingHistoryDto.MySpendPageVO::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
+                    .builder();
+
+        }
+        return R.ok(voPageBean);
+
+    }
+}

+ 134 - 1
device-api-service/src/main/java/com/xy/service/DeviceChargingConfigServiceImpl.java

@@ -1,20 +1,28 @@
 package com.xy.service;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.github.yitter.idgen.YitIdHelper;
+import com.xy.device.EnumDeviceCharging;
+import com.xy.device.EnumDeviceChargingConfigType;
 import com.xy.dto.DeviceChargingConfigDto;
 import com.xy.dto.be.MercDto;
 import com.xy.entity.DeviceChargingConfig;
+import com.xy.error.CommRuntimeException;
 import com.xy.mapper.DeviceChargingConfigMapper;
 import com.xy.service.be.MercService;
 import com.xy.utils.Beans;
 import com.xy.utils.MybatisPlusQuery;
 import com.xy.utils.R;
+import com.xy.utils.SysDictUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 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;
@@ -22,6 +30,9 @@ import org.springframework.web.bind.annotation.RequestBody;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
+
+import static com.xy.utils.Beans.copy;
 
 
 /**
@@ -46,12 +57,134 @@ public class DeviceChargingConfigServiceImpl extends ServiceImpl<DeviceChargingC
     public R<List<DeviceChargingConfigDto.Vo>> list(@RequestBody @Validated DeviceChargingConfigDto.SelectList selectList) {
         MercDto.Vo merc = mercService.obj(new MercDto.Vo().setId(selectList.getMercId())).getData();
         LambdaQueryWrapper<DeviceChargingConfig> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, DeviceChargingConfig.class)
+                .in(DeviceChargingConfig::getDeviceType, selectList.getDeviceTypes())
                 .eq(DeviceChargingConfig::getMercCode, merc.getMercCode())
                 .build();
         List<DeviceChargingConfig> list = list(lambdaQueryWrapper);
         return R.ok(Beans.copy(DeviceChargingConfigDto.Vo.class, list));
     }
 
+
+    @PostMapping("listByFeeConfig")
+    @ApiOperation("设备管理费用配置查询")
+    public R<DeviceChargingConfigDto.DeviceManagerFeeConfigVO> listByFeeConfig(@RequestBody @Validated DeviceChargingConfigDto.ListByFeeConfigDTO dto) {
+        DeviceChargingConfigDto.DeviceManagerFeeConfigVO data = new DeviceChargingConfigDto.DeviceManagerFeeConfigVO();
+        List<Integer> deviceTypes = dto.getDeviceTypes();
+        // 设备管理费-平台默认配置
+        List<DeviceChargingConfigDto.DeviceManagerFeePlatformVO> dmFeePlatforms = new ArrayList<>();
+        for (Integer type : deviceTypes) {// 默认年费,赠送天数
+            DeviceChargingConfigDto.DeviceManagerFeePlatformVO vo = new DeviceChargingConfigDto.DeviceManagerFeePlatformVO();
+            int defaultMoney = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), String.valueOf(type), Integer.class);
+            // 默认赠送天数
+            int giveDays = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), EnumDeviceCharging.N_X.getCode(), Integer.class);
+            vo.setDefFee(defaultMoney);
+            vo.setDefGiveDay(giveDays);
+            vo.setDeviceType(type);
+            dmFeePlatforms.add(vo);
+        }
+        MercDto.Vo merc = mercService.obj(new MercDto.Vo().setId(dto.getMercId())).getData();
+
+        // 设备管理费-商家自定义费用
+        List<DeviceChargingConfigDto.DeviceManagerFeeMercVO> dmFeeMercs = new ArrayList<>();
+        LambdaQueryWrapper<DeviceChargingConfig> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(dto, DeviceChargingConfig.class)
+                .in(DeviceChargingConfig::getDeviceType, deviceTypes)
+                .eq(DeviceChargingConfig::getMercCode, merc.getMercCode())
+                .build();
+        // 默认配置 type 2预充 1赠送天数
+        List<DeviceChargingConfig> list = list(lambdaQueryWrapper);
+        if (CollUtil.isNotEmpty(list)) {
+            for (DeviceChargingConfig dcc : list) {
+                Integer type = dcc.getType();
+                Integer deviceType = dcc.getDeviceType();
+                // 预充
+                if (String.valueOf(type).equals(EnumDeviceChargingConfigType.N_2.getCode())) {
+                    int defaultMoney = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), String.valueOf(deviceType), Integer.class);
+                    // 默认赠送天数
+                    int giveDays = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), EnumDeviceCharging.N_X.getCode(), Integer.class);
+                    DeviceChargingConfigDto.DeviceManagerFeeMercVO vo = new DeviceChargingConfigDto.DeviceManagerFeeMercVO();
+                    BeanUtil.copyProperties(dcc, vo);
+                    vo.setDefFee(defaultMoney);
+                    vo.setDefGiveDay(giveDays);
+                    vo.setFee(dcc.getConfigValue());
+                    Optional<DeviceChargingConfig> dcObj = list.stream()
+                            .filter(dc -> String.valueOf(dc.getType()).equals(EnumDeviceChargingConfigType.N_1.getCode()))
+                            .filter(dc -> dc.getDeviceType().intValue() == deviceType.intValue())
+                            .findFirst();
+                    vo.setGiveDay(dcObj.get().getConfigValue());
+                    dmFeeMercs.add(vo);
+                }
+            }
+        }
+
+        data.setDmFeeMercs(dmFeeMercs);
+        data.setDmFeePlatforms(dmFeePlatforms);
+        return R.ok(data);
+    }
+
+    @PostMapping("save")
+    @ApiOperation("添加")
+    public R save(@RequestBody @Validated DeviceChargingConfigDto.Save save) {
+        LocalDateTime now = LocalDateTime.now();
+
+        Integer deviceType = save.getDeviceType();
+        Long mercId = save.getMercId();
+        MercDto.Vo merc = R.feignCheckData(mercService.obj(new MercDto.Vo().setId(mercId)));
+        String mercCode = merc.getMercCode();
+        DeviceChargingConfig dc = this.getOne(Wrappers.<DeviceChargingConfig>lambdaQuery()
+                .eq(DeviceChargingConfig::getMercCode, mercCode)
+                .eq(DeviceChargingConfig::getDeviceType, deviceType)
+                .eq(DeviceChargingConfig::getType, EnumDeviceChargingConfigType.N_2.getCode())
+        );
+
+        if (dc != null) {
+            throw new CommRuntimeException("该类型配置已存在,请勿重复添加!");
+        }
+
+        // 默认赠送天数
+        int giveDays = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), EnumDeviceCharging.N_X.getCode(), Integer.class);
+        // 新增赠送天数
+        DeviceChargingConfig newDc = new DeviceChargingConfig().setDeviceType(deviceType).setConfigValue(giveDays).setMercCode(mercCode)
+                .setType(Integer.valueOf(EnumDeviceChargingConfigType.N_1.getCode())).setCreateTime(now)
+                .setUpdateTime(now).setMercCode(mercCode);
+        save(newDc);
+
+
+        DeviceChargingConfig saveInfo = copy(DeviceChargingConfig.class, save)
+                .setCreateTime(now)
+                .setUpdateTime(now).setMercCode(mercCode);
+        save(saveInfo);
+        return R.ok();
+    }
+
+    @PostMapping("update")
+    @ApiOperation("修改")
+    public R update(@RequestBody @Validated DeviceChargingConfigDto.Update update) {
+//        DeviceChargingConfig dcc = getById(update.getId());
+        DeviceChargingConfig updateInfo = copy(DeviceChargingConfig.class, update)
+                .setUpdateTime(LocalDateTime.now());
+        updateById(updateInfo);
+        return R.ok();
+    }
+
+    @PostMapping("delete")
+    @ApiOperation("删除")
+    @Transactional(rollbackFor = Exception.class)
+    public R delete(@RequestBody @Validated DeviceChargingConfigDto.Delete delete) {
+        Long id = delete.getId();
+        DeviceChargingConfig dcc = getById(delete.getId());
+        DeviceChargingConfig one = getOne(Wrappers.<DeviceChargingConfig>lambdaQuery()
+                .eq(DeviceChargingConfig::getMercCode, dcc.getMercCode())
+                .eq(DeviceChargingConfig::getDeviceType, dcc.getDeviceType())
+                .eq(DeviceChargingConfig::getType, Integer.valueOf(EnumDeviceChargingConfigType.N_1.getCode()))
+        );
+        if (one != null) {
+            removeById(one.getId());
+        }
+        removeById(delete.getId());
+        return R.ok();
+    }
+
+
     @PostMapping("saveOrUpdate")
     @ApiOperation("添加或修改")
     public R saveOrUpdate(@RequestBody @Validated DeviceChargingConfigDto.SaveOrUpdate saveOrUpdate) {
@@ -105,4 +238,4 @@ public class DeviceChargingConfigServiceImpl extends ServiceImpl<DeviceChargingC
         List<DeviceChargingConfig> list = list(lambdaQueryWrapper);
         return R.ok(Beans.copy(DeviceChargingConfigDto.Vo.class, list));
     }
-}
+}

+ 171 - 11
device-api-service/src/main/java/com/xy/service/DeviceChargingHistoryServiceImpl.java

@@ -1,5 +1,7 @@
 package com.xy.service;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
 import com.alibaba.excel.annotation.ExcelProperty;
 import com.alibaba.excel.annotation.write.style.ColumnWidth;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -11,9 +13,12 @@ import com.xy.collections.list.JArrayList;
 import com.xy.collections.list.JList;
 import com.xy.config.DeviceThreadPoolConfig;
 import com.xy.config.FileConfig;
+import com.xy.device.EnumDeviceCharging;
 import com.xy.dto.DeviceChargingHistoryDto;
+import com.xy.dto.MercFeeConfigDto;
 import com.xy.dto.OrderMercManageDto;
 import com.xy.dto.be.MercDto;
+import com.xy.entity.DeviceCharging;
 import com.xy.entity.DeviceChargingHistory;
 import com.xy.mapper.DeviceChargingHistoryMapper;
 import com.xy.service.be.MercService;
@@ -25,6 +30,7 @@ import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.SneakyThrows;
 import lombok.experimental.Accessors;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -33,11 +39,14 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.File;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.time.LocalDateTime;
 import java.time.YearMonth;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import static com.xy.utils.Beans.copy;
 import static com.xy.utils.PlusBeans.toIPage;
@@ -52,7 +61,7 @@ import static com.xy.utils.PlusBeans.toPageBean;
  * @since 2023-04-14
  */
 @Service
-@AllArgsConstructor
+@AllArgsConstructor(onConstructor_ = @Lazy)
 @Api(tags = "设备计费历史表")
 public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceChargingHistoryMapper, DeviceChargingHistory> implements DeviceChargingHistoryService {
 
@@ -64,6 +73,15 @@ public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceCharging
 
     private FileConfig fileConfig;
 
+    private DeviceChargingConfigServiceImpl deviceChargingConfigService;
+
+    private DeviceInfoService deviceInfoService;
+
+    private MercFeeConfigService mercFeeConfigService;
+
+    private DeviceChargingServiceImpl deviceChargingService;
+
+
     @Override
     @ApiOperation("分页查询")
     public R<PageBean<DeviceChargingHistoryDto.Vo>> page(DeviceChargingHistoryDto.Page page) {
@@ -87,11 +105,153 @@ public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceCharging
         return R.ok(pageBean);
     }
 
+
+    public R<PageBean<DeviceChargingHistoryDto.PageVo>> pageByTopMerc(DeviceChargingHistoryDto.PageByTopMerc page) {
+        Long curMercId = page.getCurMercId();
+        Long chooseMercId = page.getChooseMercId();
+        List<Long> mercIds = new ArrayList<>();
+        if (chooseMercId == null) {
+            mercIds = R.feignCheckData(mercService.getChildMercIds(new MercDto.QuerySubDTO().setParentMercID(curMercId)));
+        } else {
+            // 指定商户ID
+            mercIds.add(chooseMercId);
+        }
+        if (CollUtil.isEmpty(mercIds)) {
+            return R.ok();
+        }
+
+        LambdaQueryWrapper<DeviceChargingHistory> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, DeviceChargingHistory.class)
+                .ge(DeviceChargingHistory::getCreateTime, page.getBeginCreateTime())
+                .le(DeviceChargingHistory::getCreateTime, page.getEndCreateTime())
+                .in(DeviceChargingHistory::getMercId, mercIds)
+                .build()
+                .orderByDesc(DeviceChargingHistory::getCreateTime);
+        IPage<DeviceChargingHistory> iPage = page(PlusBeans.toIPage(page.getPage()), lambdaQueryWrapper);
+        PageBean<DeviceChargingHistoryDto.PageVo> pageBean = toPageBean(DeviceChargingHistoryDto.PageVo.class, iPage);
+        List<DeviceChargingHistoryDto.PageVo> records = pageBean.getRecords();
+        if (Emptys.check(records)) {
+            // 佣金配置查询
+            List<MercFeeConfigDto.ListFeeConfigByMercVO> feeConfigByMercVOS = R.feignCheckData(mercFeeConfigService.listFeeConfigByMerc(new MercFeeConfigDto.ListFeeConfigByMercDTO().setMercId(curMercId)));
+            Map<Long, MercFeeConfigDto.ListFeeConfigByMercVO> configByMercVOMap = MapUtil.newHashMap();
+            if (CollUtil.isNotEmpty(feeConfigByMercVOS)) {
+                configByMercVOMap = feeConfigByMercVOS.stream().collect(Collectors.toMap(MercFeeConfigDto.ListFeeConfigByMercVO::getMercId, f -> f));
+            }
+
+            copy(records)
+                    .target(() -> orderMercManageService.list(new OrderMercManageDto.SelectList().setId(new JArrayList<>(records).getProperty(DeviceChargingHistoryDto.PageVo::getOrderId))).getData()
+                            , DeviceChargingHistoryDto.PageVo::getOrderId, DeviceChargingHistoryDto.PageVo::getFiles, OrderMercManageDto.Vo::getId, OrderMercManageDto.Vo::getFiles
+                    )
+                    .target(() -> mercService.list(new MercDto.SelectList().setMercIds(new JArrayList<>(records).getProperty(DeviceChargingHistoryDto.PageVo::getMercId).comparing())).getData(),
+                            DeviceChargingHistoryDto.PageVo::getMercId, DeviceChargingHistoryDto.PageVo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
+                    .builder();
+            List<Long> deviceIds = records.stream().map(DeviceChargingHistoryDto.PageVo::getDeviceId).distinct().collect(Collectors.toList());
+
+//            List<DeviceInfoDto.Vo> deviceList = R.feignCheckData(deviceInfoService.listCommon(new DeviceInfoDto.ListCommon().setDeviceIds(deviceIds)));
+//            Map<Long, DeviceInfoDto.Vo> devcieMap = deviceList.stream().collect(Collectors.toMap(DeviceInfoDto.Vo::getDeviceId, d -> d));
+
+            List<DeviceCharging> deviceChargings = deviceChargingService.listByIds(deviceIds);
+            Map<Long, DeviceCharging> deviceChargingMap = MapUtil.newHashMap();
+            if (CollUtil.isNotEmpty(deviceChargings)) {
+                deviceChargingMap = deviceChargings.stream().collect(Collectors.toMap(DeviceCharging::getDeviceId, d -> d));
+            }
+            for (DeviceChargingHistoryDto.PageVo record : records) {
+                Long mercId = record.getMercId();
+                Long deviceId = record.getDeviceId();
+                // 初始0 设备管理费佣金
+                record.setAgentMoney(0);
+                if (!configByMercVOMap.isEmpty() && configByMercVOMap.get(mercId) != null) {
+                    MercFeeConfigDto.ListFeeConfigByMercVO listFeeConfigByMercVO = configByMercVOMap.get(mercId);
+                    Integer extraMoney = listFeeConfigByMercVO.getFeeConfig().getFeeDevice();
+                    // 设备管理费佣金
+                    record.setAgentMoney(extraMoney);
+                }
+                // 封装过期状态说明
+                String timeoutStatus;
+                DeviceCharging dc = deviceChargingMap.get(deviceId);
+                if (dc != null) {
+                    Integer value = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), EnumDeviceCharging.N_200.getCode(), Integer.class);
+
+                    LocalDateTime timeout = dc.getTimeout();
+                    long s = DataTime.diff(LocalDateTime.now(), timeout, "s");
+                    if (s <= 0) {
+                        timeoutStatus = "欠费(" + (~(s / 86400 - 1)) + "天)";
+                    } else {
+                        timeoutStatus = s <= value * 86400 ? "即将到期(" + s / 86400 + "天)" : "正常(" + s / 86400 + "天)";
+                    }
+                    // 过期状态说明
+                    record.setTimeoutStatus(timeoutStatus);
+                    // 过期时间
+                    record.setTimeout(timeout);
+                }
+            }
+            pageBean.setRecords(records);
+
+        }
+        return R.ok(pageBean);
+    }
+
+    public R<PageBean<DeviceChargingHistoryDto.MySpendPageVO>> mySpendPage(DeviceChargingHistoryDto.PageByTopMerc page) {
+        Long curMercId = page.getCurMercId();
+        List<Long> mercIds = new ArrayList<>();
+        // 指定商户ID
+        mercIds.add(curMercId);
+        LambdaQueryWrapper<DeviceChargingHistory> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, DeviceChargingHistory.class)
+                .ge(DeviceChargingHistory::getCreateTime, page.getBeginCreateTime())
+                .le(DeviceChargingHistory::getCreateTime, page.getEndCreateTime())
+                .in(DeviceChargingHistory::getMercId, mercIds)
+                .build()
+                .orderByDesc(DeviceChargingHistory::getCreateTime);
+        IPage<DeviceChargingHistory> iPage = page(PlusBeans.toIPage(page.getPage()), lambdaQueryWrapper);
+        PageBean<DeviceChargingHistoryDto.MySpendPageVO> pageBean = toPageBean(DeviceChargingHistoryDto.MySpendPageVO.class, iPage);
+        List<DeviceChargingHistoryDto.MySpendPageVO> records = pageBean.getRecords();
+        if (Emptys.check(records)) {
+            copy(records)
+                    .target(() -> orderMercManageService.list(new OrderMercManageDto.SelectList().setId(new JArrayList<>(records).getProperty(DeviceChargingHistoryDto.MySpendPageVO::getOrderId))).getData()
+                            , DeviceChargingHistoryDto.MySpendPageVO::getOrderId, DeviceChargingHistoryDto.MySpendPageVO::getFiles, OrderMercManageDto.Vo::getId, OrderMercManageDto.Vo::getFiles
+                    )
+                    .target(() -> mercService.list(new MercDto.SelectList().setMercIds(new JArrayList<>(records).getProperty(DeviceChargingHistoryDto.MySpendPageVO::getMercId).comparing())).getData(),
+                            DeviceChargingHistoryDto.MySpendPageVO::getMercId, DeviceChargingHistoryDto.MySpendPageVO::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
+                    .builder();
+            List<Long> deviceIds = records.stream().map(DeviceChargingHistoryDto.MySpendPageVO::getDeviceId).distinct().collect(Collectors.toList());
+
+            List<DeviceCharging> deviceChargings = deviceChargingService.listByIds(deviceIds);
+            Map<Long, DeviceCharging> deviceChargingMap = MapUtil.newHashMap();
+            if (CollUtil.isNotEmpty(deviceChargings)) {
+                deviceChargingMap = deviceChargings.stream().collect(Collectors.toMap(DeviceCharging::getDeviceId, d -> d));
+            }
+            for (DeviceChargingHistoryDto.MySpendPageVO record : records) {
+                Long deviceId = record.getDeviceId();
+                // 封装过期状态说明
+                String timeoutStatus;
+                DeviceCharging dc = deviceChargingMap.get(deviceId);
+                if (dc != null) {
+                    Integer value = SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), EnumDeviceCharging.N_200.getCode(), Integer.class);
+
+                    LocalDateTime timeout = dc.getTimeout();
+                    long s = DataTime.diff(LocalDateTime.now(), timeout, "s");
+                    if (s <= 0) {
+                        timeoutStatus = "欠费(" + (~(s / 86400 - 1)) + "天)";
+                    } else {
+                        timeoutStatus = s <= value * 86400 ? "即将到期(" + s / 86400 + "天)" : "正常(" + s / 86400 + "天)";
+                    }
+                    // 过期状态说明
+                    record.setTimeoutStatus(timeoutStatus);
+                    // 过期时间
+                    record.setTimeout(timeout);
+                }
+            }
+            pageBean.setRecords(records);
+
+        }
+        return R.ok(pageBean);
+    }
+
+
     @ApiOperation("月统计分页")
     @PostMapping("moonCountPage")
     public R<PageBean<DeviceChargingHistoryDto.MoonCountVo>> moonCountPage(@RequestBody DeviceChargingHistoryDto.MoonCountPage moonCountPage) {
         JList<DeviceChargingHistoryDto.MoonCountVo> moonCountVos = new JArrayList<>();
-        //查询数据
+        // 查询数据
         List<String> attrNames = Arrays.asList(
                 LambdaUtils.getUnderlineCaseName(DeviceChargingHistory::getMercId)
         );
@@ -119,9 +279,9 @@ public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceCharging
                     .setChargingMoney(deviceChargingHistory.getChargingMoney());
             moonCountVos.add(moonCountVo);
         });
-        //翻译商户名称
+        // 翻译商户名称
         Beans.copy(moonCountVos).target(() -> mercService.list(new MercDto.SelectList().setMercIds(moonCountVos.getProperty(DeviceChargingHistoryDto.MoonCountVo::getMercId).comparing())).getData(),
-                DeviceChargingHistoryDto.MoonCountVo::getMercId, DeviceChargingHistoryDto.MoonCountVo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
+                        DeviceChargingHistoryDto.MoonCountVo::getMercId, DeviceChargingHistoryDto.MoonCountVo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
                 .builder();
         PageBean<DeviceChargingHistoryDto.MoonCountVo> pageBean = new PageBean<DeviceChargingHistoryDto.MoonCountVo>()
                 .setCurrent(iPage.getCurrent())
@@ -135,7 +295,7 @@ public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceCharging
     @PostMapping("moonCount")
     public R<List<DeviceChargingHistoryDto.MoonCountVo>> moonCount(@RequestBody DeviceChargingHistoryDto.MoonCount moonCount) {
         JList<DeviceChargingHistoryDto.MoonCountVo> moonCountVos = new JArrayList<>();
-        //查询数据
+        // 查询数据
         List<String> attrNames = Arrays.asList(
                 LambdaUtils.getUnderlineCaseName(DeviceChargingHistory::getMercId),
                 "DATE_FORMAT(" + LambdaUtils.getUnderlineCaseName(DeviceChargingHistory::getCreateTime) + ", '%Y-%m')"
@@ -165,9 +325,9 @@ public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceCharging
             });
         }));
         execute.end();
-        //翻译商户名称
+        // 翻译商户名称
         Beans.copy(moonCountVos).target(() -> mercService.list(new MercDto.SelectList().setMercIds(moonCountVos.getProperty(DeviceChargingHistoryDto.MoonCountVo::getMercId).comparing())).getData(),
-                DeviceChargingHistoryDto.MoonCountVo::getMercId, DeviceChargingHistoryDto.MoonCountVo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
+                        DeviceChargingHistoryDto.MoonCountVo::getMercId, DeviceChargingHistoryDto.MoonCountVo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
                 .builder();
         return R.ok(moonCountVos.desc(DeviceChargingHistoryDto.MoonCountVo::getDate));
     }
@@ -176,7 +336,7 @@ public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceCharging
     @ApiOperation("月统计导出")
     @PostMapping("moonCountDownload")
     public void moonCountDownload(@RequestBody DeviceChargingHistoryDto.MoonCount moonCount) {
-        //生成excel
+        // 生成excel
         String name = YitIdHelper.nextId() + ".xlsx";
         String path = fileConfig.getPath() + File.separator + name;
         ExcelUtils.SheetAndData<MoonCountData> sheetAndData = ExcelUtils.create(path, MoonCountData.class);
@@ -187,7 +347,7 @@ public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceCharging
             }
             return Beans.copy(MoonCountData.class, data);
         }).builder();
-        //下载文件
+        // 下载文件
         InputStream inputStream = IoUtils.inputStream(path).get();
         response.setHeader("Content-Disposition", "attachment; filename=" + "设备管理费月统计数据.xlsx");
         response.setContentType("application/xlsx");
@@ -199,7 +359,7 @@ public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceCharging
         }
         inputStream.close();
         outputStream.close();
-        //删除文件
+        // 删除文件
         new File(path).delete();
     }
 
@@ -243,4 +403,4 @@ public class DeviceChargingHistoryServiceImpl extends ServiceImpl<DeviceCharging
         @ExcelProperty(value = "续费金额")
         private Integer chargingMoney;
     }
-}
+}

+ 64 - 42
device-api-service/src/main/java/com/xy/service/DeviceChargingServiceImpl.java

@@ -13,8 +13,10 @@ import com.xy.collections.map.JMap;
 import com.xy.config.DeviceThreadPoolConfig;
 import com.xy.device.*;
 import com.xy.dto.*;
+import com.xy.dto.be.MercDto;
 import com.xy.entity.*;
 import com.xy.mapper.DeviceChargingMapper;
+import com.xy.service.be.MercService;
 import com.xy.utils.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -68,6 +70,10 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
 
     private AlipayDeviceService alipayDeviceService;
 
+    private MercFeeConfigService mercFeeConfigService;
+
+    private MercService mercService;
+
     @PostMapping("updateTimeout")
     @ApiOperation("修改过期时间")
     public R updateTimeout(@RequestBody @Validated DeviceChargingDto.UpdateTimeout updateTimeout) {
@@ -101,32 +107,36 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
         if (cover.size() > 1) {
             return R.fail("设备类型必须一致");
         }
-        //查询设备状态信息
+        // 佣金配置查询
+        MercFeeConfigDto.FeeConfigByMercVO mercFeeConfig = R.feignCheckData(mercFeeConfigService.getFeeConfigByMerc(new MercFeeConfigDto.FeeConfigByMerc().setMercCode(list.get(0).getMercCode())));
+
+        // 查询设备状态信息
         List<DeviceStatus> deviceStatuses = deviceStatusService.list(new LambdaQueryWrapper<DeviceStatus>().in(DeviceStatus::getDeviceId, deviceIds));
         JMap<Long, DeviceStatus> deviceStatusesJMaps = new JArrayList<>(deviceStatuses).toMap(DeviceStatus::getDeviceId).cover();
         List<String> mercCodes = new ArrayList<>();
         deviceAlgorithmChargingService.getMercCodes(list.get(0).getMercCode(), mercCodes);
-        //查询设备计费配置表
+        // 查询设备计费配置表  设备管理费
         List<DeviceChargingConfig> deviceChargingConfigs = deviceChargingConfigService.list(new LambdaQueryWrapper<DeviceChargingConfig>()
                 .in(DeviceChargingConfig::getMercCode, mercCodes)
                 .eq(DeviceChargingConfig::getType, SysDictUtils.getValue(EnumDeviceChargingConfigType.Code.CODE.getCode(), EnumDeviceChargingConfigType.N_2.getCode(), Integer.class))
                 .eq(DeviceChargingConfig::getDeviceType, list.get(0).getDeviceType())
                 .orderByDesc(DeviceChargingConfig::getMercCode)
         );
-        //有则使用,无则使用默认字典
-        int standard = Emptys.check(deviceChargingConfigs) ? deviceChargingConfigs.get(0).getConfigValue()
+        // 设备管理费
+        int standard = Emptys.check(deviceChargingConfigs) ? (deviceChargingConfigs.get(0).getConfigValue())
                 : SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), String.valueOf(list.get(0).getDeviceType()), Integer.class);
+        standard = mercFeeConfig.getFeeDevice() + standard;
         String deviceTypeName = SysDictUtils.get(EnumDeviceType.Code.CODE.getCode(), String.valueOf(list.get(0).getDeviceType())).getMsg();
-        //查询算法预充配置
+        // 查询算法预充配置  设备激活
         JList<DeviceInfo> values = cover.getValues();
         List<DeviceTypeAlgorithmBeforConfig> deviceTypeAlgorithmBeforConfigs = deviceTypeAlgorithmBeforConfigService.list(new LambdaQueryWrapper<DeviceTypeAlgorithmBeforConfig>()
                 .eq(DeviceTypeAlgorithmBeforConfig::getDeviceType, list.get(0).getDeviceType())
-                .eq(DeviceTypeAlgorithmBeforConfig::getMercId, list.get(0).getMercId())
+                .in(DeviceTypeAlgorithmBeforConfig::getMercCode, mercCodes)
                 .in(DeviceTypeAlgorithmBeforConfig::getAlgorithmId, values.getProperty(DeviceInfo::getAlgorithmId))
         );
         JMap<Long, DeviceTypeAlgorithmBeforConfig> deviceTypeAlgorithmBeforConfigsJMaps = Emptys.check(deviceTypeAlgorithmBeforConfigs) ? new JArrayList<>(deviceTypeAlgorithmBeforConfigs).toMap(DeviceTypeAlgorithmBeforConfig::getAlgorithmId).cover()
                 : new JHashMap<>();
-        //查询默认算法信息
+        // 查询默认算法信息
         JList<Long> algorithmIds = deviceInfos.getProperty(DeviceInfo::getAlgorithmId);
         Map<Long, String> moonAlgorithmTypesMap = new HashMap<>();
         Map<Long, String> algorithmPayConfigMap = new HashMap<>();
@@ -141,26 +151,31 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
             }
         }
         for (DeviceInfo deviceInfo : list) {
-            //封装设备信息
+            // 封装设备信息
             DeviceChargingDto.PayCheckVo payCheckVo = new DeviceChargingDto.PayCheckVo();
             DeviceStatus deviceStatus = deviceStatusesJMaps.get(deviceInfo.getDeviceId());
             DeviceChargingDto.PayCheckVo.DeviceInfo deviceInfoObj = Beans.copy(Beans.copy(DeviceChargingDto.PayCheckVo.DeviceInfo.class, deviceInfo), deviceStatus)
                     .setDeviceTypeName(deviceTypeName)
                     .setStandard(BigDecimal.valueOf(standard).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_DOWN).doubleValue() + "元/年")
                     .setMoney(standard);
-            //封装算法购买信息
+            // 封装算法购买信息
             DeviceTypeAlgorithmBeforConfig deviceTypeAlgorithmBeforConfig = deviceTypeAlgorithmBeforConfigsJMaps.get(deviceInfo.getAlgorithmId());
             String algorithmName = moonAlgorithmTypesMap.get(deviceInfo.getAlgorithmId());
             String algorithmPayConfig = algorithmPayConfigMap.get(deviceInfo.getAlgorithmId());
             DeviceAlgorithmChargingDto.AlgorithmMoonConfig algorithmMoonConfig = JSONUtil.parseObj(algorithmPayConfig).toBean(DeviceAlgorithmChargingDto.AlgorithmMoonConfig.class);
             DeviceAlgorithmChargingDto.AlgorithmMoonConfig.Inf inf = algorithmMoonConfig.getInf();
+
+            // 单笔算法费用 代理商额外收取
+            int extraSingleMoney = mercFeeConfig.getFeeAlgorithm();
             DeviceChargingDto.PayCheckVo.DeviceAlgorithmCharging infDeviceAlgorithmCharging = Beans.copy(DeviceChargingDto.PayCheckVo.DeviceAlgorithmCharging.class, deviceInfo)
                     .setDeviceTypeName(deviceTypeName)
                     .setAlgorithmId(deviceInfo.getAlgorithmId())
                     .setAlgorithmName(algorithmName)
-                    .setStandard(BigDecimal.valueOf(algorithmMoonConfig.getPrice()).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_DOWN).doubleValue() + "元/每笔(" + inf.getSize() + "笔)")
-                    .setMoney(deviceTypeAlgorithmBeforConfig == null ? inf.getMoney() : deviceTypeAlgorithmBeforConfig.getMoney());
-            //封装算法包月信息
+                    // 算法计费标准
+                    .setStandard(BigDecimal.valueOf(algorithmMoonConfig.getPrice() + extraSingleMoney).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_DOWN).doubleValue() + "元/每笔(" + inf.getSize() + "笔)")
+                    // 设备激活 代理商费用 deviceTypeAlgorithmBeforConfig.getExtraMoney()
+                    .setMoney(deviceTypeAlgorithmBeforConfig == null ? inf.getMoney() + mercFeeConfig.getFeeActive() : deviceTypeAlgorithmBeforConfig.getMoney() + mercFeeConfig.getFeeActive());
+            // 封装算法包月信息
             DeviceAlgorithmChargingDto.AlgorithmMoonConfig.Moon moon = algorithmMoonConfig.getMoon();
             DeviceChargingDto.PayCheckVo.DeviceAlgorithmCharging moonDeviceAlgorithmCharging = Beans.copy(DeviceChargingDto.PayCheckVo.DeviceAlgorithmCharging.class, deviceInfo)
                     .setDeviceTypeName(deviceTypeName)
@@ -181,9 +196,9 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
     public R check(@RequestBody @Validated DeviceChargingDto.Check check) {
         LocalDateTime now = LocalDateTime.now();
         DeviceCharging deviceCharging = getById(check.getDeviceId());
-        //不存在则新增
+        // 不存在则新增
         if (deviceCharging == null) {
-            //查询设备计费配置表
+            // 查询设备计费配置表
             DeviceInfoDto.Vo deviceInfo = deviceInfoService.obj(new DeviceInfoDto.Obj().setDeviceId(check.getDeviceId())).getData();
             List<String> mercCodes = new ArrayList<>();
             deviceAlgorithmChargingService.getMercCodes(deviceInfo.getMercCode(), mercCodes);
@@ -193,10 +208,10 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
                     .eq(DeviceChargingConfig::getDeviceType, deviceInfo.getDeviceType())
                     .orderByDesc(DeviceChargingConfig::getMercCode)
             );
-            //有则使用,无则使用默认字典
+            // 有则使用,无则使用默认字典
             int chargingX = Emptys.check(deviceChargingConfigs) ? deviceChargingConfigs.get(0).getConfigValue()
                     : SysDictUtils.getValue(EnumDeviceCharging.Code.CODE.getCode(), EnumDeviceCharging.N_X.getCode(), Integer.class);
-            //新增
+            // 新增
             String timeout = DataTime.getStringAround(0, 0, chargingX, 0, 0, 0);
             deviceCharging = new DeviceCharging()
                     .setDeviceId(check.getDeviceId())
@@ -204,7 +219,7 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
                     .setCreateTime(now);
             save(deviceCharging);
         }
-        //验证过期时间
+        // 验证过期时间
         int contrast = DataTime.stringContrast(DataTime.toString(deviceCharging.getTimeout()), DataTime.toString(now));
         if (contrast <= 0) {
             return R.fail(R.Enum.CHARGING.getCode(), R.Enum.CHARGING.getMsg());
@@ -223,8 +238,15 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
         List<DeviceChargingDto.PageVo> records = iPage.getRecords();
         if (Emptys.check(records)) {
             Map<String, SysDictRedis> stringSysDictRedisMap = SysDictUtils.get(EnumDeviceCharging.Code.CODE.getCode());
+            Long mercId = page.getMercId();
+            MercDto.Vo merc = mercService.obj(new MercDto.Vo().setId(mercId)).getData();
+            // 佣金配置查询
+            MercFeeConfigDto.FeeConfigByMercVO mercFeeConfig = R.feignCheckData(mercFeeConfigService.getFeeConfigByMerc(new MercFeeConfigDto.FeeConfigByMerc().setMercCode(merc.getMercCode())));
+            log.info("商户:{},设备管理费佣金", mercId, JSONUtil.toJsonPrettyStr(mercFeeConfig));
+            // 设备管理费佣金
+            Integer feeDevice = mercFeeConfig.getFeeDevice();
             for (DeviceChargingDto.PageVo record : records) {
-                //封装过期状态说明
+                // 封装过期状态说明
                 String timeoutStatus;
                 DeviceChargingDto.Vo deviceCharging = record.getDeviceCharging();
                 LocalDateTime timeout = deviceCharging.getTimeout();
@@ -236,21 +258,21 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
                 }
                 record.getDeviceCharging().setTimeoutStatus(timeoutStatus);
                 DeviceInfoDto.Vo deviceInfo = record.getDeviceInfo();
-                //查询设备计费配置
+                // 查询设备计费配置
                 DeviceChargingConfigDto.SelectList selectList = new DeviceChargingConfigDto.SelectList()
                         .setDeviceType(deviceInfo.getDeviceType())
                         .setMercId(deviceInfo.getMercId());
                 selectList.setType(prep);
                 List<DeviceChargingConfigDto.Vo> deviceChargingConfigs = deviceChargingConfigService.list2(selectList).getData();
                 if (Emptys.check(deviceChargingConfigs)) {
-                    //获取自定义配置计费标准
+                    // 获取自定义配置计费标准
                     DeviceChargingConfigDto.Vo deviceChargingConfig = deviceChargingConfigs.get(0);
-                    record.setChargingMoney(deviceChargingConfig.getConfigValue());
+                    record.setChargingMoney(deviceChargingConfig.getConfigValue() + feeDevice);
                 } else {
-                    //获取默认计费标准
+                    // 获取默认计费标准
                     SysDictRedis sysDictRedis = stringSysDictRedisMap.get(deviceInfo.getDeviceType().toString());
                     if (sysDictRedis != null) {
-                        record.setChargingMoney(Integer.valueOf(sysDictRedis.getValue()));
+                        record.setChargingMoney(Integer.valueOf(sysDictRedis.getValue()) + feeDevice);
                     }
                 }
             }
@@ -282,7 +304,7 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
         if (!Emptys.check(deviceChargingHistories)) {
             return R.fail();
         }
-        //添加设备计费历史表
+        // 添加设备计费历史表
         deviceChargingHistoryService.saveBatch(deviceChargingHistories);
         return R.ok();
     }
@@ -290,7 +312,7 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
     @Override
     @ApiOperation("购买回调")
     public R payNotice(DeviceChargingDto.PayNotice payNotice) {
-        //查询设备计费历史表
+        // 查询设备计费历史表
         List<DeviceChargingHistory> list = deviceChargingHistoryService.list(new LambdaQueryWrapper<DeviceChargingHistory>().eq(DeviceChargingHistory::getOrderId, payNotice.getOrderId()));
         if (!Emptys.check(list)) {
             return R.ok();
@@ -298,16 +320,16 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
         LocalDateTime now = LocalDateTime.now();
         JList<DeviceChargingHistory> deviceChargingHistories = new JArrayList<>(list);
         int aliDeviceType = SysDictUtils.getValue(EnumDeviceType.Code.CODE.getCode(), EnumDeviceType.N_5.getCode(), Integer.class);
-        //查询设备信息
+        // 查询设备信息
         List<DeviceInfo> deviceInfos = deviceInfoService.list(new LambdaQueryWrapper<DeviceInfo>().in(DeviceInfo::getDeviceId, deviceChargingHistories.getProperty(DeviceChargingHistory::getDeviceId)));
         JMap<Long, DeviceInfo> deviceInfoJMap = new JArrayList<>(deviceInfos).toMap(DeviceInfo::getDeviceId).cover();
-        //查询设备系统信息
+        // 查询设备系统信息
         List<DeviceSysinfoDto.Vo> deviceSysinfos = deviceSysinfoService.list(new DeviceSysinfoDto.SelectList().setDeviceIds(deviceChargingHistories.getProperty(DeviceChargingHistory::getDeviceId))).getData();
         JMap<Long, DeviceSysinfoDto.Vo> deviceSysinfosJMaps = new JArrayList<>(deviceSysinfos).toMap(DeviceSysinfoDto.Vo::getDeviceId).cover();
-        //查询设备计费表
+        // 查询设备计费表
         List<DeviceCharging> deviceChargings = list(new LambdaQueryWrapper<DeviceCharging>().in(DeviceCharging::getDeviceId, deviceChargingHistories.getProperty(DeviceChargingHistory::getDeviceId)));
         JMap<Long, DeviceCharging> deviceChargingsJMaps = new JArrayList<>(deviceChargings).toMap(DeviceCharging::getDeviceId).cover();
-        //获取已支付字典
+        // 获取已支付字典
         Integer status = SysDictUtils.getValue(EnumDeviceChargingHistoryStatus.Code.CODE.getCode(), EnumDeviceChargingHistoryStatus.N_2.getCode(), Integer.class);
         JList<DeviceCharging> updateDeviceCharging = new JArrayList<>();
         JList<DeviceInfoDto.Update> updateDeviceInfos = new JArrayList<>();
@@ -321,21 +343,21 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
                     .setLastChargingTime(now);
             Integer chargingSize = deviceChargingHistory.getChargingSize();
             boolean fal = false;
-            //设备计费历史完成
+            // 设备计费历史完成
             deviceChargingHistory.setStatus(status);
             String timeout = DataTime.getStringAround(chargingSize, 0, 0, 0, 0, 0, DataTime.toString(deviceCharging.getTimeout()));
             deviceCharging.setChargingSumMoney(deviceCharging.getChargingSumMoney() + deviceChargingHistory.getChargingMoney())
                     .setTimeout(DataTime.toLocal(timeout));
-            //过期时间大于当前时间
+            // 过期时间大于当前时间
             if (DataTime.stringContrast(timeout, DataTime.toString(now)) > 0) {
                 fal = true;
             }
             if (fal) {
-                //解冻设备
+                // 解冻设备
                 DeviceInfoDto.Update updateDeviceInfo = new DeviceInfoDto.Update()
                         .setDeviceId(deviceChargingHistory.getDeviceId());
                 updateDeviceInfo.setFreezeStatus(1);
-                //激活设备
+                // 激活设备
                 if (deviceChargingHistory.getChargingType() != 100) {
                     if (deviceInfo.getActiveState() == 2) {
                         updateDeviceInfo.setActiveState(1);
@@ -346,14 +368,14 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
                 }
                 updateDeviceInfos.add(updateDeviceInfo);
             }
-            //支付宝设备
+            // 支付宝设备
             if (deviceInfo.getDeviceType() == aliDeviceType) {
                 if (deviceChargingHistory.getChargingType() != 100 && deviceInfo.getActiveState() == 2) {
-                    //支付宝绑定
+                    // 支付宝绑定
                     DeviceSysinfoDto.Vo deviceSysinfo = deviceSysinfosJMaps.get(deviceChargingHistory.getDeviceId());
                     BindDeviceDTO bindDeviceDTO = new BindDeviceDTO().setTerminalId(String.valueOf(deviceInfo.getDeviceId()))
                             .setBoardSn(deviceSysinfo.getDeviceSn());
-                    //支付宝激活
+                    // 支付宝激活
                     BindActiveDTO bindActiveDTO = new BindActiveDTO()
                             .setTerminalId(String.valueOf(deviceInfo.getDeviceId()))
                             .setBoardSn(deviceSysinfo.getDeviceSn())
@@ -365,29 +387,29 @@ public class DeviceChargingServiceImpl extends ServiceImpl<DeviceChargingMapper,
             updateDeviceChargingHistory.add(deviceChargingHistory);
         }
         int size = 50;
-        //修改设备计费记录
+        // 修改设备计费记录
         if (Emptys.check(updateDeviceCharging)) {
             JList<JList<DeviceCharging>> partition = updateDeviceCharging.partition(size);
             partition.forEach(data -> updateBatchById(data));
         }
-        //修改设备计费历史记录
+        // 修改设备计费历史记录
         if (Emptys.check(updateDeviceChargingHistory)) {
             JList<JList<DeviceChargingHistory>> partition = updateDeviceChargingHistory.partition(size);
             partition.forEach(data -> deviceChargingHistoryService.updateBatchById(data));
         }
-        //修改设备
+        // 修改设备
         if (Emptys.check(updateDeviceInfos)) {
             JList<JList<DeviceInfoDto.Update>> partition = updateDeviceInfos.partition(size);
             partition.forEach(data -> deviceInfoService.updateBatch(data));
         }
-        //支付宝刷脸柜激活请求
+        // 支付宝刷脸柜激活请求
         log.info("支付宝刷脸柜激活请求参数:{}", ailiActive.toString());
         if (Emptys.check(ailiActive)) {
             ThreadPoolUtils.Execute execute = ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.ALI_DEVICE_ACTIVE, ailiActive.size());
             ailiActive.forEach(bindDeviceDTOBindActiveDTOTuple2 -> execute.execute(() -> {
-                //调用支付宝绑定
+                // 调用支付宝绑定
                 R.feignCheckData(alipayDeviceService.deviceBind(bindDeviceDTOBindActiveDTOTuple2.getV1()));
-                //调用支付宝激活
+                // 调用支付宝激活
                 R.feignCheckData(alipayDeviceService.deviceActive(bindDeviceDTOBindActiveDTOTuple2.getV2()));
             }));
         }

+ 179 - 128
device-api-service/src/main/java/com/xy/service/DeviceInfoServiceImpl.java

@@ -37,6 +37,7 @@ import com.xy.error.CommRuntimeException;
 import com.xy.mapper.DeviceInfoMapper;
 import com.xy.mapper.entity.DeviceInfoQueryPage;
 import com.xy.service.be.MercFeignService;
+import com.xy.service.be.MercService;
 import com.xy.service.common.MercPlaceService;
 import com.xy.service.common.MercRegionService;
 import com.xy.sys.EnumDataClearSize;
@@ -112,6 +113,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     private final MercUserBindDeviceService mercUserBindDeviceService;
 
     private final DevicePartServiceImpl devicePartService;
+    private final MercService mercService;
 
 
     @Override
@@ -127,7 +129,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
             }
         });
 
-        //没有管理员的的设置默认值
+        // 没有管理员的的设置默认值
         deviceInfoList.stream().filter(s -> s.getAdminName() == null).forEach(s -> s.setAdminName(noAdmin));
         return R.ok(deviceInfoList);
     }
@@ -147,7 +149,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
             }
         });
 
-        //没有管理员的的设置默认值
+        // 没有管理员的的设置默认值
         deviceInfoList.getRecords().stream().filter(s -> s.getAdminName() == null).forEach(s -> s.setAdminName(noAdmin));
         return R.ok(toPageBean(DeviceInfoDto.ListByAdminName.class, deviceInfoList));
     }
@@ -157,10 +159,10 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     public R<List<DeviceInfoDto.GroupByAdminNameVo>> groupByAdminName(@RequestBody @Validated DeviceInfoDto.GroupByAdminNameDto dto) {
         String noAdmin = "未分配管理员";
         List<DeviceInfoDto.ListByAdminName> deviceInfoList = listByAdminName(dto).getData();
-        //根据管理员名字分组
+        // 根据管理员名字分组
         Map<String, List<DeviceInfoDto.ListByAdminName>> deviceMap = deviceInfoList.stream().collect(Collectors.groupingBy(DeviceInfoDto.ListByAdminName::getAdminName));
         List<DeviceInfoDto.GroupByAdminNameVo> list = new ArrayList<>();
-        //不包含未分配管理员的
+        // 不包含未分配管理员的
         deviceMap.forEach(
                 (k, i) -> {
                     DeviceInfoDto.GroupByAdminNameVo vo = new DeviceInfoDto.GroupByAdminNameVo();
@@ -172,7 +174,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                     }
                 }
         );
-        //包含分配管理员的
+        // 包含分配管理员的
         List<DeviceInfoDto.ListByAdminName> noAdminNamesList = deviceMap.get(noAdmin);
         if (Emptys.check(noAdminNamesList)) {
             DeviceInfoDto.GroupByAdminNameVo vo = new DeviceInfoDto.GroupByAdminNameVo();
@@ -188,10 +190,10 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     public R<List<DeviceInfoDto.GroupByAdminNameVo>> groupByAdminCount(@RequestBody @Validated DeviceInfoDto.GroupByAdminNameDto dto) {
         String noAdmin = "未分配管理员";
         List<DeviceInfoDto.ListByAdminName> deviceInfoList = listByAdminName(dto).getData();
-        //根据管理员名字分组
+        // 根据管理员名字分组
         Map<String, List<DeviceInfoDto.ListByAdminName>> deviceMap = deviceInfoList.stream().collect(Collectors.groupingBy(DeviceInfoDto.ListByAdminName::getAdminName));
         List<DeviceInfoDto.GroupByAdminNameVo> list = new ArrayList<>();
-        //不包含未分配管理员的
+        // 不包含未分配管理员的
         deviceMap.forEach(
                 (k, i) -> {
                     DeviceInfoDto.GroupByAdminNameVo vo = new DeviceInfoDto.GroupByAdminNameVo();
@@ -203,7 +205,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                     }
                 }
         );
-        //包含分配管理员的
+        // 包含分配管理员的
         List<DeviceInfoDto.ListByAdminName> noAdminNamesList = deviceMap.get(noAdmin);
         if (Emptys.check(noAdminNamesList)) {
             DeviceInfoDto.GroupByAdminNameVo vo = new DeviceInfoDto.GroupByAdminNameVo();
@@ -250,7 +252,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         String searchKey = dto.getSearchKey();
         Integer thirdStatus = dto.getThirdStatus();
         List<String> statusList = new ArrayList<>();
-        //1待审核,2已审核
+        // 1待审核,2已审核
         if (thirdStatus != null && thirdStatus.intValue() == 1) {
             statusList = CollUtil.newArrayList("1000", "2000", "3000", "5000");
         }
@@ -281,8 +283,8 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                  */
                 String tyStatus = deviceInfo.getThirdStatus();
                 if (!"4000".equals(tyStatus)) {
-                    //未登记成功的需要实时查询
-                    //查询登记设备
+                    // 未登记成功的需要实时查询
+                    // 查询登记设备
                     DeviceQueryVO deviceQueryVO = tyApiService.deviceQuery(new DeviceQueryDTO().setCpuId(String.valueOf(deviceId)));
                     Integer status = deviceQueryVO.getStatus();
                     String message = deviceQueryVO.getMessage();
@@ -318,7 +320,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         }
         List<GoodsDeviceDto.Vo> goodsDevices = R.feignCheckData(goodsDeviceService.list(selectList));
         if (type == 2 && CollUtil.isEmpty(goodsDevices)) {
-            //右侧已选的
+            // 右侧已选的
             return R.ok(new PageBean<>());
         }
         List<Long> deviceIds = goodsDevices.stream().map(GoodsDeviceDto.Vo::getDeviceId).collect(Collectors.toList());
@@ -326,7 +328,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         LambdaQueryWrapper<DeviceInfo> lqw = new MybatisPlusQuery().eqWrapper(dto, DeviceInfo.class)
                 .build();
         lqw.in(type == 2 && CollUtil.isNotEmpty(deviceIds), DeviceInfo::getDeviceId, deviceIds);
-        //左侧排除掉已关联的
+        // 左侧排除掉已关联的
         lqw.notIn(type == 1 && CollUtil.isNotEmpty(deviceIds), DeviceInfo::getDeviceId, deviceIds);
         lqw.and(StrUtil.isNotEmpty(searchKey), wrapper -> wrapper
                 .eq(DeviceInfo::getDeviceId, searchKey)
@@ -347,7 +349,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @ApiOperation("设备列表带卡包数")
     public R<PageBean<DeviceInfoDto.AlgorithmChargingVo>> algorithmChargingDevice(@RequestBody @Validated DeviceInfoDto.AlgorithmCharging algorithmCharging) {
         PageBean pageBean = algorithmCharging.getPage();
-        //查询设备
+        // 查询设备
         Integer value = SysDictUtils.getValue(EnumDeviceActiveStatus.Code.CODE.getCode(), EnumDeviceActiveStatus.N_1.getCode(), Integer.class);
         LambdaUpdateWrapper<DeviceInfo> lambdaUpdateWrapper = new LambdaUpdateWrapper<DeviceInfo>()
                 .eq(DeviceInfo::getMercId, algorithmCharging.getMercId())
@@ -360,7 +362,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         if (!Emptys.check(algorithmChargingVos)) {
             return R.ok(algorithmChargingVoPageBean);
         }
-        //查询卡包数量
+        // 查询卡包数量
         List<DeviceAlgorithmChargingDto.CountVo> data = deviceAlgorithmChargingService.count(new DeviceAlgorithmChargingDto.Count()
                 .setDeviceIds(new JArrayList<>(algorithmChargingVos).getProperty(DeviceInfoDto.AlgorithmChargingVo::getDeviceId))
                 .setMercId(algorithmCharging.getMercId())
@@ -413,6 +415,55 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         return R.ok(toPageBean(DeviceInfoDto.Vo.class, iPage));
     }
 
+    @Override
+    @ApiOperation("设备流水统计分页")
+    public R<PageBean<DeviceDataDto.DeviceFlowCountVO>> deviceFlowCountPage(@RequestBody @Valid DeviceDataDto.DeviceFlowCountDTO dto) {
+        Long curMercId = dto.getCurMercId();
+        PageBean pageBean = dto.getPage();
+        List<Long> mercIds = new ArrayList<>();
+        Long chooseMercId = dto.getChooseMercId();
+        if (chooseMercId == null) {
+            // 未指定商户 查下级商户含自身
+            mercIds = R.feignCheckData(mercService.getAllSubMercIds(new MercDto.QuerySubDTO().setParentMercID(curMercId)));
+        } else {
+            mercIds.add(chooseMercId);
+
+        }
+        LambdaQueryWrapper<DeviceInfo> lqw = new MybatisPlusQuery().eqWrapper(dto, DeviceInfo.class)
+                .ge(DeviceInfo::getActiveTime, dto.getActiveStartTime())
+                .le(DeviceInfo::getActiveTime, dto.getActiveEndStartTime())
+                .build().in(DeviceInfo::getMercId, mercIds).eq(DeviceInfo::getActiveState, DeviceActiveStateEnum.TRUE.getCode());
+        IPage<DeviceInfo> iPage = page(toIPage(pageBean), lqw);
+        PageBean<DeviceDataDto.DeviceFlowCountVO> dataPage = toPageBean(DeviceDataDto.DeviceFlowCountVO.class, iPage);
+
+        List<DeviceDataDto.DeviceFlowCountVO> records = dataPage.getRecords();
+        if (CollUtil.isNotEmpty(records)) {
+
+            List<Long> placeIds = records.stream().filter(s -> s.getPlaceId() != null).map(DeviceDataDto.DeviceFlowCountVO::getPlaceId).distinct().collect(Collectors.toList());
+
+            List<MercPlaceDto.Vo> merPlaceList = R.feignCheckData(mercPlaceService.list(new MercPlaceDto.ListDto().setIds(placeIds)));
+            if (Emptys.check(merPlaceList)) {
+                Map<Long, MercPlaceDto.Vo> placeMap = merPlaceList.stream().collect(Collectors.toMap(MercPlaceDto.Vo::getId, p -> p));
+
+                for (DeviceDataDto.DeviceFlowCountVO record : records) {
+                    Long placeId = record.getPlaceId();
+                    if (placeId == null) {
+                        continue;
+                    }
+                    // 点位 区域 反显
+                    MercPlaceDto.Vo placeVo = placeMap.get(placeId);
+                    if (placeVo != null) {
+                        record.setDistrictName(placeVo.getRegionName());
+                        record.setPlaceName(placeVo.getPlaceName());
+                    }
+                }
+                dataPage.setRecords(records);
+            }
+        }
+        return R.ok(dataPage);
+    }
+
+
     /**
      * 按商户分页查设备
      *
@@ -430,7 +481,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
 
 
         if (BooleanUtil.isFalse(choosed)) {
-            //未选择 排除已选择
+            // 未选择 排除已选择
             if (CollUtil.isNotEmpty(deviceIds)) {
                 lqw.notIn(DeviceInfo::getDeviceId, deviceIds);
             } else {
@@ -440,8 +491,8 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                 lqw.in(DeviceInfo::getDeviceId, myDeviceIds);
             }
         } else {
-            //已选择
-            //指定设备 已选择
+            // 已选择
+            // 指定设备 已选择
             if (CollUtil.isNotEmpty(deviceIds)) {
                 lqw.in(DeviceInfo::getDeviceId, deviceIds);
             } else {
@@ -449,7 +500,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
             }
         }
 
-        //设备搜索
+        // 设备搜索
         lqw.and(StrUtil.isNotEmpty(deviceSearch),
                 wrapper -> wrapper
                         .likeRight(DeviceInfo::getDeviceName, deviceSearch)
@@ -463,7 +514,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @Override
     @ApiOperation("对象查询")
     public R<DeviceInfoDto.Vo> obj(DeviceInfoDto.Obj obj) {
-        //设备信息
+        // 设备信息
         LambdaQueryWrapper<DeviceInfo> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(obj, DeviceInfo.class).build();
         List<DeviceInfo> list = list(lambdaQueryWrapper);
         if (!Emptys.check(list)) {
@@ -484,21 +535,21 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
             ThreadPoolUtils.Execute execute = ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, num);
             if (obj.getIsSysinfo()) {
                 execute.execute(() -> {
-                    //系统信息
+                    // 系统信息
                     DeviceSysinfoDto.Vo deviceSysinfo = deviceSysinfoService.get(new DeviceSysinfoDto.Vo().setDeviceId(deviceInfo.getDeviceId())).getData();
                     deviceInfo.setDeviceSysinfo(deviceSysinfo);
                 });
             }
             if (obj.getIsStatus()) {
                 execute.execute(() -> {
-                    //状态信息
+                    // 状态信息
                     DeviceStatusDto.Vo deviceStatus = deviceStatusService.obj(new DeviceStatusDto.Vo().setDeviceId(deviceInfo.getDeviceId())).getData();
                     deviceInfo.setDeviceStatus(deviceStatus);
                 });
             }
             if (obj.getIsRegister()) {
                 execute.execute(() -> {
-                    //注册信息
+                    // 注册信息
                     DeviceRegisterDto.Vo deviceRegister = deviceRegisterService.obj(new DeviceRegisterDto.Vo().setDeviceId(deviceInfo.getDeviceId())).getData();
                     deviceInfo.setDeviceRegister(deviceRegister);
                 });
@@ -528,14 +579,14 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @Override
     @ApiOperation("设备访问历史添加")
     public R history(DeviceInfoDto.Obj obj) {
-        //获取字典
+        // 获取字典
         SysDictRedis sysDictRedis = SysDictUtils.get(EnumDataClearSize.Code.CODE.getCode(), EnumDataClearSize.DEVICE_HISTORY_TWIG.getCode());
         Integer value = Integer.valueOf(sysDictRedis.getValue());
-        //获取redis
+        // 获取redis
         String key = keyPrefix + AuthorizeUtils.getLoginId(Long.class);
         List<String> list = redisService.getList(key);
         list.add(0, String.valueOf(obj.getDeviceId()));
-        //去重
+        // 去重
         List<String> redisList = new ArrayList<>();
         JList<String> comparing = new JArrayList<>(list).comparing();
         if (comparing.size() > value) {
@@ -562,7 +613,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         }
         DeviceStatusDto.Vo deviceStatus = deviceInfo.getDeviceStatus();
         SysDictRedis qualitySets = SysDictUtils.get(EnumQualityMercSets.Code.CODE.getCode(), EnumQualityMercSets.MERC_CODE.getCode());
-        //设备当前商户是质检时不检查
+        // 设备当前商户是质检时不检查
         if (!qualitySets.getValue().equals(deviceInfo.getMercCode())) {
             check(deviceInfo.getActiveState(), 2, "设备未激活");
             check(deviceInfo.getFreezeStatus(), 2, "设备已冻结");
@@ -580,13 +631,13 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @PostMapping("historyList")
     @ApiOperation("设备访问历史查询")
     public R<List<DeviceInfoDto.Vo>> historyList() {
-        //获取redis
+        // 获取redis
         String key = keyPrefix + AuthorizeUtils.getLoginId(Long.class);
         List<String> deviceIds = redisService.getList(key);
         if (!Emptys.check(deviceIds)) {
             return R.ok();
         }
-        //查询数据库
+        // 查询数据库
         List<DeviceInfo> list = list(new LambdaQueryWrapper<DeviceInfo>().in(DeviceInfo::getDeviceId, deviceIds));
         return R.ok(copy(DeviceInfoDto.Vo.class, list));
     }
@@ -605,15 +656,15 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @PostMapping("update")
     public R update(@RequestBody @Validated DeviceInfoDto.Update update) {
         DeviceInfo deviceInfo = getById(update.getDeviceId());
-        //判断是否更新了点位
+        // 判断是否更新了点位
         if (Emptys.check(update.getPlaceId()) && !Objects.equals(deviceInfo.getPlaceId(), update.getPlaceId())) {
-            //把设备绑定给点位管理员
+            // 把设备绑定给点位管理员
             MercUserBindDeviceDto.BindByDeviceUpdate bindByPlaceIdDTto = new MercUserBindDeviceDto.BindByDeviceUpdate();
             bindByPlaceIdDTto.setDeviceId(update.getDeviceId())
                     .setPlaceId(update.getPlaceId())
                     .setMercId(deviceInfo.getMercId());
             mercUserBindDeviceService.bindByDeviceUpdate(bindByPlaceIdDTto);
-            //更新坐标为点位的坐标
+            // 更新坐标为点位的坐标
             MercPlaceDto.ObjVo place = mercPlaceService.obj(new MercPlaceDto.Obj().setId(update.getPlaceId())).getData();
             update.setLat(place.getLat()).setLon(place.getLon());
         }
@@ -626,19 +677,19 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         DeviceInfoDto.Vo device = R.feignCheckData(this.obj(new DeviceInfoDto.Obj().setDeviceId(deviceId).setIsSysinfo(true)));
         Long algorithmId = update.getAlgorithmId();
         if (algorithmId != null && AlgorithmTypeEnum.CLOUD.getId() == algorithmId) {
-            //云从算法
+            // 云从算法
             boolean b = cloudWalkApiService.checkDeviceExist(deviceId);
             if (!b) {
-                //货柜不存在,新增
+                // 货柜不存在,新增
                 cloudWalkApiService.containerAdd(new ContainerAddDTO().setContainerCode(String.valueOf(deviceId)));
             }
         } else if (algorithmId != null && AlgorithmTypeEnum.TY.getId() == algorithmId) {
-            //拓元算法
-            //查询登记设备
+            // 拓元算法
+            // 查询登记设备
             DeviceQueryVO deviceQueryVO = tyApiService.deviceQuery(new DeviceQueryDTO().setCpuId(String.valueOf(deviceId)));
             Integer status = deviceQueryVO.getStatus();
             if (status != null && 1000 == status.intValue()) {
-                //未知的设备CPUID,进行登记
+                // 未知的设备CPUID,进行登记
                 tyApiService.deviceReg(new DeviceRegDTO()
                         .setCpuId(String.valueOf(deviceId))
                         .setDeviceNumber(String.valueOf(deviceId))
@@ -688,20 +739,20 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @ApiOperation("更新商户线路")
     public R updateLine(@RequestBody @Validated DeviceInfoDto.UpdateLine updateLine) {
         LambdaUpdateWrapper<DeviceInfo> luw = new LambdaUpdateWrapper<DeviceInfo>().eq(DeviceInfo::getMercId, updateLine.getMercId());
-        //绑定线路,更换线路
+        // 绑定线路,更换线路
         if (DeviceInfoDto.UPDATE.equals(updateLine.getType())) {
             DeviceInfo deviceInfo = new DeviceInfo();
             deviceInfo.setPlaceLineId(updateLine.getPlaceLineId());
             luw.in(DeviceInfo::getDeviceId, updateLine.getDeviceIds());
             baseMapper.update(deviceInfo, luw);
         }
-        //删除线路
+        // 删除线路
         if (DeviceInfoDto.DEL.equals(updateLine.getType())) {
             luw.eq(DeviceInfo::getPlaceLineId, updateLine.getWherePlaceLineId());
             luw.set(DeviceInfo::getPlaceLineId, null);
             baseMapper.update(null, luw);
         }
-        //解绑线路 设置线路ID为null
+        // 解绑线路 设置线路ID为null
         if (DeviceInfoDto.CLEAR.equals(updateLine.getType())) {
             luw.in(DeviceInfo::getDeviceId, updateLine.getDeviceIds());
             luw.set(DeviceInfo::getPlaceLineId, null);
@@ -715,20 +766,20 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @ApiOperation("更新商户点位")
     public R updatePlace(@RequestBody @Validated DeviceInfoDto.UpdatePlace updatePlace) {
         LambdaUpdateWrapper<DeviceInfo> luw = new LambdaUpdateWrapper<DeviceInfo>().eq(DeviceInfo::getMercId, updatePlace.getMercId());
-        //绑定点位,更换点位
+        // 绑定点位,更换点位
         if (DeviceInfoDto.UPDATE.equals(updatePlace.getType())) {
             DeviceInfo deviceInfo = new DeviceInfo();
             deviceInfo.setPlaceId(updatePlace.getPlaceId());
             luw.in(DeviceInfo::getDeviceId, updatePlace.getDeviceIds());
             baseMapper.update(deviceInfo, luw);
         }
-        //删除点位
+        // 删除点位
         if (DeviceInfoDto.DEL.equals(updatePlace.getType())) {
             luw.eq(DeviceInfo::getPlaceId, updatePlace.getWherePlaceId());
             luw.set(DeviceInfo::getPlaceId, null);
             baseMapper.update(null, luw);
         }
-        //解绑点位 设置点位ID为null
+        // 解绑点位 设置点位ID为null
         if (DeviceInfoDto.CLEAR.equals(updatePlace.getType())) {
             luw.in(DeviceInfo::getDeviceId, updatePlace.getDeviceIds());
             luw.set(DeviceInfo::getPlaceId, null);
@@ -760,13 +811,13 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         PageBean<DeviceInfoDto.Vo2> pageBean = queryPage(page);
         List<DeviceInfoDto.Vo2> records = pageBean.getRecords();
         List<DeviceInfoDto.DeviceExcelVO> deviceExcelVOS = BeanUtil.copyToList(records, DeviceInfoDto.DeviceExcelVO.class);
-        //异步导出参数封装
+        // 异步导出参数封装
         ExcelDTO<DeviceInfoDto.DeviceExcelVO> excelDTO = new ExcelDTO<>();
         excelDTO.setData(deviceExcelVOS);
         excelDTO.setHead(DeviceInfoDto.DeviceExcelVO.class);
         excelDTO.setSheetName(FileExportType.DEVICE_INFO.getDescription());
         excelDTO.setFileExportType(FileExportType.DEVICE_INFO);
-        //执行导出
+        // 执行导出
         fileExportService.exportExcelAsync(excelDTO);
     }
 
@@ -787,16 +838,16 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         String mercCode = auth.getMercCode();
         Long algorithmId = auth.getAlgorithmId();
         String mercName = auth.getMercName();
-        //商户最终设备列表
+        // 商户最终设备列表
         List<Long> deviceIds = auth.getDeviceIds();
         List<DeviceInfo> devices = getDevicesByMercId(mercId);
-        //取消商户设备授权
+        // 取消商户设备授权
         if (CollUtil.isEmpty(deviceIds)) {
             if (CollUtil.isEmpty(devices)) {
                 return R.ok(Boolean.TRUE);
             }
         }
-        //更新商户设备授权
+        // 更新商户设备授权
         List<DeviceInfo> deviceInfos = this.listByIds(deviceIds);
         List<DeviceStatus> deviceStatuses = new ArrayList<>();
         for (DeviceInfo deviceInfo : deviceInfos) {
@@ -804,24 +855,24 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
             Long deviceId = deviceInfo.getDeviceId();
 
             if (ObjectUtil.equals(deviceType, DeviceTypeEnum.TYPE5.getCode())) {
-                //支付宝设备算法
+                // 支付宝设备算法
                 algorithmId = AlgorithmTypeEnum.ALIPAY.getId();
             } else {
-                //非支付宝算法
+                // 非支付宝算法
                 if (AlgorithmTypeEnum.CLOUD.getId() == algorithmId) {
-                    //云从算法
+                    // 云从算法
                     boolean b = cloudWalkApiService.checkDeviceExist(deviceId);
                     if (!b) {
-                        //货柜不存在,新增
+                        // 货柜不存在,新增
                         cloudWalkApiService.containerAdd(new ContainerAddDTO().setContainerCode(String.valueOf(deviceId)));
                     }
                 } else if (AlgorithmTypeEnum.TY.getId() == algorithmId) {
-                    //拓元算法
-                    //查询登记设备
+                    // 拓元算法
+                    // 查询登记设备
                     DeviceQueryVO deviceQueryVO = tyApiService.deviceQuery(new DeviceQueryDTO().setCpuId(String.valueOf(deviceId)));
                     Integer status = deviceQueryVO.getStatus();
                     if (status != null && 1000 == status.intValue()) {
-                        //未知的设备CPUID,进行登记
+                        // 未知的设备CPUID,进行登记
                         tyApiService.deviceReg(new DeviceRegDTO()
                                 .setCpuId(String.valueOf(deviceId))
                                 .setDeviceNumber(String.valueOf(deviceId))
@@ -833,7 +884,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
             String refMercCode = deviceInfo.getMercCode();
 
             if (BooleanUtil.isFalse(auth.getMercOperate())) {
-                //非商户操作
+                // 非商户操作
                 //  只有解绑后,才能给顶级商户授权
                 if (refMercId != -1 && refMercId != mercId.intValue()) {
                     StrBuilder sb = StrBuilder.create();
@@ -844,20 +895,20 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                             .append(deviceInfo.getMercName())
                             .append("]绑定,请先进行解绑!")
                             .toString();
-                    //非质检商户需要进行判断,质检商户跳过
+                    // 非质检商户需要进行判断,质检商户跳过
                     if (!QA_MERC_CODE.equals(refMercCode)) {
-                        //已关联别商户
+                        // 已关联别商户
                         return R.fail(errMsg, Boolean.FALSE);
                     }
 
                 }
             } else {
-                //商户操作直接转移给子商户
+                // 商户操作直接转移给子商户
             }
 
-            //绑定关系
+            // 绑定关系
             deviceInfo.setMercId(mercId).setMercCode(mercCode).setAlgorithmId(algorithmId).setMercName(mercName);
-            //标记机器可交易
+            // 标记机器可交易
             DeviceStatus deviceStatus = new DeviceStatus()
                     .setDeviceId(deviceInfo.getDeviceId())
                     .setIsPay(true);
@@ -904,13 +955,13 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     private Boolean removeMerDevicesByDeviceIds(DeviceInfoDto.MercDeviceUnBindDto dto, List<DeviceInfo> deviceInfos) {
         if (CollUtil.isNotEmpty(deviceInfos)) {
             deviceInfos.forEach(deviceInfo -> {
-                //回收 到当前操作商户
+                // 回收 到当前操作商户
                 deviceInfo.setMercId(dto.getMercId());
                 deviceInfo.setMercDeviceCode(StrUtil.EMPTY);
                 deviceInfo.setMercName(dto.getMercName());
                 deviceInfo.setMercCode(dto.getMercCode());
             });
-            //批量更新
+            // 批量更新
             return updateBatchById(deviceInfos);
         }
 
@@ -928,13 +979,13 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         MercDto.Vo mercCheck = R.feignCheckData(mercFeignService.obj(new MercDto.ListDTO().setMercCode(QA_MERC_CODE)));
         if (CollUtil.isNotEmpty(deviceInfos)) {
             deviceInfos.forEach(deviceInfo -> {
-                //回收
+                // 回收
                 deviceInfo.setMercId(mercCheck.getId());
                 deviceInfo.setMercDeviceCode(StrUtil.EMPTY);
                 deviceInfo.setMercName(mercCheck.getName());
                 deviceInfo.setMercCode(QA_MERC_CODE);
             });
-            //批量更新
+            // 批量更新
             return updateBatchById(deviceInfos);
         }
 
@@ -951,7 +1002,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     private Boolean removeMerRefDevices(List<DeviceInfo> deviceInfos, Long parentId) {
         if (CollUtil.isNotEmpty(deviceInfos) && parentId != null) {
             deviceInfos.forEach(deviceInfo -> {
-                //非顶级兴元商户,解绑后,机器归父商户
+                // 非顶级兴元商户,解绑后,机器归父商户
                 if (parentId != 1) {
                     MercDto.Vo mercParent = R.feignCheckData(mercFeignService.obj(new MercDto.ListDTO().setId(parentId)));
                     if (mercParent != null) {
@@ -965,7 +1016,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                     }
 
                 }
-                //一级商户,解绑后,直接释放
+                // 一级商户,解绑后,直接释放
                 if (parentId == 0) {
                     MercDto.Vo mercCheck = R.feignCheckData(mercFeignService.obj(new MercDto.ListDTO().setMercCode(QA_MERC_CODE)));
                     if (mercCheck != null) {
@@ -981,7 +1032,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                 }
 
             });
-            //批量更新
+            // 批量更新
             return updateBatchById(deviceInfos);
         }
 
@@ -1014,7 +1065,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
 //            queryWrapper.in(LambdaUtils.getUnderlineCaseName(DeviceInfo::getPlaceLineId), placeLineIds);
 //        }
 
-        //fixed
+        // fixed
         if (StrUtil.isNotEmpty(deviceSearch)) {
             queryWrapper.and(wrapper -> wrapper.likeRight(LambdaUtils.getUnderlineCaseName(DeviceInfo::getDeviceName), deviceSearch).or()
                     .eq(LambdaUtils.getUnderlineCaseName(DeviceInfo::getDeviceId), deviceSearch));
@@ -1048,7 +1099,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     public R<DeviceInfoDto.MercHomeStatisticalVO> mercHomeStatistical(DeviceInfoDto.MercHomeQueryDTO dto) {
         Long mercId = dto.getMercId();
         List<Long> myDeviceIds = dto.getMyDeviceIds();
-        //初始化数据
+        // 初始化数据
         DeviceInfoDto.MercHomeStatisticalVO mercHomeStatisticalVO = new DeviceInfoDto.MercHomeStatisticalVO()
                 .setClosedNum(0).setOfflineNum(0)
                 .setOnlineNum(0).setOperatingNum(0).setNeedToFillNum(0);
@@ -1062,9 +1113,9 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         }
 
 
-        //在线、离线
+        // 在线、离线
         List<DeviceStatus> deviceStatuses = deviceStatusService.listByIds(myDeviceIds);
-        //分组统计
+        // 分组统计
         Map<Integer, Long> countNetstateMap = deviceStatuses.stream().collect(Collectors
                 .groupingBy(DeviceStatus::getNetState, Collectors.counting()));
         Integer onlineDictValue = SysDictUtils.getValue(EnumDeviceOnlineStatus.Code.CODE.getCode(), EnumDeviceOnlineStatus.CONNECTED.getCode(), Integer.class);
@@ -1075,20 +1126,20 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         mercHomeStatisticalVO.setOnlineNum(onlineNum);
         mercHomeStatisticalVO.setOfflineNum(offlineNum);
 
-        //锁机、未锁机
+        // 锁机、未锁机
 //        Map<Integer, Long> countLockLstateMap = deviceStatuses.stream().collect(Collectors
 //                .groupingBy(DeviceStatus::getLockStateL, Collectors.counting()));
 //        Long lockLStateNum = countLockLstateMap.get(DeviceLockState.LOCK.getCode());
 //        Long unLockLStateNum = countLockLstateMap.get(DeviceLockState.UN_LOCK.getCode());
         Map<Integer, Long> countLockLstateMap = mercDevices.stream().collect(Collectors
                 .groupingBy(DeviceInfo::getBusyState, Collectors.counting()));
-        //运营
+        // 运营
         Long operatingNum = countLockLstateMap.get(DeviceBusySateType.OPERATING.getCode());
-        //停运
+        // 停运
         Long suspendedNum = countLockLstateMap.get(DeviceBusySateType.SUSPENDED.getCode());
         mercHomeStatisticalVO.setOperatingNum(operatingNum == null ? 0 : operatingNum.intValue());
         mercHomeStatisticalVO.setClosedNum(suspendedNum == null ? 0 : suspendedNum.intValue());
-        //待补货
+        // 待补货
         Integer deviceNum = R.feignCheckData(goodsDeviceService.countOutOfStockDevice(new GoodsDeviceDto.CountOutOfStockDevice().setMercId(mercId).setDeviceIds(myDeviceIds)));
         mercHomeStatisticalVO.setNeedToFillNum(deviceNum);
         return R.ok(mercHomeStatisticalVO);
@@ -1102,7 +1153,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         String deviceName = dto.getDeviceName();
         Long deviceId = dto.getDeviceId();
         List<Long> searchPlaceIdList = new ArrayList<>();
-        //根据管理员名字查询点位ID列表
+        // 根据管理员名字查询点位ID列表
         if (Emptys.check(dto.getAdminName())) {
             MercPlaceDto.ListDto placeDto = new MercPlaceDto.ListDto();
             placeDto.setMercId(mercId).setAdminName(dto.getAdminName());
@@ -1122,7 +1173,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         }
         List<Long> searchDeviceIds = new ArrayList<>();
         if (StrUtil.isNotEmpty(searchKey) || StrUtil.isNotEmpty(dto.getAdminName())) {
-            //名称或者编号搜索设备
+            // 名称或者编号搜索设备
             LambdaQueryWrapper<DeviceInfo> deviceLqw = Wrappers.<DeviceInfo>lambdaQuery()
                     .eq(DeviceInfo::getMercId, mercId)
                     .in(Emptys.check(searchPlaceIdList), DeviceInfo::getPlaceId, searchPlaceIdList);
@@ -1147,7 +1198,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         Integer busyStatus = dto.getBusyStatus();
         Integer onlineStatus = dto.getOnlineStatus();
         Integer deviceType = dto.getDeviceType();
-        //条件查询 在线状态,运营状态,设备类型,
+        // 条件查询 在线状态,运营状态,设备类型,
         List<Long> deviceIdList = new ArrayList<>();
         if (deviceId != null && myDeviceIds.indexOf(deviceId) > 0) {
             deviceIdList.add(deviceId);
@@ -1168,7 +1219,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                         queryDeviceIds.add(id);
                     }
                 }
-                //无符合权限的搜索设备,返空
+                // 无符合权限的搜索设备,返空
                 if (CollUtil.isEmpty(queryDeviceIds)) {
                     return R.ok(new ArrayList<>());
                 } else {
@@ -1202,7 +1253,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         List<DeviceInfoDto.MercHomeListVO> dataList = new ArrayList<>(list.size());
 
         LambdaQueryWrapper<DeviceInfo> lqw = new LambdaQueryWrapper<>();
-        //非质检商户才需要激活
+        // 非质检商户才需要激活
         lqw.eq(!isQa, DeviceInfo::getActiveState, DeviceActiveStateEnum.TRUE.getCode());
         lqw.eq(mercId != null, DeviceInfo::getMercId, mercId);
         lqw.eq(busyStatus != null, DeviceInfo::getBusyState, busyStatus);
@@ -1210,15 +1261,15 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         lqw.in(CollUtil.isNotEmpty(deviceIdList), DeviceInfo::getDeviceId, deviceIdList);
         lqw.like(StrUtil.isNotEmpty(deviceName), DeviceInfo::getDeviceName, deviceName).orderByAsc(true, DeviceInfo::getDeviceName, DeviceInfo::getDeviceId);
         List<DeviceInfoDto.Vo> deviceInfoList = copy(DeviceInfoDto.Vo.class, this.list(lqw));
-        //根据点位ID查询管理员名字
+        // 根据点位ID查询管理员名字
         List<Long> placeIdList = deviceInfoList.stream().map(DeviceInfoDto.Vo::getPlaceId).distinct().filter(Objects::nonNull).collect(Collectors.toList());
         List<MercPlaceDto.Vo> mercPlaceList = mercPlaceService.list(new MercPlaceDto.ListDto().setIds(placeIdList)).getData();
         if (Emptys.check(mercPlaceList)) {
-            //Map<Long, String> mercPlaceMap = mercPlaceList.stream().collect(Collectors.toMap(i -> i.getId(), i -> i.getAdminName()));
+            // Map<Long, String> mercPlaceMap = mercPlaceList.stream().collect(Collectors.toMap(i -> i.getId(), i -> i.getAdminName()));
             Map<Long, String> mercPlaceMap = mercPlaceList.stream().collect(HashMap::new, (map, item) -> map.put(item.getId(), item.getAdminName()), HashMap::putAll);
             deviceInfoList.forEach(i -> i.setAdminName(mercPlaceMap.get(i.getPlaceId())));
         }
-        //没有管理员的的设置默认值
+        // 没有管理员的的设置默认值
         deviceInfoList.stream().filter(s -> s.getAdminName() == null).forEach(s -> s.setAdminName("未分配管理员"));
         List<String> adminNameList = deviceInfoList.stream().map(DeviceInfoDto.Vo::getAdminName).distinct().collect(Collectors.toList());
         List<Long> dIds = deviceInfoList.stream().map(DeviceInfoDto.Vo::getDeviceId).distinct().collect(Collectors.toList());
@@ -1228,7 +1279,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
             deviceSysInfoMap = deviceSysList.stream().collect(Collectors.toMap(DeviceSysinfoDto.Vo::getDeviceId, i -> i));
         }
 
-        //根据管理员名字分组
+        // 根据管理员名字分组
         Map<String, List<DeviceInfoDto.Vo>> deviceMap = deviceInfoList.stream().collect(Collectors.groupingBy(DeviceInfoDto.Vo::getAdminName));
 
         DateTime date = DateTime.now();
@@ -1237,18 +1288,18 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         for (String adminName : adminNameList) {
             DeviceInfoDto.MercHomeListVO vo = new DeviceInfoDto.MercHomeListVO();
             vo.setAdminName(adminName);
-            //区域下的设备列表
+            // 区域下的设备列表
             List<DeviceInfoDto.MercHomeDeviceVo> deviceInfos = BeanUtil.copyToList(deviceMap.get(adminName), DeviceInfoDto.MercHomeDeviceVo.class);
             vo.setDeviceNum(deviceInfos.size());
             if (CollUtil.isEmpty(deviceInfos)) {
                 continue;
             }
 
-            //设备销售统计
+            // 设备销售统计
             List<Long> deviceIds = deviceInfos.stream().map(DeviceInfoDto.MercHomeDeviceVo::getDeviceId).collect(Collectors.toList());
 
 
-            //设备状态查询
+            // 设备状态查询
             List<DeviceStatusDto.Vo> deviceStatusList = deviceStatusService.list(new DeviceStatusDto.SelectList().setDeviceIds(deviceIds)).getData();
             Map<Long, DeviceStatusDto.Vo> datdeviceStatusMap = new HashMap<>();
             if (CollUtil.isNotEmpty(deviceStatusList)) {
@@ -1262,10 +1313,10 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
 
             for (DeviceInfoDto.MercHomeDeviceVo device : deviceInfos) {
                 Long dId = device.getDeviceId();
-                //设备类型 反显
+                // 设备类型 反显
                 SysDictRedis dictDeviceType = SysDictUtils.get(DictConsts.DEVICE_TYPE, String.valueOf(device.getDeviceType()));
                 device.setDeviceTypeName(dictDeviceType.getMsg());
-                //运营状态 反显
+                // 运营状态 反显
                 SysDictRedis dictBusyState = SysDictUtils.get(DictConsts.DEVICE_BUSY_STATUS, String.valueOf(device.getBusyState()));
                 device.setBusyStateName(dictBusyState.getMsg());
 
@@ -1274,10 +1325,10 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                 CountDto.OrderByCreateTimeAndMercId orderByCreateTimeAndMercId = new CountDto.OrderByCreateTimeAndMercId()
                         .setMerdId(mercId).setBeginTime(start).setEndTime(end).setDeviceIds(CollUtil.newArrayList(dId));
                 log.info("设备订单统计:{}", JSONUtil.toJsonPrettyStr(orderByCreateTimeAndMercId));
-                //完成订单
+                // 完成订单
                 CountDto.SuccessVo successVo = R.feignCheckData(countApiService.orderBySuccess(orderByCreateTimeAndMercId));
 
-                //今日销售、库存情况 反显
+                // 今日销售、库存情况 反显
                 device.setDayOrderNum(successVo != null ? successVo.getOrdersSize() : zero);
                 device.setDaySalesPrice(successVo != null ? successVo.getOrderTotalMoney() : zero);
                 DeviceStatusDto.Vo deviceStatus = datdeviceStatusMap.get(device.getDeviceId());
@@ -1288,7 +1339,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                         device.setFillNum(goodsDevice.stream().mapToInt(GoodsDeviceDto.Vo::getFillCount).sum());
                     }
                 }
-                //温控仪 反显
+                // 温控仪 反显
                 DeviceSysinfoDto.Vo dSysInfo = deviceSysInfoMap.get(dId);
                 if (dSysInfo == null) {
                     device.setIsHaveTemp(false);
@@ -1296,14 +1347,14 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                     device.setIsHaveTemp(BooleanUtil.isTrue(dSysInfo.getIsHaveTemp()));
                 }
 
-                //算法類型
+                // 算法類型
                 Long algorithmId = device.getAlgorithmId();
                 if (algorithmId != null) {
                     String name = algorithmListMap.get(algorithmId);
                     device.setAlgorithmAlias(name);
                 }
 
-                //联网状态
+                // 联网状态
                 Integer netState = deviceStatus == null ? DeviceNetSateType.DISCONNECT.getCode() : deviceStatus.getNetState();
                 device.setNetState(netState);
                 if (netState == null) {
@@ -1320,7 +1371,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                     device.setDeviceStateR(deviceStateR);
                     Boolean isUseBattery = deviceStatus.getIsUseBattery();
                     if (BooleanUtil.isTrue(isUseBattery)) {
-                        //使用电池。即断电状态
+                        // 使用电池。即断电状态
                         device.setSysPower(2);
                     } else {
                         device.setSysPower(1);
@@ -1335,7 +1386,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
 
             }
 
-            //名称排序
+            // 名称排序
             if (CollUtil.isNotEmpty(deviceInfos)) {
                 deviceInfos = ListUtil.sortByProperty(deviceInfos, LambdaUtils.getProperty(DeviceInfoDto.MercHomeDeviceVo::getDeviceName));
                 deviceInfos = ListUtil.sortByProperty(deviceInfos, LambdaUtils.getProperty(DeviceInfoDto.MercHomeDeviceVo::getDeviceId));
@@ -1393,16 +1444,16 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
     @Override
     public R<PageBean<DeviceInfoDto.MerHomeSearchVO>> mercDeviceSearchPage(@RequestBody DeviceInfoDto.Page page) {
         PageBean<DeviceInfoDto.MerHomeSearchVO> pageData = new PageBean<>();
-        //小程序独有查询字段 缺货状态:stockStatus ,是否查故障设备:fault
+        // 小程序独有查询字段 缺货状态:stockStatus ,是否查故障设备:fault
         Boolean fault = page.getFault();
         Long mercId = page.getMercId();
         List<Long> myDeviceIds = page.getMyDeviceIds();
         if (CollUtil.isEmpty(myDeviceIds)) {
-            //无设备
+            // 无设备
             return R.ok(pageData);
         }
         if (BooleanUtil.isTrue(fault)) {
-            //查询故障设备
+            // 查询故障设备
             List<DeviceEventMsg> deviceEventMsgs = deviceEventMsgService.list(Wrappers.<DeviceEventMsg>lambdaQuery()
                     .eq(mercId != null, DeviceEventMsg::getMercId, page.getMercId())
                     .in(DeviceEventMsg::getDeviceId, myDeviceIds));
@@ -1427,12 +1478,12 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
             List<Long> deviceIds = records.stream().map(DeviceInfoDto.Vo2::getDeviceId).collect(Collectors.toList());
             String type = EnumDeviceDataType.DAY.getCode();
             String todayDate = DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN);
-            //查询当天
+            // 查询当天
             DeviceDataDto.ListDTO dto = new DeviceDataDto.ListDTO()
                     .setDeviceIds(deviceIds).setType(type).setDateValue(Integer.valueOf(todayDate)).setMercId(mercId);
             List<DeviceDataDto.Vo> deviceDataList = deviceDataService.list(dto);
             Map<Long, DeviceDataDto.Vo> dataMap = MapUtil.newHashMap();
-            //统计数据反显
+            // 统计数据反显
             if (CollUtil.isNotEmpty(deviceDataList)) {
                 dataMap = deviceDataList.stream().collect(Collectors.toMap(DeviceDataDto.Vo::getDeviceId, d -> d));
             }
@@ -1441,7 +1492,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                 Long deviceId = v.getDeviceId();
                 DeviceDataDto.Vo vo = dataMap.get(deviceId);
                 if (vo != null) {
-                    //今日订单数
+                    // 今日订单数
                     v.setDayOrderNum(vo != null ? vo.getSalesCount() : 0);
                     v.setDaySalesPrice(vo != null ? vo.getSalesMoney() : 0);
                     BeanUtil.copyProperties(vo, merHomeSearchVO);
@@ -1479,19 +1530,19 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         Integer type = dto.getType();
         switch (type) {
             case 1:
-                //经营数据
+                // 经营数据
                 return R.ok(dataCount1(dto));
             case 2:
-                //经营图表
+                // 经营图表
                 return R.ok(dataCount2(dto));
             case 3:
-                //温度图表
+                // 温度图表
                 return R.ok(dataCount3(dto));
             case 4:
-                //信号图表
+                // 信号图表
                 return R.ok(dataCount4(dto));
             case 5:
-                //商品管理
+                // 商品管理
                 return R.ok(dataCount5(dto));
             default:
                 break;
@@ -1509,7 +1560,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         Long deviceId = dto.getDeviceId();
         Long mercId = dto.getMercId();
         DeviceInfoDto.DeviceDataCountVO vo = new DeviceInfoDto.DeviceDataCountVO();
-        //当天
+        // 当天
 
 
         DateTime date = DateTime.now();
@@ -1519,7 +1570,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         CountDto.OrderByCreateTimeAndMercId orderByCreateTimeAndMercId = new CountDto.OrderByCreateTimeAndMercId()
                 .setMerdId(mercId).setBeginTime(start).setEndTime(end).setDeviceIds(deviceIds);
 
-        //完成订单
+        // 完成订单
         CountDto.SuccessVo successVo = R.feignCheckData(countApiService.orderBySuccess(orderByCreateTimeAndMercId));
 
         DeviceDataDto.Vo dayData = new DeviceDataDto.Vo();
@@ -1530,16 +1581,16 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         }
 
 
-        //当月
+        // 当月
         DeviceDataDto.Vo monthData = new DeviceDataDto.Vo();
 
-        //月度统计
+        // 月度统计
         DateTime startM = DateUtil.beginOfMonth(date);
         DateTime endM = DateUtil.endOfMonth(date);
 
         CountDto.OrderByCreateTimeAndMercId monthOrder = new CountDto.OrderByCreateTimeAndMercId()
                 .setMerdId(mercId).setBeginTime(startM).setEndTime(endM).setDeviceIds(deviceIds);
-        //完成订单
+        // 完成订单
         CountDto.SuccessVo successVoM = R.feignCheckData(countApiService.orderBySuccess(monthOrder));
 
 
@@ -1561,7 +1612,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
      */
     private DeviceInfoDto.DeviceDataCountVO dataCount2(DeviceInfoDto.DeviceDataCountDTO dto) {
         Long deviceId = dto.getDeviceId();
-        //近一个月 (销售额,订单数,退款金额,退款数)
+        // 近一个月 (销售额,订单数,退款金额,退款数)
         DeviceInfoDto.DeviceDataCountVO vo = new DeviceInfoDto.DeviceDataCountVO();
         DeviceInfoDto.BusinessChart businessChart = new DeviceInfoDto.BusinessChart();
         List<String> categories = DataTime.dayListByLastDay(30);
@@ -1579,7 +1630,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
             return vo;
         }
 
-        //每天的数据
+        // 每天的数据
         Map<Integer, DeviceDataDto.Vo> dataDayMap = listByDay.stream().collect(Collectors.toMap(DeviceDataDto.Vo::getDateValue, i -> i));
 
         List<DeviceInfoDto.MyChartSeries3> series = new ArrayList<>();
@@ -1587,12 +1638,12 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         String[] names = {"销售额", "订单数", "退款金额", "退款数"};
         for (int i = 0; i < names.length; i++) {
             DeviceInfoDto.MyChartSeries3 myChartSeries = new DeviceInfoDto.MyChartSeries3();
-            //某个类型每天的数据
+            // 某个类型每天的数据
             List<String> data = new ArrayList<>();
             if (i == 0) {
-                //销售额
+                // 销售额
                 dateList.forEach(d -> {
-                    //每日数据填充
+                    // 每日数据填充
                     DeviceDataDto.Vo deviceData = dataDayMap.get(d);
 
                     if (deviceData == null) {
@@ -1604,9 +1655,9 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
                     }
                 });
             } else if (i == 1) {
-                //订单数
+                // 订单数
                 dateList.forEach(d -> {
-                    //每日数据填充
+                    // 每日数据填充
                     DeviceDataDto.Vo deviceData = dataDayMap.get(d);
                     String value = "0";
                     if (deviceData == null) {
@@ -1618,9 +1669,9 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
 
                 });
             } else if (i == 2) {
-                //退款金额
+                // 退款金额
                 dateList.forEach(d -> {
-                    //每日数据填充
+                    // 每日数据填充
                     DeviceDataDto.Vo deviceData = dataDayMap.get(d);
                     if (deviceData == null) {
                         data.add(String.valueOf(BigDecimal.ZERO));
@@ -1632,9 +1683,9 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
 
                 });
             } else if (i == 3) {
-                //退款数
+                // 退款数
                 dateList.forEach(d -> {
-                    //每日数据填充
+                    // 每日数据填充
                     DeviceDataDto.Vo deviceData = dataDayMap.get(d);
                     if (deviceData == null) {
                         data.add("0");
@@ -1668,7 +1719,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         }
         String startTime = choosDate + " 00:00:00";
         String endTime = choosDate + " 23:59:59";
-        //查询选定日期的温度数据
+        // 查询选定日期的温度数据
         List<DeviceTempRecords> deviceTempRecords = deviceTempRecordsService.list(Wrappers.<DeviceTempRecords>lambdaQuery()
                 .eq(DeviceTempRecords::getDeviceId, deviceId).between(DeviceTempRecords::getCreateTime, startTime, endTime)
                 .orderBy(true, true, DeviceTempRecords::getCreateTime));
@@ -1715,7 +1766,7 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         }
         String startTime = choosDate + " 00:00:00";
         String endTime = choosDate + " 23:59:59";
-        //查询选定日期的温度数据
+        // 查询选定日期的温度数据
         List<DeviceNetRecord> deviceNetRecords = deviceNetRecordService.list(Wrappers.<DeviceNetRecord>lambdaQuery()
                 .eq(DeviceNetRecord::getDeviceId, deviceId).between(DeviceNetRecord::getCreateTime, startTime, endTime)
                 .orderBy(true, true, DeviceNetRecord::getCreateTime));
@@ -1758,8 +1809,8 @@ public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoMapper, DeviceI
         Long deviceId = dto.getDeviceId();
         DeviceInfoDto.DeviceDataCountVO vo = new DeviceInfoDto.DeviceDataCountVO();
         DeviceInfoDto.GoodsData goodsData = new DeviceInfoDto.GoodsData();
-        //在售商品种类
-        //根据设备ID查商品id
+        // 在售商品种类
+        // 根据设备ID查商品id
         GoodsDeviceDto.SelectList selectList = new GoodsDeviceDto.SelectList();
         selectList.setDeviceIds(CollUtil.newArrayList(deviceId));
         selectList.setMercId(dto.getMercId());

+ 177 - 11
device-api-service/src/main/java/com/xy/service/DeviceSimChargeServiceImpl.java

@@ -1,5 +1,7 @@
 package com.xy.service;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
 import com.alibaba.excel.annotation.ExcelProperty;
 import com.alibaba.excel.annotation.write.style.ColumnWidth;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -11,10 +13,14 @@ import com.xy.collections.list.JArrayList;
 import com.xy.collections.list.JList;
 import com.xy.config.DeviceThreadPoolConfig;
 import com.xy.config.FileConfig;
+import com.xy.device.EnumSimConfig;
 import com.xy.dto.DeviceSimChargeDto;
+import com.xy.dto.MercFeeConfigDto;
 import com.xy.dto.OrderMercManageDto;
 import com.xy.dto.be.MercDto;
+import com.xy.entity.DeviceSim;
 import com.xy.entity.DeviceSimCharge;
+import com.xy.entity.SysDictRedis;
 import com.xy.mapper.DeviceSimChargeMapper;
 import com.xy.service.be.MercService;
 import com.xy.util.ExcelUtils;
@@ -33,8 +39,12 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.File;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import static com.xy.utils.Beans.copy;
 import static com.xy.utils.PlusBeans.toIPage;
@@ -64,6 +74,11 @@ public class DeviceSimChargeServiceImpl extends ServiceImpl<DeviceSimChargeMappe
 
     private FileConfig fileConfig;
 
+    private MercFeeConfigService mercFeeConfigService;
+
+    private DeviceSimServiceImpl deviceSimService;
+
+
     @PostMapping("page")
     @ApiOperation("分页查询")
     public R<PageBean<DeviceSimChargeDto.Vo>> page(@RequestBody DeviceSimChargeDto.Page page) {
@@ -81,17 +96,168 @@ public class DeviceSimChargeServiceImpl extends ServiceImpl<DeviceSimChargeMappe
                     .target(() -> orderMercManageService.list(new OrderMercManageDto.SelectList().setId(new JArrayList<>(records).getProperty(DeviceSimChargeDto.Vo::getOrderId))).getData()
                             , DeviceSimChargeDto.Vo::getOrderId, DeviceSimChargeDto.Vo::getFiles, OrderMercManageDto.Vo::getId, OrderMercManageDto.Vo::getFiles
                     ).target(() -> mercService.list(new MercDto.SelectList().setMercIds(new JArrayList<>(records).getProperty(DeviceSimChargeDto.Vo::getMercId).comparing())).getData()
-                    , DeviceSimChargeDto.Vo::getMercId, DeviceSimChargeDto.Vo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
+                            , DeviceSimChargeDto.Vo::getMercId, DeviceSimChargeDto.Vo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
+                    .builder();
+        }
+        return R.ok(voPageBean);
+    }
+
+    public R<PageBean<DeviceSimChargeDto.PageByTopMercVO>> pageByTopMerc(DeviceSimChargeDto.PageByTopMerc page) {
+        Long curMercId = page.getCurMercId();
+        Long chooseMercId = page.getChooseMercId();
+        List<Long> mercIds = new ArrayList<>();
+        if (chooseMercId == null) {
+            mercIds = R.feignCheckData(mercService.getChildMercIds(new MercDto.QuerySubDTO().setParentMercID(curMercId)));
+        } else {
+            // 指定商户ID
+            mercIds.add(chooseMercId);
+        }
+        if (CollUtil.isEmpty(mercIds)) {
+            return R.ok();
+        }
+        PageBean pageBean = page.getPage();
+        LambdaQueryWrapper<DeviceSimCharge> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, DeviceSimCharge.class)
+                .ge(DeviceSimCharge::getCreateTime, page.getBeginCreateTime())
+                .le(DeviceSimCharge::getCreateTime, page.getEndCreateTime())
+                .in(DeviceSimCharge::getMercId, mercIds)
+                .build()
+                .orderByDesc(!Emptys.check(pageBean.getOrders()), DeviceSimCharge::getCreateTime);
+        IPage<DeviceSimCharge> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
+        PageBean<DeviceSimChargeDto.PageByTopMercVO> voPageBean = toPageBean(DeviceSimChargeDto.PageByTopMercVO.class, iPage);
+        List<DeviceSimChargeDto.PageByTopMercVO> records = voPageBean.getRecords();
+
+        if (Emptys.check(records)) {
+            // 佣金配置查询
+            List<MercFeeConfigDto.ListFeeConfigByMercVO> feeConfigByMercVOS = R.feignCheckData(mercFeeConfigService.listFeeConfigByMerc(new MercFeeConfigDto.ListFeeConfigByMercDTO().setMercId(curMercId)));
+            Map<Long, MercFeeConfigDto.ListFeeConfigByMercVO> configByMercVOMap = MapUtil.newHashMap();
+            if (CollUtil.isNotEmpty(feeConfigByMercVOS)) {
+                configByMercVOMap = feeConfigByMercVOS.stream().collect(Collectors.toMap(MercFeeConfigDto.ListFeeConfigByMercVO::getMercId, f -> f));
+            }
+            copy(records)
+                    .target(() -> orderMercManageService.list(new OrderMercManageDto.SelectList().setId(new JArrayList<>(records).getProperty(DeviceSimChargeDto.PageByTopMercVO::getOrderId))).getData()
+                            , DeviceSimChargeDto.PageByTopMercVO::getOrderId, DeviceSimChargeDto.PageByTopMercVO::getFiles, OrderMercManageDto.Vo::getId, OrderMercManageDto.Vo::getFiles
+                    ).target(() -> mercService.list(new MercDto.SelectList().setMercIds(new JArrayList<>(records).getProperty(DeviceSimChargeDto.PageByTopMercVO::getMercId).comparing())).getData()
+                            , DeviceSimChargeDto.PageByTopMercVO::getMercId, DeviceSimChargeDto.PageByTopMercVO::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
+                    .builder();
+            List<String> simIds = records.stream().map(DeviceSimChargeDto.PageByTopMercVO::getSimId).collect(Collectors.toList());
+            List<DeviceSim> deviceSims = deviceSimService.listByIds(simIds);
+            Map<String, DeviceSim> deviceSimMap = MapUtil.newHashMap();
+            if (CollUtil.isNotEmpty(deviceSims)) {
+                deviceSimMap = deviceSims.stream().collect(Collectors.toMap(DeviceSim::getId, ds -> ds));
+            }
+            Map<String, SysDictRedis> simConfig = SysDictUtils.get(EnumSimConfig.Code.CODE.getCode());
+
+            Integer value = Integer.valueOf(simConfig.get(EnumSimConfig.N_200.getCode()).getValue());
+
+            for (DeviceSimChargeDto.PageByTopMercVO record : records) {
+                Long mercId = record.getMercId();
+                String simId = record.getSimId();
+                // 佣金初始化
+                Integer extraMoney = 0;
+                MercFeeConfigDto.ListFeeConfigByMercVO listFeeConfigByMercVO = configByMercVOMap.get(mercId);
+                if (listFeeConfigByMercVO != null) {
+                    extraMoney = listFeeConfigByMercVO.getFeeConfig().getFeeSimcard();
+                    record.setAgentMoney(extraMoney);
+                }
+                DeviceSim sim = deviceSimMap.get(simId);
+                // 封装过期状态说明
+                if (Emptys.check(sim)) {
+                    LocalDateTime timeout = sim.getTimeout();
+                    if (timeout == null) {
+                        record.setTimeoutStatus("未初始化");
+                    } else {
+                        String timeoutStatus;
+                        long s = DataTime.diff(LocalDateTime.now(), timeout, "s");
+                        if (s <= 0) {
+                            timeoutStatus = "欠费(" + (~(s / 86400 - 1)) + "天)";
+                        } else {
+                            timeoutStatus = s <= value * 86400 ? "即将到期(" + s / 86400 + "天)" : "正常(" + s / 86400 + "天)";
+                        }
+                        record.setTimeoutStatus(timeoutStatus);
+                    }
+                    record.setTimeout(timeout);
+                }
+
+            }
+        }
+        return R.ok(voPageBean);
+
+    }
+
+    /**
+     * 财务管理-支出管理-流量卡费明细
+     *
+     * @param page
+     * @return
+     */
+
+    public R<PageBean<DeviceSimChargeDto.MySpendPageVO>> mySpendPage(DeviceSimChargeDto.PageByTopMerc page) {
+        Long curMercId = page.getCurMercId();
+        List<Long> mercIds = new ArrayList<>();
+        // 指定商户ID
+        mercIds.add(curMercId);
+        PageBean pageBean = page.getPage();
+        LambdaQueryWrapper<DeviceSimCharge> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, DeviceSimCharge.class)
+                .ge(DeviceSimCharge::getCreateTime, page.getBeginCreateTime())
+                .le(DeviceSimCharge::getCreateTime, page.getEndCreateTime())
+                .in(DeviceSimCharge::getMercId, mercIds)
+                .build()
+                .orderByDesc(!Emptys.check(pageBean.getOrders()), DeviceSimCharge::getCreateTime);
+        IPage<DeviceSimCharge> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
+        PageBean<DeviceSimChargeDto.MySpendPageVO> voPageBean = toPageBean(DeviceSimChargeDto.MySpendPageVO.class, iPage);
+        List<DeviceSimChargeDto.MySpendPageVO> records = voPageBean.getRecords();
+
+        if (Emptys.check(records)) {
+            copy(records)
+                    .target(() -> orderMercManageService.list(new OrderMercManageDto.SelectList().setId(new JArrayList<>(records).getProperty(DeviceSimChargeDto.MySpendPageVO::getOrderId))).getData()
+                            , DeviceSimChargeDto.MySpendPageVO::getOrderId, DeviceSimChargeDto.MySpendPageVO::getFiles, OrderMercManageDto.Vo::getId, OrderMercManageDto.Vo::getFiles
+                    ).target(() -> mercService.list(new MercDto.SelectList().setMercIds(new JArrayList<>(records).getProperty(DeviceSimChargeDto.MySpendPageVO::getMercId).comparing())).getData()
+                            , DeviceSimChargeDto.MySpendPageVO::getMercId, DeviceSimChargeDto.MySpendPageVO::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
                     .builder();
+            List<String> simIds = records.stream().map(DeviceSimChargeDto.MySpendPageVO::getSimId).collect(Collectors.toList());
+            List<DeviceSim> deviceSims = deviceSimService.listByIds(simIds);
+            Map<String, DeviceSim> deviceSimMap = MapUtil.newHashMap();
+            if (CollUtil.isNotEmpty(deviceSims)) {
+                deviceSimMap = deviceSims.stream().collect(Collectors.toMap(DeviceSim::getId, ds -> ds));
+            }
+            Map<String, SysDictRedis> simConfig = SysDictUtils.get(EnumSimConfig.Code.CODE.getCode());
+
+            Integer value = Integer.valueOf(simConfig.get(EnumSimConfig.N_200.getCode()).getValue());
+
+            for (DeviceSimChargeDto.MySpendPageVO record : records) {
+                Long mercId = record.getMercId();
+                String simId = record.getSimId();
+                DeviceSim sim = deviceSimMap.get(simId);
+                // 封装过期状态说明
+                if (Emptys.check(sim)) {
+                    LocalDateTime timeout = sim.getTimeout();
+                    if (timeout == null) {
+                        record.setTimeoutStatus("未初始化");
+                    } else {
+                        String timeoutStatus;
+                        long s = DataTime.diff(LocalDateTime.now(), timeout, "s");
+                        if (s <= 0) {
+                            timeoutStatus = "欠费(" + (~(s / 86400 - 1)) + "天)";
+                        } else {
+                            timeoutStatus = s <= value * 86400 ? "即将到期(" + s / 86400 + "天)" : "正常(" + s / 86400 + "天)";
+                        }
+                        record.setTimeoutStatus(timeoutStatus);
+                    }
+                    record.setTimeout(timeout);
+                }
+
+            }
         }
         return R.ok(voPageBean);
+
     }
 
+
     @ApiOperation("月统计分页")
     @PostMapping("moonCountPage")
     public R<PageBean<DeviceSimChargeDto.MoonCountVo>> moonCountPage(@RequestBody DeviceSimChargeDto.MoonCountPage moonCountPage) {
         JList<DeviceSimChargeDto.MoonCountVo> moonCountVos = new JArrayList<>();
-        //查询数据
+        // 查询数据
         List<String> attrNames = Arrays.asList(
                 LambdaUtils.getUnderlineCaseName(DeviceSimCharge::getMercId)
         );
@@ -119,9 +285,9 @@ public class DeviceSimChargeServiceImpl extends ServiceImpl<DeviceSimChargeMappe
                     .setMoney(deviceSimCharge.getMoney());
             moonCountVos.add(moonCountVo);
         });
-        //翻译商户名称
+        // 翻译商户名称
         Beans.copy(moonCountVos).target(() -> mercService.list(new MercDto.SelectList().setMercIds(moonCountVos.getProperty(DeviceSimChargeDto.MoonCountVo::getMercId).comparing())).getData(),
-                DeviceSimChargeDto.MoonCountVo::getMercId, DeviceSimChargeDto.MoonCountVo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
+                        DeviceSimChargeDto.MoonCountVo::getMercId, DeviceSimChargeDto.MoonCountVo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
                 .builder();
         PageBean<DeviceSimChargeDto.MoonCountVo> pageBean = new PageBean<DeviceSimChargeDto.MoonCountVo>()
                 .setCurrent(iPage.getCurrent())
@@ -135,7 +301,7 @@ public class DeviceSimChargeServiceImpl extends ServiceImpl<DeviceSimChargeMappe
     @PostMapping("moonCount")
     public R<List<DeviceSimChargeDto.MoonCountVo>> moonCount(@RequestBody DeviceSimChargeDto.MoonCount moonCount) {
         JList<DeviceSimChargeDto.MoonCountVo> moonCountVos = new JArrayList<>();
-        //查询数据
+        // 查询数据
         List<String> attrNames = Arrays.asList(
                 LambdaUtils.getUnderlineCaseName(DeviceSimCharge::getMercId),
                 "DATE_FORMAT(" + LambdaUtils.getUnderlineCaseName(DeviceSimCharge::getCreateTime) + ", '%Y-%m')"
@@ -165,9 +331,9 @@ public class DeviceSimChargeServiceImpl extends ServiceImpl<DeviceSimChargeMappe
             });
         }));
         execute.end();
-        //翻译商户名称
+        // 翻译商户名称
         Beans.copy(moonCountVos).target(() -> mercService.list(new MercDto.SelectList().setMercIds(moonCountVos.getProperty(DeviceSimChargeDto.MoonCountVo::getMercId).comparing())).getData(),
-                DeviceSimChargeDto.MoonCountVo::getMercId, DeviceSimChargeDto.MoonCountVo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
+                        DeviceSimChargeDto.MoonCountVo::getMercId, DeviceSimChargeDto.MoonCountVo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
                 .builder();
         return R.ok(moonCountVos.desc(DeviceSimChargeDto.MoonCountVo::getDate));
     }
@@ -176,7 +342,7 @@ public class DeviceSimChargeServiceImpl extends ServiceImpl<DeviceSimChargeMappe
     @ApiOperation("月统计导出")
     @PostMapping("moonCountDownload")
     public void moonCountDownload(@RequestBody DeviceSimChargeDto.MoonCount moonCount) {
-        //生成excel
+        // 生成excel
         String name = YitIdHelper.nextId() + ".xlsx";
         String path = fileConfig.getPath() + File.separator + name;
         ExcelUtils.SheetAndData<MoonCountData> sheetAndData = ExcelUtils.create(path, MoonCountData.class);
@@ -187,7 +353,7 @@ public class DeviceSimChargeServiceImpl extends ServiceImpl<DeviceSimChargeMappe
             }
             return Beans.copy(MoonCountData.class, data);
         }).builder();
-        //下载文件
+        // 下载文件
         InputStream inputStream = IoUtils.inputStream(path).get();
         response.setHeader("Content-Disposition", "attachment; filename=" + "设备管理费月统计数据.xlsx");
         response.setContentType("application/xlsx");
@@ -199,7 +365,7 @@ public class DeviceSimChargeServiceImpl extends ServiceImpl<DeviceSimChargeMappe
         }
         inputStream.close();
         outputStream.close();
-        //删除文件
+        // 删除文件
         new File(path).delete();
     }
 
@@ -227,4 +393,4 @@ public class DeviceSimChargeServiceImpl extends ServiceImpl<DeviceSimChargeMappe
         @ExcelProperty(value = "续费金额")
         private Integer money;
     }
-}
+}

+ 42 - 26
device-api-service/src/main/java/com/xy/service/DeviceSimServiceImpl.java

@@ -18,10 +18,13 @@ import com.xy.config.FileConfig;
 import com.xy.device.EnumDeviceChargingHistoryStatus;
 import com.xy.device.EnumSimConfig;
 import com.xy.dto.DeviceSimDto;
+import com.xy.dto.MercFeeConfigAlgorithmTypeDto;
+import com.xy.dto.MercFeeConfigSimCardDto;
 import com.xy.entity.DeviceSim;
 import com.xy.entity.DeviceSimCharge;
 import com.xy.entity.SysDictRedis;
 import com.xy.mapper.DeviceSimMapper;
+import com.xy.service.be.MercService;
 import com.xy.util.ExcelUtils;
 import com.xy.utils.*;
 import io.swagger.annotations.Api;
@@ -31,6 +34,7 @@ import lombok.Data;
 import lombok.RequiredArgsConstructor;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -63,7 +67,7 @@ import static com.xy.utils.PlusBeans.toPageBean;
  * @since 2023-10-16
  */
 @Service
-@AllArgsConstructor
+@AllArgsConstructor(onConstructor_ = @Lazy)
 @Api(tags = "设备流量卡")
 public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim> implements DeviceSimService {
 
@@ -73,6 +77,10 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
 
     private FileConfig fileConfig;
 
+    private MercFeeConfigSimCardServiceImpl mercFeeConfigSimCardService;
+
+    private MercService mercService;
+
 
     @PostMapping("countWaitHandle")
     @ApiOperation("抄送流量卡-运营首页概况")
@@ -108,16 +116,16 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
     @Override
     @ApiOperation("购买回调")
     public R payNotice(DeviceSimDto.PayNotice payNotice) {
-        //查询设备流量卡充值表
+        // 查询设备流量卡充值表
         List<DeviceSimCharge> list = deviceSimChargeService.list(new LambdaQueryWrapper<DeviceSimCharge>().eq(DeviceSimCharge::getOrderId, payNotice.getOrderId()));
         if (!Emptys.check(list)) {
             return R.ok();
         }
-        //查询设备流量卡
+        // 查询设备流量卡
         JList<DeviceSimCharge> deviceSimCharges = new JArrayList<>(list);
         JMap<String, DeviceSimCharge> deviceSimChargesJMaps = deviceSimCharges.toMap(DeviceSimCharge::getSimId).cover();
         List<DeviceSim> deviceSims = listByIds(deviceSimCharges.getProperty(DeviceSimCharge::getSimId));
-        //循环处理
+        // 循环处理
         LocalDateTime now = LocalDateTime.now();
         deviceSims.forEach(deviceSim -> {
             DeviceSimCharge deviceSimCharge = deviceSimChargesJMaps.get(deviceSim.getId());
@@ -132,9 +140,9 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
                     .setLastRenewalTime(now)
                     .setUpdateTime(now);
         });
-        //修改设备流量卡信息
+        // 修改设备流量卡信息
         updateBatchById(deviceSims);
-        //修改设备流量卡充值
+        // 修改设备流量卡充值
         Integer status = SysDictUtils.getValue(EnumDeviceChargingHistoryStatus.Code.CODE.getCode(), EnumDeviceChargingHistoryStatus.N_2.getCode(), Integer.class);
         deviceSimCharges.forEach(deviceSimCharge -> deviceSimCharge.setStatus(status).setUpdateTime(now));
         deviceSimChargeService.updateBatchById(deviceSimCharges);
@@ -164,10 +172,14 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
         IPage<DeviceSimDto.PageVo> iPage = baseMapper.page(toIPage(page.getPage()), page);
         List<DeviceSimDto.PageVo> records = iPage.getRecords();
         if (Emptys.check(records)) {
-            String name = simConfig.get(EnumSimConfig.name.getCode()).getValue();
-            Integer money = Integer.valueOf(simConfig.get(EnumSimConfig.money.getCode()).getValue());
+//            String name = simConfig.get(EnumSimConfig.name.getCode()).getValue();
+//            Integer money = Integer.valueOf(simConfig.get(EnumSimConfig.money.getCode()).getValue());
+            List<MercFeeConfigSimCardDto.DeviceSimPayVO> deviceSimPayVOS = R.feignCheckData(mercFeeConfigSimCardService.paySimCardFee(new MercFeeConfigAlgorithmTypeDto.SimPayQueryDTO().setMercId(page.getMercId())));
+            MercFeeConfigSimCardDto.DeviceSimPayVO deviceSimPayVO = deviceSimPayVOS.get(0);
+            String name = deviceSimPayVO.getName();
+            Integer money = deviceSimPayVO.getMoney();
             records.forEach(record -> {
-                //封装过期状态说明
+                // 封装过期状态说明
                 DeviceSimDto.Vo sim = record.getSim();
                 if (Emptys.check(sim)) {
                     LocalDateTime timeout = sim.getTimeout();
@@ -184,7 +196,7 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
                         record.getSim().setTimeoutStatus(timeoutStatus);
                     }
                 }
-                //封装计费标准
+                // 封装计费标准
                 record.setChargingName(name).setChargingMoney(money);
             });
         }
@@ -194,14 +206,18 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
     @PostMapping("pageByNotInit")
     @ApiOperation("未初始化分页查询")
     public R<PageBean<DeviceSimDto.PageVo>> pageByNotInit(@RequestBody DeviceSimDto.Page page) {
-        Map<String, SysDictRedis> simConfig = SysDictUtils.get(EnumSimConfig.Code.CODE.getCode());
+//        Map<String, SysDictRedis> simConfig = SysDictUtils.get(EnumSimConfig.Code.CODE.getCode());
         IPage<DeviceSimDto.PageVo> iPage = baseMapper.page2(toIPage(page.getPage()), page);
         List<DeviceSimDto.PageVo> records = iPage.getRecords();
         if (Emptys.check(records)) {
-            String name = simConfig.get(EnumSimConfig.name.getCode()).getValue();
-            Integer money = Integer.valueOf(simConfig.get(EnumSimConfig.money.getCode()).getValue());
+//            String name = simConfig.get(EnumSimConfig.name.getCode()).getValue();
+//            Integer money = Integer.valueOf(simConfig.get(EnumSimConfig.money.getCode()).getValue());
+            List<MercFeeConfigSimCardDto.DeviceSimPayVO> deviceSimPayVOS = R.feignCheckData(mercFeeConfigSimCardService.paySimCardFee(new MercFeeConfigAlgorithmTypeDto.SimPayQueryDTO().setMercId(page.getMercId())));
+            MercFeeConfigSimCardDto.DeviceSimPayVO deviceSimPayVO = deviceSimPayVOS.get(0);
+            String name = deviceSimPayVO.getName();
+            Integer money = deviceSimPayVO.getMoney();
             records.forEach(record -> {
-                //封装计费标准
+                // 封装计费标准
                 record.setChargingName(name).setChargingMoney(money);
             });
         }
@@ -214,17 +230,17 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
         Map<String, SysDictRedis> simConfig = SysDictUtils.get(EnumSimConfig.Code.CODE.getCode());
         Integer value = Integer.valueOf(simConfig.get(EnumSimConfig.N_200.getCode()).getValue());
         String theTime = DataTime.getStringAround(0, 0, value, 0, 0, 0);
-        //并行数据
+        // 并行数据
         DeviceSimDto.PageCountVo pageCountVo = new DeviceSimDto.PageCountVo();
         ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, 6)
                 .execute(() -> {
-                    //全部
+                    // 全部
                     DeviceSimDto.PageCount paramsObj = Beans.copy(DeviceSimDto.PageCount.class, pageCount);
                     int count = baseMapper.pageCount(paramsObj);
                     pageCountVo.setAllCount(count);
                 })
                 .execute(() -> {
-                    //即将过期
+                    // 即将过期
                     DeviceSimDto.PageCount paramsObj = Beans.copy(DeviceSimDto.PageCount.class, pageCount)
                             .setChargingStatus(1)
                             .setThisTime(LocalDateTime.now())
@@ -233,7 +249,7 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
                     pageCountVo.setBeTimeoutCount(count);
                 })
                 .execute(() -> {
-                    //已过期
+                    // 已过期
                     DeviceSimDto.PageCount paramsObj = Beans.copy(DeviceSimDto.PageCount.class, pageCount)
                             .setChargingStatus(2)
                             .setThisTime(LocalDateTime.now())
@@ -242,21 +258,21 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
                     pageCountVo.setTimeoutCount(count);
                 })
                 .execute(() -> {
-                    //已激活
+                    // 已激活
                     DeviceSimDto.PageCount paramsObj = Beans.copy(DeviceSimDto.PageCount.class, pageCount)
                             .setIsActivate(true);
                     int count = baseMapper.pageCount(paramsObj);
                     pageCountVo.setIsActivate(count);
                 })
                 .execute(() -> {
-                    //未激活
+                    // 未激活
                     DeviceSimDto.PageCount paramsObj = Beans.copy(DeviceSimDto.PageCount.class, pageCount)
                             .setIsActivate(false);
                     int count = baseMapper.pageCount(paramsObj);
                     pageCountVo.setIsNotActivate(count);
                 })
                 .execute(() -> {
-                    //未初始化
+                    // 未初始化
                     DeviceSimDto.PageCount paramsObj = Beans.copy(DeviceSimDto.PageCount.class, pageCount);
                     int count = baseMapper.pageCount2(paramsObj);
                     pageCountVo.setNotInitCount(count);
@@ -269,12 +285,12 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
     @ApiOperation("导出流量卡数据")
     @PostMapping("download")
     public void download(@RequestBody DeviceSimDto.Download download) {
-        //生成excel
+        // 生成excel
         String name = YitIdHelper.nextId() + ".xlsx";
         String path = fileConfig.getPath() + File.separator + name;
         ExcelUtils.SheetAndData<UploadSim> sheetAndData = ExcelUtils.create(path, UploadSim.class);
         sheetAndData.sheet("流量卡数据", () -> {
-            //生成导出数据
+            // 生成导出数据
             List<DeviceSimDto.PageVo> pageVos;
             if (download.getIsNotInit()) {
                 pageVos = baseMapper.page2(download);
@@ -300,7 +316,7 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
                 }
                 uploadSims.add(uploadSim);
             });
-            //修改批次号
+            // 修改批次号
             String updateBatchNo = download.getUpdateBatchNo();
             Boolean isUpdateBatchNo = download.getIsUpdateBatchNo();
             if (Emptys.check(updateBatchNo) && Emptys.check(isUpdateBatchNo) && isUpdateBatchNo) {
@@ -318,7 +334,7 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
             }
             return uploadSims;
         }).builder();
-        //下载文件
+        // 下载文件
         InputStream inputStream = IoUtils.inputStream(path).get();
         response.setHeader("Content-Disposition", "attachment; filename=" + "sim_data.xlsx");
         response.setContentType("application/xlsx");
@@ -330,7 +346,7 @@ public class DeviceSimServiceImpl extends ServiceImpl<DeviceSimMapper, DeviceSim
         }
         inputStream.close();
         outputStream.close();
-        //删除文件
+        // 删除文件
         new File(path).delete();
     }
 

+ 107 - 3
device-api-service/src/main/java/com/xy/service/DeviceTypeAlgorithmBeforConfigServiceImpl.java

@@ -1,14 +1,27 @@
 package com.xy.service;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.xy.annotation.LogOperate;
+import com.xy.device.EnumAlgorithmPayConfig;
+import com.xy.device.EnumAlgorithmTypes;
+import com.xy.dto.AlgorithmDto;
+import com.xy.dto.DeviceAlgorithmChargingDto;
 import com.xy.dto.DeviceTypeAlgorithmBeforConfigDto;
+import com.xy.dto.be.MercDto;
 import com.xy.entity.DeviceTypeAlgorithmBeforConfig;
+import com.xy.entity.SysDictRedis;
+import com.xy.error.CommRuntimeException;
 import com.xy.mapper.DeviceTypeAlgorithmBeforConfigMapper;
+import com.xy.service.be.MercService;
 import com.xy.utils.Emptys;
 import com.xy.utils.MybatisPlusQuery;
 import com.xy.utils.R;
+import com.xy.utils.SysDictUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
@@ -18,7 +31,11 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 
 import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import static com.xy.utils.Beans.copy;
 
@@ -36,10 +53,18 @@ import static com.xy.utils.Beans.copy;
 @Api(tags = "设备类型算法预充配置")
 public class DeviceTypeAlgorithmBeforConfigServiceImpl extends ServiceImpl<DeviceTypeAlgorithmBeforConfigMapper, DeviceTypeAlgorithmBeforConfig> implements DeviceTypeAlgorithmBeforConfigService {
 
+    private AlgorithmService algorithmService;
+    private MercService mercService;
+    private DeviceAlgorithmChargingServiceImpl deviceAlgorithmChargingService;
+
     @Override
     @ApiOperation("对象查询")
     public R<DeviceTypeAlgorithmBeforConfigDto.Vo> obj(@RequestBody DeviceTypeAlgorithmBeforConfigDto.Vo vo) {
+        MercDto.Vo merc = R.feignCheckData(mercService.obj(new MercDto.Vo().setId(vo.getMercId())));
+        List<String> mercCodes = new ArrayList<>();
+        deviceAlgorithmChargingService.getMercCodes(merc.getMercCode(), mercCodes);
         DeviceTypeAlgorithmBeforConfigDto.SelectList selectList = copy(DeviceTypeAlgorithmBeforConfigDto.SelectList.class, vo);
+        selectList.setMercCodes(mercCodes);
         List<DeviceTypeAlgorithmBeforConfigDto.Vo> list = list(selectList).getData();
         if (Emptys.check(list)) {
             return R.ok(list.get(0));
@@ -50,19 +75,98 @@ public class DeviceTypeAlgorithmBeforConfigServiceImpl extends ServiceImpl<Devic
     @PostMapping("list")
     @ApiOperation("集合查询")
     public R<List<DeviceTypeAlgorithmBeforConfigDto.Vo>> list(@RequestBody DeviceTypeAlgorithmBeforConfigDto.SelectList selectList) {
-        LambdaQueryWrapper<DeviceTypeAlgorithmBeforConfig> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, DeviceTypeAlgorithmBeforConfig.class).build();
+        List<String> mercCodes = selectList.getMercCodes();
+        if (CollUtil.isNotEmpty(mercCodes)) {
+            // 优先编码查询
+            selectList.setMercId(null);
+        }
+        LambdaQueryWrapper<DeviceTypeAlgorithmBeforConfig> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, DeviceTypeAlgorithmBeforConfig.class).build()
+                .in(CollUtil.isNotEmpty(mercCodes), DeviceTypeAlgorithmBeforConfig::getMercCode, mercCodes);
         List<DeviceTypeAlgorithmBeforConfig> list = list(lambdaQueryWrapper);
         return R.ok(copy(DeviceTypeAlgorithmBeforConfigDto.Vo.class, list));
     }
 
+    @PostMapping("deviceActiveFeeList")
+    @ApiOperation("费用管理-设备激活费用查询")
+    public R<DeviceTypeAlgorithmBeforConfigDto.DeviceActiveFeeVO> deviceActiveFeeList(@RequestBody DeviceTypeAlgorithmBeforConfigDto.DeviceActiveFeeDTO dto) {
+        DeviceTypeAlgorithmBeforConfigDto.DeviceActiveFeeVO vo = new DeviceTypeAlgorithmBeforConfigDto.DeviceActiveFeeVO();
+        Long mercId = dto.getMercId();
+        LambdaQueryWrapper<DeviceTypeAlgorithmBeforConfig> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(dto, DeviceTypeAlgorithmBeforConfig.class).build();
+        List<DeviceTypeAlgorithmBeforConfig> list = list(lambdaQueryWrapper);
+        // 查询默认算法信息
+        List<AlgorithmDto.ListNameId> listNameIds = R.feignCheckData(algorithmService.ListNameId());
+        List<Long> algorithmIds = listNameIds.stream().map(AlgorithmDto.ListNameId::getId).collect(Collectors.toList());
+        Map<Long, String> agMap = listNameIds.stream().collect(Collectors.toMap(AlgorithmDto.ListNameId::getId, AlgorithmDto.ListNameId::getName));
+//        Map<Long, String> moonAlgorithmTypesMap = new HashMap<>();
+        Map<Long, String> algorithmPayConfigMap = new HashMap<>();
+        for (Long algorithmId : algorithmIds) {
+            SysDictRedis moonAlgorithmTypes = SysDictUtils.get(EnumAlgorithmTypes.Code.CODE.getCode(), String.valueOf(algorithmId));
+            // 算法类型对应的字典配置的默认激活费(无设备类型)
+            SysDictRedis algorithmPayConfig = SysDictUtils.get(EnumAlgorithmPayConfig.Code.CODE.getCode(), String.valueOf(algorithmId));
+//            if (Emptys.check(moonAlgorithmTypes)) {
+//                moonAlgorithmTypesMap.put(algorithmId, moonAlgorithmTypes.getMsg());
+//            }
+            if (Emptys.check(algorithmPayConfig)) {
+                algorithmPayConfigMap.put(algorithmId, algorithmPayConfig.getValue());
+            }
+        }
+
+
+        // 字典默认配置
+        List<DeviceTypeAlgorithmBeforConfigDto.DeviceActiveDictVO> deviceActiveDicts = new ArrayList<>();
+
+        for (Long algorithmId : algorithmIds) {
+            String algorithmName = agMap.get(algorithmId);
+            String algorithmPayConfig = algorithmPayConfigMap.get(algorithmId);
+            DeviceAlgorithmChargingDto.AlgorithmMoonConfig algorithmMoonConfig = JSONUtil.parseObj(algorithmPayConfig).toBean(DeviceAlgorithmChargingDto.AlgorithmMoonConfig.class);
+            DeviceAlgorithmChargingDto.AlgorithmMoonConfig.Inf inf = algorithmMoonConfig.getInf();
+            Integer money = inf.getMoney();
+            DeviceTypeAlgorithmBeforConfigDto.DeviceActiveDictVO dictVO = new DeviceTypeAlgorithmBeforConfigDto.DeviceActiveDictVO();
+            dictVO.setAlgorithmId(algorithmId);
+            dictVO.setAlgorithmName(algorithmName);
+            dictVO.setMoney(money);
+            dictVO.setSize(inf.getSize());
+            deviceActiveDicts.add(dictVO);
+        }
+        // 平台给商家定义的配置
+        List<DeviceTypeAlgorithmBeforConfigDto.DeviceActiveMercFeeVO> deviceActiveMercFees = new ArrayList<>();
+        if (CollUtil.isNotEmpty(list)) {
+            // 平台给商家自定义的设备激活费用,多了个设备类型
+            BeanUtil.copyToList(list, DeviceTypeAlgorithmBeforConfigDto.DeviceActiveMercFeeVO.class);
+            for (DeviceTypeAlgorithmBeforConfig db : list) {
+                DeviceTypeAlgorithmBeforConfigDto.DeviceActiveMercFeeVO dbData = new DeviceTypeAlgorithmBeforConfigDto.DeviceActiveMercFeeVO();
+                BeanUtil.copyProperties(db, dbData);
+                String algorithmName = agMap.get(db.getAlgorithmId());
+                dbData.setAlgorithmName(algorithmName);
+                deviceActiveMercFees.add(dbData);
+            }
+        }
+        vo.setDeviceActiveDicts(deviceActiveDicts);
+        vo.setDeviceActiveMercFees(deviceActiveMercFees);
+        return R.ok(vo);
+    }
+
     @LogOperate
     @PostMapping("save")
     @ApiOperation("添加")
     public R save(@RequestBody @Validated DeviceTypeAlgorithmBeforConfigDto.Save save) {
+        Integer deviceType = save.getDeviceType();
+        Long algorithmId = save.getAlgorithmId();
+        Long mercId = save.getMercId();
+        MercDto.Vo merc = R.feignCheckData(mercService.obj(new MercDto.Vo().setId(mercId)));
+        String mercCode = merc.getMercCode();
+        DeviceTypeAlgorithmBeforConfig dc = this.getOne(Wrappers.<DeviceTypeAlgorithmBeforConfig>lambdaQuery()
+                .eq(DeviceTypeAlgorithmBeforConfig::getMercId, mercId)
+                .eq(DeviceTypeAlgorithmBeforConfig::getAlgorithmId, algorithmId)
+                .eq(DeviceTypeAlgorithmBeforConfig::getDeviceType, deviceType)
+        );
+        if (dc != null) {
+            throw new CommRuntimeException("该类型配置已存在,请勿重复添加!");
+        }
         LocalDateTime now = LocalDateTime.now();
         DeviceTypeAlgorithmBeforConfig saveInfo = copy(DeviceTypeAlgorithmBeforConfig.class, save)
                 .setCreateTime(now)
-                .setUpdateTime(now);
+                .setUpdateTime(now).setMercCode(mercCode);
         save(saveInfo);
         return R.ok().setLogMsg(String.format("商户id:%s,算法id:%s,预充金额:%s", save.getMercId(), save.getAlgorithmId(), save.getMoney()));
     }
@@ -85,4 +189,4 @@ public class DeviceTypeAlgorithmBeforConfigServiceImpl extends ServiceImpl<Devic
         removeById(delete.getId());
         return R.ok();
     }
-}
+}

+ 37 - 0
device-api-service/src/main/java/com/xy/service/MercExtraFeeService.java

@@ -0,0 +1,37 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+import com.xy.dto.DeviceInfoDto;
+import com.xy.dto.MercFeeExtraDTO;
+import com.xy.utils.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import javax.validation.Valid;
+
+/**
+ * 商户扩展费用
+ *
+ * @author 谭斌
+ * @date 2024/04/15
+ */
+@Service
+@RequiredArgsConstructor
+@Api(tags = "商户扩展费用-各种类型")
+@RestMappingController("merc/fee/extra")
+public class MercExtraFeeService {
+
+    private final DeviceInfoServiceImpl deviceInfoService;
+
+    @ApiOperation("按类型获取费用")
+    @PostMapping("getByType")
+    public R getByType(@RequestBody @Valid MercFeeExtraDTO.Query q) {
+        return R.ok();
+    }
+
+
+}

+ 174 - 0
device-api-service/src/main/java/com/xy/service/MercFeeConfigAlgorithmTypeServiceImpl.java

@@ -0,0 +1,174 @@
+package com.xy.service;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.xy.device.EnumAlgorithmPayConfig;
+import com.xy.device.EnumAlgorithmTypes;
+import com.xy.device.EnumDeviceCharging;
+import com.xy.device.EnumDeviceChargingConfigType;
+import com.xy.dto.*;
+import com.xy.dto.be.MercDto;
+import com.xy.entity.DeviceChargingConfig;
+import com.xy.entity.DeviceTypeAlgorithmBeforConfig;
+import com.xy.entity.MercFeeConfigAlgorithmType;
+import com.xy.entity.SysDictRedis;
+import com.xy.error.CommRuntimeException;
+import com.xy.mapper.MercFeeConfigAlgorithmTypeMapper;
+import com.xy.service.MercFeeConfigAlgorithmTypeService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.service.be.MercService;
+import com.xy.utils.*;
+import io.swagger.annotations.ApiModelProperty;
+import org.springframework.stereotype.Service;
+import io.swagger.annotations.Api;
+import lombok.AllArgsConstructor;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.PostMapping;
+import io.swagger.annotations.ApiOperation;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springframework.validation.annotation.Validated;
+
+import static com.xy.utils.Beans.copy;
+import static com.xy.utils.PlusBeans.toIPage;
+import static com.xy.utils.PlusBeans.toPageBean;
+
+
+/**
+ * <p>
+ * 商户算法扣费标准配置扩展 服务实现类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+@Service
+@AllArgsConstructor
+@Api(tags = "商户算法扣费标准配置扩展")
+public class MercFeeConfigAlgorithmTypeServiceImpl extends ServiceImpl<MercFeeConfigAlgorithmTypeMapper, MercFeeConfigAlgorithmType> implements MercFeeConfigAlgorithmTypeService {
+
+    private MercService mercService;
+    private AlgorithmService algorithmService;
+
+    @PostMapping("obj")
+    @ApiOperation("对象查询")
+    public R<MercFeeConfigAlgorithmTypeDto.Vo> obj(@RequestBody MercFeeConfigAlgorithmTypeDto.Vo vo) {
+        MercFeeConfigAlgorithmTypeDto.SelectList selectList = copy(MercFeeConfigAlgorithmTypeDto.SelectList.class, vo);
+        List<MercFeeConfigAlgorithmTypeDto.Vo> list = list(selectList).getData();
+        if (Emptys.check(list)) {
+            return R.ok(list.get(0));
+        }
+        return R.ok();
+    }
+
+    @PostMapping("list")
+    @ApiOperation("集合查询")
+    public R<List<MercFeeConfigAlgorithmTypeDto.Vo>> list(@RequestBody MercFeeConfigAlgorithmTypeDto.SelectList selectList) {
+        LambdaQueryWrapper<MercFeeConfigAlgorithmType> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, MercFeeConfigAlgorithmType.class).build();
+        List<MercFeeConfigAlgorithmType> list = list(lambdaQueryWrapper);
+        return R.ok(copy(MercFeeConfigAlgorithmTypeDto.Vo.class, list));
+    }
+
+    @Override
+    @ApiOperation("设备算法费用配置查询")
+    public R<MercFeeConfigAlgorithmTypeDto.DeviceAlgorithmConfigVO> listByFeeConfig(@RequestBody @Validated MercFeeConfigAlgorithmTypeDto.ListByFeeConfigDTO dto) {
+        MercFeeConfigAlgorithmTypeDto.DeviceAlgorithmConfigVO data = new MercFeeConfigAlgorithmTypeDto.DeviceAlgorithmConfigVO();
+        Long mercId = dto.getMercId();
+        MercDto.Vo merc = R.feignCheckData(mercService.obj(new MercDto.Vo().setId(mercId)));
+
+        //查询默认算法信息
+        //算法费-平台默认配置
+        List<MercFeeConfigAlgorithmTypeDto.DeviceAlgorithmPlatformVO> deviceAcPlatformList = new ArrayList<>();
+        List<AlgorithmDto.ListNameId> listNameIds = R.feignCheckData(algorithmService.ListNameId());
+        List<Long> algorithmIds = listNameIds.stream().map(AlgorithmDto.ListNameId::getId).collect(Collectors.toList());
+//        Map<Long, String> agMap = listNameIds.stream().collect(Collectors.toMap(AlgorithmDto.ListNameId::getId, AlgorithmDto.ListNameId::getName));
+        Map<Long, String> algorithmPayConfigMap = new HashMap<>();
+        for (Long algorithmId : algorithmIds) {
+            SysDictRedis moonAlgorithmTypes = SysDictUtils.get(EnumAlgorithmTypes.Code.CODE.getCode(), String.valueOf(algorithmId));
+            //算法类型对应的字典配置的默认激活费(无设备类型)
+            SysDictRedis algorithmPayConfig = SysDictUtils.get(EnumAlgorithmPayConfig.Code.CODE.getCode(), String.valueOf(algorithmId));
+            if (Emptys.check(algorithmPayConfig)) {
+                MercFeeConfigAlgorithmTypeDto.DeviceAlgorithmPlatformVO dap = new MercFeeConfigAlgorithmTypeDto.DeviceAlgorithmPlatformVO();
+                dap.setAlgorithmId(algorithmId);
+                DeviceAlgorithmChargingDto.AlgorithmMoonConfig algorithmMoonConfig = JSONUtil.parseObj(algorithmPayConfig.getValue()).toBean(DeviceAlgorithmChargingDto.AlgorithmMoonConfig.class);
+//                DeviceAlgorithmChargingDto.AlgorithmMoonConfig.Inf inf = algorithmMoonConfig.getInf();
+                DeviceAlgorithmChargingDto.AlgorithmMoonConfig.Moon moon = algorithmMoonConfig.getMoon();
+                dap.setMoonMoney(moon.getMoney());
+                dap.setMoonSize(moon.getSize());
+                dap.setSingleMoney(algorithmMoonConfig.getPrice());
+                deviceAcPlatformList.add(dap);
+                algorithmPayConfigMap.put(algorithmId, algorithmPayConfig.getValue());
+            }
+        }
+
+        // 设备管理费-商家自定义费用
+        List<MercFeeConfigAlgorithmTypeDto.DeviceAlgorithmMercVO> deviceAcMercList = new ArrayList<>();
+        LambdaQueryWrapper<MercFeeConfigAlgorithmType> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(dto, MercFeeConfigAlgorithmType.class)
+                .in(MercFeeConfigAlgorithmType::getAlgorithmId, algorithmIds)
+                .eq(MercFeeConfigAlgorithmType::getMercCode, merc.getMercCode())
+                .build();
+        //默认配置 type 2预充 1赠送天数
+        List<MercFeeConfigAlgorithmType> list = list(lambdaQueryWrapper);
+        if (CollUtil.isNotEmpty(list)) {
+            for (MercFeeConfigAlgorithmType cfg : list) {
+                MercFeeConfigAlgorithmTypeDto.DeviceAlgorithmMercVO damVo = BeanUtil.copyProperties(cfg, MercFeeConfigAlgorithmTypeDto.DeviceAlgorithmMercVO.class);
+                Long algorithmId = damVo.getAlgorithmId();
+                String algorithmPayConfig = algorithmPayConfigMap.get(algorithmId);
+                DeviceAlgorithmChargingDto.AlgorithmMoonConfig algorithmMoonConfig = JSONUtil.parseObj(algorithmPayConfig).toBean(DeviceAlgorithmChargingDto.AlgorithmMoonConfig.class);
+                DeviceAlgorithmChargingDto.AlgorithmMoonConfig.Inf inf = algorithmMoonConfig.getInf();
+                DeviceAlgorithmChargingDto.AlgorithmMoonConfig.Moon moon = algorithmMoonConfig.getMoon();
+                damVo.setMoonMoney(moon.getMoney());
+                damVo.setMoonSize(moon.getSize());
+                damVo.setSingleMoney(algorithmMoonConfig.getPrice());
+                deviceAcMercList.add(damVo);
+            }
+        }
+        data.setDeviceAcMercList(deviceAcMercList);
+        data.setDeviceAcPlatformList(deviceAcPlatformList);
+        return R.ok(data);
+    }
+
+
+    @PostMapping("page")
+    @ApiOperation("分页查询")
+    public R<PageBean<MercFeeConfigAlgorithmTypeDto.Vo>> page(@RequestBody MercFeeConfigAlgorithmTypeDto.Page page) {
+        PageBean pageBean = page.getPage();
+        LambdaQueryWrapper<MercFeeConfigAlgorithmType> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, MercFeeConfigAlgorithmType.class).build();
+        IPage<MercFeeConfigAlgorithmType> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
+        return R.ok(toPageBean(MercFeeConfigAlgorithmTypeDto.Vo.class, iPage));
+    }
+
+    @PostMapping("save")
+    @ApiOperation("添加")
+    public R save(@RequestBody @Validated MercFeeConfigAlgorithmTypeDto.Save save) {
+        Long mercId = save.getMercId();
+        Long algorithmId = save.getAlgorithmId();
+        MercFeeConfigAlgorithmType mc = this.getOne(Wrappers.<MercFeeConfigAlgorithmType>lambdaQuery()
+                .eq(MercFeeConfigAlgorithmType::getMercId, mercId)
+                .eq(MercFeeConfigAlgorithmType::getAlgorithmId, algorithmId)
+        );
+        if (mc != null) {
+            throw new CommRuntimeException("该类型配置已存在,请勿重复添加!");
+        }
+        MercDto.Vo merc = R.feignCheckData(mercService.obj(new MercDto.Vo().setId(mercId)));
+        String mercCode = merc.getMercCode();
+        MercFeeConfigAlgorithmType saveInfo = copy(MercFeeConfigAlgorithmType.class, save);
+        saveInfo.setMercCode(mercCode);
+        save(saveInfo);
+        return R.ok();
+    }
+
+    @PostMapping("update")
+    @ApiOperation("修改")
+    public R update(@RequestBody @Validated MercFeeConfigAlgorithmTypeDto.Update update) {
+        MercFeeConfigAlgorithmType updateInfo = copy(MercFeeConfigAlgorithmType.class, update);
+        updateById(updateInfo);
+        return R.ok();
+    }
+}

+ 212 - 0
device-api-service/src/main/java/com/xy/service/MercFeeConfigSimCardServiceImpl.java

@@ -0,0 +1,212 @@
+package com.xy.service;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.device.EnumSimConfig;
+import com.xy.dto.MercFeeConfigAlgorithmTypeDto;
+import com.xy.dto.MercFeeConfigDto;
+import com.xy.dto.MercFeeConfigSimCardDto;
+import com.xy.dto.be.MercDto;
+import com.xy.entity.MercFeeConfigSimCard;
+import com.xy.error.CommRuntimeException;
+import com.xy.mapper.MercFeeConfigSimCardMapper;
+import com.xy.service.be.MercService;
+import com.xy.utils.*;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+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 java.util.ArrayList;
+import java.util.List;
+
+import static com.xy.utils.Beans.copy;
+import static com.xy.utils.PlusBeans.toIPage;
+import static com.xy.utils.PlusBeans.toPageBean;
+
+
+/**
+ * <p>
+ * 商户流量卡费配置扩展 服务实现类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+@Service
+@AllArgsConstructor
+@Api(tags = "商户流量卡费配置扩展")
+public class MercFeeConfigSimCardServiceImpl extends ServiceImpl<MercFeeConfigSimCardMapper, MercFeeConfigSimCard> implements MercFeeConfigSimCardService {
+
+    private MercService mercService;
+    private DeviceAlgorithmChargingServiceImpl deviceAlgorithmChargingService;
+    private MercFeeConfigService mercFeeConfigService;
+
+
+    @PostMapping("obj")
+    @ApiOperation("对象查询")
+    public R<MercFeeConfigSimCardDto.Vo> obj(@RequestBody MercFeeConfigSimCardDto.Vo vo) {
+        MercFeeConfigSimCardDto.SelectList selectList = copy(MercFeeConfigSimCardDto.SelectList.class, vo);
+        List<MercFeeConfigSimCardDto.Vo> list = list(selectList).getData();
+        if (Emptys.check(list)) {
+            return R.ok(list.get(0));
+        }
+        return R.ok();
+    }
+
+    @PostMapping("list")
+    @ApiOperation("集合查询")
+    public R<List<MercFeeConfigSimCardDto.Vo>> list(@RequestBody MercFeeConfigSimCardDto.SelectList selectList) {
+        LambdaQueryWrapper<MercFeeConfigSimCard> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, MercFeeConfigSimCard.class).build();
+        List<MercFeeConfigSimCard> list = list(lambdaQueryWrapper);
+        return R.ok(copy(MercFeeConfigSimCardDto.Vo.class, list));
+    }
+
+    @PostMapping("page")
+    @ApiOperation("分页查询")
+    public R<PageBean<MercFeeConfigSimCardDto.Vo>> page(@RequestBody MercFeeConfigSimCardDto.Page page) {
+        PageBean pageBean = page.getPage();
+        LambdaQueryWrapper<MercFeeConfigSimCard> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, MercFeeConfigSimCard.class).build();
+        IPage<MercFeeConfigSimCard> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
+        return R.ok(toPageBean(MercFeeConfigSimCardDto.Vo.class, iPage));
+    }
+
+    @PostMapping("listByFeeConfig")
+    @ApiOperation("流量卡费用配置查询")
+    public R<MercFeeConfigSimCardDto.DeviceSimConfigVO> listByFeeConfig(@RequestBody @Validated MercFeeConfigAlgorithmTypeDto.ListByFeeConfigDTO dto) {
+        MercFeeConfigSimCardDto.DeviceSimConfigVO data = new MercFeeConfigSimCardDto.DeviceSimConfigVO();
+        Long mercId = dto.getMercId();
+        MercDto.Vo merc = R.feignCheckData(mercService.obj(new MercDto.Vo().setId(mercId)));
+        //查询默认算法信息
+        //流量卡费-平台默认配置
+        List<MercFeeConfigSimCardDto.DeviceSimPlatformVO> deviceSimPlatformList = new ArrayList<>();
+
+        Integer money = SysDictUtils.getValue(EnumSimConfig.Code.CODE.getCode(), EnumSimConfig.money.getCode(), Integer.class);
+        String name = SysDictUtils.getValue(EnumSimConfig.Code.CODE.getCode(), EnumSimConfig.name.getCode(), String.class);
+        Integer expireDay = SysDictUtils.getValue(EnumSimConfig.Code.CODE.getCode(), EnumSimConfig.N_200.getCode(), Integer.class);
+        deviceSimPlatformList.add(new MercFeeConfigSimCardDto.DeviceSimPlatformVO().setName(name).setExpireDay(expireDay).setMoney(money));
+
+
+        // 设备管理费-商家自定义费用
+        List<MercFeeConfigSimCardDto.DeviceSimMercVO> deviceSimMercList = new ArrayList<>();
+        LambdaQueryWrapper<MercFeeConfigSimCard> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(dto, MercFeeConfigSimCard.class)
+                .eq(MercFeeConfigSimCard::getMercId, merc.getId())
+                .build();
+        //默认配置 type 2预充 1赠送天数
+        List<MercFeeConfigSimCard> list = list(lambdaQueryWrapper);
+        if (CollUtil.isNotEmpty(list)) {
+            for (MercFeeConfigSimCard cfg : list) {
+                MercFeeConfigSimCardDto.DeviceSimMercVO deviceSimMercVO = BeanUtil.copyProperties(cfg, MercFeeConfigSimCardDto.DeviceSimMercVO.class);
+                deviceSimMercVO.setName(name).setExpireDay(expireDay).setMoney(money);
+                deviceSimMercList.add(deviceSimMercVO);
+            }
+        }
+        data.setDeviceSimPlatformList(deviceSimPlatformList);
+        data.setDeviceSimMercList(deviceSimMercList);
+        return R.ok(data);
+    }
+
+    @PostMapping("paySimCardFee")
+    @ApiOperation("流量卡费用")
+    public R<List<MercFeeConfigSimCardDto.DeviceSimPayVO>> paySimCardFee(@RequestBody @Validated MercFeeConfigAlgorithmTypeDto.SimPayQueryDTO dto) {
+        Long mercId = dto.getMercId();
+        MercDto.Vo merc = R.feignCheckData(mercService.obj(new MercDto.Vo().setId(mercId)));
+        String mercCode = merc.getMercCode();
+        List<String> mercCodes = new ArrayList<>();
+        deviceAlgorithmChargingService.getMercCodes(mercCode, mercCodes);
+        //查询默认算法信息
+        //流量卡费-平台默认配置
+        Integer money = SysDictUtils.getValue(EnumSimConfig.Code.CODE.getCode(), EnumSimConfig.money.getCode(), Integer.class);
+        String name = SysDictUtils.getValue(EnumSimConfig.Code.CODE.getCode(), EnumSimConfig.name.getCode(), String.class);
+        //佣金配置查询
+        MercFeeConfigDto.FeeConfigByMercVO mercFeeConfig = R.feignCheckData(mercFeeConfigService.getFeeConfigByMerc(new MercFeeConfigDto.FeeConfigByMerc().setMercCode(merc.getMercCode())));
+
+        // 设备管理费-商家自定义费用
+        List<MercFeeConfigSimCardDto.DeviceSimPayVO> deviceSimMercList = new ArrayList<>();
+        LambdaQueryWrapper<MercFeeConfigSimCard> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(dto, MercFeeConfigSimCard.class)
+                .in(MercFeeConfigSimCard::getMercCode, mercCodes)
+                .build();
+        List<MercFeeConfigSimCard> list = list(lambdaQueryWrapper);
+        if (CollUtil.isNotEmpty(list)) {
+            for (MercFeeConfigSimCard cfg : list) {
+                MercFeeConfigSimCardDto.DeviceSimPayVO deviceSimMercVO = BeanUtil.copyProperties(cfg, MercFeeConfigSimCardDto.DeviceSimPayVO.class);
+                deviceSimMercVO.setName(name).setMoney(cfg.getExtraMoney() + mercFeeConfig.getFeeSimcard());
+                deviceSimMercList.add(deviceSimMercVO);
+            }
+        } else {
+            MercFeeConfigSimCardDto.DeviceSimPayVO deviceSimMercVO = new MercFeeConfigSimCardDto.DeviceSimPayVO();
+            deviceSimMercVO.setName(name).setMoney(money + mercFeeConfig.getFeeSimcard());
+            deviceSimMercList.add(deviceSimMercVO);
+        }
+
+        return R.ok(deviceSimMercList);
+    }
+
+    @Override
+    @ApiOperation("商户自定义流量卡费用")
+    public R<List<MercFeeConfigSimCardDto.DeviceSimPayVO>> listByMerc(MercFeeConfigAlgorithmTypeDto.SimPayQueryDTO dto) {
+        Long mercId = dto.getMercId();
+        MercDto.Vo merc = R.feignCheckData(mercService.obj(new MercDto.Vo().setId(mercId)));
+        String mercCode = merc.getMercCode();
+        List<String> mercCodes = new ArrayList<>();
+        deviceAlgorithmChargingService.getMercCodes(mercCode, mercCodes);
+        //查询默认算法信息
+        //流量卡费-平台默认配置
+        Integer money = SysDictUtils.getValue(EnumSimConfig.Code.CODE.getCode(), EnumSimConfig.money.getCode(), Integer.class);
+        String name = SysDictUtils.getValue(EnumSimConfig.Code.CODE.getCode(), EnumSimConfig.name.getCode(), String.class);
+
+        // 设备管理费-商家自定义费用
+        List<MercFeeConfigSimCardDto.DeviceSimPayVO> deviceSimMercList = new ArrayList<>();
+        LambdaQueryWrapper<MercFeeConfigSimCard> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(dto, MercFeeConfigSimCard.class)
+                .in(MercFeeConfigSimCard::getMercCode, mercCodes)
+                .build();
+        List<MercFeeConfigSimCard> list = list(lambdaQueryWrapper);
+        if (CollUtil.isNotEmpty(list)) {
+            for (MercFeeConfigSimCard cfg : list) {
+                MercFeeConfigSimCardDto.DeviceSimPayVO deviceSimMercVO = BeanUtil.copyProperties(cfg, MercFeeConfigSimCardDto.DeviceSimPayVO.class);
+                deviceSimMercVO.setName(name).setMoney(money + cfg.getExtraMoney());
+                deviceSimMercList.add(deviceSimMercVO);
+            }
+        }
+
+        return R.ok(deviceSimMercList);
+    }
+
+
+    @PostMapping("save")
+    @ApiOperation("添加")
+    public R save(@RequestBody @Validated MercFeeConfigSimCardDto.Save save) {
+        Long mercId = save.getMercId();
+        MercFeeConfigSimCard mc = this.getOne(Wrappers.<MercFeeConfigSimCard>lambdaQuery()
+                .eq(MercFeeConfigSimCard::getMercId, mercId)
+        );
+        if (mc != null) {
+            throw new CommRuntimeException("该类型配置已存在,请勿重复添加!");
+        }
+        MercFeeConfigSimCard saveInfo = copy(MercFeeConfigSimCard.class, save);
+        save(saveInfo);
+        return R.ok();
+    }
+
+    @PostMapping("update")
+    @ApiOperation("修改")
+    public R update(@RequestBody @Validated MercFeeConfigSimCardDto.Update update) {
+        MercFeeConfigSimCard updateInfo = copy(MercFeeConfigSimCard.class, update);
+        updateById(updateInfo);
+        return R.ok();
+    }
+
+    @PostMapping("delete")
+    @ApiOperation("删除")
+    public R delete(@RequestBody @Validated MercFeeConfigSimCardDto.Delete delete) {
+        removeById(delete.getId());
+        return R.ok();
+    }
+}

+ 94 - 0
device-api-service/src/main/java/com/xy/service/MercFeeCountDayServiceImpl.java

@@ -0,0 +1,94 @@
+package com.xy.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.dto.MercFeeCountDayDto;
+import com.xy.entity.MercFeeCountDay;
+import com.xy.mapper.MercFeeCountDayMapper;
+import com.xy.utils.Emptys;
+import com.xy.utils.MybatisPlusQuery;
+import com.xy.utils.PageBean;
+import com.xy.utils.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+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 java.util.List;
+
+import static com.xy.utils.Beans.copy;
+import static com.xy.utils.PlusBeans.toIPage;
+import static com.xy.utils.PlusBeans.toPageBean;
+
+
+/**
+ * <p>
+ * 商户佣金费用收益每日统计(不含今天) 服务实现类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@Service
+@AllArgsConstructor
+@Api(tags = "商户佣金费用收益每日统计(不含今天)")
+public class MercFeeCountDayServiceImpl extends ServiceImpl<MercFeeCountDayMapper, MercFeeCountDay> implements MercFeeCountDayService {
+
+    @PostMapping("obj")
+    @ApiOperation("对象查询")
+    public R<MercFeeCountDayDto.Vo> obj(@RequestBody MercFeeCountDayDto.Vo vo) {
+        MercFeeCountDayDto.SelectList selectList = copy(MercFeeCountDayDto.SelectList.class, vo);
+        List<MercFeeCountDayDto.Vo> list = list(selectList).getData();
+        if (Emptys.check(list)) {
+            return R.ok(list.get(0));
+        }
+        return R.ok();
+    }
+
+    @PostMapping("list")
+    @ApiOperation("集合查询")
+    public R<List<MercFeeCountDayDto.Vo>> list(@RequestBody MercFeeCountDayDto.SelectList selectList) {
+        LambdaQueryWrapper<MercFeeCountDay> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, MercFeeCountDay.class).build();
+        List<MercFeeCountDay> list = list(lambdaQueryWrapper);
+        return R.ok(copy(MercFeeCountDayDto.Vo.class, list));
+    }
+
+    @PostMapping("page")
+    @ApiOperation("分页查询")
+    public R<PageBean<MercFeeCountDayDto.Vo>> page(@RequestBody MercFeeCountDayDto.Page page) {
+        PageBean pageBean = page.getPage();
+        LambdaQueryWrapper<MercFeeCountDay> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, MercFeeCountDay.class).build();
+        IPage<MercFeeCountDay> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
+        return R.ok(toPageBean(MercFeeCountDayDto.Vo.class, iPage));
+    }
+
+    @PostMapping("save")
+    @ApiOperation("添加")
+    public R save(@RequestBody @Validated MercFeeCountDayDto.Save save) {
+        MercFeeCountDay saveInfo = copy(MercFeeCountDay.class, save);
+        save(saveInfo);
+        return R.ok();
+    }
+
+    @PostMapping("update")
+    @ApiOperation("修改")
+    public R update(@RequestBody @Validated MercFeeCountDayDto.Update update) {
+        MercFeeCountDay updateInfo = copy(MercFeeCountDay.class, update);
+        updateById(updateInfo);
+        return R.ok();
+    }
+
+    /**
+     * 查询指定月份费用总和
+     *
+     * @param countByMonth
+     * @return
+     */
+    public List<MercFeeCountDayDto.CountByMonthVO> countByMonth(MercFeeCountDayDto.CountByMonth countByMonth) {
+        return this.baseMapper.countByMonth(countByMonth);
+    }
+}

+ 160 - 0
device-api-service/src/main/java/com/xy/service/MercFeeCountMonthServiceImpl.java

@@ -0,0 +1,160 @@
+package com.xy.service;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.dto.MercFeeCountMonthDto;
+import com.xy.dto.be.MercDto;
+import com.xy.entity.MercFeeCountMonth;
+import com.xy.entity.MercFeeStatistic;
+import com.xy.mapper.MercFeeCountMonthMapper;
+import com.xy.service.be.MercFeignService;
+import com.xy.utils.Emptys;
+import com.xy.utils.MybatisPlusQuery;
+import com.xy.utils.PageBean;
+import com.xy.utils.R;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+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 java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static com.xy.utils.Beans.copy;
+import static com.xy.utils.PlusBeans.toIPage;
+import static com.xy.utils.PlusBeans.toPageBean;
+
+
+/**
+ * <p>
+ * 商户佣金费用收益每月统计(不含本月) 服务实现类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@Service
+@AllArgsConstructor
+@Api(tags = "商户佣金费用收益每月统计(不含本月)")
+public class MercFeeCountMonthServiceImpl extends ServiceImpl<MercFeeCountMonthMapper, MercFeeCountMonth> implements MercFeeCountMonthService {
+
+    private MercFeignService mercFeignService;
+    private MercFeeStatisticServiceImpl mercFeeStatisticService;
+
+    @PostMapping("obj")
+    @ApiOperation("对象查询")
+    public R<MercFeeCountMonthDto.Vo> obj(@RequestBody MercFeeCountMonthDto.Vo vo) {
+        MercFeeCountMonthDto.SelectList selectList = copy(MercFeeCountMonthDto.SelectList.class, vo);
+        List<MercFeeCountMonthDto.Vo> list = list(selectList).getData();
+        if (Emptys.check(list)) {
+            return R.ok(list.get(0));
+        }
+        return R.ok();
+    }
+
+    @PostMapping("list")
+    @ApiOperation("集合查询")
+    public R<List<MercFeeCountMonthDto.Vo>> list(@RequestBody MercFeeCountMonthDto.SelectList selectList) {
+        LambdaQueryWrapper<MercFeeCountMonth> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, MercFeeCountMonth.class).build();
+        List<MercFeeCountMonth> list = list(lambdaQueryWrapper);
+        return R.ok(copy(MercFeeCountMonthDto.Vo.class, list));
+    }
+
+    /**
+     * 收益概览-分页查询
+     *
+     * @param page
+     * @return
+     */
+    public R<PageBean<MercFeeCountMonthDto.Vo>> page(MercFeeCountMonthDto.Page page) {
+
+        PageBean pageBean = page.getPage();
+
+
+        String start = page.getBeginTime();
+        String end = page.getEndTime();
+
+        LambdaQueryWrapper<MercFeeCountMonth> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, MercFeeCountMonth.class)
+                .build()
+
+                .orderByDesc(MercFeeCountMonth::getDateValue);
+
+        if (StrUtil.isNotEmpty(start) && StrUtil.isNotEmpty(end)) {
+            // 2024-04-03
+            String startDate = start.replaceAll("-", "");
+            String endDate = end.replaceAll("-", "");
+            int s = Integer.parseInt(startDate.substring(0, 4) + startDate.substring(5, 7));
+            int e = Integer.parseInt(endDate.substring(0, 4) + endDate.substring(5, 7));
+            lambdaQueryWrapper.between(MercFeeCountMonth::getDateValue, s, e);
+        }
+        IPage<MercFeeCountMonth> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
+        PageBean<MercFeeCountMonthDto.Vo> pageData = toPageBean(MercFeeCountMonthDto.Vo.class, iPage);
+        List<MercFeeCountMonthDto.Vo> records = pageData.getRecords();
+        if (Emptys.check(records)) {
+            List<Long> mercIds = records.stream().map(MercFeeCountMonthDto.Vo::getMercId).distinct().collect(Collectors.toList());
+            List<MercDto.Vo> mercList = R.feignCheckData(mercFeignService.listMerc(new MercDto.ListDTO().setIds(mercIds)));
+            Map<Long, String> mercMap = mercList.stream().collect(Collectors.toMap(MercDto.Vo::getId, MercDto.Vo::getName));
+            for (MercFeeCountMonthDto.Vo record : records) {
+                Long mercId = record.getMercId();
+                // 反显商户名称
+                String mercName = mercMap.get(mercId);
+                record.setMercName(mercName);
+            }
+            pageData.setRecords(records);
+        }
+        return R.ok(pageData);
+    }
+
+    /**
+     * 确认佣金
+     *
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public R confirm(MercFeeCountMonthDto.ConfirmDTO dto) {
+        Long id = dto.getId();
+        Long parentMercId = dto.getParentMercId();
+        MercFeeCountMonth countMonth = getOne(Wrappers.<MercFeeCountMonth>lambdaQuery()
+                .eq(MercFeeCountMonth::getParentMercId, parentMercId)
+                .eq(MercFeeCountMonth::getId, id)
+        );
+        if (countMonth != null) {
+            // 确认
+            countMonth.setVerify(true);
+            countMonth.setVerifyTime(LocalDateTime.now());
+            updateById(countMonth);
+            // 确认后,更新统计表
+            MercFeeStatistic mercFeeStatistic = mercFeeStatisticService.getByMercId(parentMercId);
+            // 更新确认金额,可结算金额
+            mercFeeStatistic.setVerifyMoney(mercFeeStatistic.getVerifyMoney() + countMonth.getBrokerage());
+            mercFeeStatistic.setUnSettleMoney(mercFeeStatistic.getUnSettleMoney() + countMonth.getBrokerage());
+            mercFeeStatisticService.updateById(mercFeeStatistic);
+        }
+        return R.ok();
+    }
+
+    @PostMapping("save")
+    @ApiOperation("添加")
+    public R save(@RequestBody @Validated MercFeeCountMonthDto.Save save) {
+        MercFeeCountMonth saveInfo = copy(MercFeeCountMonth.class, save);
+        save(saveInfo);
+        return R.ok();
+    }
+
+    @PostMapping("update")
+    @ApiOperation("修改")
+    public R update(@RequestBody @Validated MercFeeCountMonthDto.Update update) {
+        MercFeeCountMonth updateInfo = copy(MercFeeCountMonth.class, update);
+        updateById(updateInfo);
+        return R.ok();
+    }
+}

+ 145 - 0
device-api-service/src/main/java/com/xy/service/MercFeeSettleServiceImpl.java

@@ -0,0 +1,145 @@
+package com.xy.service;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.dto.MercFeeSettleDto;
+import com.xy.dto.be.MercDto;
+import com.xy.entity.MercFeeSettle;
+import com.xy.entity.MercFeeStatistic;
+import com.xy.mapper.MercFeeSettleMapper;
+import com.xy.service.be.MercFeignService;
+import com.xy.utils.Emptys;
+import com.xy.utils.MybatisPlusQuery;
+import com.xy.utils.PageBean;
+import com.xy.utils.R;
+import com.xy.utils.enums.MercFeeSettleSate;
+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 java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static com.xy.utils.Beans.copy;
+import static com.xy.utils.PlusBeans.toIPage;
+import static com.xy.utils.PlusBeans.toPageBean;
+
+
+/**
+ * <p>
+ * 商户佣金费用结算 服务实现类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@Service
+@AllArgsConstructor(onConstructor_ = @Lazy)
+@Api(tags = "商户佣金费用结算")
+public class MercFeeSettleServiceImpl extends ServiceImpl<MercFeeSettleMapper, MercFeeSettle> implements MercFeeSettleService {
+
+    private MercFeeStatisticServiceImpl mercFeeStatisticService;
+    private MercFeignService mercFeignService;
+
+
+    @PostMapping("obj")
+    @ApiOperation("对象查询")
+    public R<MercFeeSettleDto.Vo> obj(@RequestBody MercFeeSettleDto.Vo vo) {
+        MercFeeSettleDto.SelectList selectList = copy(MercFeeSettleDto.SelectList.class, vo);
+        List<MercFeeSettleDto.Vo> list = list(selectList).getData();
+        if (Emptys.check(list)) {
+            return R.ok(list.get(0));
+        }
+        return R.ok();
+    }
+
+    @PostMapping("list")
+    @ApiOperation("集合查询")
+    public R<List<MercFeeSettleDto.Vo>> list(@RequestBody MercFeeSettleDto.SelectList selectList) {
+        LambdaQueryWrapper<MercFeeSettle> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, MercFeeSettle.class).build();
+        List<MercFeeSettle> list = list(lambdaQueryWrapper);
+        return R.ok(copy(MercFeeSettleDto.Vo.class, list));
+    }
+
+    @PostMapping("page")
+    @ApiOperation("平台运营-佣金结算记录分页")
+    public R<PageBean<MercFeeSettleDto.Vo>> page(@RequestBody MercFeeSettleDto.Page page) {
+        PageBean pageBean = page.getPage();
+        LambdaQueryWrapper<MercFeeSettle> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, MercFeeSettle.class)
+                .ge(MercFeeSettle::getCreateTime, page.getBeginCreateTime())
+                .le(MercFeeSettle::getCreateTime, page.getEndCreateTime())
+                .build().orderByDesc(!Emptys.check(pageBean.getOrders()), MercFeeSettle::getCreateTime);
+        IPage<MercFeeSettle> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
+        PageBean<MercFeeSettleDto.Vo> pb = toPageBean(MercFeeSettleDto.Vo.class, iPage);
+        List<MercFeeSettleDto.Vo> records = pb.getRecords();
+        if (CollUtil.isNotEmpty(records)) {
+            List<Long> mercIds = records.stream().map(MercFeeSettleDto.Vo::getMercId).distinct().collect(Collectors.toList());
+            List<MercDto.Vo> mercList = R.feignCheckData(mercFeignService.listMerc(new MercDto.ListDTO().setIds(mercIds)));
+            Map<Long, String> mercMap = mercList.stream().collect(Collectors.toMap(MercDto.Vo::getId, MercDto.Vo::getName));
+            for (MercFeeSettleDto.Vo record : records) {
+                Long mercId = record.getMercId();
+                // 反显商户名称
+                String mercName = mercMap.get(mercId);
+                record.setMercName(mercName);
+            }
+            pb.setRecords(records);
+        }
+        return R.ok(pb);
+    }
+
+
+    @PostMapping("save")
+    @ApiOperation("添加")
+    public R save(@RequestBody @Validated MercFeeSettleDto.Save save) {
+        MercFeeSettle saveInfo = copy(MercFeeSettle.class, save);
+        save(saveInfo);
+        return R.ok();
+    }
+
+    @PostMapping("doSettle")
+    @ApiOperation("运营端结算完成操作")
+    public R doSettle(@RequestBody @Validated MercFeeSettleDto.DoSettle update) {
+        List<Long> ids = update.getIds();
+        List<MercFeeSettle> mercFeeSettles = this.listByIds(ids);
+        mercFeeSettles.forEach(mfs -> {
+            mfs.setSettleState(MercFeeSettleSate.S3.getCode());
+            mfs.setFinishSettleTime(LocalDateTime.now());
+            // 结算完成需要更新统计表
+            Long mercId = mfs.getMercId();
+            MercFeeStatistic mercFeeStatistic = mercFeeStatisticService.getByMercId(mercId);
+            // 累计已结算金额
+            mercFeeStatistic.setSettleMoney(mercFeeStatistic.getSettleMoney() + mfs.getSettleMoney());
+            mercFeeStatisticService.updateById(mercFeeStatistic);
+        });
+        return R.ok(updateBatchById(mercFeeSettles));
+    }
+
+    /**
+     * 结算申请
+     *
+     * @param dto
+     * @return
+     */
+    public R<Boolean> applySettle(MercFeeSettleDto.ApplyDTO dto) {
+        MercFeeSettle saveInfo = copy(MercFeeSettle.class, dto);
+        saveInfo.setSettleState(MercFeeSettleSate.S2.getCode());
+        return R.ok(save(saveInfo));
+    }
+
+    @PostMapping("update")
+    @ApiOperation("修改")
+    public R update(@RequestBody @Validated MercFeeSettleDto.Update update) {
+        MercFeeSettle updateInfo = copy(MercFeeSettle.class, update);
+        updateById(updateInfo);
+        return R.ok();
+    }
+}

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

@@ -0,0 +1,133 @@
+package com.xy.service;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xy.dto.MercFeeSettleDto;
+import com.xy.dto.MercFeeStatisticDto;
+import com.xy.entity.MercFeeStatistic;
+import com.xy.mapper.MercFeeStatisticMapper;
+import com.xy.utils.Emptys;
+import com.xy.utils.MybatisPlusQuery;
+import com.xy.utils.PageBean;
+import com.xy.utils.R;
+import com.xy.utils.enums.MercFeeSettleSate;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+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 java.util.List;
+
+import static com.xy.utils.Beans.copy;
+import static com.xy.utils.PlusBeans.toIPage;
+import static com.xy.utils.PlusBeans.toPageBean;
+
+
+/**
+ * <p>
+ * 商户佣金费用统计 服务实现类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-24
+ */
+@Service
+@AllArgsConstructor
+@Api(tags = "商户佣金费用统计")
+public class MercFeeStatisticServiceImpl extends ServiceImpl<MercFeeStatisticMapper, MercFeeStatistic> implements MercFeeStatisticService {
+
+    private MercFeeSettleServiceImpl mercFeeSettleService;
+
+    /**
+     * 收益总览
+     *
+     * @param mercId
+     * @return
+     */
+    public R<MercFeeStatisticDto.InFoVO> info(Long mercId) {
+        MercFeeStatistic mercFeeStatistic = getByMercId(mercId);
+        MercFeeStatisticDto.InFoVO inFoVO = BeanUtil.copyProperties(mercFeeStatistic, MercFeeStatisticDto.InFoVO.class);
+        //结算中金额
+        int settlingMoney = 0;
+        MercFeeSettleDto.SelectList selectList = new MercFeeSettleDto.SelectList();
+        selectList.setMercId(mercId);
+        selectList.setSettleState(MercFeeSettleSate.S2.getCode());
+        List<MercFeeSettleDto.Vo> list = R.feignCheckData(mercFeeSettleService.list(selectList));
+        if (CollUtil.isNotEmpty(list)) {
+            settlingMoney = list.stream().mapToInt(MercFeeSettleDto.Vo::getSettleMoney).sum();
+        }
+        inFoVO.setSettlingMoney(settlingMoney);
+        return R.ok(inFoVO);
+    }
+
+
+    @PostMapping("obj")
+    @ApiOperation("对象查询")
+    public R<MercFeeStatisticDto.Vo> obj(@RequestBody MercFeeStatisticDto.Vo vo) {
+        MercFeeStatisticDto.SelectList selectList = copy(MercFeeStatisticDto.SelectList.class, vo);
+        List<MercFeeStatisticDto.Vo> list = list(selectList).getData();
+        if (Emptys.check(list)) {
+            return R.ok(list.get(0));
+        }
+        return R.ok();
+    }
+
+    /**
+     * 获取商户统计数据,不存在则初始化新增
+     *
+     * @param mercId
+     * @return
+     */
+    public MercFeeStatistic getByMercId(Long mercId) {
+        MercFeeStatistic mercFeeStatistic = this.getById(mercId);
+        if (mercFeeStatistic == null) {
+            MercFeeStatistic newObj = new MercFeeStatistic()
+                    .setMercId(mercId)
+                    .setSettleMoney(0)
+                    .setUnSettleMoney(0)
+                    .setVerifyMoney(0);
+            save(newObj);
+            mercFeeStatistic = newObj;
+        }
+        return mercFeeStatistic;
+    }
+
+    @PostMapping("list")
+    @ApiOperation("集合查询")
+    public R<List<MercFeeStatisticDto.Vo>> list(@RequestBody MercFeeStatisticDto.SelectList selectList) {
+        LambdaQueryWrapper<MercFeeStatistic> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, MercFeeStatistic.class).build();
+        List<MercFeeStatistic> list = list(lambdaQueryWrapper);
+        return R.ok(copy(MercFeeStatisticDto.Vo.class, list));
+    }
+
+    @PostMapping("page")
+    @ApiOperation("分页查询")
+    public R<PageBean<MercFeeStatisticDto.Vo>> page(@RequestBody MercFeeStatisticDto.Page page) {
+        PageBean pageBean = page.getPage();
+        LambdaQueryWrapper<MercFeeStatistic> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, MercFeeStatistic.class).build();
+        IPage<MercFeeStatistic> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
+        return R.ok(toPageBean(MercFeeStatisticDto.Vo.class, iPage));
+    }
+
+    @PostMapping("save")
+    @ApiOperation("添加")
+    public R save(@RequestBody @Validated MercFeeStatisticDto.Save save) {
+        MercFeeStatistic saveInfo = copy(MercFeeStatistic.class, save);
+        save(saveInfo);
+        return R.ok();
+    }
+
+    @PostMapping("update")
+    @ApiOperation("修改")
+    public R update(@RequestBody @Validated MercFeeStatisticDto.Update update) {
+        MercFeeStatistic updateInfo = copy(MercFeeStatistic.class, update);
+        updateById(updateInfo);
+        return R.ok();
+    }
+}

+ 9 - 6
device-api-service/src/main/resources/mapper/DeviceChargingMapper.xml

@@ -1,7 +1,6 @@
 <?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="queryPageMap" type="com.xy.dto.DeviceChargingDto$PageVo">
         <association property="deviceInfo" javaType="com.xy.dto.DeviceInfoDto$Vo">
             <id column="device_id" property="deviceId"/>
@@ -29,16 +28,20 @@
             </association>
         </association>
         <association property="deviceCharging" javaType="com.xy.dto.DeviceChargingDto$Vo">
-            <result column="charging_sum_money" property="chargingSumMoney" />
-            <result column="timeout" property="timeout" />
-            <result column="last_charging_time" property="lastChargingTime" />
-            <result column="charging_create_time" property="createTime" />
+            <result column="charging_sum_money" property="chargingSumMoney"/>
+            <result column="timeout" property="timeout"/>
+            <result column="last_charging_time" property="lastChargingTime"/>
+            <result column="charging_create_time" property="createTime"/>
+            <result column="last_charging_money" property="lastChargingMoney"/>
+            <result column="last_charging_pay_type" property="lastChargingPayType"/>
         </association>
     </resultMap>
 
     <select id="page" resultMap="queryPageMap">
         select di.*,
         ds.net_state,
+        dc.last_charging_money,
+        dc.last_charging_pay_type,
         dc.charging_sum_money, dc.timeout, dc.last_charging_time, dc.create_time as charging_create_time
         from device_info di
         join device_status ds on (di.device_id = ds.device_id)
@@ -54,7 +57,7 @@
         <if test="queryPage.chargingStatus != null and queryPage.chargingStatus != ''">
             <!-- 即将过期 -->
             <if test="queryPage.chargingStatus == 1">
-               and dc.timeout >= #{queryPage.thisTime} and dc.timeout &lt;= #{queryPage.theTime}
+                and dc.timeout >= #{queryPage.thisTime} and dc.timeout &lt;= #{queryPage.theTime}
             </if>
             <!-- 已过期 -->
             <if test="queryPage.chargingStatus == 2">

+ 9 - 0
device-api/src/main/java/com/xy/consts/DictConsts.java

@@ -47,6 +47,15 @@ public class DictConsts {
      * 订单支付类型
      */
     public static final String ORDER_PAY_TYPE = "order_pay_type";
+    /**
+     * 续费方式
+     */
+    public static final String ORDER_MERC_MANAGE_PAY_TYPE = "order_merc_manage_pay_type";
+    /**
+     * 费用支付状态
+     */
+    public static final String ORDER_MERC_MANAGE_STATUS = "order_merc_manage_status";
+    public static final String ALGORITHM_TYPES = "algorithm_types";
 
 
 }

+ 293 - 1
device-api/src/main/java/com/xy/dto/DeviceAlgorithmChargingHistoryDto.java

@@ -1,12 +1,17 @@
 package com.xy.dto;
 
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.NumberFormat;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.xy.annotate.DictFormat;
+import com.xy.consts.DictConsts;
+import com.xy.convert.CustomFenToYuanConverter;
+import com.xy.convert.DictConvert;
 import com.xy.utils.PageBean;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.experimental.Accessors;
 
-import javax.validation.constraints.NotNull;
 import java.time.LocalDateTime;
 
 /**
@@ -28,6 +33,293 @@ public class DeviceAlgorithmChargingHistoryDto {
 
     }
 
+    @Data
+    @Accessors(chain = true)
+    public static class MySpendPageVO {
+
+
+        @ApiModelProperty(value = "代理商金额")
+        private Integer agentMoney;
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+        @ApiModelProperty(value = "订单id")
+        private String orderId;
+
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "算法id")
+        private Long algorithmId;
+
+        @ApiModelProperty(value = "名称")
+        private String name;
+
+        @ApiModelProperty(value = "充值金额")
+        private Integer chargingMoney;
+
+        @ApiModelProperty(value = "充值数量")
+        private Integer chargingSize;
+
+        @ApiModelProperty(value = "充值方式")
+        private Integer chargingType;
+
+        @ApiModelProperty(value = "状态")
+        private Integer status;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "备注")
+        private String note;
+
+        @ApiModelProperty(value = "附件")
+        private String files;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class PageByTopMercVO {
+
+
+        @ApiModelProperty(value = "代理商金额")
+        private Integer agentMoney;
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+        @ApiModelProperty(value = "订单id")
+        private String orderId;
+
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "算法id")
+        private Long algorithmId;
+
+        @ApiModelProperty(value = "名称")
+        private String name;
+
+        @ApiModelProperty(value = "充值金额")
+        private Integer chargingMoney;
+
+        @ApiModelProperty(value = "充值数量")
+        private Integer chargingSize;
+
+        @ApiModelProperty(value = "充值方式")
+        private Integer chargingType;
+
+        @ApiModelProperty(value = "状态")
+        private Integer status;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "备注")
+        private String note;
+
+        @ApiModelProperty(value = "附件")
+        private String files;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class PageExcelVo {
+
+//        @ExcelProperty("说明")
+//        @ApiModelProperty(value = "备注")
+//        private String note;
+
+
+        @ExcelProperty("商户名称")
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+
+        @ExcelProperty("缴费单号")
+        @ApiModelProperty(value = "缴费单号")
+        private String orderId;
+        @ExcelProperty("设备编号")
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ExcelProperty(value = "算法类型", converter = DictConvert.class)
+        @DictFormat(DictConsts.ALGORITHM_TYPES)
+        @ApiModelProperty(value = "算法类型")
+        private Long algorithmId;
+
+//        @ApiModelProperty(value = "名称")
+//        private String name;
+
+        @ExcelProperty(value = "实缴金额", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        @ApiModelProperty(value = "实缴金额")
+        private Integer chargingMoney;
+
+        @ApiModelProperty(value = "佣金")
+        @ExcelProperty(value = "佣金", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        private Integer agentMoney;
+
+
+        @ExcelProperty("缴费数量(笔)")
+        @ApiModelProperty(value = "缴费数量")
+        private Integer chargingSize;
+
+
+        @ExcelProperty(value = "缴费方式", converter = DictConvert.class)
+        @DictFormat(DictConsts.ORDER_MERC_MANAGE_PAY_TYPE)
+        @ApiModelProperty(value = "缴费方式")
+        private Integer chargingType;
+
+        @ExcelProperty(value = "支付状态", converter = DictConvert.class)
+        @DictFormat(DictConsts.ORDER_MERC_MANAGE_STATUS)
+        @ApiModelProperty(value = "支付状态")
+        private Integer status;
+
+
+        @ExcelProperty("支付时间")
+        @ApiModelProperty(value = "缴费时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class SpendPageExcelVo {
+
+
+        @ExcelProperty("商户名称")
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+
+        @ExcelProperty("缴费单号")
+        @ApiModelProperty(value = "缴费单号")
+        private String orderId;
+        @ExcelProperty("设备编号")
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ExcelProperty(value = "算法类型", converter = DictConvert.class)
+        @DictFormat(DictConsts.ALGORITHM_TYPES)
+        @ApiModelProperty(value = "算法类型")
+        private Long algorithmId;
+
+//        @ApiModelProperty(value = "名称")
+//        private String name;
+
+        @ExcelProperty(value = "实缴金额", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        @ApiModelProperty(value = "实缴金额")
+        private Integer chargingMoney;
+
+
+        @ExcelProperty("缴费数量(笔)")
+        @ApiModelProperty(value = "缴费数量")
+        private Integer chargingSize;
+
+
+        @ExcelProperty(value = "缴费方式", converter = DictConvert.class)
+        @DictFormat(DictConsts.ORDER_MERC_MANAGE_PAY_TYPE)
+        @ApiModelProperty(value = "缴费方式")
+        private Integer chargingType;
+
+        @ExcelProperty(value = "支付状态", converter = DictConvert.class)
+        @DictFormat(DictConsts.ORDER_MERC_MANAGE_STATUS)
+        @ApiModelProperty(value = "支付状态")
+        private Integer status;
+
+
+        @ExcelProperty("支付时间")
+        @ApiModelProperty(value = "缴费时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class PageByTopMerc {
+
+        @ApiModelProperty("分页对象")
+        private PageBean page;
+
+        @ApiModelProperty(value = "创建时间-起")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime beginCreateTime;
+
+        @ApiModelProperty(value = "创建时间-始")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime endCreateTime;
+
+
+        @ApiModelProperty(value = "商户id")
+        private Long curMercId;
+
+        @ApiModelProperty(value = "指定商户id")
+        private Long chooseMercId;
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+
+        @ApiModelProperty(value = "订单id")
+        private String orderId;
+
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "算法id")
+        private Long algorithmId;
+
+        @ApiModelProperty(value = "名称")
+        private String name;
+
+        @ApiModelProperty(value = "充值金额")
+        private Integer chargingMoney;
+
+        @ApiModelProperty(value = "充值数量")
+        private Integer chargingSize;
+
+        @ApiModelProperty(value = "充值方式")
+        private Integer chargingType;
+
+        @ApiModelProperty(value = "状态")
+        private Integer status;
+
+
+        @ApiModelProperty(value = "备注")
+        private String note;
+
+        @ApiModelProperty(value = "附件")
+        private String files;
+
+
+    }
+
     @Data
     @Accessors(chain = true)
     public static class Vo {

+ 185 - 1
device-api/src/main/java/com/xy/dto/DeviceChargingConfigDto.java

@@ -24,15 +24,79 @@ public class DeviceChargingConfigDto {
     @Accessors(chain = true)
     public static class SelectList extends Vo {
 
+
+        @ApiModelProperty(value = "商户id", required = true)
+        private Long mercId;
+
+        @ApiModelProperty(value = "商户id", required = true)
+        private List<String> mercCodes;
+
+        @ApiModelProperty(value = "设备类型", required = true)
+        private Integer deviceType;
+
+        @ApiModelProperty(value = "设备类型", required = true)
+        private List<Integer> deviceTypes;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class ListByFeeConfigDTO extends Vo {
+
         @NotNull(message = "mercId不能为空")
         @ApiModelProperty(value = "商户id", required = true)
         private Long mercId;
 
-        @NotNull(message = "deviceType不能为空")
+
+        @NotEmpty(message = "设备类型不可为空")
         @ApiModelProperty(value = "设备类型", required = true)
+        private List<Integer> deviceTypes;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Save extends Vo {
+
+
+        @NotNull(message = "mercId不能为空")
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+
+        @NotNull(message = "deviceType不能为空")
+        @ApiModelProperty(value = "设备类型")
         private Integer deviceType;
+
+        @ApiModelProperty(value = "佣金;单位:分")
+        private Integer extraMoney;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Delete {
+
+        @NotNull(message = "id不能为空")
+        @ApiModelProperty(value = "id")
+        private Long id;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Update extends Vo {
+
+        @NotNull(message = "id不能为空")
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @NotNull(message = "type不能为空")
+        @ApiModelProperty(value = "类型", required = true)
+        private Integer type;
+
+        @NotNull(message = "money不能为空")
+        @ApiModelProperty(value = "预充金额;单位:分")
+        private Integer configValue;
     }
 
+
     @Data
     @Accessors(chain = true)
     public static class SaveOrUpdate {
@@ -96,6 +160,126 @@ public class DeviceChargingConfigDto {
         @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
         private LocalDateTime updateTime;
 
+        @ApiModelProperty(value = "代理商额外费用")
+        private Integer extraMoney;
+
+
+    }
+
+    /**
+     * 设备管理费配置
+     */
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceManagerFeeConfigVO {
+        @ApiModelProperty(value = "设备管理费-平台默认配置")
+        private List<DeviceManagerFeePlatformVO> dmFeePlatforms;
+        @ApiModelProperty(value = "设备管理费-商家自定义费用")
+        private List<DeviceManagerFeeMercVO> dmFeeMercs;
+    }
+
+    /**
+     * 设备管理费-平台默认配置
+     */
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceManagerFeePlatformVO {
+        @ApiModelProperty(value = "默认赠送年费")
+        private Integer defFee;
+        @ApiModelProperty(value = "默认赠送天数")
+        private Integer defGiveDay;
+
+        @ApiModelProperty(value = "设备类型")
+        private Integer deviceType;
+
+
+    }
+
+    /**
+     * 设备管理费-商家自定义费用
+     */
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceManagerFeeMercVO {
+        @ApiModelProperty(value = "默认赠送年费")
+        private Integer defFee;
+        @ApiModelProperty(value = "默认赠送天数")
+        private Integer defGiveDay;
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "商户编码")
+        private String mercCode;
+
+        @ApiModelProperty(value = "设备类型")
+        private Integer deviceType;
+
+        @ApiModelProperty(value = "自定义赠送天数")
+        private Integer giveDay;
+
+        @ApiModelProperty(value = "自定义年费")
+        private Integer fee;
+
+        @ApiModelProperty(value = "备注")
+        private String note;
+
+        @ApiModelProperty(value = "类型")
+        private Integer type;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "代理商额外费用")
+        private Integer extraMoney;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class FeeConfigVO {
+
+        @ApiModelProperty(value = "默认赠送年费")
+        private Integer defFee;
+        @ApiModelProperty(value = "默认赠送天数")
+        private Integer defGiveDay;
+
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "商户编码")
+        private String mercCode;
+
+        @ApiModelProperty(value = "设备类型")
+        private Integer deviceType;
+
+        @ApiModelProperty(value = "自定义赠送天数")
+        private Integer giveDay;
+
+        @ApiModelProperty(value = "自定义年费")
+        private Integer fee;
+
+        @ApiModelProperty(value = "备注")
+        private String note;
+
+        @ApiModelProperty(value = "类型")
+        private Integer type;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
 
     }
 

+ 266 - 1
device-api/src/main/java/com/xy/dto/DeviceChargingHistoryDto.java

@@ -1,12 +1,17 @@
 package com.xy.dto;
 
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.NumberFormat;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.xy.annotate.DictFormat;
+import com.xy.consts.DictConsts;
+import com.xy.convert.CustomFenToYuanConverter;
+import com.xy.convert.DictConvert;
 import com.xy.utils.PageBean;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.experimental.Accessors;
 
-import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.List;
 
@@ -20,6 +25,210 @@ import java.util.List;
  */
 public class DeviceChargingHistoryDto {
 
+    @Data
+    @Accessors(chain = true)
+    public static class MySpendPageVO {
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+
+        @ApiModelProperty(value = "订单id")
+        private String orderId;
+
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "续费金额")
+        private Integer chargingMoney;
+
+        @ApiModelProperty(value = "佣金")
+        private Integer agentMoney;
+
+        @ApiModelProperty(value = "续费数量")
+        private Integer chargingSize;
+
+        @ApiModelProperty(value = "续费方式")
+        private Integer chargingType;
+
+        @ApiModelProperty(value = "状态")
+        private Integer status;
+
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        @ApiModelProperty(value = "创建时间")
+        private LocalDateTime createTime;
+
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        @ApiModelProperty(value = "更新时间")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "备注")
+        private String note;
+
+        @ApiModelProperty(value = "附件")
+        private String files;
+
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+
+
+        @ApiModelProperty(value = "过期时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime timeout;
+
+        @ApiModelProperty(value = "过期状态说明")
+        private String timeoutStatus;
+
+
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class PageVo {
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+
+        @ApiModelProperty(value = "订单id")
+        private String orderId;
+
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "续费金额")
+        private Integer chargingMoney;
+
+        @ApiModelProperty(value = "佣金")
+        private Integer agentMoney;
+
+        @ApiModelProperty(value = "续费数量")
+        private Integer chargingSize;
+
+        @ApiModelProperty(value = "续费方式")
+        private Integer chargingType;
+
+        @ApiModelProperty(value = "状态")
+        private Integer status;
+
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        @ApiModelProperty(value = "创建时间")
+        private LocalDateTime createTime;
+
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        @ApiModelProperty(value = "更新时间")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "备注")
+        private String note;
+
+        @ApiModelProperty(value = "附件")
+        private String files;
+
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+
+
+        @ApiModelProperty(value = "过期时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime timeout;
+
+        @ApiModelProperty(value = "过期状态说明")
+        private String timeoutStatus;
+
+
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class PageExcelVo {
+        @ExcelProperty("商户名称")
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+        @ExcelProperty("缴费单号")
+        @ApiModelProperty(value = "缴费单号")
+        private String orderId;
+        @ExcelProperty("设备编号")
+        @ApiModelProperty(value = "设备编号")
+        private Long deviceId;
+        @ExcelProperty(value = "实缴金额", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        @ApiModelProperty(value = "续费金额")
+        private Integer chargingMoney;
+        @ApiModelProperty(value = "佣金")
+        @ExcelProperty(value = "佣金", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        private Integer agentMoney;
+        @ExcelProperty("续费数量(年)")
+        @ApiModelProperty(value = "续费数量")
+        private Integer chargingSize;
+        @ExcelProperty(value = "续费方式", converter = DictConvert.class)
+        @DictFormat(DictConsts.ORDER_MERC_MANAGE_PAY_TYPE)
+        @ApiModelProperty(value = "续费方式")
+        private Integer chargingType;
+        @ExcelProperty("缴费时间")
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+
+        @ExcelProperty("过期时间")
+        @ApiModelProperty(value = "过期时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime timeout;
+        @ExcelProperty("状态说明")
+        @ApiModelProperty(value = "过期状态说明")
+        private String timeoutStatus;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class SpendPageExcelVo {
+        @ExcelProperty("商户名称")
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+        @ExcelProperty("缴费单号")
+        @ApiModelProperty(value = "缴费单号")
+        private String orderId;
+        @ExcelProperty("设备编号")
+        @ApiModelProperty(value = "设备编号")
+        private Long deviceId;
+        @ExcelProperty(value = "实缴金额", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        @ApiModelProperty(value = "续费金额")
+        private Integer chargingMoney;
+
+        @ExcelProperty("续费数量(年)")
+        @ApiModelProperty(value = "续费数量")
+        private Integer chargingSize;
+        @ExcelProperty(value = "续费方式", converter = DictConvert.class)
+        @DictFormat(DictConsts.ORDER_MERC_MANAGE_PAY_TYPE)
+        @ApiModelProperty(value = "续费方式")
+        private Integer chargingType;
+        @ExcelProperty("缴费时间")
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+
+        @ExcelProperty("过期时间")
+        @ApiModelProperty(value = "过期时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime timeout;
+        @ExcelProperty("状态说明")
+        @ApiModelProperty(value = "过期状态说明")
+        private String timeoutStatus;
+
+    }
+
+
     @Data
     @Accessors(chain = true)
     public static class Vo {
@@ -82,6 +291,62 @@ public class DeviceChargingHistoryDto {
         private LocalDateTime endCreateTime;
     }
 
+    @Data
+    @Accessors(chain = true)
+    public static class PageByTopMerc {
+        @ApiModelProperty("分页对象")
+        private PageBean page;
+
+        @ApiModelProperty("是否导出当前页")
+        private Boolean exportPage = true;
+        @ApiModelProperty(value = "创建时间-起")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime beginCreateTime;
+        @ApiModelProperty(value = "创建时间-始")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime endCreateTime;
+        @ApiModelProperty(value = "id")
+        private Long id;
+        @ApiModelProperty(value = "商户id")
+        private Long curMercId;
+        @ApiModelProperty(value = "指定商户id")
+        private Long chooseMercId;
+        @ApiModelProperty(value = "订单id")
+        private String orderId;
+        @ApiModelProperty(value = "设备id")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "续费金额")
+        private Integer chargingMoney;
+        @ApiModelProperty(value = "续费数量")
+        private Integer chargingSize;
+        @ApiModelProperty(value = "续费方式")
+        private Integer chargingType;
+        @ApiModelProperty(value = "状态")
+        private Integer status;
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        @ApiModelProperty(value = "创建时间")
+        private LocalDateTime createTime;
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        @ApiModelProperty(value = "更新时间")
+        private LocalDateTime updateTime;
+        @ApiModelProperty(value = "备注")
+        private String note;
+        @ApiModelProperty(value = "附件")
+        private String files;
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+
+        // size -1 不分页
+        public PageBean getPage() {
+            if (!this.exportPage) {
+                this.page.setSize(-1L);
+            }
+            return page;
+        }
+    }
+
+
     @Data
     @Accessors(chain = true)
     public static class MoonCount {

+ 212 - 0
device-api/src/main/java/com/xy/dto/DeviceDataDto.java

@@ -2,7 +2,10 @@ package com.xy.dto;
 
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.NumberFormat;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.xy.convert.CustomFenToYuanConverter;
 import com.xy.utils.PageBean;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -450,4 +453,213 @@ public class DeviceDataDto {
         @ApiModelProperty(value = "设备ID")
         private List<Long> deviceId;
     }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceFlowDetailDTO {
+        @ApiModelProperty(value = "是否统计所有,用于导出明细(false)")
+        private Boolean countAll;
+
+        @ApiModelProperty(value = "设备ID")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "月份-起")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime beginCreateTime;
+
+        @ApiModelProperty(value = "月份-止")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime endCreateTime;
+
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceFlowCountDTO {
+        @ApiModelProperty("分页对象")
+        private PageBean page;
+
+        @ApiModelProperty("是否导出当前页")
+        private Boolean exportPage = true;
+        @ApiModelProperty(value = "设备ID")
+        private Long deviceId;
+        @ApiModelProperty(value = "月份-起")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime beginCreateTime;
+        @ApiModelProperty(value = "月份-止")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime endCreateTime;
+        @ApiModelProperty(value = "投放时间-起")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime activeStartTime;
+        @ApiModelProperty(value = "投放时间-止")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime activeEndStartTime;
+        @ApiModelProperty(value = "商户id")
+        private Long curMercId;
+        @ApiModelProperty(value = "指定商户id")
+        private Long chooseMercId;
+        @ApiModelProperty(value = "商户ID")
+        private List<Long> mercIds;
+
+        // size -1 不分页
+        public PageBean getPage() {
+            if (!this.exportPage) {
+                this.page.setSize(-1L);
+            }
+            return page;
+        }
+
+
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceFlowCountExcelVo {
+        @ApiModelProperty(value = "月度流水列表")
+        List<DeviceFlowMonthVO> monthflowList;
+        @ExcelProperty("设备ID")
+        @ApiModelProperty(value = "设备ID")
+        private Long deviceId;
+        @ExcelProperty("设备")
+        @ApiModelProperty(value = "设备")
+        private String deviceName;
+        @ExcelProperty("商户名称")
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+        @ApiModelProperty(value = "区域")
+        private String districtName;
+        @ApiModelProperty(value = "点位")
+        private String placeName;
+        @ApiModelProperty(value = "投放时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime activeTime;
+        @ApiModelProperty(value = "月平均流水")
+        private BigDecimal monthAvgMoney;
+        @ApiModelProperty(value = "总计流水")
+        private Integer totalMoney;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceFlowCountVO {
+        @ApiModelProperty(value = "月度流水列表")
+        List<DeviceFlowMonthVO> monthflowList;
+        @ApiModelProperty(value = "商户ID")
+        private Long mercId;
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+        @ApiModelProperty(value = "设备ID")
+        private Long deviceId;
+        @ApiModelProperty(value = "设备名称")
+        private String deviceName;
+        @ApiModelProperty(value = "区域")
+        private String districtName;
+        @ApiModelProperty(value = "点位")
+        private String placeName;
+        /**
+         * 点位id
+         */
+        private Long placeId;
+        @ApiModelProperty(value = "投放时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime activeTime;
+        @ApiModelProperty(value = "月平均流水")
+        private BigDecimal monthAvgMoney;
+        @ApiModelProperty(value = "总计流水")
+        private Integer totalMoney;
+
+
+    }
+
+    /**
+     * 每月流水
+     */
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceFlowMonthVO {
+        @ApiModelProperty(value = "设备ID")
+        private Long deviceId;
+        @ApiModelProperty(value = "月份")
+        private Integer month;
+        @ApiModelProperty(value = "当月流水")
+        private Integer monthMoney;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceFlowDetailExcelVO {
+        @ExcelProperty("月份")
+        @ApiModelProperty(value = "月份")
+        private Integer month;
+
+//        @ExcelProperty("设备编号")
+//        @ApiModelProperty(value = "设备ID")
+//        private Long deviceId;
+
+        @ApiModelProperty(value = "当月流水")
+        @ExcelProperty(value = "当月流水", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        private Integer monthMoney;
+
+        @ApiModelProperty(value = "收入")
+        @ExcelProperty(value = "收入", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        private Integer incomeMoney;
+
+        @ApiModelProperty(value = "支出")
+        @ExcelProperty(value = "支出", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        private Integer expenditureMoney;
+
+
+    }
+
+    /**
+     * 流水明细
+     */
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceFlowDetailVO {
+        @ApiModelProperty(value = "投放时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime activeTime;
+
+        @ApiModelProperty(value = "设备ID")
+        private Long deviceId;
+
+        @ApiModelProperty(value = "月平均流水")
+        private BigDecimal monthAvgMoney;
+
+        @ApiModelProperty(value = "总计流水")
+        private Integer totalMoney;
+
+        @ApiModelProperty(value = "流水明细")
+        private List<DeviceFlowDetail> details;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceFlowDetail {
+        @ApiModelProperty(value = "设备ID")
+        private Long deviceId;
+        @ApiModelProperty(value = "月份")
+        private Integer month;
+        @ApiModelProperty(value = "当月流水")
+        private Integer monthMoney;
+
+        @ApiModelProperty(value = "收入")
+        private Integer incomeMoney;
+
+        @ApiModelProperty(value = "支出")
+        private Integer expenditureMoney;
+
+    }
+
 }

+ 287 - 0
device-api/src/main/java/com/xy/dto/DeviceSimChargeDto.java

@@ -1,6 +1,12 @@
 package com.xy.dto;
 
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.NumberFormat;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.xy.annotate.DictFormat;
+import com.xy.consts.DictConsts;
+import com.xy.convert.CustomFenToYuanConverter;
+import com.xy.convert.DictConvert;
 import com.xy.utils.PageBean;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -35,6 +41,287 @@ public class DeviceSimChargeDto {
         private LocalDateTime endCreateTime;
     }
 
+    @Data
+    @Accessors(chain = true)
+    public static class PageExcelVo {
+        @ExcelProperty("商户名称")
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+
+        @ExcelProperty("缴费单号")
+        @ApiModelProperty(value = "缴费单号")
+        private String orderId;
+
+        @ExcelProperty("流量卡号")
+        @ApiModelProperty(value = "流量卡id")
+        private String simId;
+
+
+        @ApiModelProperty(value = "金额")
+        @ExcelProperty(value = "金额", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        private Integer money;
+
+        @ApiModelProperty(value = "佣金")
+        @ExcelProperty(value = "佣金", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        private Integer agentMoney;
+
+        @ExcelProperty("续费时长(年)")
+        @ApiModelProperty(value = "数量")
+        private Integer size;
+
+        @ExcelProperty(value = "支付方式", converter = DictConvert.class)
+        @DictFormat(DictConsts.ORDER_PAY_TYPE)
+        @ApiModelProperty(value = "支付方式")
+        private Integer payType;
+
+
+        @ExcelProperty(value = "支付状态", converter = DictConvert.class)
+        @DictFormat(DictConsts.ORDER_MERC_MANAGE_STATUS)
+        @ApiModelProperty(value = "支付状态")
+        private Integer status;
+
+        @ExcelProperty("支付时间")
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ExcelProperty("过期时间")
+        @ApiModelProperty(value = "过期时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime timeout;
+
+        @ApiModelProperty(value = "状态")
+        @ExcelProperty("过期状态说明")
+        private String timeoutStatus;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class SpendPageExcelVo {
+        @ExcelProperty("商户名称")
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+
+        @ExcelProperty("缴费单号")
+        @ApiModelProperty(value = "缴费单号")
+        private String orderId;
+
+        @ExcelProperty("流量卡号")
+        @ApiModelProperty(value = "流量卡id")
+        private String simId;
+
+
+        @ApiModelProperty(value = "金额")
+        @ExcelProperty(value = "金额", converter = CustomFenToYuanConverter.class)
+        @NumberFormat("#0.00")
+        private Integer money;
+
+
+        @ExcelProperty("续费时长(年)")
+        @ApiModelProperty(value = "数量")
+        private Integer size;
+
+        @ExcelProperty(value = "支付方式", converter = DictConvert.class)
+        @DictFormat(DictConsts.ORDER_PAY_TYPE)
+        @ApiModelProperty(value = "支付方式")
+        private Integer payType;
+
+
+        @ExcelProperty(value = "支付状态", converter = DictConvert.class)
+        @DictFormat(DictConsts.ORDER_MERC_MANAGE_STATUS)
+        @ApiModelProperty(value = "支付状态")
+        private Integer status;
+
+        @ExcelProperty("支付时间")
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ExcelProperty("过期时间")
+        @ApiModelProperty(value = "过期时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime timeout;
+
+        @ApiModelProperty(value = "状态")
+        @ExcelProperty("过期状态说明")
+        private String timeoutStatus;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class MySpendPageVO {
+
+        @ApiModelProperty(value = "过期时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime timeout;
+
+        @ApiModelProperty(value = "过期状态说明")
+        private String timeoutStatus;
+
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "订单id")
+        private String orderId;
+
+        @ApiModelProperty(value = "流量卡id")
+        private String simId;
+
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+
+        @ApiModelProperty(value = "金额")
+        private Integer money;
+
+        @ApiModelProperty(value = "代理商金额")
+        private Integer agentMoney;
+
+        @ApiModelProperty(value = "数量")
+        private Integer size;
+
+        @ApiModelProperty(value = "支付方式")
+        private Integer payType;
+
+        @ApiModelProperty(value = "状态")
+        private Integer status;
+
+        @ApiModelProperty(value = "备注")
+        private String note;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "附件")
+        private String files;
+
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+
+
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class PageByTopMercVO {
+
+        @ApiModelProperty(value = "过期时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime timeout;
+
+        @ApiModelProperty(value = "过期状态说明")
+        private String timeoutStatus;
+
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "订单id")
+        private String orderId;
+
+        @ApiModelProperty(value = "流量卡id")
+        private String simId;
+
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+
+        @ApiModelProperty(value = "金额")
+        private Integer money;
+
+        @ApiModelProperty(value = "代理商金额")
+        private Integer agentMoney;
+
+        @ApiModelProperty(value = "数量")
+        private Integer size;
+
+        @ApiModelProperty(value = "支付方式")
+        private Integer payType;
+
+        @ApiModelProperty(value = "状态")
+        private Integer status;
+
+        @ApiModelProperty(value = "备注")
+        private String note;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "附件")
+        private String files;
+
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class PageByTopMerc {
+
+        @ApiModelProperty("分页对象")
+        private PageBean page;
+
+        @ApiModelProperty("是否导出当前页")
+        private Boolean exportPage = true;
+        @ApiModelProperty(value = "创建时间-起")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime beginCreateTime;
+        @ApiModelProperty(value = "创建时间-始")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime endCreateTime;
+        @ApiModelProperty(value = "商户id")
+        private Long curMercId;
+        @ApiModelProperty(value = "指定商户id")
+        private Long chooseMercId;
+        @ApiModelProperty(value = "id")
+        private Long id;
+        @ApiModelProperty(value = "订单id")
+        private String orderId;
+        @ApiModelProperty(value = "流量卡id")
+        private String simId;
+        @ApiModelProperty(value = "金额")
+        private Integer money;
+        @ApiModelProperty(value = "数量")
+        private Integer size;
+        @ApiModelProperty(value = "支付方式")
+        private Integer payType;
+        @ApiModelProperty(value = "状态")
+        private Integer status;
+        @ApiModelProperty(value = "备注")
+        private String note;
+        @ApiModelProperty(value = "附件")
+        private String files;
+
+        // size -1 不分页
+        public PageBean getPage() {
+            if (!this.exportPage) {
+                this.page.setSize(-1L);
+            }
+            return page;
+        }
+
+
+    }
+
+
     @Data
     @Accessors(chain = true)
     public static class Vo {

+ 104 - 0
device-api/src/main/java/com/xy/dto/DeviceTypeAlgorithmBeforConfigDto.java

@@ -7,6 +7,7 @@ import lombok.experimental.Accessors;
 
 import javax.validation.constraints.NotNull;
 import java.time.LocalDateTime;
+import java.util.List;
 
 /**
  * <p>
@@ -22,8 +23,105 @@ public class DeviceTypeAlgorithmBeforConfigDto {
     @Accessors(chain = true)
     public static class SelectList extends Vo {
 
+        @ApiModelProperty(value = "商户编码")
+        private List<String> mercCodes;
     }
 
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceActiveFeeDTO {
+        @ApiModelProperty(value = "id")
+        private Long id;
+        @NotNull(message = "商户ID不可为空")
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+
+        @ApiModelProperty(value = "设备类型")
+        private Integer deviceType;
+
+        @ApiModelProperty(value = "算法id")
+        private Long algorithmId;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceActiveFeeVO {
+
+        @ApiModelProperty(value = "字典默认配置")
+        private List<DeviceActiveDictVO> deviceActiveDicts;
+
+        @ApiModelProperty(value = "平台给商家定义的配置")
+        private List<DeviceActiveMercFeeVO> deviceActiveMercFees;
+
+    }
+
+    /**
+     * 平台给商家定义的费用配置
+     */
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceActiveMercFeeVO {
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+
+        @ApiModelProperty(value = "设备类型")
+        private Integer deviceType;
+
+        @ApiModelProperty(value = "算法id")
+        private Long algorithmId;
+
+        @ApiModelProperty(value = "算法名称")
+        private String algorithmName;
+
+        @ApiModelProperty(value = "预充金额;单位:分")
+        private Integer money;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+
+        @ApiModelProperty(value = "商户编码")
+        private String mercCode;
+
+        @ApiModelProperty(value = "代理商额外收取金额;单位:分")
+        private Integer extraMoney;
+
+
+    }
+
+    /**
+     * 字典默认配置
+     */
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceActiveDictVO {
+        @ApiModelProperty(value = "算法笔数")
+        private Integer size;
+
+        @ApiModelProperty(value = "算法id")
+        private Long algorithmId;
+
+        @ApiModelProperty(value = "算法名称")
+        private String algorithmName;
+
+        @ApiModelProperty(value = "预充金额;单位:分")
+        private Integer money;
+
+
+    }
+
+
     @Data
     @Accessors(chain = true)
     public static class Save extends Vo {
@@ -94,6 +192,12 @@ public class DeviceTypeAlgorithmBeforConfigDto {
         @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
         private LocalDateTime updateTime;
 
+        @ApiModelProperty(value = "商户编码")
+        private String mercCode;
+
+        @ApiModelProperty(value = "代理商额外收取金额;单位:分")
+        private Integer extraMoney;
+
 
     }
 

+ 179 - 0
device-api/src/main/java/com/xy/dto/MercFeeConfigAlgorithmTypeDto.java

@@ -0,0 +1,179 @@
+package com.xy.dto;
+
+import java.time.LocalDateTime;
+
+import java.io.Serializable;
+import java.util.List;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+import com.xy.utils.PageBean;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+/**
+ * <p>
+ * 商户算法扣费标准配置扩展
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+public class MercFeeConfigAlgorithmTypeDto {
+
+    @Data
+    @Accessors(chain = true)
+    public static class SelectList extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class ListByFeeConfigDTO extends Vo {
+        @NotNull(message = "mercId不能为空")
+        @ApiModelProperty(value = "商户id", required = true)
+        private Long mercId;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class SimPayQueryDTO {
+        @NotNull(message = "商户id不能为空")
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Page extends Vo {
+
+        @ApiModelProperty(value = "分页对象", required = true)
+        private PageBean page;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Save extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Update extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceAlgorithmConfigVO {
+        @ApiModelProperty(value = "算法费-平台默认配置")
+        private List<DeviceAlgorithmPlatformVO> deviceAcPlatformList;
+        @ApiModelProperty(value = "算法费-商家自定义费用")
+        private List<DeviceAlgorithmMercVO> deviceAcMercList;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceAlgorithmPlatformVO {
+
+        @ApiModelProperty(value = "包月费用,单位 分")
+        private Integer moonMoney;
+        @ApiModelProperty(value = "包月笔数")
+        private Integer moonSize;
+        @ApiModelProperty(value = "单笔费用,单位 分")
+        private Integer singleMoney;
+        @ApiModelProperty(value = "算法类型")
+        private Long algorithmId;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceAlgorithmMercVO {
+
+        @ApiModelProperty(value = "ID")
+        private Long id;
+
+        @ApiModelProperty(value = "商户编码")
+        private String mercCode;
+
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "创建人")
+        private Long createUser;
+
+        @ApiModelProperty(value = "更新人")
+        private Long updateUser;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "算法ID")
+        private Long algorithmId;
+
+        @ApiModelProperty(value = "包月费用(比平台多收的金额)")
+        private Integer extraMonthMoney;
+
+        @ApiModelProperty(value = "算法单笔金额(比平台多收的金额)")
+        private Integer extraSingleMoney;
+
+        @ApiModelProperty(value = "平台包月费用,单位 分")
+        private Integer moonMoney;
+        @ApiModelProperty(value = "平台单笔费用,单位 分")
+        private Integer singleMoney;
+        @ApiModelProperty(value = "包月笔数")
+        private Integer moonSize;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Vo {
+
+        @ApiModelProperty(value = "ID")
+        private Long id;
+
+        @ApiModelProperty(value = "商户编码")
+        private String mercCode;
+
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "创建人")
+        private Long createUser;
+
+        @ApiModelProperty(value = "更新人")
+        private Long updateUser;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "算法ID")
+        private Long algorithmId;
+
+        @ApiModelProperty(value = "包月费用(比平台多收的金额)")
+        private Integer extraMonthMoney;
+
+        @ApiModelProperty(value = "算法单笔金额(比平台多收的金额)")
+        private Integer extraSingleMoney;
+
+
+    }
+
+}

+ 165 - 0
device-api/src/main/java/com/xy/dto/MercFeeConfigSimCardDto.java

@@ -0,0 +1,165 @@
+package com.xy.dto;
+
+import java.time.LocalDateTime;
+
+import java.io.Serializable;
+import java.util.List;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+import com.xy.utils.PageBean;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * <p>
+ * 商户流量卡费配置扩展
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+public class MercFeeConfigSimCardDto {
+    @Data
+    @Accessors(chain = true)
+    public static class Delete {
+
+        @NotNull(message = "id不能为空")
+        @ApiModelProperty(value = "id")
+        private Long id;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceSimConfigVO {
+        @ApiModelProperty(value = "流量卡费-平台默认配置")
+        private List<DeviceSimPlatformVO> deviceSimPlatformList;
+        @ApiModelProperty(value = "流量卡费-商家自定义费用")
+        private List<DeviceSimMercVO> deviceSimMercList;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceSimPlatformVO {
+
+        @ApiModelProperty(value = "名称")
+        private String name;
+        @ApiModelProperty(value = "年费,单位 分")
+        private Integer money;
+        @ApiModelProperty(value = "即将过期天数")
+        private Integer expireDay;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceSimMercVO {
+
+        @ApiModelProperty(value = "ID")
+        private Long id;
+
+        @ApiModelProperty(value = "商户编码")
+        private String mercCode;
+
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "创建人")
+        private Long createUser;
+
+        @ApiModelProperty(value = "更新人")
+        private Long updateUser;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "流量卡费金额(比平台多收的金额)")
+        private Integer extraMoney;
+
+        @ApiModelProperty(value = "名称")
+        private String name;
+        @ApiModelProperty(value = "年费,单位 分")
+        private Integer money;
+        @ApiModelProperty(value = "即将过期天数")
+        private Integer expireDay;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DeviceSimPayVO {
+        @ApiModelProperty(value = "名称")
+        private String name;
+        @ApiModelProperty(value = "年费,单位 分")
+        private Integer money;
+
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class SelectList extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Page extends Vo {
+
+        @ApiModelProperty(value = "分页对象", required = true)
+        private PageBean page;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Save extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Update extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Vo {
+
+        @ApiModelProperty(value = "ID")
+        private Long id;
+
+        @ApiModelProperty(value = "商户编码")
+        private String mercCode;
+
+        @ApiModelProperty(value = "商户id")
+        private Long mercId;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "创建人")
+        private Long createUser;
+
+        @ApiModelProperty(value = "更新人")
+        private Long updateUser;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "流量卡费金额(比平台多收的金额)")
+        private Integer extraMoney;
+
+
+    }
+
+}

+ 125 - 0
device-api/src/main/java/com/xy/dto/MercFeeCountDayDto.java

@@ -0,0 +1,125 @@
+package com.xy.dto;
+
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.xy.utils.PageBean;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 商户佣金费用收益每日统计(不含今天)
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+public class MercFeeCountDayDto {
+    @Data
+    @Accessors(chain = true)
+    public static class ExcuteDayDTO {
+        @NotBlank(message = "日期不可为空yyyyMMdd")
+        @ApiModelProperty(value = "分页对象", required = true)
+        private String date;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class SelectList extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Page extends Vo {
+
+        @ApiModelProperty(value = "分页对象", required = true)
+        private PageBean page;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Save extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Update extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class CountByMonth {
+        @ApiModelProperty("统计月份202206")
+        private Integer monthValue;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class CountByMonthVO {
+        @ApiModelProperty(value = "商户ID")
+        private Long mercId;
+
+        @ApiModelProperty(value = "父商户ID")
+        private Long parentMercId;
+
+        @ApiModelProperty(value = "缴费金额")
+        private Integer payMoney;
+
+        @ApiModelProperty(value = "佣金")
+        private Integer brokerage;
+
+        @ApiModelProperty(value = "缴费类型")
+        private Integer feeType;
+
+
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class Vo {
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "商户ID")
+        private Long mercId;
+
+        @ApiModelProperty(value = "父商户ID")
+        private Long parentMercId;
+
+        @ApiModelProperty(value = "统计日期20220603")
+        private Integer dateValue;
+
+        @ApiModelProperty(value = "统计日期202206")
+        private Integer monthValue;
+
+        @ApiModelProperty(value = "缴费金额")
+        private Integer payMoney;
+
+        @ApiModelProperty(value = "佣金")
+        private Integer brokerage;
+
+        @ApiModelProperty(value = "缴费类型")
+        private Integer feeType;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+
+    }
+
+}

+ 125 - 0
device-api/src/main/java/com/xy/dto/MercFeeCountMonthDto.java

@@ -0,0 +1,125 @@
+package com.xy.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.xy.utils.PageBean;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 商户佣金费用收益每月统计(不含本月)
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+public class MercFeeCountMonthDto {
+    @Data
+    @Accessors(chain = true)
+    public static class ExcuteDayDTO {
+        @NotBlank(message = "日期不可为空yyyyMM")
+        @ApiModelProperty(value = "分页对象", required = true)
+        private String date;
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class SelectList extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Page extends Vo {
+        @ApiModelProperty(value = "月份-起")
+      
+        private String beginTime;
+
+        @ApiModelProperty(value = "月份-止")
+
+        private String endTime;
+
+        @ApiModelProperty(value = "分页对象", required = true)
+        private PageBean page;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class ConfirmDTO {
+        @NotNull(message = "确认对象不可为空!")
+        @ApiModelProperty(value = "ID", required = true)
+        private Long id;
+
+        @ApiModelProperty(value = "父商户ID", hidden = true)
+        private Long parentMercId;
+
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Save extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Update extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Vo {
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "商户ID")
+        private Long mercId;
+
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+
+        @ApiModelProperty(value = "父商户ID")
+        private Long parentMercId;
+
+
+        @ApiModelProperty(value = "统计日期202206")
+        private Integer dateValue;
+
+        @ApiModelProperty(value = "缴费金额")
+        private Integer payMoney;
+
+        @ApiModelProperty(value = "佣金")
+        private Integer brokerage;
+
+        @ApiModelProperty(value = "缴费类型;字典-merc_fee_type")
+        private Integer feeType;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "是否确认")
+        private Boolean verify;
+
+        @ApiModelProperty(value = "确认时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime verifyTime;
+
+
+    }
+
+}

+ 36 - 0
device-api/src/main/java/com/xy/dto/MercFeeExtraDTO.java

@@ -0,0 +1,36 @@
+package com.xy.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.xy.utils.PageBean;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * <p>
+ * 商户扩展费用
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+public class MercFeeExtraDTO {
+    @Data
+    @Accessors(chain = true)
+    public static class Query {
+
+        @NotNull(message = "商户ID不能为空")
+        @ApiModelProperty(value = "商户ID")
+        private Long mercId;
+
+        @NotNull(message = "查询类型不可为空")
+        @ApiModelProperty(value = "类型 1设备管理费。2设备激活费。3算法扣费标准。4流量卡费")
+        private Integer type;
+    }
+
+
+}

+ 127 - 0
device-api/src/main/java/com/xy/dto/MercFeeSettleDto.java

@@ -0,0 +1,127 @@
+package com.xy.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.xy.utils.PageBean;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * <p>
+ * 商户佣金费用结算
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+public class MercFeeSettleDto {
+
+    @Data
+    @Accessors(chain = true)
+    public static class SelectList extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Page extends Vo {
+        @ApiModelProperty(value = "创建时间-起")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime beginCreateTime;
+
+        @ApiModelProperty(value = "创建时间-始")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime endCreateTime;
+
+        @ApiModelProperty(value = "分页对象", required = true)
+        private PageBean page;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class ApplyDTO {
+
+        @ApiModelProperty(value = "商户ID", hidden = true)
+        private Long mercId;
+
+        @NotNull(message = "结算金额不可为空")
+        @ApiModelProperty(value = "结算金额")
+        private Integer settleMoney;
+
+        @ApiModelProperty(value = "发票图片(最多支持4个,|分隔)")
+        private String titleImg;
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class Save extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DoSettle {
+        @NotEmpty(message = "未选择操作对象")
+        @ApiModelProperty(value = "ids")
+        private List<Long> ids;
+
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class Update extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Vo {
+
+        @ApiModelProperty(value = "id")
+        private Long id;
+
+        @ApiModelProperty(value = "商户ID")
+        private Long mercId;
+
+        @ApiModelProperty(value = "商户名称")
+        private String mercName;
+
+        @ApiModelProperty(value = "结算金额")
+        private Integer settleMoney;
+
+        @ApiModelProperty(value = "申请时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "申请人")
+        private Long createUser;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+        @ApiModelProperty(value = "结算状态(1未结算、结算中、2已结算)")
+        private Integer settleState;
+
+        @ApiModelProperty(value = "结算完成时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime finishSettleTime;
+
+        @ApiModelProperty(value = "发票图片(最多支持4个,|分隔)")
+        private String titleImg;
+
+        @ApiModelProperty(value = "结算人")
+        private Long updateUser;
+
+
+    }
+
+}

+ 97 - 0
device-api/src/main/java/com/xy/dto/MercFeeStatisticDto.java

@@ -0,0 +1,97 @@
+package com.xy.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.xy.utils.PageBean;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 商户佣金费用统计
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-24
+ */
+public class MercFeeStatisticDto {
+
+    @Data
+    @Accessors(chain = true)
+    public static class SelectList extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Page extends Vo {
+
+        @ApiModelProperty(value = "分页对象", required = true)
+        private PageBean page;
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Save extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Update extends Vo {
+
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class Vo {
+
+        @ApiModelProperty(value = "商户ID")
+        private Long mercId;
+
+        @ApiModelProperty(value = "累计已结算佣金")
+        private Integer settleMoney;
+
+        @ApiModelProperty(value = "可结算佣金")
+        private Integer unSettleMoney;
+
+        @ApiModelProperty(value = "累计已确认佣金")
+        private Integer verifyMoney;
+
+        @ApiModelProperty(value = "创建时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime createTime;
+
+        @ApiModelProperty(value = "更新时间")
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private LocalDateTime updateTime;
+
+
+    }
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class InFoVO {
+
+        @ApiModelProperty(value = "商户ID")
+        private Long mercId;
+
+        @ApiModelProperty(value = "累计已结算佣金")
+        private Integer settleMoney;
+
+        @ApiModelProperty(value = "可结算佣金")
+        private Integer unSettleMoney;
+
+        @ApiModelProperty(value = "累计已确认佣金")
+        private Integer verifyMoney;
+
+        @ApiModelProperty(value = "结算中金额")
+        private Integer settlingMoney;
+
+    }
+
+}

+ 14 - 0
device-api/src/main/java/com/xy/service/DeviceInfoService.java

@@ -1,6 +1,7 @@
 package com.xy.service;
 
 import com.xy.annotate.RestMappingController;
+import com.xy.dto.DeviceDataDto;
 import com.xy.dto.DeviceInfoDto;
 import com.xy.dto.DeviceSysinfoDto;
 import com.xy.utils.PageBean;
@@ -9,6 +10,7 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 
+import javax.validation.Valid;
 import java.util.List;
 import java.util.Map;
 
@@ -26,6 +28,7 @@ public interface DeviceInfoService {
     /**
      * 简单商户设备分页
      * 只返回设备ID和名称
+     *
      * @param dto
      * @return
      */
@@ -109,6 +112,16 @@ public interface DeviceInfoService {
     @PostMapping("page")
     R<PageBean<DeviceInfoDto.Vo2>> page(@RequestBody DeviceInfoDto.Page page);
 
+    /**
+     * 设备流水统计
+     *
+     * @param dto
+     * @return
+     */
+    @PostMapping("deviceFlowCountPage")
+    R<PageBean<DeviceDataDto.DeviceFlowCountVO>> deviceFlowCountPage(@RequestBody @Valid DeviceDataDto.DeviceFlowCountDTO dto);
+
+
     /**
      * 更新商户点位
      *
@@ -218,6 +231,7 @@ public interface DeviceInfoService {
 
     @PostMapping("updateLonByPlaceId")
     R updateLonByPlaceId(@RequestBody @Validated DeviceInfoDto.UpdateLonByPlaceId dto);
+
     /**
      * 激活数量统计
      *

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

@@ -0,0 +1,24 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+import com.xy.dto.MercFeeConfigAlgorithmTypeDto;
+import com.xy.utils.R;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+/**
+ * <p>
+ * 商户算法扣费标准配置扩展 服务类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+@RestMappingController("/merc-fee-config-algorithm-type")
+public interface MercFeeConfigAlgorithmTypeService {
+    @PostMapping("listByFeeConfig")
+    R<MercFeeConfigAlgorithmTypeDto.DeviceAlgorithmConfigVO> listByFeeConfig(@RequestBody @Validated MercFeeConfigAlgorithmTypeDto.ListByFeeConfigDTO dto);
+
+}

+ 34 - 0
device-api/src/main/java/com/xy/service/MercFeeConfigSimCardService.java

@@ -0,0 +1,34 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+import com.xy.dto.MercFeeConfigAlgorithmTypeDto;
+import com.xy.dto.MercFeeConfigSimCardDto;
+import com.xy.utils.R;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 商户流量卡费配置扩展 服务类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-07
+ */
+@RestMappingController("/merc-fee-config-sim-card")
+public interface MercFeeConfigSimCardService {
+
+    /**
+     * 商户自定义流量卡费用
+     *
+     * @param dto
+     * @return
+     */
+    @PostMapping("listByMerc")
+    R<List<MercFeeConfigSimCardDto.DeviceSimPayVO>> listByMerc(@RequestBody @Validated MercFeeConfigAlgorithmTypeDto.SimPayQueryDTO dto);
+
+}

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

@@ -0,0 +1,16 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+
+/**
+ * <p>
+ * 商户佣金费用收益每日统计(不含今天) 服务类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@RestMappingController("/merc-fee-count-day")
+public interface MercFeeCountDayService {
+
+}

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

@@ -0,0 +1,16 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+
+/**
+ * <p>
+ * 商户佣金费用收益每月统计(不含本月) 服务类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@RestMappingController("/merc-fee-count-month")
+public interface MercFeeCountMonthService {
+
+}

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

@@ -0,0 +1,16 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+
+/**
+ * <p>
+ * 商户佣金费用结算 服务类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-23
+ */
+@RestMappingController("/merc-fee-settle")
+public interface MercFeeSettleService {
+
+}

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

@@ -0,0 +1,16 @@
+package com.xy.service;
+
+import com.xy.annotate.RestMappingController;
+
+/**
+ * <p>
+ * 商户佣金费用统计 服务类
+ * </p>
+ *
+ * @author 谭斌
+ * @since 2024-04-24
+ */
+@RestMappingController("/merc-fee-statistic")
+public interface MercFeeStatisticService {
+
+}

+ 48 - 0
device-api/src/main/java/com/xy/utils/enums/MercFeeSettleSate.java

@@ -0,0 +1,48 @@
+package com.xy.utils.enums;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.ToString;
+
+/**
+ * 佣金费用结算状态 (1 未结算、结算中、2 已结算)
+ */
+@Getter
+@ToString
+@AllArgsConstructor
+public enum MercFeeSettleSate {
+
+
+    S1(1, "未结算"),
+    S2(2, "结算中"),
+    S3(3, "已结算"),
+    ;
+
+    /**
+     * 编码值
+     */
+    private Integer code;
+
+    /**
+     * 描述
+     */
+    private String description;
+
+
+    /**
+     * 通过code获取enum
+     *
+     * @param code
+     * @return
+     */
+    public static MercFeeSettleSate getEnumByCode(Integer code) {
+        MercFeeSettleSate[] values = values();
+        for (MercFeeSettleSate value : values) {
+            if (value.getCode().equals(code)) {
+                return value;
+            }
+        }
+        return null;
+    }
+}