Files
Gardomatic/internal/api/season_templates.go
T
kleiax 904d14b64c
CI / test (push) Canceled after 0s
Initial commit
2026-09-12 22:22:17 +02:00

94 lines
3.2 KiB
Go

package api
import (
"errors"
"time"
"gardomatic.kleiax.de/internal/storage"
)
type seasonTemplateDefinition struct {
origin storage.TaskTemplateOrigin
title string
trigger storage.TaskTriggerType
monthFrom, dayFrom *int
monthTo, dayTo *int
}
func (app *application) syncSeasonTaskTemplates(gardenID int, species storage.Species) error {
if app.models.SpeciesTaskTemplates == nil {
return nil
}
existing, err := app.models.SpeciesTaskTemplates.GetAllForSpecies(gardenID, species.ID)
if err != nil {
return err
}
byOrigin := make(map[storage.TaskTemplateOrigin]storage.SpeciesTaskTemplate, len(existing))
for _, template := range existing {
if template.Origin != storage.TaskTemplateOriginManual {
byOrigin[template.Origin] = template
}
}
definitions := []seasonTemplateDefinition{
{storage.TaskTemplateOriginSeasonSowing, "Aussaat", storage.TaskTriggerRelativeToSowing, species.SowMonthFrom, species.SowDayFrom, species.SowMonthTo, species.SowDayTo},
{storage.TaskTemplateOriginSeasonPlanting, "Pflanzen", storage.TaskTriggerRelativeToSpeciesPlanting, species.PlantingMonthFrom, species.PlantingDayFrom, species.PlantingMonthTo, species.PlantingDayTo},
{storage.TaskTemplateOriginSeasonHarvest, "Ernten", storage.TaskTriggerRelativeToHarvest, species.HarvestMonthFrom, species.HarvestDayFrom, species.HarvestMonthTo, species.HarvestDayTo},
}
writeScope := gardenID
if species.GardenID == nil {
writeScope = 0
}
for _, definition := range definitions {
template, found := byOrigin[definition.origin]
if definition.monthFrom == nil {
if found && template.Active {
template.Active = false
if _, err = app.models.SpeciesTaskTemplates.Update(writeScope, template); err != nil {
return err
}
}
continue
}
if found {
// Preserve all user-editable fields. Only repair legacy generated templates.
if template.TriggerType != definition.trigger {
template.TriggerType = definition.trigger
if _, err = app.models.SpeciesTaskTemplates.Update(writeScope, template); err != nil {
return err
}
}
continue
}
duration := seasonDurationDays(definition.monthFrom, definition.dayFrom, definition.monthTo, definition.dayTo)
template = storage.SpeciesTaskTemplate{
SpeciesID: species.ID, Origin: definition.origin, Title: definition.title,
Description: definition.title + " im vorgesehenen Zeitraum", TriggerType: definition.trigger,
TriggerOffsetUnit: storage.TaskDurationDay, Duration: duration, DurationUnit: storage.TaskDurationDay,
Recurrence: storage.TaskRecurrenceNone, RecurrenceInterval: 1, Active: true,
}
if _, err = app.models.SpeciesTaskTemplates.Insert(template); err != nil && !errors.Is(err, storage.ErrConflict) {
return err
}
}
return nil
}
func seasonDurationDays(fromMonth, fromDay, toMonth, toDay *int) int {
if fromMonth == nil || toMonth == nil {
return 0
}
startDay, endDay := 1, 1
if fromDay != nil {
startDay = *fromDay
}
if toDay != nil {
endDay = *toDay
}
start := time.Date(2024, time.Month(*fromMonth), startDay, 0, 0, 0, 0, time.UTC)
end := time.Date(2024, time.Month(*toMonth), endDay, 0, 0, 0, 0, time.UTC)
if end.Before(start) {
end = end.AddDate(1, 0, 0)
}
return int(end.Sub(start).Hours() / 24)
}