Просмотр исходного кода

✨ feat: 支持按设备手动重建运行记录

- 根据设备反查部门及上级运行计划
- 清理当天旧工单、设备明细和人工运行日志
- 按小部门施工设备及负责人重新生成填报记录
- 修复已删除数据回显及待填写工单显示填写时间问题
Zimo 2 дней назад
Родитель
Сommit
309f63275a

+ 9 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotoperationplan/IotOperationPlanController.java

@@ -82,6 +82,14 @@ public class IotOperationPlanController {
         return success(true);
         return success(true);
     }
     }
 
 
+    @PostMapping("/manual-generate")
+    @Operation(summary = "根据设备手动重新生成所在小部门当天的运行记录")
+    @Parameter(name = "deviceId", description = "设备编号", required = true)
+    @PreAuthorize("@ss.hasPermission('rq:iot-operation-plan:create')")
+    public CommonResult<String> manualGenerateByDeviceId(@RequestParam("deviceId") Long deviceId) {
+        return success(iotOperationPlanService.manualGenerateByDeviceId(deviceId));
+    }
+
     @DeleteMapping("/delete")
     @DeleteMapping("/delete")
     @Operation(summary = "删除运行记录计划")
     @Operation(summary = "删除运行记录计划")
     @Parameter(name = "id", description = "编号", required = true)
     @Parameter(name = "id", description = "编号", required = true)
@@ -144,4 +152,4 @@ public class IotOperationPlanController {
                         BeanUtils.toBean(list, IotOperationPlanRespVO.class));
                         BeanUtils.toBean(list, IotOperationPlanRespVO.class));
     }*/
     }*/
 
 
-}
+}

+ 24 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotopeationfill/IotOpeationFillMapper.java

@@ -134,6 +134,30 @@ public interface IotOpeationFillMapper extends BaseMapperX<IotOpeationFillDO> {
     @TenantIgnore
     @TenantIgnore
     int insertFill(List<IotOpeationFillDO> vo);
     int insertFill(List<IotOpeationFillDO> vo);
 
 
+    @TenantIgnore
+    List<Long> selectOrderIdsByDeviceAndCreateTime(@Param("deviceId") Long deviceId,
+                                                   @Param("beginTime") LocalDateTime beginTime,
+                                                   @Param("endTime") LocalDateTime endTime);
+
+    @TenantIgnore
+    List<Long> selectOrderIdsByDeptAndCreateTime(@Param("deptId") Long deptId,
+                                                 @Param("beginTime") LocalDateTime beginTime,
+                                                 @Param("endTime") LocalDateTime endTime);
+
+    @TenantIgnore
+    List<Long> selectDeviceIdsByOrderIds(@Param("orderIds") Collection<Long> orderIds);
+
+    @TenantIgnore
+    int logicalDeleteByOrderIds(@Param("orderIds") Collection<Long> orderIds);
+
+    @TenantIgnore
+    int logicalDeleteOrdersByIds(@Param("orderIds") Collection<Long> orderIds);
+
+    @TenantIgnore
+    int deleteManualRunLogs(@Param("deviceIds") Collection<Long> deviceIds,
+                            @Param("beginTime") LocalDateTime beginTime,
+                            @Param("endTime") LocalDateTime endTime);
+
     /*int insertFillOrder(List<IotOpeationFillDO> vo);*/
     /*int insertFillOrder(List<IotOpeationFillDO> vo);*/
 
 
     @TenantIgnore
     @TenantIgnore

+ 8 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotoperationplan/IotOperationPlanMapper.java

@@ -40,4 +40,11 @@ public interface IotOperationPlanMapper extends BaseMapperX<IotOperationPlanDO>
 
 
     List<IotOperationPlanDO> getReportPlan(@Param("deviceIds")Collection<Long> deviceIds);
     List<IotOperationPlanDO> getReportPlan(@Param("deviceIds")Collection<Long> deviceIds);
 
 
-}
+    default List<IotOperationPlanDO> selectEnabledListByDeptIds(Collection<Long> deptIds) {
+        return selectList(new LambdaQueryWrapperX<IotOperationPlanDO>()
+                .in(IotOperationPlanDO::getDeptId, deptIds)
+                .eq(IotOperationPlanDO::getStatus, 0)
+                .orderByDesc(IotOperationPlanDO::getId));
+    }
+
+}

