Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cmd/server/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
handler "github.com/Financial-Partner/server/internal/interfaces/http"
"github.com/Financial-Partner/server/internal/interfaces/http/middleware"
auth_usecase "github.com/Financial-Partner/server/internal/module/auth/usecase"
gacha_usecase "github.com/Financial-Partner/server/internal/module/gacha/usecase"
goal_usecase "github.com/Financial-Partner/server/internal/module/goal/usecase"
investment_usecase "github.com/Financial-Partner/server/internal/module/investment/usecase"
transaction_usecase "github.com/Financial-Partner/server/internal/module/transaction/usecase"
Expand Down Expand Up @@ -86,15 +87,20 @@ func ProvideTransactionService() *transaction_usecase.Service {
return transaction_usecase.NewService()
}

func ProvideGachaService() *gacha_usecase.Service {
return gacha_usecase.NewService()
}

func ProvideHandler(
userService *user_usecase.Service,
authService *auth_usecase.Service,
goalService *goal_usecase.Service,
investmentService *investment_usecase.Service,
transactionService *transaction_usecase.Service,
gachaService *gacha_usecase.Service,
log loggerInfra.Logger,
) *handler.Handler {
return handler.NewHandler(userService, authService, goalService, investmentService, transactionService, log)
return handler.NewHandler(userService, authService, goalService, investmentService, transactionService, gachaService, log)
}

func ProvideAuthMiddleware(jwtManager *authInfra.JWTManager, cfg *config.Config, log loggerInfra.Logger) *middleware.AuthMiddleware {
Expand Down
10 changes: 7 additions & 3 deletions cmd/server/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,15 @@ func setupProtectedRoutes(router *mux.Router, handlers *handler.Handler) {
investmentRoutes := router.PathPrefix("/investments").Subrouter()
investmentRoutes.HandleFunc("", handlers.GetOpportunities).Methods(http.MethodGet)

userInvestmentRoute := router.PathPrefix("/users/me/investment").Subrouter()
userInvestmentRoute.HandleFunc("/", handlers.CreateUserInvestment).Methods(http.MethodPost)
userInvestmentRoute.HandleFunc("/", handlers.GetUserInvestments).Methods(http.MethodGet)
userInvestmentRoutes := router.PathPrefix("/users/me/investment").Subrouter()
userInvestmentRoutes.HandleFunc("/", handlers.CreateUserInvestment).Methods(http.MethodPost)
userInvestmentRoutes.HandleFunc("/", handlers.GetUserInvestments).Methods(http.MethodGet)

transactionRoutes := router.PathPrefix("/transactions").Subrouter()
transactionRoutes.HandleFunc("", handlers.CreateTransaction).Methods(http.MethodPost)
transactionRoutes.HandleFunc("", handlers.GetTransactions).Methods(http.MethodGet)

gachaRoutes := router.PathPrefix("/gacha").Subrouter()
gachaRoutes.HandleFunc("/draw", handlers.DrawGacha).Methods(http.MethodPost)
gachaRoutes.HandleFunc("/preview", handlers.PreviewGachas).Methods(http.MethodGet)
}
1 change: 1 addition & 0 deletions cmd/server/wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func InitializeServer(cfgFile string) (*Server, error) {
ProvideGoalService,
ProvideInvestmentService,
ProvideTransactionService,
ProvideGachaService,
ProvideHandler,
ProvideAuthMiddleware,
ProvideRouter,
Expand Down
3 changes: 2 additions & 1 deletion cmd/server/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions internal/entities/gacha.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package entities

import (
"go.mongodb.org/mongo-driver/bson/primitive"
)

type Gacha struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
ImgSrc string `bson:"img_src" json:"img_src"`
}
14 changes: 14 additions & 0 deletions internal/interfaces/http/dto/gacha.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dto

type GachaResponse struct {
ID string `json:"id" example:"60d6ec33f777b123e4567890"`
ImgSrc string `json:"img_src" example:"https://example.com/image.png"`
}

type DrawGachaRequest struct {
Amount int64 `json:"amount" example:"100" binding:"required"`
}

type PreviewGachasResponse struct {
Gachas []GachaResponse `json:"gachas"`
}
2 changes: 2 additions & 0 deletions internal/interfaces/http/error/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ const (
ErrFailedToGetUserInvestments = "Failed to get user investments"
ErrFailedToGetTransactions = "Failed to get transactions"
ErrFailedToCreateTransaction = "Failed to create a transaction"
ErrFailedToDrawGacha = "Failed to draw a gacha"
ErrFailedToPreviewGachas = "Failed to preview gachas"
)
100 changes: 100 additions & 0 deletions internal/interfaces/http/gacha.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package handler

import (
"context"
"encoding/json"
"net/http"

"github.com/Financial-Partner/server/internal/contextutil"
"github.com/Financial-Partner/server/internal/entities"
"github.com/Financial-Partner/server/internal/interfaces/http/dto"
httperror "github.com/Financial-Partner/server/internal/interfaces/http/error"
responde "github.com/Financial-Partner/server/internal/interfaces/http/respond"
)

//go:generate mockgen -source=gacha.go -destination=gacha_mock.go -package=handler

type GachaService interface {
DrawGacha(ctx context.Context, userID string, req *dto.DrawGachaRequest) (*entities.Gacha, error)
PreviewGachas(ctx context.Context, userID string) ([]entities.Gacha, error)
}

// @Summary Decrease user's gacha amount and return gacha result
// @Description Decrease user's gacha amount and return gacha result
// @Tags gacha
// @Accept json
// @Produce json
// @Param request body dto.DrawGachaRequest true "Draw gacha request"
// @Param Authorization header string true "Bearer {token}" default "Bearer "
// @Success 200 {object} dto.GachaResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 500 {object} dto.ErrorResponse
// @Router /gacha/draw [post]
func (h *Handler) DrawGacha(w http.ResponseWriter, r *http.Request) {
userID, ok := contextutil.GetUserID(r.Context())
if !ok {
h.log.Warnf("failed to get user ID from context")
responde.WithError(w, r, h.log, nil, httperror.ErrUnauthorized, http.StatusUnauthorized)
return
}

var req dto.DrawGachaRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
h.log.WithError(err).Warnf("failed to decode request body")
responde.WithError(w, r, h.log, err, httperror.ErrInvalidRequest, http.StatusBadRequest)
return
}

gacha, err := h.gachaService.DrawGacha(r.Context(), userID, &req)
if err != nil {
h.log.WithError(err).Warnf("failed to draw a gacha")
responde.WithError(w, r, h.log, err, httperror.ErrFailedToDrawGacha, http.StatusInternalServerError)
return
}

resp := dto.GachaResponse{
ID: gacha.ID.Hex(),
ImgSrc: gacha.ImgSrc,
}

responde.WithJSON(w, r, resp, http.StatusOK)
}

