Ver Fonte

feat(waterSupply): 提供清警复核入口,支持对单台或全部供水设备补齐历史遗留清警 (#51)

Kazerin há 1 mês atrás
pai
commit
ce25e35929

+ 20 - 0
pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/WaterSupply/MonitorAlarm/WaterSupplyAlarmController.java

@@ -10,11 +10,14 @@ import com.zksy.WaterSupply.MonitorAlarm.dto.out.AlarmMapPointOutDTO;
 import com.zksy.WaterSupply.MonitorAlarm.dto.out.AlarmStatsOutDTO;
 import com.zksy.WaterSupply.MonitorAlarm.dto.out.WaterAlarmOutDTO;
 import com.zksy.WaterSupply.MonitorAlarm.service.IWaterSupplyAlarmService;
+import com.zksy.base.alarm.service.AlarmClearResult;
+import com.zksy.base.alarm.service.AlarmClearService;
 import com.zksy.WaterSupply.export.WaterAlarmLedgerExportDTO;
 import com.zksy.common.annotation.Log;
 import com.zksy.common.core.domain.AjaxResult;
 import com.zksy.common.enums.BusinessType;
 import com.zksy.common.utils.poi.ExcelUtil;
+import com.zksy.common.utils.StringUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
@@ -42,6 +45,23 @@ public class WaterSupplyAlarmController {
     @Autowired
     private IWaterSupplyAlarmService waterSupplyAlarmService;
 
+    @Autowired
+    private AlarmClearService alarmClearService;
+
+    @PostMapping("/clear/review")
+    @ApiOperation("清警复核:按设备汇总有效报警原因,全部收口才清除设备报警状态;不传设备编码则复核全部供水设备")
+    @Log(title = "供水设备清警复核", businessType = BusinessType.UPDATE)
+    @PreAuthorize("@ss.hasPermi('waterSupply:alarm:handle')")
+    public AjaxResult reviewAlarmClear(
+            @ApiParam(value = "设备编码,不传则复核全部供水设备")
+            @RequestParam(value = "deviceCode", required = false) String deviceCode) {
+        if (StringUtils.isNotEmpty(deviceCode)) {
+            AlarmClearResult result = alarmClearService.review(deviceCode, "手工复核");
+            return AjaxResult.success(result);
+        }
+        return AjaxResult.success(alarmClearService.reviewAllWaterDevices("手工复核"));
+    }
+
     /** 已停用写接口的统一提示:供水报警的写入口只有报警审核(转工单 / 误报解除)。 */
     private static final String RETIRED_WRITE_ENDPOINT_MESSAGE =
             "该接口已停用:供水报警的写入口统一为报警审核(转工单 / 误报解除),请改用 /waterSupply/alarm/audit";

+ 13 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/alarm/service/AlarmClearService.java

@@ -1,5 +1,7 @@
 package com.zksy.base.alarm.service;
 
+import java.util.Map;
+
 /**
  * 运行系统清警复核能力(Gogs #51)。
  *
@@ -17,4 +19,15 @@ public interface AlarmClearService {
      * @return 复核判定结果(含剩余原因数量与摘要)
      */
     AlarmClearResult review(String deviceCode, String triggerSource);
+
+    /**
+     * 对全部供水设备执行一次清警复核。
+     *
+     * <p>用于补偿历史遗留:早于本能力上线就已收口、但设备报警状态仍停留在 1 的供水设备,
+     * 此后不会再有误报解除或工单结案动作来触发复核,只能靠本入口补齐。</p>
+     *
+     * @param triggerSource 触发来源
+     * @return 设备编码 -> 复核结果(含未清警的原因说明)
+     */
+    Map<String, AlarmClearResult> reviewAllWaterDevices(String triggerSource);
 }

+ 18 - 1
pipe-network-service/zksy-system/src/main/java/com/zksy/base/alarm/service/impl/AlarmClearServiceImpl.java

@@ -15,6 +15,7 @@ import com.zksy.base.domain.EquipmentBase;
 import com.zksy.base.domain.EquipmentStatus;
 import com.zksy.base.mapper.EquipmentBaseMapper;
 import com.zksy.base.mapper.EquipmentStatusMapper;
+import com.zksy.base.service.impl.WaterSupplyQueryService;
 import com.zksy.ops.domain.WorkOrder;
 import com.zksy.ops.enums.WorkOrderStatusEnum;
 import com.zksy.ops.mapper.WorkOrderMapper;
@@ -72,6 +73,7 @@ public class AlarmClearServiceImpl implements AlarmClearService {
     private final EquipmentBaseMapper equipmentBaseMapper;
     private final EquipmentStatusMapper equipmentStatusMapper;
     private final AlarmClearLogMapper alarmClearLogMapper;
+    private final WaterSupplyQueryService waterSupplyQueryService;
 
     @Autowired
     public AlarmClearServiceImpl(AlarmDataService alarmDataService,
@@ -79,13 +81,28 @@ public class AlarmClearServiceImpl implements AlarmClearService {
                                  WorkOrderMapper workOrderMapper,
                                  EquipmentBaseMapper equipmentBaseMapper,
                                  EquipmentStatusMapper equipmentStatusMapper,
-                                 AlarmClearLogMapper alarmClearLogMapper) {
+                                 AlarmClearLogMapper alarmClearLogMapper,
+                                 WaterSupplyQueryService waterSupplyQueryService) {
         this.alarmDataService = alarmDataService;
         this.alarmAuditMapper = alarmAuditMapper;
         this.workOrderMapper = workOrderMapper;
         this.equipmentBaseMapper = equipmentBaseMapper;
         this.equipmentStatusMapper = equipmentStatusMapper;
         this.alarmClearLogMapper = alarmClearLogMapper;
+        this.waterSupplyQueryService = waterSupplyQueryService;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, AlarmClearResult> reviewAllWaterDevices(String triggerSource) {
+        Map<String, AlarmClearResult> results = new LinkedHashMap<>();
+        for (EquipmentBase device : waterSupplyQueryService.findWaterDevices()) {
+            if (device == null || StrUtil.isBlank(device.getEquipmentCode())) {
+                continue;
+            }
+            results.put(device.getEquipmentCode(), review(device.getEquipmentCode(), triggerSource));
+        }
+        return results;
     }
 
     @Override

+ 28 - 1
pipe-network-service/zksy-system/src/test/java/com/zksy/base/alarm/service/AlarmClearServiceTest.java

@@ -23,6 +23,7 @@ import org.mockito.ArgumentCaptor;
 
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -59,6 +60,8 @@ class AlarmClearServiceTest {
     private EquipmentBaseMapper equipmentBaseMapper;
     private EquipmentStatusMapper equipmentStatusMapper;
     private AlarmClearLogMapper alarmClearLogMapper;
+    private com.zksy.base.service.EquipmentBaseService equipmentBaseServiceForScope;
+    private com.zksy.base.service.impl.WaterSupplyQueryService waterSupplyQueryService;
 
     @BeforeEach
     void setUp() {
@@ -68,8 +71,9 @@ class AlarmClearServiceTest {
         equipmentBaseMapper = mock(EquipmentBaseMapper.class);
         equipmentStatusMapper = mock(EquipmentStatusMapper.class);
         alarmClearLogMapper = mock(AlarmClearLogMapper.class);
+        waterSupplyQueryService = mock(com.zksy.base.service.impl.WaterSupplyQueryService.class);
         service = new AlarmClearServiceImpl(alarmDataService, alarmAuditMapper, workOrderMapper,
-                equipmentBaseMapper, equipmentStatusMapper, alarmClearLogMapper);
+                equipmentBaseMapper, equipmentStatusMapper, alarmClearLogMapper, waterSupplyQueryService);
 
         when(equipmentBaseMapper.selectList(any())).thenReturn(Collections.singletonList(device()));
         when(alarmAuditMapper.selectList(any())).thenReturn(Collections.emptyList());
@@ -235,6 +239,29 @@ class AlarmClearServiceTest {
         assertEquals(1, status.getAlarmStatus());
     }
 
+    @Test
+    void reviewAllWaterDevicesClearsEveryDeviceWithoutRemainingCause() {
+        EquipmentBase clearedDevice = device();
+        EquipmentBase pinnedDevice = new EquipmentBase();
+        pinnedDevice.setEquipmentId("EQ-W-2");
+        pinnedDevice.setEquipmentCode("CN-GS-202609020002");
+        when(waterSupplyQueryService.findWaterDevices())
+                .thenReturn(Arrays.asList(clearedDevice, pinnedDevice));
+
+        // 设备1:历史报警已收口 -> 可清警
+        when(alarmDataService.list(any(AbstractWrapper.class))).thenReturn(Collections.singletonList(
+                alarm("alarm-1", "压力过低", 1)));
+        when(equipmentBaseMapper.selectList(any())).thenReturn(Collections.singletonList(clearedDevice));
+        EquipmentStatus status = alarmingStatus();
+
+        Map<String, AlarmClearResult> results = service.reviewAllWaterDevices("手工复核");
+
+        assertTrue(results.containsKey("CN-GS-202609020001"));
+        assertTrue(results.get("CN-GS-202609020001").isCleared());
+        assertEquals(0, status.getAlarmStatus());
+        assertEquals(2, results.size());
+    }
+
     @Test
     void aHandledAlarmRecordCountsAsResolvedSoLegacyRowsCannotPinTheDevice() {
         EquipmentStatus status = alarmingStatus();