release: v0.1 #7
@ -83,6 +83,7 @@ func getVerbs(ctx context.Context, config *AppConfig) (commands []*cobra.Command
|
|||||||
Use: r.Name,
|
Use: r.Name,
|
||||||
Aliases: r.Aliases,
|
Aliases: r.Aliases,
|
||||||
Short: r.Description,
|
Short: r.Description,
|
||||||
|
Args: cobra.MaximumNArgs(1),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
// Configure log
|
// Configure log
|
||||||
var logLevel = slog.LevelWarn
|
var logLevel = slog.LevelWarn
|
||||||
@ -120,6 +121,7 @@ func getVerbs(ctx context.Context, config *AppConfig) (commands []*cobra.Command
|
|||||||
param.Description,
|
param.Description,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
verbCommand.AddCommand(resourceCommand)
|
verbCommand.AddCommand(resourceCommand)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package meals
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.bissendorf.co/bissendorf/unifood/m/v2/core/handler"
|
"git.bissendorf.co/bissendorf/unifood/m/v2/core/handler"
|
||||||
@ -22,47 +24,68 @@ type MealsHandler struct {
|
|||||||
|
|
||||||
func (h *MealsHandler) Get(ctx context.Context, name string, params params.Container) (*interfaces.ResourceList, error) {
|
func (h *MealsHandler) Get(ctx context.Context, name string, params params.Container) (*interfaces.ResourceList, error) {
|
||||||
// Read parameters
|
// Read parameters
|
||||||
p, err := params.GetValue(handler.ParamDate)
|
date, err := params.GetValue(handler.ParamDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to parse date parameter: %w", err)
|
return nil, fmt.Errorf("unable to parse date parameter: %w", err)
|
||||||
}
|
}
|
||||||
date := p.(time.Time)
|
|
||||||
|
|
||||||
location, err := params.GetValue(handler.ParamLocation)
|
restaurant, err := params.GetValue(handler.ParamRestaurant)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to parse location parameter: %w", err)
|
return nil, fmt.Errorf("unable to parse restaurant parameter: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build query
|
// Build query
|
||||||
query := fmt.Sprintf(
|
query := "page('meals').children.filterBy('printonly', 0)"
|
||||||
`page('meals').children.filterBy('location', '%s').filterBy('date', '%s').filterBy('printonly', 0)`,
|
if date != "" {
|
||||||
location,
|
parsed, err := time.Parse(time.DateOnly, date.(string))
|
||||||
date.Format(time.DateOnly),
|
if err != nil {
|
||||||
)
|
return nil, fmt.Errorf("unable to parse date parameter: %w", err)
|
||||||
|
}
|
||||||
|
query += fmt.Sprintf(".filterBy('date', '%s')", parsed.Format(time.DateOnly))
|
||||||
|
}
|
||||||
|
if restaurant != "" {
|
||||||
|
query += fmt.Sprintf(".filterBy('location', '%s')", restaurant.(string))
|
||||||
|
}
|
||||||
|
if name != "" {
|
||||||
|
query += fmt.Sprintf(".filterBy('id', 'meals/%s')", name)
|
||||||
|
}
|
||||||
|
|
||||||
// Run query
|
// Run query
|
||||||
meals, err := h.QueryClient.Get(ctx,
|
meals, err := h.QueryClient.Get(ctx,
|
||||||
query,
|
query,
|
||||||
`{"title":true,"ingredients":"page.ingredients.toObject","prices":"page.prices.toObject","location":true,"counter":true,"date":true,"mealadds":true,"mark":true,"frei3":true,"printonly":true,"kombicategory":true,"categories":"page.categories.split"}`,
|
`{"title":true,"id":"page.id","ingredients":"page.ingredients.toObject","prices":"page.prices.toObject","location":true,"counter":true,"date":true,"mealadds":true,"mark":true,"frei3":true,"printonly":true,"kombicategory":true,"categories":"page.categories.split"}`,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("querying menu failed: %w", err)
|
return nil, fmt.Errorf("querying menu failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transform to meal resource
|
||||||
|
items := util.Transform(*meals, func(i *stwbremen.Meal) *resources.Meal {
|
||||||
|
d, err := resources.MealFromDTO(*i)
|
||||||
|
if err != nil {
|
||||||
|
return &resources.Meal{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return d
|
||||||
|
})
|
||||||
|
|
||||||
|
// Sort by date, restaurant and title - need to apply stable sorts in reverse order to achieve this
|
||||||
|
slices.SortFunc(items, func(a, b *resources.Meal) int {
|
||||||
|
return strings.Compare(a.Title, b.Title)
|
||||||
|
})
|
||||||
|
slices.SortStableFunc(items, func(a, b *resources.Meal) int {
|
||||||
|
return strings.Compare(a.RestaurantID, b.RestaurantID)
|
||||||
|
})
|
||||||
|
slices.SortStableFunc(items, func(a, b *resources.Meal) int {
|
||||||
|
return a.Date.Compare(b.Date)
|
||||||
|
})
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
return &interfaces.ResourceList{
|
return &interfaces.ResourceList{
|
||||||
ItemKind: resources.ResourceMeal,
|
ItemKind: resources.ResourceMeal,
|
||||||
Items: util.Transform(*meals, func(i *stwbremen.Meal) interfaces.Resource {
|
Items: util.Transform(items, func(i **resources.Meal) interfaces.Resource { return *i }),
|
||||||
d, err := resources.MealFromDTO(*i)
|
|
||||||
if err != nil {
|
|
||||||
return &resources.Meal{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return d
|
|
||||||
}),
|
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *MealsHandler) GetParametersForVerb(verb interfaces.Verb) []params.Registration {
|
func (h *MealsHandler) GetParametersForVerb(verb interfaces.Verb) []params.Registration {
|
||||||
@ -71,14 +94,14 @@ func (h *MealsHandler) GetParametersForVerb(verb interfaces.Verb) []params.Regis
|
|||||||
Name: handler.ParamDate,
|
Name: handler.ParamDate,
|
||||||
ShortHand: "d",
|
ShortHand: "d",
|
||||||
Description: "Meal date",
|
Description: "Meal date",
|
||||||
DefaultFunc: func() string { return time.Now().Format(time.DateOnly) },
|
DefaultFunc: func() string { return "" },
|
||||||
ParseFunc: func(value string) (any, error) { return time.Parse(time.DateOnly, value) },
|
ParseFunc: params.ParseString,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: handler.ParamLocation,
|
Name: handler.ParamRestaurant,
|
||||||
ShortHand: "l",
|
ShortHand: "r",
|
||||||
Description: "Select a restaurant",
|
Description: "Select a restaurant",
|
||||||
DefaultFunc: func() string { return "330" },
|
DefaultFunc: func() string { return "" },
|
||||||
ParseFunc: params.ParseString,
|
ParseFunc: params.ParseString,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ParamDate string = "date"
|
ParamDate string = "date"
|
||||||
ParamLocation string = "location"
|
ParamRestaurant string = "restaurant"
|
||||||
)
|
)
|
||||||
|
|||||||
1
model/external/stwbremen/meal.go
vendored
1
model/external/stwbremen/meal.go
vendored
@ -2,6 +2,7 @@ package stwbremen
|
|||||||
|
|
||||||
type Meal struct {
|
type Meal struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
|
ID string `json:"id"`
|
||||||
Ingredients []Ingredient `json:"ingredients"`
|
Ingredients []Ingredient `json:"ingredients"`
|
||||||
Prices []Price `json:"prices"`
|
Prices []Price `json:"prices"`
|
||||||
Location string `json:"location"`
|
Location string `json:"location"`
|
||||||
|
|||||||
@ -16,12 +16,15 @@ func MealFromDTO(meal stwbremen.Meal) (*Meal, error) {
|
|||||||
return nil, fmt.Errorf("unable to parse meal date: %w", err)
|
return nil, fmt.Errorf("unable to parse meal date: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
id, _ := strings.CutPrefix(meal.ID, "meals/")
|
||||||
|
|
||||||
return &Meal{
|
return &Meal{
|
||||||
Title: meal.Title,
|
Title: meal.Title,
|
||||||
Location: meal.Location,
|
RestaurantID: meal.Location,
|
||||||
Date: date,
|
ID: id,
|
||||||
Tags: strings.Split(strings.Replace(meal.Tags, " ", "", -1), ","),
|
Date: date,
|
||||||
Counter: meal.Counter,
|
Tags: strings.Split(strings.Replace(meal.Tags, " ", "", -1), ","),
|
||||||
|
Counter: meal.Counter,
|
||||||
Prices: util.Map(meal.Prices, func(i *stwbremen.Price) (string, float32) {
|
Prices: util.Map(meal.Prices, func(i *stwbremen.Price) (string, float32) {
|
||||||
p, err := strconv.ParseFloat(strings.Trim(i.Price, " "), 32)
|
p, err := strconv.ParseFloat(strings.Trim(i.Price, " "), 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -41,13 +44,14 @@ func MealFromDTO(meal stwbremen.Meal) (*Meal, error) {
|
|||||||
const ResourceMeal = "meal"
|
const ResourceMeal = "meal"
|
||||||
|
|
||||||
type Meal struct {
|
type Meal struct {
|
||||||
Title string
|
Title string
|
||||||
Location string
|
ID string
|
||||||
Ingredients []ingredient
|
RestaurantID string
|
||||||
Prices map[string]float32
|
Ingredients []ingredient
|
||||||
Date time.Time
|
Prices map[string]float32
|
||||||
Counter string
|
Date time.Time
|
||||||
Tags []string
|
Counter string
|
||||||
|
Tags []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ingredient struct {
|
type ingredient struct {
|
||||||
@ -56,10 +60,12 @@ type ingredient struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Meal) Kind() string { return ResourceMeal }
|
func (d *Meal) Kind() string { return ResourceMeal }
|
||||||
func (d *Meal) ItemName() string { return d.Title }
|
func (d *Meal) ItemName() string { return d.ID }
|
||||||
|
|
||||||
// Table output
|
// Table output
|
||||||
func (d *Meal) ColumnNames() []string { return []string{"Location", "Date", "Counter", "Price"} }
|
func (d *Meal) ColumnNames() []string {
|
||||||
func (d *Meal) Columns() []any {
|
return []string{"Date", "Restaurant", "Title", "Counter", "Price"}
|
||||||
return []any{d.Location, d.Date.Format(time.DateOnly), d.Counter, d.Prices["Studierende"]}
|
}
|
||||||
|
func (d *Meal) Columns() []any {
|
||||||
|
return []any{d.Date.Format(time.DateOnly), d.RestaurantID, d.Title, d.Counter, d.Prices["Studierende"]}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user