diff options
Diffstat (limited to 'backend/internal/api/v1/loans')
-rw-r--r-- | backend/internal/api/v1/loans/loans.go | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/backend/internal/api/v1/loans/loans.go b/backend/internal/api/v1/loans/loans.go new file mode 100644 index 0000000..06d96b0 --- /dev/null +++ b/backend/internal/api/v1/loans/loans.go @@ -0,0 +1,248 @@ +package loans + +import ( + "net/http" + "strconv" + "time" + + "finance/backend/internal/database" + "finance/backend/internal/models" + + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +// GetLoans returns all loans for the authenticated user +func GetLoans() 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 loans []models.Loan + + // Fetch all loans for the user + if err := database.DB.Where("user_id = ?", userObj.ID).Find(&loans).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch loans"}) + return + } + + c.JSON(http.StatusOK, gin.H{"loans": loans}) + } +} + +// GetLoanByID returns a specific loan by ID +func GetLoanByID() 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 loan ID from URL parameter + loanID, err := strconv.ParseUint(c.Param("id"), 10, 32) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid loan ID format"}) + return + } + + var loan models.Loan + + // Fetch the loan and ensure it belongs to the authenticated user + if err := database.DB.Where("id = ? AND user_id = ?", loanID, userObj.ID).First(&loan).Error; err != nil { + if err == gorm.ErrRecordNotFound { + c.JSON(http.StatusNotFound, gin.H{"error": "Loan not found"}) + } else { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch loan"}) + } + return + } + + c.JSON(http.StatusOK, gin.H{"loan": loan}) + } +} + +// CreateLoan creates a new loan +func CreateLoan() 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"` + OriginalAmount int64 `json:"originalAmount" binding:"required"` + CurrentBalance int64 `json:"currentBalance" binding:"required"` + InterestRate float64 `json:"interestRate"` + StartDate string `json:"startDate" binding:"required"` + EndDate string `json:"endDate" binding:"required"` + AccountID *uint `json:"accountId"` + } + + // Bind JSON to struct + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + // Parse dates + startDate, err := time.Parse("2006-01-02", input.StartDate) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid start date format"}) + return + } + + endDate, err := time.Parse("2006-01-02", input.EndDate) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid end date format"}) + return + } + + // Create loan object + loan := models.Loan{ + UserID: userObj.ID, + Name: input.Name, + OriginalAmount: input.OriginalAmount, + CurrentBalance: input.CurrentBalance, + InterestRate: input.InterestRate, + StartDate: startDate, + EndDate: endDate, + AccountID: input.AccountID, + } + + // Save to database + if err := database.DB.Create(&loan).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create loan"}) + return + } + + c.JSON(http.StatusCreated, gin.H{"loan": loan}) + } +} + +// UpdateLoan updates an existing loan +func UpdateLoan() 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 loan ID from URL parameter + loanID, err := strconv.ParseUint(c.Param("id"), 10, 32) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid loan ID format"}) + return + } + + // Check if the loan exists and belongs to the user + var loan models.Loan + if err := database.DB.Where("id = ? AND user_id = ?", loanID, userObj.ID).First(&loan).Error; err != nil { + if err == gorm.ErrRecordNotFound { + c.JSON(http.StatusNotFound, gin.H{"error": "Loan not found"}) + } else { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch loan"}) + } + return + } + + // Define a struct to bind the request JSON + var input struct { + Name string `json:"name"` + CurrentBalance int64 `json:"currentBalance"` + InterestRate float64 `json:"interestRate"` + EndDate string `json:"endDate"` + AccountID *uint `json:"accountId"` + } + + // 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 != "" { + loan.Name = input.Name + } + if input.CurrentBalance != 0 { + loan.CurrentBalance = input.CurrentBalance + } + if input.InterestRate != 0 { + loan.InterestRate = input.InterestRate + } + if input.EndDate != "" { + endDate, err := time.Parse("2006-01-02", input.EndDate) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid end date format"}) + return + } + loan.EndDate = endDate + } + if input.AccountID != nil { + loan.AccountID = input.AccountID + } + + // Save updates to database + if err := database.DB.Save(&loan).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update loan"}) + return + } + + c.JSON(http.StatusOK, gin.H{"loan": loan}) + } +} + +// DeleteLoan deletes a loan +func DeleteLoan() 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 loan ID from URL parameter + loanID, err := strconv.ParseUint(c.Param("id"), 10, 32) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid loan ID format"}) + return + } + + // Check if the loan exists and belongs to the user + var loan models.Loan + if err := database.DB.Where("id = ? AND user_id = ?", loanID, userObj.ID).First(&loan).Error; err != nil { + if err == gorm.ErrRecordNotFound { + c.JSON(http.StatusNotFound, gin.H{"error": "Loan not found"}) + } else { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch loan"}) + } + return + } + + // Delete the loan + if err := database.DB.Delete(&loan).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete loan"}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "Loan deleted successfully"}) + } +} |