package handler import ( "BE-MiniERP/database" "BE-MiniERP/modules/inventory/models" "BE-MiniERP/modules/inventory/repository" "BE-MiniERP/modules/inventory/service" "strconv" "strings" "github.com/gofiber/fiber/v2" ) type ProductHandler struct { Repo *repository.ProductRepository } func NewProductHandler() *ProductHandler { return &ProductHandler{ Repo: repository.NewProductRepository(database.DB), } } func (h *ProductHandler) GetAll(c *fiber.Ctx) error { page := c.QueryInt("page", 1) limit := c.QueryInt("limit", 10) // default 10 offset := (page - 1) * limit search := c.Query("search", "") categoryID := c.QueryInt("category_id", 0) collectionID := c.QueryInt("collection_id", 0) colourID := c.QueryInt("colour_id", 0) sizeID := c.QueryInt("size_id", 0) products, err := h.Repo.FindAll(page, limit, offset, search, uint(categoryID), uint(collectionID), uint(colourID), uint(sizeID)) if err != nil { return c.Status(500).JSON(fiber.Map{"error": "Failed to fetch products"}) } return c.JSON(products) } func (h *ProductHandler) Create(c *fiber.Ctx) error { var input models.Product if err := c.BodyParser(&input); err != nil { return c.Status(400).JSON(fiber.Map{"error": "Invalid input format"}) } if input.Name == "" { return c.Status(400).JSON(fiber.Map{"error": "Product name is required"}) } if input.Price <= 0 { return c.Status(400).JSON(fiber.Map{"error": "Price must be greater than 0"}) } if input.Hpp <= 0 { return c.Status(400).JSON(fiber.Map{"error": "HPP must be greater than 0"}) } if input.CategoryID == 0 { return c.Status(400).JSON(fiber.Map{"error": "Category ID is required"}) } if input.CollectionID == 0 { return c.Status(400).JSON(fiber.Map{"error": "Collection ID is required"}) } if input.ColourID == 0 { return c.Status(400).JSON(fiber.Map{"error": "Colour ID is required"}) } if input.SizeID == 0 { return c.Status(400).JSON(fiber.Map{"error": "Size ID is required"}) } if input.UnitOfMeasure == "" { return c.Status(400).JSON(fiber.Map{"error": "Unit of measure is required"}) } if err := h.Repo.PreloadRelations(&input); err != nil { return c.Status(400).JSON(fiber.Map{ "error": "Failed to preload relations: " + err.Error(), }) } sku, err := service.GenerateSKU(&input) if err != nil { return c.Status(400).JSON(fiber.Map{ "error": "Failed to generate SKU: " + err.Error(), }) } input.SKU = sku if err := h.Repo.Create(&input); err != nil { if strings.Contains(err.Error(), "duplicate key value") && strings.Contains(err.Error(), "sku") { return c.Status(400).JSON(fiber.Map{"error": "SKU already exists"}) } return c.Status(500).JSON(fiber.Map{ "error": "Failed to create product: " + err.Error(), }) } return c.Status(201).JSON(input) } func (h *ProductHandler) Update(c *fiber.Ctx) error { id, _ := strconv.Atoi(c.Params("id")) var input models.Product if err := c.BodyParser(&input); err != nil { return c.Status(400).JSON(fiber.Map{"error": "Invalid input"}) } if err := h.Repo.Update(uint(id), &input); err != nil { return c.Status(500).JSON(fiber.Map{"error": "Failed to update product"}) } return c.JSON(fiber.Map{"message": "Product updated"}) } func (h *ProductHandler) Delete(c *fiber.Ctx) error { id, _ := strconv.Atoi(c.Params("id")) if err := h.Repo.Delete(uint(id)); err != nil { return c.Status(500).JSON(fiber.Map{"error": "Failed to delete product"}) } return c.JSON(fiber.Map{"message": "Product deleted"}) }