Przeglądaj źródła

pms 瑞都日报 加载中航北斗油耗数据 逻辑优化

zhangcl 2 dni temu
rodzic
commit
836d6cdc42
14 zmienionych plików z 404 dodań i 48 usunięć
  1. 3 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotcarzhbd/vo/IotCarZhbdPageReqVO.java
  2. 6 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdailyreportfuel/vo/IotDailyReportFuelPageReqVO.java
  3. 4 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotprojecttask/vo/IotProjectTaskPlatformVO.java
  4. 34 2
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/IotRdDailyReportController.java
  5. 24 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/IotCarDevicePlateVO.java
  6. 3 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/IotDeviceMapper.java
  7. 5 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotcarzhbd/IotCarZhbdMapper.java
  8. 1 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotdailyreportfuel/IotDailyReportFuelMapper.java
  9. 0 42
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotrydailyreport/IotRyDailyReportMapper.java
  10. 90 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/IotAllZhbdJob.java
  11. 158 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/dailyreport/CreateRyDailyReportOrderJob.java
  12. 4 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/httpEntity/ResponseOilData.java
  13. 58 4
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/util/ZHBDUtil.java
  14. 14 0
      yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotDeviceMapper.xml

+ 3 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotcarzhbd/vo/IotCarZhbdPageReqVO.java

@@ -45,4 +45,7 @@ public class IotCarZhbdPageReqVO extends PageParam {
 
     @Schema(description = "设备编码 与设备表额外匹配的编码", example = "10570")
     private Collection<String> customDeviceCodes;
+
+    @Schema(description = "中航北斗 carId 集合", example = "10570")
+    private Collection<String> carIds;
 }

+ 6 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdailyreportfuel/vo/IotDailyReportFuelPageReqVO.java

@@ -9,6 +9,7 @@ import org.springframework.format.annotation.DateTimeFormat;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.Collection;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
@@ -56,4 +57,9 @@ public class IotDailyReportFuelPageReqVO extends PageParam {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
 
+    /**
+     * 扩展属性
+     */
+    @Schema(description = "日报id集合", example = "你猜")
+    private Collection<Long> reportIds;
 }

+ 4 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotprojecttask/vo/IotProjectTaskPlatformVO.java

@@ -5,6 +5,7 @@ import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Set;
 
@@ -39,4 +40,7 @@ public class IotProjectTaskPlatformVO {
 
     @Schema(description = "任务状态 数据字典label值", example = "施工")
     private String rdStatusLabel;
+
+    @Schema(description = "关联井当日油耗", example = "12.3")
+    private BigDecimal dailyFuel;
 }

+ 34 - 2
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/IotRdDailyReportController.java

@@ -486,7 +486,6 @@ public class IotRdDailyReportController {
             dailyReportVO.setDeptName(dept.getName());
         }
 
