Yimaru-BackEnd/internal/web_server/handlers/transfer_handler.go

117 lines
4.0 KiB
Go

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)
}
}