feat(ui+backend): task categories edition
This commit is contained in:
14
internal/graph/error.go
Normal file
14
internal/graph/error.go
Normal file
@ -0,0 +1,14 @@
|
||||
package graph
|
||||
|
||||
import (
|
||||
"github.com/vektah/gqlparser/v2/gqlerror"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrAssociatedTaskExist = &gqlerror.Error{
|
||||
Message: "",
|
||||
Extensions: map[string]interface{}{
|
||||
"code": "associated-task-exist",
|
||||
},
|
||||
}
|
||||
)
|
@ -30,6 +30,11 @@ input TimeUnitChanges {
|
||||
acronym: String
|
||||
}
|
||||
|
||||
input ProjectTaskCategoryChanges {
|
||||
label: String
|
||||
costPerTimeUnit: Float
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
updateUser(id: ID!, changes: UserChanges!): User!
|
||||
createProject(changes: CreateProjectChanges!): Project!
|
||||
@ -37,5 +42,8 @@ type Mutation {
|
||||
addProjectTask(projectId: ID!, changes: ProjectTaskChanges!): Task!
|
||||
removeProjectTask(projectId: ID!, taskId: ID!): Boolean!
|
||||
updateProjectTask(projectId: ID!, taskId: ID!, changes: ProjectTaskChanges!): Task!
|
||||
addProjectTaskCategory(projectId: ID!, changes: ProjectTaskCategoryChanges!): TaskCategory!
|
||||
updateProjectTaskCategory(projectId: ID!, taskCategoryId: ID!, changes: ProjectTaskCategoryChanges!): TaskCategory!
|
||||
removeProjectTaskCategory(projectId: ID!, taskCategoryId: ID!): Boolean!
|
||||
updateProjectParams(projectId: ID!, changes: ProjectParamsChanges!): ProjectParams!
|
||||
}
|
@ -34,6 +34,18 @@ func (r *mutationResolver) UpdateProjectTask(ctx context.Context, projectID int6
|
||||
return handleUpdateProjectTask(ctx, projectID, taskID, changes)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) AddProjectTaskCategory(ctx context.Context, projectID int64, changes model.ProjectTaskCategoryChanges) (*model.TaskCategory, error) {
|
||||
return handleAddProjectTaskCategory(ctx, projectID, changes)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) UpdateProjectTaskCategory(ctx context.Context, projectID int64, taskCategoryID int64, changes model.ProjectTaskCategoryChanges) (*model.TaskCategory, error) {
|
||||
return handleUpdateProjectTaskCategory(ctx, projectID, taskCategoryID, changes)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) RemoveProjectTaskCategory(ctx context.Context, projectID int64, taskCategoryID int64) (bool, error) {
|
||||
return handleRemoveProjectTaskCategory(ctx, projectID, taskCategoryID)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) UpdateProjectParams(ctx context.Context, projectID int64, changes model.ProjectParamsChanges) (*model.ProjectParams, error) {
|
||||
return handleUpdateProjectParams(ctx, projectID, changes)
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package graph
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
|
||||
"forge.cadoles.com/Cadoles/guesstimate/internal/model"
|
||||
model1 "forge.cadoles.com/Cadoles/guesstimate/internal/model"
|
||||
"github.com/pkg/errors"
|
||||
@ -126,3 +128,56 @@ func handleUpdateProjectParams(ctx context.Context, projectID int64, changes mod
|
||||
|
||||
return project.Params, nil
|
||||
}
|
||||
|
||||
func handleAddProjectTaskCategory(ctx context.Context, projectID int64, changes model.ProjectTaskCategoryChanges) (*model.TaskCategory, error) {
|
||||
db, err := getDB(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
repo := model.NewProjectRepository(db)
|
||||
|
||||
taskCategory, err := repo.AddTaskCategory(ctx, projectID, changes)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return taskCategory, nil
|
||||
}
|
||||
|
||||
func handleUpdateProjectTaskCategory(ctx context.Context, projectID int64, taskCategoryID int64, changes model.ProjectTaskCategoryChanges) (*model.TaskCategory, error) {
|
||||
db, err := getDB(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
repo := model.NewProjectRepository(db)
|
||||
|
||||
taskCategory, err := repo.UpdateTaskCategory(ctx, projectID, taskCategoryID, changes)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return taskCategory, nil
|
||||
}
|
||||
|
||||
func handleRemoveProjectTaskCategory(ctx context.Context, projectID int64, taskCategoryID int64) (bool, error) {
|
||||
db, err := getDB(ctx)
|
||||
if err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
repo := model.NewProjectRepository(db)
|
||||
|
||||
if err := repo.RemoveTaskCategory(ctx, projectID, taskCategoryID); err != nil {
|
||||
if errors.Is(err, model.ErrAssociatedTaskExist) {
|
||||
graphql.AddError(ctx, ErrAssociatedTaskExist)
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
7
internal/model/error.go
Normal file
7
internal/model/error.go
Normal file
@ -0,0 +1,7 @@
|
||||
package model
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrAssociatedTaskExist = errors.New("associated task exist")
|
||||
)
|
@ -144,10 +144,6 @@ func (r *ProjectRepository) AddTask(ctx context.Context, projectID int64, change
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := tx.Save(task).Error; err != nil {
|
||||
return errors.Wrap(err, "could not create task")
|
||||
}
|
||||
|
||||
err := tx.Model(project).Association("Tasks").Append(task).Error
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not add task")
|
||||
@ -279,6 +275,94 @@ func (r *ProjectRepository) UpdateParams(ctx context.Context, projectID int64, c
|
||||
return project, nil
|
||||
}
|
||||
|
||||
func (r *ProjectRepository) AddTaskCategory(ctx context.Context, projectID int64, changes ProjectTaskCategoryChanges) (*TaskCategory, error) {
|
||||
project := &Project{}
|
||||
project.ID = projectID
|
||||
taskCategory := &TaskCategory{}
|
||||
|
||||
err := r.db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := updateTaskCategoryWithChanges(tx, taskCategory, changes); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
err := tx.Model(project).Association("TaskCategories").Append(taskCategory).Error
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not add task category")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not add task category")
|
||||
}
|
||||
|
||||
return taskCategory, nil
|
||||
}
|
||||
|
||||
func (r *ProjectRepository) RemoveTaskCategory(ctx context.Context, projectID int64, taskCategoryID int64) error {
|
||||
project := &Project{}
|
||||
project.ID = projectID
|
||||
|
||||
err := r.db.Transaction(func(tx *gorm.DB) error {
|
||||
taskCategory := &TaskCategory{}
|
||||
taskCategory.ID = taskCategoryID
|
||||
|
||||
var totalAssociatedTasks int
|
||||
if err := tx.Model(&Task{}).Where("category_id = ?", taskCategoryID).Count(&totalAssociatedTasks).Error; err != nil {
|
||||
return errors.Wrap(err, "could not count associated tasks")
|
||||
}
|
||||
|
||||
if totalAssociatedTasks != 0 {
|
||||
return errors.WithStack(ErrAssociatedTaskExist)
|
||||
}
|
||||
|
||||
err := tx.Model(project).Association("TaskCategories").Delete(taskCategory).Error
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not remove task category relationship")
|
||||
}
|
||||
|
||||
err = tx.Delete(taskCategory, "id = ? AND project_id = ?", taskCategoryID, projectID).Error
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not delete task category")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not remove task category")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ProjectRepository) UpdateTaskCategory(ctx context.Context, projectID, taskCategoryID int64, changes ProjectTaskCategoryChanges) (*TaskCategory, error) {
|
||||
taskCategory := &TaskCategory{}
|
||||
|
||||
err := r.db.Transaction(func(tx *gorm.DB) error {
|
||||
err := tx.Model(taskCategory).
|
||||
First(taskCategory, "id = ? AND project_id = ?", taskCategoryID, projectID).
|
||||
Error
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := updateTaskCategoryWithChanges(tx, taskCategory, changes); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if err := tx.Save(taskCategory).Error; err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not update task category")
|
||||
}
|
||||
|
||||
return taskCategory, nil
|
||||
}
|
||||
|
||||
func updateTaskWithChanges(db *gorm.DB, task *Task, changes ProjectTaskChanges) error {
|
||||
if changes.Label != nil {
|
||||
task.Label = changes.Label
|
||||
@ -330,6 +414,18 @@ func updateTaskWithChanges(db *gorm.DB, task *Task, changes ProjectTaskChanges)
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateTaskCategoryWithChanges(db *gorm.DB, taskCategory *TaskCategory, changes ProjectTaskCategoryChanges) error {
|
||||
if changes.Label != nil {
|
||||
taskCategory.Label = *changes.Label
|
||||
}
|
||||
|
||||
if changes.CostPerTimeUnit != nil {
|
||||
taskCategory.CostPerTimeUnit = *changes.CostPerTimeUnit
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewProjectRepository(db *gorm.DB) *ProjectRepository {
|
||||
return &ProjectRepository{db}
|
||||
}
|
||||
|
Reference in New Issue
Block a user