package service import ( "context" "github.com/calendarapi/internal/models" "github.com/calendarapi/internal/repository" "github.com/calendarapi/internal/utils" "github.com/google/uuid" "github.com/jackc/pgx/v5" ) type TaskDependencyService struct { queries *repository.Queries } func NewTaskDependencyService(queries *repository.Queries) *TaskDependencyService { return &TaskDependencyService{queries: queries} } func (s *TaskDependencyService) Add(ctx context.Context, userID uuid.UUID, taskID uuid.UUID, blocksTaskID uuid.UUID) error { if taskID == blocksTaskID { return models.NewValidationError("task cannot depend on itself") } if _, err := s.queries.GetTaskByID(ctx, repository.GetTaskByIDParams{ ID: utils.ToPgUUID(taskID), OwnerID: utils.ToPgUUID(userID), }); err != nil { if err == pgx.ErrNoRows { return models.ErrNotFound } return models.ErrInternal } hasCircle, err := s.queries.CheckDirectCircularDependency(ctx, repository.CheckDirectCircularDependencyParams{ BlocksTaskID: utils.ToPgUUID(taskID), TaskID: utils.ToPgUUID(blocksTaskID), }) if err != nil { return models.ErrInternal } if hasCircle { return models.NewConflictError("circular dependency detected") } return s.queries.AddTaskDependency(ctx, repository.AddTaskDependencyParams{ TaskID: utils.ToPgUUID(taskID), BlocksTaskID: utils.ToPgUUID(blocksTaskID), }) } func (s *TaskDependencyService) Remove(ctx context.Context, userID uuid.UUID, taskID uuid.UUID, blocksTaskID uuid.UUID) error { if _, err := s.queries.GetTaskByID(ctx, repository.GetTaskByIDParams{ ID: utils.ToPgUUID(taskID), OwnerID: utils.ToPgUUID(userID), }); err != nil { if err == pgx.ErrNoRows { return models.ErrNotFound } return models.ErrInternal } return s.queries.RemoveTaskDependency(ctx, repository.RemoveTaskDependencyParams{ TaskID: utils.ToPgUUID(taskID), BlocksTaskID: utils.ToPgUUID(blocksTaskID), }) } func (s *TaskDependencyService) ListBlockers(ctx context.Context, userID uuid.UUID, taskID uuid.UUID) ([]models.Task, error) { if _, err := s.queries.GetTaskByID(ctx, repository.GetTaskByIDParams{ ID: utils.ToPgUUID(taskID), OwnerID: utils.ToPgUUID(userID), }); err != nil { if err == pgx.ErrNoRows { return nil, models.ErrNotFound } return nil, models.ErrInternal } rows, err := s.queries.ListTaskBlockers(ctx, utils.ToPgUUID(taskID)) if err != nil { return nil, models.ErrInternal } tasks := make([]models.Task, 0, len(rows)) for _, r := range rows { tasks = append(tasks, *taskFromDB(r)) } return tasks, nil }