# 方案：删除设备前的使用校验

## 1. 目标

在删除设备前，检查该设备是否被任何任务关联。如果设备正在被使用，则禁止删除，并向用户返回明确的错误提示。

## 2. 核心思路

我们将遵循您项目清晰的分层架构，将“检查设备是否被任务使用”这一业务规则放在 **应用层** (`internal/app/service/`)
中进行协调。当上层请求删除设备时，应用服务会先调用仓库层查询 `device_tasks` 关联表，如果发现设备仍被任务关联，则会拒绝删除并返回一个明确的业务错误。

## 3. 实施步骤

### 3.1. 仓库层 (`DeviceRepository`)

-   **动作**: 在 `internal/infra/repository/device_repository.go` 的 `DeviceRepository` 接口中，增加一个新方法
    `IsDeviceInUse(deviceID uint) (bool, error)`。
-   **实现**: 在 `gormDeviceRepository` 中实现此方法。该方法将通过对 `models.DeviceTask` 模型执行 `Count`
    操作来高效地判断是否存在 `device_id` 匹配的记录。这比查询完整记录性能更好。

### 3.2. 应用层 (`DeviceService`)

-   **动作**:
    1.  在 `internal/app/service/device_service.go` 文件顶部定义一个新的错误变量 `ErrDeviceInUse`，例如
        `var ErrDeviceInUse = errors.New("设备正在被一个或多个任务使用，无法删除")`。
    2.  修改该文件中的 `DeleteDevice` 方法。
-   **实现**: 在 `DeleteDevice` 方法中，在调用 `s.deviceRepo.Delete()` 之前，先调用我们刚刚创建的
    `s.deviceRepo.IsDeviceInUse()` 方法。如果返回 `true`，则立即返回 `ErrDeviceInUse` 错误，中断删除流程。

### 3.3. 表现层 (`DeviceController`)

-   **动作**: 修改 `internal/app/controller/device/device_controller.go` 中的 `DeleteDevice` 方法。
-   **实现**: 在错误处理逻辑中，增加一个 `case` 来专门捕获从服务层返回的 `service.ErrDeviceInUse`
    错误。当捕获到此错误时，返回一个带有明确提示信息（如“设备正在被任务使用，无法删除”）和合适 HTTP 状态码（例如 `409 Conflict`）的错误响应。

## 4. 方案优势

-   **职责清晰**: 业务流程的编排和校验逻辑被正确地放置在应用层，符合您项目清晰的分层架构。
-   **高效查询**: 通过 `COUNT` 查询代替 `Find`，避免了不必要的数据加载，性能更佳。
-   **代码内聚**: 与设备相关的数据库操作都统一封装在 `DeviceRepository` 中。
-   **用户友好**: 通过在控制器层处理特定业务错误，可以给前端返回明确、可操作的错误信息。