diff --git a/backend/database/db.go b/backend/database/db.go index 9dc8ba8..0a92abc 100644 --- a/backend/database/db.go +++ b/backend/database/db.go @@ -20,5 +20,5 @@ func InitDB() { log.Fatal("Failed to connect to database:", err) } - DB.AutoMigrate(&models.Item{}, &models.User{}) + DB.AutoMigrate(&models.Item{}, &models.User{}, &models.CartItem{}) } diff --git a/backend/handlers/cart_handler.go b/backend/handlers/cart_handler.go new file mode 100644 index 0000000..bda9daf --- /dev/null +++ b/backend/handlers/cart_handler.go @@ -0,0 +1,108 @@ +package handlers + +import ( + "net/http" + + "github.com/gin-gonic/gin" + + "fishfish/database" + "fishfish/models" +) + +func getUserID(c *gin.Context) uint { + userID, _ := c.Get("user_id") + return userID.(uint) +} + +func GetCart(c *gin.Context) { + userID := getUserID(c) + + var cartItems []models.CartItem + if err := database.DB.Preload("Item").Where("user_id=?", userID).Find(&cartItems).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Не удалось получить корзину"}) + return + } + + c.JSON(http.StatusOK, cartItems) +} + +func AddToCart(c *gin.Context) { + userID := getUserID(c) + + var req struct { + ItemID uint `json:"item_id" bindind:"required"` + Quantity float64 `json:"quantity" bindind:"required,gt=0"` + } + + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Некорректные данные"}) + return + } + + var item models.Item + + if err := database.DB.First(&item, req.ItemID).Error; err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "Товар не найден"}) + return + } + + if req.Quantity > item.Stock { + c.JSON(http.StatusBadRequest, gin.H{"error": "Недостаточно товара на складе"}) + } + + var cartItem models.CartItem + err := database.DB.Where("user_id = ? AND item_id = ?", userID, req.ItemID).First(&cartItem).Error + if err != nil { + + cartItem = models.CartItem{ + UserID: userID, + ItemID: req.ItemID, + Quantity: req.Quantity, + } + + database.DB.Create(&cartItem) + } else { + cartItem.Quantity += req.Quantity + database.DB.Save(&cartItem) + } + + c.JSON(http.StatusOK, gin.H{"message": "Товар добавлен в корзину"}) +} + +func UpdateCartItem(c *gin.Context) { + userID := getUserID(c) + cartItemID := c.Param("id") + + var req struct { + Quantity float64 `json:"quantity" binding:"required,gt=0"` + } + + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Некорректные данные"}) + return + } + + var cartItem models.CartItem + if err := database.DB.Where("id = ? AND user_id = ?", cartItemID, userID).First(&cartItem).Error; err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "Позиция не найдена"}) + return + } + + cartItem.Quantity = req.Quantity + database.DB.Save(&cartItem) + + c.JSON(http.StatusOK, gin.H{"message": "Количество обновлено"}) +} + +func RemoveFromCart(c *gin.Context) { + userID := getUserID(c) + cartItemID := c.Param("id") + + result := database.DB.Where("id = ? AND user_id = ? ", cartItemID, userID).Delete(&models.CartItem{}) + if result.RowsAffected == 0 { + c.JSON(http.StatusNotFound, gin.H{"error": "Позиция не найдена"}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "Товар удален из корзины"}) +} diff --git a/backend/main.go b/backend/main.go index 892b608..c4a2f2b 100644 --- a/backend/main.go +++ b/backend/main.go @@ -48,6 +48,10 @@ func main() { protected.DELETE("/items/:id", handlers.DeleteItem) protected.PATCH("/items/:id", handlers.UpdateItem) protected.POST("/items", handlers.AddItem) + protected.GET("/cart/", handlers.GetCart) + protected.POST("/cart/", handlers.AddToCart) + protected.PATCH("/cart/:id", handlers.UpdateCartItem) + protected.DELETE("/cart/:id", handlers.RemoveFromCart) } admin := protected.Group("/") diff --git a/backend/models/cart.go b/backend/models/cart.go new file mode 100644 index 0000000..90751f5 --- /dev/null +++ b/backend/models/cart.go @@ -0,0 +1,16 @@ +package models + +import ( + "time" +) + +type CartItem struct { + ID uint `json:"id" gorm:"primaryKey"` + UserID uint `json:"user_id" gorm:"not null;uniqueIndex;idx_user_item"` + ItemID uint `json:"item_id" gorm:"not null;uniqueIndex;idx_user_item"` + Quantity float64 `json:"quantity" gorm:"not null;default:1"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + + Item Item `json:"item" gorm:"foreignKey:ItemID"` +} diff --git a/backend/models/user.go b/backend/models/user.go index 0012155..4efa857 100644 --- a/backend/models/user.go +++ b/backend/models/user.go @@ -6,7 +6,7 @@ type User struct { gorm.Model `json:"-"` Username string `gorm:"unique;not null" binding:"required"` Password string `gorm:"not null" json:"-" binding:"required,min=8"` - Role string `gorm:"default:'Рабочий'" json:"role"` + Role string `gorm:"default:'customer'" json:"role"` FirstName string `json:"first_name" binding:"required"` LastName string `gorm:"index" json:"last_name" binding:"required"` Phone string `gorm:"index" json:"phone"`