From 483eb2772365879c6e29cf0874ebee704fb5d427 Mon Sep 17 00:00:00 2001 From: Pavel Date: Fri, 12 Jan 2024 16:46:36 +0300 Subject: [PATCH] add base logic for activate promo --- .../promocode/promocode_controller.go | 27 ++++++++++++ internal/models/bonus.go | 8 ++++ internal/repository/promocode_repository.go | 44 +++++++++++++++++++ internal/server/http/http_server.go | 1 + internal/services/promocode_service.go | 11 +++++ 5 files changed, 91 insertions(+) diff --git a/internal/controller/promocode/promocode_controller.go b/internal/controller/promocode/promocode_controller.go index 783d4ea..75fe521 100644 --- a/internal/controller/promocode/promocode_controller.go +++ b/internal/controller/promocode/promocode_controller.go @@ -83,3 +83,30 @@ func (p *PromoCodeController) GetList(c *fiber.Ctx) error { } return c.Status(fiber.StatusOK).JSON(resp) } + +func (p *PromoCodeController) Activate(c *fiber.Ctx) error { + var req models.ActivateReq + if err := c.BodyParser(&req); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request payload"}) + } + + if req.Codeword == "" { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "codeword is required"}) + } + + greetings, err := p.promoCodeService.ActivatePromo(c.Context(), &req) + if err != nil { + p.logger.Error("Failed to activate promocode", zap.Error(err)) + + if errors.Is(err, repository.ErrPromoCodeNotFound) { + return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "PromoCode not found"}) + } + + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"}) + } + + resp := models.ActivateResp{ + Greetings: greetings, + } + return c.Status(fiber.StatusOK).JSON(resp) +} diff --git a/internal/models/bonus.go b/internal/models/bonus.go index 7a4dc9e..4bec834 100644 --- a/internal/models/bonus.go +++ b/internal/models/bonus.go @@ -56,3 +56,11 @@ type GetPromoCodesListResp struct { Count int64 `json:"count"` // количество в выборке всего Items []PromoCode `json:"items"` // "страница" промокодов } + +type ActivateReq struct { + Codeword string `json:"codeword"` +} + +type ActivateResp struct { + Greetings string `json:"greetings"` // поле из активированного промокода +} diff --git a/internal/repository/promocode_repository.go b/internal/repository/promocode_repository.go index 83944ef..1e6fab5 100644 --- a/internal/repository/promocode_repository.go +++ b/internal/repository/promocode_repository.go @@ -185,3 +185,47 @@ func (r *PromoCodeRepository) GetPromoCodesList(ctx context.Context, req *models return promoCodes, count, nil } + +func (r *PromoCodeRepository) ActivatePromo(ctx context.Context, req *models.ActivateReq) (string, error) { + session, err := r.mdb.Database().Client().StartSession() + if err != nil { + return "", err + } + defer session.EndSession(ctx) + + var greetings string + + transactionErr := mongo.WithSession(ctx, session, func(sc mongo.SessionContext) error { + filter := bson.M{ + "codeword": req.Codeword, + "delete": false, + "outdated": false, + "offLimit": false, + "activationCount": bson.M{"$gt": 0}, + "dueTo": bson.M{"$gt": time.Now().Unix()}, + } + update := bson.M{ + "$inc": bson.M{"activationCount": -1}, + } + opts := options.FindOneAndUpdate().SetReturnDocument(options.After) + + var updatedPromoCode models.PromoCode + err := r.mdb.FindOneAndUpdate(sc, filter, update, opts).Decode(&updatedPromoCode) + if err != nil { + if err == mongo.ErrNoDocuments { + return ErrPromoCodeNotFound + } + return err + } + + greetings = updatedPromoCode.Greetings + + return nil + }) + + if transactionErr != nil { + return "", transactionErr + } + + return greetings, nil +} diff --git a/internal/server/http/http_server.go b/internal/server/http/http_server.go index 43e75cd..ce4a0c3 100644 --- a/internal/server/http/http_server.go +++ b/internal/server/http/http_server.go @@ -60,6 +60,7 @@ func (s *Server) registerRoutes() { s.app.Post("/promocode/create", s.PromoCodeController.CreatePromoCode) s.app.Put("/promocode/edit", s.PromoCodeController.EditPromoCode) s.app.Post("/promocode/getList", s.PromoCodeController.GetList) + s.app.Post("/promocode/activate", s.PromoCodeController.Activate) //... other } diff --git a/internal/services/promocode_service.go b/internal/services/promocode_service.go index 11cd344..a016f4a 100644 --- a/internal/services/promocode_service.go +++ b/internal/services/promocode_service.go @@ -10,6 +10,7 @@ type PromoCodeRepository interface { CreatePromoCode(ctx context.Context, req *models.PromoCode) (*models.PromoCode, error) EditPromoCode(ctx context.Context, req *models.ReqEditPromoCode) (*models.PromoCode, error) GetPromoCodesList(ctx context.Context, req *models.GetPromoCodesListReq) ([]models.PromoCode, int64, error) + ActivatePromo(ctx context.Context, req *models.ActivateReq) (string, error) } type PromoDeps struct { @@ -58,3 +59,13 @@ func (s *PromoCodeService) GetPromoCodesList(ctx context.Context, req *models.Ge return promoCodes, count, nil } + +func (s *PromoCodeService) ActivatePromo(ctx context.Context, req *models.ActivateReq) (string, error) { + greetings, err := s.promoCodeRepo.ActivatePromo(ctx, req) + if err != nil { + s.logger.Error("Failed to activate promocode", zap.Error(err)) + return "", err + } + + return greetings, nil +}