移动文件位置
This commit is contained in:
@@ -1,226 +0,0 @@
|
|||||||
package plan
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PlanToResponse 将Plan模型转换为PlanResponse
|
|
||||||
func PlanToResponse(plan *models.Plan) (*PlanResponse, error) {
|
|
||||||
if plan == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
response := &PlanResponse{
|
|
||||||
ID: plan.ID,
|
|
||||||
Name: plan.Name,
|
|
||||||
Description: plan.Description,
|
|
||||||
ExecutionType: plan.ExecutionType,
|
|
||||||
Status: plan.Status,
|
|
||||||
ExecuteNum: plan.ExecuteNum,
|
|
||||||
ExecuteCount: plan.ExecuteCount,
|
|
||||||
CronExpression: plan.CronExpression,
|
|
||||||
ContentType: plan.ContentType,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换子计划
|
|
||||||
if plan.ContentType == models.PlanContentTypeSubPlans {
|
|
||||||
response.SubPlans = make([]SubPlanResponse, len(plan.SubPlans))
|
|
||||||
for i, subPlan := range plan.SubPlans {
|
|
||||||
subPlanResp, err := SubPlanToResponse(&subPlan)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
response.SubPlans[i] = subPlanResp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换任务
|
|
||||||
if plan.ContentType == models.PlanContentTypeTasks {
|
|
||||||
response.Tasks = make([]TaskResponse, len(plan.Tasks))
|
|
||||||
for i, task := range plan.Tasks {
|
|
||||||
taskResp, err := TaskToResponse(&task)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
response.Tasks[i] = taskResp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PlanFromCreateRequest 将CreatePlanRequest转换为Plan模型,并进行业务规则验证
|
|
||||||
func PlanFromCreateRequest(req *CreatePlanRequest) (*models.Plan, error) {
|
|
||||||
if req == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
plan := &models.Plan{
|
|
||||||
Name: req.Name,
|
|
||||||
Description: req.Description,
|
|
||||||
ExecutionType: req.ExecutionType,
|
|
||||||
ExecuteNum: req.ExecuteNum,
|
|
||||||
CronExpression: req.CronExpression,
|
|
||||||
// ContentType 在控制器中设置,此处不再处理
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理子计划 (通过ID引用)
|
|
||||||
if req.SubPlanIDs != nil {
|
|
||||||
subPlanSlice := req.SubPlanIDs
|
|
||||||
plan.SubPlans = make([]models.SubPlan, len(subPlanSlice))
|
|
||||||
for i, childPlanID := range subPlanSlice {
|
|
||||||
plan.SubPlans[i] = models.SubPlan{
|
|
||||||
ChildPlanID: childPlanID,
|
|
||||||
ExecutionOrder: i, // 默认执行顺序, ReorderSteps会再次确认
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理任务
|
|
||||||
if req.Tasks != nil {
|
|
||||||
taskSlice := req.Tasks
|
|
||||||
plan.Tasks = make([]models.Task, len(taskSlice))
|
|
||||||
for i, taskReq := range taskSlice {
|
|
||||||
task, err := TaskFromRequest(&taskReq)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
plan.Tasks[i] = task
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. 首先,执行重复性验证
|
|
||||||
if err := plan.ValidateExecutionOrder(); err != nil {
|
|
||||||
// 如果检测到重复,立即返回错误
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 然后,调用方法来修复顺序断层
|
|
||||||
plan.ReorderSteps()
|
|
||||||
|
|
||||||
return plan, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PlanFromUpdateRequest 将UpdatePlanRequest转换为Plan模型,并进行业务规则验证
|
|
||||||
func PlanFromUpdateRequest(req *UpdatePlanRequest) (*models.Plan, error) {
|
|
||||||
if req == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
plan := &models.Plan{
|
|
||||||
Name: req.Name,
|
|
||||||
Description: req.Description,
|
|
||||||
ExecutionType: req.ExecutionType,
|
|
||||||
ExecuteNum: req.ExecuteNum,
|
|
||||||
CronExpression: req.CronExpression,
|
|
||||||
// ContentType 在控制器中设置,此处不再处理
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理子计划 (通过ID引用)
|
|
||||||
if req.SubPlanIDs != nil {
|
|
||||||
subPlanSlice := req.SubPlanIDs
|
|
||||||
plan.SubPlans = make([]models.SubPlan, len(subPlanSlice))
|
|
||||||
for i, childPlanID := range subPlanSlice {
|
|
||||||
plan.SubPlans[i] = models.SubPlan{
|
|
||||||
ChildPlanID: childPlanID,
|
|
||||||
ExecutionOrder: i, // 默认执行顺序, ReorderSteps会再次确认
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理任务
|
|
||||||
if req.Tasks != nil {
|
|
||||||
taskSlice := req.Tasks
|
|
||||||
plan.Tasks = make([]models.Task, len(taskSlice))
|
|
||||||
for i, taskReq := range taskSlice {
|
|
||||||
task, err := TaskFromRequest(&taskReq)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
plan.Tasks[i] = task
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. 首先,执行重复性验证
|
|
||||||
if err := plan.ValidateExecutionOrder(); err != nil {
|
|
||||||
// 如果检测到重复,立即返回错误
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 然后,调用方法来修复顺序断层
|
|
||||||
plan.ReorderSteps()
|
|
||||||
|
|
||||||
return plan, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SubPlanToResponse 将SubPlan模型转换为SubPlanResponse
|
|
||||||
func SubPlanToResponse(subPlan *models.SubPlan) (SubPlanResponse, error) {
|
|
||||||
if subPlan == nil {
|
|
||||||
return SubPlanResponse{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
response := SubPlanResponse{
|
|
||||||
ID: subPlan.ID,
|
|
||||||
ParentPlanID: subPlan.ParentPlanID,
|
|
||||||
ChildPlanID: subPlan.ChildPlanID,
|
|
||||||
ExecutionOrder: subPlan.ExecutionOrder,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果有完整的子计划数据,也进行转换
|
|
||||||
if subPlan.ChildPlan != nil {
|
|
||||||
childPlanResp, err := PlanToResponse(subPlan.ChildPlan)
|
|
||||||
if err != nil {
|
|
||||||
return SubPlanResponse{}, err
|
|
||||||
}
|
|
||||||
response.ChildPlan = childPlanResp
|
|
||||||
}
|
|
||||||
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TaskToResponse 将Task模型转换为TaskResponse
|
|
||||||
func TaskToResponse(task *models.Task) (TaskResponse, error) {
|
|
||||||
if task == nil {
|
|
||||||
return TaskResponse{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var params map[string]interface{}
|
|
||||||
if len(task.Parameters) > 0 && string(task.Parameters) != "null" {
|
|
||||||
if err := task.ParseParameters(¶ms); err != nil {
|
|
||||||
return TaskResponse{}, fmt.Errorf("parsing task parameters failed (ID: %d): %w", task.ID, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TaskResponse{
|
|
||||||
ID: task.ID,
|
|
||||||
PlanID: task.PlanID,
|
|
||||||
Name: task.Name,
|
|
||||||
Description: task.Description,
|
|
||||||
ExecutionOrder: task.ExecutionOrder,
|
|
||||||
Type: task.Type,
|
|
||||||
Parameters: params,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TaskFromRequest 将TaskRequest转换为Task模型
|
|
||||||
func TaskFromRequest(req *TaskRequest) (models.Task, error) {
|
|
||||||
if req == nil {
|
|
||||||
return models.Task{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
paramsJSON, err := json.Marshal(req.Parameters)
|
|
||||||
if err != nil {
|
|
||||||
return models.Task{}, fmt.Errorf("serializing task parameters failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.Task{
|
|
||||||
Name: req.Name,
|
|
||||||
Description: req.Description,
|
|
||||||
ExecutionOrder: req.ExecutionOrder,
|
|
||||||
Type: req.Type,
|
|
||||||
Parameters: paramsJSON,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
@@ -1,459 +0,0 @@
|
|||||||
package plan_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
|
|
||||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/plan"
|
|
||||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"gorm.io/datatypes"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPlanToResponse(t *testing.T) {
|
|
||||||
t.Run("nil plan", func(t *testing.T) {
|
|
||||||
response := plan.PlanToResponse(nil)
|
|
||||||
assert.Nil(t, response)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("basic plan without associations", func(t *testing.T) {
|
|
||||||
planModel := &models.Plan{
|
|
||||||
Model: gorm.Model{ID: 1},
|
|
||||||
Name: "Test Plan",
|
|
||||||
Description: "A test plan",
|
|
||||||
ExecutionType: models.PlanExecutionTypeAutomatic,
|
|
||||||
CronExpression: "0 0 * * *",
|
|
||||||
ContentType: models.PlanContentTypeTasks,
|
|
||||||
}
|
|
||||||
|
|
||||||
response := plan.PlanToResponse(planModel)
|
|
||||||
assert.NotNil(t, response)
|
|
||||||
assert.Equal(t, uint(1), response.ID)
|
|
||||||
assert.Equal(t, "Test Plan", response.Name)
|
|
||||||
assert.Equal(t, "A test plan", response.Description)
|
|
||||||
assert.Equal(t, models.PlanExecutionTypeAutomatic, response.ExecutionType)
|
|
||||||
assert.Equal(t, "0 0 * * *", response.CronExpression)
|
|
||||||
assert.Equal(t, models.PlanContentTypeTasks, response.ContentType)
|
|
||||||
assert.Empty(t, response.SubPlans)
|
|
||||||
assert.Empty(t, response.Tasks)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("plan with sub plans", func(t *testing.T) {
|
|
||||||
childPlan := &models.Plan{
|
|
||||||
Model: gorm.Model{ID: 2},
|
|
||||||
Name: "Child Plan",
|
|
||||||
ContentType: models.PlanContentTypeTasks,
|
|
||||||
}
|
|
||||||
|
|
||||||
planModel := &models.Plan{
|
|
||||||
Model: gorm.Model{ID: 1},
|
|
||||||
Name: "Parent Plan",
|
|
||||||
ContentType: models.PlanContentTypeSubPlans,
|
|
||||||
SubPlans: []models.SubPlan{
|
|
||||||
{
|
|
||||||
Model: gorm.Model{ID: 10},
|
|
||||||
ParentPlanID: 1,
|
|
||||||
ChildPlanID: 2,
|
|
||||||
ExecutionOrder: 1,
|
|
||||||
ChildPlan: childPlan,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
response := plan.PlanToResponse(planModel)
|
|
||||||
assert.NotNil(t, response)
|
|
||||||
assert.Equal(t, uint(1), response.ID)
|
|
||||||
assert.Equal(t, "Parent Plan", response.Name)
|
|
||||||
assert.Equal(t, models.PlanContentTypeSubPlans, response.ContentType)
|
|
||||||
assert.Len(t, response.SubPlans, 1)
|
|
||||||
assert.Empty(t, response.Tasks)
|
|
||||||
|
|
||||||
subPlanResp := response.SubPlans[0]
|
|
||||||
assert.Equal(t, uint(10), subPlanResp.ID)
|
|
||||||
assert.Equal(t, uint(1), subPlanResp.ParentPlanID)
|
|
||||||
assert.Equal(t, uint(2), subPlanResp.ChildPlanID)
|
|
||||||
assert.Equal(t, 1, subPlanResp.ExecutionOrder)
|
|
||||||
assert.NotNil(t, subPlanResp.ChildPlan)
|
|
||||||
assert.Equal(t, "Child Plan", subPlanResp.ChildPlan.Name)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("plan with tasks", func(t *testing.T) {
|
|
||||||
params := datatypes.JSON([]byte(`{"device_id": 1, "value": 25}`))
|
|
||||||
|
|
||||||
planModel := &models.Plan{
|
|
||||||
Model: gorm.Model{ID: 1},
|
|
||||||
Name: "Task Plan",
|
|
||||||
ContentType: models.PlanContentTypeTasks,
|
|
||||||
Tasks: []models.Task{
|
|
||||||
{
|
|
||||||
Model: gorm.Model{ID: 10},
|
|
||||||
PlanID: 1,
|
|
||||||
Name: "Task 1",
|
|
||||||
Description: "First task",
|
|
||||||
ExecutionOrder: 1,
|
|
||||||
Type: models.TaskTypeWaiting,
|
|
||||||
Parameters: params,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
response := plan.PlanToResponse(planModel)
|
|
||||||
assert.NotNil(t, response)
|
|
||||||
assert.Equal(t, uint(1), response.ID)
|
|
||||||
assert.Equal(t, "Task Plan", response.Name)
|
|
||||||
assert.Equal(t, models.PlanContentTypeTasks, response.ContentType)
|
|
||||||
assert.Len(t, response.Tasks, 1)
|
|
||||||
assert.Empty(t, response.SubPlans)
|
|
||||||
|
|
||||||
taskResp := response.Tasks[0]
|
|
||||||
assert.Equal(t, uint(10), taskResp.ID)
|
|
||||||
assert.Equal(t, uint(1), taskResp.PlanID)
|
|
||||||
assert.Equal(t, "Task 1", taskResp.Name)
|
|
||||||
assert.Equal(t, "First task", taskResp.Description)
|
|
||||||
assert.Equal(t, 1, taskResp.ExecutionOrder)
|
|
||||||
assert.Equal(t, models.TaskTypeWaiting, taskResp.Type)
|
|
||||||
assert.Equal(t, controller.Properties(params), taskResp.Parameters)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPlanFromCreateRequest(t *testing.T) {
|
|
||||||
t.Run("nil request", func(t *testing.T) {
|
|
||||||
planModel, err := plan.PlanFromCreateRequest(nil)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Nil(t, planModel)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("basic plan without associations", func(t *testing.T) {
|
|
||||||
req := &plan.CreatePlanRequest{
|
|
||||||
Name: "Test Plan",
|
|
||||||
Description: "A test plan",
|
|
||||||
ExecutionType: models.PlanExecutionTypeAutomatic,
|
|
||||||
CronExpression: "0 0 * * *",
|
|
||||||
ContentType: models.PlanContentTypeTasks,
|
|
||||||
}
|
|
||||||
|
|
||||||
planModel, err := plan.PlanFromCreateRequest(req)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotNil(t, planModel)
|
|
||||||
assert.Equal(t, "Test Plan", planModel.Name)
|
|
||||||
assert.Equal(t, "A test plan", planModel.Description)
|
|
||||||
assert.Equal(t, models.PlanExecutionTypeAutomatic, planModel.ExecutionType)
|
|
||||||
assert.Equal(t, "0 0 * * *", planModel.CronExpression)
|
|
||||||
assert.Equal(t, models.PlanContentTypeTasks, planModel.ContentType)
|
|
||||||
assert.Empty(t, planModel.SubPlans)
|
|
||||||
assert.Empty(t, planModel.Tasks)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("plan with sub plan IDs", func(t *testing.T) {
|
|
||||||
req := &plan.CreatePlanRequest{
|
|
||||||
Name: "Parent Plan",
|
|
||||||
ContentType: models.PlanContentTypeSubPlans,
|
|
||||||
SubPlanIDs: []uint{2, 3},
|
|
||||||
}
|
|
||||||
|
|
||||||
planModel, err := plan.PlanFromCreateRequest(req)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotNil(t, planModel)
|
|
||||||
assert.Equal(t, "Parent Plan", planModel.Name)
|
|
||||||
assert.Equal(t, models.PlanContentTypeSubPlans, planModel.ContentType)
|
|
||||||
assert.Len(t, planModel.SubPlans, 2)
|
|
||||||
assert.Empty(t, planModel.Tasks)
|
|
||||||
|
|
||||||
assert.Equal(t, uint(2), planModel.SubPlans[0].ChildPlanID)
|
|
||||||
assert.Equal(t, 1, planModel.SubPlans[0].ExecutionOrder)
|
|
||||||
assert.Equal(t, uint(3), planModel.SubPlans[1].ChildPlanID)
|
|
||||||
assert.Equal(t, 2, planModel.SubPlans[1].ExecutionOrder)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("plan with tasks", func(t *testing.T) {
|
|
||||||
params := controller.Properties([]byte(`{"device_id": 1, "value": 25}`))
|
|
||||||
|
|
||||||
req := &plan.CreatePlanRequest{
|
|
||||||
Name: "Task Plan",
|
|
||||||
ContentType: models.PlanContentTypeTasks,
|
|
||||||
Tasks: []plan.TaskRequest{
|
|
||||||
{
|
|
||||||
Name: "Task 1",
|
|
||||||
Description: "First task",
|
|
||||||
ExecutionOrder: 1,
|
|
||||||
Type: models.TaskTypeWaiting,
|
|
||||||
Parameters: params,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
planModel, err := plan.PlanFromCreateRequest(req)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotNil(t, planModel)
|
|
||||||
assert.Equal(t, "Task Plan", planModel.Name)
|
|
||||||
assert.Equal(t, models.PlanContentTypeTasks, planModel.ContentType)
|
|
||||||
assert.Len(t, planModel.Tasks, 1)
|
|
||||||
assert.Empty(t, planModel.SubPlans)
|
|
||||||
|
|
||||||
task := planModel.Tasks[0]
|
|
||||||
assert.Equal(t, "Task 1", task.Name)
|
|
||||||
assert.Equal(t, "First task", task.Description)
|
|
||||||
assert.Equal(t, 1, task.ExecutionOrder)
|
|
||||||
assert.Equal(t, models.TaskTypeWaiting, task.Type)
|
|
||||||
assert.Equal(t, datatypes.JSON(params), task.Parameters)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("plan with tasks with gapped execution order", func(t *testing.T) {
|
|
||||||
req := &plan.CreatePlanRequest{
|
|
||||||
Name: "Task Plan with Gaps",
|
|
||||||
ContentType: models.PlanContentTypeTasks,
|
|
||||||
Tasks: []plan.TaskRequest{
|
|
||||||
{Name: "Task 3", ExecutionOrder: 5},
|
|
||||||
{Name: "Task 1", ExecutionOrder: 2},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
planModel, err := plan.PlanFromCreateRequest(req)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotNil(t, planModel)
|
|
||||||
assert.Len(t, planModel.Tasks, 2)
|
|
||||||
|
|
||||||
// After ReorderSteps, tasks are sorted by their original ExecutionOrder and then re-numbered.
|
|
||||||
assert.Equal(t, "Task 1", planModel.Tasks[0].Name)
|
|
||||||
assert.Equal(t, 1, planModel.Tasks[0].ExecutionOrder)
|
|
||||||
assert.Equal(t, "Task 3", planModel.Tasks[1].Name)
|
|
||||||
assert.Equal(t, 2, planModel.Tasks[1].ExecutionOrder)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("plan with duplicate task execution order", func(t *testing.T) {
|
|
||||||
req := &plan.CreatePlanRequest{
|
|
||||||
Name: "Invalid Plan",
|
|
||||||
ContentType: models.PlanContentTypeTasks,
|
|
||||||
Tasks: []plan.TaskRequest{
|
|
||||||
{Name: "Task 1", ExecutionOrder: 1},
|
|
||||||
{Name: "Task 2", ExecutionOrder: 1}, // Duplicate order
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
planModel, err := plan.PlanFromCreateRequest(req)
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.Contains(t, err.Error(), "任务执行顺序重复")
|
|
||||||
assert.Nil(t, planModel)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPlanFromUpdateRequest(t *testing.T) {
|
|
||||||
t.Run("nil request", func(t *testing.T) {
|
|
||||||
planModel, err := plan.PlanFromUpdateRequest(nil)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Nil(t, planModel)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("basic plan without associations", func(t *testing.T) {
|
|
||||||
req := &plan.UpdatePlanRequest{
|
|
||||||
Name: "Updated Plan",
|
|
||||||
Description: "An updated plan",
|
|
||||||
ExecutionType: models.PlanExecutionTypeManual,
|
|
||||||
CronExpression: "0 30 * * *",
|
|
||||||
ContentType: models.PlanContentTypeTasks,
|
|
||||||
}
|
|
||||||
|
|
||||||
planModel, err := plan.PlanFromUpdateRequest(req)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotNil(t, planModel)
|
|
||||||
assert.Equal(t, "Updated Plan", planModel.Name)
|
|
||||||
assert.Equal(t, "An updated plan", planModel.Description)
|
|
||||||
assert.Equal(t, models.PlanExecutionTypeManual, planModel.ExecutionType)
|
|
||||||
assert.Equal(t, "0 30 * * *", planModel.CronExpression)
|
|
||||||
assert.Equal(t, models.PlanContentTypeTasks, planModel.ContentType)
|
|
||||||
assert.Empty(t, planModel.SubPlans)
|
|
||||||
assert.Empty(t, planModel.Tasks)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("plan with sub plan IDs", func(t *testing.T) {
|
|
||||||
req := &plan.UpdatePlanRequest{
|
|
||||||
Name: "Updated Parent Plan",
|
|
||||||
ContentType: models.PlanContentTypeSubPlans,
|
|
||||||
SubPlanIDs: []uint{2, 3},
|
|
||||||
}
|
|
||||||
|
|
||||||
planModel, err := plan.PlanFromUpdateRequest(req)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotNil(t, planModel)
|
|
||||||
|
|
||||||
assert.Equal(t, "Updated Parent Plan", planModel.Name)
|
|
||||||
assert.Equal(t, models.PlanContentTypeSubPlans, planModel.ContentType)
|
|
||||||
assert.Len(t, planModel.SubPlans, 2)
|
|
||||||
assert.Empty(t, planModel.Tasks)
|
|
||||||
|
|
||||||
assert.Equal(t, uint(2), planModel.SubPlans[0].ChildPlanID)
|
|
||||||
assert.Equal(t, 1, planModel.SubPlans[0].ExecutionOrder)
|
|
||||||
assert.Equal(t, uint(3), planModel.SubPlans[1].ChildPlanID)
|
|
||||||
assert.Equal(t, 2, planModel.SubPlans[1].ExecutionOrder)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("plan with tasks", func(t *testing.T) {
|
|
||||||
params := controller.Properties([]byte(`{"device_id": 1, "value": 25}`))
|
|
||||||
|
|
||||||
req := &plan.UpdatePlanRequest{
|
|
||||||
Name: "Updated Task Plan",
|
|
||||||
ContentType: models.PlanContentTypeTasks,
|
|
||||||
Tasks: []plan.TaskRequest{
|
|
||||||
{
|
|
||||||
Name: "Task 1",
|
|
||||||
Description: "First task",
|
|
||||||
ExecutionOrder: 1,
|
|
||||||
Type: models.TaskTypeWaiting,
|
|
||||||
Parameters: params,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
planModel, err := plan.PlanFromUpdateRequest(req)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotNil(t, planModel)
|
|
||||||
assert.Equal(t, "Updated Task Plan", planModel.Name)
|
|
||||||
assert.Equal(t, models.PlanContentTypeTasks, planModel.ContentType)
|
|
||||||
assert.Len(t, planModel.Tasks, 1)
|
|
||||||
assert.Empty(t, planModel.SubPlans)
|
|
||||||
|
|
||||||
task := planModel.Tasks[0]
|
|
||||||
assert.Equal(t, "Task 1", task.Name)
|
|
||||||
assert.Equal(t, 1, task.ExecutionOrder)
|
|
||||||
assert.Equal(t, datatypes.JSON(params), task.Parameters)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("plan with duplicate task execution order", func(t *testing.T) {
|
|
||||||
req := &plan.UpdatePlanRequest{
|
|
||||||
Name: "Invalid Updated Plan",
|
|
||||||
ContentType: models.PlanContentTypeTasks,
|
|
||||||
Tasks: []plan.TaskRequest{
|
|
||||||
{Name: "Task 1", ExecutionOrder: 1},
|
|
||||||
{Name: "Task 2", ExecutionOrder: 1}, // Duplicate order
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
planModel, err := plan.PlanFromUpdateRequest(req)
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.Contains(t, err.Error(), "任务执行顺序重复")
|
|
||||||
assert.Nil(t, planModel)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("plan with tasks with gapped execution order", func(t *testing.T) {
|
|
||||||
req := &plan.UpdatePlanRequest{
|
|
||||||
Name: "Updated Task Plan with Gaps",
|
|
||||||
ContentType: models.PlanContentTypeTasks,
|
|
||||||
Tasks: []plan.TaskRequest{
|
|
||||||
{Name: "Task 3", ExecutionOrder: 5},
|
|
||||||
{Name: "Task 1", ExecutionOrder: 2},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
planModel, err := plan.PlanFromUpdateRequest(req)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotNil(t, planModel)
|
|
||||||
assert.Len(t, planModel.Tasks, 2)
|
|
||||||
|
|
||||||
// After ReorderSteps, tasks are sorted by their original ExecutionOrder and then re-numbered.
|
|
||||||
assert.Equal(t, "Task 1", planModel.Tasks[0].Name)
|
|
||||||
assert.Equal(t, 1, planModel.Tasks[0].ExecutionOrder)
|
|
||||||
assert.Equal(t, "Task 3", planModel.Tasks[1].Name)
|
|
||||||
assert.Equal(t, 2, planModel.Tasks[1].ExecutionOrder)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSubPlanToResponse(t *testing.T) {
|
|
||||||
t.Run("nil sub plan", func(t *testing.T) {
|
|
||||||
response := plan.SubPlanToResponse(nil)
|
|
||||||
assert.Equal(t, plan.SubPlanResponse{}, response)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("sub plan without child plan", func(t *testing.T) {
|
|
||||||
subPlan := &models.SubPlan{
|
|
||||||
Model: gorm.Model{ID: 10},
|
|
||||||
ParentPlanID: 1,
|
|
||||||
ChildPlanID: 2,
|
|
||||||
ExecutionOrder: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
response := plan.SubPlanToResponse(subPlan)
|
|
||||||
assert.Equal(t, uint(10), response.ID)
|
|
||||||
assert.Equal(t, uint(1), response.ParentPlanID)
|
|
||||||
assert.Equal(t, uint(2), response.ChildPlanID)
|
|
||||||
assert.Equal(t, 1, response.ExecutionOrder)
|
|
||||||
assert.Nil(t, response.ChildPlan)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("sub plan with child plan", func(t *testing.T) {
|
|
||||||
childPlan := &models.Plan{
|
|
||||||
Model: gorm.Model{ID: 2},
|
|
||||||
Name: "Child Plan",
|
|
||||||
}
|
|
||||||
|
|
||||||
subPlan := &models.SubPlan{
|
|
||||||
Model: gorm.Model{ID: 10},
|
|
||||||
ParentPlanID: 1,
|
|
||||||
ChildPlanID: 2,
|
|
||||||
ExecutionOrder: 1,
|
|
||||||
ChildPlan: childPlan,
|
|
||||||
}
|
|
||||||
|
|
||||||
response := plan.SubPlanToResponse(subPlan)
|
|
||||||
assert.Equal(t, uint(10), response.ID)
|
|
||||||
assert.Equal(t, uint(1), response.ParentPlanID)
|
|
||||||
assert.Equal(t, uint(2), response.ChildPlanID)
|
|
||||||
assert.Equal(t, 1, response.ExecutionOrder)
|
|
||||||
assert.NotNil(t, response.ChildPlan)
|
|
||||||
assert.Equal(t, "Child Plan", response.ChildPlan.Name)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTaskToResponse(t *testing.T) {
|
|
||||||
t.Run("nil task", func(t *testing.T) {
|
|
||||||
response := plan.TaskToResponse(nil)
|
|
||||||
assert.Equal(t, plan.TaskResponse{}, response)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("task with parameters", func(t *testing.T) {
|
|
||||||
params := datatypes.JSON([]byte(`{"device_id": 1, "value": 25}`))
|
|
||||||
task := &models.Task{
|
|
||||||
Model: gorm.Model{ID: 10},
|
|
||||||
PlanID: 1,
|
|
||||||
Name: "Test Task",
|
|
||||||
Description: "A test task",
|
|
||||||
ExecutionOrder: 1,
|
|
||||||
Type: models.TaskTypeWaiting,
|
|
||||||
Parameters: params,
|
|
||||||
}
|
|
||||||
|
|
||||||
response := plan.TaskToResponse(task)
|
|
||||||
assert.Equal(t, uint(10), response.ID)
|
|
||||||
assert.Equal(t, uint(1), response.PlanID)
|
|
||||||
assert.Equal(t, "Test Task", response.Name)
|
|
||||||
assert.Equal(t, "A test task", response.Description)
|
|
||||||
assert.Equal(t, 1, response.ExecutionOrder)
|
|
||||||
assert.Equal(t, models.TaskTypeWaiting, response.Type)
|
|
||||||
assert.Equal(t, controller.Properties(params), response.Parameters)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTaskFromRequest(t *testing.T) {
|
|
||||||
t.Run("nil request", func(t *testing.T) {
|
|
||||||
task := plan.TaskFromRequest(nil)
|
|
||||||
assert.Equal(t, models.Task{}, task)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("task with parameters", func(t *testing.T) {
|
|
||||||
params := controller.Properties([]byte(`{"device_id": 1, "value": 25}`))
|
|
||||||
req := &plan.TaskRequest{
|
|
||||||
Name: "Test Task",
|
|
||||||
Description: "A test task",
|
|
||||||
ExecutionOrder: 1,
|
|
||||||
Type: models.TaskTypeWaiting,
|
|
||||||
Parameters: params,
|
|
||||||
}
|
|
||||||
|
|
||||||
task := plan.TaskFromRequest(req)
|
|
||||||
assert.Equal(t, "Test Task", task.Name)
|
|
||||||
assert.Equal(t, "A test task", task.Description)
|
|
||||||
assert.Equal(t, 1, task.ExecutionOrder)
|
|
||||||
assert.Equal(t, models.TaskTypeWaiting, task.Type)
|
|
||||||
assert.Equal(t, datatypes.JSON(params), task.Parameters)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -2,98 +2,18 @@ package dto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewPlanFromCreateRequest 将 CreatePlanRequest 转换为 models.Plan
|
// NewPlanToResponse 将Plan模型转换为PlanResponse
|
||||||
func NewPlanFromCreateRequest(req *CreatePlanRequest) (*models.Plan, error) {
|
|
||||||
plan := &models.Plan{
|
|
||||||
Name: req.Name,
|
|
||||||
Description: req.Description,
|
|
||||||
ExecutionType: req.ExecutionType,
|
|
||||||
ExecuteNum: req.ExecuteNum,
|
|
||||||
CronExpression: req.CronExpression,
|
|
||||||
Status: models.PlanStatusDisabled, // 默认创建时为禁用状态
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(req.SubPlanIDs) > 0 {
|
|
||||||
plan.ContentType = models.PlanContentTypeSubPlans
|
|
||||||
for _, subPlanID := range req.SubPlanIDs {
|
|
||||||
plan.SubPlans = append(plan.SubPlans, models.SubPlan{
|
|
||||||
ChildPlanID: subPlanID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else if len(req.Tasks) > 0 {
|
|
||||||
plan.ContentType = models.PlanContentTypeTasks
|
|
||||||
for _, taskReq := range req.Tasks {
|
|
||||||
parametersJSON, err := json.Marshal(taskReq.Parameters)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("序列化任务参数失败: %w", err)
|
|
||||||
}
|
|
||||||
plan.Tasks = append(plan.Tasks, models.Task{
|
|
||||||
Name: taskReq.Name,
|
|
||||||
Description: taskReq.Description,
|
|
||||||
ExecutionOrder: taskReq.ExecutionOrder,
|
|
||||||
Type: taskReq.Type,
|
|
||||||
Parameters: parametersJSON,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, errors.New("计划必须包含子计划或任务")
|
|
||||||
}
|
|
||||||
|
|
||||||
return plan, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPlanFromUpdateRequest 将 UpdatePlanRequest 转换为 models.Plan
|
|
||||||
func NewPlanFromUpdateRequest(req *UpdatePlanRequest) (*models.Plan, error) {
|
|
||||||
plan := &models.Plan{
|
|
||||||
Name: req.Name,
|
|
||||||
Description: req.Description,
|
|
||||||
ExecutionType: req.ExecutionType,
|
|
||||||
ExecuteNum: req.ExecuteNum,
|
|
||||||
CronExpression: req.CronExpression,
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(req.SubPlanIDs) > 0 {
|
|
||||||
plan.ContentType = models.PlanContentTypeSubPlans
|
|
||||||
for _, subPlanID := range req.SubPlanIDs {
|
|
||||||
plan.SubPlans = append(plan.SubPlans, models.SubPlan{
|
|
||||||
ChildPlanID: subPlanID,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else if len(req.Tasks) > 0 {
|
|
||||||
plan.ContentType = models.PlanContentTypeTasks
|
|
||||||
for _, taskReq := range req.Tasks {
|
|
||||||
parametersJSON, err := json.Marshal(taskReq.Parameters)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("序列化任务参数失败: %w", err)
|
|
||||||
}
|
|
||||||
plan.Tasks = append(plan.Tasks, models.Task{
|
|
||||||
Name: taskReq.Name,
|
|
||||||
Description: taskReq.Description,
|
|
||||||
ExecutionOrder: taskReq.ExecutionOrder,
|
|
||||||
Type: taskReq.Type,
|
|
||||||
Parameters: parametersJSON,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, errors.New("计划必须包含子计划或任务")
|
|
||||||
}
|
|
||||||
|
|
||||||
return plan, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPlanToResponse 将 models.Plan 转换为 PlanResponse
|
|
||||||
func NewPlanToResponse(plan *models.Plan) (*PlanResponse, error) {
|
func NewPlanToResponse(plan *models.Plan) (*PlanResponse, error) {
|
||||||
if plan == nil {
|
if plan == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := &PlanResponse{
|
response := &PlanResponse{
|
||||||
ID: plan.ID,
|
ID: plan.ID,
|
||||||
Name: plan.Name,
|
Name: plan.Name,
|
||||||
Description: plan.Description,
|
Description: plan.Description,
|
||||||
@@ -105,41 +25,202 @@ func NewPlanToResponse(plan *models.Plan) (*PlanResponse, error) {
|
|||||||
ContentType: plan.ContentType,
|
ContentType: plan.ContentType,
|
||||||
}
|
}
|
||||||
|
|
||||||
if plan.ContentType == models.PlanContentTypeSubPlans && len(plan.SubPlans) > 0 {
|
// 转换子计划
|
||||||
resp.SubPlans = make([]SubPlanResponse, 0, len(plan.SubPlans))
|
if plan.ContentType == models.PlanContentTypeSubPlans {
|
||||||
for _, sp := range plan.SubPlans {
|
response.SubPlans = make([]SubPlanResponse, len(plan.SubPlans))
|
||||||
childPlanResp, err := NewPlanToResponse(sp.ChildPlan) // 递归调用
|
for i, subPlan := range plan.SubPlans {
|
||||||
|
subPlanResp, err := SubPlanToResponse(&subPlan)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
resp.SubPlans = append(resp.SubPlans, SubPlanResponse{
|
response.SubPlans[i] = subPlanResp
|
||||||
ID: sp.ID,
|
|
||||||
ParentPlanID: sp.ParentPlanID,
|
|
||||||
ChildPlanID: sp.ChildPlanID,
|
|
||||||
ExecutionOrder: sp.ExecutionOrder,
|
|
||||||
ChildPlan: childPlanResp,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
} else if plan.ContentType == models.PlanContentTypeTasks && len(plan.Tasks) > 0 {
|
}
|
||||||
resp.Tasks = make([]TaskResponse, 0, len(plan.Tasks))
|
|
||||||
for _, task := range plan.Tasks {
|
// 转换任务
|
||||||
var parameters map[string]interface{}
|
if plan.ContentType == models.PlanContentTypeTasks {
|
||||||
|
response.Tasks = make([]TaskResponse, len(plan.Tasks))
|
||||||
|
for i, task := range plan.Tasks {
|
||||||
|
taskResp, err := TaskToResponse(&task)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
response.Tasks[i] = taskResp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPlanFromCreateRequest 将CreatePlanRequest转换为Plan模型,并进行业务规则验证
|
||||||
|
func NewPlanFromCreateRequest(req *CreatePlanRequest) (*models.Plan, error) {
|
||||||
|
if req == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
plan := &models.Plan{
|
||||||
|
Name: req.Name,
|
||||||
|
Description: req.Description,
|
||||||
|
ExecutionType: req.ExecutionType,
|
||||||
|
ExecuteNum: req.ExecuteNum,
|
||||||
|
CronExpression: req.CronExpression,
|
||||||
|
// ContentType 在控制器中设置,此处不再处理
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理子计划 (通过ID引用)
|
||||||
|
if req.SubPlanIDs != nil {
|
||||||
|
subPlanSlice := req.SubPlanIDs
|
||||||
|
plan.SubPlans = make([]models.SubPlan, len(subPlanSlice))
|
||||||
|
for i, childPlanID := range subPlanSlice {
|
||||||
|
plan.SubPlans[i] = models.SubPlan{
|
||||||
|
ChildPlanID: childPlanID,
|
||||||
|
ExecutionOrder: i, // 默认执行顺序, ReorderSteps会再次确认
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理任务
|
||||||
|
if req.Tasks != nil {
|
||||||
|
taskSlice := req.Tasks
|
||||||
|
plan.Tasks = make([]models.Task, len(taskSlice))
|
||||||
|
for i, taskReq := range taskSlice {
|
||||||
|
task, err := TaskFromRequest(&taskReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
plan.Tasks[i] = task
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 首先,执行重复性验证
|
||||||
|
if err := plan.ValidateExecutionOrder(); err != nil {
|
||||||
|
// 如果检测到重复,立即返回错误
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 然后,调用方法来修复顺序断层
|
||||||
|
plan.ReorderSteps()
|
||||||
|
|
||||||
|
return plan, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPlanFromUpdateRequest 将UpdatePlanRequest转换为Plan模型,并进行业务规则验证
|
||||||
|
func NewPlanFromUpdateRequest(req *UpdatePlanRequest) (*models.Plan, error) {
|
||||||
|
if req == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
plan := &models.Plan{
|
||||||
|
Name: req.Name,
|
||||||
|
Description: req.Description,
|
||||||
|
ExecutionType: req.ExecutionType,
|
||||||
|
ExecuteNum: req.ExecuteNum,
|
||||||
|
CronExpression: req.CronExpression,
|
||||||
|
// ContentType 在控制器中设置,此处不再处理
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理子计划 (通过ID引用)
|
||||||
|
if req.SubPlanIDs != nil {
|
||||||
|
subPlanSlice := req.SubPlanIDs
|
||||||
|
plan.SubPlans = make([]models.SubPlan, len(subPlanSlice))
|
||||||
|
for i, childPlanID := range subPlanSlice {
|
||||||
|
plan.SubPlans[i] = models.SubPlan{
|
||||||
|
ChildPlanID: childPlanID,
|
||||||
|
ExecutionOrder: i, // 默认执行顺序, ReorderSteps会再次确认
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理任务
|
||||||
|
if req.Tasks != nil {
|
||||||
|
taskSlice := req.Tasks
|
||||||
|
plan.Tasks = make([]models.Task, len(taskSlice))
|
||||||
|
for i, taskReq := range taskSlice {
|
||||||
|
task, err := TaskFromRequest(&taskReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
plan.Tasks[i] = task
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 首先,执行重复性验证
|
||||||
|
if err := plan.ValidateExecutionOrder(); err != nil {
|
||||||
|
// 如果检测到重复,立即返回错误
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 然后,调用方法来修复顺序断层
|
||||||
|
plan.ReorderSteps()
|
||||||
|
|
||||||
|
return plan, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubPlanToResponse 将SubPlan模型转换为SubPlanResponse
|
||||||
|
func SubPlanToResponse(subPlan *models.SubPlan) (SubPlanResponse, error) {
|
||||||
|
if subPlan == nil {
|
||||||
|
return SubPlanResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
response := SubPlanResponse{
|
||||||
|
ID: subPlan.ID,
|
||||||
|
ParentPlanID: subPlan.ParentPlanID,
|
||||||
|
ChildPlanID: subPlan.ChildPlanID,
|
||||||
|
ExecutionOrder: subPlan.ExecutionOrder,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有完整的子计划数据,也进行转换
|
||||||
|
if subPlan.ChildPlan != nil {
|
||||||
|
childPlanResp, err := NewPlanToResponse(subPlan.ChildPlan)
|
||||||
|
if err != nil {
|
||||||
|
return SubPlanResponse{}, err
|
||||||
|
}
|
||||||
|
response.ChildPlan = childPlanResp
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TaskToResponse 将Task模型转换为TaskResponse
|
||||||
|
func TaskToResponse(task *models.Task) (TaskResponse, error) {
|
||||||
|
if task == nil {
|
||||||
|
return TaskResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var params map[string]interface{}
|
||||||
if len(task.Parameters) > 0 && string(task.Parameters) != "null" {
|
if len(task.Parameters) > 0 && string(task.Parameters) != "null" {
|
||||||
if err := json.Unmarshal(task.Parameters, ¶meters); err != nil {
|
if err := task.ParseParameters(¶ms); err != nil {
|
||||||
return nil, fmt.Errorf("解析任务参数失败 (ID: %d): %w", task.ID, err)
|
return TaskResponse{}, fmt.Errorf("parsing task parameters failed (ID: %d): %w", task.ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resp.Tasks = append(resp.Tasks, TaskResponse{
|
|
||||||
|
return TaskResponse{
|
||||||
ID: task.ID,
|
ID: task.ID,
|
||||||
PlanID: task.PlanID,
|
PlanID: task.PlanID,
|
||||||
Name: task.Name,
|
Name: task.Name,
|
||||||
Description: task.Description,
|
Description: task.Description,
|
||||||
ExecutionOrder: task.ExecutionOrder,
|
ExecutionOrder: task.ExecutionOrder,
|
||||||
Type: task.Type,
|
Type: task.Type,
|
||||||
Parameters: parameters,
|
Parameters: params,
|
||||||
})
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TaskFromRequest 将TaskRequest转换为Task模型
|
||||||
|
func TaskFromRequest(req *TaskRequest) (models.Task, error) {
|
||||||
|
if req == nil {
|
||||||
|
return models.Task{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
paramsJSON, err := json.Marshal(req.Parameters)
|
||||||
|
if err != nil {
|
||||||
|
return models.Task{}, fmt.Errorf("serializing task parameters failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return models.Task{
|
||||||
|
Name: req.Name,
|
||||||
|
Description: req.Description,
|
||||||
|
ExecutionOrder: req.ExecutionOrder,
|
||||||
|
Type: req.Type,
|
||||||
|
Parameters: paramsJSON,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user