v2.0: massive test data (104 products, 41 postings, 20 returns, 20 payouts, 25 txs, 3 companies)
- Remove unused gin dependency from go.mod - Remove credential logging from startup - Remove dead parseOfferIDs function - Add method check to GET /v1/product/list - Complete all filter implementations (since, to, status, product_id, return_id, dir, analytics, page) - CancelPosting now validates posting existence (404 for unknown) - Implement MOCK_STOCKS_JSON file loading - Add Phase 2 endpoints: v3/product/import, v1/product/info/description, v1/product/info/attributes, v2/category/tree, v3/category/attribute, v3/category/attribute/values - Generate 104 products/stocks/prices across 3 companies: TechGiant (TG-0001..TG-0035), FashionLine (FL-0001..FL-0035), HomeStyle (HS-0001..HS-0034) - 41 postings, 20 returns, 20 payouts, 25 transactions - 31 tests (all PASS with race detector) - Add Makefile
This commit is contained in:
263
internal/handlers/categories.go
Normal file
263
internal/handlers/categories.go
Normal file
@ -0,0 +1,263 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type CategoryTreeRequest struct {
|
||||
Language string `json:"language"`
|
||||
}
|
||||
|
||||
type CategoryTreeNode struct {
|
||||
CategoryID int64 `json:"category_id"`
|
||||
Title string `json:"title"`
|
||||
Children []CategoryTreeNode `json:"children"`
|
||||
}
|
||||
|
||||
type CategoryTreeResponse struct {
|
||||
Result []CategoryTreeNode `json:"result"`
|
||||
}
|
||||
|
||||
func CategoryTree(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "method not allowed", 405)
|
||||
return
|
||||
}
|
||||
|
||||
var req CategoryTreeRequest
|
||||
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(CategoryTreeResponse{
|
||||
Result: []CategoryTreeNode{
|
||||
{
|
||||
CategoryID: 17000000,
|
||||
Title: "Электроника",
|
||||
Children: []CategoryTreeNode{
|
||||
{CategoryID: 17000001, Title: "Смартфоны и гаджеты", Children: []CategoryTreeNode{
|
||||
{CategoryID: 17036136, Title: "Смартфоны"},
|
||||
{CategoryID: 17036137, Title: "Планшеты"},
|
||||
}},
|
||||
{CategoryID: 17000002, Title: "Ноутбуки и компьютеры"},
|
||||
},
|
||||
},
|
||||
{
|
||||
CategoryID: 17010000,
|
||||
Title: "Одежда",
|
||||
Children: []CategoryTreeNode{
|
||||
{CategoryID: 17010001, Title: "Мужская одежда"},
|
||||
{CategoryID: 17010002, Title: "Женская одежда"},
|
||||
},
|
||||
},
|
||||
{
|
||||
CategoryID: 17020000,
|
||||
Title: "Дом и сад",
|
||||
Children: []CategoryTreeNode{
|
||||
{CategoryID: 17020001, Title: "Мебель"},
|
||||
{CategoryID: 17020002, Title: "Освещение"},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type CategoryAttributeRequest struct {
|
||||
AttributeType string `json:"attribute_type"`
|
||||
CategoryID []int64 `json:"category_id"`
|
||||
Language string `json:"language"`
|
||||
}
|
||||
|
||||
type CategoryAttribute struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Type string `json:"type"`
|
||||
IsCollection bool `json:"is_collection"`
|
||||
IsRequired bool `json:"is_required"`
|
||||
GroupID int64 `json:"group_id"`
|
||||
GroupName string `json:"group_name"`
|
||||
DictionaryID int64 `json:"dictionary_id"`
|
||||
}
|
||||
|
||||
type CategoryAttributesResponse struct {
|
||||
Result []CategoryAttribute `json:"result"`
|
||||
}
|
||||
|
||||
func CategoryAttributes(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "method not allowed", 405)
|
||||
return
|
||||
}
|
||||
|
||||
var req CategoryAttributeRequest
|
||||
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(CategoryAttributesResponse{
|
||||
Result: []CategoryAttribute{
|
||||
{
|
||||
ID: 8229,
|
||||
Name: "Название модели",
|
||||
Description: "Название модели товара",
|
||||
Type: "String",
|
||||
IsCollection: false,
|
||||
IsRequired: true,
|
||||
GroupID: 1,
|
||||
GroupName: "Основные характеристики",
|
||||
DictionaryID: 0,
|
||||
},
|
||||
{
|
||||
ID: 85,
|
||||
Name: "Бренд",
|
||||
Description: "Производитель товара",
|
||||
Type: "String",
|
||||
IsCollection: false,
|
||||
IsRequired: true,
|
||||
GroupID: 1,
|
||||
GroupName: "Основные характеристики",
|
||||
DictionaryID: 0,
|
||||
},
|
||||
{
|
||||
ID: 9044,
|
||||
Name: "Цвет товара",
|
||||
Description: "Основной цвет",
|
||||
Type: "String",
|
||||
IsCollection: false,
|
||||
IsRequired: false,
|
||||
GroupID: 2,
|
||||
GroupName: "Внешний вид",
|
||||
DictionaryID: 0,
|
||||
},
|
||||
{
|
||||
ID: 4416,
|
||||
Name: "Гарантия",
|
||||
Description: "Срок гарантии в месяцах",
|
||||
Type: "Number",
|
||||
IsCollection: false,
|
||||
IsRequired: false,
|
||||
GroupID: 3,
|
||||
GroupName: "Гарантия и сервис",
|
||||
DictionaryID: 0,
|
||||
},
|
||||
{
|
||||
ID: 4074,
|
||||
Name: "Комплектация",
|
||||
Description: "Что входит в комплект поставки",
|
||||
Type: "String",
|
||||
IsCollection: true,
|
||||
IsRequired: false,
|
||||
GroupID: 4,
|
||||
GroupName: "Комплектация",
|
||||
DictionaryID: 0,
|
||||
},
|
||||
{
|
||||
ID: 5076,
|
||||
Name: "Вес с упаковкой",
|
||||
Description: "Вес товара в упаковке, г",
|
||||
Type: "Number",
|
||||
IsCollection: false,
|
||||
IsRequired: false,
|
||||
GroupID: 5,
|
||||
GroupName: "Упаковка и габариты",
|
||||
DictionaryID: 0,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type CategoryAttributeValuesRequest struct {
|
||||
AttributeID int64 `json:"attribute_id"`
|
||||
CategoryID int64 `json:"category_id"`
|
||||
Language string `json:"language"`
|
||||
}
|
||||
|
||||
type CategoryAttributeValue struct {
|
||||
ID int64 `json:"id"`
|
||||
Value string `json:"value"`
|
||||
Info string `json:"info,omitempty"`
|
||||
}
|
||||
|
||||
type CategoryAttributeValuesResponse struct {
|
||||
Result []CategoryAttributeValue `json:"result"`
|
||||
}
|
||||
|
||||
func CategoryAttributeValues(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "method not allowed", 405)
|
||||
return
|
||||
}
|
||||
|
||||
var req CategoryAttributeValuesRequest
|
||||
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(CategoryAttributeValuesResponse{
|
||||
Result: []CategoryAttributeValue{
|
||||
{ID: 1, Value: "Apple", Info: "Apple Inc."},
|
||||
{ID: 2, Value: "Samsung", Info: "Samsung Electronics"},
|
||||
{ID: 3, Value: "Xiaomi", Info: "Xiaomi Corporation"},
|
||||
{ID: 4, Value: "Huawei", Info: "Huawei Technologies"},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type ProductAttributesRequest struct {
|
||||
Filter struct {
|
||||
OfferIDs []string `json:"offer_id"`
|
||||
ProductIDs []int64 `json:"product_id"`
|
||||
} `json:"filter"`
|
||||
}
|
||||
|
||||
type ProductAttributeValue struct {
|
||||
AttributeID int64 `json:"attribute_id"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type ProductAttributesResult struct {
|
||||
OfferID string `json:"offer_id"`
|
||||
ProductID int64 `json:"product_id"`
|
||||
Attributes []ProductAttributeValue `json:"attributes"`
|
||||
}
|
||||
|
||||
type ProductAttributesResponse struct {
|
||||
Result []ProductAttributesResult `json:"result"`
|
||||
}
|
||||
|
||||
func ProductAttributes(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "method not allowed", 405)
|
||||
return
|
||||
}
|
||||
|
||||
var req ProductAttributesRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
writeError(w, 400, "invalid json")
|
||||
return
|
||||
}
|
||||
|
||||
allProducts := GetProductsFixtures()
|
||||
results := make([]ProductAttributesResult, 0)
|
||||
|
||||
for _, oid := range req.Filter.OfferIDs {
|
||||
for _, p := range allProducts {
|
||||
if p.OfferID == oid {
|
||||
results = append(results, ProductAttributesResult{
|
||||
OfferID: p.OfferID,
|
||||
ProductID: p.ProductID,
|
||||
Attributes: []ProductAttributeValue{
|
||||
{AttributeID: 8229, Value: p.Name},
|
||||
{AttributeID: 85, Value: "Test Brand"},
|
||||
{AttributeID: 9044, Value: "Черный"},
|
||||
},
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(ProductAttributesResponse{
|
||||
Result: results,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user