diff --git a/internal/server/api.go b/internal/server/api.go index 3cd5edf..ac1eda1 100644 --- a/internal/server/api.go +++ b/internal/server/api.go @@ -4,6 +4,7 @@ import ( "context" "errors" "github.com/oapi-codegen/runtime/types" + "github.com/shopspring/decimal" "time" "github.com/gofiber/fiber/v2" @@ -41,7 +42,7 @@ func (h *APIHandlers) ListTrainings(ctx context.Context, req ListTrainingsReques pricing := make([]TrainingPrice, len(t.Pricing)) for idx, p := range t.Pricing { pricing[idx] = TrainingPrice{ - Amount: p.Amount, + Amount: p.Amount.String(), Currency: p.Currency, Type: TrainingPriceType(p.Type), } @@ -61,8 +62,18 @@ func (h *APIHandlers) ListTrainings(ctx context.Context, req ListTrainingsReques func (h *APIHandlers) CreateTraining(ctx context.Context, req CreateTrainingRequestObject) (CreateTrainingResponseObject, error) { pricing := make([]training.TrainingPrice, len(req.Body.Pricing)) for idx, p := range req.Body.Pricing { + amount, err := decimal.NewFromString(p.Amount) + if err != nil { + return CreateTraining400ApplicationProblemPlusJSONResponse{ + InvalidInputErrorApplicationProblemPlusJSONResponse: InvalidInputErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusBadRequest, + Title: "Invalid Input: Invalid amount", + Detail: err.Error(), + }}, nil + } + pricing[idx] = training.TrainingPrice{ - Amount: p.Amount, + Amount: amount, Currency: p.Currency, Type: training.TrainingPriceType(p.Type), } @@ -88,7 +99,7 @@ func (h *APIHandlers) CreateTraining(ctx context.Context, req CreateTrainingRequ responsePricing := make([]TrainingPrice, len(t.Pricing)) for idx, p := range t.Pricing { responsePricing[idx] = TrainingPrice{ - Amount: p.Amount, + Amount: p.Amount.String(), Currency: p.Currency, Type: TrainingPriceType(p.Type), } @@ -143,7 +154,7 @@ func (h *APIHandlers) GetTraining(ctx context.Context, req GetTrainingRequestObj pricing := make([]TrainingPrice, len(t.Pricing)) for idx, p := range t.Pricing { pricing[idx] = TrainingPrice{ - Amount: p.Amount, + Amount: p.Amount.String(), Currency: p.Currency, Type: TrainingPriceType(p.Type), } @@ -160,8 +171,18 @@ func (h *APIHandlers) GetTraining(ctx context.Context, req GetTrainingRequestObj func (h *APIHandlers) UpdateTraining(ctx context.Context, req UpdateTrainingRequestObject) (UpdateTrainingResponseObject, error) { pricing := make([]training.TrainingPrice, len(req.Body.Pricing)) for idx, p := range req.Body.Pricing { + amount, err := decimal.NewFromString(p.Amount) + if err != nil { + return UpdateTraining400ApplicationProblemPlusJSONResponse{ + InvalidInputErrorApplicationProblemPlusJSONResponse: InvalidInputErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusBadRequest, + Title: "Invalid Input: Invalid amount", + Detail: err.Error(), + }}, nil + } + pricing[idx] = training.TrainingPrice{ - Amount: p.Amount, + Amount: amount, Currency: p.Currency, Type: training.TrainingPriceType(p.Type), } @@ -217,7 +238,7 @@ func (h *APIHandlers) ListTrainingDates(ctx context.Context, req ListTrainingDat Address: td.Address, Capacity: td.Capacity, Price: Price{ - Amount: td.Price.Amount, + Amount: td.Price.Amount.String(), Currency: td.Price.Currency, }, } @@ -227,8 +248,18 @@ func (h *APIHandlers) ListTrainingDates(ctx context.Context, req ListTrainingDat } func (h *APIHandlers) CreateTrainingDate(ctx context.Context, req CreateTrainingDateRequestObject) (CreateTrainingDateResponseObject, error) { + amount, err := decimal.NewFromString(req.Body.Price.Amount) + if err != nil { + return CreateTrainingDate400ApplicationProblemPlusJSONResponse{ + InvalidInputErrorApplicationProblemPlusJSONResponse: InvalidInputErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusBadRequest, + Title: "Invalid Input: Invalid amount", + Detail: err.Error(), + }}, nil + } + price := money.Price{ - Amount: req.Body.Price.Amount, + Amount: amount, Currency: req.Body.Price.Currency, } @@ -273,7 +304,7 @@ func (h *APIHandlers) CreateTrainingDate(ctx context.Context, req CreateTraining Address: td.Address, Capacity: td.Capacity, Price: Price{ - Amount: td.Price.Amount, + Amount: td.Price.Amount.String(), Currency: td.Price.Currency, }, }, nil @@ -326,15 +357,25 @@ func (h *APIHandlers) GetTrainingDate(ctx context.Context, req GetTrainingDateRe Address: td.Address, Capacity: td.Capacity, Price: Price{ - Amount: td.Price.Amount, + Amount: td.Price.Amount.String(), Currency: td.Price.Currency, }, }, nil } func (h *APIHandlers) UpdateTrainingDate(ctx context.Context, req UpdateTrainingDateRequestObject) (UpdateTrainingDateResponseObject, error) { + amount, err := decimal.NewFromString(req.Body.Price.Amount) + if err != nil { + return UpdateTrainingDate400ApplicationProblemPlusJSONResponse{ + InvalidInputErrorApplicationProblemPlusJSONResponse: InvalidInputErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusBadRequest, + Title: "Invalid Input: Invalid amount", + Detail: err.Error(), + }}, nil + } + price := money.Price{ - Amount: req.Body.Price.Amount, + Amount: amount, Currency: req.Body.Price.Currency, } @@ -380,7 +421,7 @@ func (h *APIHandlers) UpdateTrainingDate(ctx context.Context, req UpdateTraining Address: td.Address, Capacity: td.Capacity, Price: Price{ - Amount: td.Price.Amount, + Amount: td.Price.Amount.String(), Currency: td.Price.Currency, }, }, nil @@ -422,7 +463,7 @@ func (h *APIHandlers) ListAllUpcomingTrainingDates(ctx context.Context, req List Address: td.Address, Capacity: td.Capacity, Price: Price{ - Amount: td.Price.Amount, + Amount: td.Price.Amount.String(), Currency: td.Price.Currency, }, } @@ -455,7 +496,7 @@ func (h *APIHandlers) ListTrainingUpcomingDates(ctx context.Context, req ListTra Address: td.Address, Capacity: td.Capacity, Price: Price{ - Amount: td.Price.Amount, + Amount: td.Price.Amount.String(), Currency: td.Price.Currency, }, } @@ -487,11 +528,55 @@ func (h *APIHandlers) ListTrainingDateAttendees(ctx context.Context, req ListTra } func (h *APIHandlers) CreateTrainingDateAttendee(ctx context.Context, req CreateTrainingDateAttendeeRequestObject) (CreateTrainingDateAttendeeResponseObject, error) { - ta := training.TrainingDateAttendee{ - Name: req.Body.Name, + _, err := h.trainingRepository.FindByID(req.TrainingID) + if err != nil { + if errors.Is(err, training.ErrTrainingNotFound) { + return CreateTrainingDateAttendee404ApplicationProblemPlusJSONResponse{ + NotFoundErrorApplicationProblemPlusJSONResponse: NotFoundErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusNotFound, + Title: "Not Found: Training not found", + }}, nil + } else { + return CreateTrainingDateAttendee500ApplicationProblemPlusJSONResponse{ + InternalErrorApplicationProblemPlusJSONResponse: InternalErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusInternalServerError, + Title: "Internal Server Error: Failed to get training", + Detail: err.Error(), + }}, nil + } } - err := h.trainingDateAttendeeRepository.Create(req.TrainingDateID, &ta) + td, err := h.trainingDateRepository.FindByID(req.TrainingDateID) + if err != nil { + if errors.Is(err, training.ErrTrainingDateNotFound) { + return CreateTrainingDateAttendee404ApplicationProblemPlusJSONResponse{ + NotFoundErrorApplicationProblemPlusJSONResponse: NotFoundErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusNotFound, + Title: "Not Found: Training date not found", + }}, nil + } else { + return CreateTrainingDateAttendee500ApplicationProblemPlusJSONResponse{ + InternalErrorApplicationProblemPlusJSONResponse: InternalErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusInternalServerError, + Title: "Internal Server Error: Failed to get training date", + Detail: err.Error(), + }}, nil + } + } + + ta := training.TrainingDateAttendee{ + Name: req.Body.Name, + Email: string(req.Body.Email), + Phone: req.Body.Phone, + Company: req.Body.Company, + Position: req.Body.Position, + IsStudent: *req.Body.IsStudent, + HasPaid: false, + HasAttended: false, + Bill: td.Price, + } + + err = h.trainingDateAttendeeRepository.Create(req.TrainingDateID, &ta) if err != nil { return CreateTrainingDateAttendee500ApplicationProblemPlusJSONResponse{ InternalErrorApplicationProblemPlusJSONResponse: InternalErrorApplicationProblemPlusJSONResponse{ @@ -511,6 +596,10 @@ func (h *APIHandlers) CreateTrainingDateAttendee(ctx context.Context, req Create IsStudent: &ta.IsStudent, HasAttended: ta.HasAttended, HasPaid: ta.HasPaid, + Bill: Price{ + Amount: ta.Bill.Amount.String(), + Currency: ta.Bill.Currency, + }, }, nil } @@ -551,6 +640,42 @@ func (h *APIHandlers) DeleteTrainingDateAttendee(ctx context.Context, req Delete } func (h *APIHandlers) GetTrainingDateAttendee(ctx context.Context, req GetTrainingDateAttendeeRequestObject) (GetTrainingDateAttendeeResponseObject, error) { + _, err := h.trainingRepository.FindByID(req.TrainingID) + if err != nil { + if errors.Is(err, training.ErrTrainingNotFound) { + return GetTrainingDateAttendee404ApplicationProblemPlusJSONResponse{ + NotFoundErrorApplicationProblemPlusJSONResponse: NotFoundErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusNotFound, + Title: "Not Found: Training not found", + }}, nil + } else { + return GetTrainingDateAttendee500ApplicationProblemPlusJSONResponse{ + InternalErrorApplicationProblemPlusJSONResponse: InternalErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusInternalServerError, + Title: "Internal Server Error: Failed to get training", + Detail: err.Error(), + }}, nil + } + } + + _, err = h.trainingDateRepository.FindByID(req.TrainingDateID) + if err != nil { + if errors.Is(err, training.ErrTrainingDateNotFound) { + return GetTrainingDateAttendee404ApplicationProblemPlusJSONResponse{ + NotFoundErrorApplicationProblemPlusJSONResponse: NotFoundErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusNotFound, + Title: "Not Found: Training date not found", + }}, nil + } else { + return GetTrainingDateAttendee500ApplicationProblemPlusJSONResponse{ + InternalErrorApplicationProblemPlusJSONResponse: InternalErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusInternalServerError, + Title: "Internal Server Error: Failed to get training date", + Detail: err.Error(), + }}, nil + } + } + ta, err := h.trainingDateAttendeeRepository.FindByID(req.TrainingDateAttendeeID) if errors.Is(err, training.ErrTrainingDateAttendeeNotFound) { return GetTrainingDateAttendee404ApplicationProblemPlusJSONResponse{ @@ -577,16 +702,76 @@ func (h *APIHandlers) GetTrainingDateAttendee(ctx context.Context, req GetTraini IsStudent: &ta.IsStudent, HasAttended: ta.HasAttended, HasPaid: ta.HasPaid, + Bill: Price{ + Amount: ta.Bill.Amount.String(), + Currency: ta.Bill.Currency, + }, }, nil } func (h *APIHandlers) UpdateTrainingDateAttendee(ctx context.Context, req UpdateTrainingDateAttendeeRequestObject) (UpdateTrainingDateAttendeeResponseObject, error) { - ta := training.TrainingDateAttendee{ - ID: req.TrainingDateAttendeeID, - Name: req.Body.Name, + _, err := h.trainingRepository.FindByID(req.TrainingID) + if err != nil { + if errors.Is(err, training.ErrTrainingNotFound) { + return UpdateTrainingDateAttendee404ApplicationProblemPlusJSONResponse{ + NotFoundErrorApplicationProblemPlusJSONResponse: NotFoundErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusNotFound, + Title: "Not Found: Training not found", + }}, nil + } else { + return UpdateTrainingDateAttendee500ApplicationProblemPlusJSONResponse{ + InternalErrorApplicationProblemPlusJSONResponse: InternalErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusInternalServerError, + Title: "Internal Server Error: Failed to get training", + Detail: err.Error(), + }}, nil + } } - err := h.trainingDateAttendeeRepository.Update(&ta) + _, err = h.trainingDateRepository.FindByID(req.TrainingDateID) + if err != nil { + if errors.Is(err, training.ErrTrainingDateNotFound) { + return UpdateTrainingDateAttendee404ApplicationProblemPlusJSONResponse{ + NotFoundErrorApplicationProblemPlusJSONResponse: NotFoundErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusNotFound, + Title: "Not Found: Training date not found", + }}, nil + } else { + return UpdateTrainingDateAttendee500ApplicationProblemPlusJSONResponse{ + InternalErrorApplicationProblemPlusJSONResponse: InternalErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusInternalServerError, + Title: "Internal Server Error: Failed to get training date", + Detail: err.Error(), + }}, nil + } + } + + ta, err := h.trainingDateAttendeeRepository.FindByID(req.TrainingDateAttendeeID) + if err != nil { + if errors.Is(err, training.ErrTrainingDateAttendeeNotFound) { + return UpdateTrainingDateAttendee404ApplicationProblemPlusJSONResponse{ + NotFoundErrorApplicationProblemPlusJSONResponse: NotFoundErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusNotFound, + Title: "Not Found: Training date attendee not found", + }}, nil + } else { + return UpdateTrainingDateAttendee500ApplicationProblemPlusJSONResponse{ + InternalErrorApplicationProblemPlusJSONResponse: InternalErrorApplicationProblemPlusJSONResponse{ + Status: fiber.StatusInternalServerError, + Title: "Internal Server Error: Failed to get training date attendee", + Detail: err.Error(), + }}, nil + } + } + + ta.Name = req.Body.Name + ta.Email = string(req.Body.Email) + ta.Phone = req.Body.Phone + ta.Company = req.Body.Company + ta.Position = req.Body.Position + ta.IsStudent = *req.Body.IsStudent + + err = h.trainingDateAttendeeRepository.Update(ta) if err != nil { return UpdateTrainingDateAttendee500ApplicationProblemPlusJSONResponse{ InternalErrorApplicationProblemPlusJSONResponse: InternalErrorApplicationProblemPlusJSONResponse{ @@ -606,5 +791,9 @@ func (h *APIHandlers) UpdateTrainingDateAttendee(ctx context.Context, req Update IsStudent: &ta.IsStudent, HasAttended: ta.HasAttended, HasPaid: ta.HasPaid, + Bill: Price{ + Amount: ta.Bill.Amount.String(), + Currency: ta.Bill.Currency, + }, }, nil }