## MODIFIED Requirements

### Requirement: 流量耗尽自动复机

系统 SHALL 在套餐激活或流量重置后，对满足以下全部条件的卡自动调用运营商接口复机：
1. `stop_reason = "traffic_exhausted"`（仅限流量耗尽停机，手动停机不自动复机）
2. `real_name_status = 1`（已完成实名认证）
3. `network_status = 0`（当前处于停机状态）

系统 SHALL 在执行复机前获取 Redis 分布式锁（Key：`card:resume:lock:{cardID}`，TTL 30s），防止并发重复调用 Gateway。

#### Scenario: 所有条件满足时自动复机
- **GIVEN** 卡 C1 满足：`stop_reason=traffic_exhausted`，`real_name_status=1`，`network_status=0`
- **WHEN** `ResumeCardIfStopped(ctx, "iot_card", cardID)` 被调用
- **THEN** 系统获取分布式锁，调用 `gateway.StartCard`，更新 `network_status=1`，清空 `stop_reason`，释放锁

#### Scenario: 未实名卡跳过自动复机
- **GIVEN** 卡 C2 `stop_reason=traffic_exhausted`，`real_name_status=0`，`network_status=0`
- **WHEN** `ResumeCardIfStopped` 被调用
- **THEN** 系统记录 WARN 日志，静默跳过，不调用 Gateway，函数返回 nil

#### Scenario: 手动停机的卡不被自动复机
- **GIVEN** 卡 C3 `stop_reason=manual`，`real_name_status=1`，`network_status=0`
- **WHEN** `ResumeCardIfStopped` 被调用
- **THEN** 系统检测到 `stop_reason != traffic_exhausted`，静默跳过

#### Scenario: 并发调用时只有一次复机执行
- **GIVEN** 卡 C4 满足复机条件，复机操作正在执行（分布式锁被持有）
- **WHEN** 第二个 `ResumeCardIfStopped` 调用同时到达
- **THEN** 第二个调用获锁失败，直接返回，不调用 Gateway

#### Scenario: 设备类型载体复机遍历所有绑定卡
- **GIVEN** 设备 D1 绑定 3 张卡（C1 已实名停机、C2 已实名停机、C3 未实名停机）
- **WHEN** `ResumeCardIfStopped(ctx, "device", deviceID)` 被调用
- **THEN** C1 和 C2 自动复机，C3 因未实名跳过

## ADDED Requirements

### Requirement: 套餐超额停机必须写入 stop_reason 和 stopped_at

系统 SHALL 在套餐虚流量超额触发停机时（`stopCards` 函数），写入 `stop_reason=traffic_exhausted` 和 `stopped_at` 到 IoT 卡记录。

#### Scenario: 虚流量超额停机完整写入 DB
- **GIVEN** 卡 C1 当月流量超过套餐 `virtual_data_mb` 上限，`network_status=1`
- **WHEN** `HandlePackageCheck` 的 `stopCards` 执行
- **THEN** Gateway 调用成功后，DB 更新包含：`network_status=0`，`stop_reason=traffic_exhausted`，`stopped_at=now()`，`updated_at=now()`

### Requirement: 保护期停机使用常量 stop_reason

系统 SHALL 在保护期一致性检查停机时，使用 `constants.StopReasonProtectPeriod` 常量（值：`protect_period`）记录 `stop_reason`。

#### Scenario: 保护期停机写入正确原因
- **GIVEN** 设备处于停机保护期，绑定的卡 C1 `network_status=1`（开机状态不一致）
- **WHEN** `HandleProtectConsistencyCheck` 触发停机
- **THEN** DB 中 `stop_reason=protect_period`（使用常量，非中文硬编码）
- **AND** `ResumeCardIfStopped` 调用时因 `stop_reason != traffic_exhausted` 跳过，不会错误触发自动复机
