实现创建计划

This commit is contained in:
2025-09-13 20:13:53 +08:00
parent bd22e452d3
commit 287c27a5ab

View File

@@ -13,6 +13,9 @@ var (
ErrUpdateWithInvalidRoot = errors.New("更新操作的目标根计划无效或ID为0")
ErrNewSubPlanInUpdate = errors.New("计划树中包含一个ID为0的新子计划更新操作只允许关联已存在的计划")
ErrNodeDoesNotExist = errors.New("计划树中包含一个或多个在数据库中不存在的计划")
ErrCreateWithNonZeroID = errors.New("创建操作的计划ID必须为0")
ErrSubPlanIDIsZeroOnCreate = errors.New("子计划ID为0创建操作只允许关联已存在的计划")
ErrMixedContent = errors.New("计划不能同时包含任务和子计划")
)
// PlanRepository 定义了与计划模型相关的数据库操作接口
@@ -24,6 +27,8 @@ type PlanRepository interface {
GetBasicPlanByID(id uint) (*models.Plan, error)
// GetPlanByID 根据ID获取计划包含子计划和任务详情
GetPlanByID(id uint) (*models.Plan, error)
// Create 创建一个新的计划
Create(plan *models.Plan) error
// UpdatePlan 更新计划,包括子计划和任务
UpdatePlan(plan *models.Plan) error
}
@@ -107,6 +112,76 @@ func (r *gormPlanRepository) GetPlanByID(id uint) (*models.Plan, error) {
return &plan, nil
}
// Create 创建一个新的计划
func (r *gormPlanRepository) Create(plan *models.Plan) error {
return r.db.Transaction(func(tx *gorm.DB) error {
// 1. 前置校验
if plan.ID != 0 {
return ErrCreateWithNonZeroID
}
// 检查是否同时包含任务和子计划
if len(plan.Tasks) > 0 && len(plan.SubPlans) > 0 {
return ErrMixedContent
}
// 如果是子计划类型验证所有子计划是否存在且ID不为0
if plan.ContentType == models.PlanContentTypeSubPlans {
childIDsToValidate := make(map[uint]bool)
for _, subPlanLink := range plan.SubPlans {
if subPlanLink.ChildPlan == nil || subPlanLink.ChildPlan.ID == 0 {
return ErrSubPlanIDIsZeroOnCreate
}
childIDsToValidate[subPlanLink.ChildPlan.ID] = true
}
var ids []uint
for id := range childIDsToValidate {
ids = append(ids, id)
}
if len(ids) > 0 {
var count int64
if err := tx.Model(&models.Plan{}).Where("id IN ?", ids).Count(&count).Error; err != nil {
return fmt.Errorf("验证子计划存在性失败: %w", err)
}
if int(count) != len(ids) {
return ErrNodeDoesNotExist
}
}
}
// 2. 创建根计划
// GORM 会自动处理关联的 Tasks (如果 ContentType 是 tasks 且 Task.ID 为 0)
if err := tx.Create(plan).Error; err != nil {
return err
}
// 3. 处理子计划关联 (如果 ContentType 是 sub_plans)
// GORM 不会自动创建 SubPlan 关联记录,需要手动处理
if plan.ContentType == models.PlanContentTypeSubPlans {
// 收集所有 SubPlan 关联,设置 ParentPlanID
var subPlanLinksToCreate []models.SubPlan
for i := range plan.SubPlans {
plan.SubPlans[i].ParentPlanID = plan.ID // 设置父计划ID
// 确保 ChildPlanID 被正确设置,因为 ChildPlan 对象可能只在内存中
if plan.SubPlans[i].ChildPlanID == 0 && plan.SubPlans[i].ChildPlan != nil {
plan.SubPlans[i].ChildPlanID = plan.SubPlans[i].ChildPlan.ID
}
subPlanLinksToCreate = append(subPlanLinksToCreate, plan.SubPlans[i])
}
// 批量创建 SubPlan 关联记录
if len(subPlanLinksToCreate) > 0 {
if err := tx.CreateInBatches(subPlanLinksToCreate, 100).Error; err != nil { // 批量大小100
return err
}
}
}
return nil
})
}
// UpdatePlan 是更新计划的公共入口点
func (r *gormPlanRepository) UpdatePlan(plan *models.Plan) error {
return r.db.Transaction(func(tx *gorm.DB) error {
@@ -299,3 +374,5 @@ func (r *gormPlanRepository) reconcileSubPlans(tx *gorm.DB, plan *models.Plan) e
}
return nil
}
/// ABC