issue_56 #58

Merged
huang merged 17 commits from issue_56 into main 2025-11-05 23:56:50 +08:00
28 changed files with 576 additions and 461 deletions
Showing only changes of commit 203be4307d - Show all commits

View File

@@ -1,113 +1,113 @@
- **`internal/app/service/pig_farm_service.go` (`service.PigFarmService`)**
- **结构体改造**:
- [ ] 移除 `PigFarmService` 结构体中的 `logger *logs.Logger` 成员。
- [ ] 新增 `selfCtx context.Context` 成员。
- [ ] 移除 `PigFarmService` 结构体中的 `repo repository.PigFarmRepository` 成员,改为
- [x] 移除 `PigFarmService` 结构体中的 `logger *logs.Logger` 成员。
- [x] 新增 `selfCtx context.Context` 成员。
- [x] 移除 `PigFarmService` 结构体中的 `repo repository.PigFarmRepository` 成员,改为
`repo repository.PigFarmRepository`
- **构造函数改造 (`NewPigFarmService`)**:
- [ ] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [ ] 在函数内部,为 `PigFarmService` 创建其专属的 `selfCtx`
- [x] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [x] 在函数内部,为 `PigFarmService` 创建其专属的 `selfCtx`
`selfCtx := logs.AddCompName(ctx, "PigFarmService")`
- [ ] 将这个 `selfCtx` 赋值给 `PigFarmService` 结构体的 `selfCtx` 成员。
- [x] 将这个 `selfCtx` 赋值给 `PigFarmService` 结构体的 `selfCtx` 成员。
- **公共方法改造 (
所有方法,例如 `CreatePigHouse`, `GetPigHouseByID`, `ListPigHouses`, `UpdatePigHouse`, `DeletePigHouse`,
`CreatePen`, `GetPenByID`, `ListPens`, `UpdatePen`, `DeletePen`, `UpdatePenStatus`)**:
- [ ] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [ ] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
- [x] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [x] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
`context.Context``logger` 实例。
- [ ] 将所有对 `s.logger.Errorf``s.logger.Infof` 的调用替换为 `logger.Errorf``logger.Infof`
- [ ] 确保所有对 `s.repo` 的调用都将 `newCtx` 作为第一个参数传递。
- [x] 将所有对 `s.logger.Errorf``s.logger.Infof` 的调用替换为 `logger.Errorf``logger.Infof`
- [x] 确保所有对 `s.repo` 的调用都将 `newCtx` 作为第一个参数传递。
- **`internal/app/service/pig_batch_service.go` (`service.PigBatchService`)**
- **结构体改造**:
- [ ] 移除 `PigBatchService` 结构体中的 `logger *logs.Logger` 成员。
- [ ] 新增 `selfCtx context.Context` 成员。
- [x] 移除 `PigBatchService` 结构体中的 `logger *logs.Logger` 成员。
- [x] 新增 `selfCtx context.Context` 成员。
- **构造函数改造 (`NewPigBatchService`)**:
- [ ] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [ ] 在函数内部,为 `PigBatchService` 创建其专属的 `selfCtx`
- [x] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [x] 在函数内部,为 `PigBatchService` 创建其专属的 `selfCtx`
`selfCtx := logs.AddCompName(ctx, "PigBatchService")`
- [ ] 将这个 `selfCtx` 赋值给 `PigBatchService` 结构体的 `selfCtx` 成员。
- [x] 将这个 `selfCtx` 赋值给 `PigBatchService` 结构体的 `selfCtx` 成员。
- **公共方法改造 (
所有方法,例如 `CreatePigBatch`, `GetPigBatch`, `UpdatePigBatch`, `DeletePigBatch`, `ListPigBatches`,
`AssignEmptyPensToBatch`, `ReclassifyPenToNewBatch`, `RemoveEmptyPenFromBatch`, `MovePigsIntoPen`, `SellPigs`,
`BuyPigs`, `RecordSickPigs`, `RecordSickPigRecovery`, `RecordSickPigDeath`, `RecordSickPigCull`, `RecordDeath`,
`RecordCull`)**:
- [ ] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [ ] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
- [x] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [x] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
`context.Context``logger` 实例。
- [ ] 将所有对 `s.logger.Errorf``s.logger.Infof` 的调用替换为 `logger.Errorf``logger.Infof`
- [ ] 确保所有对 `s.pigBatchRepo`, `s.pigBatchLogRepo`, `s.uow`, `s.transferSvc`, `s.tradeSvc`, `s.sickSvc`
- [x] 将所有对 `s.logger.Errorf``s.logger.Infof` 的调用替换为 `logger.Errorf``logger.Infof`
- [x] 确保所有对 `s.pigBatchRepo`, `s.pigBatchLogRepo`, `s.uow`, `s.transferSvc`, `s.tradeSvc`, `s.sickSvc`
等依赖的调用都将 `newCtx` 作为第一个参数传递。
- **`internal/app/service/monitor_service.go` (`service.MonitorService`)**
- **结构体改造**:
- [ ] 移除 `MonitorService` 结构体中的 `logger *logs.Logger` 成员。
- [ ] 新增 `selfCtx context.Context` 成员。
- [x] 移除 `MonitorService` 结构体中的 `logger *logs.Logger` 成员。
- [x] 新增 `selfCtx context.Context` 成员。
- **构造函数改造 (`NewMonitorService`)**:
- [ ] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [ ] 在函数内部,为 `MonitorService` 创建其专属的 `selfCtx`
- [x] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [x] 在函数内部,为 `MonitorService` 创建其专属的 `selfCtx`
`selfCtx := logs.AddCompName(ctx, "MonitorService")`
- [ ] 将这个 `selfCtx` 赋值给 `MonitorService` 结构体的 `selfCtx` 成员。
- [x] 将这个 `selfCtx` 赋值给 `MonitorService` 结构体的 `selfCtx` 成员。
- **公共方法改造 (
所有方法,例如 `ListSensorData`, `ListDeviceCommandLogs`, `ListPlanExecutionLogs`, `ListTaskExecutionLogs`,
`ListPendingCollections`, `ListUserActionLogs`, `ListRawMaterialPurchases`, `ListRawMaterialStockLogs`,
`ListFeedUsageRecords`, `ListMedicationLogs`, `ListPigBatchLogs`, `ListWeighingBatches`, `ListWeighingRecords`,
`ListPigTransferLogs`, `ListPigSickLogs`, `ListPigPurchases`, `ListPigSales`, `ListNotifications`)**:
- [ ] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [ ] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
- [x] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [x] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
`context.Context``logger` 实例。
- [ ] 将所有对 `s.logger.Errorf``s.logger.Infof` 的调用替换为 `logger.Errorf``logger.Infof`
- [ ] 确保所有对 `s.repo` 的调用都将 `newCtx` 作为第一个参数传递。
- [x] 将所有对 `s.logger.Errorf``s.logger.Infof` 的调用替换为 `logger.Errorf``logger.Infof`
- [x] 确保所有对 `s.repo` 的调用都将 `newCtx` 作为第一个参数传递。
- **`internal/app/service/device_service.go` (`service.DeviceService`)**
- **结构体改造**:
- [ ] 移除 `DeviceService` 结构体中的 `logger *logs.Logger` 成员。
- [ ] 新增 `selfCtx context.Context` 成员。
- [x] 移除 `DeviceService` 结构体中的 `logger *logs.Logger` 成员。
- [x] 新增 `selfCtx context.Context` 成员。
- **构造函数改造 (`NewDeviceService`)**:
- [ ] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [ ] 在函数内部,为 `DeviceService` 创建其专属的 `selfCtx`
- [x] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [x] 在函数内部,为 `DeviceService` 创建其专属的 `selfCtx`
`selfCtx := logs.AddCompName(ctx, "DeviceService")`
- [ ] 将这个 `selfCtx` 赋值给 `DeviceService` 结构体的 `selfCtx` 成员。
- [x] 将这个 `selfCtx` 赋值给 `DeviceService` 结构体的 `selfCtx` 成员。
- **公共方法改造 (
所有方法,例如 `CreateDevice`, `GetDevice`, `ListDevices`, `UpdateDevice`, `DeleteDevice`, `ManualControl`,
`CreateAreaController`, `GetAreaController`, `ListAreaControllers`, `UpdateAreaController`,
`DeleteAreaController`, `CreateDeviceTemplate`, `GetDeviceTemplate`, `ListDeviceTemplates`,
`UpdateDeviceTemplate`, `DeleteDeviceTemplate`)**:
- [ ] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [ ] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
- [x] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [x] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
`context.Context``logger` 实例。
- [ ] 将所有对 `s.logger.Errorf`, `s.logger.Warnf`, `s.logger.Infof` 的调用替换为 `logger.Errorf`,
- [x] 将所有对 `s.logger.Errorf`, `s.logger.Warnf`, `s.logger.Infof` 的调用替换为 `logger.Errorf`,
`logger.Warnf`, `logger.Infof`
- [ ] 确保所有对 `s.repo`, `s.generalDeviceService` 等依赖的调用都将 `newCtx` 作为第一个参数传递。
- [x] 确保所有对 `s.repo`, `s.generalDeviceService` 等依赖的调用都将 `newCtx` 作为第一个参数传递。
- **`internal/app/service/plan_service.go` (`service.PlanService`)**
- **结构体改造**:
- [ ] 移除 `PlanService` 结构体中的 `logger *logs.Logger` 成员。
- [ ] 新增 `selfCtx context.Context` 成员。
- [x] 移除 `PlanService` 结构体中的 `logger *logs.Logger` 成员。
- [x] 新增 `selfCtx context.Context` 成员。
- **构造函数改造 (`NewPlanService`)**:
- [ ] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [ ] 在函数内部,为 `PlanService` 创建其专属的 `selfCtx``selfCtx := logs.AddCompName(ctx, "PlanService")`
- [ ] 将这个 `selfCtx` 赋值给 `PlanService` 结构体的 `selfCtx` 成员。
- [x] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [x] 在函数内部,为 `PlanService` 创建其专属的 `selfCtx``selfCtx := logs.AddCompName(ctx, "PlanService")`
- [x] 将这个 `selfCtx` 赋值给 `PlanService` 结构体的 `selfCtx` 成员。
- **公共方法改造 (
所有方法,例如 `CreatePlan`, `GetPlanByID`, `ListPlans`, `UpdatePlan`, `DeletePlan`, `StartPlan`, `StopPlan`)**:
- [ ] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [ ] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
- [x] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [x] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
`context.Context``logger` 实例。
- [ ] 将所有对 `s.logger.Errorf``s.logger.Infof` 的调用替换为 `logger.Errorf``logger.Infof`
- [ ] 确保所有对 `s.repo`, `s.planExecutionManager`, `s.analysisPlanTaskManager` 等依赖的调用都将 `newCtx`
- [x] 将所有对 `s.logger.Errorf``s.logger.Infof` 的调用替换为 `logger.Errorf``logger.Infof`
- [x] 确保所有对 `s.repo`, `s.planExecutionManager`, `s.analysisPlanTaskManager` 等依赖的调用都将 `newCtx`
作为第一个参数传递。
- **`internal/app/service/user_service.go` (`service.UserService`)**
- **结构体改造**:
- [ ] 移除 `UserService` 结构体中的 `logger *logs.Logger` 成员。
- [ ] 新增 `selfCtx context.Context` 成员。
- [x] 移除 `UserService` 结构体中的 `logger *logs.Logger` 成员。
- [x] 新增 `selfCtx context.Context` 成员。
- **构造函数改造 (`NewUserService`)**:
- [ ] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [ ] 在函数内部,为 `UserService` 创建其专属的 `selfCtx``selfCtx := logs.AddCompName(ctx, "UserService")`
- [ ] 将这个 `selfCtx` 赋值给 `UserService` 结构体的 `selfCtx` 成员。
- [x] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [x] 在函数内部,为 `UserService` 创建其专属的 `selfCtx``selfCtx := logs.AddCompName(ctx, "UserService")`
- [x] 将这个 `selfCtx` 赋值给 `UserService` 结构体的 `selfCtx` 成员。
- **公共方法改造 (所有方法,例如 `CreateUser`, `Login`, `SendTestNotification`)**:
- [ ] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [ ] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
- [x] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [x] 在方法入口处,使用 `newCtx, logger := logs.Trace(ctx, s.selfCtx, "MethodName")` 获取新的
`context.Context``logger` 实例。
- [ ] 将所有对 `s.logger.Errorf``s.logger.Infof` 的调用替换为 `logger.Errorf``logger.Infof`
- [ ] 确保所有对 `s.repo`, `s.tokenService`, `s.notifier` 等依赖的调用都将 `newCtx` 作为第一个参数传递。
- [x] 将所有对 `s.logger.Errorf``s.logger.Infof` 的调用替换为 `logger.Errorf``logger.Infof`
- [x] 确保所有对 `s.repo`, `s.tokenService`, `s.notifier` 等依赖的调用都将 `newCtx` 作为第一个参数传递。

View File

@@ -1,39 +1,39 @@
- **`internal/app/webhook/chirp_stack.go` (`webhook.ChirpStackListener`)**
- **结构体改造**:
- [ ] 移除 `ChirpStackListener` 结构体中的 `logger *logs.Logger` 成员。
- [ ] 新增 `selfCtx context.Context` 成员。
- [x] 移除 `ChirpStackListener` 结构体中的 `logger *logs.Logger` 成员。
- [x] 新增 `selfCtx context.Context` 成员。
- **构造函数改造 (`NewChirpStackListener`)**:
- [ ] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [ ] 在函数内部,为 `ChirpStackListener` 创建其专属的 `selfCtx`
- [x] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [x] 在函数内部,为 `ChirpStackListener` 创建其专属的 `selfCtx`
`selfCtx := logs.AddCompName(ctx, "ChirpStackListener")`
- [ ] 将这个 `selfCtx` 赋值给 `ChirpStackListener` 结构体的 `selfCtx` 成员。
- [x] 将这个 `selfCtx` 赋值给 `ChirpStackListener` 结构体的 `selfCtx` 成员。
- **公共方法改造 (`Handler`)**:
- [ ] `Handler` 方法返回 `http.HandlerFunc`。在返回的 `http.HandlerFunc` 内部,获取 `r.Context()` 作为
- [x] `Handler` 方法返回 `http.HandlerFunc`。在返回的 `http.HandlerFunc` 内部,获取 `r.Context()` 作为
`upstreamCtx`
- [ ] 在 `go c.handler(b, event)` 调用之前,将 `upstreamCtx` 传递给 `c.handler` 方法,即
- [x] 在 `go c.handler(b, event)` 调用之前,将 `upstreamCtx` 传递给 `c.handler` 方法,即
`go c.handler(upstreamCtx, b, event)`
- [ ] 将所有对 `c.logger.Errorf` 的调用替换为 `logger.Errorf` (在 `handler` 方法中处理)。
- [x] 将所有对 `c.logger.Errorf` 的调用替换为 `logger.Errorf` (在 `handler` 方法中处理)。
- **内部辅助方法改造 (`handler`, `handleUpEvent`, `handleStatusEvent`, `handleAckEvent`, `handleLogEvent`,
`handleJoinEvent`, `handleTxAckEvent`, `handleLocationEvent`, `handleIntegrationEvent`, `recordSensorData`)**:
- [ ] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [ ] 在每个方法入口处,使用 `newCtx, logger := logs.Trace(ctx, c.selfCtx, "MethodName")` 获取新的
- [x] 修改方法签名,添加 `ctx context.Context` 作为第一个参数。
- [x] 在每个方法入口处,使用 `newCtx, logger := logs.Trace(ctx, c.selfCtx, "MethodName")` 获取新的
`context.Context``logger` 实例。
- [ ] 将所有对 `c.logger.Errorf`, `c.logger.Infof`, `c.logger.Warnf` 的调用替换为 `logger.Errorf`,
- [x] 将所有对 `c.logger.Errorf`, `c.logger.Infof`, `c.logger.Warnf` 的调用替换为 `logger.Errorf`,
`logger.Infof`, `logger.Warnf`
- [ ] 确保所有对 `c.sensorDataRepo`, `c.deviceRepo`, `c.areaControllerRepo`, `c.deviceCommandLogRepo`,
- [x] 确保所有对 `c.sensorDataRepo`, `c.deviceRepo`, `c.areaControllerRepo`, `c.deviceCommandLogRepo`,
`c.pendingCollectionRepo` 等依赖的调用都将 `newCtx` 作为第一个参数传递。
- **`internal/app/webhook/placeholder_listener.go` (`webhook.PlaceholderListener`)**
- **结构体改造**:
- [ ] 移除 `PlaceholderListener` 结构体中的 `logger *logs.Logger` 成员。
- [ ] 新增 `selfCtx context.Context` 成员。
- [x] 移除 `PlaceholderListener` 结构体中的 `logger *logs.Logger` 成员。
- [x] 新增 `selfCtx context.Context` 成员。
- **构造函数改造 (`NewPlaceholderListener`)**:
- [ ] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [ ] 在函数内部,为 `PlaceholderListener` 创建其专属的 `selfCtx`
- [x] 修改函数签名,移除 `logger *logs.Logger` 参数,改为接收 `ctx context.Context`
- [x] 在函数内部,为 `PlaceholderListener` 创建其专属的 `selfCtx`
`selfCtx := logs.AddCompName(ctx, "PlaceholderListener")`
- [ ] 将这个 `selfCtx` 赋值给 `PlaceholderListener` 结构体的 `selfCtx` 成员。
- [ ] 使用 `newCtx, logger := logs.Trace(ctx, selfCtx, "NewPlaceholderListener")` 获取 `logger` 实例,并替换
- [x] 将这个 `selfCtx` 赋值给 `PlaceholderListener` 结构体的 `selfCtx` 成员。
- [x] 使用 `newCtx, logger := logs.Trace(ctx, selfCtx, "NewPlaceholderListener")` 获取 `logger` 实例,并替换
`logger.Info` 调用。
- **公共方法改造 (`Handler`)**:
- [ ] 在 `Handler` 方法返回的 `http.HandlerFunc` 内部,获取 `r.Context()` 作为 `upstreamCtx`
- [ ] 使用 `newCtx, logger := logs.Trace(upstreamCtx, p.selfCtx, "Handler")` 获取 `logger` 实例。
- [ ] 将所有对 `p.logger.Warn` 的调用替换为 `logger.Warn`
- [x] 在 `Handler` 方法返回的 `http.HandlerFunc` 内部,获取 `r.Context()` 作为 `upstreamCtx`
- [x] 使用 `newCtx, logger := logs.Trace(upstreamCtx, p.selfCtx, "Handler")` 获取 `logger` 实例。
- [x] 将所有对 `p.logger.Warn` 的调用替换为 `logger.Warn`

