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