package handler import ( "errors" "apskel-pos-be/internal/constants" "apskel-pos-be/internal/contract" "apskel-pos-be/internal/logger" "apskel-pos-be/internal/models" "apskel-pos-be/internal/processor" "apskel-pos-be/internal/repository" "apskel-pos-be/internal/service" "apskel-pos-be/internal/util" "github.com/gin-gonic/gin" ) type CustomerPointsHandler struct { customerPointsService service.CustomerPointsService } func NewCustomerPointsHandler(customerPointsService service.CustomerPointsService) *CustomerPointsHandler { return &CustomerPointsHandler{ customerPointsService: customerPointsService, } } func (h *CustomerPointsHandler) GetCustomerPoints(c *gin.Context) { ctx := c.Request.Context() // Get customer ID from context (set by middleware) customerID, exists := c.Get("customer_id") if !exists { logger.FromContext(ctx).Error("Customer ID not found in context") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Customer ID not found"), }), "CustomerPointsHandler::GetCustomerPoints") return } customerIDStr, ok := customerID.(string) if !ok { logger.FromContext(ctx).Error("Invalid customer ID type in context") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Invalid customer ID"), }), "CustomerPointsHandler::GetCustomerPoints") return } response, err := h.customerPointsService.GetCustomerPoints(ctx, customerIDStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("CustomerPointsHandler::GetCustomerPoints -> service call failed") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(walletErrorCode(err), constants.RequestEntity, err.Error()), }), "CustomerPointsHandler::GetCustomerPoints") return } util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "CustomerPointsHandler::GetCustomerPoints") } func (h *CustomerPointsHandler) GetCustomerTokens(c *gin.Context) { ctx := c.Request.Context() // Get customer ID from context (set by middleware) customerID, exists := c.Get("customer_id") if !exists { logger.FromContext(ctx).Error("Customer ID not found in context") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Customer ID not found"), }), "CustomerPointsHandler::GetCustomerTokens") return } customerIDStr, ok := customerID.(string) if !ok { logger.FromContext(ctx).Error("Invalid customer ID type in context") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Invalid customer ID"), }), "CustomerPointsHandler::GetCustomerTokens") return } response, err := h.customerPointsService.GetCustomerTokens(ctx, customerIDStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("CustomerPointsHandler::GetCustomerTokens -> service call failed") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(walletErrorCode(err), constants.RequestEntity, err.Error()), }), "CustomerPointsHandler::GetCustomerTokens") return } util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "CustomerPointsHandler::GetCustomerTokens") } func (h *CustomerPointsHandler) GetCustomerWallet(c *gin.Context) { ctx := c.Request.Context() // Get customer ID from context (set by middleware) customerID, exists := c.Get("customer_id") if !exists { logger.FromContext(ctx).Error("Customer ID not found in context") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Customer ID not found"), }), "CustomerPointsHandler::GetCustomerWallet") return } customerIDStr, ok := customerID.(string) if !ok { logger.FromContext(ctx).Error("Invalid customer ID type in context") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Invalid customer ID"), }), "CustomerPointsHandler::GetCustomerWallet") return } response, err := h.customerPointsService.GetCustomerWallet(ctx, customerIDStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("CustomerPointsHandler::GetCustomerWallet -> service call failed") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(walletErrorCode(err), constants.RequestEntity, err.Error()), }), "CustomerPointsHandler::GetCustomerWallet") return } util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "CustomerPointsHandler::GetCustomerWallet") } func (h *CustomerPointsHandler) GetCustomerGames(c *gin.Context) { ctx := c.Request.Context() response, err := h.customerPointsService.GetCustomerGames(ctx) if err != nil { logger.FromContext(ctx).WithError(err).Error("CustomerPointsHandler::GetCustomerGames -> service call failed") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.InternalServerErrorCode, constants.RequestEntity, err.Error()), }), "CustomerPointsHandler::GetCustomerGames") return } util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "CustomerPointsHandler::GetCustomerGames") } func (h *CustomerPointsHandler) GetFerrisWheelGame(c *gin.Context) { ctx := c.Request.Context() response, err := h.customerPointsService.GetFerrisWheelGame(ctx) if err != nil { logger.FromContext(ctx).WithError(err).Error("CustomerPointsHandler::GetFerrisWheelGame -> service call failed") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.InternalServerErrorCode, constants.RequestEntity, err.Error()), }), "CustomerPointsHandler::GetFerrisWheelGame") return } util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "CustomerPointsHandler::GetFerrisWheelGame") } // GetCustomerWalletTransactions is GET /customer/wallet/transactions: the ledger, newest // first, filterable by currency, type and date (docs/prd-point-coin.md F6). func (h *CustomerPointsHandler) GetCustomerWalletTransactions(c *gin.Context) { ctx := c.Request.Context() customerID, ok := c.Get("customer_id") customerIDStr, isString := customerID.(string) if !ok || !isString { logger.FromContext(ctx).Error("Customer ID not found in context") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Customer ID not found"), }), "CustomerPointsHandler::GetCustomerWalletTransactions") return } var query models.ListCustomerWalletTransactionsQuery if err := c.ShouldBindQuery(&query); err != nil { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.MalformedFieldErrorCode, constants.RequestEntity, err.Error()), }), "CustomerPointsHandler::GetCustomerWalletTransactions") return } response, err := h.customerPointsService.GetCustomerWalletTransactions(ctx, customerIDStr, query) if err != nil { logger.FromContext(ctx).WithError(err).Error("CustomerPointsHandler::GetCustomerWalletTransactions -> service call failed") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(walletErrorCode(err), constants.RequestEntity, err.Error()), }), "CustomerPointsHandler::GetCustomerWalletTransactions") return } util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "CustomerPointsHandler::GetCustomerWalletTransactions") } // walletErrorCode tells a bad request apart from a server failure on the wallet // endpoints. func walletErrorCode(err error) string { switch { case errors.Is(err, processor.ErrInvalidWalletQuery): return constants.ValidationErrorCode case errors.Is(err, repository.ErrWalletNotFound): return constants.NotFoundErrorCode default: return constants.InternalServerErrorCode } } // GetCustomerWalletExpiring is GET /customer/wallet/expiring: what will expire, per // currency and day (docs/prd-point-coin.md F6). func (h *CustomerPointsHandler) GetCustomerWalletExpiring(c *gin.Context) { ctx := c.Request.Context() customerID, ok := c.Get("customer_id") customerIDStr, isString := customerID.(string) if !ok || !isString { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Customer ID not found"), }), "CustomerPointsHandler::GetCustomerWalletExpiring") return } response, err := h.customerPointsService.GetCustomerWalletExpiring(ctx, customerIDStr) if err != nil { logger.FromContext(ctx).WithError(err).Error("CustomerPointsHandler::GetCustomerWalletExpiring -> service call failed") util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(walletErrorCode(err), constants.RequestEntity, err.Error()), }), "CustomerPointsHandler::GetCustomerWalletExpiring") return } util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "CustomerPointsHandler::GetCustomerWalletExpiring") }