Skip to content

Commit df302da

Browse files
authored
Merge pull request #13 from Financial-Partner/feat/define_gacha_api_interface
Add Gacha service and related handlers for drawing and previewing gacha
2 parents c3146f2 + 0615460 commit df302da

16 files changed

Lines changed: 826 additions & 7 deletions

File tree

cmd/server/providers.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
handler "github.com/Financial-Partner/server/internal/interfaces/http"
1717
"github.com/Financial-Partner/server/internal/interfaces/http/middleware"
1818
auth_usecase "github.com/Financial-Partner/server/internal/module/auth/usecase"
19+
gacha_usecase "github.com/Financial-Partner/server/internal/module/gacha/usecase"
1920
goal_usecase "github.com/Financial-Partner/server/internal/module/goal/usecase"
2021
investment_usecase "github.com/Financial-Partner/server/internal/module/investment/usecase"
2122
transaction_usecase "github.com/Financial-Partner/server/internal/module/transaction/usecase"
@@ -86,15 +87,20 @@ func ProvideTransactionService() *transaction_usecase.Service {
8687
return transaction_usecase.NewService()
8788
}
8889

90+
func ProvideGachaService() *gacha_usecase.Service {
91+
return gacha_usecase.NewService()
92+
}
93+
8994
func ProvideHandler(
9095
userService *user_usecase.Service,
9196
authService *auth_usecase.Service,
9297
goalService *goal_usecase.Service,
9398
investmentService *investment_usecase.Service,
9499
transactionService *transaction_usecase.Service,
100+
gachaService *gacha_usecase.Service,
95101
log loggerInfra.Logger,
96102
) *handler.Handler {
97-
return handler.NewHandler(userService, authService, goalService, investmentService, transactionService, log)
103+
return handler.NewHandler(userService, authService, goalService, investmentService, transactionService, gachaService, log)
98104
}
99105

