generated from VLADIMIR/template
101 lines
2.8 KiB
Go
101 lines
2.8 KiB
Go
// Package task_service implements the shared developer board.
|
|
package task_service
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
"unicode/utf8"
|
|
|
|
"evening_detective_server/internal/repos/tasks_repo"
|
|
)
|
|
|
|
var (
|
|
ErrInvalidTask = tasks_repo.ErrInvalidTask
|
|
ErrNotFound = tasks_repo.ErrNotFound
|
|
ErrConflict = tasks_repo.ErrConflict
|
|
ErrInvalidAssignee = tasks_repo.ErrInvalidAssignee
|
|
)
|
|
|
|
type Task = tasks_repo.Task
|
|
type Assignee = tasks_repo.Assignee
|
|
|
|
type ITasksRepo interface {
|
|
List(context.Context) ([]*Task, error)
|
|
ListAssignees(context.Context) ([]Assignee, error)
|
|
Create(context.Context, Task) (*Task, error)
|
|
Update(context.Context, Task) (*Task, error)
|
|
SetStatus(context.Context, int, int, string) (*Task, error)
|
|
Delete(context.Context, int, int) error
|
|
}
|
|
|
|
type TaskService struct{ repo ITasksRepo }
|
|
|
|
func NewTaskService(repo ITasksRepo) *TaskService { return &TaskService{repo: repo} }
|
|
|
|
func (s *TaskService) List(ctx context.Context) ([]*Task, error) { return s.repo.List(ctx) }
|
|
func (s *TaskService) ListAssignees(ctx context.Context) ([]Assignee, error) {
|
|
return s.repo.ListAssignees(ctx)
|
|
}
|
|
|
|
// ParseDueDate preserves calendar dates without a local time zone conversion.
|
|
func ParseDueDate(value string) (*time.Time, error) {
|
|
if value == "" {
|
|
return nil, nil
|
|
}
|
|
date, err := time.Parse("2006-01-02", value)
|
|
if err != nil || date.Year() < 1 {
|
|
return nil, ErrInvalidTask
|
|
}
|
|
return &date, nil
|
|
}
|
|
|
|
func validStatus(status string) bool {
|
|
return status == "new" || status == "in_progress" || status == "review" || status == "done"
|
|
}
|
|
|
|
func validate(task *Task) error {
|
|
task.Title = strings.TrimSpace(task.Title)
|
|
if task.Title == "" || strings.ContainsRune(task.Title, 0) || strings.ContainsRune(task.Description, 0) ||
|
|
utf8.RuneCountInString(task.Title) > 255 ||
|
|
utf8.RuneCountInString(task.Description) > 10000 || !validStatus(task.Status) ||
|
|
(task.AssigneeID != nil && *task.AssigneeID <= 0) {
|
|
return ErrInvalidTask
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *TaskService) Create(ctx context.Context, task Task) (*Task, error) {
|
|
if task.Status == "" {
|
|
task.Status = "new"
|
|
}
|
|
if err := validate(&task); err != nil {
|
|
return nil, err
|
|
}
|
|
return s.repo.Create(ctx, task)
|
|
}
|
|
|
|
func (s *TaskService) Update(ctx context.Context, task Task) (*Task, error) {
|
|
if task.ID <= 0 || task.Version <= 0 {
|
|
return nil, ErrInvalidTask
|
|
}
|
|
if err := validate(&task); err != nil {
|
|
return nil, err
|
|
}
|
|
return s.repo.Update(ctx, task)
|
|
}
|
|
|
|
func (s *TaskService) SetStatus(ctx context.Context, id, version int, status string) (*Task, error) {
|
|
if id <= 0 || version <= 0 || !validStatus(status) {
|
|
return nil, ErrInvalidTask
|
|
}
|
|
return s.repo.SetStatus(ctx, id, version, status)
|
|
}
|
|
|
|
func (s *TaskService) Delete(ctx context.Context, id, version int) error {
|
|
if id <= 0 || version <= 0 {
|
|
return ErrInvalidTask
|
|
}
|
|
return s.repo.Delete(ctx, id, version)
|
|
}
|