From fc0e8a36cefcb8f73a1f6368a3072f99207811c3 Mon Sep 17 00:00:00 2001 From: huang <1724659546@qq.com> Date: Sat, 13 Sep 2025 22:21:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=88=A0=E9=99=A4=E8=AE=A1?= =?UTF-8?q?=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/infra/repository/plan_repository.go | 64 ++++++++++++++++---- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/internal/infra/repository/plan_repository.go b/internal/infra/repository/plan_repository.go index 6b3f802..c78b8ef 100644 --- a/internal/infra/repository/plan_repository.go +++ b/internal/infra/repository/plan_repository.go @@ -10,12 +10,13 @@ import ( // 定义仓库层可导出的公共错误 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("计划不能同时包含任务和子计划") + 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("计划不能同时包含任务和子计划") + ErrDeleteWithReferencedPlan = errors.New("禁止删除正在被引用的计划") ) // PlanRepository 定义了与计划模型相关的数据库操作接口 @@ -27,10 +28,12 @@ type PlanRepository interface { GetBasicPlanByID(id uint) (*models.Plan, error) // GetPlanByID 根据ID获取计划,包含子计划和任务详情 GetPlanByID(id uint) (*models.Plan, error) - // Create 创建一个新的计划 - Create(plan *models.Plan) error + // CreatePlan 创建一个新的计划 + CreatePlan(plan *models.Plan) error // UpdatePlan 更新计划,包括子计划和任务 UpdatePlan(plan *models.Plan) error + // DeletePlan 根据ID删除计划,同时删除其关联的任务(非子任务)或子计划关联 + DeletePlan(id uint) error } // gormPlanRepository 是 PlanRepository 的 GORM 实现 @@ -112,8 +115,8 @@ func (r *gormPlanRepository) GetPlanByID(id uint) (*models.Plan, error) { return &plan, nil } -// Create 创建一个新的计划 -func (r *gormPlanRepository) Create(plan *models.Plan) error { +// CreatePlan 创建一个新的计划 +func (r *gormPlanRepository) CreatePlan(plan *models.Plan) error { return r.db.Transaction(func(tx *gorm.DB) error { // 1. 前置校验 if plan.ID != 0 { @@ -362,4 +365,43 @@ func (r *gormPlanRepository) reconcileSubPlans(tx *gorm.DB, plan *models.Plan) e return nil } -/// ABC +// DeletePlan 根据ID删除计划,同时删除其关联的任务(非子任务)或子计划关联 +func (r *gormPlanRepository) DeletePlan(id uint) error { + return r.db.Transaction(func(tx *gorm.DB) error { + // 1. 检查该计划是否是其他计划的子计划 + var count int64 + if err := tx.Model(&models.SubPlan{}).Where("child_plan_id = ?", id).Count(&count).Error; err != nil { + return fmt.Errorf("检查计划是否为子计划失败: %w", err) + } + if count > 0 { + return ErrDeleteWithReferencedPlan + } + + var plan models.Plan + // 2. 获取计划以确定其内容类型 + if err := tx.First(&plan, id).Error; err != nil { + return err + } + + // 3. 根据内容类型删除关联数据 + switch plan.ContentType { + case models.PlanContentTypeTasks: + // 删除与此计划关联的所有非子任务 + if err := tx.Where("plan_id = ? AND parent_task_id IS NULL", id).Delete(&models.Task{}).Error; err != nil { + return fmt.Errorf("删除计划ID %d 的任务失败: %w", id, err) + } + case models.PlanContentTypeSubPlans: + // 删除与此计划关联的所有子计划链接 + if err := tx.Where("parent_plan_id = ?", id).Delete(&models.SubPlan{}).Error; err != nil { + return fmt.Errorf("删除计划ID %d 的子计划关联失败: %w", id, err) + } + } + + // 4. 删除计划本身 + if err := tx.Delete(&models.Plan{}, id).Error; err != nil { + return fmt.Errorf("删除计划ID %d 失败: %w", id, err) + } + + return nil + }) +}