实现创建计划
This commit is contained in:
@@ -10,9 +10,12 @@ import (
|
|||||||
|
|
||||||
// 定义仓库层可导出的公共错误
|
// 定义仓库层可导出的公共错误
|
||||||
var (
|
var (
|
||||||
ErrUpdateWithInvalidRoot = errors.New("更新操作的目标根计划无效或ID为0")
|
ErrUpdateWithInvalidRoot = errors.New("更新操作的目标根计划无效或ID为0")
|
||||||
ErrNewSubPlanInUpdate = errors.New("计划树中包含一个ID为0的新子计划,更新操作只允许关联已存在的计划")
|
ErrNewSubPlanInUpdate = errors.New("计划树中包含一个ID为0的新子计划,更新操作只允许关联已存在的计划")
|
||||||
ErrNodeDoesNotExist = errors.New("计划树中包含一个或多个在数据库中不存在的计划")
|
ErrNodeDoesNotExist = errors.New("计划树中包含一个或多个在数据库中不存在的计划")
|
||||||
|
ErrCreateWithNonZeroID = errors.New("创建操作的计划ID必须为0")
|
||||||
|
ErrSubPlanIDIsZeroOnCreate = errors.New("子计划ID为0,创建操作只允许关联已存在的计划")
|
||||||
|
ErrMixedContent = errors.New("计划不能同时包含任务和子计划")
|
||||||
)
|
)
|
||||||
|
|
||||||
// PlanRepository 定义了与计划模型相关的数据库操作接口
|
// PlanRepository 定义了与计划模型相关的数据库操作接口
|
||||||
@@ -24,6 +27,8 @@ type PlanRepository interface {
|
|||||||
GetBasicPlanByID(id uint) (*models.Plan, error)
|
GetBasicPlanByID(id uint) (*models.Plan, error)
|
||||||
// GetPlanByID 根据ID获取计划,包含子计划和任务详情
|
// GetPlanByID 根据ID获取计划,包含子计划和任务详情
|
||||||
GetPlanByID(id uint) (*models.Plan, error)
|
GetPlanByID(id uint) (*models.Plan, error)
|
||||||
|
// Create 创建一个新的计划
|
||||||
|
Create(plan *models.Plan) error
|
||||||
// UpdatePlan 更新计划,包括子计划和任务
|
// UpdatePlan 更新计划,包括子计划和任务
|
||||||
UpdatePlan(plan *models.Plan) error
|
UpdatePlan(plan *models.Plan) error
|
||||||
}
|
}
|
||||||
@@ -107,6 +112,76 @@ func (r *gormPlanRepository) GetPlanByID(id uint) (*models.Plan, error) {
|
|||||||
return &plan, nil
|
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 是更新计划的公共入口点
|
// UpdatePlan 是更新计划的公共入口点
|
||||||
func (r *gormPlanRepository) UpdatePlan(plan *models.Plan) error {
|
func (r *gormPlanRepository) UpdatePlan(plan *models.Plan) error {
|
||||||
return r.db.Transaction(func(tx *gorm.DB) 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ABC
|
||||||
|
|||||||
Reference in New Issue
Block a user