57 lines
1.8 KiB
Go
57 lines
1.8 KiB
Go
package handlers
|
||
|
||
import (
|
||
"net/http"
|
||
"slices"
|
||
"time"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
// Фильтры списков, которым нужна проверка значения до ухода в SQL.
|
||
|
||
// checkFilter — сверяет ?param= со списком допустимых значений.
|
||
// Плохое значение — 400 с именем параметра, а не пустой список:
|
||
// «введено что-то не то» и «таких записей нет» — разные вещи.
|
||
func checkFilter(c *gin.Context, param string, allowed []string) bool {
|
||
v := c.Query(param)
|
||
if v == "" || slices.Contains(allowed, v) {
|
||
return true
|
||
}
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid " + param})
|
||
return false
|
||
}
|
||
|
||
// dateRange разбирает date_from/date_to в формате YYYY-MM-DD (даты
|
||
// по created_at). Верхняя граница сдвигается на сутки: date_to=2026-10-01
|
||
// означает «весь день 1 октября», а не «до полуночи 30 сентября».
|
||
func dateRange(c *gin.Context) (from, to *time.Time, ok bool) {
|
||
parse := func(param string, end bool) (*time.Time, bool) {
|
||
v := c.Query(param)
|
||
if v == "" {
|
||
return nil, true
|
||
}
|
||
d, err := time.Parse("2006-01-02", v)
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid " + param})
|
||
return nil, false
|
||
}
|
||
if end {
|
||
d = d.AddDate(0, 0, 1) // верхняя граница исключительная
|
||
}
|
||
return &d, true
|
||
}
|
||
|
||
if from, ok = parse("date_from", false); !ok {
|
||
return nil, nil, false
|
||
}
|
||
if to, ok = parse("date_to", true); !ok {
|
||
return nil, nil, false
|
||
}
|
||
if from != nil && to != nil && !to.After(*from) {
|
||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid date range"})
|
||
return nil, nil, false
|
||
}
|
||
return from, to, true
|
||
}
|