From d1e543a79f71e65e450cf2a7815f95a68406bb93 Mon Sep 17 00:00:00 2001 From: efrilm Date: Wed, 30 Sep 2026 14:43:15 +0700 Subject: [PATCH] refactor(loyalty): remove the dead customer points and tokens code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First part of PC-601 (docs/prd-point-coin.md §10.7): the code that has had no way in since balances moved to the wallet. - The /marketing/customer-points and /marketing/customer-tokens routes were commented out; their 16 handler methods, the GamificationService methods behind them, and the validators, transformers, mappers and contract/model types only they used are gone. - CustomerPointsProcessor loses its "not implemented" stubs; it keeps the customer app's balance, wallet and games endpoints. - CustomerTokensProcessor and the customer points and tokens repositories, wired but no longer called by anything, are gone. What stays until its preconditions are met: the customer_points and customer_tokens tables and their entities, which cmd/wallet-migrate still reads, and the /customer/points, /customer/tokens aliases and the token_used / tokens_remaining fields, until the apps no longer use them. Co-Authored-By: Claude Opus 5.5 --- internal/app/app.go | 8 +- internal/contract/customer_points_contract.go | 58 --- internal/contract/customer_tokens_contract.go | 52 -- internal/handler/gamification_handler.go | 471 ------------------ internal/mappers/customer_points_mapper.go | 46 -- internal/mappers/customer_tokens_mapper.go | 48 -- internal/models/customer_points.go | 58 --- internal/models/customer_tokens.go | 44 -- .../processor/customer_points_processor.go | 47 -- .../processor/customer_tokens_processor.go | 198 -------- .../repository/customer_points_repository.go | 97 ---- .../repository/customer_tokens_repository.go | 131 ----- internal/router/router.go | 25 - internal/service/gamification_service.go | 174 +------ .../transformer/gamification_transformer.go | 125 ----- internal/validator/gamification_validator.go | 160 ------ 16 files changed, 11 insertions(+), 1731 deletions(-) delete mode 100644 internal/contract/customer_tokens_contract.go delete mode 100644 internal/mappers/customer_points_mapper.go delete mode 100644 internal/mappers/customer_tokens_mapper.go delete mode 100644 internal/models/customer_tokens.go delete mode 100644 internal/processor/customer_tokens_processor.go delete mode 100644 internal/repository/customer_points_repository.go delete mode 100644 internal/repository/customer_tokens_repository.go diff --git a/internal/app/app.go b/internal/app/app.go index df1bf1b..0e04b7e 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -267,7 +267,6 @@ type repositories struct { chartOfAccountRepo *repository.ChartOfAccountRepositoryImpl accountRepo *repository.AccountRepositoryImpl orderIngredientTransactionRepo *repository.OrderIngredientTransactionRepositoryImpl - customerTokensRepo *repository.CustomerTokensRepository tierRepo *repository.TierRepository gameRepo *repository.GameRepository gamePrizeRepo *repository.GamePrizeRepository @@ -277,7 +276,6 @@ type repositories struct { campaignRepo repository.CampaignRepository campaignRuleRepo repository.CampaignRuleRepository customerAuthRepo repository.CustomerAuthRepository - customerPointsRepo repository.CustomerPointsRepository otpRepo repository.OtpRepository sessionRepo repository.SessionRepository txManager *repository.TxManager @@ -325,7 +323,6 @@ func (a *App) initRepositories() *repositories { chartOfAccountRepo: repository.NewChartOfAccountRepositoryImpl(a.db), accountRepo: repository.NewAccountRepositoryImpl(a.db), orderIngredientTransactionRepo: repository.NewOrderIngredientTransactionRepositoryImpl(a.db).(*repository.OrderIngredientTransactionRepositoryImpl), - customerTokensRepo: repository.NewCustomerTokensRepository(a.db), tierRepo: repository.NewTierRepository(a.db), gameRepo: repository.NewGameRepository(a.db), gamePrizeRepo: repository.NewGamePrizeRepository(a.db), @@ -335,7 +332,6 @@ func (a *App) initRepositories() *repositories { campaignRepo: repository.NewCampaignRepository(a.db), campaignRuleRepo: repository.NewCampaignRuleRepository(a.db), customerAuthRepo: repository.NewCustomerAuthRepository(a.db), - customerPointsRepo: repository.NewCustomerPointsRepository(a.db), otpRepo: repository.NewOtpRepository(a.db), sessionRepo: repository.NewSessionRepository(a.redisClient), txManager: repository.NewTxManager(a.db), @@ -378,7 +374,6 @@ type processors struct { chartOfAccountProcessor *processor.ChartOfAccountProcessorImpl accountProcessor *processor.AccountProcessorImpl orderIngredientTransactionProcessor *processor.OrderIngredientTransactionProcessorImpl - customerTokensProcessor *processor.CustomerTokensProcessor tierProcessor *processor.TierProcessor gameProcessor *processor.GameProcessor gamePrizeProcessor *processor.GamePrizeProcessor @@ -461,7 +456,6 @@ func (a *App) initProcessors(cfg *config.Config, repos *repositories) *processor chartOfAccountProcessor: processor.NewChartOfAccountProcessorImpl(repos.chartOfAccountRepo, repos.chartOfAccountTypeRepo), accountProcessor: processor.NewAccountProcessorImpl(repos.accountRepo, repos.chartOfAccountRepo), orderIngredientTransactionProcessor: processor.NewOrderIngredientTransactionProcessorImpl(repos.orderIngredientTransactionRepo, repos.productRecipeRepo, repos.ingredientRepo, repos.unitRepo).(*processor.OrderIngredientTransactionProcessorImpl), - customerTokensProcessor: processor.NewCustomerTokensProcessor(repos.customerTokensRepo), tierProcessor: processor.NewTierProcessor(repos.tierRepo), gameProcessor: processor.NewGameProcessor(repos.gameRepo), gamePrizeProcessor: processor.NewGamePrizeProcessor(repos.gamePrizeRepo), @@ -570,7 +564,7 @@ func (a *App) initServices(processors *processors, repos *repositories, cfg *con chartOfAccountService := service.NewChartOfAccountService(processors.chartOfAccountProcessor) accountService := service.NewAccountService(processors.accountProcessor) orderIngredientTransactionService := service.NewOrderIngredientTransactionService(processors.orderIngredientTransactionProcessor, repos.txManager) - gamificationService := service.NewGamificationService(processors.customerPointsProcessor, processors.customerTokensProcessor, processors.tierProcessor, processors.gameProcessor, processors.gamePrizeProcessor, processors.gamePlayProcessor, processors.omsetTrackerProcessor) + gamificationService := service.NewGamificationService(processors.tierProcessor, processors.gameProcessor, processors.gamePrizeProcessor, processors.gamePlayProcessor, processors.omsetTrackerProcessor) rewardService := service.NewRewardService(processors.rewardProcessor) campaignService := service.NewCampaignService(processors.campaignProcessor, processors.campaignRuleProcessor) customerAuthService := service.NewCustomerAuthService(processors.customerAuthProcessor) diff --git a/internal/contract/customer_points_contract.go b/internal/contract/customer_points_contract.go index d7cd65a..591758c 100644 --- a/internal/contract/customer_points_contract.go +++ b/internal/contract/customer_points_contract.go @@ -2,66 +2,8 @@ package contract import ( "time" - - "github.com/google/uuid" ) -// Existing gamification contracts -type CreateCustomerPointsRequest struct { - CustomerID uuid.UUID `json:"customer_id" validate:"required"` - Balance int64 `json:"balance" validate:"min=0"` -} - -type UpdateCustomerPointsRequest struct { - Balance int64 `json:"balance" validate:"min=0"` -} - -type AddCustomerPointsRequest struct { - Points int64 `json:"points" validate:"required,min=1"` -} - -type DeductCustomerPointsRequest struct { - Points int64 `json:"points" validate:"required,min=1"` -} - -type CustomerPointsResponse struct { - ID uuid.UUID `json:"id"` - CustomerID uuid.UUID `json:"customer_id"` - Balance int64 `json:"balance"` - Customer *CustomerResponse `json:"customer,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -type ListCustomerPointsRequest struct { - Page int `json:"page" validate:"min=1"` - Limit int `json:"limit" validate:"min=1,max=100"` - Search string `json:"search"` - SortBy string `json:"sort_by" validate:"omitempty,oneof=balance created_at updated_at"` - SortOrder string `json:"sort_order" validate:"omitempty,oneof=asc desc"` -} - -type PaginatedCustomerPointsResponse struct { - Data []CustomerPointsResponse `json:"data"` - TotalCount int `json:"total_count"` - Page int `json:"page"` - Limit int `json:"limit"` - TotalPages int `json:"total_pages"` -} - -// New customer API contracts -type GetCustomerPointsRequest struct { - // No additional fields needed - customer ID comes from JWT token -} - -type GetCustomerTokensRequest struct { - // No additional fields needed - customer ID comes from JWT token -} - -type GetCustomerWalletRequest struct { - // No additional fields needed - customer ID comes from JWT token -} - // Response Contracts type GetCustomerPointsResponse struct { Status string `json:"status"` diff --git a/internal/contract/customer_tokens_contract.go b/internal/contract/customer_tokens_contract.go deleted file mode 100644 index 21d90c6..0000000 --- a/internal/contract/customer_tokens_contract.go +++ /dev/null @@ -1,52 +0,0 @@ -package contract - -import ( - "time" - - "github.com/google/uuid" -) - -type CreateCustomerTokensRequest struct { - CustomerID uuid.UUID `json:"customer_id" validate:"required"` - TokenType string `json:"token_type" validate:"required,oneof=SPIN RAFFLE MINIGAME"` - Balance int64 `json:"balance" validate:"min=0"` -} - -type UpdateCustomerTokensRequest struct { - Balance int64 `json:"balance" validate:"min=0"` -} - -type AddCustomerTokensRequest struct { - Tokens int64 `json:"tokens" validate:"required,min=1"` -} - -type DeductCustomerTokensRequest struct { - Tokens int64 `json:"tokens" validate:"required,min=1"` -} - -type CustomerTokensResponse struct { - ID uuid.UUID `json:"id"` - CustomerID uuid.UUID `json:"customer_id"` - TokenType string `json:"token_type"` - Balance int64 `json:"balance"` - Customer *CustomerResponse `json:"customer,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -type ListCustomerTokensRequest struct { - Page int `json:"page" validate:"min=1"` - Limit int `json:"limit" validate:"min=1,max=100"` - Search string `json:"search"` - TokenType string `json:"token_type" validate:"omitempty,oneof=SPIN RAFFLE MINIGAME"` - SortBy string `json:"sort_by" validate:"omitempty,oneof=balance token_type created_at updated_at"` - SortOrder string `json:"sort_order" validate:"omitempty,oneof=asc desc"` -} - -type PaginatedCustomerTokensResponse struct { - Data []CustomerTokensResponse `json:"data"` - TotalCount int `json:"total_count"` - Page int `json:"page"` - Limit int `json:"limit"` - TotalPages int `json:"total_pages"` -} diff --git a/internal/handler/gamification_handler.go b/internal/handler/gamification_handler.go index 4344a35..4c3c606 100644 --- a/internal/handler/gamification_handler.go +++ b/internal/handler/gamification_handler.go @@ -9,7 +9,6 @@ import ( "apskel-pos-be/internal/validator" "github.com/gin-gonic/gin" - "github.com/google/uuid" ) type GamificationHandler struct { @@ -27,239 +26,6 @@ func NewGamificationHandler( } } -// Customer Points Handlers -func (h *GamificationHandler) CreateCustomerPoints(c *gin.Context) { - ctx := c.Request.Context() - - var req contract.CreateCustomerPointsRequest - if err := c.ShouldBindJSON(&req); err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::CreateCustomerPoints -> request binding failed") - validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::CreateCustomerPoints") - return - } - - validationError, validationErrorCode := h.gamificationValidator.ValidateCreateCustomerPointsRequest(&req) - if validationError != nil { - logger.FromContext(c.Request.Context()).WithError(validationError).Error("GamificationHandler::CreateCustomerPoints -> request validation failed") - validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::CreateCustomerPoints") - return - } - - response, err := h.gamificationService.CreateCustomerPoints(ctx, &req) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::CreateCustomerPoints -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerPointsEntity, err.Error())}), "GamificationHandler::CreateCustomerPoints") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::CreateCustomerPoints") -} - -func (h *GamificationHandler) GetCustomerPoints(c *gin.Context) { - ctx := c.Request.Context() - - idStr := c.Param("id") - id, err := uuid.Parse(idStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::GetCustomerPoints -> invalid ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerPointsEntity, "Invalid ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::GetCustomerPoints") - return - } - - response, err := h.gamificationService.GetCustomerPoints(ctx, id) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::GetCustomerPoints -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerPointsEntity, err.Error())}), "GamificationHandler::GetCustomerPoints") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::GetCustomerPoints") -} - -func (h *GamificationHandler) GetCustomerPointsByCustomerID(c *gin.Context) { - ctx := c.Request.Context() - customerIDStr := c.Param("customer_id") - customerID, err := uuid.Parse(customerIDStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::GetCustomerPointsByCustomerID -> invalid customer ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerPointsEntity, "Invalid customer ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::GetCustomerPointsByCustomerID") - return - } - - response, err := h.gamificationService.GetCustomerPointsByCustomerID(ctx, customerID) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::GetCustomerPointsByCustomerID -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerPointsEntity, err.Error())}), "GamificationHandler::GetCustomerPointsByCustomerID") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::GetCustomerPointsByCustomerID") -} - -func (h *GamificationHandler) ListCustomerPoints(c *gin.Context) { - ctx := c.Request.Context() - var req contract.ListCustomerPointsRequest - if err := c.ShouldBindQuery(&req); err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::ListCustomerPoints -> request binding failed") - validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::ListCustomerPoints") - return - } - - validationError, validationErrorCode := h.gamificationValidator.ValidateListCustomerPointsRequest(&req) - if validationError != nil { - logger.FromContext(c.Request.Context()).WithError(validationError).Error("GamificationHandler::ListCustomerPoints -> request validation failed") - validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::ListCustomerPoints") - return - } - - response, err := h.gamificationService.ListCustomerPoints(ctx, &req) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::ListCustomerPoints -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerPointsEntity, err.Error())}), "GamificationHandler::ListCustomerPoints") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::ListCustomerPoints") -} - -func (h *GamificationHandler) UpdateCustomerPoints(c *gin.Context) { - ctx := c.Request.Context() - idStr := c.Param("id") - id, err := uuid.Parse(idStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::UpdateCustomerPoints -> invalid ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerPointsEntity, "Invalid ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::UpdateCustomerPoints") - return - } - - var req contract.UpdateCustomerPointsRequest - if err := c.ShouldBindJSON(&req); err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::UpdateCustomerPoints -> request binding failed") - validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::UpdateCustomerPoints") - return - } - - validationError, validationErrorCode := h.gamificationValidator.ValidateUpdateCustomerPointsRequest(&req) - if validationError != nil { - logger.FromContext(c.Request.Context()).WithError(validationError).Error("GamificationHandler::UpdateCustomerPoints -> request validation failed") - validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::UpdateCustomerPoints") - return - } - - response, err := h.gamificationService.UpdateCustomerPoints(ctx, id, &req) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::UpdateCustomerPoints -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerPointsEntity, err.Error())}), "GamificationHandler::UpdateCustomerPoints") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::UpdateCustomerPoints") -} - -func (h *GamificationHandler) DeleteCustomerPoints(c *gin.Context) { - ctx := c.Request.Context() - idStr := c.Param("id") - id, err := uuid.Parse(idStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::DeleteCustomerPoints -> invalid ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerPointsEntity, "Invalid ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::DeleteCustomerPoints") - return - } - - err = h.gamificationService.DeleteCustomerPoints(ctx, id) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::DeleteCustomerPoints -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerPointsEntity, err.Error())}), "GamificationHandler::DeleteCustomerPoints") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(nil), "GamificationHandler::DeleteCustomerPoints") -} - -func (h *GamificationHandler) AddCustomerPoints(c *gin.Context) { - ctx := c.Request.Context() - customerIDStr := c.Param("customer_id") - customerID, err := uuid.Parse(customerIDStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::AddCustomerPoints -> invalid customer ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerPointsEntity, "Invalid customer ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::AddCustomerPoints") - return - } - - var req contract.AddCustomerPointsRequest - if err := c.ShouldBindJSON(&req); err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::AddCustomerPoints -> request binding failed") - validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::AddCustomerPoints") - return - } - - validationError, validationErrorCode := h.gamificationValidator.ValidateAddCustomerPointsRequest(&req) - if validationError != nil { - logger.FromContext(c.Request.Context()).WithError(validationError).Error("GamificationHandler::AddCustomerPoints -> request validation failed") - validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::AddCustomerPoints") - return - } - - response, err := h.gamificationService.AddCustomerPoints(ctx, customerID, &req) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::AddCustomerPoints -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerPointsEntity, err.Error())}), "GamificationHandler::AddCustomerPoints") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::AddCustomerPoints") -} - -func (h *GamificationHandler) DeductCustomerPoints(c *gin.Context) { - ctx := c.Request.Context() - customerIDStr := c.Param("customer_id") - customerID, err := uuid.Parse(customerIDStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::DeductCustomerPoints -> invalid customer ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerPointsEntity, "Invalid customer ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::DeductCustomerPoints") - return - } - - var req contract.DeductCustomerPointsRequest - if err := c.ShouldBindJSON(&req); err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::DeductCustomerPoints -> request binding failed") - validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::DeductCustomerPoints") - return - } - - validationError, validationErrorCode := h.gamificationValidator.ValidateDeductCustomerPointsRequest(&req) - if validationError != nil { - logger.FromContext(c.Request.Context()).WithError(validationError).Error("GamificationHandler::DeductCustomerPoints -> request validation failed") - validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::DeductCustomerPoints") - return - } - - response, err := h.gamificationService.DeductCustomerPoints(ctx, customerID, &req) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::DeductCustomerPoints -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerPointsEntity, err.Error())}), "GamificationHandler::DeductCustomerPoints") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::DeductCustomerPoints") -} - // Play Game Handler func (h *GamificationHandler) PlayGame(c *gin.Context) { ctx := c.Request.Context() @@ -288,240 +54,3 @@ func (h *GamificationHandler) PlayGame(c *gin.Context) { util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::PlayGame") } - -// Additional handler methods for other gamification features -func (h *GamificationHandler) CreateCustomerTokens(c *gin.Context) { - ctx := c.Request.Context() - var req contract.CreateCustomerTokensRequest - if err := c.ShouldBindJSON(&req); err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::CreateCustomerTokens -> request binding failed") - validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::CreateCustomerTokens") - return - } - - validationError, validationErrorCode := h.gamificationValidator.ValidateCreateCustomerTokensRequest(&req) - if validationError != nil { - logger.FromContext(c.Request.Context()).WithError(validationError).Error("GamificationHandler::CreateCustomerTokens -> request validation failed") - validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::CreateCustomerTokens") - return - } - - response, err := h.gamificationService.CreateCustomerTokens(ctx, &req) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::CreateCustomerTokens -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerTokensEntity, err.Error())}), "GamificationHandler::CreateCustomerTokens") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::CreateCustomerTokens") -} - -func (h *GamificationHandler) GetCustomerTokens(c *gin.Context) { - ctx := c.Request.Context() - idStr := c.Param("id") - id, err := uuid.Parse(idStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::GetCustomerTokens -> invalid ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerTokensEntity, "Invalid ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::GetCustomerTokens") - return - } - - response, err := h.gamificationService.GetCustomerTokens(ctx, id) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::GetCustomerTokens -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerTokensEntity, err.Error())}), "GamificationHandler::GetCustomerTokens") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::GetCustomerTokens") -} - -func (h *GamificationHandler) GetCustomerTokensByCustomerIDAndType(c *gin.Context) { - ctx := c.Request.Context() - customerIDStr := c.Param("customer_id") - customerID, err := uuid.Parse(customerIDStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::GetCustomerTokensByCustomerIDAndType -> invalid customer ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerTokensEntity, "Invalid customer ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::GetCustomerTokensByCustomerIDAndType") - return - } - - tokenType := c.Param("token_type") - - response, err := h.gamificationService.GetCustomerTokensByCustomerIDAndType(ctx, customerID, tokenType) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::GetCustomerTokensByCustomerIDAndType -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerTokensEntity, err.Error())}), "GamificationHandler::GetCustomerTokensByCustomerIDAndType") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::GetCustomerTokensByCustomerIDAndType") -} - -func (h *GamificationHandler) ListCustomerTokens(c *gin.Context) { - ctx := c.Request.Context() - var req contract.ListCustomerTokensRequest - if err := c.ShouldBindQuery(&req); err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::ListCustomerTokens -> request binding failed") - validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::ListCustomerTokens") - return - } - - validationError, validationErrorCode := h.gamificationValidator.ValidateListCustomerTokensRequest(&req) - if validationError != nil { - logger.FromContext(c.Request.Context()).WithError(validationError).Error("GamificationHandler::ListCustomerTokens -> request validation failed") - validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::ListCustomerTokens") - return - } - - response, err := h.gamificationService.ListCustomerTokens(ctx, &req) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::ListCustomerTokens -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerTokensEntity, err.Error())}), "GamificationHandler::ListCustomerTokens") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::ListCustomerTokens") -} - -func (h *GamificationHandler) UpdateCustomerTokens(c *gin.Context) { - ctx := c.Request.Context() - idStr := c.Param("id") - id, err := uuid.Parse(idStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::UpdateCustomerTokens -> invalid ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerTokensEntity, "Invalid ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::UpdateCustomerTokens") - return - } - - var req contract.UpdateCustomerTokensRequest - if err := c.ShouldBindJSON(&req); err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::UpdateCustomerTokens -> request binding failed") - validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::UpdateCustomerTokens") - return - } - - validationError, validationErrorCode := h.gamificationValidator.ValidateUpdateCustomerTokensRequest(&req) - if validationError != nil { - logger.FromContext(c.Request.Context()).WithError(validationError).Error("GamificationHandler::UpdateCustomerTokens -> request validation failed") - validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::UpdateCustomerTokens") - return - } - - response, err := h.gamificationService.UpdateCustomerTokens(ctx, id, &req) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::UpdateCustomerTokens -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerTokensEntity, err.Error())}), "GamificationHandler::UpdateCustomerTokens") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::UpdateCustomerTokens") -} - -func (h *GamificationHandler) DeleteCustomerTokens(c *gin.Context) { - ctx := c.Request.Context() - idStr := c.Param("id") - id, err := uuid.Parse(idStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::DeleteCustomerTokens -> invalid ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerTokensEntity, "Invalid ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::DeleteCustomerTokens") - return - } - - err = h.gamificationService.DeleteCustomerTokens(ctx, id) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::DeleteCustomerTokens -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerTokensEntity, err.Error())}), "GamificationHandler::DeleteCustomerTokens") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(nil), "GamificationHandler::DeleteCustomerTokens") -} - -func (h *GamificationHandler) AddCustomerTokens(c *gin.Context) { - ctx := c.Request.Context() - customerIDStr := c.Param("customer_id") - customerID, err := uuid.Parse(customerIDStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::AddCustomerTokens -> invalid customer ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerTokensEntity, "Invalid customer ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::AddCustomerTokens") - return - } - - tokenType := c.Param("token_type") - - var req contract.AddCustomerTokensRequest - if err := c.ShouldBindJSON(&req); err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::AddCustomerTokens -> request binding failed") - validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::AddCustomerTokens") - return - } - - validationError, validationErrorCode := h.gamificationValidator.ValidateAddCustomerTokensRequest(&req) - if validationError != nil { - logger.FromContext(c.Request.Context()).WithError(validationError).Error("GamificationHandler::AddCustomerTokens -> request validation failed") - validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::AddCustomerTokens") - return - } - - response, err := h.gamificationService.AddCustomerTokens(ctx, customerID, tokenType, &req) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::AddCustomerTokens -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerTokensEntity, err.Error())}), "GamificationHandler::AddCustomerTokens") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::AddCustomerTokens") -} - -func (h *GamificationHandler) DeductCustomerTokens(c *gin.Context) { - ctx := c.Request.Context() - customerIDStr := c.Param("customer_id") - customerID, err := uuid.Parse(customerIDStr) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::DeductCustomerTokens -> invalid customer ID") - validationResponseError := contract.NewResponseError(constants.InvalidFieldErrorCode, constants.CustomerTokensEntity, "Invalid customer ID format") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::DeductCustomerTokens") - return - } - - tokenType := c.Param("token_type") - - var req contract.DeductCustomerTokensRequest - if err := c.ShouldBindJSON(&req); err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::DeductCustomerTokens -> request binding failed") - validationResponseError := contract.NewResponseError(constants.MissingFieldErrorCode, constants.RequestEntity, err.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::DeductCustomerTokens") - return - } - - validationError, validationErrorCode := h.gamificationValidator.ValidateDeductCustomerTokensRequest(&req) - if validationError != nil { - logger.FromContext(c.Request.Context()).WithError(validationError).Error("GamificationHandler::DeductCustomerTokens -> request validation failed") - validationResponseError := contract.NewResponseError(validationErrorCode, constants.RequestEntity, validationError.Error()) - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{validationResponseError}), "GamificationHandler::DeductCustomerTokens") - return - } - - response, err := h.gamificationService.DeductCustomerTokens(ctx, customerID, tokenType, &req) - if err != nil { - logger.FromContext(c.Request.Context()).WithError(err).Error("GamificationHandler::DeductCustomerTokens -> service call failed") - util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{contract.NewResponseError(constants.InternalServerErrorCode, constants.CustomerTokensEntity, err.Error())}), "GamificationHandler::DeductCustomerTokens") - return - } - - util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "GamificationHandler::DeductCustomerTokens") -} diff --git a/internal/mappers/customer_points_mapper.go b/internal/mappers/customer_points_mapper.go deleted file mode 100644 index 0cf67ba..0000000 --- a/internal/mappers/customer_points_mapper.go +++ /dev/null @@ -1,46 +0,0 @@ -package mappers - -import ( - "apskel-pos-be/internal/entities" - "apskel-pos-be/internal/models" -) - -// ToCustomerPointsResponse converts a customer points entity to a customer points response -func ToCustomerPointsResponse(customerPoints *entities.CustomerPoints) *models.CustomerPointsResponse { - if customerPoints == nil { - return nil - } - - return &models.CustomerPointsResponse{ - ID: customerPoints.ID, - CustomerID: customerPoints.CustomerID, - Balance: customerPoints.Balance, - Customer: ToCustomerResponse(&customerPoints.Customer), - CreatedAt: customerPoints.CreatedAt, - UpdatedAt: customerPoints.UpdatedAt, - } -} - -// ToCustomerPointsResponses converts a slice of customer points entities to customer points responses -func ToCustomerPointsResponses(customerPoints []entities.CustomerPoints) []models.CustomerPointsResponse { - responses := make([]models.CustomerPointsResponse, len(customerPoints)) - for i, cp := range customerPoints { - responses[i] = *ToCustomerPointsResponse(&cp) - } - return responses -} - -// ToCustomerPointsEntity converts a create customer points request to a customer points entity -func ToCustomerPointsEntity(req *models.CreateCustomerPointsRequest) *entities.CustomerPoints { - return &entities.CustomerPoints{ - CustomerID: req.CustomerID, - Balance: req.Balance, - } -} - -// UpdateCustomerPointsEntity updates a customer points entity with update request data -func UpdateCustomerPointsEntity(customerPoints *entities.CustomerPoints, req *models.UpdateCustomerPointsRequest) { - if req.Balance >= 0 { - customerPoints.Balance = req.Balance - } -} diff --git a/internal/mappers/customer_tokens_mapper.go b/internal/mappers/customer_tokens_mapper.go deleted file mode 100644 index e88cfed..0000000 --- a/internal/mappers/customer_tokens_mapper.go +++ /dev/null @@ -1,48 +0,0 @@ -package mappers - -import ( - "apskel-pos-be/internal/entities" - "apskel-pos-be/internal/models" -) - -// ToCustomerTokensResponse converts a customer tokens entity to a customer tokens response -func ToCustomerTokensResponse(customerTokens *entities.CustomerTokens) *models.CustomerTokensResponse { - if customerTokens == nil { - return nil - } - - return &models.CustomerTokensResponse{ - ID: customerTokens.ID, - CustomerID: customerTokens.CustomerID, - TokenType: string(customerTokens.TokenType), - Balance: customerTokens.Balance, - Customer: ToCustomerResponse(&customerTokens.Customer), - CreatedAt: customerTokens.CreatedAt, - UpdatedAt: customerTokens.UpdatedAt, - } -} - -// ToCustomerTokensResponses converts a slice of customer tokens entities to customer tokens responses -func ToCustomerTokensResponses(customerTokens []entities.CustomerTokens) []models.CustomerTokensResponse { - responses := make([]models.CustomerTokensResponse, len(customerTokens)) - for i, ct := range customerTokens { - responses[i] = *ToCustomerTokensResponse(&ct) - } - return responses -} - -// ToCustomerTokensEntity converts a create customer tokens request to a customer tokens entity -func ToCustomerTokensEntity(req *models.CreateCustomerTokensRequest) *entities.CustomerTokens { - return &entities.CustomerTokens{ - CustomerID: req.CustomerID, - TokenType: entities.TokenType(req.TokenType), - Balance: req.Balance, - } -} - -// UpdateCustomerTokensEntity updates a customer tokens entity with update request data -func UpdateCustomerTokensEntity(customerTokens *entities.CustomerTokens, req *models.UpdateCustomerTokensRequest) { - if req.Balance >= 0 { - customerTokens.Balance = req.Balance - } -} diff --git a/internal/models/customer_points.go b/internal/models/customer_points.go index c4b4ca9..9e1c84f 100644 --- a/internal/models/customer_points.go +++ b/internal/models/customer_points.go @@ -2,66 +2,8 @@ package models import ( "time" - - "github.com/google/uuid" ) -// Existing gamification models -type CreateCustomerPointsRequest struct { - CustomerID uuid.UUID `json:"customer_id" validate:"required"` - Balance int64 `json:"balance" validate:"min=0"` -} - -type UpdateCustomerPointsRequest struct { - Balance int64 `json:"balance" validate:"min=0"` -} - -type AddCustomerPointsRequest struct { - Balance int64 `json:"balance" validate:"required,min=1"` -} - -type DeductCustomerPointsRequest struct { - Balance int64 `json:"balance" validate:"required,min=1"` -} - -type CustomerPointsResponse struct { - ID uuid.UUID `json:"id"` - CustomerID uuid.UUID `json:"customer_id"` - Balance int64 `json:"balance"` - Customer *CustomerResponse `json:"customer,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -type ListCustomerPointsQuery struct { - Page int `json:"page" validate:"min=1"` - Limit int `json:"limit" validate:"min=1,max=100"` - Search string `json:"search"` - SortBy string `json:"sort_by" validate:"omitempty,oneof=balance created_at updated_at"` - SortOrder string `json:"sort_order" validate:"omitempty,oneof=asc desc"` -} - -type PaginatedCustomerPointsResponse struct { - Data []CustomerPointsResponse `json:"data"` - TotalCount int `json:"total_count"` - Page int `json:"page"` - Limit int `json:"limit"` - TotalPages int `json:"total_pages"` -} - -// New customer API models -type GetCustomerPointsRequest struct { - // No additional fields needed - customer ID comes from JWT token -} - -type GetCustomerTokensRequest struct { - // No additional fields needed - customer ID comes from JWT token -} - -type GetCustomerWalletRequest struct { - // No additional fields needed - customer ID comes from JWT token -} - // Response Models type GetCustomerPointsResponse struct { Status string `json:"status"` diff --git a/internal/models/customer_tokens.go b/internal/models/customer_tokens.go deleted file mode 100644 index 7ee4455..0000000 --- a/internal/models/customer_tokens.go +++ /dev/null @@ -1,44 +0,0 @@ -package models - -import ( - "time" - - "github.com/google/uuid" -) - -type CreateCustomerTokensRequest struct { - CustomerID uuid.UUID `json:"customer_id" validate:"required"` - TokenType string `json:"token_type" validate:"required,oneof=SPIN RAFFLE MINIGAME"` - Balance int64 `json:"balance" validate:"min=0"` -} - -type UpdateCustomerTokensRequest struct { - Balance int64 `json:"balance" validate:"min=0"` -} - -type AddCustomerTokensRequest struct { - Tokens int64 `json:"tokens" validate:"required,min=1"` -} - -type DeductCustomerTokensRequest struct { - Tokens int64 `json:"tokens" validate:"required,min=1"` -} - -type CustomerTokensResponse struct { - ID uuid.UUID `json:"id"` - CustomerID uuid.UUID `json:"customer_id"` - TokenType string `json:"token_type"` - Balance int64 `json:"balance"` - Customer *CustomerResponse `json:"customer,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -type ListCustomerTokensQuery struct { - Page int `query:"page" validate:"min=1"` - Limit int `query:"limit" validate:"min=1,max=100"` - Search string `query:"search"` - TokenType string `query:"token_type" validate:"omitempty,oneof=SPIN RAFFLE MINIGAME"` - SortBy string `query:"sort_by" validate:"omitempty,oneof=balance token_type created_at updated_at"` - SortOrder string `query:"sort_order" validate:"omitempty,oneof=asc desc"` -} diff --git a/internal/processor/customer_points_processor.go b/internal/processor/customer_points_processor.go index bd87c33..a5a96aa 100644 --- a/internal/processor/customer_points_processor.go +++ b/internal/processor/customer_points_processor.go @@ -22,53 +22,6 @@ func NewCustomerPointsProcessor(walletQuery *WalletQueryProcessor, gameRepo *rep } } -// Existing gamification methods - placeholder implementations -func (p *CustomerPointsProcessor) CreateCustomerPoints(ctx context.Context, req *models.CreateCustomerPointsRequest) (*models.CustomerPointsResponse, error) { - // TODO: Implement this method - return nil, fmt.Errorf("not implemented") -} - -func (p *CustomerPointsProcessor) GetCustomerPoints(ctx context.Context, id uuid.UUID) (*models.CustomerPointsResponse, error) { - // TODO: Implement this method - return nil, fmt.Errorf("not implemented") -} - -func (p *CustomerPointsProcessor) GetCustomerPointsByCustomerID(ctx context.Context, customerID uuid.UUID) (*models.CustomerPointsResponse, error) { - // TODO: Implement this method - return nil, fmt.Errorf("not implemented") -} - -func (p *CustomerPointsProcessor) ListCustomerPoints(ctx context.Context, query *models.ListCustomerPointsQuery) (*models.PaginatedCustomerPointsResponse, error) { - // Return empty paginated response for now - return &models.PaginatedCustomerPointsResponse{ - Data: []models.CustomerPointsResponse{}, - TotalCount: 0, - Page: 1, - Limit: 10, - TotalPages: 0, - }, nil -} - -func (p *CustomerPointsProcessor) UpdateCustomerPoints(ctx context.Context, id uuid.UUID, req *models.UpdateCustomerPointsRequest) (*models.CustomerPointsResponse, error) { - // TODO: Implement this method - return nil, fmt.Errorf("not implemented") -} - -func (p *CustomerPointsProcessor) DeleteCustomerPoints(ctx context.Context, id uuid.UUID) error { - // TODO: Implement this method - return fmt.Errorf("not implemented") -} - -func (p *CustomerPointsProcessor) AddPoints(ctx context.Context, customerID uuid.UUID, points int64) (*models.CustomerPointsResponse, error) { - // TODO: Implement this method - return nil, fmt.Errorf("not implemented") -} - -func (p *CustomerPointsProcessor) DeductPoints(ctx context.Context, customerID uuid.UUID, points int64) (*models.CustomerPointsResponse, error) { - // TODO: Implement this method - return nil, fmt.Errorf("not implemented") -} - // The three endpoints below are the customer app's balance screens. They read the // EnakPoint & EnakCoin wallet; customer_points and customer_tokens are no longer used // for balances (docs/prd-point-coin.md §9). diff --git a/internal/processor/customer_tokens_processor.go b/internal/processor/customer_tokens_processor.go deleted file mode 100644 index f66e693..0000000 --- a/internal/processor/customer_tokens_processor.go +++ /dev/null @@ -1,198 +0,0 @@ -package processor - -import ( - "apskel-pos-be/internal/entities" - "apskel-pos-be/internal/mappers" - "apskel-pos-be/internal/models" - "apskel-pos-be/internal/repository" - "context" - "errors" - "fmt" - - "github.com/google/uuid" -) - -type CustomerTokensProcessor struct { - customerTokensRepo *repository.CustomerTokensRepository -} - -func NewCustomerTokensProcessor(customerTokensRepo *repository.CustomerTokensRepository) *CustomerTokensProcessor { - return &CustomerTokensProcessor{ - customerTokensRepo: customerTokensRepo, - } -} - -// CreateCustomerTokens creates a new customer tokens record -func (p *CustomerTokensProcessor) CreateCustomerTokens(ctx context.Context, req *models.CreateCustomerTokensRequest) (*models.CustomerTokensResponse, error) { - // Convert request to entity - customerTokens := mappers.ToCustomerTokensEntity(req) - - // Create customer tokens - err := p.customerTokensRepo.Create(ctx, customerTokens) - if err != nil { - return nil, fmt.Errorf("failed to create customer tokens: %w", err) - } - - return mappers.ToCustomerTokensResponse(customerTokens), nil -} - -// GetCustomerTokens retrieves customer tokens by ID -func (p *CustomerTokensProcessor) GetCustomerTokens(ctx context.Context, id uuid.UUID) (*models.CustomerTokensResponse, error) { - customerTokens, err := p.customerTokensRepo.GetByID(ctx, id) - if err != nil { - return nil, fmt.Errorf("customer tokens not found: %w", err) - } - - return mappers.ToCustomerTokensResponse(customerTokens), nil -} - -// GetCustomerTokensByCustomerIDAndType retrieves customer tokens by customer ID and token type -func (p *CustomerTokensProcessor) GetCustomerTokensByCustomerIDAndType(ctx context.Context, customerID uuid.UUID, tokenType string) (*models.CustomerTokensResponse, error) { - customerTokens, err := p.customerTokensRepo.EnsureCustomerTokens(ctx, customerID, entities.TokenType(tokenType)) - if err != nil { - return nil, fmt.Errorf("failed to get customer tokens: %w", err) - } - - return mappers.ToCustomerTokensResponse(customerTokens), nil -} - -// ListCustomerTokens retrieves customer tokens with pagination and filtering -func (p *CustomerTokensProcessor) ListCustomerTokens(ctx context.Context, query *models.ListCustomerTokensQuery) (*models.PaginatedResponse[models.CustomerTokensResponse], error) { - // Set default values - if query.Page <= 0 { - query.Page = 1 - } - if query.Limit <= 0 { - query.Limit = 10 - } - if query.Limit > 100 { - query.Limit = 100 - } - - offset := (query.Page - 1) * query.Limit - - // Get customer tokens from repository - customerTokens, total, err := p.customerTokensRepo.List( - ctx, - offset, - query.Limit, - query.Search, - query.TokenType, - query.SortBy, - query.SortOrder, - ) - if err != nil { - return nil, fmt.Errorf("failed to list customer tokens: %w", err) - } - - // Convert to responses - responses := mappers.ToCustomerTokensResponses(customerTokens) - - // Calculate pagination info - totalPages := int((total + int64(query.Limit) - 1) / int64(query.Limit)) - - return &models.PaginatedResponse[models.CustomerTokensResponse]{ - Data: responses, - Pagination: models.Pagination{ - Page: query.Page, - Limit: query.Limit, - Total: total, - TotalPages: totalPages, - }, - }, nil -} - -// UpdateCustomerTokens updates an existing customer tokens record -func (p *CustomerTokensProcessor) UpdateCustomerTokens(ctx context.Context, id uuid.UUID, req *models.UpdateCustomerTokensRequest) (*models.CustomerTokensResponse, error) { - // Get existing customer tokens - customerTokens, err := p.customerTokensRepo.GetByID(ctx, id) - if err != nil { - return nil, fmt.Errorf("customer tokens not found: %w", err) - } - - // Update customer tokens fields - mappers.UpdateCustomerTokensEntity(customerTokens, req) - - // Save updated customer tokens - err = p.customerTokensRepo.Update(ctx, customerTokens) - if err != nil { - return nil, fmt.Errorf("failed to update customer tokens: %w", err) - } - - return mappers.ToCustomerTokensResponse(customerTokens), nil -} - -// DeleteCustomerTokens deletes a customer tokens record -func (p *CustomerTokensProcessor) DeleteCustomerTokens(ctx context.Context, id uuid.UUID) error { - // Get existing customer tokens - _, err := p.customerTokensRepo.GetByID(ctx, id) - if err != nil { - return fmt.Errorf("customer tokens not found: %w", err) - } - - // Delete customer tokens - err = p.customerTokensRepo.Delete(ctx, id) - if err != nil { - return fmt.Errorf("failed to delete customer tokens: %w", err) - } - - return nil -} - -// AddTokens adds tokens to a customer's balance -func (p *CustomerTokensProcessor) AddTokens(ctx context.Context, customerID uuid.UUID, tokenType string, tokens int64) (*models.CustomerTokensResponse, error) { - if tokens <= 0 { - return nil, errors.New("tokens must be greater than 0") - } - - // Ensure customer tokens record exists - _, err := p.customerTokensRepo.EnsureCustomerTokens(ctx, customerID, entities.TokenType(tokenType)) - if err != nil { - return nil, fmt.Errorf("failed to ensure customer tokens: %w", err) - } - - // Add tokens - err = p.customerTokensRepo.AddTokens(ctx, customerID, entities.TokenType(tokenType), tokens) - if err != nil { - return nil, fmt.Errorf("failed to add tokens: %w", err) - } - - // Get updated customer tokens - customerTokens, err := p.customerTokensRepo.GetByCustomerIDAndType(ctx, customerID, entities.TokenType(tokenType)) - if err != nil { - return nil, fmt.Errorf("failed to get updated customer tokens: %w", err) - } - - return mappers.ToCustomerTokensResponse(customerTokens), nil -} - -// DeductTokens deducts tokens from a customer's balance -func (p *CustomerTokensProcessor) DeductTokens(ctx context.Context, customerID uuid.UUID, tokenType string, tokens int64) (*models.CustomerTokensResponse, error) { - if tokens <= 0 { - return nil, errors.New("tokens must be greater than 0") - } - - // Get current customer tokens - customerTokens, err := p.customerTokensRepo.GetByCustomerIDAndType(ctx, customerID, entities.TokenType(tokenType)) - if err != nil { - return nil, fmt.Errorf("customer tokens not found: %w", err) - } - - if customerTokens.Balance < tokens { - return nil, errors.New("insufficient tokens balance") - } - - // Deduct tokens - err = p.customerTokensRepo.DeductTokens(ctx, customerID, entities.TokenType(tokenType), tokens) - if err != nil { - return nil, fmt.Errorf("failed to deduct tokens: %w", err) - } - - // Get updated customer tokens - updatedCustomerTokens, err := p.customerTokensRepo.GetByCustomerIDAndType(ctx, customerID, entities.TokenType(tokenType)) - if err != nil { - return nil, fmt.Errorf("failed to get updated customer tokens: %w", err) - } - - return mappers.ToCustomerTokensResponse(updatedCustomerTokens), nil -} diff --git a/internal/repository/customer_points_repository.go b/internal/repository/customer_points_repository.go deleted file mode 100644 index 6ee1677..0000000 --- a/internal/repository/customer_points_repository.go +++ /dev/null @@ -1,97 +0,0 @@ -package repository - -import ( - "context" - "fmt" - - "apskel-pos-be/internal/entities" - - "gorm.io/gorm" -) - -type CustomerPointsRepository interface { - GetCustomerTotalPoints(ctx context.Context, customerID string) (int64, error) - GetCustomerTotalTokens(ctx context.Context, customerID string) (int64, error) - GetCustomerPointsHistory(ctx context.Context, customerID string, limit int) ([]entities.CustomerPoints, error) - GetCustomerTokensHistory(ctx context.Context, customerID string, limit int) ([]entities.CustomerTokens, error) -} - -type customerPointsRepository struct { - db *gorm.DB -} - -func NewCustomerPointsRepository(db *gorm.DB) CustomerPointsRepository { - return &customerPointsRepository{ - db: db, - } -} - -func (r *customerPointsRepository) GetCustomerTotalPoints(ctx context.Context, customerID string) (int64, error) { - var totalPoints int64 - - err := r.db.WithContext(ctx). - Model(&entities.CustomerPoints{}). - Where("customer_id = ?", customerID). - Select("COALESCE(SUM(balance), 0)"). - Scan(&totalPoints).Error - - if err != nil { - return 0, fmt.Errorf("failed to get customer total points: %w", err) - } - - return totalPoints, nil -} - -func (r *customerPointsRepository) GetCustomerTotalTokens(ctx context.Context, customerID string) (int64, error) { - var totalTokens int64 - - err := r.db.WithContext(ctx). - Model(&entities.CustomerTokens{}). - Where("customer_id = ?", customerID). - Select("COALESCE(SUM(balance), 0)"). - Scan(&totalTokens).Error - - if err != nil { - return 0, fmt.Errorf("failed to get customer total tokens: %w", err) - } - - return totalTokens, nil -} - -func (r *customerPointsRepository) GetCustomerPointsHistory(ctx context.Context, customerID string, limit int) ([]entities.CustomerPoints, error) { - var pointsHistory []entities.CustomerPoints - - query := r.db.WithContext(ctx). - Where("customer_id = ?", customerID). - Order("created_at DESC") - - if limit > 0 { - query = query.Limit(limit) - } - - err := query.Find(&pointsHistory).Error - if err != nil { - return nil, fmt.Errorf("failed to get customer points history: %w", err) - } - - return pointsHistory, nil -} - -func (r *customerPointsRepository) GetCustomerTokensHistory(ctx context.Context, customerID string, limit int) ([]entities.CustomerTokens, error) { - var tokensHistory []entities.CustomerTokens - - query := r.db.WithContext(ctx). - Where("customer_id = ?", customerID). - Order("created_at DESC") - - if limit > 0 { - query = query.Limit(limit) - } - - err := query.Find(&tokensHistory).Error - if err != nil { - return nil, fmt.Errorf("failed to get customer tokens history: %w", err) - } - - return tokensHistory, nil -} diff --git a/internal/repository/customer_tokens_repository.go b/internal/repository/customer_tokens_repository.go deleted file mode 100644 index de29903..0000000 --- a/internal/repository/customer_tokens_repository.go +++ /dev/null @@ -1,131 +0,0 @@ -package repository - -import ( - "apskel-pos-be/internal/entities" - "context" - "fmt" - - "github.com/google/uuid" - "gorm.io/gorm" -) - -type CustomerTokensRepository struct { - db *gorm.DB -} - -func NewCustomerTokensRepository(db *gorm.DB) *CustomerTokensRepository { - return &CustomerTokensRepository{db: db} -} - -func (r *CustomerTokensRepository) Create(ctx context.Context, customerTokens *entities.CustomerTokens) error { - return r.db.WithContext(ctx).Create(customerTokens).Error -} - -func (r *CustomerTokensRepository) GetByID(ctx context.Context, id uuid.UUID) (*entities.CustomerTokens, error) { - var customerTokens entities.CustomerTokens - err := r.db.WithContext(ctx).Preload("Customer").Where("id = ?", id).First(&customerTokens).Error - if err != nil { - return nil, err - } - return &customerTokens, nil -} - -func (r *CustomerTokensRepository) GetByCustomerIDAndType(ctx context.Context, customerID uuid.UUID, tokenType entities.TokenType) (*entities.CustomerTokens, error) { - var customerTokens entities.CustomerTokens - err := r.db.WithContext(ctx).Preload("Customer").Where("customer_id = ? AND token_type = ?", customerID, tokenType).First(&customerTokens).Error - if err != nil { - return nil, err - } - return &customerTokens, nil -} - -func (r *CustomerTokensRepository) GetByCustomerID(ctx context.Context, customerID uuid.UUID) ([]entities.CustomerTokens, error) { - var customerTokens []entities.CustomerTokens - err := r.db.WithContext(ctx).Preload("Customer").Where("customer_id = ?", customerID).Find(&customerTokens).Error - if err != nil { - return nil, err - } - return customerTokens, nil -} - -func (r *CustomerTokensRepository) List(ctx context.Context, offset, limit int, search, tokenType string, sortBy, sortOrder string) ([]entities.CustomerTokens, int64, error) { - var customerTokens []entities.CustomerTokens - var total int64 - - query := r.db.WithContext(ctx).Preload("Customer") - - if search != "" { - searchTerm := "%" + search + "%" - query = query.Joins("JOIN customers ON customer_tokens.customer_id = customers.id"). - Where("customers.name ILIKE ? OR customers.email ILIKE ?", searchTerm, searchTerm) - } - - if tokenType != "" { - query = query.Where("token_type = ?", tokenType) - } - - if err := query.Model(&entities.CustomerTokens{}).Count(&total).Error; err != nil { - return nil, 0, err - } - - if sortBy != "" { - if sortOrder == "" { - sortOrder = "asc" - } - query = query.Order(fmt.Sprintf("customer_tokens.%s %s", sortBy, sortOrder)) - } else { - query = query.Order("customer_tokens.created_at DESC") - } - - err := query.Offset(offset).Limit(limit).Find(&customerTokens).Error - if err != nil { - return nil, 0, err - } - - return customerTokens, total, nil -} - -func (r *CustomerTokensRepository) Update(ctx context.Context, customerTokens *entities.CustomerTokens) error { - return r.db.WithContext(ctx).Save(customerTokens).Error -} - -func (r *CustomerTokensRepository) Delete(ctx context.Context, id uuid.UUID) error { - return r.db.WithContext(ctx).Delete(&entities.CustomerTokens{}, id).Error -} - -func (r *CustomerTokensRepository) AddTokens(ctx context.Context, customerID uuid.UUID, tokenType entities.TokenType, tokens int64) error { - return r.db.WithContext(ctx).Model(&entities.CustomerTokens{}). - Where("customer_id = ? AND token_type = ?", customerID, tokenType). - Update("balance", gorm.Expr("balance + ?", tokens)).Error -} - -func (r *CustomerTokensRepository) DeductTokens(ctx context.Context, customerID uuid.UUID, tokenType entities.TokenType, tokens int64) error { - return r.db.WithContext(ctx).Model(&entities.CustomerTokens{}). - Where("customer_id = ? AND token_type = ? AND balance >= ?", customerID, tokenType, tokens). - Update("balance", gorm.Expr("balance - ?", tokens)).Error -} - -func (r *CustomerTokensRepository) EnsureCustomerTokens(ctx context.Context, customerID uuid.UUID, tokenType entities.TokenType) (*entities.CustomerTokens, error) { - customerTokens, err := r.GetByCustomerIDAndType(ctx, customerID, tokenType) - if err == nil { - return customerTokens, nil - } - - if err != gorm.ErrRecordNotFound { - return nil, err - } - - // Create new customer tokens record - newCustomerTokens := &entities.CustomerTokens{ - CustomerID: customerID, - TokenType: tokenType, - Balance: 0, - } - - err = r.Create(ctx, newCustomerTokens) - if err != nil { - return nil, err - } - - return newCustomerTokens, nil -} diff --git a/internal/router/router.go b/internal/router/router.go index d3a4b6f..a06e26e 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -542,31 +542,6 @@ func (r *Router) addAppRoutes(rg *gin.Engine) { gamification := protected.Group("/marketing") gamification.Use(r.authMiddleware.RequireAdminOrManager()) { - //customerPoints := gamification.Group("/customer-points") - //{ - // customerPoints.POST("", r.gamificationHandler.CreateCustomerPoints) - // customerPoints.GET("", r.gamificationHandler.ListCustomerPoints) - // customerPoints.GET("/:id", r.gamificationHandler.GetCustomerPoints) - // customerPoints.PUT("/:id", r.gamificationHandler.UpdateCustomerPoints) - // customerPoints.DELETE("/:id", r.gamificationHandler.DeleteCustomerPoints) - // customerPoints.GET("/customer/:customer_id", r.gamificationHandler.GetCustomerPointsByCustomerID) - // customerPoints.POST("/customer/:customer_id/add", r.gamificationHandler.AddCustomerPoints) - // customerPoints.POST("/customer/:customer_id/deduct", r.gamificationHandler.DeductCustomerPoints) - //} - - // Customer Tokens - //customerTokens := gamification.Group("/customer-tokens") - //{ - // customerTokens.POST("", r.gamificationHandler.CreateCustomerTokens) - // customerTokens.GET("", r.gamificationHandler.ListCustomerTokens) - // customerTokens.GET("/:id", r.gamificationHandler.GetCustomerTokens) - // customerTokens.PUT("/:id", r.gamificationHandler.UpdateCustomerTokens) - // customerTokens.DELETE("/:id", r.gamificationHandler.DeleteCustomerTokens) - // customerTokens.GET("/customer/:customer_id/type/:token_type", r.gamificationHandler.GetCustomerTokensByCustomerIDAndType) - // customerTokens.POST("/customer/:customer_id/type/:token_type/add", r.gamificationHandler.AddCustomerTokens) - // customerTokens.POST("/customer/:customer_id/type/:token_type/deduct", r.gamificationHandler.DeductCustomerTokens) - //} - // Tiers tiers := gamification.Group("/tiers") { diff --git a/internal/service/gamification_service.go b/internal/service/gamification_service.go index 6b5b22c..7096fe1 100644 --- a/internal/service/gamification_service.go +++ b/internal/service/gamification_service.go @@ -11,26 +11,6 @@ import ( ) type GamificationService interface { - // Customer Points - CreateCustomerPoints(ctx context.Context, req *contract.CreateCustomerPointsRequest) (*contract.CustomerPointsResponse, error) - GetCustomerPoints(ctx context.Context, id uuid.UUID) (*contract.CustomerPointsResponse, error) - GetCustomerPointsByCustomerID(ctx context.Context, customerID uuid.UUID) (*contract.CustomerPointsResponse, error) - ListCustomerPoints(ctx context.Context, query *contract.ListCustomerPointsRequest) (*contract.PaginatedCustomerPointsResponse, error) - UpdateCustomerPoints(ctx context.Context, id uuid.UUID, req *contract.UpdateCustomerPointsRequest) (*contract.CustomerPointsResponse, error) - DeleteCustomerPoints(ctx context.Context, id uuid.UUID) error - AddCustomerPoints(ctx context.Context, customerID uuid.UUID, req *contract.AddCustomerPointsRequest) (*contract.CustomerPointsResponse, error) - DeductCustomerPoints(ctx context.Context, customerID uuid.UUID, req *contract.DeductCustomerPointsRequest) (*contract.CustomerPointsResponse, error) - - // Customer Tokens - CreateCustomerTokens(ctx context.Context, req *contract.CreateCustomerTokensRequest) (*contract.CustomerTokensResponse, error) - GetCustomerTokens(ctx context.Context, id uuid.UUID) (*contract.CustomerTokensResponse, error) - GetCustomerTokensByCustomerIDAndType(ctx context.Context, customerID uuid.UUID, tokenType string) (*contract.CustomerTokensResponse, error) - ListCustomerTokens(ctx context.Context, query *contract.ListCustomerTokensRequest) (*contract.PaginatedCustomerTokensResponse, error) - UpdateCustomerTokens(ctx context.Context, id uuid.UUID, req *contract.UpdateCustomerTokensRequest) (*contract.CustomerTokensResponse, error) - DeleteCustomerTokens(ctx context.Context, id uuid.UUID) error - AddCustomerTokens(ctx context.Context, customerID uuid.UUID, tokenType string, req *contract.AddCustomerTokensRequest) (*contract.CustomerTokensResponse, error) - DeductCustomerTokens(ctx context.Context, customerID uuid.UUID, tokenType string, req *contract.DeductCustomerTokensRequest) (*contract.CustomerTokensResponse, error) - // Tiers CreateTier(ctx context.Context, req *contract.CreateTierRequest) (*contract.TierResponse, error) GetTier(ctx context.Context, id uuid.UUID) (*contract.TierResponse, error) @@ -72,18 +52,14 @@ type GamificationService interface { } type GamificationServiceImpl struct { - customerPointsProcessor *processor.CustomerPointsProcessor - customerTokensProcessor *processor.CustomerTokensProcessor - tierProcessor *processor.TierProcessor - gameProcessor *processor.GameProcessor - gamePrizeProcessor *processor.GamePrizeProcessor - gamePlayProcessor *processor.GamePlayProcessor - omsetTrackerProcessor *processor.OmsetTrackerProcessor + tierProcessor *processor.TierProcessor + gameProcessor *processor.GameProcessor + gamePrizeProcessor *processor.GamePrizeProcessor + gamePlayProcessor *processor.GamePlayProcessor + omsetTrackerProcessor *processor.OmsetTrackerProcessor } func NewGamificationService( - customerPointsProcessor *processor.CustomerPointsProcessor, - customerTokensProcessor *processor.CustomerTokensProcessor, tierProcessor *processor.TierProcessor, gameProcessor *processor.GameProcessor, gamePrizeProcessor *processor.GamePrizeProcessor, @@ -91,144 +67,14 @@ func NewGamificationService( omsetTrackerProcessor *processor.OmsetTrackerProcessor, ) *GamificationServiceImpl { return &GamificationServiceImpl{ - customerPointsProcessor: customerPointsProcessor, - customerTokensProcessor: customerTokensProcessor, - tierProcessor: tierProcessor, - gameProcessor: gameProcessor, - gamePrizeProcessor: gamePrizeProcessor, - gamePlayProcessor: gamePlayProcessor, - omsetTrackerProcessor: omsetTrackerProcessor, + tierProcessor: tierProcessor, + gameProcessor: gameProcessor, + gamePrizeProcessor: gamePrizeProcessor, + gamePlayProcessor: gamePlayProcessor, + omsetTrackerProcessor: omsetTrackerProcessor, } } -// Customer Points Service Methods -func (s *GamificationServiceImpl) CreateCustomerPoints(ctx context.Context, req *contract.CreateCustomerPointsRequest) (*contract.CustomerPointsResponse, error) { - modelReq := transformer.CreateCustomerPointsRequestToModel(req) - response, err := s.customerPointsProcessor.CreateCustomerPoints(ctx, modelReq) - if err != nil { - return nil, err - } - return transformer.CustomerPointsModelToResponse(response), nil -} - -func (s *GamificationServiceImpl) GetCustomerPoints(ctx context.Context, id uuid.UUID) (*contract.CustomerPointsResponse, error) { - response, err := s.customerPointsProcessor.GetCustomerPoints(ctx, id) - if err != nil { - return nil, err - } - return transformer.CustomerPointsModelToResponse(response), nil -} - -func (s *GamificationServiceImpl) GetCustomerPointsByCustomerID(ctx context.Context, customerID uuid.UUID) (*contract.CustomerPointsResponse, error) { - response, err := s.customerPointsProcessor.GetCustomerPointsByCustomerID(ctx, customerID) - if err != nil { - return nil, err - } - return transformer.CustomerPointsModelToResponse(response), nil -} - -func (s *GamificationServiceImpl) ListCustomerPoints(ctx context.Context, query *contract.ListCustomerPointsRequest) (*contract.PaginatedCustomerPointsResponse, error) { - modelQuery := transformer.ListCustomerPointsRequestToModel(query) - response, err := s.customerPointsProcessor.ListCustomerPoints(ctx, modelQuery) - if err != nil { - return nil, err - } - return transformer.PaginatedCustomerPointsResponseToContract(response), nil -} - -func (s *GamificationServiceImpl) UpdateCustomerPoints(ctx context.Context, id uuid.UUID, req *contract.UpdateCustomerPointsRequest) (*contract.CustomerPointsResponse, error) { - modelReq := transformer.UpdateCustomerPointsRequestToModel(req) - response, err := s.customerPointsProcessor.UpdateCustomerPoints(ctx, id, modelReq) - if err != nil { - return nil, err - } - return transformer.CustomerPointsModelToResponse(response), nil -} - -func (s *GamificationServiceImpl) DeleteCustomerPoints(ctx context.Context, id uuid.UUID) error { - return s.customerPointsProcessor.DeleteCustomerPoints(ctx, id) -} - -func (s *GamificationServiceImpl) AddCustomerPoints(ctx context.Context, customerID uuid.UUID, req *contract.AddCustomerPointsRequest) (*contract.CustomerPointsResponse, error) { - response, err := s.customerPointsProcessor.AddPoints(ctx, customerID, req.Points) - if err != nil { - return nil, err - } - return transformer.CustomerPointsModelToResponse(response), nil -} - -func (s *GamificationServiceImpl) DeductCustomerPoints(ctx context.Context, customerID uuid.UUID, req *contract.DeductCustomerPointsRequest) (*contract.CustomerPointsResponse, error) { - response, err := s.customerPointsProcessor.DeductPoints(ctx, customerID, req.Points) - if err != nil { - return nil, err - } - return transformer.CustomerPointsModelToResponse(response), nil -} - -// Customer Tokens Service Methods -func (s *GamificationServiceImpl) CreateCustomerTokens(ctx context.Context, req *contract.CreateCustomerTokensRequest) (*contract.CustomerTokensResponse, error) { - modelReq := transformer.CreateCustomerTokensRequestToModel(req) - response, err := s.customerTokensProcessor.CreateCustomerTokens(ctx, modelReq) - if err != nil { - return nil, err - } - return transformer.CustomerTokensModelToResponse(response), nil -} - -func (s *GamificationServiceImpl) GetCustomerTokens(ctx context.Context, id uuid.UUID) (*contract.CustomerTokensResponse, error) { - response, err := s.customerTokensProcessor.GetCustomerTokens(ctx, id) - if err != nil { - return nil, err - } - return transformer.CustomerTokensModelToResponse(response), nil -} - -func (s *GamificationServiceImpl) GetCustomerTokensByCustomerIDAndType(ctx context.Context, customerID uuid.UUID, tokenType string) (*contract.CustomerTokensResponse, error) { - response, err := s.customerTokensProcessor.GetCustomerTokensByCustomerIDAndType(ctx, customerID, tokenType) - if err != nil { - return nil, err - } - return transformer.CustomerTokensModelToResponse(response), nil -} - -func (s *GamificationServiceImpl) ListCustomerTokens(ctx context.Context, query *contract.ListCustomerTokensRequest) (*contract.PaginatedCustomerTokensResponse, error) { - modelQuery := transformer.ListCustomerTokensRequestToModel(query) - response, err := s.customerTokensProcessor.ListCustomerTokens(ctx, modelQuery) - if err != nil { - return nil, err - } - return transformer.PaginatedCustomerTokensResponseToContract(response), nil -} - -func (s *GamificationServiceImpl) UpdateCustomerTokens(ctx context.Context, id uuid.UUID, req *contract.UpdateCustomerTokensRequest) (*contract.CustomerTokensResponse, error) { - modelReq := transformer.UpdateCustomerTokensRequestToModel(req) - response, err := s.customerTokensProcessor.UpdateCustomerTokens(ctx, id, modelReq) - if err != nil { - return nil, err - } - return transformer.CustomerTokensModelToResponse(response), nil -} - -func (s *GamificationServiceImpl) DeleteCustomerTokens(ctx context.Context, id uuid.UUID) error { - return s.customerTokensProcessor.DeleteCustomerTokens(ctx, id) -} - -func (s *GamificationServiceImpl) AddCustomerTokens(ctx context.Context, customerID uuid.UUID, tokenType string, req *contract.AddCustomerTokensRequest) (*contract.CustomerTokensResponse, error) { - response, err := s.customerTokensProcessor.AddTokens(ctx, customerID, tokenType, req.Tokens) - if err != nil { - return nil, err - } - return transformer.CustomerTokensModelToResponse(response), nil -} - -func (s *GamificationServiceImpl) DeductCustomerTokens(ctx context.Context, customerID uuid.UUID, tokenType string, req *contract.DeductCustomerTokensRequest) (*contract.CustomerTokensResponse, error) { - response, err := s.customerTokensProcessor.DeductTokens(ctx, customerID, tokenType, req.Tokens) - if err != nil { - return nil, err - } - return transformer.CustomerTokensModelToResponse(response), nil -} - // Tier Service Methods func (s *GamificationServiceImpl) CreateTier(ctx context.Context, req *contract.CreateTierRequest) (*contract.TierResponse, error) { modelReq := transformer.CreateTierRequestToModel(req) diff --git a/internal/transformer/gamification_transformer.go b/internal/transformer/gamification_transformer.go index a1a0dcd..0b66a63 100644 --- a/internal/transformer/gamification_transformer.go +++ b/internal/transformer/gamification_transformer.go @@ -5,131 +5,6 @@ import ( "apskel-pos-be/internal/models" ) -// Customer Points Transformers -func CreateCustomerPointsRequestToModel(req *contract.CreateCustomerPointsRequest) *models.CreateCustomerPointsRequest { - return &models.CreateCustomerPointsRequest{ - CustomerID: req.CustomerID, - Balance: req.Balance, - } -} - -func UpdateCustomerPointsRequestToModel(req *contract.UpdateCustomerPointsRequest) *models.UpdateCustomerPointsRequest { - return &models.UpdateCustomerPointsRequest{ - Balance: req.Balance, - } -} - -func ListCustomerPointsRequestToModel(req *contract.ListCustomerPointsRequest) *models.ListCustomerPointsQuery { - return &models.ListCustomerPointsQuery{ - Page: req.Page, - Limit: req.Limit, - Search: req.Search, - SortBy: req.SortBy, - SortOrder: req.SortOrder, - } -} - -func CustomerPointsModelToResponse(model *models.CustomerPointsResponse) *contract.CustomerPointsResponse { - if model == nil { - return nil - } - - var customer *contract.CustomerResponse - if model.Customer != nil { - customer = CustomerModelToResponse(model.Customer) - } - - return &contract.CustomerPointsResponse{ - ID: model.ID, - CustomerID: model.CustomerID, - Balance: model.Balance, - Customer: customer, - CreatedAt: model.CreatedAt, - UpdatedAt: model.UpdatedAt, - } -} - -func PaginatedCustomerPointsResponseToContract(model *models.PaginatedCustomerPointsResponse) *contract.PaginatedCustomerPointsResponse { - if model == nil { - return nil - } - - responses := make([]contract.CustomerPointsResponse, len(model.Data)) - for i, item := range model.Data { - responses[i] = *CustomerPointsModelToResponse(&item) - } - - return &contract.PaginatedCustomerPointsResponse{ - Data: responses, - TotalCount: model.TotalCount, - Page: model.Page, - Limit: model.Limit, - TotalPages: model.TotalPages, - } -} - -// Customer Tokens Transformers -func CreateCustomerTokensRequestToModel(req *contract.CreateCustomerTokensRequest) *models.CreateCustomerTokensRequest { - return &models.CreateCustomerTokensRequest{ - CustomerID: req.CustomerID, - TokenType: req.TokenType, - Balance: req.Balance, - } -} - -func UpdateCustomerTokensRequestToModel(req *contract.UpdateCustomerTokensRequest) *models.UpdateCustomerTokensRequest { - return &models.UpdateCustomerTokensRequest{ - Balance: req.Balance, - } -} - -func ListCustomerTokensRequestToModel(req *contract.ListCustomerTokensRequest) *models.ListCustomerTokensQuery { - return &models.ListCustomerTokensQuery{ - Page: req.Page, - Limit: req.Limit, - Search: req.Search, - TokenType: req.TokenType, - SortBy: req.SortBy, - SortOrder: req.SortOrder, - } -} - -func CustomerTokensModelToResponse(model *models.CustomerTokensResponse) *contract.CustomerTokensResponse { - if model == nil { - return nil - } - - var customer *contract.CustomerResponse - if model.Customer != nil { - customer = CustomerModelToResponse(model.Customer) - } - - return &contract.CustomerTokensResponse{ - ID: model.ID, - CustomerID: model.CustomerID, - TokenType: model.TokenType, - Balance: model.Balance, - Customer: customer, - CreatedAt: model.CreatedAt, - UpdatedAt: model.UpdatedAt, - } -} - -func PaginatedCustomerTokensResponseToContract(model *models.PaginatedResponse[models.CustomerTokensResponse]) *contract.PaginatedCustomerTokensResponse { - responses := make([]contract.CustomerTokensResponse, len(model.Data)) - for i, item := range model.Data { - responses[i] = *CustomerTokensModelToResponse(&item) - } - - return &contract.PaginatedCustomerTokensResponse{ - Data: responses, - TotalCount: int(model.Pagination.Total), - Page: model.Pagination.Page, - Limit: model.Pagination.Limit, - TotalPages: model.Pagination.TotalPages, - } -} - // Tier Transformers func CreateTierRequestToModel(req *contract.CreateTierRequest) *models.CreateTierRequest { return &models.CreateTierRequest{ diff --git a/internal/validator/gamification_validator.go b/internal/validator/gamification_validator.go index 2ce5a44..e0fc023 100644 --- a/internal/validator/gamification_validator.go +++ b/internal/validator/gamification_validator.go @@ -9,20 +9,6 @@ import ( ) type GamificationValidator interface { - // Customer Points - ValidateCreateCustomerPointsRequest(req *contract.CreateCustomerPointsRequest) (error, string) - ValidateUpdateCustomerPointsRequest(req *contract.UpdateCustomerPointsRequest) (error, string) - ValidateListCustomerPointsRequest(req *contract.ListCustomerPointsRequest) (error, string) - ValidateAddCustomerPointsRequest(req *contract.AddCustomerPointsRequest) (error, string) - ValidateDeductCustomerPointsRequest(req *contract.DeductCustomerPointsRequest) (error, string) - - // Customer Tokens - ValidateCreateCustomerTokensRequest(req *contract.CreateCustomerTokensRequest) (error, string) - ValidateUpdateCustomerTokensRequest(req *contract.UpdateCustomerTokensRequest) (error, string) - ValidateListCustomerTokensRequest(req *contract.ListCustomerTokensRequest) (error, string) - ValidateAddCustomerTokensRequest(req *contract.AddCustomerTokensRequest) (error, string) - ValidateDeductCustomerTokensRequest(req *contract.DeductCustomerTokensRequest) (error, string) - // Tiers ValidateCreateTierRequest(req *contract.CreateTierRequest) (error, string) ValidateUpdateTierRequest(req *contract.UpdateTierRequest) (error, string) @@ -60,152 +46,6 @@ func NewGamificationValidator() *GamificationValidatorImpl { } } -// Customer Points Validators -func (v *GamificationValidatorImpl) ValidateCreateCustomerPointsRequest(req *contract.CreateCustomerPointsRequest) (error, string) { - if err := v.validate.Struct(req); err != nil { - return err, "VALIDATION_ERROR" - } - - if req.Balance < 0 { - return errors.New("balance cannot be negative"), "INVALID_BALANCE" - } - - return nil, "" -} - -func (v *GamificationValidatorImpl) ValidateUpdateCustomerPointsRequest(req *contract.UpdateCustomerPointsRequest) (error, string) { - if err := v.validate.Struct(req); err != nil { - return err, "VALIDATION_ERROR" - } - - if req.Balance < 0 { - return errors.New("balance cannot be negative"), "INVALID_BALANCE" - } - - return nil, "" -} - -func (v *GamificationValidatorImpl) ValidateListCustomerPointsRequest(req *contract.ListCustomerPointsRequest) (error, string) { - if err := v.validate.Struct(req); err != nil { - return err, "VALIDATION_ERROR" - } - - if req.Page <= 0 { - req.Page = 1 - } - if req.Limit <= 0 { - req.Limit = 10 - } - if req.Limit > 100 { - req.Limit = 100 - } - - return nil, "" -} - -func (v *GamificationValidatorImpl) ValidateAddCustomerPointsRequest(req *contract.AddCustomerPointsRequest) (error, string) { - if err := v.validate.Struct(req); err != nil { - return err, "VALIDATION_ERROR" - } - - if req.Points <= 0 { - return errors.New("points must be greater than 0"), "INVALID_POINTS" - } - - return nil, "" -} - -func (v *GamificationValidatorImpl) ValidateDeductCustomerPointsRequest(req *contract.DeductCustomerPointsRequest) (error, string) { - if err := v.validate.Struct(req); err != nil { - return err, "VALIDATION_ERROR" - } - - if req.Points <= 0 { - return errors.New("points must be greater than 0"), "INVALID_POINTS" - } - - return nil, "" -} - -// Customer Tokens Validators -func (v *GamificationValidatorImpl) ValidateCreateCustomerTokensRequest(req *contract.CreateCustomerTokensRequest) (error, string) { - if err := v.validate.Struct(req); err != nil { - return err, "VALIDATION_ERROR" - } - - if req.Balance < 0 { - return errors.New("balance cannot be negative"), "INVALID_BALANCE" - } - - validTokenTypes := []string{"SPIN", "RAFFLE", "MINIGAME"} - if !contains(validTokenTypes, req.TokenType) { - return errors.New("invalid token type"), "INVALID_TOKEN_TYPE" - } - - return nil, "" -} - -func (v *GamificationValidatorImpl) ValidateUpdateCustomerTokensRequest(req *contract.UpdateCustomerTokensRequest) (error, string) { - if err := v.validate.Struct(req); err != nil { - return err, "VALIDATION_ERROR" - } - - if req.Balance < 0 { - return errors.New("balance cannot be negative"), "INVALID_BALANCE" - } - - return nil, "" -} - -func (v *GamificationValidatorImpl) ValidateListCustomerTokensRequest(req *contract.ListCustomerTokensRequest) (error, string) { - if err := v.validate.Struct(req); err != nil { - return err, "VALIDATION_ERROR" - } - - if req.Page <= 0 { - req.Page = 1 - } - if req.Limit <= 0 { - req.Limit = 10 - } - if req.Limit > 100 { - req.Limit = 100 - } - - if req.TokenType != "" { - validTokenTypes := []string{"SPIN", "RAFFLE", "MINIGAME"} - if !contains(validTokenTypes, req.TokenType) { - return errors.New("invalid token type"), "INVALID_TOKEN_TYPE" - } - } - - return nil, "" -} - -func (v *GamificationValidatorImpl) ValidateAddCustomerTokensRequest(req *contract.AddCustomerTokensRequest) (error, string) { - if err := v.validate.Struct(req); err != nil { - return err, "VALIDATION_ERROR" - } - - if req.Tokens <= 0 { - return errors.New("tokens must be greater than 0"), "INVALID_TOKENS" - } - - return nil, "" -} - -func (v *GamificationValidatorImpl) ValidateDeductCustomerTokensRequest(req *contract.DeductCustomerTokensRequest) (error, string) { - if err := v.validate.Struct(req); err != nil { - return err, "VALIDATION_ERROR" - } - - if req.Tokens <= 0 { - return errors.New("tokens must be greater than 0"), "INVALID_TOKENS" - } - - return nil, "" -} - // Tier Validators func (v *GamificationValidatorImpl) ValidateCreateTierRequest(req *contract.CreateTierRequest) (error, string) { if err := v.validate.Struct(req); err != nil {