package handlers import ( "fmt" "net/http" "github.com/gin-gonic/gin" "gorm.io/gorm" "fishfish/database" "fishfish/models" ) func StockIn(c *gin.Context) { var input struct { ItemID uint `json:"item_id" binding:"required"` Quantity float64 `json:"quantity" binding:"required"` Comment string `json:"comment"` } if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Неверные данные"}) return } if input.Quantity <= 0 { c.JSON(http.StatusBadRequest, gin.H{"error": "Количество должно быть положительным"}) return } err := database.DB.Transaction(func(tx *gorm.DB) error { result := tx.Model(&models.Item{}). Where("id = ? ", input.ItemID). Update("stock", gorm.Expr("stock + ?", input.Quantity)) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return fmt.Errorf("товар не найден") } movement := models.StockMovement{ ItemID: input.ItemID, Type: "in", Quantity: input.Quantity, Reason: "purchase", Comment: input.Comment, } if err := tx.Create(&movement).Error; err != nil { return err } return nil }) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "Приход оформлен"}) } func StockOut(c *gin.Context) { var input struct { ItemID uint `json:"item_id" binding:"required"` Quantity float64 `json:"quantity" binding:"required"` Comment string `json:"comment"` } if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Неверные данные"}) return } if input.Quantity <= 0 { c.JSON(http.StatusBadRequest, gin.H{"error": "Количество должно быть положительным"}) return } err := database.DB.Transaction(func(tx *gorm.DB) error { result := tx.Model(&models.Item{}). Where("id = ? AND stock >= ? ", input.ItemID, input.Quantity). Update("stock", gorm.Expr("stock - ?", input.Quantity)) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return fmt.Errorf("товар не найден или не достаточно товара") } movement := models.StockMovement{ ItemID: input.ItemID, Type: "out", Quantity: input.Quantity, Reason: "sale", Comment: input.Comment, } if err := tx.Create(&movement).Error; err != nil { return err } return nil }) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "Уход оформлен"}) } func GetStockMovements(c *gin.Context) { itemID := c.Query("item_id") var movements []models.StockMovement query := database.DB.Preload("Item").Order("created_at desc") if itemID != "" { query = query.Where("item_id = ?", itemID) } if err := query.Find(&movements).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Не удалось получить историю"}) return } c.JSON(http.StatusOK, movements) }