+ 3 - 2
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotopeationfill/IotOpeationFillServiceImpl.java

@@ -580,8 +580,9 @@ public class IotOpeationFillServiceImpl implements IotOpeationFillService {
                 .collect(Collectors.groupingBy(IotOpeationFillDO::getOrderId));
                 .collect(Collectors.groupingBy(IotOpeationFillDO::getOrderId));
 
 
         for (IotOpeationFillOrderDO record : records.getList()) {
         for (IotOpeationFillOrderDO record : records.getList()) {
-            if (record.getCreateTime() != null && record.getUpdateTime() != null
-                    && record.getCreateTime().isEqual(record.getUpdateTime())) {
+            // updateTime 在新增工单时会被公共字段处理器自动赋值,不能据此判断是否已经填写。
+            // 待填写工单尚未产生真实填写时间,列表不返回该字段。
+            if (record.getOrderStatus() == 0) {
                 record.setUpdateTime(null);
                 record.setUpdateTime(null);
             }
             }
 
 

+ 9 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotoperationplan/IotOperationPlanService.java

@@ -54,4 +54,12 @@ public interface IotOperationPlanService {
 
 
     void updateInspectPlanStatus(Long id, Integer status);
     void updateInspectPlanStatus(Long id, Integer status);
 
 
-}
+    /**
+     * 根据设备手动重新生成设备所在小部门当天的运行记录。
+     *
+     * @param deviceId 用于定位小部门和上级运行计划的设备编号
+     * @return 生成结果说明
+     */
+    String manualGenerateByDeviceId(Long deviceId);
+
+}

+ 223 - 2
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotoperationplan/IotOperationPlanServiceImpl.java

@@ -1,13 +1,31 @@
 package cn.iocoder.yudao.module.pms.service.iotoperationplan;
 package cn.iocoder.yudao.module.pms.service.iotoperationplan;
 
 
+import cn.iocoder.yudao.module.pms.constant.PmsConstants;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotopeationfill.IotOpeationFillDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotopeationfill.IotOpeationFillOrderDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotoperationplandev.IotOperationPlanDevDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotoperationplandev.IotOperationPlanDevDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillOrderMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotoperationplandev.IotOperationPlanDevMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotoperationplandev.IotOperationPlanDevMapper;
-import com.google.common.collect.ImmutableBiMap;
+import cn.iocoder.yudao.module.pms.message.PmsMessage;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+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.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import javax.annotation.Resource;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
 
 
+import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.*;
 import cn.iocoder.yudao.module.pms.controller.admin.iotoperationplan.vo.*;
 import cn.iocoder.yudao.module.pms.controller.admin.iotoperationplan.vo.*;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotoperationplan.IotOperationPlanDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotoperationplan.IotOperationPlanDO;
@@ -18,7 +36,9 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotoperationplan.IotOperationPlanMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotoperationplan.IotOperationPlanMapper;
 
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_DEVICE_NOT_EXISTS;
 import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_OPERATION_PLAN_NOT_EXISTS;
 import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_OPERATION_PLAN_NOT_EXISTS;
+import static cn.iocoder.yudao.module.pms.framework.config.MultiThreadConfiguration.PMS_THREAD_POOL_TASK_EXECUTOR;
 
 
 
 
 /**
 /**
@@ -28,12 +48,27 @@ import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_OPERATION_
  */
  */
 @Service
 @Service
 @Validated
 @Validated
+@Slf4j
 public class IotOperationPlanServiceImpl implements IotOperationPlanService {
 public class IotOperationPlanServiceImpl implements IotOperationPlanService {
 
 
     @Resource
     @Resource
     private IotOperationPlanMapper iotOperationPlanMapper;
     private IotOperationPlanMapper iotOperationPlanMapper;
     @Resource
     @Resource
     private IotOperationPlanDevMapper planDevMapper;
     private IotOperationPlanDevMapper planDevMapper;
+    @Resource
+    private IotDeviceMapper iotDeviceMapper;
+    @Resource
+    private IotOpeationFillMapper iotOpeationFillMapper;
+    @Resource
+    private IotOpeationFillOrderMapper iotOpeationFillOrderMapper;
+    @Resource
+    private DeptService deptService;
+    @Resource
+    private AdminUserApi adminUserApi;
+    @Resource
+    private PmsMessage pmsMessage;
+    @Resource(name = PMS_THREAD_POOL_TASK_EXECUTOR)
+    private ThreadPoolTaskExecutor pmsThreadPoolTaskExecutor;
 
 
     @Override
     @Override
     public Long createIotOperationPlan(IotOperationPlanSaveReqVO createReqVO) {
     public Long createIotOperationPlan(IotOperationPlanSaveReqVO createReqVO) {
@@ -100,4 +135,190 @@ public class IotOperationPlanServiceImpl implements IotOperationPlanService {
         iotOperationPlanMapper.updateById(planDO);
         iotOperationPlanMapper.updateById(planDO);
     }
     }
 
 
-}
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String manualGenerateByDeviceId(Long deviceId) {
+        IotDeviceDO device = iotDeviceMapper.selectById(deviceId);
+        if (device == null || device.getDeptId() == null) {
+            throw exception(IOT_DEVICE_NOT_EXISTS);
+        }
+
+        Long deptId = device.getDeptId();
+        DeptDO dept = deptService.getDeptNoPermission(deptId);
+        if (dept == null) {
+            throw exception(IOT_DEVICE_NOT_EXISTS);
+        }
+
+        IotOperationPlanDO plan = findNearestEnabledPlan(dept);
+        if (plan == null) {
+            throw exception(IOT_OPERATION_PLAN_NOT_EXISTS);
+        }
+
+        LocalDateTime now = LocalDateTime.now();
+        LocalDateTime beginTime = LocalDate.now().atStartOfDay();
+        LocalDateTime endTime = beginTime.plusDays(1);
+        boolean deviceGeneratedToday = !iotOpeationFillMapper
+                .selectOrderIdsByDeviceAndCreateTime(deviceId, beginTime, endTime).isEmpty();
+
+        // 已经生成过的设备允许重建当天记录;尚未生成时必须先到达计划生成时间。
+        if (!deviceGeneratedToday && now.isBefore(calculateNextCreateTime(plan))) {
+            return "未到运行记录生成时间,无需生成";
+        }
+        if (!deviceGeneratedToday && !"sg".equals(device.getDeviceStatus())) {
+            return "当前设备不在施工状态,无需生成";
+        }
+
+        // 设备只是定位入口。重建时删除并重建它所在小部门当天的全部运行记录。
+        List<Long> oldOrderIds = iotOpeationFillMapper
+                .selectOrderIdsByDeptAndCreateTime(deptId, beginTime, endTime);
+        Set<Long> runLogDeviceIds = new HashSet<>();
+        runLogDeviceIds.add(deviceId);
+        if (!oldOrderIds.isEmpty()) {
+            runLogDeviceIds.addAll(iotOpeationFillMapper.selectDeviceIdsByOrderIds(oldOrderIds));
+            iotOpeationFillMapper.deleteManualRunLogs(runLogDeviceIds, beginTime, endTime);
+            iotOpeationFillMapper.logicalDeleteByOrderIds(oldOrderIds);
+            iotOpeationFillMapper.logicalDeleteOrdersByIds(oldOrderIds);
+        } else {
+            iotOpeationFillMapper.deleteManualRunLogs(runLogDeviceIds, beginTime, endTime);
+        }
+
+        List<IotDeviceRespVO> constructionDevices = iotOpeationFillMapper
+                .getFillDevices2(Collections.singleton(deptId));
+        if (constructionDevices.isEmpty()) {
+            return oldOrderIds.isEmpty()
+                    ? "当前小部门没有可生成运行记录的施工设备"
+                    : "已删除原运行记录,当前小部门没有施工设备";
+        }
+
+        List<Long> constructionDeviceIds = new ArrayList<>(constructionDevices.size());
+        for (IotDeviceRespVO constructionDevice : constructionDevices) {
+            constructionDeviceIds.add(constructionDevice.getId());
+        }
+        List<IotOpeationFillDO> fillDevices = iotOpeationFillMapper.getFillDevices(constructionDeviceIds);
+        List<IotOpeationFillOrderDO> newOrders = createOrders(dept, fillDevices, now);
+        if (newOrders.isEmpty()) {
+            return "当前小部门的施工设备未配置负责人,无法生成运行记录";
+        }
+
+        iotOpeationFillOrderMapper.insertBatch(newOrders);
+        Map<Integer, Long> orderIdByUserId = new HashMap<>();
+        for (IotOpeationFillOrderDO order : newOrders) {
+            orderIdByUserId.put(order.getUserId(), order.getId());
+        }
+
+        List<IotOpeationFillDO> newFills = new ArrayList<>();
+        for (IotOpeationFillDO fillDevice : fillDevices) {
+            Long orderId = orderIdByUserId.get(fillDevice.getUserId());
+            if (orderId == null) {
+                continue;
+            }
+            fillDevice.setDeviceId(fillDevice.getId());
+            fillDevice.setDeptId(deptId);
+            fillDevice.setOrderId(orderId);
+            fillDevice.setCreateTime(now);
+            fillDevice.setIsReport(0);
+            newFills.add(fillDevice);
+        }
+        if (!newFills.isEmpty()) {
+            iotOpeationFillMapper.insertFill(newFills);
+        }
+        sendMessagesAfterCommit(newOrders);
+
+        return oldOrderIds.isEmpty() ? "运行记录生成成功" : "运行记录重新生成成功";
+    }
+
+    private IotOperationPlanDO findNearestEnabledPlan(DeptDO dept) {
+        List<Long> ancestorDeptIds = new ArrayList<>();
+        Set<Long> visitedDeptIds = new HashSet<>();
+        DeptDO current = dept;
+        while (current != null && visitedDeptIds.add(current.getId())) {
+            ancestorDeptIds.add(current.getId());
+            if (current.getParentId() == null || DeptDO.PARENT_ID_ROOT.equals(current.getParentId())) {
+                break;
+            }
+            current = deptService.getDeptNoPermission(current.getParentId());
+        }
+
+        List<IotOperationPlanDO> plans = iotOperationPlanMapper.selectEnabledListByDeptIds(ancestorDeptIds);
+        for (Long ancestorDeptId : ancestorDeptIds) {
+            for (IotOperationPlanDO plan : plans) {
+                if (ancestorDeptId.equals(plan.getDeptId())) {
+                    return plan;
+                }
+            }
+        }
+        return null;
+    }
+
+    private LocalDateTime calculateNextCreateTime(IotOperationPlanDO plan) {
+        LocalDateTime baseTime = plan.getLastCreateTime() != null
+                ? plan.getLastCreateTime() : plan.getBeginCreateTime();
+        if (baseTime == null || plan.getPlanCycle() == null || plan.getPlanCycle().intValue() <= 0) {
+            throw exception(IOT_OPERATION_PLAN_NOT_EXISTS);
+        }
+
+        int cycle = plan.getPlanCycle().intValue();
+        if ("hour".equals(plan.getPlanUnit())) {
+            return baseTime.plusHours(cycle);
+        }
+        if ("day".equals(plan.getPlanUnit())) {
+            return baseTime.plusDays(cycle);
+        }
+        if ("month".equals(plan.getPlanUnit())) {
+            return baseTime.plusMonths(cycle);
+        }
+        throw exception(IOT_OPERATION_PLAN_NOT_EXISTS);
+    }
+
+    private List<IotOpeationFillOrderDO> createOrders(DeptDO dept, List<IotOpeationFillDO> fillDevices,
+            LocalDateTime createTime) {
+        Set<Integer> userIds = new LinkedHashSet<>();
+        for (IotOpeationFillDO fillDevice : fillDevices) {
+            if (fillDevice.getUserId() != null) {
+                userIds.add(fillDevice.getUserId());
+            }
+        }
+
+        List<IotOpeationFillOrderDO> orders = new ArrayList<>(userIds.size());
+        for (Integer userId : userIds) {
+            AdminUserRespDTO user = adminUserApi.getUser(userId.longValue());
+            if (user == null) {
+                continue;
+            }
+            IotOpeationFillOrderDO order = new IotOpeationFillOrderDO();
+            order.setOrderName(dept.getName() + "/" + createTime.toLocalDate() + "运行记录填报");
+            order.setDeptId(dept.getId());
+            order.setOrderStatus(0);
+            order.setCreateTime(createTime);
+            order.setUserName(user.getNickname());
+            order.setUserId(userId);
+            order.setMobile(user.getMobile());
+            orders.add(order);
+        }
+        return orders;
+    }
+
+    private void sendMessagesAfterCommit(List<IotOpeationFillOrderDO> orders) {
+        Runnable task = () -> pmsThreadPoolTaskExecutor.execute(() -> {
+            for (IotOpeationFillOrderDO order : orders) {
+                try {
+                    pmsMessage.sendMessage(order.getId(), order.getOrderName(), PmsConstants.GENERATE_OPERATION,
+                            order.getUserId().longValue(), order.getMobile());
+                } catch (Exception ex) {
+                    log.error("手动生成运行记录后发送通知失败,orderId={}", order.getId(), ex);
+                }
+            }
+        });
+        if (TransactionSynchronizationManager.isSynchronizationActive()) {
+            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+                @Override
+                public void afterCommit() {
+                    task.run();
+                }
+            });
+        } else {
+            task.run();
+        }
+    }
+
+}

+ 86 - 2
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotOpeationFillMapper.xml

@@ -172,6 +172,71 @@
         </foreach>
         </foreach>
     </insert>
     </insert>
 
 
+    <select id="selectOrderIdsByDeviceAndCreateTime" resultType="java.lang.Long">
+        select distinct f.order_id
+        from rq_iot_opeation_fill f
+        inner join rq_iot_opeation_fill_order o on o.id = f.order_id
+        where f.device_id = #{deviceId}
+          and f.deleted = 0
+          and o.deleted = 0
+          and o.create_time &gt;= #{beginTime}
+          and o.create_time &lt; #{endTime}
+    </select>
+
+    <select id="selectOrderIdsByDeptAndCreateTime" resultType="java.lang.Long">
+        select distinct f.order_id
+        from rq_iot_opeation_fill f
+        inner join rq_iot_opeation_fill_order o on o.id = f.order_id
+        where f.dept_id = #{deptId}
+          and f.deleted = 0
+          and o.deleted = 0
+          and o.create_time &gt;= #{beginTime}
+          and o.create_time &lt; #{endTime}
+    </select>
+
+    <select id="selectDeviceIdsByOrderIds" resultType="java.lang.Long">
+        select distinct device_id
+        from rq_iot_opeation_fill
+        where deleted = 0
+          and order_id in
+        <foreach collection="orderIds" item="orderId" open="(" separator="," close=")">
+            #{orderId}
+        </foreach>
+    </select>
+
+    <update id="logicalDeleteByOrderIds">
+        update rq_iot_opeation_fill
+        set deleted = 1,
+            update_time = now()
+        where deleted = 0
+          and order_id in
+        <foreach collection="orderIds" item="orderId" open="(" separator="," close=")">
+            #{orderId}
+        </foreach>
+    </update>
+
+    <update id="logicalDeleteOrdersByIds">
+        update rq_iot_opeation_fill_order
+        set deleted = 1,
+            update_time = now()
+        where deleted = 0
+          and id in
+        <foreach collection="orderIds" item="orderId" open="(" separator="," close=")">
+            #{orderId}
+        </foreach>
+    </update>
+
+    <delete id="deleteManualRunLogs">
+        delete from rq_iot_device_run_log
+        where (type is null or type in (0, 1))
+          and create_time &gt;= #{beginTime}
+          and create_time &lt; #{endTime}
+          and device_id in
+        <foreach collection="deviceIds" item="deviceId" open="(" separator="," close=")">
+            #{deviceId}
+        </foreach>
+    </delete>
+
     <!-- <insert id="insertFillOrder"
     <!-- <insert id="insertFillOrder"
              parameterType="cn.iocoder.yudao.module.pms.dal.dataobject.iotopeationfill.IotOpeationFillDO">
              parameterType="cn.iocoder.yudao.module.pms.dal.dataobject.iotopeationfill.IotOpeationFillDO">
          insert into rq_iot_opeation_fill_order(dept_id,order_name,
          insert into rq_iot_opeation_fill_order(dept_id,order_name,
@@ -227,6 +292,7 @@
             DATE(create_time) = #{createTime}
             DATE(create_time) = #{createTime}
           and
           and
             is_sum = 0
             is_sum = 0
+          and deleted = 0
     </update>
     </update>
 
 
 
 
@@ -250,6 +316,7 @@
             (#{item.deviceId}, #{item.pointName}, #{item.createTime}, 0)
             (#{item.deviceId}, #{item.pointName}, #{item.createTime}, 0)
         </foreach>
         </foreach>
         )
         )
+        and deleted = 0
     </update>
     </update>
 
 
     <update id="updateSumLog" parameterType="cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO">
     <update id="updateSumLog" parameterType="cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO">
@@ -264,6 +331,7 @@
             DATE(create_time) = #{createTime}
             DATE(create_time) = #{createTime}
           and
           and
             is_sum = 1
             is_sum = 1
+          and deleted = 0
     </update>
     </update>
 
 
 
 
@@ -288,6 +356,7 @@
             (#{item.deviceId}, #{item.pointName}, #{item.createTime}, 1)
             (#{item.deviceId}, #{item.pointName}, #{item.createTime}, 1)
         </foreach>
         </foreach>
         )
         )
+        and deleted = 0
     </update>
     </update>
 
 
     <!-- <select id="fillList" parameterType="cn.iocoder.yudao.module.pms.controller.admin.iotopeationfill.vo.IotOpeationFillRespVO"
     <!-- <select id="fillList" parameterType="cn.iocoder.yudao.module.pms.controller.admin.iotopeationfill.vo.IotOpeationFillRespVO"
@@ -922,12 +991,14 @@
         SELECT
         SELECT
         point_name,
         point_name,
         fill_content,
         fill_content,
-        (select max(total_run_time) from rq_iot_device_run_log  where  device_id = #{deviceId})total_run_time
+        (select max(total_run_time) from rq_iot_device_run_log
+         where device_id = #{deviceId} and deleted = 0) total_run_time
         FROM rq_iot_device_run_log
         FROM rq_iot_device_run_log
         WHERE
         WHERE
         device_id = #{deviceId}
         device_id = #{deviceId}
         and
         and
         DATE(create_time)  = DATE(#{createTime})
         DATE(create_time)  = DATE(#{createTime})
+        and deleted = 0
         order by id
         order by id
         desc
         desc
         limit 1
         limit 1
@@ -944,6 +1015,7 @@
         point_name = #{pointName}
         point_name = #{pointName}
         and
         and
         DATE(create_time)  = DATE(#{createTime})
         DATE(create_time)  = DATE(#{createTime})
+        and deleted = 0
         order by id
         order by id
         desc
         desc
         limit 1
         limit 1
@@ -960,6 +1032,7 @@
             (#{item.deviceId}, #{item.pointName}, DATE(#{item.createTime}))
             (#{item.deviceId}, #{item.pointName}, DATE(#{item.createTime}))
         </foreach>
         </foreach>
         )
         )
+        AND r.deleted = 0
         -- 确保每个条件只返回最新一条记录(按id降序,取最大id)
         -- 确保每个条件只返回最新一条记录(按id降序,取最大id)
         AND r.id IN (
         AND r.id IN (
         SELECT MAX(id)
         SELECT MAX(id)
@@ -969,6 +1042,7 @@
             (#{item.deviceId}, #{item.pointName}, DATE(#{item.createTime}))
             (#{item.deviceId}, #{item.pointName}, DATE(#{item.createTime}))
         </foreach>
         </foreach>
         )
         )
+        AND deleted = 0
         GROUP BY device_id, point_name, DATE(create_time)
         GROUP BY device_id, point_name, DATE(create_time)
         )
         )
     </select>
     </select>
@@ -981,6 +1055,7 @@
         device_id = #{deviceId}
         device_id = #{deviceId}
         and
         and
         point_name=#{pointName}
         point_name=#{pointName}
+        and deleted = 0
     </select>
     </select>
 
 
     <!--<select id="batchGetMaxFillInfo" parameterType="java.util.List"
     <!--<select id="batchGetMaxFillInfo" parameterType="java.util.List"
@@ -1022,6 +1097,8 @@
         ) AS rn
         ) AS rn
         FROM rq_iot_device_run_log
         FROM rq_iot_device_run_log
         WHERE
         WHERE
+        deleted = 0
+        AND
         -- 批量匹配多个 (device_id, point_name) 组合(保留原 foreach 逻辑)
         -- 批量匹配多个 (device_id, point_name) 组合(保留原 foreach 逻辑)
         (device_id, point_name) IN (
         (device_id, point_name) IN (
         <foreach collection="list" item="item" separator=",">
         <foreach collection="list" item="item" separator=",">
@@ -1584,6 +1661,7 @@
           and
           and
             point_name = #{pointName}
             point_name = #{pointName}
           and DATE(create_time) = DATE(#{createTime})
           and DATE(create_time) = DATE(#{createTime})
+          and deleted = 0
     </select>
     </select>
 
 
     <!--
     <!--
@@ -1605,6 +1683,7 @@
         </foreach>
         </foreach>
         )
         )
         AND device_code = ''
         AND device_code = ''
+        AND deleted = 0
         -- 按创建时间降序,保持结果一致性(可选,与原单查行为对齐)
         -- 按创建时间降序,保持结果一致性(可选,与原单查行为对齐)
         ORDER BY
         ORDER BY
         create_time DESC
         create_time DESC
@@ -1620,6 +1699,7 @@
             (#{item.deviceId}, #{item.pointName}, DATE(#{item.createTime}))
             (#{item.deviceId}, #{item.pointName}, DATE(#{item.createTime}))
         </foreach>
         </foreach>
         )
         )
+        and deleted = 0
     </select>
     </select>
 
 
     <select id="maxReportData" parameterType="cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO"
     <select id="maxReportData" parameterType="cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO"
@@ -1632,17 +1712,20 @@
             device_id = #{deviceId}
             device_id = #{deviceId}
           AND point_name = #{pointName}
           AND point_name = #{pointName}
           AND create_time &lt; #{createTime}
           AND create_time &lt; #{createTime}
+          AND deleted = 0
     </select>
     </select>
 
 
 
 
     <select id="batchQueryMaxReportData" resultType="cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO">
     <select id="batchQueryMaxReportData" resultType="cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO">
         SELECT t.device_id, t.point_name, MAX(t.total_run_time) as total_run_time
         SELECT t.device_id, t.point_name, MAX(t.total_run_time) as total_run_time
         FROM rq_iot_device_run_log t
         FROM rq_iot_device_run_log t
-        WHERE
+        WHERE (
         <foreach collection="list" item="item" separator="OR">
         <foreach collection="list" item="item" separator="OR">
             (t.device_id = #{item.deviceId}
             (t.device_id = #{item.deviceId}
             AND t.point_name = #{item.pointName})
             AND t.point_name = #{item.pointName})
         </foreach>
         </foreach>
+        )
+        AND t.deleted = 0
         GROUP BY t.device_id, t.point_name
         GROUP BY t.device_id, t.point_name
     </select>
     </select>
 
 
@@ -1656,6 +1739,7 @@
           and
           and
             point_name = #{pointName}
             point_name = #{pointName}
           and DATE(create_time) = DATE(#{createTime})
           and DATE(create_time) = DATE(#{createTime})
+          and deleted = 0
     </select>
     </select>
 
 
     <select id="getDesc" parameterType="cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO"
     <select id="getDesc" parameterType="cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO"