## ADDED Requirements ### Requirement: 设备级套餐耗尽时触发绑定卡停机 当套餐载体为设备(`carrier_type = "device"`)且所有生效套餐流量耗尽时,系统 SHALL 查询该设备绑定的所有 IoT 卡,并对每张卡异步触发停机检查(`CheckAndStopCard`)。 **触发位置**:`UsageService.checkAndTriggerSuspension`,在确认无生效套餐后执行。 **幂等保护**:`CheckAndStopCard` 内部检查卡是否已为停机状态(`network_status = 0`),重复调用不会重复调网关。 **仅处理绑定卡**:通过 `DeviceSimBindingStore.ListByDeviceID` 获取当前绑定关系(`bind_status = 1`),未绑定或已解绑的卡不受影响。 #### Scenario: 设备套餐流量耗尽,绑定卡在线 - **WHEN** `DeductDataUsage` 在 `carrier_type = "device"` 场景下扣减流量后,`checkAndTriggerSuspension` 发现该设备无生效套餐(`status IN (0,1)`) - **THEN** 系统查询该设备的绑定卡列表,对每张在线(`network_status = 1`)且已实名(`real_name_status = 1`)的卡异步调用 `CheckAndStopCard`,将卡停机(`network_status = 0`,`stop_reason = "traffic_exhausted"`) #### Scenario: 设备套餐流量耗尽,绑定卡已停机 - **WHEN** `checkAndTriggerSuspension` 触发设备级停机检查,但绑定卡已经是停机状态(`network_status = 0`) - **THEN** `CheckAndStopCard` 检查到卡已停机,跳过网关调用,不产生重复操作 #### Scenario: 设备无绑定卡 - **WHEN** `checkAndTriggerSuspension` 触发设备级停机检查,但该设备当前无有效绑定记录 - **THEN** 系统静默跳过,不报错,记录 Debug 日志 #### Scenario: 套餐载体为 iot_card,不受影响 - **WHEN** `DeductDataUsage` 在 `carrier_type = "iot_card"` 场景下触发停机检查 - **THEN** 仅对该卡本身执行 `CheckAndStopCard`,不查询设备绑定关系(与现有行为一致)