View File

@@ -32,6 +32,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/infra/config"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)

View File

@@ -7,6 +7,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/middleware"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"github.com/labstack/echo/v4"
echoSwagger "github.com/swaggo/echo-swagger"
)

View File

@@ -4,6 +4,7 @@ import (
"errors"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"github.com/labstack/echo/v4"
)

View File

@@ -9,6 +9,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"github.com/labstack/echo/v4"
"gorm.io/gorm"
)

View File

@@ -7,6 +7,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
"github.com/labstack/echo/v4"
)

View File

@@ -7,6 +7,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"github.com/labstack/echo/v4"
)

View File

@@ -3,6 +3,7 @@ package management
import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"github.com/labstack/echo/v4"
)

View File

@@ -3,6 +3,7 @@ package management
import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"github.com/labstack/echo/v4"
)

View File

@@ -5,6 +5,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"github.com/labstack/echo/v4"
)

View File

@@ -9,6 +9,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"github.com/labstack/echo/v4"
)

View File

@@ -9,6 +9,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
"github.com/labstack/echo/v4"
)

View File

@@ -10,6 +10,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
"git.huangwc.com/pig/pig-farm-controller/internal/domain/plan"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"github.com/labstack/echo/v4"
)

View File

@@ -4,6 +4,7 @@ import (
"net/http"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"github.com/labstack/echo/v4"
)

View File

@@ -8,6 +8,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"github.com/labstack/echo/v4"
)

View File

@@ -2,6 +2,7 @@ package dto
import (
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"go.uber.org/zap/zapcore"
)

View File

@@ -5,6 +5,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/notify"
"go.uber.org/zap/zapcore"
)

View File

@@ -6,6 +6,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/domain/audit"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"github.com/labstack/echo/v4"
)

View File

@@ -12,6 +12,7 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
"github.com/labstack/echo/v4"
"gorm.io/gorm"
)

View File

