From 401cc5330e6068919e1835be78bd97ece006332e Mon Sep 17 00:00:00 2001 From: Vojtech Mares Date: Sun, 5 May 2024 16:25:10 +0200 Subject: [PATCH] feat(server): bump generated api code and implement upcoming training date handlers --- internal/server/api.gen.go | 232 ++++++++++++++++++++++++++++++++----- internal/server/api.go | 64 ++++++++++ 2 files changed, 267 insertions(+), 29 deletions(-) diff --git a/internal/server/api.gen.go b/internal/server/api.gen.go index 50304fa..02a700c 100644 --- a/internal/server/api.gen.go +++ b/internal/server/api.gen.go @@ -46,9 +46,15 @@ type GetTrainingDateResponse = TrainingDate // GetTrainingResponse defines model for GetTrainingResponse. type GetTrainingResponse = Training +// ListAllUpcomingTrainingDatesResponse defines model for ListAllUpcomingTrainingDatesResponse. +type ListAllUpcomingTrainingDatesResponse = []TrainingDate + // ListTrainingDatesResponse defines model for ListTrainingDatesResponse. type ListTrainingDatesResponse = []TrainingDate +// ListTrainingUpcomingDatesResponse defines model for ListTrainingUpcomingDatesResponse. +type ListTrainingUpcomingDatesResponse = []TrainingDate + // ListTrainingsResponse defines model for ListTrainingsResponse. type ListTrainingsResponse = []Training @@ -175,6 +181,9 @@ type ServerInterface interface { // Create a new training // (POST /v1/trainings) CreateTraining(c *fiber.Ctx) error + // List all dates of a training + // (GET /v1/trainings/upcoming-dates) + ListAllUpcomingTrainingDates(c *fiber.Ctx) error // Delete a training by ID // (DELETE /v1/trainings/{trainingID}) DeleteTraining(c *fiber.Ctx, trainingID TrainingID) error @@ -199,6 +208,9 @@ type ServerInterface interface { // Update a training date by ID // (PUT /v1/trainings/{trainingID}/dates/{trainingDateID}) UpdateTrainingDate(c *fiber.Ctx, trainingID TrainingID, trainingDateID TrainingDateID) error + // List upcoming dates of a training + // (GET /v1/trainings/{trainingID}/upcoming-dates) + ListTrainingUpcomingDates(c *fiber.Ctx, trainingID TrainingID) error } // ServerInterfaceWrapper converts contexts to parameters. @@ -220,6 +232,12 @@ func (siw *ServerInterfaceWrapper) CreateTraining(c *fiber.Ctx) error { return siw.Handler.CreateTraining(c) } +// ListAllUpcomingTrainingDates operation middleware +func (siw *ServerInterfaceWrapper) ListAllUpcomingTrainingDates(c *fiber.Ctx) error { + + return siw.Handler.ListAllUpcomingTrainingDates(c) +} + // DeleteTraining operation middleware func (siw *ServerInterfaceWrapper) DeleteTraining(c *fiber.Ctx) error { @@ -372,6 +390,22 @@ func (siw *ServerInterfaceWrapper) UpdateTrainingDate(c *fiber.Ctx) error { return siw.Handler.UpdateTrainingDate(c, trainingID, trainingDateID) } +// ListTrainingUpcomingDates operation middleware +func (siw *ServerInterfaceWrapper) ListTrainingUpcomingDates(c *fiber.Ctx) error { + + var err error + + // ------------- Path parameter "trainingID" ------------- + var trainingID TrainingID + + err = runtime.BindStyledParameterWithOptions("simple", "trainingID", c.Params("trainingID"), &trainingID, runtime.BindStyledParameterOptions{Explode: false, Required: true}) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, fmt.Errorf("Invalid format for parameter trainingID: %w", err).Error()) + } + + return siw.Handler.ListTrainingUpcomingDates(c, trainingID) +} + // FiberServerOptions provides options for the Fiber server. type FiberServerOptions struct { BaseURL string @@ -397,6 +431,8 @@ func RegisterHandlersWithOptions(router fiber.Router, si ServerInterface, option router.Post(options.BaseURL+"/v1/trainings", wrapper.CreateTraining) + router.Get(options.BaseURL+"/v1/trainings/upcoming-dates", wrapper.ListAllUpcomingTrainingDates) + router.Delete(options.BaseURL+"/v1/trainings/:trainingID", wrapper.DeleteTraining) router.Get(options.BaseURL+"/v1/trainings/:trainingID", wrapper.GetTraining) @@ -413,6 +449,8 @@ func RegisterHandlersWithOptions(router fiber.Router, si ServerInterface, option router.Put(options.BaseURL+"/v1/trainings/:trainingID/dates/:trainingDateID", wrapper.UpdateTrainingDate) + router.Get(options.BaseURL+"/v1/trainings/:trainingID/upcoming-dates", wrapper.ListTrainingUpcomingDates) + } type InternalErrorApplicationProblemPlusJSONResponse ProblemDetails @@ -487,6 +525,44 @@ func (response CreateTraining500ApplicationProblemPlusJSONResponse) VisitCreateT return ctx.JSON(&response) } +type ListAllUpcomingTrainingDatesRequestObject struct { +} + +type ListAllUpcomingTrainingDatesResponseObject interface { + VisitListAllUpcomingTrainingDatesResponse(ctx *fiber.Ctx) error +} + +type ListAllUpcomingTrainingDates200JSONResponse ListAllUpcomingTrainingDatesResponse + +func (response ListAllUpcomingTrainingDates200JSONResponse) VisitListAllUpcomingTrainingDatesResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/json") + ctx.Status(200) + + return ctx.JSON(&response) +} + +type ListAllUpcomingTrainingDates404ApplicationProblemPlusJSONResponse struct { + NotFoundErrorApplicationProblemPlusJSONResponse +} + +func (response ListAllUpcomingTrainingDates404ApplicationProblemPlusJSONResponse) VisitListAllUpcomingTrainingDatesResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/problem+json") + ctx.Status(404) + + return ctx.JSON(&response) +} + +type ListAllUpcomingTrainingDates500ApplicationProblemPlusJSONResponse struct { + InternalErrorApplicationProblemPlusJSONResponse +} + +func (response ListAllUpcomingTrainingDates500ApplicationProblemPlusJSONResponse) VisitListAllUpcomingTrainingDatesResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/problem+json") + ctx.Status(500) + + return ctx.JSON(&response) +} + type DeleteTrainingRequestObject struct { TrainingID TrainingID `json:"trainingID"` } @@ -825,6 +901,45 @@ func (response UpdateTrainingDate500ApplicationProblemPlusJSONResponse) VisitUpd return ctx.JSON(&response) } +type ListTrainingUpcomingDatesRequestObject struct { + TrainingID TrainingID `json:"trainingID"` +} + +type ListTrainingUpcomingDatesResponseObject interface { + VisitListTrainingUpcomingDatesResponse(ctx *fiber.Ctx) error +} + +type ListTrainingUpcomingDates200JSONResponse ListTrainingUpcomingDatesResponse + +func (response ListTrainingUpcomingDates200JSONResponse) VisitListTrainingUpcomingDatesResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/json") + ctx.Status(200) + + return ctx.JSON(&response) +} + +type ListTrainingUpcomingDates404ApplicationProblemPlusJSONResponse struct { + NotFoundErrorApplicationProblemPlusJSONResponse +} + +func (response ListTrainingUpcomingDates404ApplicationProblemPlusJSONResponse) VisitListTrainingUpcomingDatesResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/problem+json") + ctx.Status(404) + + return ctx.JSON(&response) +} + +type ListTrainingUpcomingDates500ApplicationProblemPlusJSONResponse struct { + InternalErrorApplicationProblemPlusJSONResponse +} + +func (response ListTrainingUpcomingDates500ApplicationProblemPlusJSONResponse) VisitListTrainingUpcomingDatesResponse(ctx *fiber.Ctx) error { + ctx.Response().Header.Set("Content-Type", "application/problem+json") + ctx.Status(500) + + return ctx.JSON(&response) +} + // StrictServerInterface represents all server handlers. type StrictServerInterface interface { // List all trainings @@ -833,6 +948,9 @@ type StrictServerInterface interface { // Create a new training // (POST /v1/trainings) CreateTraining(ctx context.Context, request CreateTrainingRequestObject) (CreateTrainingResponseObject, error) + // List all dates of a training + // (GET /v1/trainings/upcoming-dates) + ListAllUpcomingTrainingDates(ctx context.Context, request ListAllUpcomingTrainingDatesRequestObject) (ListAllUpcomingTrainingDatesResponseObject, error) // Delete a training by ID // (DELETE /v1/trainings/{trainingID}) DeleteTraining(ctx context.Context, request DeleteTrainingRequestObject) (DeleteTrainingResponseObject, error) @@ -857,6 +975,9 @@ type StrictServerInterface interface { // Update a training date by ID // (PUT /v1/trainings/{trainingID}/dates/{trainingDateID}) UpdateTrainingDate(ctx context.Context, request UpdateTrainingDateRequestObject) (UpdateTrainingDateResponseObject, error) + // List upcoming dates of a training + // (GET /v1/trainings/{trainingID}/upcoming-dates) + ListTrainingUpcomingDates(ctx context.Context, request ListTrainingUpcomingDatesRequestObject) (ListTrainingUpcomingDatesResponseObject, error) } type StrictHandlerFunc func(ctx *fiber.Ctx, args interface{}) (interface{}, error) @@ -928,6 +1049,31 @@ func (sh *strictHandler) CreateTraining(ctx *fiber.Ctx) error { return nil } +// ListAllUpcomingTrainingDates operation middleware +func (sh *strictHandler) ListAllUpcomingTrainingDates(ctx *fiber.Ctx) error { + var request ListAllUpcomingTrainingDatesRequestObject + + handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { + return sh.ssi.ListAllUpcomingTrainingDates(ctx.UserContext(), request.(ListAllUpcomingTrainingDatesRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "ListAllUpcomingTrainingDates") + } + + response, err := handler(ctx, request) + + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } else if validResponse, ok := response.(ListAllUpcomingTrainingDatesResponseObject); ok { + if err := validResponse.VisitListAllUpcomingTrainingDatesResponse(ctx); err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + } else if response != nil { + return fmt.Errorf("unexpected response type: %T", response) + } + return nil +} + // DeleteTraining operation middleware func (sh *strictHandler) DeleteTraining(ctx *fiber.Ctx, trainingID TrainingID) error { var request DeleteTrainingRequestObject @@ -1165,38 +1311,66 @@ func (sh *strictHandler) UpdateTrainingDate(ctx *fiber.Ctx, trainingID TrainingI return nil } +// ListTrainingUpcomingDates operation middleware +func (sh *strictHandler) ListTrainingUpcomingDates(ctx *fiber.Ctx, trainingID TrainingID) error { + var request ListTrainingUpcomingDatesRequestObject + + request.TrainingID = trainingID + + handler := func(ctx *fiber.Ctx, request interface{}) (interface{}, error) { + return sh.ssi.ListTrainingUpcomingDates(ctx.UserContext(), request.(ListTrainingUpcomingDatesRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "ListTrainingUpcomingDates") + } + + response, err := handler(ctx, request) + + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } else if validResponse, ok := response.(ListTrainingUpcomingDatesResponseObject); ok { + if err := validResponse.VisitListTrainingUpcomingDatesResponse(ctx); err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + } else if response != nil { + return fmt.Errorf("unexpected response type: %T", response) + } + return nil +} + // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/server/api.go b/internal/server/api.go index 7754823..2746d68 100644 --- a/internal/server/api.go +++ b/internal/server/api.go @@ -380,3 +380,67 @@ func (h *APIHandlers) UpdateTrainingDate(ctx context.Context, req UpdateTraining }, }, nil } + +func (h *APIHandlers) ListAllUpcomingTrainingDates(ctx context.Context, req ListAllUpcomingTrainingDatesRequestObject) (ListAllUpcomingTrainingDatesResponseObject, error) { + trainingDates, err := h.trainingDateRepository.FindAllUpcoming() + if err != nil { + return ListAllUpcomingTrainingDates500ApplicationProblemPlusJSONResponse{ + InternalErrorApplicationProblemPlusJSONResponse: InternalErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusInternalServerError, + Title: "Internal Server Error: Failed to list upcoming training dates", + Detail: err.Error(), + }}, nil + } + + data := make([]TrainingDate, len(trainingDates)) + for idx, td := range trainingDates { + data[idx] = TrainingDate{ + Id: td.ID, + Date: td.Date, + StartTime: td.StartTime.Format(trainingDateStartTimeFormat), + Days: td.Days, + IsOnline: td.IsOnline, + Location: td.Location, + Address: td.Address, + Capacity: td.Capacity, + Price: TrainingDatePrice{ + Amount: td.Price.Amount, + Currency: td.Price.Currency, + }, + } + } + + return ListAllUpcomingTrainingDates200JSONResponse(data), nil +} + +func (h *APIHandlers) ListTrainingUpcomingDates(ctx context.Context, req ListTrainingUpcomingDatesRequestObject) (ListTrainingUpcomingDatesResponseObject, error) { + trainingDates, err := h.trainingDateRepository.FindUpcomingByTrainingID(req.TrainingID) + if err != nil { + return ListTrainingUpcomingDates500ApplicationProblemPlusJSONResponse{ + InternalErrorApplicationProblemPlusJSONResponse: InternalErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusInternalServerError, + Title: "Internal Server Error: Failed to list all upcoming training dates", + Detail: err.Error(), + }}, nil + } + + data := make([]TrainingDate, len(trainingDates)) + for idx, td := range trainingDates { + data[idx] = TrainingDate{ + Id: td.ID, + Date: td.Date, + StartTime: td.StartTime.Format(trainingDateStartTimeFormat), + Days: td.Days, + IsOnline: td.IsOnline, + Location: td.Location, + Address: td.Address, + Capacity: td.Capacity, + Price: TrainingDatePrice{ + Amount: td.Price.Amount, + Currency: td.Price.Currency, + }, + } + } + + return ListTrainingUpcomingDates200JSONResponse(data), nil +}