aboutsummaryrefslogtreecommitdiffstats
path: root/backend/internal/api/handlers/account_handler.go
blob: 5a92ef66c5fff0235aca795b37bc67048ad7ed9f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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"})
}