// @Summary Get 9 gacha images for preview
// @Description Get 9 gacha images for preview
// @Tags gacha
// @Accept json
// @Produce json
// @Param Authorization header string true "Bearer {token}" default "Bearer "
// @Success 200 {object} dto.PreviewGachasResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 500 {object} dto.ErrorResponse
// @Router /gacha/preview [get]
func (h *Handler) PreviewGachas(w http.ResponseWriter, r *http.Request) {
userID, ok := contextutil.GetUserID(r.Context())
if !ok {
h.log.Warnf("failed to get user ID from context")
responde.WithError(w, r, h.log, nil, httperror.ErrUnauthorized, http.StatusUnauthorized)
return
}

gachas, err := h.gachaService.PreviewGachas(r.Context(), userID)
if err != nil {
h.log.WithError(err).Warnf("failed to get preview gacha images")
responde.WithError(w, r, h.log, err, httperror.ErrFailedToPreviewGachas, http.StatusInternalServerError)
return
}

resp := dto.PreviewGachasResponse{
Gachas: make([]dto.GachaResponse, 0, 9),
}

for _, gacha := range gachas {
resp.Gachas = append(resp.Gachas, dto.GachaResponse{
ID: gacha.ID.Hex(),
ImgSrc: gacha.ImgSrc,
})
}

responde.WithJSON(w, r, resp, http.StatusOK)
}
73 changes: 73 additions & 0 deletions internal/interfaces/http/gacha_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading