package handlers import ( "encoding/json" "fmt" "net/http" ) type ErrorResponse struct { Code int `json:"code"` Message string `json:"message"` } type ProductStocksRequest struct { Filter struct { OfferIDs []string `json:"offer_id"` ProductIDs []int64 `json:"product_id"` Visibility string `json:"visibility"` } `json:"filter"` LastID string `json:"last_id"` Limit int `json:"limit"` } type StockItem struct { ProductID int64 `json:"product_id"` OfferID string `json:"offer_id"` Stock int `json:"stock"` WarehouseID int64 `json:"warehouse_id"` WarehouseName string `json:"warehouse_name"` } func ProductStocks(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", 405) return } var req ProductStocksRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, 400, "invalid json: "+err.Error()) return } items := GetStocksFixtures() if len(req.Filter.OfferIDs) > 0 { filtered := make([]StockItem, 0) for _, item := range items { for _, oid := range req.Filter.OfferIDs { if item.OfferID == oid { filtered = append(filtered, item) break } } } items = filtered } if len(req.Filter.ProductIDs) > 0 { filtered := make([]StockItem, 0) for _, item := range items { for _, pid := range req.Filter.ProductIDs { if item.ProductID == pid { filtered = append(filtered, item) break } } } items = filtered } if req.Filter.Visibility != "" { _ = req.Filter.Visibility } if req.Limit > 0 && len(items) > req.Limit { items = items[:req.Limit] } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]any{ "items": items, "total": len(items), }) } type ProductInfoListRequest struct { Filter struct { OfferIDs []string `json:"offer_id"` ProductIDs []int64 `json:"product_id"` } `json:"filter"` Limit int `json:"limit"` } type ProductInfoItem struct { ProductID int64 `json:"product_id"` OfferID string `json:"offer_id"` Name string `json:"name"` Barcode string `json:"barcode,omitempty"` BuyPrice float64 `json:"buy_price"` Price float64 `json:"price"` PremiumPrice float64 `json:"premium_price"` CategoryID int64 `json:"category_id"` } func ProductInfoList(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", 405) return } var req ProductInfoListRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, 400, "invalid json") return } items := GetProductsFixtures() if len(req.Filter.OfferIDs) > 0 { filtered := make([]ProductInfoItem, 0) for _, item := range items { for _, oid := range req.Filter.OfferIDs { if item.OfferID == oid { filtered = append(filtered, item) break } } } items = filtered } if len(req.Filter.ProductIDs) > 0 { filtered := make([]ProductInfoItem, 0) for _, item := range items { for _, pid := range req.Filter.ProductIDs { if item.ProductID == pid { filtered = append(filtered, item) break } } } items = filtered } if req.Limit > 0 && len(items) > req.Limit { items = items[:req.Limit] } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]any{ "items": items, "total": len(items), }) } type ImportPricesRequest struct { Items []struct { OfferID string `json:"offer_id"` Price float64 `json:"price"` OldPrice float64 `json:"old_price,omitempty"` PremiumPrice float64 `json:"premium_price,omitempty"` PremiumPriceOld float64 `json:"premium_price_old,omitempty"` } `json:"items"` } type ImportPricesResponse struct { TaskID int64 `json:"task_id"` } func ImportPrices(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", 405) return } var req ImportPricesRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, 400, "invalid json") return } if len(req.Items) == 0 { writeError(w, 400, "items is required and must not be empty") return } for _, item := range req.Items { if item.OfferID == "" { writeError(w, 400, "offer_id is required for all items") return } if item.Price <= 0 { writeError(w, 400, "price must be positive") return } } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(ImportPricesResponse{ TaskID: 1234567890, }) } type ProductPricesRequest struct { Filter struct { OfferIDs []string `json:"offer_id"` ProductIDs []int64 `json:"product_id"` } `json:"filter"` Limit int `json:"limit"` } type ProductPriceItem struct { ProductID int64 `json:"product_id"` OfferID string `json:"offer_id"` Price float64 `json:"price"` OldPrice float64 `json:"old_price,omitempty"` PremiumPrice float64 `json:"premium_price,omitempty"` PremiumPriceOld float64 `json:"premium_price_old,omitempty"` } func ProductPrices(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", 405) return } var req ProductPricesRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, 400, "invalid json") return } items := GetPricesFixtures() if len(req.Filter.OfferIDs) > 0 { filtered := make([]ProductPriceItem, 0) for _, item := range items { for _, oid := range req.Filter.OfferIDs { if item.OfferID == oid { filtered = append(filtered, item) break } } } items = filtered } if len(req.Filter.ProductIDs) > 0 { filtered := make([]ProductPriceItem, 0) for _, item := range items { for _, pid := range req.Filter.ProductIDs { if item.ProductID == pid { filtered = append(filtered, item) break } } } items = filtered } if req.Limit > 0 && len(items) > req.Limit { items = items[:req.Limit] } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]any{ "items": items, "total": len(items), }) } func ProductList(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { http.Error(w, "method not allowed", 405) return } var req ProductListRequest _ = json.NewDecoder(r.Body).Decode(&req) items := GetProductsFixtures() if req.Page > 0 { offset := (req.Page - 1) * 10 if offset < len(items) { items = items[offset:] if len(items) > 10 { items = items[:10] } } else { items = nil } } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]any{ "items": items, "total": len(GetProductsFixtures()), }) } type ProductListRequest struct { Page int `json:"page"` } type ImportProductsRequest struct { Items []ImportProductItem `json:"items"` } type ImportProductItem struct { OfferID string `json:"offer_id"` Name string `json:"name"` Barcode string `json:"barcode,omitempty"` CategoryID int64 `json:"category_id"` Price string `json:"price,omitempty"` OldPrice string `json:"old_price,omitempty"` PremiumPrice string `json:"premium_price,omitempty"` Vat string `json:"vat"` Images []string `json:"images,omitempty"` Depth int `json:"depth,omitempty"` Height int `json:"height,omitempty"` Width int `json:"width,omitempty"` DimensionUnit string `json:"dimension_unit,omitempty"` Weight int `json:"weight,omitempty"` WeightUnit string `json:"weight_unit,omitempty"` Attributes []ImportAttribute `json:"attributes,omitempty"` } type ImportAttribute struct { ID int64 `json:"id"` Values []ImportAttrValue `json:"values"` } type ImportAttrValue struct { Value string `json:"value,omitempty"` ComplexID int64 `json:"complex_id,omitempty"` Values []ImportAttrValue `json:"values,omitempty"` } type ImportProductsResponse struct { Result struct { TaskID int64 `json:"task_id"` } `json:"result"` } func ImportProducts(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", 405) return } var req ImportProductsRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, 400, "invalid json: "+err.Error()) return } if len(req.Items) == 0 { writeError(w, 400, "items is required and must not be empty") return } for i, item := range req.Items { if item.OfferID == "" { writeError(w, 400, fmt.Sprintf("items[%d].offer_id is required", i)) return } if item.Name == "" { writeError(w, 400, fmt.Sprintf("items[%d].name is required", i)) return } if item.CategoryID == 0 { writeError(w, 400, fmt.Sprintf("items[%d].category_id is required", i)) return } } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(ImportProductsResponse{ Result: struct { TaskID int64 `json:"task_id"` }{ TaskID: 990001, }, }) } type ProductDescriptionRequest struct { Filter struct { OfferIDs []string `json:"offer_id"` ProductIDs []int64 `json:"product_id"` } `json:"filter"` } type ProductDescriptionItem struct { OfferID string `json:"offer_id"` ProductID int64 `json:"product_id"` CategoryID int64 `json:"category_id"` Name string `json:"name"` Barcode string `json:"barcode"` Status string `json:"status"` State string `json:"state"` CreatedAt string `json:"created_at"` IsArchive bool `json:"is_archive"` } type ProductDescriptionResponse struct { Result []ProductDescriptionItem `json:"result"` } func ProductDescriptions(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", 405) return } var req ProductDescriptionRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, 400, "invalid json") return } allProducts := GetProductsFixtures() descs := make([]ProductDescriptionItem, 0) seen := make(map[string]bool) for _, oid := range req.Filter.OfferIDs { for _, p := range allProducts { if p.OfferID == oid && !seen[oid] { seen[oid] = true descs = append(descs, ProductDescriptionItem{ OfferID: p.OfferID, ProductID: p.ProductID, CategoryID: p.CategoryID, Name: p.Name, Barcode: p.Barcode, Status: "processed", State: "moderated", CreatedAt: "2024-01-01T00:00:00Z", IsArchive: false, }) break } } } for _, pid := range req.Filter.ProductIDs { for _, p := range allProducts { poid := p.OfferID if p.ProductID == pid && !seen[poid] { seen[poid] = true descs = append(descs, ProductDescriptionItem{ OfferID: p.OfferID, ProductID: p.ProductID, CategoryID: p.CategoryID, Name: p.Name, Barcode: p.Barcode, Status: "processed", State: "moderated", CreatedAt: "2024-01-01T00:00:00Z", IsArchive: false, }) break } } } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(ProductDescriptionResponse{ Result: descs, }) } func writeError(w http.ResponseWriter, code int, msg string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) json.NewEncoder(w).Encode(ErrorResponse{Code: code, Message: msg}) }