100106
func ProvideAuthMiddleware(jwtManager *authInfra.JWTManager, cfg *config.Config, log loggerInfra.Logger) *middleware.AuthMiddleware {

cmd/server/route.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,15 @@ func setupProtectedRoutes(router *mux.Router, handlers *handler.Handler) {
6262
investmentRoutes := router.PathPrefix("/investments").Subrouter()
6363
investmentRoutes.HandleFunc("", handlers.GetOpportunities).Methods(http.MethodGet)
6464

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

6969
transactionRoutes := router.PathPrefix("/transactions").Subrouter()
7070
transactionRoutes.HandleFunc("", handlers.CreateTransaction).Methods(http.MethodPost)
7171
transactionRoutes.HandleFunc("", handlers.GetTransactions).Methods(http.MethodGet)
72+
73+
gachaRoutes := router.PathPrefix("/gacha").Subrouter()
74+
gachaRoutes.HandleFunc("/draw", handlers.DrawGacha).Methods(http.MethodPost)
75+
gachaRoutes.HandleFunc("/preview", handlers.PreviewGachas).Methods(http.MethodGet)
7276
}

cmd/server/wire.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ func InitializeServer(cfgFile string) (*Server, error) {
2424
ProvideGoalService,
2525
ProvideInvestmentService,
2626
ProvideTransactionService,
27+
ProvideGachaService,
2728
ProvideHandler,
2829
ProvideAuthMiddleware,
2930
ProvideRouter,

cmd/server/wire_gen.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/entities/gacha.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package entities
2+
3+
import (
4+
"go.mongodb.org/mongo-driver/bson/primitive"
5+
)
6+
7+
type Gacha struct {
8+
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
9+
ImgSrc string `bson:"img_src" json:"img_src"`
10+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package dto
2+
3+
type GachaResponse struct {
4+
ID string `json:"id" example:"60d6ec33f777b123e4567890"`
5+
ImgSrc string `json:"img_src" example:"https://example.com/image.png"`
6+
}
7+
8+
type DrawGachaRequest struct {
9+
Amount int64 `json:"amount" example:"100" binding:"required"`
10+
}
11+
12+
type PreviewGachasResponse struct {
13+
Gachas []GachaResponse `json:"gachas"`
14+
}

internal/interfaces/http/error/error.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ const (
2222
ErrFailedToGetUserInvestments = "Failed to get user investments"
2323
ErrFailedToGetTransactions = "Failed to get transactions"
2424
ErrFailedToCreateTransaction = "Failed to create a transaction"
25+
ErrFailedToDrawGacha = "Failed to draw a gacha"
26+
ErrFailedToPreviewGachas = "Failed to preview gachas"
2527
)

internal/interfaces/http/gacha.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"net/http"
7+
8+
"github.com/Financial-Partner/server/internal/contextutil"
9+
"github.com/Financial-Partner/server/internal/entities"
10+
"github.com/Financial-Partner/server/internal/interfaces/http/dto"
11+
httperror "github.com/Financial-Partner/server/internal/interfaces/http/error"
12+
responde "github.com/Financial-Partner/server/internal/interfaces/http/respond"
13+
)
14+
15+
//go:generate mockgen -source=gacha.go -destination=gacha_mock.go -package=handler
16+
17+
type GachaService interface {
18+
DrawGacha(ctx context.Context, userID string, req *dto.DrawGachaRequest) (*entities.Gacha, error)
19+
PreviewGachas(ctx context.Context, userID string) ([]entities.Gacha, error)
20+
}
21+
22+
// @Summary Decrease user's gacha amount and return gacha result
23+
// @Description Decrease user's gacha amount and return gacha result
24+
// @Tags gacha
25+
// @Accept json
26+
// @Produce json
27+
// @Param request body dto.DrawGachaRequest true "Draw gacha request"
28+
// @Param Authorization header string true "Bearer {token}" default "Bearer "
29+
// @Success 200 {object} dto.GachaResponse
30+
// @Failure 401 {object} dto.ErrorResponse
31+
// @Failure 500 {object} dto.ErrorResponse
32+
// @Router /gacha/draw [post]
33+
func (h *Handler) DrawGacha(w http.ResponseWriter, r *http.Request) {
34+
userID, ok := contextutil.GetUserID(r.Context())
35+
if !ok {
36+
h.log.Warnf("failed to get user ID from context")
37+
responde.WithError(w, r, h.log, nil, httperror.ErrUnauthorized, http.StatusUnauthorized)
38+
return
39+
}
40+
41+
var req dto.DrawGachaRequest
42+
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
43+
h.log.WithError(err).Warnf("failed to decode request body")
44+
responde.WithError(w, r, h.log, err, httperror.ErrInvalidRequest, http.StatusBadRequest)
45+
return
46+
}
47+
48+
gacha, err := h.gachaService.DrawGacha(r.Context(), userID, &req)
49+
if err != nil {
50+
h.log.WithError(err).Warnf("failed to draw a gacha")
51+
responde.WithError(w, r, h.log, err, httperror.ErrFailedToDrawGacha, http.StatusInternalServerError)
52+
return
53+
}
54+
55+
resp := dto.GachaResponse{
56+
ID: gacha.ID.Hex(),
57+
ImgSrc: gacha.ImgSrc,
58+
}
59+
60+
responde.WithJSON(w, r, resp, http.StatusOK)
61+
}
62+
63+
// @Summary Get 9 gacha images for preview
64+
// @Description Get 9 gacha images for preview
65+
// @Tags gacha
66+
// @Accept json
67+
// @Produce json
68+
// @Param Authorization header string true "Bearer {token}" default "Bearer "
69+
// @Success 200 {object} dto.PreviewGachasResponse
70+
// @Failure 401 {object} dto.ErrorResponse
71+
// @Failure 500 {object} dto.ErrorResponse
72+
// @Router /gacha/preview [get]
73+
func (h *Handler) PreviewGachas(w http.ResponseWriter, r *http.Request) {
74+
userID, ok := contextutil.GetUserID(r.Context())
75+
if !ok {
76+
h.log.Warnf("failed to get user ID from context")
77+
responde.WithError(w, r, h.log, nil, httperror.ErrUnauthorized, http.StatusUnauthorized)
78+
return
79+
}
80+
81+
gachas, err := h.gachaService.PreviewGachas(r.Context(), userID)
82+
if err != nil {
83+
h.log.WithError(err).Warnf("failed to get preview gacha images")
84+
responde.WithError(w, r, h.log, err, httperror.ErrFailedToPreviewGachas, http.StatusInternalServerError)
85+
return
86+
}
87+
88+
resp := dto.PreviewGachasResponse{
89+
Gachas: make([]dto.GachaResponse, 0, 9),
90+
}
91+
92+
for _, gacha := range gachas {
93+
resp.Gachas = append(resp.Gachas, dto.GachaResponse{
94+
ID: gacha.ID.Hex(),
95+
ImgSrc: gacha.ImgSrc,
96+
})
97+
}
98+
99+
responde.WithJSON(w, r, resp, http.StatusOK)
100+
}

internal/interfaces/http/gacha_mock.go

Lines changed: 73 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)