yoake/internal/health/api_compliance.go

182 lines
4.3 KiB
Go

package health
import (
"fmt"
"sync"
"time"
"github.com/eternal-flame-AD/yoake/internal/db"
"github.com/eternal-flame-AD/yoake/internal/echoerror"
"github.com/eternal-flame-AD/yoake/internal/util"
"github.com/labstack/echo/v4"
)
const yearAbsZero = 2000
func RESTComplianceLogGet(database db.DB) func(c echo.Context) error {
return func(c echo.Context) error {
filterKeyname := c.Param("med")
from := c.QueryParam("from")
to := c.QueryParam("to")
if to == "" {
to = time.Now().Format("2006-01-02")
}
if from == "" {
from = time.Now().AddDate(0, 0, -30).Format("2006-01-02")
}
fromTime, err := time.Parse("2006-01-02", from)
if err != nil {
return echoerror.NewHttp(400, err)
}
toTime, err := time.Parse("2006-01-02", to)
if err != nil {
return echoerror.NewHttp(400, err)
}
period := util.NewDateRange(fromTime, toTime)
if days := period.Days(); days > 180 {
return echoerror.NewHttp(400, fmt.Errorf("invalid date range: %v", period))
}
logs, err := DBMedComplianceLogGet(database, period)
if db.IsNotFound(err) || logs == nil {
return c.JSON(200, ComplianceLogList{})
} else if err != nil {
return echoerror.NewHttp(500, err)
}
if filterKeyname != "" {
filtered := make(ComplianceLogList, 0, len(logs))
for _, log := range logs {
if log.MedKeyname == filterKeyname {
filtered = append(filtered, log)
}
}
logs = filtered
}
return c.JSON(200, logs)
}
}
func RESTComplianceLogPost(db db.DB, writeMutex *sync.Mutex) echo.HandlerFunc {
return func(c echo.Context) error {
var input ComplianceLog
if err := c.Bind(&input); err != nil {
return echoerror.NewHttp(400, err)
}
if input.Actual.Time.IsZero() {
return echoerror.NewHttp(400, fmt.Errorf("invalid date"))
}
writeMutex.Lock()
defer writeMutex.Unlock()
meds, err := DBMedListGet(db)
if err != nil {
return echoerror.NewHttp(500, err)
}
var dir *Direction
for _, med := range meds {
d := med
if med.KeyName() == input.MedKeyname {
dir = &d
} else if med.Name == input.MedKeyname {
input.MedKeyname = med.KeyName()
dir = &d
}
}
if dir == nil {
return echoerror.NewHttp(404, fmt.Errorf("med not found"))
}
if err := DBMedComplianceLogSetOne(db, *dir, &input); err != nil {
return err
}
if input.Actual.Dose <= 0 {
return c.NoContent(204)
}
return c.JSON(200, input)
}
}
func RESTComplianceLogProjectMed(db db.DB) func(c echo.Context) error {
return func(c echo.Context) error {
keyName := c.Param("med")
meds, err := DBMedListGet(db)
if err != nil {
return echoerror.NewHttp(500, err)
}
var dir *Direction
for _, med := range meds {
if med.KeyName() == keyName {
d := med
dir = &d
}
}
if dir == nil {
return echoerror.NewHttp(404, fmt.Errorf("med not found"))
}
complianceLog, err := DBMedComplianceLogGet(db, util.DateRangeAround(time.Now(), 1))
if err != nil {
return echoerror.NewHttp(500, err)
}
return c.JSON(200, complianceLog.ProjectNextDose(*dir))
}
}
func RESTRecalcMedComplianceLog(db db.DB, writeMutex *sync.Mutex) func(c echo.Context) error {
return func(c echo.Context) error {
meds, err := DBMedListGet(db)
if err != nil {
return echoerror.NewHttp(500, err)
}
from := time.Date(yearAbsZero, 1, 1, 0, 0, 0, 0, time.UTC)
to := time.Now()
if fromStr := c.QueryParam("from"); fromStr != "" {
from, err = time.Parse("2006-01", fromStr)
if err != nil {
return echoerror.NewHttp(400, err)
}
}
if toStr := c.QueryParam("to"); toStr != "" {
to, err = time.Parse("2006-01", toStr)
if err != nil {
return echoerror.NewHttp(400, err)
}
}
writeMutex.Lock()
defer writeMutex.Unlock()
for year := from.Year(); year <= to.Year(); year++ {
for month := 1; month <= 12; month++ {
if year == from.Year() && month < int(from.Month()) {
continue
}
if year == to.Year() && month > int(to.Month()) {
continue
}
log, err := DBMedComplianceLogGet(db, util.DateRangeAround(time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC), 1))
if err != nil {
return echoerror.NewHttp(500, err)
}
if len(log) == 0 {
continue
}
for _, dir := range meds {
log.UpdateDoseOffset(dir)
}
if err := DBMedComplianceLogAppend(db, log); err != nil {
return echoerror.NewHttp(500, err)
}
}
}
return c.NoContent(204)
}
}