package accounts import ( "net/http" "strconv" "finance/backend/internal/database" "finance/backend/internal/models" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // GetAccounts returns all accounts for the authenticated user func GetAccounts() gin.HandlerFunc { return func(c *gin.Context) { // Get user from context (set by auth middleware) user, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) return } userObj := user.(models.User) var accounts []models.Account // Fetch all accounts for the user if err := database.DB.Where("user_id = ?", userObj.ID).Find(&accounts).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch accounts"}) return } c.JSON(http.StatusOK, gin.H{"accounts": accounts}) } } // GetAccountByID returns a specific account by ID func GetAccountByID() gin.HandlerFunc { return func(c *gin.Context) { // Get user from context (set by auth middleware) user, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) return } userObj := user.(models.User) // Get account ID from URL parameter accountID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid account ID format"}) return } var account models.Account // Fetch the account and ensure it belongs to the authenticated user if err := database.DB.Where("id = ? AND user_id = ?", accountID, userObj.ID).First(&account).Error; err != nil { if err == gorm.ErrRecordNotFound { c.JSON(http.StatusNotFound, gin.H{"error": "Account not found"}) } else { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch account"}) } return } c.JSON(http.StatusOK, gin.H{"account": account}) } } // CreateAccount creates a new account func CreateAccount() gin.HandlerFunc { return func(c *gin.Context) { // Get user from context (set by auth middleware) user, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) return } userObj := user.(models.User) // Define a struct to bind the request JSON var input struct { Name string `json:"name" binding:"required"` Type string `json:"type" binding:"required"` // e.g., "Bank", "Credit Card", "Cash", "Loan", "Income Source" Balance int64 `json:"balance" binding:"required"` } // Bind JSON to struct if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Create account object account := models.Account{ UserID: userObj.ID, Name: input.Name, Type: input.Type, Balance: input.Balance, } // Save to database if err := database.DB.Create(&account).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create account"}) return } c.JSON(http.StatusCreated, gin.H{"account": account}) } } // UpdateAccount updates an existing account func UpdateAccount() gin.HandlerFunc { return func(c *gin.Context) { // Get user from context (set by auth middleware) user, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) return } userObj := user.(models.User) // Get account ID from URL parameter accountID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid account ID format"}) return } // Check if the account exists and belongs to the user var account models.Account if err := database.DB.Where("id = ? AND user_id = ?", accountID, userObj.ID).First(&account).Error; err != nil { if err == gorm.ErrRecordNotFound { c.JSON(http.StatusNotFound, gin.H{"error": "Account not found"}) } else { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch account"}) } return } // Define a struct to bind the request JSON var input struct { Name string `json:"name"` Type string `json:"type"` Balance int64 `json:"balance"` } // Bind JSON to struct 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, we should allow setting it to 0, so check if it was provided if c.Request.Method == "PUT" || c.Request.Method == "PATCH" { if c.PostForm("balance") != "" || c.GetHeader("Content-Type") == "application/json" { account.Balance = input.Balance } } // Save updates to database if err := database.DB.Save(&account).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update account"}) return } c.JSON(http.StatusOK, gin.H{"account": account}) } } // DeleteAccount deletes an account func DeleteAccount() gin.HandlerFunc { return func(c *gin.Context) { // Get user from context (set by auth middleware) user, exists := c.Get("user") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"}) return } userObj := user.(models.User) // Get account ID from URL parameter accountID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid account ID format"}) return } // Check if the account exists and belongs to the user var account models.Account if err := database.DB.Where("id = ? AND user_id = ?", accountID, userObj.ID).First(&account).Error; err != nil { if err == gorm.ErrRecordNotFound { c.JSON(http.StatusNotFound, gin.H{"error": "Account not found"}) } else { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch account"}) } return } // Delete the account if err := database.DB.Delete(&account).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete account"}) return } c.JSON(http.StatusOK, gin.H{"message": "Account deleted successfully"}) } }