@@ -1,13 +1,13 @@
// Package audit 提供了用户操作审计相关的功能
package audit
package service
import (
"context"
"time"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
// 移除对 "github.com/gin-gonic/gin" 的直接依赖
)
// RequestContext 封装了审计日志所需的请求上下文信息
@@ -17,27 +17,32 @@ type RequestContext struct {
HTTPMethod string
}
// Service 定义了审计服务的接口
type Service interface {
LogAction(user *models.User, reqCtx RequestContext, actionType, description string, targetResource interface{}, status models.AuditStatus, resultDetails string)
// AuditService 定义了审计服务的接口
type AuditService interface {
LogAction(ctx context.Context, user *models.User, reqCtx RequestContext, actionType, description string, targetResource interface{}, status models.AuditStatus, resultDetails string)
}
// service 是 Service 接口的实现
type service struct {
// auditService 是 AuditService 接口的实现
type auditService struct {
ctx context.Context
userActionLogRepository repository.UserActionLogRepository
logger *logs.Logger
}
// NewService 创建一个新的审计服务实例
func NewService(repo repository.UserActionLogRepository, logger *logs.Logger) Service {
return &service{userActionLogRepository: repo, logger: logger}
// NewAuditService 创建一个新的审计服务实例
func NewAuditService(ctx context.Context, repo repository.UserActionLogRepository) AuditService {
return &auditService{
ctx: ctx,
userActionLogRepository: repo,
}
}
// LogAction 记录一个用户操作。它在一个新的 goroutine 中异步执行,以避免阻塞主请求。
func (s *service) LogAction(user *models.User, reqCtx RequestContext, actionType, description string, targetResource interface{}, status models.AuditStatus, resultDetails string) {
func (s *auditService) LogAction(ctx context.Context, user *models.User, reqCtx RequestContext, actionType, description string, targetResource interface{}, status models.AuditStatus, resultDetails string) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "LogAction")
// 不再从 context 中获取用户信息,直接使用传入的 user 对象
if user == nil {
s.logger.Warnw("无法记录审计日志:传入的用户对象为 nil")
logger.Warnw("无法记录审计日志:传入的用户对象为 nil")
return
}
@@ -56,14 +61,14 @@ func (s *service) LogAction(user *models.User, reqCtx RequestContext, actionType
// 使用模型提供的方法来设置 TargetResource
if err := log.SetTargetResource(targetResource); err != nil {
s.logger.Errorw("无法记录审计日志:序列化 targetResource 失败", "error", err)
logger.Errorw("无法记录审计日志:序列化 targetResource 失败", "error", err)
// 即使序列化失败,我们可能仍然希望记录操作本身,所以不在此处 return
}
// 异步写入数据库,不阻塞当前请求
go func() {
if err := s.userActionLogRepository.Create(log); err != nil {
s.logger.Errorw("异步保存审计日志失败", "error", err)
if err := s.userActionLogRepository.Create(serviceCtx, log); err != nil {
logger.Errorw("异步保存审计日志失败", "error", err)
}
}()
}

View File

@@ -1,12 +1,14 @@
package service
import (
"context"
"encoding/json"
"errors"
"fmt"
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
"git.huangwc.com/pig/pig-farm-controller/internal/domain/device"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
)
@@ -25,42 +27,45 @@ var (
// DeviceService 定义了应用层的设备服务接口,用于协调设备相关的业务逻辑。
// DeviceService 定义了应用层的设备服务接口,用于协调设备相关的业务逻辑。
type DeviceService interface {
CreateDevice(req *dto.CreateDeviceRequest) (*dto.DeviceResponse, error)
GetDevice(id uint) (*dto.DeviceResponse, error)
ListDevices() ([]*dto.DeviceResponse, error)
UpdateDevice(id uint, req *dto.UpdateDeviceRequest) (*dto.DeviceResponse, error)
DeleteDevice(id uint) error
ManualControl(id uint, req *dto.ManualControlDeviceRequest) error
CreateDevice(ctx context.Context, req *dto.CreateDeviceRequest) (*dto.DeviceResponse, error)
GetDevice(ctx context.Context, id uint) (*dto.DeviceResponse, error)
ListDevices(ctx context.Context) ([]*dto.DeviceResponse, error)
UpdateDevice(ctx context.Context, id uint, req *dto.UpdateDeviceRequest) (*dto.DeviceResponse, error)
DeleteDevice(ctx context.Context, id uint) error
ManualControl(ctx context.Context, id uint, req *dto.ManualControlDeviceRequest) error
CreateAreaController(req *dto.CreateAreaControllerRequest) (*dto.AreaControllerResponse, error)
GetAreaController(id uint) (*dto.AreaControllerResponse, error)
ListAreaControllers() ([]*dto.AreaControllerResponse, error)
UpdateAreaController(id uint, req *dto.UpdateAreaControllerRequest) (*dto.AreaControllerResponse, error)
DeleteAreaController(id uint) error
CreateAreaController(ctx context.Context, req *dto.CreateAreaControllerRequest) (*dto.AreaControllerResponse, error)
GetAreaController(ctx context.Context, id uint) (*dto.AreaControllerResponse, error)
ListAreaControllers(ctx context.Context) ([]*dto.AreaControllerResponse, error)
UpdateAreaController(ctx context.Context, id uint, req *dto.UpdateAreaControllerRequest) (*dto.AreaControllerResponse, error)
DeleteAreaController(ctx context.Context, id uint) error
CreateDeviceTemplate(req *dto.CreateDeviceTemplateRequest) (*dto.DeviceTemplateResponse, error)
GetDeviceTemplate(id uint) (*dto.DeviceTemplateResponse, error)
ListDeviceTemplates() ([]*dto.DeviceTemplateResponse, error)
UpdateDeviceTemplate(id uint, req *dto.UpdateDeviceTemplateRequest) (*dto.DeviceTemplateResponse, error)
DeleteDeviceTemplate(id uint) error
CreateDeviceTemplate(ctx context.Context, req *dto.CreateDeviceTemplateRequest) (*dto.DeviceTemplateResponse, error)
GetDeviceTemplate(ctx context.Context, id uint) (*dto.DeviceTemplateResponse, error)
ListDeviceTemplates(ctx context.Context) ([]*dto.DeviceTemplateResponse, error)
UpdateDeviceTemplate(ctx context.Context, id uint, req *dto.UpdateDeviceTemplateRequest) (*dto.DeviceTemplateResponse, error)
DeleteDeviceTemplate(ctx context.Context, id uint) error
}
// deviceService 是 DeviceService 接口的具体实现。
type deviceService struct {
ctx context.Context
deviceRepo repository.DeviceRepository
areaControllerRepo repository.AreaControllerRepository
deviceTemplateRepo repository.DeviceTemplateRepository
deviceDomainSvc device.Service // 依赖领域服务
deviceDomainSvc device.Service
}
// NewDeviceService 创建一个新的 DeviceService 实例。
func NewDeviceService(
ctx context.Context,
deviceRepo repository.DeviceRepository,
areaControllerRepo repository.AreaControllerRepository,
deviceTemplateRepo repository.DeviceTemplateRepository,
deviceDomainSvc device.Service,
) DeviceService {
return &deviceService{
ctx: ctx,
deviceRepo: deviceRepo,
areaControllerRepo: areaControllerRepo,
deviceTemplateRepo: deviceTemplateRepo,
@@ -70,7 +75,8 @@ func NewDeviceService(
// --- Devices ---
func (s *deviceService) CreateDevice(req *dto.CreateDeviceRequest) (*dto.DeviceResponse, error) {
func (s *deviceService) CreateDevice(ctx context.Context, req *dto.CreateDeviceRequest) (*dto.DeviceResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreateDevice")
propertiesJSON, err := json.Marshal(req.Properties)
if err != nil {
return nil, err // Consider wrapping this error for better context
@@ -88,11 +94,11 @@ func (s *deviceService) CreateDevice(req *dto.CreateDeviceRequest) (*dto.DeviceR
return nil, err
}
if err := s.deviceRepo.Create(device); err != nil {
if err := s.deviceRepo.Create(serviceCtx, device); err != nil {
return nil, err
}
createdDevice, err := s.deviceRepo.FindByID(device.ID)
createdDevice, err := s.deviceRepo.FindByID(serviceCtx, device.ID)
if err != nil {
return nil, err
}
@@ -100,24 +106,27 @@ func (s *deviceService) CreateDevice(req *dto.CreateDeviceRequest) (*dto.DeviceR
return dto.NewDeviceResponse(createdDevice)
}
func (s *deviceService) GetDevice(id uint) (*dto.DeviceResponse, error) {
device, err := s.deviceRepo.FindByID(id)
func (s *deviceService) GetDevice(ctx context.Context, id uint) (*dto.DeviceResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetDevice")
device, err := s.deviceRepo.FindByID(serviceCtx, id)
if err != nil {
return nil, err
}
return dto.NewDeviceResponse(device)
}
func (s *deviceService) ListDevices() ([]*dto.DeviceResponse, error) {
devices, err := s.deviceRepo.ListAll()
func (s *deviceService) ListDevices(ctx context.Context) ([]*dto.DeviceResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListDevices")
devices, err := s.deviceRepo.ListAll(serviceCtx)
if err != nil {
return nil, err
}
return dto.NewListDeviceResponse(devices)
}
func (s *deviceService) UpdateDevice(id uint, req *dto.UpdateDeviceRequest) (*dto.DeviceResponse, error) {
existingDevice, err := s.deviceRepo.FindByID(id)
func (s *deviceService) UpdateDevice(ctx context.Context, id uint, req *dto.UpdateDeviceRequest) (*dto.DeviceResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateDevice")
existingDevice, err := s.deviceRepo.FindByID(serviceCtx, id)
if err != nil {
return nil, err
}
@@ -137,11 +146,11 @@ func (s *deviceService) UpdateDevice(id uint, req *dto.UpdateDeviceRequest) (*dt
return nil, err
}
if err := s.deviceRepo.Update(existingDevice); err != nil {
if err := s.deviceRepo.Update(serviceCtx, existingDevice); err != nil {
return nil, err
}
updatedDevice, err := s.deviceRepo.FindByID(existingDevice.ID)
updatedDevice, err := s.deviceRepo.FindByID(serviceCtx, existingDevice.ID)
if err != nil {
return nil, err
}
@@ -149,16 +158,17 @@ func (s *deviceService) UpdateDevice(id uint, req *dto.UpdateDeviceRequest) (*dt
return dto.NewDeviceResponse(updatedDevice)
}
func (s *deviceService) DeleteDevice(id uint) error {
func (s *deviceService) DeleteDevice(ctx context.Context, id uint) error {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeleteDevice")
// 检查设备是否存在
_, err := s.deviceRepo.FindByID(id)
_, err := s.deviceRepo.FindByID(serviceCtx, id)
if err != nil {
return err // 如果未找到,会返回 gorm.ErrRecordNotFound
}
// 在删除前检查设备是否被任务使用
inUse, err := s.deviceRepo.IsDeviceInUse(id)
inUse, err := s.deviceRepo.IsDeviceInUse(serviceCtx, id)
if err != nil {
// 如果检查过程中发生数据库错误,则返回错误
return fmt.Errorf("检查设备使用情况失败: %w", err)
@@ -169,17 +179,18 @@ func (s *deviceService) DeleteDevice(id uint) error {
}
// 只有在未被使用时,才执行删除操作
return s.deviceRepo.Delete(id)
return s.deviceRepo.Delete(serviceCtx, id)
}
func (s *deviceService) ManualControl(id uint, req *dto.ManualControlDeviceRequest) error {
dev, err := s.deviceRepo.FindByID(id)
func (s *deviceService) ManualControl(ctx context.Context, id uint, req *dto.ManualControlDeviceRequest) error {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ManualControl")
dev, err := s.deviceRepo.FindByID(serviceCtx, id)
if err != nil {
return err
}
if req.Action == nil {
return s.deviceDomainSvc.Collect(dev.AreaControllerID, []*models.Device{dev})
return s.deviceDomainSvc.Collect(serviceCtx, dev.AreaControllerID, []*models.Device{dev})
} else {
action := device.DeviceActionStart
switch *req.Action {
@@ -190,13 +201,14 @@ func (s *deviceService) ManualControl(id uint, req *dto.ManualControlDeviceReque
default:
return errors.New("invalid action")
}
return s.deviceDomainSvc.Switch(dev, action)
return s.deviceDomainSvc.Switch(serviceCtx, dev, action)
}
}
// --- Area Controllers ---
func (s *deviceService) CreateAreaController(req *dto.CreateAreaControllerRequest) (*dto.AreaControllerResponse, error) {
func (s *deviceService) CreateAreaController(ctx context.Context, req *dto.CreateAreaControllerRequest) (*dto.AreaControllerResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreateAreaController")
propertiesJSON, err := json.Marshal(req.Properties)
if err != nil {
return nil, err
@@ -213,31 +225,34 @@ func (s *deviceService) CreateAreaController(req *dto.CreateAreaControllerReques
return nil, err
}
if err := s.areaControllerRepo.Create(ac); err != nil {
if err := s.areaControllerRepo.Create(serviceCtx, ac); err != nil {
return nil, err
}
return dto.NewAreaControllerResponse(ac)
}
func (s *deviceService) GetAreaController(id uint) (*dto.AreaControllerResponse, error) {
ac, err := s.areaControllerRepo.FindByID(id)
func (s *deviceService) GetAreaController(ctx context.Context, id uint) (*dto.AreaControllerResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetAreaController")
ac, err := s.areaControllerRepo.FindByID(serviceCtx, id)
if err != nil {
return nil, err
}
return dto.NewAreaControllerResponse(ac)
}
func (s *deviceService) ListAreaControllers() ([]*dto.AreaControllerResponse, error) {
acs, err := s.areaControllerRepo.ListAll()
func (s *deviceService) ListAreaControllers(ctx context.Context) ([]*dto.AreaControllerResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListAreaControllers")
acs, err := s.areaControllerRepo.ListAll(serviceCtx)
if err != nil {
return nil, err
}
return dto.NewListAreaControllerResponse(acs)
}
func (s *deviceService) UpdateAreaController(id uint, req *dto.UpdateAreaControllerRequest) (*dto.AreaControllerResponse, error) {
existingAC, err := s.areaControllerRepo.FindByID(id)
func (s *deviceService) UpdateAreaController(ctx context.Context, id uint, req *dto.UpdateAreaControllerRequest) (*dto.AreaControllerResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateAreaController")
existingAC, err := s.areaControllerRepo.FindByID(serviceCtx, id)
if err != nil {
return nil, err
}
@@ -256,23 +271,24 @@ func (s *deviceService) UpdateAreaController(id uint, req *dto.UpdateAreaControl
return nil, err
}
if err := s.areaControllerRepo.Update(existingAC); err != nil {
if err := s.areaControllerRepo.Update(serviceCtx, existingAC); err != nil {
return nil, err
}
return dto.NewAreaControllerResponse(existingAC)
}
func (s *deviceService) DeleteAreaController(id uint) error {
func (s *deviceService) DeleteAreaController(ctx context.Context, id uint) error {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeleteAreaController")
// 1. 检查是否存在
_, err := s.areaControllerRepo.FindByID(id)
_, err := s.areaControllerRepo.FindByID(serviceCtx, id)
if err != nil {
return err // 如果未找到gorm会返回 ErrRecordNotFound
}
// 2. 检查是否被使用(业务逻辑)
inUse, err := s.deviceRepo.IsAreaControllerInUse(id)
inUse, err := s.deviceRepo.IsAreaControllerInUse(serviceCtx, id)
if err != nil {
return err // 返回数据库检查错误
}
@@ -281,12 +297,13 @@ func (s *deviceService) DeleteAreaController(id uint) error {
}
// 3. 执行删除
return s.areaControllerRepo.Delete(id)
return s.areaControllerRepo.Delete(serviceCtx, id)
}
// --- Device Templates ---
func (s *deviceService) CreateDeviceTemplate(req *dto.CreateDeviceTemplateRequest) (*dto.DeviceTemplateResponse, error) {
func (s *deviceService) CreateDeviceTemplate(ctx context.Context, req *dto.CreateDeviceTemplateRequest) (*dto.DeviceTemplateResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreateDeviceTemplate")
commandsJSON, err := json.Marshal(req.Commands)
if err != nil {
return nil, err
@@ -310,31 +327,34 @@ func (s *deviceService) CreateDeviceTemplate(req *dto.CreateDeviceTemplateReques
return nil, err
}
if err := s.deviceTemplateRepo.Create(deviceTemplate); err != nil {
if err := s.deviceTemplateRepo.Create(serviceCtx, deviceTemplate); err != nil {
return nil, err
}
return dto.NewDeviceTemplateResponse(deviceTemplate)
}
func (s *deviceService) GetDeviceTemplate(id uint) (*dto.DeviceTemplateResponse, error) {
deviceTemplate, err := s.deviceTemplateRepo.FindByID(id)
func (s *deviceService) GetDeviceTemplate(ctx context.Context, id uint) (*dto.DeviceTemplateResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetDeviceTemplate")
deviceTemplate, err := s.deviceTemplateRepo.FindByID(serviceCtx, id)
if err != nil {
return nil, err
}
return dto.NewDeviceTemplateResponse(deviceTemplate)
}
func (s *deviceService) ListDeviceTemplates() ([]*dto.DeviceTemplateResponse, error) {
deviceTemplates, err := s.deviceTemplateRepo.ListAll()
func (s *deviceService) ListDeviceTemplates(ctx context.Context) ([]*dto.DeviceTemplateResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListDeviceTemplates")
deviceTemplates, err := s.deviceTemplateRepo.ListAll(serviceCtx)
if err != nil {
return nil, err
}
return dto.NewListDeviceTemplateResponse(deviceTemplates)
}
func (s *deviceService) UpdateDeviceTemplate(id uint, req *dto.UpdateDeviceTemplateRequest) (*dto.DeviceTemplateResponse, error) {
existingDeviceTemplate, err := s.deviceTemplateRepo.FindByID(id)
func (s *deviceService) UpdateDeviceTemplate(ctx context.Context, id uint, req *dto.UpdateDeviceTemplateRequest) (*dto.DeviceTemplateResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateDeviceTemplate")
existingDeviceTemplate, err := s.deviceTemplateRepo.FindByID(serviceCtx, id)
if err != nil {
return nil, err
}
@@ -360,23 +380,24 @@ func (s *deviceService) UpdateDeviceTemplate(id uint, req *dto.UpdateDeviceTempl
return nil, err
}
if err := s.deviceTemplateRepo.Update(existingDeviceTemplate); err != nil {
if err := s.deviceTemplateRepo.Update(serviceCtx, existingDeviceTemplate); err != nil {
return nil, err
}
return dto.NewDeviceTemplateResponse(existingDeviceTemplate)
}
func (s *deviceService) DeleteDeviceTemplate(id uint) error {
func (s *deviceService) DeleteDeviceTemplate(ctx context.Context, id uint) error {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeleteDeviceTemplate")
// 1. 检查是否存在
_, err := s.deviceTemplateRepo.FindByID(id)
_, err := s.deviceTemplateRepo.FindByID(serviceCtx, id)
if err != nil {
return err
}
// 2. 检查是否被使用(业务逻辑)
inUse, err := s.deviceTemplateRepo.IsInUse(id)
inUse, err := s.deviceTemplateRepo.IsInUse(serviceCtx, id)
if err != nil {
return err
}
@@ -385,5 +406,5 @@ func (s *deviceService) DeleteDeviceTemplate(id uint) error {
}
// 3. 执行删除
return s.deviceTemplateRepo.Delete(id)
return s.deviceTemplateRepo.Delete(serviceCtx, id)
}

View File

@@ -1,35 +1,39 @@
package service
import (
"context"
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
)
// MonitorService 定义了监控相关的业务逻辑服务接口
type MonitorService interface {
ListSensorData(req *dto.ListSensorDataRequest) (*dto.ListSensorDataResponse, error)
ListDeviceCommandLogs(req *dto.ListDeviceCommandLogRequest) (*dto.ListDeviceCommandLogResponse, error)
ListPlanExecutionLogs(req *dto.ListPlanExecutionLogRequest) (*dto.ListPlanExecutionLogResponse, error)
ListTaskExecutionLogs(req *dto.ListTaskExecutionLogRequest) (*dto.ListTaskExecutionLogResponse, error)
ListPendingCollections(req *dto.ListPendingCollectionRequest) (*dto.ListPendingCollectionResponse, error)
ListUserActionLogs(req *dto.ListUserActionLogRequest) (*dto.ListUserActionLogResponse, error)
ListRawMaterialPurchases(req *dto.ListRawMaterialPurchaseRequest) (*dto.ListRawMaterialPurchaseResponse, error)
ListRawMaterialStockLogs(req *dto.ListRawMaterialStockLogRequest) (*dto.ListRawMaterialStockLogResponse, error)
ListFeedUsageRecords(req *dto.ListFeedUsageRecordRequest) (*dto.ListFeedUsageRecordResponse, error)
ListMedicationLogs(req *dto.ListMedicationLogRequest) (*dto.ListMedicationLogResponse, error)
ListPigBatchLogs(req *dto.ListPigBatchLogRequest) (*dto.ListPigBatchLogResponse, error)
ListWeighingBatches(req *dto.ListWeighingBatchRequest) (*dto.ListWeighingBatchResponse, error)
ListWeighingRecords(req *dto.ListWeighingRecordRequest) (*dto.ListWeighingRecordResponse, error)
ListPigTransferLogs(req *dto.ListPigTransferLogRequest) (*dto.ListPigTransferLogResponse, error)
ListPigSickLogs(req *dto.ListPigSickLogRequest) (*dto.ListPigSickLogResponse, error)
ListPigPurchases(req *dto.ListPigPurchaseRequest) (*dto.ListPigPurchaseResponse, error)
ListPigSales(req *dto.ListPigSaleRequest) (*dto.ListPigSaleResponse, error)
ListNotifications(req *dto.ListNotificationRequest) (*dto.ListNotificationResponse, error)
ListSensorData(ctx context.Context, req *dto.ListSensorDataRequest) (*dto.ListSensorDataResponse, error)
ListDeviceCommandLogs(ctx context.Context, req *dto.ListDeviceCommandLogRequest) (*dto.ListDeviceCommandLogResponse, error)
ListPlanExecutionLogs(ctx context.Context, req *dto.ListPlanExecutionLogRequest) (*dto.ListPlanExecutionLogResponse, error)
ListTaskExecutionLogs(ctx context.Context, req *dto.ListTaskExecutionLogRequest) (*dto.ListTaskExecutionLogResponse, error)
ListPendingCollections(ctx context.Context, req *dto.ListPendingCollectionRequest) (*dto.ListPendingCollectionResponse, error)
ListUserActionLogs(ctx context.Context, req *dto.ListUserActionLogRequest) (*dto.ListUserActionLogResponse, error)
ListRawMaterialPurchases(ctx context.Context, req *dto.ListRawMaterialPurchaseRequest) (*dto.ListRawMaterialPurchaseResponse, error)
ListRawMaterialStockLogs(ctx context.Context, req *dto.ListRawMaterialStockLogRequest) (*dto.ListRawMaterialStockLogResponse, error)
ListFeedUsageRecords(ctx context.Context, req *dto.ListFeedUsageRecordRequest) (*dto.ListFeedUsageRecordResponse, error)
ListMedicationLogs(ctx context.Context, req *dto.ListMedicationLogRequest) (*dto.ListMedicationLogResponse, error)
ListPigBatchLogs(ctx context.Context, req *dto.ListPigBatchLogRequest) (*dto.ListPigBatchLogResponse, error)
ListWeighingBatches(ctx context.Context, req *dto.ListWeighingBatchRequest) (*dto.ListWeighingBatchResponse, error)
ListWeighingRecords(ctx context.Context, req *dto.ListWeighingRecordRequest) (*dto.ListWeighingRecordResponse, error)
ListPigTransferLogs(ctx context.Context, req *dto.ListPigTransferLogRequest) (*dto.ListPigTransferLogResponse, error)
ListPigSickLogs(ctx context.Context, req *dto.ListPigSickLogRequest) (*dto.ListPigSickLogResponse, error)
ListPigPurchases(ctx context.Context, req *dto.ListPigPurchaseRequest) (*dto.ListPigPurchaseResponse, error)
ListPigSales(ctx context.Context, req *dto.ListPigSaleRequest) (*dto.ListPigSaleResponse, error)
ListNotifications(ctx context.Context, req *dto.ListNotificationRequest) (*dto.ListNotificationResponse, error)
}
// monitorService 是 MonitorService 接口的具体实现
type monitorService struct {
ctx context.Context
sensorDataRepo repository.SensorDataRepository
deviceCommandLogRepo repository.DeviceCommandLogRepository
executionLogRepo repository.ExecutionLogRepository
@@ -48,6 +52,7 @@ type monitorService struct {
// NewMonitorService 创建一个新的 MonitorService 实例
func NewMonitorService(
ctx context.Context,
sensorDataRepo repository.SensorDataRepository,
deviceCommandLogRepo repository.DeviceCommandLogRepository,
executionLogRepo repository.ExecutionLogRepository,
@@ -64,6 +69,7 @@ func NewMonitorService(
notificationRepo repository.NotificationRepository,
) MonitorService {
return &monitorService{
ctx: ctx,
sensorDataRepo: sensorDataRepo,
deviceCommandLogRepo: deviceCommandLogRepo,
executionLogRepo: executionLogRepo,
@@ -82,7 +88,8 @@ func NewMonitorService(
}
// ListSensorData 负责处理查询传感器数据列表的业务逻辑
func (s *monitorService) ListSensorData(req *dto.ListSensorDataRequest) (*dto.ListSensorDataResponse, error) {
func (s *monitorService) ListSensorData(ctx context.Context, req *dto.ListSensorDataRequest) (*dto.ListSensorDataResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListSensorData")
opts := repository.SensorDataListOptions{
DeviceID: req.DeviceID,
OrderBy: req.OrderBy,
@@ -94,7 +101,7 @@ func (s *monitorService) ListSensorData(req *dto.ListSensorDataRequest) (*dto.Li
opts.SensorType = &sensorType
}
data, total, err := s.sensorDataRepo.List(opts, req.Page, req.PageSize)
data, total, err := s.sensorDataRepo.List(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -103,7 +110,8 @@ func (s *monitorService) ListSensorData(req *dto.ListSensorDataRequest) (*dto.Li
}
// ListDeviceCommandLogs 负责处理查询设备命令日志列表的业务逻辑
func (s *monitorService) ListDeviceCommandLogs(req *dto.ListDeviceCommandLogRequest) (*dto.ListDeviceCommandLogResponse, error) {
func (s *monitorService) ListDeviceCommandLogs(ctx context.Context, req *dto.ListDeviceCommandLogRequest) (*dto.ListDeviceCommandLogResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListDeviceCommandLogs")
opts := repository.DeviceCommandLogListOptions{
DeviceID: req.DeviceID,
ReceivedSuccess: req.ReceivedSuccess,
@@ -112,7 +120,7 @@ func (s *monitorService) ListDeviceCommandLogs(req *dto.ListDeviceCommandLogRequ
EndTime: req.EndTime,
}
data, total, err := s.deviceCommandLogRepo.List(opts, req.Page, req.PageSize)
data, total, err := s.deviceCommandLogRepo.List(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -121,7 +129,8 @@ func (s *monitorService) ListDeviceCommandLogs(req *dto.ListDeviceCommandLogRequ
}
// ListPlanExecutionLogs 负责处理查询计划执行日志列表的业务逻辑
func (s *monitorService) ListPlanExecutionLogs(req *dto.ListPlanExecutionLogRequest) (*dto.ListPlanExecutionLogResponse, error) {
func (s *monitorService) ListPlanExecutionLogs(ctx context.Context, req *dto.ListPlanExecutionLogRequest) (*dto.ListPlanExecutionLogResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPlanExecutionLogs")
opts := repository.PlanExecutionLogListOptions{
PlanID: req.PlanID,
OrderBy: req.OrderBy,
@@ -133,7 +142,7 @@ func (s *monitorService) ListPlanExecutionLogs(req *dto.ListPlanExecutionLogRequ
opts.Status = &status
}
planLogs, total, err := s.executionLogRepo.ListPlanExecutionLogs(opts, req.Page, req.PageSize)
planLogs, total, err := s.executionLogRepo.ListPlanExecutionLogs(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -151,7 +160,7 @@ func (s *monitorService) ListPlanExecutionLogs(req *dto.ListPlanExecutionLogRequ
planIds = append(planIds, datum.PlanID)
}
}
plans, err := s.planRepository.GetPlansByIDs(planIds)
plans, err := s.planRepository.GetPlansByIDs(serviceCtx, planIds)
if err != nil {
return nil, err
}
@@ -159,7 +168,8 @@ func (s *monitorService) ListPlanExecutionLogs(req *dto.ListPlanExecutionLogRequ
}
// ListTaskExecutionLogs 负责处理查询任务执行日志列表的业务逻辑
func (s *monitorService) ListTaskExecutionLogs(req *dto.ListTaskExecutionLogRequest) (*dto.ListTaskExecutionLogResponse, error) {
func (s *monitorService) ListTaskExecutionLogs(ctx context.Context, req *dto.ListTaskExecutionLogRequest) (*dto.ListTaskExecutionLogResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListTaskExecutionLogs")
opts := repository.TaskExecutionLogListOptions{
PlanExecutionLogID: req.PlanExecutionLogID,
TaskID: req.TaskID,
@@ -172,7 +182,7 @@ func (s *monitorService) ListTaskExecutionLogs(req *dto.ListTaskExecutionLogRequ
opts.Status = &status
}
data, total, err := s.executionLogRepo.ListTaskExecutionLogs(opts, req.Page, req.PageSize)
data, total, err := s.executionLogRepo.ListTaskExecutionLogs(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -181,7 +191,8 @@ func (s *monitorService) ListTaskExecutionLogs(req *dto.ListTaskExecutionLogRequ
}
// ListPendingCollections 负责处理查询待采集请求列表的业务逻辑
func (s *monitorService) ListPendingCollections(req *dto.ListPendingCollectionRequest) (*dto.ListPendingCollectionResponse, error) {
func (s *monitorService) ListPendingCollections(ctx context.Context, req *dto.ListPendingCollectionRequest) (*dto.ListPendingCollectionResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPendingCollections")
opts := repository.PendingCollectionListOptions{
DeviceID: req.DeviceID,
OrderBy: req.OrderBy,
@@ -193,7 +204,7 @@ func (s *monitorService) ListPendingCollections(req *dto.ListPendingCollectionRe
opts.Status = &status
}
data, total, err := s.pendingCollectionRepo.List(opts, req.Page, req.PageSize)
data, total, err := s.pendingCollectionRepo.List(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -202,7 +213,8 @@ func (s *monitorService) ListPendingCollections(req *dto.ListPendingCollectionRe
}
// ListUserActionLogs 负责处理查询用户操作日志列表的业务逻辑
func (s *monitorService) ListUserActionLogs(req *dto.ListUserActionLogRequest) (*dto.ListUserActionLogResponse, error) {
func (s *monitorService) ListUserActionLogs(ctx context.Context, req *dto.ListUserActionLogRequest) (*dto.ListUserActionLogResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListUserActionLogs")
opts := repository.UserActionLogListOptions{
UserID: req.UserID,
Username: req.Username,
@@ -216,7 +228,7 @@ func (s *monitorService) ListUserActionLogs(req *dto.ListUserActionLogRequest) (
opts.Status = &status
}
data, total, err := s.userActionLogRepo.List(opts, req.Page, req.PageSize)
data, total, err := s.userActionLogRepo.List(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -225,7 +237,8 @@ func (s *monitorService) ListUserActionLogs(req *dto.ListUserActionLogRequest) (
}
// ListRawMaterialPurchases 负责处理查询原料采购记录列表的业务逻辑
func (s *monitorService) ListRawMaterialPurchases(req *dto.ListRawMaterialPurchaseRequest) (*dto.ListRawMaterialPurchaseResponse, error) {
func (s *monitorService) ListRawMaterialPurchases(ctx context.Context, req *dto.ListRawMaterialPurchaseRequest) (*dto.ListRawMaterialPurchaseResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListRawMaterialPurchases")
opts := repository.RawMaterialPurchaseListOptions{
RawMaterialID: req.RawMaterialID,
Supplier: req.Supplier,
@@ -234,7 +247,7 @@ func (s *monitorService) ListRawMaterialPurchases(req *dto.ListRawMaterialPurcha
EndTime: req.EndTime,
}
data, total, err := s.rawMaterialRepo.ListRawMaterialPurchases(opts, req.Page, req.PageSize)
data, total, err := s.rawMaterialRepo.ListRawMaterialPurchases(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -243,7 +256,8 @@ func (s *monitorService) ListRawMaterialPurchases(req *dto.ListRawMaterialPurcha
}
// ListRawMaterialStockLogs 负责处理查询原料库存日志列表的业务逻辑
func (s *monitorService) ListRawMaterialStockLogs(req *dto.ListRawMaterialStockLogRequest) (*dto.ListRawMaterialStockLogResponse, error) {
func (s *monitorService) ListRawMaterialStockLogs(ctx context.Context, req *dto.ListRawMaterialStockLogRequest) (*dto.ListRawMaterialStockLogResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListRawMaterialStockLogs")
opts := repository.RawMaterialStockLogListOptions{
RawMaterialID: req.RawMaterialID,
SourceID: req.SourceID,
@@ -256,7 +270,7 @@ func (s *monitorService) ListRawMaterialStockLogs(req *dto.ListRawMaterialStockL
opts.SourceType = &sourceType
}
data, total, err := s.rawMaterialRepo.ListRawMaterialStockLogs(opts, req.Page, req.PageSize)
data, total, err := s.rawMaterialRepo.ListRawMaterialStockLogs(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -265,7 +279,8 @@ func (s *monitorService) ListRawMaterialStockLogs(req *dto.ListRawMaterialStockL
}
// ListFeedUsageRecords 负责处理查询饲料使用记录列表的业务逻辑
func (s *monitorService) ListFeedUsageRecords(req *dto.ListFeedUsageRecordRequest) (*dto.ListFeedUsageRecordResponse, error) {
func (s *monitorService) ListFeedUsageRecords(ctx context.Context, req *dto.ListFeedUsageRecordRequest) (*dto.ListFeedUsageRecordResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListFeedUsageRecords")
opts := repository.FeedUsageRecordListOptions{
PenID: req.PenID,
FeedFormulaID: req.FeedFormulaID,
@@ -275,7 +290,7 @@ func (s *monitorService) ListFeedUsageRecords(req *dto.ListFeedUsageRecordReques
EndTime: req.EndTime,
}
data, total, err := s.rawMaterialRepo.ListFeedUsageRecords(opts, req.Page, req.PageSize)
data, total, err := s.rawMaterialRepo.ListFeedUsageRecords(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -284,7 +299,8 @@ func (s *monitorService) ListFeedUsageRecords(req *dto.ListFeedUsageRecordReques
}
// ListMedicationLogs 负责处理查询用药记录列表的业务逻辑
func (s *monitorService) ListMedicationLogs(req *dto.ListMedicationLogRequest) (*dto.ListMedicationLogResponse, error) {
func (s *monitorService) ListMedicationLogs(ctx context.Context, req *dto.ListMedicationLogRequest) (*dto.ListMedicationLogResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListMedicationLogs")
opts := repository.MedicationLogListOptions{
PigBatchID: req.PigBatchID,
MedicationID: req.MedicationID,
@@ -298,7 +314,7 @@ func (s *monitorService) ListMedicationLogs(req *dto.ListMedicationLogRequest) (
opts.Reason = &reason
}
data, total, err := s.medicationRepo.ListMedicationLogs(opts, req.Page, req.PageSize)
data, total, err := s.medicationRepo.ListMedicationLogs(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -307,7 +323,8 @@ func (s *monitorService) ListMedicationLogs(req *dto.ListMedicationLogRequest) (
}
// ListPigBatchLogs 负责处理查询猪批次日志列表的业务逻辑
func (s *monitorService) ListPigBatchLogs(req *dto.ListPigBatchLogRequest) (*dto.ListPigBatchLogResponse, error) {
func (s *monitorService) ListPigBatchLogs(ctx context.Context, req *dto.ListPigBatchLogRequest) (*dto.ListPigBatchLogResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigBatchLogs")
opts := repository.PigBatchLogListOptions{
PigBatchID: req.PigBatchID,
OperatorID: req.OperatorID,
@@ -320,7 +337,7 @@ func (s *monitorService) ListPigBatchLogs(req *dto.ListPigBatchLogRequest) (*dto
opts.ChangeType = &changeType
}
data, total, err := s.pigBatchLogRepo.List(opts, req.Page, req.PageSize)
data, total, err := s.pigBatchLogRepo.List(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -329,7 +346,8 @@ func (s *monitorService) ListPigBatchLogs(req *dto.ListPigBatchLogRequest) (*dto
}
// ListWeighingBatches 负责处理查询批次称重记录列表的业务逻辑
func (s *monitorService) ListWeighingBatches(req *dto.ListWeighingBatchRequest) (*dto.ListWeighingBatchResponse, error) {
func (s *monitorService) ListWeighingBatches(ctx context.Context, req *dto.ListWeighingBatchRequest) (*dto.ListWeighingBatchResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListWeighingBatches")
opts := repository.WeighingBatchListOptions{
PigBatchID: req.PigBatchID,
OrderBy: req.OrderBy,
@@ -337,7 +355,7 @@ func (s *monitorService) ListWeighingBatches(req *dto.ListWeighingBatchRequest)
EndTime: req.EndTime,
}
data, total, err := s.pigBatchRepo.ListWeighingBatches(opts, req.Page, req.PageSize)
data, total, err := s.pigBatchRepo.ListWeighingBatches(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -346,7 +364,8 @@ func (s *monitorService) ListWeighingBatches(req *dto.ListWeighingBatchRequest)
}
// ListWeighingRecords 负责处理查询单次称重记录列表的业务逻辑
func (s *monitorService) ListWeighingRecords(req *dto.ListWeighingRecordRequest) (*dto.ListWeighingRecordResponse, error) {
func (s *monitorService) ListWeighingRecords(ctx context.Context, req *dto.ListWeighingRecordRequest) (*dto.ListWeighingRecordResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListWeighingRecords")
opts := repository.WeighingRecordListOptions{
WeighingBatchID: req.WeighingBatchID,
PenID: req.PenID,
@@ -356,7 +375,7 @@ func (s *monitorService) ListWeighingRecords(req *dto.ListWeighingRecordRequest)
EndTime: req.EndTime,
}
data, total, err := s.pigBatchRepo.ListWeighingRecords(opts, req.Page, req.PageSize)
data, total, err := s.pigBatchRepo.ListWeighingRecords(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -365,7 +384,8 @@ func (s *monitorService) ListWeighingRecords(req *dto.ListWeighingRecordRequest)
}
// ListPigTransferLogs 负责处理查询猪只迁移日志列表的业务逻辑
func (s *monitorService) ListPigTransferLogs(req *dto.ListPigTransferLogRequest) (*dto.ListPigTransferLogResponse, error) {
func (s *monitorService) ListPigTransferLogs(ctx context.Context, req *dto.ListPigTransferLogRequest) (*dto.ListPigTransferLogResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigTransferLogs")
opts := repository.PigTransferLogListOptions{
PigBatchID: req.PigBatchID,
PenID: req.PenID,
@@ -380,7 +400,7 @@ func (s *monitorService) ListPigTransferLogs(req *dto.ListPigTransferLogRequest)
opts.TransferType = &transferType
}
data, total, err := s.pigTransferLogRepo.ListPigTransferLogs(opts, req.Page, req.PageSize)
data, total, err := s.pigTransferLogRepo.ListPigTransferLogs(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -389,7 +409,8 @@ func (s *monitorService) ListPigTransferLogs(req *dto.ListPigTransferLogRequest)
}
// ListPigSickLogs 负责处理查询病猪日志列表的业务逻辑
func (s *monitorService) ListPigSickLogs(req *dto.ListPigSickLogRequest) (*dto.ListPigSickLogResponse, error) {
func (s *monitorService) ListPigSickLogs(ctx context.Context, req *dto.ListPigSickLogRequest) (*dto.ListPigSickLogResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigSickLogs")
opts := repository.PigSickLogListOptions{
PigBatchID: req.PigBatchID,
PenID: req.PenID,
@@ -407,7 +428,7 @@ func (s *monitorService) ListPigSickLogs(req *dto.ListPigSickLogRequest) (*dto.L
opts.TreatmentLocation = &treatmentLocation
}
data, total, err := s.pigSickLogRepo.ListPigSickLogs(opts, req.Page, req.PageSize)
data, total, err := s.pigSickLogRepo.ListPigSickLogs(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -416,7 +437,8 @@ func (s *monitorService) ListPigSickLogs(req *dto.ListPigSickLogRequest) (*dto.L
}
// ListPigPurchases 负责处理查询猪只采购记录列表的业务逻辑
func (s *monitorService) ListPigPurchases(req *dto.ListPigPurchaseRequest) (*dto.ListPigPurchaseResponse, error) {
func (s *monitorService) ListPigPurchases(ctx context.Context, req *dto.ListPigPurchaseRequest) (*dto.ListPigPurchaseResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigPurchases")
opts := repository.PigPurchaseListOptions{
PigBatchID: req.PigBatchID,
Supplier: req.Supplier,
@@ -426,7 +448,7 @@ func (s *monitorService) ListPigPurchases(req *dto.ListPigPurchaseRequest) (*dto
EndTime: req.EndTime,
}
data, total, err := s.pigTradeRepo.ListPigPurchases(opts, req.Page, req.PageSize)
data, total, err := s.pigTradeRepo.ListPigPurchases(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -435,7 +457,8 @@ func (s *monitorService) ListPigPurchases(req *dto.ListPigPurchaseRequest) (*dto
}
// ListPigSales 负责处理查询猪只销售记录列表的业务逻辑
func (s *monitorService) ListPigSales(req *dto.ListPigSaleRequest) (*dto.ListPigSaleResponse, error) {
func (s *monitorService) ListPigSales(ctx context.Context, req *dto.ListPigSaleRequest) (*dto.ListPigSaleResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigSales")
opts := repository.PigSaleListOptions{
PigBatchID: req.PigBatchID,
Buyer: req.Buyer,
@@ -445,7 +468,7 @@ func (s *monitorService) ListPigSales(req *dto.ListPigSaleRequest) (*dto.ListPig
EndTime: req.EndTime,
}
data, total, err := s.pigTradeRepo.ListPigSales(opts, req.Page, req.PageSize)
data, total, err := s.pigTradeRepo.ListPigSales(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}
@@ -454,7 +477,8 @@ func (s *monitorService) ListPigSales(req *dto.ListPigSaleRequest) (*dto.ListPig
}
// ListNotifications 负责处理查询通知列表的业务逻辑
func (s *monitorService) ListNotifications(req *dto.ListNotificationRequest) (*dto.ListNotificationResponse, error) {
func (s *monitorService) ListNotifications(ctx context.Context, req *dto.ListNotificationRequest) (*dto.ListNotificationResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListNotifications")
opts := repository.NotificationListOptions{
UserID: req.UserID,
NotifierType: req.NotifierType,
@@ -465,7 +489,7 @@ func (s *monitorService) ListNotifications(req *dto.ListNotificationRequest) (*d
Status: req.Status,
}
data, total, err := s.notificationRepo.List(opts, req.Page, req.PageSize)
data, total, err := s.notificationRepo.List(serviceCtx, opts, req.Page, req.PageSize)
if err != nil {
return nil, err
}

View File

@@ -1,6 +1,7 @@
package service
import (
"context"
"time"
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
@@ -11,47 +12,47 @@ import (
// PigBatchService 接口定义保持不变,继续作为应用层对外的契约。
type PigBatchService interface {
CreatePigBatch(operatorID uint, dto *dto.PigBatchCreateDTO) (*dto.PigBatchResponseDTO, error)
GetPigBatch(id uint) (*dto.PigBatchResponseDTO, error)
UpdatePigBatch(id uint, dto *dto.PigBatchUpdateDTO) (*dto.PigBatchResponseDTO, error)
DeletePigBatch(id uint) error
ListPigBatches(isActive *bool) ([]*dto.PigBatchResponseDTO, error)
CreatePigBatch(ctx context.Context, operatorID uint, dto *dto.PigBatchCreateDTO) (*dto.PigBatchResponseDTO, error)
GetPigBatch(ctx context.Context, id uint) (*dto.PigBatchResponseDTO, error)
UpdatePigBatch(ctx context.Context, id uint, dto *dto.PigBatchUpdateDTO) (*dto.PigBatchResponseDTO, error)
DeletePigBatch(ctx context.Context, id uint) error
ListPigBatches(ctx context.Context, isActive *bool) ([]*dto.PigBatchResponseDTO, error)
// Pig Pen Management
AssignEmptyPensToBatch(batchID uint, penIDs []uint, operatorID uint) error
ReclassifyPenToNewBatch(fromBatchID uint, toBatchID uint, penID uint, operatorID uint, remarks string) error
RemoveEmptyPenFromBatch(batchID uint, penID uint) error
MovePigsIntoPen(batchID uint, toPenID uint, quantity int, operatorID uint, remarks string) error
AssignEmptyPensToBatch(ctx context.Context, batchID uint, penIDs []uint, operatorID uint) error
ReclassifyPenToNewBatch(ctx context.Context, fromBatchID uint, toBatchID uint, penID uint, operatorID uint, remarks string) error
RemoveEmptyPenFromBatch(ctx context.Context, batchID uint, penID uint) error
MovePigsIntoPen(ctx context.Context, batchID uint, toPenID uint, quantity int, operatorID uint, remarks string) error
// Trade Sub-service
SellPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error
BuyPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error
SellPigs(ctx context.Context, batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error
BuyPigs(ctx context.Context, batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error
// Transfer Sub-service
TransferPigsAcrossBatches(sourceBatchID uint, destBatchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error
TransferPigsWithinBatch(batchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error
TransferPigsAcrossBatches(ctx context.Context, sourceBatchID uint, destBatchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error
TransferPigsWithinBatch(ctx context.Context, batchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error
// Sick Pig Management
RecordSickPigs(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error
RecordSickPigRecovery(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error
RecordSickPigDeath(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error
RecordSickPigCull(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error
RecordSickPigs(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error
RecordSickPigRecovery(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error
RecordSickPigDeath(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error
RecordSickPigCull(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error
// Normal Pig Management
RecordDeath(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error
RecordCull(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error
RecordDeath(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error
RecordCull(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error
}
// pigBatchService 的实现现在依赖于领域服务接口。
type pigBatchService struct {
logger *logs.Logger
domainService domain_pig.PigBatchService // 依赖注入领域服务
ctx context.Context
domainService domain_pig.PigBatchService
}
// NewPigBatchService 构造函数被修改,以注入领域服务。
func NewPigBatchService(domainService domain_pig.PigBatchService, logger *logs.Logger) PigBatchService {
func NewPigBatchService(ctx context.Context, domainService domain_pig.PigBatchService) PigBatchService {
return &pigBatchService{
logger: logger,
ctx: ctx,
domainService: domainService,
}
}
@@ -78,7 +79,8 @@ func (s *pigBatchService) toPigBatchResponseDTO(batch *models.PigBatch, currentT
}
// CreatePigBatch 现在将请求委托给领域服务处理。
func (s *pigBatchService) CreatePigBatch(operatorID uint, dto *dto.PigBatchCreateDTO) (*dto.PigBatchResponseDTO, error) {
func (s *pigBatchService) CreatePigBatch(ctx context.Context, operatorID uint, dto *dto.PigBatchCreateDTO) (*dto.PigBatchResponseDTO, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "CreatePigBatch")
// 1. DTO -> 领域模型
batch := &models.PigBatch{
BatchNumber: dto.BatchNumber,
@@ -89,9 +91,9 @@ func (s *pigBatchService) CreatePigBatch(operatorID uint, dto *dto.PigBatchCreat
}
// 2. 调用领域服务
createdBatch, err := s.domainService.CreatePigBatch(operatorID, batch)
createdBatch, err := s.domainService.CreatePigBatch(serviceCtx, operatorID, batch)
if err != nil {
s.logger.Errorf("应用层: 创建猪批次失败: %v", err)
logger.Errorf("应用层: 创建猪批次失败: %v", err)
return nil, MapDomainError(err)
}
@@ -100,31 +102,33 @@ func (s *pigBatchService) CreatePigBatch(operatorID uint, dto *dto.PigBatchCreat
}
// GetPigBatch 从领域服务获取数据并转换为DTO同时处理错误转换。
func (s *pigBatchService) GetPigBatch(id uint) (*dto.PigBatchResponseDTO, error) {
batch, err := s.domainService.GetPigBatch(id)
func (s *pigBatchService) GetPigBatch(ctx context.Context, id uint) (*dto.PigBatchResponseDTO, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "GetPigBatch")
batch, err := s.domainService.GetPigBatch(serviceCtx, id)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次失败, ID: %d, 错误: %v", id, err)
logger.Warnf("应用层: 获取猪批次失败, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err)
}
currentTotalQuantity, err := s.domainService.GetCurrentPigQuantity(id)
currentTotalQuantity, err := s.domainService.GetCurrentPigQuantity(serviceCtx, id)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", id, err)
logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err)
}
currentTotalPigsInPens, err := s.domainService.GetTotalPigsInPensForBatch(id)
currentTotalPigsInPens, err := s.domainService.GetTotalPigsInPensForBatch(serviceCtx, id)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", id, err)
logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err)
}
return s.toPigBatchResponseDTO(batch, currentTotalQuantity, currentTotalPigsInPens), nil
}
// UpdatePigBatch 协调获取、更新和保存的流程,并处理错误转换。
func (s *pigBatchService) UpdatePigBatch(id uint, dto *dto.PigBatchUpdateDTO) (*dto.PigBatchResponseDTO, error) {
func (s *pigBatchService) UpdatePigBatch(ctx context.Context, id uint, dto *dto.PigBatchUpdateDTO) (*dto.PigBatchResponseDTO, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "UpdatePigBatch")
// 1. 先获取最新的领域模型
existingBatch, err := s.domainService.GetPigBatch(id)
existingBatch, err := s.domainService.GetPigBatch(serviceCtx, id)
if err != nil {
s.logger.Warnf("应用层: 更新猪批次失败,获取原批次信息错误, ID: %d, 错误: %v", id, err)
logger.Warnf("应用层: 更新猪批次失败,获取原批次信息错误, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err)
}
@@ -149,21 +153,21 @@ func (s *pigBatchService) UpdatePigBatch(id uint, dto *dto.PigBatchUpdateDTO) (*
}
// 3. 调用领域服务执行更新
updatedBatch, err := s.domainService.UpdatePigBatch(existingBatch)
updatedBatch, err := s.domainService.UpdatePigBatch(serviceCtx, existingBatch)
if err != nil {
s.logger.Errorf("应用层: 更新猪批次失败, ID: %d, 错误: %v", id, err)
logger.Errorf("应用层: 更新猪批次失败, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err)
}
// 4. 填充猪群信息
currentTotalQuantity, err := s.domainService.GetCurrentPigQuantity(id)
currentTotalQuantity, err := s.domainService.GetCurrentPigQuantity(serviceCtx, id)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", id, err)
logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err)
}
currentTotalPigsInPens, err := s.domainService.GetTotalPigsInPensForBatch(id)
currentTotalPigsInPens, err := s.domainService.GetTotalPigsInPensForBatch(serviceCtx, id)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", id, err)
logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", id, err)
return nil, MapDomainError(err)
}
@@ -172,33 +176,35 @@ func (s *pigBatchService) UpdatePigBatch(id uint, dto *dto.PigBatchUpdateDTO) (*
}
// DeletePigBatch 将删除操作委托给领域服务,并转换领域错误为应用层错误。
func (s *pigBatchService) DeletePigBatch(id uint) error {
err := s.domainService.DeletePigBatch(id)
func (s *pigBatchService) DeletePigBatch(ctx context.Context, id uint) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "DeletePigBatch")
err := s.domainService.DeletePigBatch(serviceCtx, id)
if err != nil {
s.logger.Errorf("应用层: 删除猪批次失败, ID: %d, 错误: %v", id, err)
logger.Errorf("应用层: 删除猪批次失败, ID: %d, 错误: %v", id, err)
return MapDomainError(err)
}
return nil
}
// ListPigBatches 从领域服务获取列表并进行转换。
func (s *pigBatchService) ListPigBatches(isActive *bool) ([]*dto.PigBatchResponseDTO, error) {
batches, err := s.domainService.ListPigBatches(isActive)
func (s *pigBatchService) ListPigBatches(ctx context.Context, isActive *bool) ([]*dto.PigBatchResponseDTO, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "ListPigBatches")
batches, err := s.domainService.ListPigBatches(serviceCtx, isActive)
if err != nil {
s.logger.Errorf("应用层: 批量查询猪批次失败: %v", err)
logger.Errorf("应用层: 批量查询猪批次失败: %v", err)
return nil, MapDomainError(err)
}
var responseDTOs []*dto.PigBatchResponseDTO
for _, batch := range batches {
currentTotalQuantity, err := s.domainService.GetCurrentPigQuantity(batch.ID)
currentTotalQuantity, err := s.domainService.GetCurrentPigQuantity(serviceCtx, batch.ID)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", batch.ID, err)
logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", batch.ID, err)
return nil, MapDomainError(err)
}
currentTotalPigsInPens, err := s.domainService.GetTotalPigsInPensForBatch(batch.ID)
currentTotalPigsInPens, err := s.domainService.GetTotalPigsInPensForBatch(serviceCtx, batch.ID)
if err != nil {
s.logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", batch.ID, err)
logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", batch.ID, err)
return nil, MapDomainError(err)
}
responseDTOs = append(responseDTOs, s.toPigBatchResponseDTO(batch, currentTotalQuantity, currentTotalPigsInPens))
@@ -208,140 +214,154 @@ func (s *pigBatchService) ListPigBatches(isActive *bool) ([]*dto.PigBatchRespons
}
// AssignEmptyPensToBatch 委托给领域服务
func (s *pigBatchService) AssignEmptyPensToBatch(batchID uint, penIDs []uint, operatorID uint) error {
err := s.domainService.AssignEmptyPensToBatch(batchID, penIDs, operatorID)
func (s *pigBatchService) AssignEmptyPensToBatch(ctx context.Context, batchID uint, penIDs []uint, operatorID uint) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "AssignEmptyPensToBatch")
err := s.domainService.AssignEmptyPensToBatch(serviceCtx, batchID, penIDs, operatorID)
if err != nil {
s.logger.Errorf("应用层: 为猪批次分配空栏失败, 批次ID: %d, 错误: %v", batchID, err)
logger.Errorf("应用层: 为猪批次分配空栏失败, 批次ID: %d, 错误: %v", batchID, err)
return MapDomainError(err)
}
return nil
}
// ReclassifyPenToNewBatch 委托给领域服务
func (s *pigBatchService) ReclassifyPenToNewBatch(fromBatchID uint, toBatchID uint, penID uint, operatorID uint, remarks string) error {
err := s.domainService.ReclassifyPenToNewBatch(fromBatchID, toBatchID, penID, operatorID, remarks)
func (s *pigBatchService) ReclassifyPenToNewBatch(ctx context.Context, fromBatchID uint, toBatchID uint, penID uint, operatorID uint, remarks string) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "ReclassifyPenToNewBatch")
err := s.domainService.ReclassifyPenToNewBatch(serviceCtx, fromBatchID, toBatchID, penID, operatorID, remarks)
if err != nil {
s.logger.Errorf("应用层: 划拨猪栏到新批次失败, 源批次ID: %d, 错误: %v", fromBatchID, err)
logger.Errorf("应用层: 划拨猪栏到新批次失败, 源批次ID: %d, 错误: %v", fromBatchID, err)
return MapDomainError(err)
}
return nil
}
// RemoveEmptyPenFromBatch 委托给领域服务
func (s *pigBatchService) RemoveEmptyPenFromBatch(batchID uint, penID uint) error {
err := s.domainService.RemoveEmptyPenFromBatch(batchID, penID)
func (s *pigBatchService) RemoveEmptyPenFromBatch(ctx context.Context, batchID uint, penID uint) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "RemoveEmptyPenFromBatch")
err := s.domainService.RemoveEmptyPenFromBatch(serviceCtx, batchID, penID)
if err != nil {
s.logger.Errorf("应用层: 从猪批次移除空栏失败, 批次ID: %d, 猪栏ID: %d, 错误: %v", batchID, penID, err)
logger.Errorf("应用层: 从猪批次移除空栏失败, 批次ID: %d, 猪栏ID: %d, 错误: %v", batchID, penID, err)
return MapDomainError(err)
}
return nil
}
// MovePigsIntoPen 委托给领域服务
func (s *pigBatchService) MovePigsIntoPen(batchID uint, toPenID uint, quantity int, operatorID uint, remarks string) error {
err := s.domainService.MovePigsIntoPen(batchID, toPenID, quantity, operatorID, remarks)
func (s *pigBatchService) MovePigsIntoPen(ctx context.Context, batchID uint, toPenID uint, quantity int, operatorID uint, remarks string) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "MovePigsIntoPen")
err := s.domainService.MovePigsIntoPen(serviceCtx, batchID, toPenID, quantity, operatorID, remarks)
if err != nil {
s.logger.Errorf("应用层: 将猪只移入猪栏失败, 批次ID: %d, 目标猪栏ID: %d, 错误: %v", batchID, toPenID, err)
logger.Errorf("应用层: 将猪只移入猪栏失败, 批次ID: %d, 目标猪栏ID: %d, 错误: %v", batchID, toPenID, err)
return MapDomainError(err)
}
return nil
}
// SellPigs 委托给领域服务
func (s *pigBatchService) SellPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error {
err := s.domainService.SellPigs(batchID, penID, quantity, unitPrice, tatalPrice, traderName, tradeDate, remarks, operatorID)
func (s *pigBatchService) SellPigs(ctx context.Context, batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "SellPigs")
err := s.domainService.SellPigs(serviceCtx, batchID, penID, quantity, unitPrice, tatalPrice, traderName, tradeDate, remarks, operatorID)
if err != nil {
s.logger.Errorf("应用层: 卖猪失败, 批次ID: %d, 错误: %v", batchID, err)
logger.Errorf("应用层: 卖猪失败, 批次ID: %d, 错误: %v", batchID, err)
return MapDomainError(err)
}
return nil
}
// BuyPigs 委托给领域服务
func (s *pigBatchService) BuyPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error {
err := s.domainService.BuyPigs(batchID, penID, quantity, unitPrice, tatalPrice, traderName, tradeDate, remarks, operatorID)
func (s *pigBatchService) BuyPigs(ctx context.Context, batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "BuyPigs")
err := s.domainService.BuyPigs(serviceCtx, batchID, penID, quantity, unitPrice, tatalPrice, traderName, tradeDate, remarks, operatorID)
if err != nil {
s.logger.Errorf("应用层: 买猪失败, 批次ID: %d, 错误: %v", batchID, err)
logger.Errorf("应用层: 买猪失败, 批次ID: %d, 错误: %v", batchID, err)
return MapDomainError(err)
}
return nil
}
// TransferPigsAcrossBatches 委托给领域服务
func (s *pigBatchService) TransferPigsAcrossBatches(sourceBatchID uint, destBatchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error {
err := s.domainService.TransferPigsAcrossBatches(sourceBatchID, destBatchID, fromPenID, toPenID, quantity, operatorID, remarks)
func (s *pigBatchService) TransferPigsAcrossBatches(ctx context.Context, sourceBatchID uint, destBatchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "TransferPigsAcrossBatches")
err := s.domainService.TransferPigsAcrossBatches(serviceCtx, sourceBatchID, destBatchID, fromPenID, toPenID, quantity, operatorID, remarks)
if err != nil {
s.logger.Errorf("应用层: 跨群调栏失败, 源批次ID: %d, 错误: %v", sourceBatchID, err)
logger.Errorf("应用层: 跨群调栏失败, 源批次ID: %d, 错误: %v", sourceBatchID, err)
return MapDomainError(err)
}
return nil
}
// TransferPigsWithinBatch 委托给领域服务
func (s *pigBatchService) TransferPigsWithinBatch(batchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error {
err := s.domainService.TransferPigsWithinBatch(batchID, fromPenID, toPenID, quantity, operatorID, remarks)
func (s *pigBatchService) TransferPigsWithinBatch(ctx context.Context, batchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "TransferPigsWithinBatch")
err := s.domainService.TransferPigsWithinBatch(serviceCtx, batchID, fromPenID, toPenID, quantity, operatorID, remarks)
if err != nil {
s.logger.Errorf("应用层: 群内调栏失败, 批次ID: %d, 错误: %v", batchID, err)
logger.Errorf("应用层: 群内调栏失败, 批次ID: %d, 错误: %v", batchID, err)
return MapDomainError(err)
}
return nil
}
// RecordSickPigs 委托给领域服务
func (s *pigBatchService) RecordSickPigs(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error {
err := s.domainService.RecordSickPigs(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks)
func (s *pigBatchService) RecordSickPigs(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "RecordSickPigs")
err := s.domainService.RecordSickPigs(serviceCtx, operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks)
if err != nil {
s.logger.Errorf("应用层: 记录病猪事件失败, 批次ID: %d, 错误: %v", batchID, err)
logger.Errorf("应用层: 记录病猪事件失败, 批次ID: %d, 错误: %v", batchID, err)
return MapDomainError(err)
}
return nil
}
// RecordSickPigRecovery 委托给领域服务
func (s *pigBatchService) RecordSickPigRecovery(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error {
err := s.domainService.RecordSickPigRecovery(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks)
func (s *pigBatchService) RecordSickPigRecovery(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "RecordSickPigRecovery")
err := s.domainService.RecordSickPigRecovery(serviceCtx, operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks)
if err != nil {
s.logger.Errorf("应用层: 记录病猪康复事件失败, 批次ID: %d, 错误: %v", batchID, err)
logger.Errorf("应用层: 记录病猪康复事件失败, 批次ID: %d, 错误: %v", batchID, err)
return MapDomainError(err)
}
return nil
}
// RecordSickPigDeath 委托给领域服务
func (s *pigBatchService) RecordSickPigDeath(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error {
err := s.domainService.RecordSickPigDeath(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks)
func (s *pigBatchService) RecordSickPigDeath(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "RecordSickPigDeath")
err := s.domainService.RecordSickPigDeath(serviceCtx, operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks)
if err != nil {
s.logger.Errorf("应用层: 记录病猪死亡事件失败, 批次ID: %d, 错误: %v", batchID, err)
logger.Errorf("应用层: 记录病猪死亡事件失败, 批次ID: %d, 错误: %v", batchID, err)
return MapDomainError(err)
}
return nil
}
// RecordSickPigCull 委托给领域服务
func (s *pigBatchService) RecordSickPigCull(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error {
err := s.domainService.RecordSickPigCull(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks)
func (s *pigBatchService) RecordSickPigCull(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "RecordSickPigCull")
err := s.domainService.RecordSickPigCull(serviceCtx, operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks)
if err != nil {
s.logger.Errorf("应用层: 记录病猪淘汰事件失败, 批次ID: %d, 错误: %v", batchID, err)
logger.Errorf("应用层: 记录病猪淘汰事件失败, 批次ID: %d, 错误: %v", batchID, err)
return MapDomainError(err)
}
return nil
}
// RecordDeath 委托给领域服务
func (s *pigBatchService) RecordDeath(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error {
err := s.domainService.RecordDeath(operatorID, batchID, penID, quantity, happenedAt, remarks)
func (s *pigBatchService) RecordDeath(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "RecordDeath")
err := s.domainService.RecordDeath(serviceCtx, operatorID, batchID, penID, quantity, happenedAt, remarks)
if err != nil {
s.logger.Errorf("应用层: 记录正常猪只死亡事件失败, 批次ID: %d, 错误: %v", batchID, err)
logger.Errorf("应用层: 记录正常猪只死亡事件失败, 批次ID: %d, 错误: %v", batchID, err)
return MapDomainError(err)
}
return nil
}
// RecordCull 委托给领域服务
func (s *pigBatchService) RecordCull(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error {
err := s.domainService.RecordCull(operatorID, batchID, penID, quantity, happenedAt, remarks)
func (s *pigBatchService) RecordCull(ctx context.Context, operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "RecordCull")
err := s.domainService.RecordCull(serviceCtx, operatorID, batchID, penID, quantity, happenedAt, remarks)
if err != nil {
s.logger.Errorf("应用层: 记录正常猪只淘汰事件失败, 批次ID: %d, 错误: %v", batchID, err)
logger.Errorf("应用层: 记录正常猪只淘汰事件失败, 批次ID: %d, 错误: %v", batchID, err)
return MapDomainError(err)
}
return nil

View File

@@ -1,6 +1,7 @@
package service
import (
"context"
"errors"
"fmt"
@@ -16,40 +17,41 @@ import (
// PigFarmService 提供了猪场资产管理的业务逻辑
type PigFarmService interface {
// PigHouse methods
CreatePigHouse(name, description string) (*dto.PigHouseResponse, error)
GetPigHouseByID(id uint) (*dto.PigHouseResponse, error)
ListPigHouses() ([]dto.PigHouseResponse, error)
UpdatePigHouse(id uint, name, description string) (*dto.PigHouseResponse, error)
DeletePigHouse(id uint) error
CreatePigHouse(ctx context.Context, name, description string) (*dto.PigHouseResponse, error)
GetPigHouseByID(ctx context.Context, id uint) (*dto.PigHouseResponse, error)
ListPigHouses(ctx context.Context) ([]dto.PigHouseResponse, error)
UpdatePigHouse(ctx context.Context, id uint, name, description string) (*dto.PigHouseResponse, error)
DeletePigHouse(ctx context.Context, id uint) error
// Pen methods
CreatePen(penNumber string, houseID uint, capacity int) (*dto.PenResponse, error)
GetPenByID(id uint) (*dto.PenResponse, error)
ListPens() ([]*dto.PenResponse, error)
UpdatePen(id uint, penNumber string, houseID uint, capacity int, status models.PenStatus) (*dto.PenResponse, error)
DeletePen(id uint) error
CreatePen(ctx context.Context, penNumber string, houseID uint, capacity int) (*dto.PenResponse, error)
GetPenByID(ctx context.Context, id uint) (*dto.PenResponse, error)
ListPens(ctx context.Context) ([]*dto.PenResponse, error)
UpdatePen(ctx context.Context, id uint, penNumber string, houseID uint, capacity int, status models.PenStatus) (*dto.PenResponse, error)
DeletePen(ctx context.Context, id uint) error
// UpdatePenStatus 更新猪栏状态
UpdatePenStatus(id uint, newStatus models.PenStatus) (*dto.PenResponse, error)
UpdatePenStatus(ctx context.Context, id uint, newStatus models.PenStatus) (*dto.PenResponse, error)
}
type pigFarmService struct {
logger *logs.Logger
ctx context.Context
farmRepository repository.PigFarmRepository
penRepository repository.PigPenRepository
batchRepository repository.PigBatchRepository
pigBatchService domain_pig.PigBatchService // Add domain PigBatchService dependency
uow repository.UnitOfWork // 工作单元,用于事务管理
pigBatchService domain_pig.PigBatchService
uow repository.UnitOfWork // 工作单元,用于事务管理
}
// NewPigFarmService 创建一个新的 PigFarmService 实例
func NewPigFarmService(farmRepository repository.PigFarmRepository,
func NewPigFarmService(ctx context.Context,
farmRepository repository.PigFarmRepository,
penRepository repository.PigPenRepository,
batchRepository repository.PigBatchRepository,
pigBatchService domain_pig.PigBatchService,
uow repository.UnitOfWork,
logger *logs.Logger) PigFarmService {
) PigFarmService {
return &pigFarmService{
logger: logger,
ctx: ctx,
farmRepository: farmRepository,
penRepository: penRepository,
batchRepository: batchRepository,
@@ -60,12 +62,13 @@ func NewPigFarmService(farmRepository repository.PigFarmRepository,
// --- PigHouse Implementation ---
func (s *pigFarmService) CreatePigHouse(name, description string) (*dto.PigHouseResponse, error) {
func (s *pigFarmService) CreatePigHouse(ctx context.Context, name, description string) (*dto.PigHouseResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigHouse")
house := &models.PigHouse{
Name: name,
Description: description,
}
err := s.farmRepository.CreatePigHouse(house)
err := s.farmRepository.CreatePigHouse(serviceCtx, house)
if err != nil {
return nil, err
}
@@ -76,8 +79,9 @@ func (s *pigFarmService) CreatePigHouse(name, description string) (*dto.PigHouse
}, nil
}
func (s *pigFarmService) GetPigHouseByID(id uint) (*dto.PigHouseResponse, error) {
house, err := s.farmRepository.GetPigHouseByID(id)
func (s *pigFarmService) GetPigHouseByID(ctx context.Context, id uint) (*dto.PigHouseResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigHouseByID")
house, err := s.farmRepository.GetPigHouseByID(serviceCtx, id)
if err != nil {
return nil, err
}
@@ -88,8 +92,9 @@ func (s *pigFarmService) GetPigHouseByID(id uint) (*dto.PigHouseResponse, error)
}, nil
}
func (s *pigFarmService) ListPigHouses() ([]dto.PigHouseResponse, error) {
houses, err := s.farmRepository.ListPigHouses()
func (s *pigFarmService) ListPigHouses(ctx context.Context) ([]dto.PigHouseResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigHouses")
houses, err := s.farmRepository.ListPigHouses(serviceCtx)
if err != nil {
return nil, err
}
@@ -104,13 +109,14 @@ func (s *pigFarmService) ListPigHouses() ([]dto.PigHouseResponse, error) {
return resp, nil
}
func (s *pigFarmService) UpdatePigHouse(id uint, name, description string) (*dto.PigHouseResponse, error) {
func (s *pigFarmService) UpdatePigHouse(ctx context.Context, id uint, name, description string) (*dto.PigHouseResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigHouse")
house := &models.PigHouse{
Model: gorm.Model{ID: id},
Name: name,
Description: description,
}
rowsAffected, err := s.farmRepository.UpdatePigHouse(house)
rowsAffected, err := s.farmRepository.UpdatePigHouse(serviceCtx, house)
if err != nil {
return nil, err
}
@@ -118,7 +124,7 @@ func (s *pigFarmService) UpdatePigHouse(id uint, name, description string) (*dto
return nil, ErrHouseNotFound
}
// 返回更新后的完整信息
updatedHouse, err := s.farmRepository.GetPigHouseByID(id)
updatedHouse, err := s.farmRepository.GetPigHouseByID(serviceCtx, id)
if err != nil {
return nil, err
}
@@ -129,9 +135,10 @@ func (s *pigFarmService) UpdatePigHouse(id uint, name, description string) (*dto
}, nil
}
func (s *pigFarmService) DeletePigHouse(id uint) error {
func (s *pigFarmService) DeletePigHouse(ctx context.Context, id uint) error {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigHouse")
// 业务逻辑:检查猪舍是否包含猪栏
penCount, err := s.farmRepository.CountPensInHouse(id)
penCount, err := s.farmRepository.CountPensInHouse(serviceCtx, id)
if err != nil {
return err
}
@@ -140,7 +147,7 @@ func (s *pigFarmService) DeletePigHouse(id uint) error {
}
// 调用仓库层进行删除
rowsAffected, err := s.farmRepository.DeletePigHouse(id)
rowsAffected, err := s.farmRepository.DeletePigHouse(serviceCtx, id)
if err != nil {
return err
}
@@ -152,9 +159,10 @@ func (s *pigFarmService) DeletePigHouse(id uint) error {
// --- Pen Implementation ---
func (s *pigFarmService) CreatePen(penNumber string, houseID uint, capacity int) (*dto.PenResponse, error) {
func (s *pigFarmService) CreatePen(ctx context.Context, penNumber string, houseID uint, capacity int) (*dto.PenResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePen")
// 业务逻辑:验证所属猪舍是否存在
_, err := s.farmRepository.GetPigHouseByID(houseID)
_, err := s.farmRepository.GetPigHouseByID(serviceCtx, houseID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrHouseNotFound
@@ -168,7 +176,7 @@ func (s *pigFarmService) CreatePen(penNumber string, houseID uint, capacity int)
Capacity: capacity,
Status: models.PenStatusEmpty,
}
err = s.penRepository.CreatePen(pen)
err = s.penRepository.CreatePen(serviceCtx, pen)
if err != nil {
return nil, err
}
@@ -181,15 +189,16 @@ func (s *pigFarmService) CreatePen(penNumber string, houseID uint, capacity int)
}, nil
}
func (s *pigFarmService) GetPenByID(id uint) (*dto.PenResponse, error) {
pen, err := s.penRepository.GetPenByID(id)
func (s *pigFarmService) GetPenByID(ctx context.Context, id uint) (*dto.PenResponse, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "GetPenByID")
pen, err := s.penRepository.GetPenByID(serviceCtx, id)
if err != nil {
return nil, err
}
currentPigCount, err := s.pigBatchService.GetCurrentPigsInPen(id)
currentPigCount, err := s.pigBatchService.GetCurrentPigsInPen(serviceCtx, id)
if err != nil {
s.logger.Errorf("获取猪栏 %d 存栏量失败: %v", id, err)
logger.Errorf("获取猪栏 %d 存栏量失败: %v", id, err)
currentPigCount = 0 // 如果获取计数时出错则默认为0
}
@@ -209,17 +218,18 @@ func (s *pigFarmService) GetPenByID(id uint) (*dto.PenResponse, error) {
return response, nil
}
func (s *pigFarmService) ListPens() ([]*dto.PenResponse, error) {
pens, err := s.penRepository.ListPens()
func (s *pigFarmService) ListPens(ctx context.Context) ([]*dto.PenResponse, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "ListPens")
pens, err := s.penRepository.ListPens(serviceCtx)
if err != nil {
return nil, err
}
var response []*dto.PenResponse
for _, pen := range pens {
currentPigCount, err := s.pigBatchService.GetCurrentPigsInPen(pen.ID)
currentPigCount, err := s.pigBatchService.GetCurrentPigsInPen(serviceCtx, pen.ID)
if err != nil {
s.logger.Errorf("获取猪栏 %d 存栏量失败: %v", pen.ID, err)
logger.Errorf("获取猪栏 %d 存栏量失败: %v", pen.ID, err)
currentPigCount = 0 // 如果获取计数时出错则默认为0
}
@@ -241,9 +251,10 @@ func (s *pigFarmService) ListPens() ([]*dto.PenResponse, error) {
return response, nil
}
func (s *pigFarmService) UpdatePen(id uint, penNumber string, houseID uint, capacity int, status models.PenStatus) (*dto.PenResponse, error) {
func (s *pigFarmService) UpdatePen(ctx context.Context, id uint, penNumber string, houseID uint, capacity int, status models.PenStatus) (*dto.PenResponse, error) {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePen")
// 业务逻辑:验证所属猪舍是否存在
_, err := s.farmRepository.GetPigHouseByID(houseID)
_, err := s.farmRepository.GetPigHouseByID(serviceCtx, houseID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrHouseNotFound
@@ -258,7 +269,7 @@ func (s *pigFarmService) UpdatePen(id uint, penNumber string, houseID uint, capa
Capacity: capacity,
Status: status,
}
rowsAffected, err := s.penRepository.UpdatePen(pen)
rowsAffected, err := s.penRepository.UpdatePen(serviceCtx, pen)
if err != nil {
return nil, err
}
@@ -266,7 +277,7 @@ func (s *pigFarmService) UpdatePen(id uint, penNumber string, houseID uint, capa
return nil, ErrPenNotFound
}
// 返回更新后的完整信息
updatedPen, err := s.penRepository.GetPenByID(id)
updatedPen, err := s.penRepository.GetPenByID(serviceCtx, id)
if err != nil {
return nil, err
}
@@ -280,9 +291,10 @@ func (s *pigFarmService) UpdatePen(id uint, penNumber string, houseID uint, capa
}, nil
}
func (s *pigFarmService) DeletePen(id uint) error {
func (s *pigFarmService) DeletePen(ctx context.Context, id uint) error {
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePen")
// 业务逻辑:检查猪栏是否被活跃批次使用
pen, err := s.penRepository.GetPenByID(id)
pen, err := s.penRepository.GetPenByID(serviceCtx, id)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrPenNotFound // 猪栏不存在
@@ -293,7 +305,7 @@ func (s *pigFarmService) DeletePen(id uint) error {
// 检查猪栏是否关联了活跃批次
// 注意pen.PigBatchID 是指针类型,需要检查是否为 nil
if pen.PigBatchID != nil && *pen.PigBatchID != 0 {
pigBatch, err := s.batchRepository.GetPigBatchByID(*pen.PigBatchID)
pigBatch, err := s.batchRepository.GetPigBatchByID(serviceCtx, *pen.PigBatchID)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
@@ -304,7 +316,7 @@ func (s *pigFarmService) DeletePen(id uint) error {
}
// 调用仓库层进行删除
rowsAffected, err := s.penRepository.DeletePen(id)
rowsAffected, err := s.penRepository.DeletePen(serviceCtx, id)
if err != nil {
return err
}
@@ -315,15 +327,16 @@ func (s *pigFarmService) DeletePen(id uint) error {
}
// UpdatePenStatus 更新猪栏状态
func (s *pigFarmService) UpdatePenStatus(id uint, newStatus models.PenStatus) (*dto.PenResponse, error) {
func (s *pigFarmService) UpdatePenStatus(ctx context.Context, id uint, newStatus models.PenStatus) (*dto.PenResponse, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "UpdatePenStatus")
var updatedPen *models.Pen
err := s.uow.ExecuteInTransaction(func(tx *gorm.DB) error {
pen, err := s.penRepository.GetPenByIDTx(tx, id)
pen, err := s.penRepository.GetPenByIDTx(serviceCtx, tx, id)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrPenNotFound
}
s.logger.Errorf("更新猪栏状态失败: 获取猪栏 %d 信息错误: %v", id, err)
logger.Errorf("更新猪栏状态失败: 获取猪栏 %d 信息错误: %v", id, err)
return fmt.Errorf("获取猪栏 %d 信息失败: %w", id, err)
}
@@ -348,15 +361,15 @@ func (s *pigFarmService) UpdatePenStatus(id uint, newStatus models.PenStatus) (*
"status": newStatus,
}
if err := s.penRepository.UpdatePenFieldsTx(tx, id, updates); err != nil {
s.logger.Errorf("更新猪栏 %d 状态失败: %v", id, err)
if err := s.penRepository.UpdatePenFieldsTx(serviceCtx, tx, id, updates); err != nil {
logger.Errorf("更新猪栏 %d 状态失败: %v", id, err)
return fmt.Errorf("更新猪栏 %d 状态失败: %w", id, err)
}
// 获取更新后的猪栏信息
updatedPen, err = s.penRepository.GetPenByIDTx(tx, id)
updatedPen, err = s.penRepository.GetPenByIDTx(serviceCtx, tx, id)
if err != nil {
s.logger.Errorf("更新猪栏状态后获取猪栏 %d 信息失败: %v", id, err)
logger.Errorf("更新猪栏状态后获取猪栏 %d 信息失败: %v", id, err)
return fmt.Errorf("更新猪栏状态后获取猪栏 %d 信息失败: %w", id, err)
}
return nil

View File

@@ -1,6 +1,7 @@
package service
import (
"context"
"errors"
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
@@ -12,100 +13,103 @@ import (
// PlanService 定义了计划相关的应用服务接口
type PlanService interface {
// CreatePlan 创建一个新的计划
CreatePlan(req *dto.CreatePlanRequest) (*dto.PlanResponse, error)
CreatePlan(ctx context.Context, req *dto.CreatePlanRequest) (*dto.PlanResponse, error)
// GetPlanByID 根据ID获取计划详情
GetPlanByID(id uint) (*dto.PlanResponse, error)
GetPlanByID(ctx context.Context, id uint) (*dto.PlanResponse, error)
// ListPlans 获取计划列表,支持过滤和分页
ListPlans(query *dto.ListPlansQuery) (*dto.ListPlansResponse, error)
ListPlans(ctx context.Context, query *dto.ListPlansQuery) (*dto.ListPlansResponse, error)
// UpdatePlan 更新计划
UpdatePlan(id uint, req *dto.UpdatePlanRequest) (*dto.PlanResponse, error)
UpdatePlan(ctx context.Context, id uint, req *dto.UpdatePlanRequest) (*dto.PlanResponse, error)
// DeletePlan 删除计划(软删除)
DeletePlan(id uint) error
DeletePlan(ctx context.Context, id uint) error
// StartPlan 启动计划
StartPlan(id uint) error
StartPlan(ctx context.Context, id uint) error
// StopPlan 停止计划
StopPlan(id uint) error
StopPlan(ctx context.Context, id uint) error
}
// planService 是 PlanService 接口的实现
type planService struct {
logger *logs.Logger
domainPlanService plan.Service // 替换为领域层的服务接口
ctx context.Context
domainPlanService plan.Service
}
// NewPlanService 创建一个新的 PlanService 实例
func NewPlanService(
logger *logs.Logger,
domainPlanService plan.Service, // 接收领域层服务
ctx context.Context,
domainPlanService plan.Service,
) PlanService {
return &planService{
logger: logger,
domainPlanService: domainPlanService, // 注入领域层服务
ctx: ctx,
domainPlanService: domainPlanService,
}
}
// CreatePlan 创建一个新的计划
func (s *planService) CreatePlan(req *dto.CreatePlanRequest) (*dto.PlanResponse, error) {
func (s *planService) CreatePlan(ctx context.Context, req *dto.CreatePlanRequest) (*dto.PlanResponse, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "CreatePlan")
const actionType = "应用服务层:创建计划"
// 使用 DTO 转换函数将请求转换为领域实体
planToCreate, err := dto.NewPlanFromCreateRequest(req)
if err != nil {
s.logger.Errorf("%s: 计划数据校验失败: %v", actionType, err)
logger.Errorf("%s: 计划数据校验失败: %v", actionType, err)
return nil, err
}
// 调用领域服务创建计划
createdPlan, err := s.domainPlanService.CreatePlan(planToCreate)
createdPlan, err := s.domainPlanService.CreatePlan(serviceCtx, planToCreate)
if err != nil {
s.logger.Errorf("%s: 领域服务创建计划失败: %v", actionType, err)
logger.Errorf("%s: 领域服务创建计划失败: %v", actionType, err)
return nil, err // 直接返回领域层错误
}
// 将领域实体转换为响应 DTO
resp, err := dto.NewPlanToResponse(createdPlan)
if err != nil {
s.logger.Errorf("%s: 序列化响应失败: %v, Plan: %+v", actionType, err, createdPlan)
logger.Errorf("%s: 序列化响应失败: %v, Plan: %+v", actionType, err, createdPlan)
return nil, errors.New("计划创建成功,但响应生成失败")
}
s.logger.Infof("%s: 计划创建成功, ID: %d", actionType, createdPlan.ID)
logger.Infof("%s: 计划创建成功, ID: %d", actionType, createdPlan.ID)
return resp, nil
}
// GetPlanByID 根据ID获取计划详情
func (s *planService) GetPlanByID(id uint) (*dto.PlanResponse, error) {
func (s *planService) GetPlanByID(ctx context.Context, id uint) (*dto.PlanResponse, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "GetPlanByID")
const actionType = "应用服务层:获取计划详情"
// 调用领域服务获取计划
plan, err := s.domainPlanService.GetPlanByID(id)
plan, err := s.domainPlanService.GetPlanByID(serviceCtx, id)
if err != nil {
s.logger.Errorf("%s: 领域服务获取计划详情失败: %v, ID: %d", actionType, err, id)
logger.Errorf("%s: 领域服务获取计划详情失败: %v, ID: %d", actionType, err, id)
return nil, err // 直接返回领域层错误
}
// 将领域实体转换为响应 DTO
resp, err := dto.NewPlanToResponse(plan)
if err != nil {
s.logger.Errorf("%s: 序列化响应失败: %v, Plan: %+v", actionType, err, plan)
logger.Errorf("%s: 序列化响应失败: %v, Plan: %+v", actionType, err, plan)
return nil, errors.New("获取计划详情失败: 内部数据格式错误")
}
s.logger.Infof("%s: 获取计划详情成功, ID: %d", actionType, id)
logger.Infof("%s: 获取计划详情成功, ID: %d", actionType, id)
return resp, nil
}
// ListPlans 获取计划列表,支持过滤和分页
func (s *planService) ListPlans(query *dto.ListPlansQuery) (*dto.ListPlansResponse, error) {
func (s *planService) ListPlans(ctx context.Context, query *dto.ListPlansQuery) (*dto.ListPlansResponse, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "ListPlans")
const actionType = "应用服务层:获取计划列表"
// 将 DTO 查询参数转换为领域层可接受的选项
opts := repository.ListPlansOptions{PlanType: query.PlanType}
// 调用领域服务获取计划列表
plans, total, err := s.domainPlanService.ListPlans(opts, query.Page, query.PageSize)
plans, total, err := s.domainPlanService.ListPlans(serviceCtx, opts, query.Page, query.PageSize)
if err != nil {
s.logger.Errorf("%s: 领域服务获取计划列表失败: %v", actionType, err)
logger.Errorf("%s: 领域服务获取计划列表失败: %v", actionType, err)
return nil, err // 直接返回领域层错误
}
@@ -114,7 +118,7 @@ func (s *planService) ListPlans(query *dto.ListPlansQuery) (*dto.ListPlansRespon
for _, p := range plans {
resp, err := dto.NewPlanToResponse(&p)
if err != nil {
s.logger.Errorf("%s: 序列化单个计划响应失败: %v, Plan: %+v", actionType, err, p)
logger.Errorf("%s: 序列化单个计划响应失败: %v, Plan: %+v", actionType, err, p)
// 这里选择跳过有问题的计划,并记录错误,而不是中断整个列表的返回
continue
}
@@ -125,81 +129,85 @@ func (s *planService) ListPlans(query *dto.ListPlansQuery) (*dto.ListPlansRespon
Plans: planResponses,
Total: total,
}
s.logger.Infof("%s: 获取计划列表成功, 数量: %d", actionType, len(planResponses))
logger.Infof("%s: 获取计划列表成功, 数量: %d", actionType, len(planResponses))
return resp, nil
}
// UpdatePlan 更新计划
func (s *planService) UpdatePlan(id uint, req *dto.UpdatePlanRequest) (*dto.PlanResponse, error) {
func (s *planService) UpdatePlan(ctx context.Context, id uint, req *dto.UpdatePlanRequest) (*dto.PlanResponse, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "UpdatePlan")
const actionType = "应用服务层:更新计划"
// 使用 DTO 转换函数将请求转换为领域实体
planToUpdate, err := dto.NewPlanFromUpdateRequest(req)
if err != nil {
s.logger.Errorf("%s: 计划数据校验失败: %v", actionType, err)
logger.Errorf("%s: 计划数据校验失败: %v", actionType, err)
return nil, err
}
planToUpdate.ID = id // 确保ID被设置
// 调用领域服务更新计划
updatedPlan, err := s.domainPlanService.UpdatePlan(planToUpdate)
updatedPlan, err := s.domainPlanService.UpdatePlan(serviceCtx, planToUpdate)
if err != nil {
s.logger.Errorf("%s: 领域服务更新计划失败: %v, ID: %d", actionType, err, id)
logger.Errorf("%s: 领域服务更新计划失败: %v, ID: %d", actionType, err, id)
return nil, err // 直接返回领域层错误
}
// 将领域实体转换为响应 DTO
resp, err := dto.NewPlanToResponse(updatedPlan)
if err != nil {
s.logger.Errorf("%s: 序列化响应失败: %v, Updated Plan: %+v", actionType, err, updatedPlan)
logger.Errorf("%s: 序列化响应失败: %v, Updated Plan: %+v", actionType, err, updatedPlan)
return nil, errors.New("计划更新成功,但响应生成失败")
}
s.logger.Infof("%s: 计划更新成功, ID: %d", actionType, updatedPlan.ID)
logger.Infof("%s: 计划更新成功, ID: %d", actionType, updatedPlan.ID)
return resp, nil
}
// DeletePlan 删除计划(软删除)
func (s *planService) DeletePlan(id uint) error {
func (s *planService) DeletePlan(ctx context.Context, id uint) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "DeletePlan")
const actionType = "应用服务层:删除计划"
// 调用领域服务删除计划
err := s.domainPlanService.DeletePlan(id)
err := s.domainPlanService.DeletePlan(serviceCtx, id)
if err != nil {
s.logger.Errorf("%s: 领域服务删除计划失败: %v, ID: %d", actionType, err, id)
logger.Errorf("%s: 领域服务删除计划失败: %v, ID: %d", actionType, err, id)
return err // 直接返回领域层错误
}
s.logger.Infof("%s: 计划删除成功, ID: %d", actionType, id)
logger.Infof("%s: 计划删除成功, ID: %d", actionType, id)
return nil
}
// StartPlan 启动计划
func (s *planService) StartPlan(id uint) error {
func (s *planService) StartPlan(ctx context.Context, id uint) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "StartPlan")
const actionType = "应用服务层:启动计划"
// 调用领域服务启动计划
err := s.domainPlanService.StartPlan(id)
err := s.domainPlanService.StartPlan(serviceCtx, id)
if err != nil {
s.logger.Errorf("%s: 领域服务启动计划失败: %v, ID: %d", actionType, err, id)
logger.Errorf("%s: 领域服务启动计划失败: %v, ID: %d", actionType, err, id)
return err // 直接返回领域层错误
}
s.logger.Infof("%s: 计划已成功启动, ID: %d", actionType, id)
logger.Infof("%s: 计划已成功启动, ID: %d", actionType, id)
return nil
}
// StopPlan 停止计划
func (s *planService) StopPlan(id uint) error {
func (s *planService) StopPlan(ctx context.Context, id uint) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "StopPlan")
const actionType = "应用服务层:停止计划"
// 调用领域服务停止计划
err := s.domainPlanService.StopPlan(id)
err := s.domainPlanService.StopPlan(serviceCtx, id)
if err != nil {
s.logger.Errorf("%s: 领域服务停止计划失败: %v, ID: %d", actionType, err, id)
logger.Errorf("%s: 领域服务停止计划失败: %v, ID: %d", actionType, err, id)
return err // 直接返回领域层错误
}
s.logger.Infof("%s: 计划已成功停止, ID: %d", actionType, id)
logger.Infof("%s: 计划已成功停止, ID: %d", actionType, id)
return nil
}

View File

@@ -1,6 +1,7 @@
package service
import (
"context"
"errors"
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
@@ -9,51 +10,53 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
"gorm.io/gorm"
)
// UserService 定义用户服务接口
type UserService interface {
CreateUser(req *dto.CreateUserRequest) (*dto.CreateUserResponse, error)
Login(req *dto.LoginRequest) (*dto.LoginResponse, error)
SendTestNotification(userID uint, req *dto.SendTestNotificationRequest) error
CreateUser(ctx context.Context, req *dto.CreateUserRequest) (*dto.CreateUserResponse, error)
Login(ctx context.Context, req *dto.LoginRequest) (*dto.LoginResponse, error)
SendTestNotification(ctx context.Context, userID uint, req *dto.SendTestNotificationRequest) error
}
// userService 实现了 UserService 接口
type userService struct {
ctx context.Context
userRepo repository.UserRepository
tokenService token.Service
notifyService domain_notify.Service
logger *logs.Logger
}
// NewUserService 创建并返回一个新的 UserService 实例
func NewUserService(
ctx context.Context,
userRepo repository.UserRepository,
tokenService token.Service,
notifyService domain_notify.Service,
logger *logs.Logger,
) UserService {
return &userService{
ctx: ctx,
userRepo: userRepo,
tokenService: tokenService,
notifyService: notifyService,
logger: logger,
}
}
// CreateUser 创建新用户
func (s *userService) CreateUser(req *dto.CreateUserRequest) (*dto.CreateUserResponse, error) {
func (s *userService) CreateUser(ctx context.Context, req *dto.CreateUserRequest) (*dto.CreateUserResponse, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "CreateUser")
user := &models.User{
Username: req.Username,
Password: req.Password, // 密码会在 BeforeSave 钩子中哈希
}
if err := s.userRepo.Create(user); err != nil {
s.logger.Errorf("创建用户: 创建用户失败: %v", err)
if err := s.userRepo.Create(serviceCtx, user); err != nil {
logger.Errorf("创建用户: 创建用户失败: %v", err)
// 尝试查询用户,以判断是否是用户名重复导致的错误
_, findErr := s.userRepo.FindByUsername(req.Username)
_, findErr := s.userRepo.FindByUsername(serviceCtx, req.Username)
if findErr == nil { // 如果能找到用户,说明是用户名重复
return nil, errors.New("用户名已存在")
}
@@ -69,14 +72,15 @@ func (s *userService) CreateUser(req *dto.CreateUserRequest) (*dto.CreateUserRes
}
// Login 用户登录
func (s *userService) Login(req *dto.LoginRequest) (*dto.LoginResponse, error) {
func (s *userService) Login(ctx context.Context, req *dto.LoginRequest) (*dto.LoginResponse, error) {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "Login")
// 使用新的方法,通过唯一标识符(用户名、邮箱等)查找用户
user, err := s.userRepo.FindUserForLogin(req.Identifier)
user, err := s.userRepo.FindUserForLogin(serviceCtx, req.Identifier)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("登录凭证不正确")
}
s.logger.Errorf("登录: 查询用户失败: %v", err)
logger.Errorf("登录: 查询用户失败: %v", err)
return nil, errors.New("登录失败")
}
@@ -87,7 +91,7 @@ func (s *userService) Login(req *dto.LoginRequest) (*dto.LoginResponse, error) {
// 登录成功,生成 JWT token
tokenString, err := s.tokenService.GenerateToken(user.ID)
if err != nil {
s.logger.Errorf("登录: 生成令牌失败: %v", err)
logger.Errorf("登录: 生成令牌失败: %v", err)
return nil, errors.New("登录失败,无法生成认证信息")
}
@@ -99,12 +103,13 @@ func (s *userService) Login(req *dto.LoginRequest) (*dto.LoginResponse, error) {
}
// SendTestNotification 发送测试通知
func (s *userService) SendTestNotification(userID uint, req *dto.SendTestNotificationRequest) error {
err := s.notifyService.SendTestMessage(userID, req.Type)
func (s *userService) SendTestNotification(ctx context.Context, userID uint, req *dto.SendTestNotificationRequest) error {
serviceCtx, logger := logs.Trace(ctx, s.ctx, "SendTestNotification")
err := s.notifyService.SendTestMessage(serviceCtx, userID, req.Type)
if err != nil {
s.logger.Errorf("发送测试通知: 服务层调用失败: %v", err)
logger.Errorf("发送测试通知: 服务层调用失败: %v", err)
return errors.New("发送测试消息失败: " + err.Error())
}
s.logger.Infof("发送测试通知: 成功为用户 %d 发送类型为 %s 的测试消息", userID, req.Type)
logger.Infof("发送测试通知: 成功为用户 %d 发送类型为 %s 的测试消息", userID, req.Type)
return nil
}

View File

@@ -7,7 +7,6 @@ import (
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
"git.huangwc.com/pig/pig-farm-controller/internal/app/webhook"
"git.huangwc.com/pig/pig-farm-controller/internal/domain/audit"
"git.huangwc.com/pig/pig-farm-controller/internal/domain/device"
domain_notify "git.huangwc.com/pig/pig-farm-controller/internal/domain/notify"
"git.huangwc.com/pig/pig-farm-controller/internal/domain/pig"
@@ -94,28 +93,28 @@ type Repositories struct {
func initRepositories(ctx context.Context, db *gorm.DB) *Repositories {
baseCtx := context.Background()
return &Repositories{
userRepo: repository.NewGormUserRepository(db, logs.AddCompName(baseCtx, "UserRepo")),
deviceRepo: repository.NewGormDeviceRepository(db, logs.AddCompName(baseCtx, "DeviceRepo")),
areaControllerRepo: repository.NewGormAreaControllerRepository(db, logs.AddCompName(baseCtx, "AreaControllerRepo")),
deviceTemplateRepo: repository.NewGormDeviceTemplateRepository(db, logs.AddCompName(baseCtx, "DeviceTemplateRepo")),
planRepo: repository.NewGormPlanRepository(db, logs.AddCompName(baseCtx, "PlanRepo")),
pendingTaskRepo: repository.NewGormPendingTaskRepository(db, logs.AddCompName(baseCtx, "PendingTaskRepo")),
executionLogRepo: repository.NewGormExecutionLogRepository(db, logs.AddCompName(baseCtx, "ExecutionLogRepo")),
sensorDataRepo: repository.NewGormSensorDataRepository(db, logs.AddCompName(baseCtx, "SensorDataRepo")),
deviceCommandLogRepo: repository.NewGormDeviceCommandLogRepository(db, logs.AddCompName(baseCtx, "DeviceCommandLogRepo")),
pendingCollectionRepo: repository.NewGormPendingCollectionRepository(db, logs.AddCompName(baseCtx, "PendingCollectionRepo")),
userActionLogRepo: repository.NewGormUserActionLogRepository(db, logs.AddCompName(baseCtx, "UserActionLogRepo")),
pigBatchRepo: repository.NewGormPigBatchRepository(db, logs.AddCompName(baseCtx, "PigBatchRepo")),
pigBatchLogRepo: repository.NewGormPigBatchLogRepository(db, logs.AddCompName(baseCtx, "PigBatchLogRepo")),
pigFarmRepo: repository.NewGormPigFarmRepository(db, logs.AddCompName(baseCtx, "PigFarmRepo")),
pigPenRepo: repository.NewGormPigPenRepository(db, logs.AddCompName(baseCtx, "PigPenRepo")),
pigTransferLogRepo: repository.NewGormPigTransferLogRepository(db, logs.AddCompName(baseCtx, "PigTransferLogRepo")),
pigTradeRepo: repository.NewGormPigTradeRepository(db, logs.AddCompName(baseCtx, "PigTradeRepo")),
pigSickPigLogRepo: repository.NewGormPigSickLogRepository(db, logs.AddCompName(baseCtx, "PigSickPigLogRepo")),
medicationLogRepo: repository.NewGormMedicationLogRepository(db, logs.AddCompName(baseCtx, "MedicationLogRepo")),
rawMaterialRepo: repository.NewGormRawMaterialRepository(db, logs.AddCompName(baseCtx, "RawMaterialRepo")),
notificationRepo: repository.NewGormNotificationRepository(db, logs.AddCompName(baseCtx, "NotificationRepo")),
unitOfWork: repository.NewGormUnitOfWork(db, logs.AddCompName(baseCtx, "UnitOfWork")),
userRepo: repository.NewGormUserRepository(logs.AddCompName(baseCtx, "UserRepo"), db),
deviceRepo: repository.NewGormDeviceRepository(logs.AddCompName(baseCtx, "DeviceRepo"), db),
areaControllerRepo: repository.NewGormAreaControllerRepository(logs.AddCompName(baseCtx, "AreaControllerRepo"), db),
deviceTemplateRepo: repository.NewGormDeviceTemplateRepository(logs.AddCompName(baseCtx, "DeviceTemplateRepo"), db),
planRepo: repository.NewGormPlanRepository(logs.AddCompName(baseCtx, "PlanRepo"), db),
pendingTaskRepo: repository.NewGormPendingTaskRepository(logs.AddCompName(baseCtx, "PendingTaskRepo"), db),
executionLogRepo: repository.NewGormExecutionLogRepository(logs.AddCompName(baseCtx, "ExecutionLogRepo"), db),
sensorDataRepo: repository.NewGormSensorDataRepository(logs.AddCompName(baseCtx, "SensorDataRepo"), db),
deviceCommandLogRepo: repository.NewGormDeviceCommandLogRepository(logs.AddCompName(baseCtx, "DeviceCommandLogRepo"), db),
pendingCollectionRepo: repository.NewGormPendingCollectionRepository(logs.AddCompName(baseCtx, "PendingCollectionRepo"), db),
userActionLogRepo: repository.NewGormUserActionLogRepository(logs.AddCompName(baseCtx, "UserActionLogRepo"), db),
pigBatchRepo: repository.NewGormPigBatchRepository(logs.AddCompName(baseCtx, "PigBatchRepo"), db),
pigBatchLogRepo: repository.NewGormPigBatchLogRepository(logs.AddCompName(baseCtx, "PigBatchLogRepo"), db),
pigFarmRepo: repository.NewGormPigFarmRepository(logs.AddCompName(baseCtx, "PigFarmRepo"), db),
pigPenRepo: repository.NewGormPigPenRepository(logs.AddCompName(baseCtx, "PigPenRepo"), db),
pigTransferLogRepo: repository.NewGormPigTransferLogRepository(logs.AddCompName(baseCtx, "PigTransferLogRepo"), db),
pigTradeRepo: repository.NewGormPigTradeRepository(logs.AddCompName(baseCtx, "PigTradeRepo"), db),
pigSickPigLogRepo: repository.NewGormPigSickLogRepository(logs.AddCompName(baseCtx, "PigSickPigLogRepo"), db),
medicationLogRepo: repository.NewGormMedicationLogRepository(logs.AddCompName(baseCtx, "MedicationLogRepo"), db),
rawMaterialRepo: repository.NewGormRawMaterialRepository(logs.AddCompName(baseCtx, "RawMaterialRepo"), db),
notificationRepo: repository.NewGormNotificationRepository(logs.AddCompName(baseCtx, "NotificationRepo"), db),
unitOfWork: repository.NewGormUnitOfWork(logs.AddCompName(baseCtx, "UnitOfWork"), db),
}
}
@@ -134,22 +133,21 @@ type DomainServices struct {
// initDomainServices 初始化所有的领域服务。
func initDomainServices(ctx context.Context, cfg *config.Config, infra *Infrastructure) *DomainServices {
logger := logs.GetLogger(ctx)
baseCtx := context.Background()
// 猪群管理相关
pigPenTransferManager := pig.NewPigPenTransferManager(infra.repos.pigPenRepo, infra.repos.pigTransferLogRepo, infra.repos.pigBatchRepo)
pigTradeManager := pig.NewPigTradeManager(infra.repos.pigTradeRepo)
pigSickManager := pig.NewSickPigManager(infra.repos.pigSickPigLogRepo, infra.repos.medicationLogRepo)
pigBatchDomain := pig.NewPigBatchService(infra.repos.pigBatchRepo, infra.repos.pigBatchLogRepo, infra.repos.unitOfWork,
pigPenTransferManager := pig.NewPigPenTransferManager(logs.AddCompName(baseCtx, "PigPenTransferManager"), infra.repos.pigPenRepo, infra.repos.pigTransferLogRepo, infra.repos.pigBatchRepo)
pigTradeManager := pig.NewPigTradeManager(logs.AddCompName(baseCtx, "PigTradeManager"), infra.repos.pigTradeRepo)
pigSickManager := pig.NewSickPigManager(logs.AddCompName(baseCtx, "PigSickManager"), infra.repos.pigSickPigLogRepo, infra.repos.medicationLogRepo)
pigBatchDomain := pig.NewPigBatchService(logs.AddCompName(baseCtx, "PigBatchDomain")), infra.repos.pigBatchRepo, infra.repos.pigBatchLogRepo, infra.repos.unitOfWork,
pigPenTransferManager, pigTradeManager, pigSickManager)
// 通用设备服务
generalDeviceService := device.NewGeneralDeviceService(
logs.AddCompName(baseCtx, "GeneralDeviceService"),
infra.repos.deviceRepo,
infra.repos.deviceCommandLogRepo,
infra.repos.pendingCollectionRepo,
logs.AddCompName(baseCtx, "GeneralDeviceService"),
infra.lora.comm,
)
@@ -157,10 +155,11 @@ func initDomainServices(ctx context.Context, cfg *config.Config, infra *Infrastr
taskFactory := task.NewTaskFactory(logs.AddCompName(baseCtx, "TaskFactory"), infra.repos.sensorDataRepo, infra.repos.deviceRepo, generalDeviceService)
// 计划任务管理器
analysisPlanTaskManager := plan.NewAnalysisPlanTaskManager(infra.repos.planRepo, infra.repos.pendingTaskRepo, infra.repos.executionLogRepo, logs.AddCompName(baseCtx, "AnalysisPlanTaskManager"))
analysisPlanTaskManager := plan.NewAnalysisPlanTaskManager(logs.AddCompName(baseCtx, "AnalysisPlanTaskManager"), infra.repos.planRepo, infra.repos.pendingTaskRepo, infra.repos.executionLogRepo)
// 任务执行器
planExecutionManager := plan.NewPlanExecutionManager(
logs.AddCompName(baseCtx, "PlanExecutionManager"),
infra.repos.pendingTaskRepo,
infra.repos.executionLogRepo,
infra.repos.deviceRepo,
@@ -168,7 +167,6 @@ func initDomainServices(ctx context.Context, cfg *config.Config, infra *Infrastr
infra.repos.planRepo,
analysisPlanTaskManager,
taskFactory,
logs.AddCompName(baseCtx, "PlanExecutionManager"),
generalDeviceService,
time.Duration(cfg.Task.Interval)*time.Second,
cfg.Task.NumWorkers,
@@ -176,13 +174,14 @@ func initDomainServices(ctx context.Context, cfg *config.Config, infra *Infrastr
// 计划管理器
planService := plan.NewPlanService(
logs.AddCompName(baseCtx, "PlanService"),
planExecutionManager,
analysisPlanTaskManager,
infra.repos.planRepo,
infra.repos.deviceRepo,
infra.repos.unitOfWork,
taskFactory,
logs.AddCompName(baseCtx, "PlanService"))
)
return &DomainServices{
pigPenTransferManager: pigPenTransferManager,
@@ -205,15 +204,16 @@ type AppServices struct {
deviceService service.DeviceService
planService service.PlanService
userService service.UserService
auditService audit.Service
auditService service.AuditService
}
// initAppServices 初始化所有的应用服务。
func initAppServices(ctx context.Context, infra *Infrastructure, domainServices *DomainServices) *AppServices {
baseCtx := context.Background()
pigFarmService := service.NewPigFarmService(infra.repos.pigFarmRepo, infra.repos.pigPenRepo, infra.repos.pigBatchRepo, domainServices.pigBatchDomain, infra.repos.unitOfWork, logs.AddCompName(baseCtx, "PigFarmService"))
pigBatchService := service.NewPigBatchService(domainServices.pigBatchDomain, logs.AddCompName(baseCtx, "PigBatchService"))
pigFarmService := service.NewPigFarmService(logs.AddCompName(baseCtx, "PigFarmService"), infra.repos.pigFarmRepo, infra.repos.pigPenRepo, infra.repos.pigBatchRepo, domainServices.pigBatchDomain, infra.repos.unitOfWork)
pigBatchService := service.NewPigBatchService(logs.AddCompName(baseCtx, "PigBatchService"), domainServices.pigBatchDomain)
monitorService := service.NewMonitorService(
logs.AddCompName(baseCtx, "MonitorService"),
infra.repos.sensorDataRepo,
infra.repos.deviceCommandLogRepo,
infra.repos.executionLogRepo,
@@ -230,14 +230,15 @@ func initAppServices(ctx context.Context, infra *Infrastructure, domainServices
infra.repos.notificationRepo,
)
deviceService := service.NewDeviceService(
logs.AddCompName(baseCtx, "DeviceService"),
infra.repos.deviceRepo,
infra.repos.areaControllerRepo,
infra.repos.deviceTemplateRepo,
domainServices.generalDeviceService,
)
auditService := audit.NewService(infra.repos.userActionLogRepo, logs.AddCompName(baseCtx, "AuditService"))
auditService := service.NewAuditService(logs.AddCompName(baseCtx, "AuditService"), infra.repos.userActionLogRepo)
planService := service.NewPlanService(logs.AddCompName(baseCtx, "AppPlanService"), domainServices.planService)
userService := service.NewUserService(infra.repos.userRepo, infra.tokenService, infra.notifyService, logs.AddCompName(baseCtx, "UserService"))
userService := service.NewUserService(logs.AddCompName(baseCtx, "UserService"), infra.repos.userRepo, infra.tokenService, infra.notifyService)
return &AppServices{
pigFarmService: pigFarmService,
@@ -386,7 +387,7 @@ func initStorage(ctx context.Context, cfg config.DatabaseConfig) (database.Stora
}
// 执行数据库迁移
if err := storage.Migrate(models.GetAllModels()...); err != nil {
if err := storage.Migrate(ctx, models.GetAllModels()...); err != nil {
return nil, fmt.Errorf("数据库迁移失败: %w", err)
}