Merge branch 'dev' into 'staging'
Мягкое удаление промокода и Черновик активации промокода See merge request pena-services/codeword!12
This commit is contained in:
commit
05a6f48d45
@ -193,6 +193,70 @@ paths:
|
|||||||
'500':
|
'500':
|
||||||
description: Внутренняя ошибка сервера
|
description: Внутренняя ошибка сервера
|
||||||
|
|
||||||
|
/promocode/activate:
|
||||||
|
post:
|
||||||
|
summary: Активировать промокод
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ActivateReq'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Промокод успешно активирован
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ActivateResp'
|
||||||
|
'400':
|
||||||
|
description: Невалидный запрос или отсутствует обязательное поле codeword
|
||||||
|
'404':
|
||||||
|
description: Промокод не найден
|
||||||
|
'500':
|
||||||
|
description: Внутренняя ошибка сервера
|
||||||
|
|
||||||
|
/promocode/{promocodeID}:
|
||||||
|
delete:
|
||||||
|
summary: Мягко удалить промокод по его id
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: promocodeID
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Id промокода для удаления
|
||||||
|
responses:
|
||||||
|
'204':
|
||||||
|
description: Промокод успешно помечен как удаленный
|
||||||
|
'400':
|
||||||
|
description: Неверный запрос, отсутствует идентификатор промокода
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
'404':
|
||||||
|
description: Промокод не найден
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
'500':
|
||||||
|
description: Внутренняя ошибка сервера
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
@ -387,3 +451,19 @@ components:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/PromoCodeResponse'
|
$ref: '#/components/schemas/PromoCodeResponse'
|
||||||
|
|
||||||
|
ActivateReq:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- codeword
|
||||||
|
properties:
|
||||||
|
codeword:
|
||||||
|
type: string
|
||||||
|
description: Кодовое слово промокода, которое требуется активировать
|
||||||
|
|
||||||
|
ActivateResp:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
greetings:
|
||||||
|
type: string
|
||||||
|
description: Поле из активированного промокода
|
@ -82,3 +82,51 @@ func (p *PromoCodeController) GetList(c *fiber.Ctx) error {
|
|||||||
Items: promoCodes,
|
Items: promoCodes,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PromoCodeController) Delete(c *fiber.Ctx) error {
|
||||||
|
promoCodeID := c.Params("promocodeID")
|
||||||
|
|
||||||
|
if promoCodeID == "" {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "PromoCode ID is required"})
|
||||||
|
}
|
||||||
|
|
||||||
|
err := p.promoCodeService.DeletePromoCode(c.Context(), promoCodeID)
|
||||||
|
if err != nil {
|
||||||
|
p.logger.Error("Failed to delete 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"})
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.SendStatus(fiber.StatusOK)
|
||||||
|
}
|
||||||
|
@ -70,3 +70,11 @@ type GetPromoCodesListResp struct {
|
|||||||
Count int64 `json:"count"` // количество в выборке всего
|
Count int64 `json:"count"` // количество в выборке всего
|
||||||
Items []PromoCode `json:"items"` // "страница" промокодов
|
Items []PromoCode `json:"items"` // "страница" промокодов
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ActivateReq struct {
|
||||||
|
Codeword string `json:"codeword"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActivateResp struct {
|
||||||
|
Greetings string `json:"greetings"` // поле из активированного промокода
|
||||||
|
}
|
||||||
|
@ -213,3 +213,69 @@ func (r *PromoCodeRepository) GetPromoCodesList(ctx context.Context, req *models
|
|||||||
|
|
||||||
return promoCodes, count, nil
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PromoCodeRepository) DeletePromoCode(ctx context.Context, promoCodeID string) error {
|
||||||
|
id, err := primitive.ObjectIDFromHex(promoCodeID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := r.mdb.UpdateOne(
|
||||||
|
ctx,
|
||||||
|
bson.M{"_id": id, "delete": false},
|
||||||
|
bson.M{"$set": bson.M{"delete": true}},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.MatchedCount == 0 {
|
||||||
|
return ErrPromoCodeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -60,6 +60,8 @@ func (s *Server) registerRoutes() {
|
|||||||
s.app.Post("/promocode/create", s.PromoCodeController.CreatePromoCode)
|
s.app.Post("/promocode/create", s.PromoCodeController.CreatePromoCode)
|
||||||
s.app.Put("/promocode/edit", s.PromoCodeController.EditPromoCode)
|
s.app.Put("/promocode/edit", s.PromoCodeController.EditPromoCode)
|
||||||
s.app.Post("/promocode/getList", s.PromoCodeController.GetList)
|
s.app.Post("/promocode/getList", s.PromoCodeController.GetList)
|
||||||
|
s.app.Post("/promocode/activate", s.PromoCodeController.Activate)
|
||||||
|
s.app.Delete("/promocode/:promocodeID", s.PromoCodeController.Delete)
|
||||||
//... other
|
//... other
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ type PromoCodeRepository interface {
|
|||||||
CreatePromoCode(ctx context.Context, req *models.PromoCode) (*models.PromoCode, error)
|
CreatePromoCode(ctx context.Context, req *models.PromoCode) (*models.PromoCode, error)
|
||||||
EditPromoCode(ctx context.Context, req *models.ReqEditPromoCode) (*models.PromoCode, error)
|
EditPromoCode(ctx context.Context, req *models.ReqEditPromoCode) (*models.PromoCode, error)
|
||||||
GetPromoCodesList(ctx context.Context, req *models.GetPromoCodesListReq) ([]models.PromoCode, int64, error)
|
GetPromoCodesList(ctx context.Context, req *models.GetPromoCodesListReq) ([]models.PromoCode, int64, error)
|
||||||
|
ActivatePromo(ctx context.Context, req *models.ActivateReq) (string, error)
|
||||||
|
DeletePromoCode(ctx context.Context, promoCodeID string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type PromoDeps struct {
|
type PromoDeps struct {
|
||||||
@ -58,3 +60,23 @@ func (s *PromoCodeService) GetPromoCodesList(ctx context.Context, req *models.Ge
|
|||||||
|
|
||||||
return promoCodes, count, nil
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PromoCodeService) DeletePromoCode(ctx context.Context, promoCodeID string) error {
|
||||||
|
err := s.promoCodeRepo.DeletePromoCode(ctx, promoCodeID)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("Failed simple delete promocode from database", zap.Error(err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user