214 lines
7.5 KiB
Go
214 lines
7.5 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
|
|
"git.huangwc.com/pig/pig-farm-controller/internal/domain/plan"
|
|
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
|
|
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
|
|
)
|
|
|
|
// PlanService 定义了计划相关的应用服务接口
|
|
type PlanService interface {
|
|
// CreatePlan 创建一个新的计划
|
|
CreatePlan(ctx context.Context, req *dto.CreatePlanRequest) (*dto.PlanResponse, error)
|
|
// GetPlanByID 根据ID获取计划详情
|
|
GetPlanByID(ctx context.Context, id uint) (*dto.PlanResponse, error)
|
|
// ListPlans 获取计划列表,支持过滤和分页
|
|
ListPlans(ctx context.Context, query *dto.ListPlansQuery) (*dto.ListPlansResponse, error)
|
|
// UpdatePlan 更新计划
|
|
UpdatePlan(ctx context.Context, id uint, req *dto.UpdatePlanRequest) (*dto.PlanResponse, error)
|
|
// DeletePlan 删除计划(软删除)
|
|
DeletePlan(ctx context.Context, id uint) error
|
|
// StartPlan 启动计划
|
|
StartPlan(ctx context.Context, id uint) error
|
|
// StopPlan 停止计划
|
|
StopPlan(ctx context.Context, id uint) error
|
|
}
|
|
|
|
// planService 是 PlanService 接口的实现
|
|
type planService struct {
|
|
ctx context.Context
|
|
domainPlanService plan.Service
|
|
}
|
|
|
|
// NewPlanService 创建一个新的 PlanService 实例
|
|
func NewPlanService(
|
|
ctx context.Context,
|
|
domainPlanService plan.Service,
|
|
) PlanService {
|
|
return &planService{
|
|
ctx: ctx,
|
|
domainPlanService: domainPlanService,
|
|
}
|
|
}
|
|
|
|
// CreatePlan 创建一个新的计划
|
|
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 {
|
|
logger.Errorf("%s: 计划数据校验失败: %v", actionType, err)
|
|
return nil, err
|
|
}
|
|
|
|
// 调用领域服务创建计划
|
|
createdPlan, err := s.domainPlanService.CreatePlan(serviceCtx, planToCreate)
|
|
if err != nil {
|
|
logger.Errorf("%s: 领域服务创建计划失败: %v", actionType, err)
|
|
return nil, err // 直接返回领域层错误
|
|
}
|
|
|
|
// 将领域实体转换为响应 DTO
|
|
resp, err := dto.NewPlanToResponse(createdPlan)
|
|
if err != nil {
|
|
logger.Errorf("%s: 序列化响应失败: %v, Plan: %+v", actionType, err, createdPlan)
|
|
return nil, errors.New("计划创建成功,但响应生成失败")
|
|
}
|
|
|
|
logger.Infof("%s: 计划创建成功, ID: %d", actionType, createdPlan.ID)
|
|
return resp, nil
|
|
}
|
|
|
|
// GetPlanByID 根据ID获取计划详情
|
|
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(serviceCtx, id)
|
|
if err != nil {
|
|
logger.Errorf("%s: 领域服务获取计划详情失败: %v, ID: %d", actionType, err, id)
|
|
return nil, err // 直接返回领域层错误
|
|
}
|
|
|
|
// 将领域实体转换为响应 DTO
|
|
resp, err := dto.NewPlanToResponse(plan)
|
|
if err != nil {
|
|
logger.Errorf("%s: 序列化响应失败: %v, Plan: %+v", actionType, err, plan)
|
|
return nil, errors.New("获取计划详情失败: 内部数据格式错误")
|
|
}
|
|
|
|
logger.Infof("%s: 获取计划详情成功, ID: %d", actionType, id)
|
|
return resp, nil
|
|
}
|
|
|
|
// ListPlans 获取计划列表,支持过滤和分页
|
|
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(serviceCtx, opts, query.Page, query.PageSize)
|
|
if err != nil {
|
|
logger.Errorf("%s: 领域服务获取计划列表失败: %v", actionType, err)
|
|
return nil, err // 直接返回领域层错误
|
|
}
|
|
|
|
// 将领域实体列表转换为响应 DTO 列表
|
|
planResponses := make([]dto.PlanResponse, 0, len(plans))
|
|
for _, p := range plans {
|
|
resp, err := dto.NewPlanToResponse(&p)
|
|
if err != nil {
|
|
logger.Errorf("%s: 序列化单个计划响应失败: %v, Plan: %+v", actionType, err, p)
|
|
// 这里选择跳过有问题的计划,并记录错误,而不是中断整个列表的返回
|
|
continue
|
|
}
|
|
planResponses = append(planResponses, *resp)
|
|
}
|
|
|
|
resp := &dto.ListPlansResponse{
|
|
Plans: planResponses,
|
|
Total: total,
|
|
}
|
|
logger.Infof("%s: 获取计划列表成功, 数量: %d", actionType, len(planResponses))
|
|
return resp, nil
|
|
}
|
|
|
|
// UpdatePlan 更新计划
|
|
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 {
|
|
logger.Errorf("%s: 计划数据校验失败: %v", actionType, err)
|
|
return nil, err
|
|
}
|
|
planToUpdate.ID = id // 确保ID被设置
|
|
|
|
// 调用领域服务更新计划
|
|
updatedPlan, err := s.domainPlanService.UpdatePlan(serviceCtx, planToUpdate)
|
|
if err != nil {
|
|
logger.Errorf("%s: 领域服务更新计划失败: %v, ID: %d", actionType, err, id)
|
|
return nil, err // 直接返回领域层错误
|
|
}
|
|
|
|
// 将领域实体转换为响应 DTO
|
|
resp, err := dto.NewPlanToResponse(updatedPlan)
|
|
if err != nil {
|
|
logger.Errorf("%s: 序列化响应失败: %v, Updated Plan: %+v", actionType, err, updatedPlan)
|
|
return nil, errors.New("计划更新成功,但响应生成失败")
|
|
}
|
|
|
|
logger.Infof("%s: 计划更新成功, ID: %d", actionType, updatedPlan.ID)
|
|
return resp, nil
|
|
}
|
|
|
|
// DeletePlan 删除计划(软删除)
|
|
func (s *planService) DeletePlan(ctx context.Context, id uint) error {
|
|
serviceCtx, logger := logs.Trace(ctx, s.ctx, "DeletePlan")
|
|
const actionType = "应用服务层:删除计划"
|
|
|
|
// 调用领域服务删除计划
|
|
err := s.domainPlanService.DeletePlan(serviceCtx, id)
|
|
if err != nil {
|
|
logger.Errorf("%s: 领域服务删除计划失败: %v, ID: %d", actionType, err, id)
|
|
return err // 直接返回领域层错误
|
|
}
|
|
|
|
logger.Infof("%s: 计划删除成功, ID: %d", actionType, id)
|
|
return nil
|
|
}
|
|
|
|
// StartPlan 启动计划
|
|
func (s *planService) StartPlan(ctx context.Context, id uint) error {
|
|
serviceCtx, logger := logs.Trace(ctx, s.ctx, "StartPlan")
|
|
const actionType = "应用服务层:启动计划"
|
|
|
|
// 调用领域服务启动计划
|
|
err := s.domainPlanService.StartPlan(serviceCtx, id)
|
|
if err != nil {
|
|
logger.Errorf("%s: 领域服务启动计划失败: %v, ID: %d", actionType, err, id)
|
|
return err // 直接返回领域层错误
|
|
}
|
|
|
|
logger.Infof("%s: 计划已成功启动, ID: %d", actionType, id)
|
|
return nil
|
|
}
|
|
|
|
// StopPlan 停止计划
|
|
func (s *planService) StopPlan(ctx context.Context, id uint) error {
|
|
serviceCtx, logger := logs.Trace(ctx, s.ctx, "StopPlan")
|
|
const actionType = "应用服务层:停止计划"
|
|
|
|
// 调用领域服务停止计划
|
|
err := s.domainPlanService.StopPlan(serviceCtx, id)
|
|
if err != nil {
|
|
logger.Errorf("%s: 领域服务停止计划失败: %v, ID: %d", actionType, err, id)
|
|
return err // 直接返回领域层错误
|
|
}
|
|
|
|
logger.Infof("%s: 计划已成功停止, ID: %d", actionType, id)
|
|
return nil
|
|
}
|