feat(03-02): DeviceSimBindingStore 新增 UpdateIsCurrentByDeviceID 方法

- 事务两步原子更新:先全部清空 is_current=false,再按 ICCID 设 true
- 通过子查询定位 iot_card_id,避免跨表 JOIN 更新
- currentIccid 为空时仅清空,不做第二步设置
This commit is contained in:
2026-03-28 11:36:40 +08:00
parent 8819c94322
commit ba1886c314

View File

@@ -200,3 +200,37 @@ func (s *DeviceSimBindingStore) GetBoundICCIDs(ctx context.Context, iccids []str
}
return result, nil
}
// UpdateIsCurrentByDeviceID 原子更新设备当前使用的卡标识
// 使用事务两步操作:先全部设为 false再将 currentIccid 对应行设为 true
// currentIccid 为空字符串时,仅执行全部清空(无当前卡的情况)
func (s *DeviceSimBindingStore) UpdateIsCurrentByDeviceID(ctx context.Context, deviceID uint, currentIccid string) error {
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
// 第一步:将该设备所有活跃绑定的 is_current 设为 false
if err := tx.Model(&model.DeviceSimBinding{}).
Where("device_id = ? AND bind_status = 1", deviceID).
Update("is_current", false).Error; err != nil {
return err
}
// 第二步:将当前 ICCID 对应的绑定记录设为 is_current = true
if currentIccid == "" {
return nil
}
// 通过子查询找到对应的 iot_card_id避免跨表 JOIN 更新)
var iotCardID uint
if err := tx.Table("tb_iot_card").
Select("id").
Where("iccid = ? AND deleted_at IS NULL", currentIccid).
Scan(&iotCardID).Error; err != nil {
return err
}
if iotCardID == 0 {
// 未找到对应卡记录,不更新(可能卡尚未入库)
return nil
}
return tx.Model(&model.DeviceSimBinding{}).
Where("device_id = ? AND iot_card_id = ? AND bind_status = 1", deviceID, iotCardID).
Update("is_current", true).Error
})
}