package handlers import ( "encoding/json" "fmt" "log" "os" ) type company struct { name string prefix string categoryID int64 warehouseID int64 warehouse string productCount int } var companies = []company{ {name: "TechGiant", prefix: "TG", categoryID: 17000000, warehouseID: 99100001001, warehouse: "Moscow FBO", productCount: 35}, {name: "FashionLine", prefix: "FL", categoryID: 17010000, warehouseID: 99100001002, warehouse: "St. Petersburg FBO", productCount: 35}, {name: "HomeStyle", prefix: "HS", categoryID: 17020000, warehouseID: 99100001003, warehouse: "Kazan FBO", productCount: 34}, } var productNames = map[string][]string{ "TechGiant": { "Смартфон Galaxy A%d", "Ноутбук ProBook %d", "Планшет Tab %d", "Наушники SoundBuds %d", "Часы SmartWatch %d", "Колонка BeatBox %d", "Монитор UltraView %d", "Клавиатура TypeMaster %d", "Мышь ClickPro %d", "Роутер NetStream %d", "Камера SnapCam %d", "Принтер PrintJet %d", "Флешка DataStick %d", "Внешний диск StoreVault %d", "Зарядка PowerBoost %d", }, "FashionLine": { "Футболка Casual %d", "Джинсы Street %d", "Куртка WindPro %d", "Кроссовки RunFast %d", "Рубашка Classic %d", "Платье Evening %d", "Свитер WarmTouch %d", "Шорты SummerBreeze %d", "Пальто WinterLux %d", "Кепка SunShade %d", "Шарф CozyWrap %d", "Перчатки GripPro %d", "Ремень BeltLine %d", "Носки ComfyStep %d", "Сумка CarryAll %d", }, "HomeStyle": { "Стол WorkDesk %d", "Стул SitEasy %d", "Лампа LightGlow %d", "Полка ShelfMaster %d", "Ковёр SoftFloor %d", "Штора WindowDress %d", "Подушка DreamSoft %d", "Одеяло WarmCloud %d", "Посуда CookSet %d", "Ваза FlowerHold %d", "Зеркало ReflectPro %d", "Часы WallTime %d", "Органайзер DeskTidy %d", "Корзина BinSmart %d", "Вешалка HangRight %d", }, } func generateOfferID(prefix string, num int) string { return fmt.Sprintf("%s-%04d", prefix, num) } func generateBarcode(prefix string, num int) string { return fmt.Sprintf("%s%08d", prefix, 10000000+num) } func allProducts() []ProductInfoItem { result := make([]ProductInfoItem, 0) for _, c := range companies { names := productNames[c.name] for i := 1; i <= c.productCount; i++ { nameIdx := (i - 1) % len(names) result = append(result, ProductInfoItem{ ProductID: int64(99000000000 + len(result) + 1), OfferID: generateOfferID(c.prefix, i), Name: fmt.Sprintf(names[nameIdx], i), Barcode: generateBarcode(c.prefix, i), BuyPrice: float64(500 + (i*173)%10000), Price: float64(990 + (i*197)%15000), PremiumPrice: float64(1190 + (i*211)%17000), CategoryID: c.categoryID, }) } } return result } func allStocks() []StockItem { result := make([]StockItem, 0) for _, c := range companies { for i := 1; i <= c.productCount; i++ { stock := (i*73 + 10) % 500 if stock < 0 { stock = 0 } result = append(result, StockItem{ ProductID: int64(99000000000 + len(result) + 1), OfferID: generateOfferID(c.prefix, i), Stock: stock, WarehouseID: c.warehouseID, WarehouseName: c.warehouse, }) } } return result } func allPrices() []ProductPriceItem { result := make([]ProductPriceItem, 0) for _, c := range companies { for i := 1; i <= c.productCount; i++ { price := float64(990 + (i*197)%15000) result = append(result, ProductPriceItem{ ProductID: int64(0), OfferID: generateOfferID(c.prefix, i), Price: price, OldPrice: price * 1.1, PremiumPrice: price * 1.15, PremiumPriceOld: price * 1.25, }) } } return result } func GetStocksFixtures() []StockItem { if path := os.Getenv("MOCK_STOCKS_JSON"); path != "" { if fileData, err := os.ReadFile(path); err == nil { var loaded []StockItem if json.Unmarshal(fileData, &loaded) == nil && len(loaded) > 0 { log.Printf("MOCK_STOCKS_JSON: loaded %d items from %s", len(loaded), path) return loaded } } log.Printf("MOCK_STOCKS_JSON: failed to load from %s, using defaults", path) } return allStocks() } func GetProductsFixtures() []ProductInfoItem { return allProducts() } func GetPricesFixtures() []ProductPriceItem { return allPrices() } type postingSpec struct { companyIdx int productNum1 int productNum2 int status string createdAt string updatedAt string orderType string } var postingSpecs = []postingSpec{ {0, 1, 0, "delivered", "2024-01-15T10:30:00Z", "2024-01-17T14:45:00Z", "fbs"}, {0, 2, 3, "delivered", "2024-01-16T11:00:00Z", "2024-01-18T09:30:00Z", "fbs"}, {0, 4, 0, "awaiting_deliver", "2024-01-18T08:15:00Z", "2024-01-18T08:15:00Z", "fbs"}, {0, 5, 0, "cancelled", "2024-01-17T16:00:00Z", "2024-01-17T18:30:00Z", "fbs"}, {0, 7, 8, "delivered", "2024-02-01T09:00:00Z", "2024-02-03T12:00:00Z", "fbs"}, {0, 10, 0, "delivered", "2024-02-05T14:00:00Z", "2024-02-07T16:00:00Z", "fbs"}, {0, 12, 13, "awaiting_deliver", "2024-02-10T06:00:00Z", "2024-02-10T06:00:00Z", "fbs"}, {0, 15, 0, "cancelled", "2024-02-12T18:00:00Z", "2024-02-12T20:00:00Z", "fbs"}, {0, 18, 20, "delivered", "2024-03-01T08:00:00Z", "2024-03-03T10:00:00Z", "fbo"}, {0, 22, 0, "delivered", "2024-03-05T11:00:00Z", "2024-03-07T13:00:00Z", "fbo"}, {1, 1, 0, "delivered", "2024-01-20T12:00:00Z", "2024-01-22T15:00:00Z", "fbs"}, {1, 2, 3, "delivered", "2024-01-22T09:00:00Z", "2024-01-24T11:00:00Z", "fbs"}, {1, 5, 0, "awaiting_deliver", "2024-01-25T14:00:00Z", "2024-01-25T14:00:00Z", "fbs"}, {1, 7, 8, "cancelled", "2024-01-28T16:00:00Z", "2024-01-28T18:00:00Z", "fbs"}, {1, 10, 0, "delivered", "2024-02-02T10:00:00Z", "2024-02-04T12:00:00Z", "fbs"}, {1, 12, 14, "delivered", "2024-02-08T08:00:00Z", "2024-02-10T10:00:00Z", "fbo"}, {1, 16, 0, "awaiting_deliver", "2024-02-15T13:00:00Z", "2024-02-15T13:00:00Z", "fbo"}, {1, 18, 20, "delivered", "2024-03-01T07:00:00Z", "2024-03-03T09:00:00Z", "fbs"}, {2, 1, 0, "delivered", "2024-01-18T11:00:00Z", "2024-01-20T13:00:00Z", "fbs"}, {2, 3, 4, "delivered", "2024-01-25T15:00:00Z", "2024-01-27T17:00:00Z", "fbs"}, {2, 6, 0, "awaiting_deliver", "2024-02-01T09:00:00Z", "2024-02-01T09:00:00Z", "fbs"}, {2, 8, 9, "cancelled", "2024-02-05T14:00:00Z", "2024-02-05T16:00:00Z", "fbs"}, {2, 11, 0, "delivered", "2024-02-10T08:00:00Z", "2024-02-12T10:00:00Z", "fbo"}, {2, 13, 15, "delivered", "2024-02-20T12:00:00Z", "2024-02-22T14:00:00Z", "fbo"}, {2, 17, 0, "awaiting_deliver", "2024-03-01T06:00:00Z", "2024-03-01T06:00:00Z", "fbs"}, {2, 19, 21, "delivered", "2024-03-10T10:00:00Z", "2024-03-12T12:00:00Z", "fbs"}, {0, 25, 0, "delivered", "2024-03-15T08:00:00Z", "2024-03-17T10:00:00Z", "fbs"}, {1, 22, 0, "delivered", "2024-03-18T11:00:00Z", "2024-03-20T13:00:00Z", "fbs"}, {2, 22, 23, "awaiting_deliver", "2024-04-01T07:00:00Z", "2024-04-01T07:00:00Z", "fbo"}, {0, 28, 30, "delivered", "2024-04-05T09:00:00Z", "2024-04-07T11:00:00Z", "fbo"}, {1, 25, 0, "delivered", "2024-04-10T14:00:00Z", "2024-04-12T16:00:00Z", "fbs"}, {2, 25, 27, "cancelled", "2024-04-15T10:00:00Z", "2024-04-15T12:00:00Z", "fbs"}, {0, 30, 32, "delivered", "2024-05-01T08:00:00Z", "2024-05-03T10:00:00Z", "fbs"}, {1, 28, 0, "delivered", "2024-05-05T12:00:00Z", "2024-05-07T14:00:00Z", "fbs"}, {2, 28, 30, "awaiting_deliver", "2024-05-10T09:00:00Z", "2024-05-10T09:00:00Z", "fbo"}, {0, 33, 0, "delivered", "2024-05-15T11:00:00Z", "2024-05-17T13:00:00Z", "fbo"}, {1, 31, 33, "delivered", "2024-06-01T07:00:00Z", "2024-06-03T09:00:00Z", "fbs"}, {2, 32, 0, "delivered", "2024-06-05T14:00:00Z", "2024-06-07T16:00:00Z", "fbs"}, {0, 35, 0, "cancelled", "2024-06-10T08:00:00Z", "2024-06-10T10:00:00Z", "fbs"}, {1, 35, 0, "delivered", "2024-06-15T10:00:00Z", "2024-06-17T12:00:00Z", "fbo"}, {2, 34, 0, "delivered", "2024-07-01T09:00:00Z", "2024-07-03T11:00:00Z", "fbs"}, } func productByNum(c company, num int) (int64, string, string, float64) { idx := 0 for _, comp := range companies { for i := 1; i <= comp.productCount; i++ { if comp.name == c.name && i == num { names := productNames[comp.name] nameIdx := (i - 1) % len(names) pid := int64(99000000000 + idx + 1) offerID := generateOfferID(c.prefix, i) name := fmt.Sprintf(names[nameIdx], i) price := float64(990 + (i*197)%15000) return pid, offerID, name, price } idx++ } } return 0, "", "", 0 } func getCompanyProducts(c company) []ProductInfoItem { result := make([]ProductInfoItem, 0) names := productNames[c.name] for i := 1; i <= c.productCount; i++ { nameIdx := (i - 1) % len(names) result = append(result, ProductInfoItem{ ProductID: int64(99000000000 + len(result) + 1), OfferID: generateOfferID(c.prefix, i), Name: fmt.Sprintf(names[nameIdx], i), Barcode: generateBarcode(c.prefix, i), CategoryID: c.categoryID, }) } return result } func GetPostingsFixtures() []Posting { result := make([]Posting, len(postingSpecs)) for idx, spec := range postingSpecs { c := companies[spec.companyIdx] pid1, oid1, name1, price1 := productByNum(c, spec.productNum1) products := []PostingItem{ {ProductID: pid1, OfferID: oid1, Name: name1, Quantity: (idx%3 + 1), Price: price1, ItemsCount: 1}, } if spec.productNum2 > 0 { pid2, oid2, name2, price2 := productByNum(c, spec.productNum2) products = append(products, PostingItem{ ProductID: pid2, OfferID: oid2, Name: name2, Quantity: (idx%2 + 1), Price: price2, ItemsCount: 1, }) } orderID := int64(99000000000 + idx + 1) result[idx] = Posting{ PostingNumber: fmt.Sprintf("%s-POST-%03d", c.prefix, idx+1), OrderID: orderID, OrderNumber: fmt.Sprintf("%s-ORD-%03d", c.prefix, idx+1), Status: spec.status, Products: products, CreatedAt: spec.createdAt, UpdatedAt: spec.updatedAt, WarehouseID: c.warehouseID, OrderType: spec.orderType, } } return result } func GetReturnsFixtures() []Return { returnSpecs := []struct { companyIdx int postingIdx int status string reason string reasonID int64 createdAt string deliveredAt string }{ {0, 0, "completed", "wrong_item", 10, "2024-01-20T10:00:00Z", "2024-01-22T15:00:00Z"}, {0, 1, "pending", "buyer_remorse", 20, "2024-01-21T14:30:00Z", ""}, {0, 4, "completed", "defect", 30, "2024-02-10T08:00:00Z", "2024-02-12T10:00:00Z"}, {1, 10, "completed", "wrong_item", 10, "2024-02-05T11:00:00Z", "2024-02-07T13:00:00Z"}, {1, 11, "pending", "buyer_remorse", 20, "2024-02-15T16:00:00Z", ""}, {1, 14, "completed", "wrong_size", 40, "2024-03-01T09:00:00Z", "2024-03-03T11:00:00Z"}, {2, 18, "completed", "defect", 30, "2024-02-01T14:00:00Z", "2024-02-03T16:00:00Z"}, {2, 19, "pending", "buyer_remorse", 20, "2024-02-20T10:00:00Z", ""}, {2, 23, "completed", "wrong_item", 10, "2024-03-15T08:00:00Z", "2024-03-17T10:00:00Z"}, {0, 5, "pending", "wrong_color", 50, "2024-03-20T12:00:00Z", ""}, {1, 16, "completed", "defect", 30, "2024-04-01T07:00:00Z", "2024-04-03T09:00:00Z"}, {2, 24, "pending", "buyer_remorse", 20, "2024-04-10T14:00:00Z", ""}, {0, 8, "completed", "wrong_item", 10, "2024-05-01T10:00:00Z", "2024-05-03T12:00:00Z"}, {1, 17, "completed", "wrong_size", 40, "2024-05-15T09:00:00Z", "2024-05-17T11:00:00Z"}, {2, 28, "pending", "defect", 30, "2024-06-05T08:00:00Z", ""}, {0, 6, "completed", "buyer_remorse", 20, "2024-03-01T06:00:00Z", "2024-03-03T08:00:00Z"}, {1, 12, "pending", "wrong_item", 10, "2024-02-25T15:00:00Z", ""}, {2, 20, "completed", "wrong_color", 50, "2024-03-05T11:00:00Z", "2024-03-07T13:00:00Z"}, {0, 9, "pending", "defect", 30, "2024-04-15T09:00:00Z", ""}, {1, 13, "completed", "buyer_remorse", 20, "2024-03-10T14:00:00Z", "2024-03-12T16:00:00Z"}, } result := make([]Return, len(returnSpecs)) for idx, spec := range returnSpecs { c := companies[spec.companyIdx] ps := postingSpecs[spec.postingIdx] pid, oid, name, _ := productByNum(c, ps.productNum1) result[idx] = Return{ ReturnID: int64(99000000 + idx + 1), PostingNumber: fmt.Sprintf("%s-POST-%03d", c.prefix, spec.postingIdx+1), Status: spec.status, Reason: spec.reason, ReasonID: spec.reasonID, CreatedAt: spec.createdAt, DeliveredAt: spec.deliveredAt, Items: []ReturnItem{ {ProductID: pid, OfferID: oid, Name: name, Quantity: 1, IsOptional: false}, }, } } return result } func GetTransactionsFixtures() []Transaction { txDefs := []struct { txType string amount float64 companyIdx int postingIdx int createdAt string }{ {"orders", 3980.00, 0, 0, "2024-01-17T00:00:00Z"}, {"orders", 4980.00, 0, 1, "2024-01-18T00:00:00Z"}, {"commission", -597.00, 0, 0, "2024-01-17T00:00:00Z"}, {"refund", -990.00, 0, 3, "2024-01-17T00:00:00Z"}, {"orders", 2500.00, 0, 4, "2024-02-05T00:00:00Z"}, {"commission", -375.00, 0, 4, "2024-02-05T00:00:00Z"}, {"orders", 3200.00, 1, 10, "2024-01-25T00:00:00Z"}, {"commission", -480.00, 1, 10, "2024-01-25T00:00:00Z"}, {"orders", 4500.00, 1, 11, "2024-01-26T00:00:00Z"}, {"refund", -1200.00, 1, 13, "2024-01-30T00:00:00Z"}, {"orders", 2800.00, 2, 18, "2024-01-22T00:00:00Z"}, {"commission", -420.00, 2, 18, "2024-01-22T00:00:00Z"}, {"orders", 3600.00, 2, 19, "2024-01-28T00:00:00Z"}, {"refund", -800.00, 2, 21, "2024-02-07T00:00:00Z"}, {"orders", 5100.00, 0, 8, "2024-04-01T00:00:00Z"}, {"commission", -765.00, 0, 8, "2024-04-01T00:00:00Z"}, {"orders", 3400.00, 1, 16, "2024-04-05T00:00:00Z"}, {"commission", -510.00, 1, 16, "2024-04-05T00:00:00Z"}, {"orders", 4200.00, 2, 23, "2024-04-12T00:00:00Z"}, {"refund", -950.00, 2, 31, "2024-04-17T00:00:00Z"}, {"orders", 2900.00, 0, 26, "2024-03-18T00:00:00Z"}, {"orders", 3800.00, 1, 14, "2024-02-05T00:00:00Z"}, {"commission", -570.00, 1, 14, "2024-02-05T00:00:00Z"}, {"orders", 4700.00, 2, 28, "2024-05-12T00:00:00Z"}, {"commission", -705.00, 2, 28, "2024-05-12T00:00:00Z"}, } result := make([]Transaction, len(txDefs)) for idx, def := range txDefs { c := companies[def.companyIdx] ps := postingSpecs[def.postingIdx] _, oid1, _, _ := productByNum(c, ps.productNum1) orderID := int64(99000000000 + def.postingIdx + 1) tx := Transaction{ TransactionType: def.txType, Amount: def.amount, CurrencyCode: "RUB", PostingNumber: fmt.Sprintf("%s-POST-%03d", c.prefix, def.postingIdx+1), OrderID: orderID, CreatedAt: def.createdAt, } if def.txType == "orders" { tx.Items = []TransactionItem{ {Type: "sale", Amount: def.amount / 2, Quantity: 1, ProductID: int64(99000000000 + def.postingIdx + 100), OfferID: oid1}, {Type: "sale", Amount: def.amount / 2, Quantity: 1, ProductID: int64(99000000000 + def.postingIdx + 101), OfferID: oid1}, } } result[idx] = tx } return result } func GetPayoutsFixtures() []Payout { payoutDefs := []struct { companyIdx int amount float64 opsCount int createdAt string }{ {0, 15000.00, 10, "2024-01-15T00:00:00Z"}, {0, 22500.00, 15, "2024-01-22T00:00:00Z"}, {0, 18000.00, 12, "2024-02-15T00:00:00Z"}, {0, 32000.00, 20, "2024-03-15T00:00:00Z"}, {1, 12000.00, 8, "2024-01-20T00:00:00Z"}, {1, 19500.00, 13, "2024-01-27T00:00:00Z"}, {1, 25000.00, 18, "2024-02-20T00:00:00Z"}, {1, 28000.00, 19, "2024-03-20T00:00:00Z"}, {2, 11000.00, 7, "2024-01-18T00:00:00Z"}, {2, 17000.00, 11, "2024-01-25T00:00:00Z"}, {2, 21000.00, 14, "2024-02-18T00:00:00Z"}, {2, 29000.00, 21, "2024-03-18T00:00:00Z"}, {0, 14500.00, 9, "2024-04-15T00:00:00Z"}, {1, 16500.00, 11, "2024-04-20T00:00:00Z"}, {2, 13500.00, 8, "2024-04-18T00:00:00Z"}, {0, 26000.00, 17, "2024-05-15T00:00:00Z"}, {1, 31000.00, 22, "2024-05-20T00:00:00Z"}, {2, 24000.00, 16, "2024-05-18T00:00:00Z"}, {0, 19000.00, 13, "2024-06-15T00:00:00Z"}, {1, 22000.00, 15, "2024-06-20T00:00:00Z"}, } result := make([]Payout, len(payoutDefs)) for idx, def := range payoutDefs { result[idx] = Payout{ PayoutID: int64(99001 + idx), Type: "payout", Status: "completed", Amount: def.amount, CurrencyCode: "RUB", CreatedAt: def.createdAt, OperationsCount: def.opsCount, } } return result }