@@ -0,0 +1,88 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gardomatic.kleiax.de/internal/platform/validate"
|
||||
)
|
||||
|
||||
// TaskRecurrence identifies the calendar interval of a manual task.
|
||||
type TaskRecurrence string
|
||||
|
||||
// Supported task recurrence values. An empty value disables recurrence.
|
||||
const (
|
||||
TaskRecurrenceNone TaskRecurrence = ""
|
||||
TaskRecurrenceDaily TaskRecurrence = "daily"
|
||||
TaskRecurrenceWeekly TaskRecurrence = "weekly"
|
||||
TaskRecurrenceMonthly TaskRecurrence = "monthly"
|
||||
TaskRecurrenceYearly TaskRecurrence = "yearly"
|
||||
)
|
||||
|
||||
// TaskModelInterface persists garden work items and generated task instances.
|
||||
type TaskModelInterface interface {
|
||||
Insert(task Task) (Task, error)
|
||||
Get(gardenID, id int) (Task, error)
|
||||
GetAllForGarden(gardenID int) ([]Task, error)
|
||||
Update(gardenID int, task Task) (Task, error)
|
||||
Delete(gardenID, id int) error
|
||||
}
|
||||
|
||||
// ValidateTask applies persistence-independent rules for manual garden tasks.
|
||||
func ValidateTask(v *validate.Validator, task Task) {
|
||||
v.Check(strings.TrimSpace(task.Title) != "", "title", "must be provided")
|
||||
v.Check(len(task.Title) <= 500, "title", "must not be more than 500 bytes long")
|
||||
v.Check(len(task.Description) <= 10_000, "description", "must not be more than 10000 bytes long")
|
||||
v.Check(task.Priority >= -100 && task.Priority <= 100, "priority", "must be between -100 and 100")
|
||||
if task.PlantID != nil {
|
||||
v.Check(*task.PlantID > 0, "plant_id", "must be a positive integer")
|
||||
}
|
||||
if task.LocationID != nil {
|
||||
v.Check(*task.LocationID > 0, "location_id", "must be a positive integer")
|
||||
}
|
||||
if task.DueAtStart != nil && task.DueAtEnd != nil {
|
||||
v.Check(!task.DueAtStart.After(*task.DueAtEnd), "due_at_end", "must not be before due_at_start")
|
||||
}
|
||||
v.Check(task.Recurrence == TaskRecurrenceNone || task.Recurrence == TaskRecurrenceDaily || task.Recurrence == TaskRecurrenceWeekly || task.Recurrence == TaskRecurrenceMonthly || task.Recurrence == TaskRecurrenceYearly, "recurrence", "is invalid")
|
||||
if task.Recurrence != TaskRecurrenceNone {
|
||||
v.Check(task.DueAtStart != nil || task.DueAtEnd != nil, "recurrence", "requires a due date")
|
||||
v.Check(task.RecurrenceInterval > 0, "recurrence_interval", "must be greater than zero")
|
||||
}
|
||||
validateOptionalEnum(v, "plant_status_on_completion", task.PlantStatusOnCompletion, "alive", "dead", "removed", "infested", "harvested")
|
||||
if task.PlantStatusOnCompletion != nil {
|
||||
v.Check(task.PlantID != nil, "plant_status_on_completion", "requires a plant")
|
||||
}
|
||||
if task.CompletedAt != nil {
|
||||
v.Check(task.CompletedBy != nil && *task.CompletedBy > 0, "completed_by", "must be set for a completed task")
|
||||
}
|
||||
if task.CompletedBy != nil {
|
||||
v.Check(task.CompletedAt != nil, "completed_at", "must be set when completed_by is set")
|
||||
}
|
||||
}
|
||||
|
||||
// Task represents a manual or template-generated garden work item.
|
||||
type Task struct {
|
||||
ID int `json:"id"`
|
||||
GardenID int `json:"garden_id"`
|
||||
PlantID *int `json:"plant_id,omitempty"`
|
||||
LocationID *int `json:"location_id,omitempty"`
|
||||
TemplateID *int `json:"template_id,omitempty"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
DueAtStart *time.Time `json:"due_at_start,omitempty"`
|
||||
DueAtEnd *time.Time `json:"due_at_end,omitempty"`
|
||||
GeneratedFor *time.Time `json:"generated_for,omitempty"`
|
||||
Recurrence TaskRecurrence `json:"recurrence,omitempty"`
|
||||
RecurrenceInterval int `json:"recurrence_interval"`
|
||||
RepeatFromID *int `json:"repeat_from_id,omitempty"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
||||
CompletedBy *int `json:"completed_by,omitempty"`
|
||||
Priority int `json:"priority"`
|
||||
Active bool `json:"active"`
|
||||
CreatedBy int `json:"created_by"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Version int `json:"version"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
PlantStatusOnCompletion *string `json:"plant_status_on_completion,omitempty"`
|
||||
}
|
||||
Reference in New Issue
Block a user