package handlers import ( "log/slog" "time" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/branch" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/response" customvalidator "github.com/SamuelTariku/FortuneBet-Backend/internal/web_server/validator" "github.com/gofiber/fiber/v2" ) type TransferRes struct { ID int64 `json:"id" example:"1"` Amount float32 `json:"amount" example:"100.0"` Verified bool `json:"verified" example:"true"` Type string `json:"type" example:"transfer"` PaymentMethod string `json:"payment_method" example:"bank"` ReceiverWalletID int64 `json:"receiver_wallet_id" example:"1"` SenderWalletID *int64 `json:"sender_wallet_id" example:"1"` CashierID *int64 `json:"cashier_id" example:"789"` CreatedAt time.Time `json:"created_at" example:"2025-04-08T12:00:00Z"` UpdatedAt time.Time `json:"updated_at" example:"2025-04-08T12:30:00Z"` } func convertTransfer(transfer domain.Transfer) TransferRes { var senderWalletID *int64 if transfer.SenderWalletID.Valid { senderWalletID = &transfer.SenderWalletID.Value } var cashierID *int64 if transfer.CashierID.Valid { cashierID = &transfer.CashierID.Value } return TransferRes{ ID: transfer.ID, Amount: transfer.Amount.Float64(), Verified: transfer.Verified, Type: string(transfer.Type), PaymentMethod: string(transfer.PaymentMethod), ReceiverWalletID: transfer.ReceiverWalletID, SenderWalletID: senderWalletID, CashierID: cashierID, CreatedAt: transfer.CreatedAt, UpdatedAt: transfer.UpdatedAt, } } type CreateTransferReq struct { receiverID int64 amount float64 paymentMethod string } // TransferToWallet godoc // @Summary Create a transfer to wallet // @Description Create a transfer to wallet // @Tags transfer // @Accept json // @Produce json // @Param transferToWallet body CreateTransferReq true "Create Transfer" // @Success 200 {object} TransferRes // @Failure 400 {object} response.APIResponse // @Failure 500 {object} response.APIResponse // @Router /transfer/wallet [post] func TransferToWallet(logger *slog.Logger, walletSvc *wallet.Service, branchSvc *branch.Service, validator *customvalidator.CustomValidator) fiber.Handler { return func(c *fiber.Ctx) error { // Get sender ID from the cashier userID := c.Locals("user_id").(int64) role := string(c.Locals("role").(domain.Role)) branchID := c.Locals("branch_id").(int64) if role == string(domain.RoleCustomer) { logger.Error("Unauthorized access", "userID", userID, "role", role) return response.WriteJSON(c, fiber.StatusUnauthorized, "Unauthorized access", nil, nil) } branchWallet, err := branchSvc.GetBranchByID(c.Context(), branchID) if err != nil { logger.Error("Failed to get branch wallet", "branch ID", branchID, "error", err) return response.WriteJSON(c, fiber.StatusInternalServerError, "Failed to retrieve branch wallet", err, nil) } var req CreateTransferReq if err := c.BodyParser(&req); err != nil { logger.Error("CreateTransferReq failed", "error", err) return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "Invalid request", }) } valErrs, ok := validator.Validate(c, req) if !ok { response.WriteJSON(c, fiber.StatusBadRequest, "Invalid request", valErrs, nil) return nil } transfer, err := walletSvc.TransferToWallet(c.Context(), branchWallet.ID, req.receiverID, domain.Currency(req.amount), domain.PaymentMethod(req.paymentMethod), domain.ValidInt64{Value: userID, Valid: true}) if !ok { response.WriteJSON(c, fiber.StatusInternalServerError, "Transfer Failed", err, nil) return nil } res := convertTransfer(transfer) return response.WriteJSON(c, fiber.StatusOK, "Transfer Successful", res, nil) } }