94 lines
3.2 KiB
Go
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)
|
|
}
|