删除UpdatePlan的递归更新, 因为子计划的内容不应该被更改

This commit is contained in:
2025-09-14 15:06:45 +08:00
parent 352c9d9246
commit 8ceff5c3c7
2 changed files with 0 additions and 204 deletions

View File

@@ -346,10 +346,6 @@ func (r *gormPlanRepository) reconcileSubPlans(tx *gorm.DB, plan *models.Plan) e
return err return err
} }
} }
// 递归协调子计划节点
if err := r.reconcilePlanNode(tx, link.ChildPlan); err != nil {
return err
}
} }
var linksToDelete []uint var linksToDelete []uint

View File

@@ -836,206 +836,6 @@ func TestUpdatePlan_Reconciliation(t *testing.T) {
assert.Equal(t, int64(1), taskCount, "新任务应被创建") assert.Equal(t, int64(1), taskCount, "新任务应被创建")
}, },
}, },
{
name: "递归更新-深层节点的变更",
setupDB: func(db *gorm.DB) uint {
db.Create(&models.Plan{Model: gorm.Model{ID: 1}, Name: "A", ContentType: models.PlanContentTypeSubPlans})
db.Create(&models.Plan{Model: gorm.Model{ID: 2}, Name: "B", ContentType: models.PlanContentTypeSubPlans})
db.Create(&models.Plan{Model: gorm.Model{ID: 3}, Name: "C", ContentType: models.PlanContentTypeTasks})
db.Create(&models.SubPlan{Model: gorm.Model{ID: 101}, ParentPlanID: 1, ChildPlanID: 2, ExecutionOrder: 1})
db.Create(&models.SubPlan{Model: gorm.Model{ID: 102}, ParentPlanID: 2, ChildPlanID: 3, ExecutionOrder: 1})
return 1
},
buildInput: func(db *gorm.DB) *models.Plan {
planC := &models.Plan{Model: gorm.Model{ID: 3}, Name: "C Updated", ContentType: models.PlanContentTypeTasks}
planB := &models.Plan{
Model: gorm.Model{ID: 2},
Name: "B",
ContentType: models.PlanContentTypeSubPlans,
SubPlans: []models.SubPlan{{Model: gorm.Model{ID: 102}, ParentPlanID: 2, ChildPlanID: 3, ChildPlan: planC, ExecutionOrder: 2}},
}
planA := &models.Plan{
Model: gorm.Model{ID: 1},
Name: "A Updated",
ContentType: models.PlanContentTypeSubPlans,
SubPlans: []models.SubPlan{{Model: gorm.Model{ID: 101}, ParentPlanID: 1, ChildPlanID: 2, ChildPlan: planB, ExecutionOrder: 1}},
}
return planA
},
verifyDB: func(t *testing.T, db *gorm.DB, rootPlanID uint) {
var finalA, finalC models.Plan
var finalLinkB models.SubPlan
db.First(&finalA, 1)
assert.Equal(t, "A Updated", finalA.Name)
db.First(&finalLinkB, 102)
assert.Equal(t, 2, finalLinkB.ExecutionOrder)
db.First(&finalC, 3)
assert.Equal(t, "C Updated", finalC.Name)
},
},
{
name: "递归更新-深层节点的类型转换(C从SubPlans变为Tasks)",
setupDB: func(db *gorm.DB) uint {
// 初始状态: A -> B -> C -> D
db.Create(&models.Plan{Model: gorm.Model{ID: 1}, Name: "A", ContentType: models.PlanContentTypeSubPlans})
db.Create(&models.Plan{Model: gorm.Model{ID: 2}, Name: "B", ContentType: models.PlanContentTypeSubPlans})
db.Create(&models.Plan{Model: gorm.Model{ID: 3}, Name: "C", ContentType: models.PlanContentTypeSubPlans}) // C的初始类型
db.Create(&models.Plan{Model: gorm.Model{ID: 4}, Name: "D"})
db.Create(&models.SubPlan{ParentPlanID: 1, ChildPlanID: 2})
db.Create(&models.SubPlan{ParentPlanID: 2, ChildPlanID: 3})
db.Create(&models.SubPlan{Model: gorm.Model{ID: 99}, ParentPlanID: 3, ChildPlanID: 4}) // C->D 的关联
return 1
},
buildInput: func(db *gorm.DB) *models.Plan {
// 更新操作: C的类型变为Tasks并增加一个新Task
planC := &models.Plan{
Model: gorm.Model{ID: 3},
Name: "C",
ContentType: models.PlanContentTypeTasks, // 类型变更
Tasks: []models.Task{{Name: "C's New Task"}},
}
planB := &models.Plan{
Model: gorm.Model{ID: 2},
Name: "B",
ContentType: models.PlanContentTypeSubPlans,
SubPlans: []models.SubPlan{{ChildPlanID: 3, ChildPlan: planC}},
}
planA := &models.Plan{
Model: gorm.Model{ID: 1},
Name: "A",
ContentType: models.PlanContentTypeSubPlans,
SubPlans: []models.SubPlan{{ChildPlanID: 2, ChildPlan: planB}},
}
return planA
},
verifyDB: func(t *testing.T, db *gorm.DB, rootPlanID uint) {
// 1. 验证 C->D 的旧关联已被删除
var linkCount int64
db.Model(&models.SubPlan{}).Where("id = ?", 99).Count(&linkCount)
assert.Equal(t, int64(0), linkCount, "C的旧子计划关联应被清理")
// 2. 验证 C 的新Task已被创建
var task models.Task
err := db.Where("plan_id = ?", 3).First(&task).Error
assert.NoError(t, err, "C的新任务应该被创建")
assert.Equal(t, "C's New Task", task.Name)
// 3. 验证 D 计划本身依然存在
var planDCount int64
db.Model(&models.Plan{}).Where("id = ?", 4).Count(&planDCount)
assert.Equal(t, int64(1), planDCount, "计划D本身不应被删除")
},
}, {
name: "递归更新-中间层分支替换(A->B变为A->D)",
setupDB: func(db *gorm.DB) uint {
// 初始状态: A -> B -> C
db.Create(&models.Plan{Model: gorm.Model{ID: 1}, Name: "A", ContentType: models.PlanContentTypeSubPlans})
db.Create(&models.Plan{Model: gorm.Model{ID: 2}, Name: "B", ContentType: models.PlanContentTypeSubPlans})
db.Create(&models.Plan{Model: gorm.Model{ID: 3}, Name: "C"})
db.Create(&models.SubPlan{Model: gorm.Model{ID: 101}, ParentPlanID: 1, ChildPlanID: 2}) // A->B
db.Create(&models.SubPlan{ParentPlanID: 2, ChildPlanID: 3}) // B->C
// 准备用于替换的分支: D -> E
db.Create(&models.Plan{Model: gorm.Model{ID: 4}, Name: "D", ContentType: models.PlanContentTypeSubPlans})
db.Create(&models.Plan{Model: gorm.Model{ID: 5}, Name: "E"})
db.Create(&models.SubPlan{ParentPlanID: 4, ChildPlanID: 5}) // D->E
return 1
},
buildInput: func(db *gorm.DB) *models.Plan {
// 更新操作: A的子计划从 B 替换为 D
planE := &models.Plan{Model: gorm.Model{ID: 5}, Name: "E Updated"} // 同时更新深层节点
planD := &models.Plan{
Model: gorm.Model{ID: 4},
Name: "D",
ContentType: models.PlanContentTypeSubPlans,
SubPlans: []models.SubPlan{{ChildPlanID: 5, ChildPlan: planE}},
}
planA := &models.Plan{
Model: gorm.Model{ID: 1},
Name: "A",
ContentType: models.PlanContentTypeSubPlans,
SubPlans: []models.SubPlan{{ChildPlanID: 4, ChildPlan: planD}}, // 新关联 A->D
}
return planA
},
verifyDB: func(t *testing.T, db *gorm.DB, rootPlanID uint) {
// 1. 验证 A->B 的旧关联已被删除
var linkCount int64
db.Model(&models.SubPlan{}).Where("id = ?", 101).Count(&linkCount)
assert.Equal(t, int64(0), linkCount, "A->B 的旧关联应被删除")
// 2. 验证 A->D 的新关联已创建
var newLink models.SubPlan
err := db.Where("parent_plan_id = ? AND child_plan_id = ?", 1, 4).First(&newLink).Error
assert.NoError(t, err, "A->D 的新关联应被创建")
// 3. 验证 B, C, D, E 计划本身都依然存在
var planCount int64
db.Model(&models.Plan{}).Where("id IN ?", []uint{2, 3, 4, 5}).Count(&planCount)
assert.Equal(t, int64(4), planCount, "所有被引用或解引用的计划本身都不应被删除")
// 4. 验证对新分支深层节点的递归更新已生效
var finalE models.Plan
db.First(&finalE, 5)
assert.Equal(t, "E Updated", finalE.Name)
},
},
{
name: "递归更新-菱形依赖下的冲突更新",
setupDB: func(db *gorm.DB) uint {
// 初始状态: A -> B -> D, A -> C -> D
db.Create(&models.Plan{Model: gorm.Model{ID: 1}, Name: "A", ContentType: models.PlanContentTypeSubPlans})
db.Create(&models.Plan{Model: gorm.Model{ID: 2}, Name: "B", ContentType: models.PlanContentTypeSubPlans})
db.Create(&models.Plan{Model: gorm.Model{ID: 3}, Name: "C", ContentType: models.PlanContentTypeSubPlans})
db.Create(&models.Plan{Model: gorm.Model{ID: 4}, Name: "D (Original)"}) // D的初始名字
// 创建关联
db.Create(&models.SubPlan{ParentPlanID: 1, ChildPlanID: 2, ExecutionOrder: 1}) // A->B
db.Create(&models.SubPlan{ParentPlanID: 1, ChildPlanID: 3, ExecutionOrder: 2}) // A->C
db.Create(&models.SubPlan{ParentPlanID: 2, ChildPlanID: 4}) // B->D
db.Create(&models.SubPlan{ParentPlanID: 3, ChildPlanID: 4}) // C->D
return 1
},
buildInput: func(db *gorm.DB) *models.Plan {
// 在一次调用中,通过不同路径对 D 进行不同的更新
planD_fromB := &models.Plan{Model: gorm.Model{ID: 4}, Name: "D (Updated from B)"}
planD_fromC := &models.Plan{Model: gorm.Model{ID: 4}, Name: "D (Updated from C)"}
planB := &models.Plan{
Model: gorm.Model{ID: 2},
ContentType: models.PlanContentTypeSubPlans,
SubPlans: []models.SubPlan{{ChildPlanID: 4, ChildPlan: planD_fromB}},
}
planC := &models.Plan{
Model: gorm.Model{ID: 3},
ContentType: models.PlanContentTypeSubPlans,
SubPlans: []models.SubPlan{{ChildPlanID: 4, ChildPlan: planD_fromC}},
}
planA := &models.Plan{
Model: gorm.Model{ID: 1},
ContentType: models.PlanContentTypeSubPlans,
SubPlans: []models.SubPlan{
{ChildPlanID: 2, ChildPlan: planB, ExecutionOrder: 1},
{ChildPlanID: 3, ChildPlan: planC, ExecutionOrder: 2}, // C 在 B 之后
},
}
return planA
},
verifyDB: func(t *testing.T, db *gorm.DB, rootPlanID uint) {
// 验证D 的最终名字应该符合“最后一次更新获胜”的原则
// 由于 planC 在 planB 之后被处理D 的名字应该是 "D (Updated from C)"
var finalD models.Plan
db.First(&finalD, 4)
assert.Equal(t, "D (Updated from C)", finalD.Name, "共享下游节点的更新应以后一次执行为准")
// 确保所有关联依然存在
var linkCount int64
db.Model(&models.SubPlan{}).Where("child_plan_id = ?", 4).Count(&linkCount)
assert.Equal(t, int64(2), linkCount, "D 的两个上游关联都应继续存在")
},
},
} }
for _, tc := range testCases { for _, tc := range testCases {