package handlers import ( "log" "net/http" "strconv" "finance/backend/internal/database" "finance/backend/internal/models" "github.com/gin-gonic/gin" ) // AccountHandler handles account-related operations type AccountHandler struct { } // NewAccountHandler creates and returns a new AccountHandler instance func NewAccountHandler() *AccountHandler { return &AccountHandler{} } // GetAccounts retrieves all accounts for the authenticated user func (h *AccountHandler) GetAccounts(c *gin.Context) { userID := c.MustGet("userID").(uint) var accounts []models.Account // Fetch accounts for the current user if err := database.DB.Where("user_id = ?", userID).Find(&accounts).Error; err != nil { log.Printf("Error fetching accounts for user %d: %v", userID, err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get accounts"}) return } c.JSON(http.StatusOK, accounts) } // GetAccountByID retrieves a specific account by ID for the authenticated user func (h *AccountHandler) GetAccountByID(c *gin.Context) { userID := c.MustGet("userID").(uint) accountID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid account ID"}) return } var account models.Account if err := database.DB.Where("id = ? AND user_id = ?", accountID, userID).First(&account).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Account not found"}) return } c.JSON(http.StatusOK, account) } // CreateAccount creates a new financial account for the authenticated user func (h *AccountHandler) CreateAccount(c *gin.Context) { userID := c.MustGet("userID").(uint) // Define input structure type CreateAccountInput struct { Name string `json:"name" binding:"required"` Type string `json:"type" binding:"required"` Balance int64 `json:"balance"` } var input CreateAccountInput if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Create new account account := models.Account{ UserID: userID, Name: input.Name, Type: input.Type, Balance: input.Balance, } if err := database.DB.Create(&account).Error; err != nil { log.Printf("Error creating account for user %d: %v", userID, err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create account"}) return } c.JSON(http.StatusCreated, account) } // UpdateAccount updates an existing account for the authenticated user func (h *AccountHandler) UpdateAccount(c *gin.Context) { userID := c.MustGet("userID").(uint) accountID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid account ID"}) return } // Find account var account models.Account if err := database.DB.Where("id = ? AND user_id = ?", accountID, userID).First(&account).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Account not found"}) return } // Define update structure type UpdateAccountInput struct { Name string `json:"name"` Type string `json:"type"` Balance int64 `json:"balance"` } var input UpdateAccountInput if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Update fields if provided if input.Name != "" { account.Name = input.Name } if input.Type != "" { account.Type = input.Type } // For balance updates, we'll accept zero values, so we update unconditionally account.Balance = input.Balance if err := database.DB.Save(&account).Error; err != nil { log.Printf("Error updating account ID %d for user %d: %v", accountID, userID, err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update account"}) return } c.JSON(http.StatusOK, account) } // DeleteAccount deletes an account belonging to the authenticated user func (h *AccountHandler) DeleteAccount(c *gin.Context) { userID := c.MustGet("userID").(uint) accountID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid account ID"}) return } // Check if account exists and belongs to user var account models.Account if err := database.DB.Where("id = ? AND user_id = ?", accountID, userID).First(&account).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Account not found"}) return } // Delete account if err := database.DB.Delete(&account).Error; err != nil { log.Printf("Error deleting account ID %d for user %d: %v", accountID, userID, err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete account"}) return } c.JSON(http.StatusOK, gin.H{"message": "Account deleted successfully"}) }