|
@@ -31,21 +31,21 @@ import static org.mockito.Mockito.when;
|
|
|
/**
|
|
/**
|
|
|
* 工单读适配器契约(执行票 12 范围 1)。
|
|
* 工单读适配器契约(执行票 12 范围 1)。
|
|
|
*
|
|
*
|
|
|
- * <p>这两组断言针对**真实库暴露过的缺陷**,控制器层测试用 mock 适配器测不到:
|
|
|
|
|
|
|
+ * <p>断言针对真实库核实过的行为:
|
|
|
* <ol>
|
|
* <ol>
|
|
|
- * <li>`alarm_data.id` 在真实库中全部是同一个**全零占位值**(非标识性)——
|
|
|
|
|
- * 若按 `id` 解析报警,`events/ALARM/{code}/work-orders` 恒回 EMPTY,
|
|
|
|
|
- * 即使该报警确实有工单。故必须按 `alarm_no` 解析。</li>
|
|
|
|
|
|
|
+ * <li>报警事件端点用 {@code alarm_data.id}(真实 UUID,各报警互不相同)定位,
|
|
|
|
|
+ * 命中后回该报警实际关联的工单,而不是恒回 EMPTY。</li>
|
|
|
* <li>设备维度返回该设备已有**全部**工单,未关联报警者须**显式**标 false,
|
|
* <li>设备维度返回该设备已有**全部**工单,未关联报警者须**显式**标 false,
|
|
|
- * 且不得伪造 `eventAssociation`(不得拿全零 id 冒充报警标识)。</li>
|
|
|
|
|
|
|
+ * 且不得伪造 `eventAssociation`。</li>
|
|
|
* </ol>
|
|
* </ol>
|
|
|
*/
|
|
*/
|
|
|
class BusinessCockpitWorkOrderReadAdapterTest {
|
|
class BusinessCockpitWorkOrderReadAdapterTest {
|
|
|
|
|
|
|
|
private static final String DEVICE_CODE = "EQ-001";
|
|
private static final String DEVICE_CODE = "EQ-001";
|
|
|
private static final String EQUIPMENT_ID = "EQID-001";
|
|
private static final String EQUIPMENT_ID = "EQID-001";
|
|
|
- /** 真实库中 alarm_data.id 的取值:全零占位,不具标识性。 */
|
|
|
|
|
- private static final String PLACEHOLDER_ID = "00000000000000000000000000000000";
|
|
|
|
|
|
|
+ /** 报警主键:真实库中为 32 位 UUID,各报警互不相同。 */
|
|
|
|
|
+ private static final String ALARM_ID = "fca8fd6b6d6f3408e964db88640dc399";
|
|
|
|
|
+ private static final String ALARM_NO = "BJ202609291243545660";
|
|
|
|
|
|
|
|
private WorkOrderService workOrderService;
|
|
private WorkOrderService workOrderService;
|
|
|
private AlarmDataService alarmDataService;
|
|
private AlarmDataService alarmDataService;
|
|
@@ -81,26 +81,42 @@ class BusinessCockpitWorkOrderReadAdapterTest {
|
|
|
entityClass);
|
|
entityClass);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /** 报警维度:必须按 alarm_no 解析,不能因主键是全零占位就恒回 EMPTY。 */
|
|
|
|
|
|
|
+ /** 报警维度:按报警主键解析,命中后回该报警实际关联的工单(不得恒回 EMPTY)。 */
|
|
|
@Test
|
|
@Test
|
|
|
- void alarmEventResolvesByAlarmNoNotByPlaceholderId() {
|
|
|
|
|
- AlarmData alarm = alarm(PLACEHOLDER_ID, "BJ202609291243545660", 279L);
|
|
|
|
|
- when(alarmDataService.list(any(LambdaQueryWrapper.class)))
|
|
|
|
|
- .thenReturn(Collections.singletonList(alarm));
|
|
|
|
|
|
|
+ void alarmEventResolvesByAlarmIdAndReturnsItsLinkedOrders() {
|
|
|
|
|
+ AlarmData alarm = alarm(ALARM_ID, ALARM_NO, 279L);
|
|
|
|
|
+ when(alarmDataService.getById(ALARM_ID)).thenReturn(alarm);
|
|
|
when(workOrderService.list(any(LambdaQueryWrapper.class)))
|
|
when(workOrderService.list(any(LambdaQueryWrapper.class)))
|
|
|
.thenReturn(Collections.singletonList(order(279L, "WO-279", 5)));
|
|
.thenReturn(Collections.singletonList(order(279L, "WO-279", 5)));
|
|
|
|
|
|
|
|
- CockpitWorkOrderReadSnapshot snapshot =
|
|
|
|
|
- adapter.loadByEvent("ALARM", "BJ202609291243545660");
|
|
|
|
|
|
|
+ CockpitWorkOrderReadSnapshot snapshot = adapter.loadByEvent("ALARM", ALARM_ID);
|
|
|
|
|
|
|
|
- assertNotNull(snapshot, "按真实单号必须能解析到报警");
|
|
|
|
|
|
|
+ assertNotNull(snapshot, "按报警主键必须能解析到报警");
|
|
|
assertEquals(1, snapshot.getWorkOrders().size(), "该报警确有工单,不得回 EMPTY");
|
|
assertEquals(1, snapshot.getWorkOrders().size(), "该报警确有工单,不得回 EMPTY");
|
|
|
CockpitWorkOrderSummary summary = snapshot.getWorkOrders().get(0);
|
|
CockpitWorkOrderSummary summary = snapshot.getWorkOrders().get(0);
|
|
|
assertEquals("WO-279", summary.getWorkOrderCode());
|
|
assertEquals("WO-279", summary.getWorkOrderCode());
|
|
|
assertTrue(summary.isAssociatedWithCurrentEvent(), "报警维度命中的工单即实际关联");
|
|
assertTrue(summary.isAssociatedWithCurrentEvent(), "报警维度命中的工单即实际关联");
|
|
|
- // eventCode 必须回真实单号,不得回全零占位 id
|
|
|
|
|
- assertEquals("BJ202609291243545660", summary.getEventAssociation().getEventCode());
|
|
|
|
|
- assertEquals("BJ202609291243545660", snapshot.getEventCode());
|
|
|
|
|
|
|
+ // 对外标识回该报警主键(真实 UUID),与请求标识一致
|
|
|
|
|
+ assertEquals(ALARM_ID, summary.getEventAssociation().getEventCode());
|
|
|
|
|
+ assertEquals(ALARM_ID, snapshot.getEventCode());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 主键查不到时回退按 alarm_no 定位,便于调用方用真实单号查询。 */
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void alarmEventFallsBackToAlarmNoWhenIdMisses() {
|
|
|
|
|
+ AlarmData alarm = alarm(ALARM_ID, ALARM_NO, 279L);
|
|
|
|
|
+ when(alarmDataService.getById(ALARM_NO)).thenReturn(null);
|
|
|
|
|
+ when(alarmDataService.list(any(LambdaQueryWrapper.class)))
|
|
|
|
|
+ .thenReturn(Collections.singletonList(alarm));
|
|
|
|
|
+ when(workOrderService.list(any(LambdaQueryWrapper.class)))
|
|
|
|
|
+ .thenReturn(Collections.singletonList(order(279L, "WO-279", 5)));
|
|
|
|
|
+
|
|
|
|
|
+ CockpitWorkOrderReadSnapshot snapshot = adapter.loadByEvent("ALARM", ALARM_NO);
|
|
|
|
|
+
|
|
|
|
|
+ assertNotNull(snapshot);
|
|
|
|
|
+ assertEquals(1, snapshot.getWorkOrders().size());
|
|
|
|
|
+ // 回显仍用报警主键,而不是请求里那个单号
|
|
|
|
|
+ assertEquals(ALARM_ID, snapshot.getEventCode());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 未关联报警的工单:显式 false 且不得伪造 eventAssociation。 */
|
|
/** 未关联报警的工单:显式 false 且不得伪造 eventAssociation。 */
|
|
@@ -112,7 +128,7 @@ class BusinessCockpitWorkOrderReadAdapterTest {
|
|
|
order(281L, "WO-ORPHAN", 1));
|
|
order(281L, "WO-ORPHAN", 1));
|
|
|
// 只有 279 被报警引用;281 无任何报警关联
|
|
// 只有 279 被报警引用;281 无任何报警关联
|
|
|
when(alarmDataService.list(any(LambdaQueryWrapper.class)))
|
|
when(alarmDataService.list(any(LambdaQueryWrapper.class)))
|
|
|
- .thenReturn(Collections.singletonList(alarm(PLACEHOLDER_ID, "BJ-001", 279L)));
|
|
|
|
|
|
|
+ .thenReturn(Collections.singletonList(alarm(ALARM_ID, ALARM_NO, 279L)));
|
|
|
when(workOrderService.list(any(LambdaQueryWrapper.class))).thenReturn(orders);
|
|
when(workOrderService.list(any(LambdaQueryWrapper.class))).thenReturn(orders);
|
|
|
|
|
|
|
|
CockpitWorkOrderReadSnapshot snapshot = adapter.loadByDevice(DEVICE_CODE);
|
|
CockpitWorkOrderReadSnapshot snapshot = adapter.loadByDevice(DEVICE_CODE);
|
|
@@ -120,7 +136,7 @@ class BusinessCockpitWorkOrderReadAdapterTest {
|
|
|
assertEquals(2, snapshot.getWorkOrders().size(), "设备维度返回已有全部工单");
|
|
assertEquals(2, snapshot.getWorkOrders().size(), "设备维度返回已有全部工单");
|
|
|
CockpitWorkOrderSummary linked = snapshot.getWorkOrders().get(0);
|
|
CockpitWorkOrderSummary linked = snapshot.getWorkOrders().get(0);
|
|
|
assertTrue(linked.isAssociatedWithCurrentEvent());
|
|
assertTrue(linked.isAssociatedWithCurrentEvent());
|
|
|
- assertEquals("BJ-001", linked.getEventAssociation().getEventCode());
|
|
|
|
|
|
|
+ assertEquals(ALARM_ID, linked.getEventAssociation().getEventCode());
|
|
|
|
|
|
|
|
CockpitWorkOrderSummary orphan = snapshot.getWorkOrders().get(1);
|
|
CockpitWorkOrderSummary orphan = snapshot.getWorkOrders().get(1);
|
|
|
assertFalse(orphan.isAssociatedWithCurrentEvent(), "未关联必须显式 false");
|
|
assertFalse(orphan.isAssociatedWithCurrentEvent(), "未关联必须显式 false");
|