-
         // 日报任务对应的平台井列表
         if (1 == dailyReport.getPlatformWell()) {
             // 查询未施工完成的平台井 关联井列表
@@ -500,15 +499,19 @@ public class IotRdDailyReportController {
             List<IotRdDailyReportDO> reports = iotRdDailyReportService.dailyReports(reportReqVO);
             // key任务id  value日报id
             Map<Long, Long> reportPair = new HashMap<>();
+            // key任务id  value任务井对应日报当日油耗
+            Map<Long, BigDecimal> reportFuelPair = new HashMap<>();
             // key任务id  value平台井日报已经设置的多种属性
             Map<Long, IotProjectTaskPlatformVO> platformPair = new HashMap<>();
+            Set<Long> reportIds = new HashSet<>();
             if (CollUtil.isNotEmpty(reports)) {
                 reports.forEach(report -> {
+                    reportIds.add(report.getId());
                     // 保养平台井关联的多个日报使用
                     reportPair.put(report.getTaskId(), report.getId());
                     // 设置 平台关联井 已经设置的 属性 施工状态 施工工艺 工作量属性
                     // 查询 平台关联井详情使用
-
+                    reportFuelPair.put(report.getTaskId(), report.getDailyFuel());
                     IotProjectTaskPlatformVO platformVO = new IotProjectTaskPlatformVO();
                     platformVO.setRdStatus(report.getRdStatus());
                     if (StrUtil.isNotBlank(report.getRdStatus()) && statusDictPair.containsKey(report.getRdStatus())) {
@@ -528,6 +531,27 @@ public class IotRdDailyReportController {
                     platformPair.put(report.getTaskId(), platformVO);
                 });
             }
+            // 查询多个日报id 对应的 已经保存的油耗记录
+            IotDailyReportFuelPageReqVO fuelReqVO = new IotDailyReportFuelPageReqVO();
+            fuelReqVO.setType("RD");
+            fuelReqVO.setReportIds(reportIds);
+            List<IotDailyReportFuelDO> relatedReportFuels = iotDailyReportFuelService.getIotDailyReportFuels(fuelReqVO);
+            Map<Long, List<IotDailyReportFuelDO>> reportFuelsPair = new HashMap<>();
+            if (CollUtil.isNotEmpty(relatedReportFuels)) {
+                relatedReportFuels.forEach(fuel -> {
+                    if (reportFuelsPair.containsKey(fuel.getReportId())) {
+                        List<IotDailyReportFuelDO> tempFuels = reportFuelsPair.get(fuel.getReportId());
+                        tempFuels.add(fuel);
+                        reportFuelsPair.put(fuel.getReportId(), tempFuels);
+                    } else {
+                        List<IotDailyReportFuelDO> tempFuels = new ArrayList<>();
+                        tempFuels.add(fuel);
+                        reportFuelsPair.put(fuel.getReportId(), tempFuels);
+                    }
+                });
+            }
+            // 返回已经填报的油耗记录
+
             List<IotProjectTaskPlatformVO> platforms = new ArrayList<>();
             if (CollUtil.isNotEmpty(tasks)) {
                 tasks.forEach(task -> {
@@ -538,6 +562,7 @@ public class IotRdDailyReportController {
                         platform.setWellName(task.getWellName());
                         platform.setWorkloadDesign(task.getWorkloadDesign());
                         platform.setReportId(reportPair.get(task.getId()));
+                        platform.setDailyFuel(reportFuelPair.get(task.getId()));
                         if (platformPair.containsKey(task.getId())) {
                             IotProjectTaskPlatformVO tempPlatform = platformPair.get(task.getId());
                             platform.setRdStatus(tempPlatform.getRdStatus());
@@ -555,6 +580,8 @@ public class IotRdDailyReportController {
                 List<IotProjectTaskPlatformVO> finishedPlatforms = new ArrayList<>();
                 // key任务井id   value任务井名称
                 Map<Long, String> wellNamePair = new HashMap<>();
+                // key任务id  value任务井对应日报当日油耗
+                Map<Long, BigDecimal> finishedReportFuelPair = new HashMap<>();
                 // 查询当前任务关联的平台井任务列表
                 IotProjectTaskPageReqVO currentPlatformTaskReqVO = new IotProjectTaskPageReqVO();
                 currentPlatformTaskReqVO.setPlatformGroup(dailyReport.getTaskPlatform());
@@ -576,9 +603,14 @@ public class IotRdDailyReportController {
                 }
                 if (CollUtil.isNotEmpty(currentRelatedReports)) {
                     currentRelatedReports.forEach(report -> {
+                        if (reportFuelsPair.containsKey(report.getId())) {
+                            List<IotDailyReportFuelDO> finishedReportFuels = reportFuelsPair.get(report.getId());
+                            dailyReportVO.setReportedFuels(finishedReportFuels);
+                        }
                         if (StrUtil.isNotBlank(report.getRdStatus())) {
                             IotProjectTaskPlatformVO platform = new IotProjectTaskPlatformVO();
                             platform.setId(report.getTaskId());
+                            platform.setDailyFuel(report.getDailyFuel());
                             if (wellNamePair.containsKey(report.getTaskId())) {
                                 platform.setWellName(wellNamePair.get(report.getTaskId()));
                             }

+ 24 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/vo/IotCarDevicePlateVO.java

@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.pms.controller.admin.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 设备台账 车辆设备 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotCarDevicePlateVO {
+
+    @Schema(description = "设备id")
+    private Long deviceId;
+
+    @Schema(description = "资产编码")
+    private String deviceCode;
+
+    @Schema(description = "设备名称")
+    private String deviceName;
+
+    @Schema(description = "规格型号")
+    private String licensePlate;
+
+}

+ 3 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/IotDeviceMapper.java

@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.SortablePageParam;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainWorkOrderPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotCarDevicePlateVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
@@ -264,6 +265,8 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> {
 
     IPage<IotDeviceRespVO> deviceAssociateBomListPage(IPage<IotDeviceRespVO> page,
                                                       @Param("deviceIds") Collection<Long> deviceIds, @Param("bomFlag") String bomFlag);
+
+    List<IotCarDevicePlateVO> allCarsContainsPlates();
     default Long selectCountByTimeAndStatus(IotDevicePageReqVO reqVO) {
         return selectCount(new LambdaQueryWrapperX<IotDeviceDO>()
                 .eqIfPresent(IotDeviceDO::getDeviceStatus, reqVO.getDeviceStatus())

+ 5 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotcarzhbd/IotCarZhbdMapper.java

@@ -1,8 +1,10 @@
 package cn.iocoder.yudao.module.pms.dal.mysql.iotcarzhbd;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdPageReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotcarzhbd.IotCarZhbdDO;
 import org.apache.ibatis.annotations.Mapper;
@@ -28,12 +30,15 @@ public interface IotCarZhbdMapper extends BaseMapperX<IotCarZhbdDO> {
                 .orderByDesc(IotCarZhbdDO::getId));
     }
 
+    @DataPermission(enable = false)
+    @TenantIgnore
     default List<IotCarZhbdDO> selectList(IotCarZhbdPageReqVO reqVO) {
         return selectList(new LambdaQueryWrapperX<IotCarZhbdDO>()
                 .eqIfPresent(IotCarZhbdDO::getDeviceCode, reqVO.getDeviceCode())
                 .inIfPresent(IotCarZhbdDO::getDeviceCode, reqVO.getDeviceCodes())
                 .likeIfPresent(IotCarZhbdDO::getDeviceName, reqVO.getDeviceName())
                 .eqIfPresent(IotCarZhbdDO::getCarId, reqVO.getCarId())
+                .inIfPresent(IotCarZhbdDO::getCarId, reqVO.getCarIds())
                 .betweenIfPresent(IotCarZhbdDO::getCreateTime, reqVO.getCreateTime())
                 .likeIfPresent(IotCarZhbdDO::getUserName, reqVO.getUserName())
                 .inIfPresent(IotCarZhbdDO::getUserName, reqVO.getCustomDeviceCodes())

+ 1 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotdailyreportfuel/IotDailyReportFuelMapper.java

@@ -38,6 +38,7 @@ public interface IotDailyReportFuelMapper extends BaseMapperX<IotDailyReportFuel
         return selectList(new LambdaQueryWrapperX<IotDailyReportFuelDO>()
                 .eqIfPresent(IotDailyReportFuelDO::getType, reqVO.getType())
                 .eqIfPresent(IotDailyReportFuelDO::getReportId, reqVO.getReportId())
+                .inIfPresent(IotDailyReportFuelDO::getReportId, reqVO.getReportIds())
                 .eqIfPresent(IotDailyReportFuelDO::getDeviceId, reqVO.getDeviceId())
                 .eqIfPresent(IotDailyReportFuelDO::getDeviceCode, reqVO.getDeviceCode())
                 .eqIfPresent(IotDailyReportFuelDO::getYfDeviceCode, reqVO.getYfDeviceCode())

+ 0 - 42
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotrydailyreport/IotRyDailyReportMapper.java

@@ -28,48 +28,6 @@ import java.util.Objects;
 @Mapper
 public interface IotRyDailyReportMapper extends BaseMapperX<IotRyDailyReportDO> {
 
-    /* default PageResult<IotRyDailyReportDO> selectPage(IotRyDailyReportPageReqVO reqVO) {
-        // 获取查询参数中的projectClassification值
-        String projectClassification = reqVO.getProjectClassification();
-        return selectPage(reqVO, new LambdaQueryWrapperX<IotRyDailyReportDO>()
-                .eqIfPresent(IotRyDailyReportDO::getDeptId, reqVO.getDeptId())
-                .eqIfPresent(IotRyDailyReportDO::getProjectId, reqVO.getProjectId())
-                .eqIfPresent(IotRyDailyReportDO::getTaskId, reqVO.getTaskId())
-                // .eqIfPresent(IotRyDailyReportDO::getProjectClassification, reqVO.getProjectClassification())
-                .eqIfPresent(IotRyDailyReportDO::getRelocationDays, reqVO.getRelocationDays())
-                .betweenIfPresent(IotRyDailyReportDO::getLatestWellDoneTime, reqVO.getLatestWellDoneTime())
-                .eqIfPresent(IotRyDailyReportDO::getCurrentDepth, reqVO.getCurrentDepth())
-                .eqIfPresent(IotRyDailyReportDO::getDailyFootage, reqVO.getDailyFootage())
-                .eqIfPresent(IotRyDailyReportDO::getMonthlyFootage, reqVO.getMonthlyFootage())
-                .eqIfPresent(IotRyDailyReportDO::getAnnualFootage, reqVO.getAnnualFootage())
-                .eqIfPresent(IotRyDailyReportDO::getDailyPowerUsage, reqVO.getDailyPowerUsage())
-                .eqIfPresent(IotRyDailyReportDO::getMonthlyPowerUsage, reqVO.getMonthlyPowerUsage())
-                .eqIfPresent(IotRyDailyReportDO::getDailyFuel, reqVO.getDailyFuel())
-                .eqIfPresent(IotRyDailyReportDO::getMonthlyFuel, reqVO.getMonthlyFuel())
-                .betweenIfPresent(IotRyDailyReportDO::getNonProductionTime, reqVO.getNonProductionTime())
-                .eqIfPresent(IotRyDailyReportDO::getRyNptReason, reqVO.getRyNptReason())
-                .betweenIfPresent(IotRyDailyReportDO::getConstructionStartDate, reqVO.getConstructionStartDate())
-                .betweenIfPresent(IotRyDailyReportDO::getConstructionEndDate, reqVO.getConstructionEndDate())
-                .eqIfPresent(IotRyDailyReportDO::getProductionStatus, reqVO.getProductionStatus())
-                .eqIfPresent(IotRyDailyReportDO::getNextPlan, reqVO.getNextPlan())
-                .eqIfPresent(IotRyDailyReportDO::getRigStatus, reqVO.getRigStatus())
-                .eqIfPresent(IotRyDailyReportDO::getPersonnel, reqVO.getPersonnel())
-                .eqIfPresent(IotRyDailyReportDO::getMudDensity, reqVO.getMudDensity())
-                .eqIfPresent(IotRyDailyReportDO::getMudViscosity, reqVO.getMudViscosity())
-                .eqIfPresent(IotRyDailyReportDO::getLateralLength, reqVO.getLateralLength())
-                .eqIfPresent(IotRyDailyReportDO::getWellInclination, reqVO.getWellInclination())
-                .eqIfPresent(IotRyDailyReportDO::getAzimuth, reqVO.getAzimuth())
-                .eqIfPresent(IotRyDailyReportDO::getExtProperty, reqVO.getExtProperty())
-                .eqIfPresent(IotRyDailyReportDO::getSort, reqVO.getSort())
-                .eqIfPresent(IotRyDailyReportDO::getRemark, reqVO.getRemark())
-                .eqIfPresent(IotRyDailyReportDO::getStatus, reqVO.getStatus())
-                .eqIfPresent(IotRyDailyReportDO::getProcessInstanceId, reqVO.getProcessInstanceId())
-                .eqIfPresent(IotRyDailyReportDO::getAuditStatus, reqVO.getAuditStatus())
-                .betweenIfPresent(IotRyDailyReportDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(IotRyDailyReportDO::getCreateTime)
-                .orderByAsc(IotRyDailyReportDO::getId));
-    } */
-
     default List<IotRyDailyReportDO> dailyReports(IotRyDailyReportPageReqVO reqVO) {
         // 获取查询参数中的 projectClassification 值
         String projectClassification = reqVO.getProjectClassification();

+ 90 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/IotAllZhbdJob.java

@@ -0,0 +1,90 @@
+package cn.iocoder.yudao.module.pms.job;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
+import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
+import cn.iocoder.yudao.module.pms.controller.admin.iotcarzhbd.vo.IotCarZhbdPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotCarDevicePlateVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotcarzhbd.IotCarZhbdDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotcarzhbd.IotCarZhbdMapper;
+import cn.iocoder.yudao.module.pms.util.ZHBDUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+
+/**
+ * 根据设备表中的 车牌号 对应的 中航北斗的 vehicle_id carId
+ */
+@Component
+@Slf4j
+public class IotAllZhbdJob implements JobHandler {
+
+    @Autowired
+    private IotDeviceMapper iotDeviceMapper;
+    @Autowired
+    private ZHBDUtil zhbdUtil;
+
+    @Autowired
+    private IotCarZhbdMapper iotCarZhbdMapper;
+
+    @Override
+    @TenantIgnore
+    public String execute(String param) throws Exception {
+        // 查询设备表中 所有设备名称包含车牌号的 车辆
+        List<IotCarDevicePlateVO> carContainsPlates = iotDeviceMapper.allCarsContainsPlates();
+        Set<String> uniquePlates = new HashSet<>();
+        // key车牌号   value车辆对象(设备编码、设备名称、设备id)
+        Map<String, IotCarDevicePlateVO> plateDevicePair = new HashMap<>();
+        if (CollUtil.isNotEmpty(carContainsPlates)) {
+            carContainsPlates.forEach(plate -> {
+                uniquePlates.add(plate.getLicensePlate());
+                plateDevicePair.put(plate.getLicensePlate(), plate);
+            });
+            // 将集合中的车辆牌号拼接成逗号分隔的字符串
+            if (CollUtil.isNotEmpty(uniquePlates)) {
+                // 查询出 rq_iot_car_zhbd 表中已经存在的所有 carId
+                IotCarZhbdPageReqVO reqVO = new IotCarZhbdPageReqVO();
+                List<IotCarZhbdDO> existCars = iotCarZhbdMapper.selectList(reqVO);
+                Set<String> existCarIds = new HashSet<>();
+                if (CollUtil.isNotEmpty(existCars)) {
+                    existCars.forEach(car -> {
+                        existCarIds.add(car.getCarId());
+                    });
+                }
+
+                String uniquePlatesStr = StrUtil.join(",", uniquePlates);
+                log.info("逗号分隔的车辆号:{}", uniquePlatesStr);
+                // key车牌号   value中航北斗carId
+                Map<String, Integer> carLocationPair = zhbdUtil.carLocations(uniquePlatesStr);
+                // 将接口返回的 在本地表不存在的车辆信息保存
+                List<IotCarZhbdDO> tobeAddedCars = new ArrayList<>();
+                // 筛选出 中航北斗 carId 不在表 rq_iot_car_zhbd 中存在的记录
+                if (CollUtil.isNotEmpty(carLocationPair)) {
+                    carLocationPair.forEach((plateNum, carId) -> {
+                        if (!existCarIds.contains(String.valueOf(carId))) {
+                            IotCarZhbdDO car = new IotCarZhbdDO();
+                            car.setCarId(String.valueOf(carId));
+                            if (plateDevicePair.containsKey(plateNum)) {
+                                IotCarDevicePlateVO carDevice = plateDevicePair.get(plateNum);
+                                if (ObjUtil.isNotEmpty(carDevice)) {
+                                    car.setDeviceCode(carDevice.getDeviceCode());
+                                    car.setDeviceName(carDevice.getDeviceName());
+                                }
+                            }
+                            tobeAddedCars.add(car);
+                        }
+                    });
+                    if (CollUtil.isNotEmpty(tobeAddedCars)) {
+                        iotCarZhbdMapper.insertBatch(tobeAddedCars);
+                    }
+                }
+            }
+        }
+        return "success";
+    }
+}

+ 158 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/dailyreport/CreateRyDailyReportOrderJob.java

@@ -0,0 +1,158 @@
+package cn.iocoder.yudao.module.pms.job.dailyreport;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
+import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
+import cn.iocoder.yudao.module.pms.controller.admin.depttype.vo.IotDeptTypePageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.depttype.IotDeptTypeDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotrydailyreport.IotRyDailyReportDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.depttype.IotDeptTypeMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotrydailyreport.IotRyDailyReportMapper;
+import cn.iocoder.yudao.module.pms.message.PmsMessage;
+import cn.iocoder.yudao.module.pms.service.iotdeviceperson.IotDevicePersonService;
+import cn.iocoder.yudao.module.pms.service.iotmainworkorderbom.IotMainWorkOrderBomService;
+import cn.iocoder.yudao.module.pms.service.iotprojecttask.IotProjectTaskService;
+import cn.iocoder.yudao.module.pms.service.iotrydailyreport.IotRyDailyReportService;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
+import cn.iocoder.yudao.module.system.service.dept.DeptService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static cn.iocoder.yudao.module.pms.framework.config.MultiThreadConfiguration.PMS_THREAD_POOL_TASK_EXECUTOR;
+
+/**
+ * 瑞鹰挂靠队伍 生成日报
+ */
+@Component
+@Slf4j
+public class CreateRyDailyReportOrderJob implements JobHandler {
+    @Resource
+    private IotDevicePersonService iotDevicePersonService;
+    @Resource
+    private IotRyDailyReportMapper iotRyDailyReportMapper;
+    @Autowired
+    private IotRyDailyReportService iotRyDailyReportService;
+
+    @Autowired
+    private IotDeviceMapper iotDeviceMapper;
+    @Resource
+    private IotProjectTaskService iotProjectTaskService;
+    @Resource
+    private AdminUserApi adminUserApi;
+    @Resource
+    private IotMainWorkOrderBomService iotMainWorkOrderBomService;
+    @Resource
+    private IotDeptTypeMapper iotDeptTypeMapper;
+    @Resource(name = PMS_THREAD_POOL_TASK_EXECUTOR)
+    private ThreadPoolTaskExecutor pmsThreadPoolTaskExecutor;
+    @Resource
+    private PmsMessage pmsMessage;
+    @Resource
+    private DeptService deptService;
+
+    @Override
+    @TenantIgnore
+    public String execute(String param) throws Exception {
+
+        // 查询瑞鹰下所有部门 筛选出 修井 队伍(不包含任何设备的队伍)
+        IotDeptTypePageReqVO deptTypeReqVO = new IotDeptTypePageReqVO();
+        // 查询 钻井 修井 类型的部门
+        deptTypeReqVO.setType("xj");
+        List<IotDeptTypeDO> deptTypes = iotDeptTypeMapper.selectList(deptTypeReqVO);
+        Set<Long> xjDeptIds = new HashSet<>();
+        if (CollUtil.isNotEmpty(deptTypes)) {
+            deptTypes.forEach(deptType -> {
+                xjDeptIds.add(deptType.getDeptId());
+            });
+        }
+        // 查询瑞鹰下所有队伍
+        Set<Long> ryTeamDeptIds = new HashSet<>();
+        // 查询瑞鹰所有 队伍 项目部
+        Set<Long> ryChildDeptIds = deptService.getChildDeptIdListFromCache(158l);
+        List<DeptDO> depts =deptService.getDeptList(ryChildDeptIds);
+        if (CollUtil.isNotEmpty(depts)) {
+            depts.forEach(dept -> {
+                if ("3".equals(dept.getType())) {
+                    ryTeamDeptIds.add(dept.getId());
+                }
+            });
+        }
+        // 查询瑞鹰所有队伍关联的设备 筛选出不包含任何设备的队伍
+        IotDevicePageReqVO reqVO = new IotDevicePageReqVO();
+        reqVO.setDeptIds(new ArrayList<>(ryTeamDeptIds));
+        List<IotDeviceDO> devices = iotDeviceMapper.selectListAlone(reqVO);
+        // 包含设备的部门id集合
+        Set<Long> containsDeviceDeptIds = new HashSet<>();
+        if (CollUtil.isNotEmpty(devices)) {
+            devices.forEach(device -> {
+                containsDeviceDeptIds.add(device.getDeptId());
+            });
+        }
+        // 不包含任何设备的队伍id集合
+        Set<Long> noDeviceXjDeptIds = xjDeptIds.stream()
+                .filter(deptId -> !containsDeviceDeptIds.contains(deptId))
+                .collect(Collectors.toSet());
+
+        // 查询无设备修井队伍日报列表
+        IotRyDailyReportPageReqVO ryReqVO = new IotRyDailyReportPageReqVO();
+        ryReqVO.setDeptIds(noDeviceXjDeptIds);
+        ryReqVO.setProjectClassification("2");
+        List<IotRyDailyReportDO> ryDailyReports = iotRyDailyReportMapper.dailyReports(ryReqVO);
+
+        // 查询所有瑞都的项目任务 以‘部门-时间’ 为唯一键 当天创建时间 内没有生成过日报 就自动生成
+        IotRdDailyReportPageReqVO pageReqVO = new IotRdDailyReportPageReqVO();
+        LocalDateTime currentDate = LocalDateTime.now();
+        String currentFormatDateStr = LocalDateTimeUtil.format(currentDate, "yyyy-MM-dd");
+        // 前一天的日期
+        LocalDateTime yesterday = currentDate.minusDays(1);
+        // 当天已经生成日报的修井队伍deptId集合
+        Set<Long> currentDayReportedDeptIds = new HashSet<>();
+        if (CollUtil.isNotEmpty(ryDailyReports)) {
+            ryDailyReports.forEach(report -> {
+                // 查询当天生成的日报
+                LocalDateTime createDate = report.getCreateTime();
+                String formatDateStr = LocalDateTimeUtil.format(createDate, "yyyy-MM-dd");
+                if (formatDateStr.equals(currentFormatDateStr)) {
+                    currentDayReportedDeptIds.add(report.getTaskId());
+                }
+            });
+        }
+
+        // 如果当天的修井日报记录中不包含 无设备的修井队伍部门id 则生成修井队伍日报记录
+        Set<Long> tobeReportXjDeptIds = noDeviceXjDeptIds.stream()
+                .filter(deptId -> !currentDayReportedDeptIds.contains(deptId))
+                .collect(Collectors.toSet());
+
+        if (CollUtil.isNotEmpty(tobeReportXjDeptIds)) {
+            List<IotRyDailyReportDO> tobeAddedReports = new ArrayList<>();
+            tobeReportXjDeptIds.forEach(deptId -> {
+                IotRyDailyReportDO noDeviceReport = new IotRyDailyReportDO();
+                noDeviceReport.setDeptId(deptId);
+                noDeviceReport.setProjectClassification("2");
+                tobeAddedReports.add(noDeviceReport);
+            });
+            if (CollUtil.isNotEmpty(tobeAddedReports)) {
+                iotRyDailyReportMapper.insertBatch(tobeAddedReports);
+            }
+        }
+
+        return "创建成功";
+    }
+}

+ 4 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/httpEntity/ResponseOilData.java

@@ -13,4 +13,8 @@ import java.util.Map;
 public class ResponseOilData {
     public List<Map<String,Object>> pageList;
     public long total;
+    // 查询车辆位置返回的数据集合
+    public List<Map<String,Object>> data;
+    // 时间戳
+    public long time;
 }

+ 58 - 4
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/util/ZHBDUtil.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.pms.util;
 
+import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.module.pms.job.IotDeviceCarFuelVO;
 import cn.iocoder.yudao.module.pms.job.httpEntity.ApiOilResponse;
@@ -37,7 +38,10 @@ public class ZHBDUtil {
     private static final String ID = "NjI1LjUyNS42ODg";
     private static final String SECRET = "3897865b70d7bf29fcca5029147f7d0a";
     private static final String TOKEN_URL = "https://zhbdgps.cn/video/webapi/user/login";
-    private static final String LOCATION_URL="https://zhbdgps.cn/video/webapi/report/fuel/daily/detail";
+    // 日报表明细
+    private static final String LOCATION_URL = "https://zhbdgps.cn/video/webapi/report/fuel/daily/detail";
+    // 查询位置(车牌号)
+    private static final String GET_LOCATION_USE_PLATES_URL = "https://zhbdgps.cn/video/webapi/location/get-location-use-plates";
     private static final String parameter = "lng,lat,today_distance,distance,todayoil,totaloil,online,oil1,oil2,oil3,oil4,vehicle_name";
 
     @Autowired
@@ -76,7 +80,7 @@ public class ZHBDUtil {
         Map<Integer, IotDeviceCarFuelVO> carOilFuelPair = new HashMap<>();
         if (StrUtil.isNotBlank(zhbdtoken)) {
             try {
-                String jsonResponse = sendPostRequest(requestMap, zhbdtoken);
+                String jsonResponse = sendPostRequest(requestMap, zhbdtoken, LOCATION_URL);
                 ApiOilResponse response = parseResponse(jsonResponse);
                 if (response != null && response.code == 200) {
                     List<Map<String, Object>> details = response.data.pageList;
@@ -101,7 +105,57 @@ public class ZHBDUtil {
         return carOilFuelPair;
     }
 
-    private String sendPostRequest(Map<String, Object> requestData,String token) throws IOException {
+    /**
+     * 获取车辆位置 主要是获取车辆的 carId
+     * @param plates 中航北斗 车牌号 逗号分隔
+     * @return
+     * @throws Exception
+     */
+    public Map<String, Integer> carLocations(String plates) throws Exception {
+        String zhbdtoken = redisTemplate.opsForValue().get("zhbdtoken");
+        if (StrUtil.isBlank(zhbdtoken)) {
+            Map<String, String> map = new HashMap<>();
+            map.put("id", ID);
+            map.put("secret", SECRET);
+            JSONObject entries = restTemplate.postForObject(TOKEN_URL, map, JSONObject.class);
+            if (Objects.nonNull(entries)&&entries.get("code") != null&&Integer.parseInt(String.valueOf(entries.get("code")))==200) {
+                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(entries.get("data")));
+                zhbdtoken = jsonObject.get("token").toString();
+                redisTemplate.opsForValue().set("zhbdtoken", zhbdtoken, 80000, TimeUnit.SECONDS);
+            }
+        }
+        // 构建请求JSON
+        Map<String, Object> requestMap = new HashMap<>();
+        // 车牌号码 用逗号分隔,例如(示例车牌1,示例车牌2)
+        requestMap.put("plates", plates);
+        requestMap.put("time", null);
+
+        // key车牌号   value车辆carId
+        Map<String, Integer> plateCarIdPair = new HashMap<>();
+        if (StrUtil.isNotBlank(zhbdtoken)) {
+            try {
+                String jsonResponse = sendPostRequest(requestMap, zhbdtoken, GET_LOCATION_USE_PLATES_URL);
+                ApiOilResponse response = parseResponse(jsonResponse);
+                if (response != null && response.code == 200) {
+                    List<Map<String, Object>> locations = response.data.data;
+                    // 所有车辆的最后位置信息
+                    for (Map<String, Object> detail : locations) {
+                        Integer carId = Integer.valueOf(detail.get("vehicle_id").toString());
+                        // 车牌号
+                        String vehicleName = String.valueOf(detail.get("vehicle_name"));
+                        if (StrUtil.isNotBlank(vehicleName) && ObjUtil.isNotEmpty(carId)) {
+                            plateCarIdPair.put(vehicleName, carId);
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                log.info("获取油耗数据失败!");
+            }
+        }
+        return plateCarIdPair;
+    }
+
+    private String sendPostRequest(Map<String, Object> requestData, String token, String requestUrl) throws IOException {
 
         OkHttpClient client = new OkHttpClient();
         ObjectMapper objectMapper = new ObjectMapper();
@@ -109,7 +163,7 @@ public class ZHBDUtil {
         okhttp3.RequestBody body = okhttp3.RequestBody.create(json, okhttp3.MediaType.parse("application/json"));
 
         Request request = new Request.Builder()
-                .url(LOCATION_URL)
+                .url(requestUrl)
                 .post(body)
                 .addHeader("Content-Type", "application/json")
                 .addHeader("Authorization", "Bearer " + token)// 关键头信息

+ 14 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotDeviceMapper.xml

@@ -509,4 +509,18 @@
         AND l.id = latest.max_id
         ) tmp ON tmp.device_id = t2.id
     </select>
+
+    <!-- 查询设备表中所有 设备名称中包含 车牌号的车辆 -->
+    <select id="allCarsContainsPlates"
+            resultType="cn.iocoder.yudao.module.pms.controller.admin.vo.IotCarDevicePlateVO">
+        SELECT
+            id deviceId,
+            device_code deviceCode,
+            device_name deviceName,
+            REGEXP_SUBSTR(device_name, '([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-Z0-9]{4,7}[A-Z0-9挂学警港澳使领])') as licensePlate
+        FROM rq_iot_device
+        WHERE
+            deleted = 0
+          AND device_name REGEXP '([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-Z0-9]{4,7}[A-Z0-9挂学警港澳使领])';
+    </select>
 </mapper>