vantuz 3.1.2 → 3.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/plugins/vantuz/platforms/trendyol.js +162 -150
package/package.json
CHANGED
|
@@ -42,243 +42,254 @@ export class TrendyolAPI {
|
|
|
42
42
|
data,
|
|
43
43
|
params
|
|
44
44
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
});
|
|
46
|
+
return { success: true, data: response.data };
|
|
47
|
+
} catch(error) {
|
|
48
|
+
const errorMsg = error.response?.data?.errors?.[0]?.message || error.message;
|
|
49
|
+
const statusCode = error.response?.status;
|
|
50
|
+
|
|
51
|
+
console.error(`[Trendyol] API Hatası (${statusCode}): ${errorMsg}`);
|
|
52
|
+
if (error.response?.data) {
|
|
53
|
+
try {
|
|
54
|
+
console.error('[Trendyol] Hata Detayı:', JSON.stringify(error.response.data));
|
|
55
|
+
} catch (e) { }
|
|
52
56
|
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
success: false,
|
|
60
|
+
error: errorMsg,
|
|
61
|
+
status: statusCode
|
|
62
|
+
};
|
|
53
63
|
}
|
|
64
|
+
}
|
|
54
65
|
|
|
55
66
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
56
67
|
// ÜRÜN İŞLEMLERİ
|
|
57
68
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
58
69
|
|
|
59
70
|
async getProducts(params = {}) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
const { page = 0, size = 50, barcode, approved, onSale } = params;
|
|
72
|
+
return await this._request('GET', `/suppliers/${this.supplierId}/products`, null, {
|
|
73
|
+
page, size, barcode, approved, onSale
|
|
74
|
+
});
|
|
75
|
+
}
|
|
65
76
|
|
|
66
77
|
async getProductByBarcode(barcode) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
return { success: false, error: 'Ürün bulunamadı' };
|
|
78
|
+
const result = await this.getProducts({ barcode });
|
|
79
|
+
if (result.success && result.data.content?.length > 0) {
|
|
80
|
+
return { success: true, data: result.data.content[0] };
|
|
72
81
|
}
|
|
82
|
+
return { success: false, error: 'Ürün bulunamadı' };
|
|
83
|
+
}
|
|
73
84
|
|
|
74
85
|
async createProducts(products) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
// items: [{ barcode, title, productMainId, brandId, categoryId, ... }]
|
|
87
|
+
return await this._request('POST', `/suppliers/${this.supplierId}/v2/products`, { items: products });
|
|
88
|
+
}
|
|
78
89
|
|
|
79
90
|
async updateProducts(products) {
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
return await this._request('PUT', `/suppliers/${this.supplierId}/v2/products`, { items: products });
|
|
92
|
+
}
|
|
82
93
|
|
|
83
94
|
async deleteProducts(barcodes) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
95
|
+
const items = barcodes.map(barcode => ({ barcode }));
|
|
96
|
+
return await this._request('DELETE', `/suppliers/${this.supplierId}/products`, { items });
|
|
97
|
+
}
|
|
87
98
|
|
|
88
99
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
89
100
|
// FİYAT & STOK
|
|
90
101
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
91
102
|
|
|
92
103
|
async updatePriceAndStock(items) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
104
|
+
// items: [{ barcode, quantity, salePrice, listPrice }]
|
|
105
|
+
return await this._request('POST', `/suppliers/${this.supplierId}/products/price-and-inventory`, { items });
|
|
106
|
+
}
|
|
96
107
|
|
|
97
108
|
async updatePrice(barcode, salePrice, listPrice = null) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
109
|
+
return await this.updatePriceAndStock([{
|
|
110
|
+
barcode,
|
|
111
|
+
salePrice,
|
|
112
|
+
listPrice: listPrice || salePrice
|
|
113
|
+
}]);
|
|
114
|
+
}
|
|
104
115
|
|
|
105
116
|
async updateStock(barcode, quantity) {
|
|
106
|
-
|
|
107
|
-
|
|
117
|
+
return await this.updatePriceAndStock([{ barcode, quantity }]);
|
|
118
|
+
}
|
|
108
119
|
|
|
109
120
|
async bulkPriceUpdate(updates) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
121
|
+
// updates: [{ barcode, price, listPrice? }]
|
|
122
|
+
const items = updates.map(u => ({
|
|
123
|
+
barcode: u.barcode,
|
|
124
|
+
salePrice: u.price,
|
|
125
|
+
listPrice: u.listPrice || u.price
|
|
126
|
+
}));
|
|
127
|
+
return await this.updatePriceAndStock(items);
|
|
128
|
+
}
|
|
118
129
|
|
|
119
130
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
120
131
|
// SİPARİŞ İŞLEMLERİ
|
|
121
132
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
122
133
|
|
|
123
134
|
async getOrders(params = {}) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
const {
|
|
136
|
+
status,
|
|
137
|
+
startDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).getTime(), // Son 30 gün
|
|
138
|
+
endDate = Date.now(),
|
|
139
|
+
page = 0,
|
|
140
|
+
size = 50,
|
|
141
|
+
orderNumber
|
|
142
|
+
} = params;
|
|
143
|
+
|
|
144
|
+
return await this._request('GET', `/suppliers/${this.supplierId}/orders`, null, {
|
|
145
|
+
status, startDate, endDate, page, size, orderNumber, orderByDirection: 'DESC', orderByField: 'PackageLastModifiedDate'
|
|
146
|
+
});
|
|
147
|
+
}
|
|
137
148
|
|
|
138
149
|
async getOrderByNumber(orderNumber) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
return { success: false, error: 'Sipariş bulunamadı' };
|
|
150
|
+
const result = await this.getOrders({ orderNumber });
|
|
151
|
+
if (result.success && result.data.content?.length > 0) {
|
|
152
|
+
return { success: true, data: result.data.content[0] };
|
|
144
153
|
}
|
|
154
|
+
return { success: false, error: 'Sipariş bulunamadı' };
|
|
155
|
+
}
|
|
145
156
|
|
|
146
157
|
async updateOrderStatus(lines, status, params = {}) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return { success: false, error: 'Geçersiz durum' };
|
|
158
|
+
// lines: [{ lineId, quantity }]
|
|
159
|
+
// status: Picking, Invoiced, UnSupplied
|
|
160
|
+
const endpoint = `/suppliers/${this.supplierId}/shipment-packages`;
|
|
161
|
+
|
|
162
|
+
if (status === 'Picking') {
|
|
163
|
+
return await this._request('PUT', endpoint, { lines, status: 'Picking' });
|
|
164
|
+
} else if (status === 'Invoiced') {
|
|
165
|
+
return await this._request('PUT', endpoint, {
|
|
166
|
+
lines,
|
|
167
|
+
status: 'Invoiced',
|
|
168
|
+
invoiceNumber: params.invoiceNumber
|
|
169
|
+
});
|
|
162
170
|
}
|
|
163
171
|
|
|
172
|
+
return { success: false, error: 'Geçersiz durum' };
|
|
173
|
+
}
|
|
174
|
+
|
|
164
175
|
async shipOrder(shipmentPackageId, trackingNumber, cargoKey = 'YURTICI') {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
176
|
+
// cargoKey: YURTICI, MNG, ARAS, PTT, SURAT, UPS, HOROZ, CEVA, SENDEO
|
|
177
|
+
return await this._request('PUT',
|
|
178
|
+
`/suppliers/${this.supplierId}/shipment-packages/${shipmentPackageId}`,
|
|
179
|
+
{
|
|
180
|
+
trackingNumber,
|
|
181
|
+
cargoProviderCode: cargoKey,
|
|
182
|
+
status: 'Shipped'
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
}
|
|
175
186
|
|
|
176
187
|
async getShipmentProviders() {
|
|
177
|
-
|
|
178
|
-
|
|
188
|
+
return await this._request('GET', '/shipment-providers');
|
|
189
|
+
}
|
|
179
190
|
|
|
180
191
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
181
192
|
// KATEGORİ & MARKA
|
|
182
193
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
183
194
|
|
|
184
195
|
async getCategories() {
|
|
185
|
-
|
|
186
|
-
|
|
196
|
+
return await this._request('GET', '/product-categories');
|
|
197
|
+
}
|
|
187
198
|
|
|
188
199
|
async getCategoryAttributes(categoryId) {
|
|
189
|
-
|
|
190
|
-
|
|
200
|
+
return await this._request('GET', `/product-categories/${categoryId}/attributes`);
|
|
201
|
+
}
|
|
191
202
|
|
|
192
203
|
async searchBrands(name) {
|
|
193
|
-
|
|
194
|
-
|
|
204
|
+
return await this._request('GET', '/brands', null, { name });
|
|
205
|
+
}
|
|
195
206
|
|
|
196
207
|
async getBrandsByCategory(categoryId) {
|
|
197
|
-
|
|
198
|
-
|
|
208
|
+
return await this._request('GET', `/product-categories/${categoryId}/brands`);
|
|
209
|
+
}
|
|
199
210
|
|
|
200
211
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
201
212
|
// RAKİP ANALİZİ (Scraping - Dikkat: Rate limit)
|
|
202
213
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
203
214
|
|
|
204
215
|
async getCompetitorPrices(barcode) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
216
|
+
// Bu endpoint resmi API'de yok, web scraping gerekir
|
|
217
|
+
// Alternatif: Brave Search API ile rakip araması
|
|
218
|
+
try {
|
|
219
|
+
// Trendyol'da aynı ürünü satan diğer satıcıları bul
|
|
220
|
+
const searchUrl = `https://www.trendyol.com/sr?q=${barcode}`;
|
|
221
|
+
// Not: Bu gerçek scraping gerektirir, burada placeholder
|
|
222
|
+
return {
|
|
223
|
+
success: true,
|
|
224
|
+
competitors: [],
|
|
225
|
+
message: 'Rakip analizi için web_search tool kullanın'
|
|
226
|
+
};
|
|
227
|
+
} catch (error) {
|
|
228
|
+
return { success: false, error: error.message };
|
|
219
229
|
}
|
|
230
|
+
}
|
|
220
231
|
|
|
221
232
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
222
233
|
// SORU & CEVAP
|
|
223
234
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
224
235
|
|
|
225
236
|
async getQuestions(params = {}) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
237
|
+
const { status = 'WAITING_FOR_ANSWER', page = 0, size = 50 } = params;
|
|
238
|
+
return await this._request('GET', `/suppliers/${this.supplierId}/questions/filter`, null, {
|
|
239
|
+
status, page, size
|
|
240
|
+
});
|
|
241
|
+
}
|
|
231
242
|
|
|
232
243
|
async answerQuestion(questionId, answer) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
244
|
+
return await this._request('POST', `/suppliers/${this.supplierId}/questions/${questionId}/answers`, {
|
|
245
|
+
text: answer
|
|
246
|
+
});
|
|
247
|
+
}
|
|
237
248
|
|
|
238
249
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
239
250
|
// WEBHOOK
|
|
240
251
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
241
252
|
|
|
242
253
|
async getWebhooks() {
|
|
243
|
-
|
|
244
|
-
|
|
254
|
+
return await this._request('GET', `/suppliers/${this.supplierId}/webhooks`);
|
|
255
|
+
}
|
|
245
256
|
|
|
246
257
|
async createWebhook(url, events = ['order.created', 'order.shipped']) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
258
|
+
return await this._request('POST', `/suppliers/${this.supplierId}/webhooks`, {
|
|
259
|
+
url,
|
|
260
|
+
events
|
|
261
|
+
});
|
|
262
|
+
}
|
|
252
263
|
|
|
253
264
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
254
265
|
// YARDIMCI METODLAR
|
|
255
266
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
256
267
|
|
|
257
268
|
async testConnection() {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
269
|
+
const result = await this.getProducts({ page: 0, size: 1 });
|
|
270
|
+
return result.success;
|
|
271
|
+
}
|
|
261
272
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
273
|
+
isConnected() {
|
|
274
|
+
return !!(this.supplierId && this.apiKey && this.apiSecret);
|
|
275
|
+
}
|
|
265
276
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
277
|
+
formatProduct(raw) {
|
|
278
|
+
return {
|
|
279
|
+
id: raw.id,
|
|
280
|
+
barcode: raw.barcode,
|
|
281
|
+
title: raw.title,
|
|
282
|
+
brand: raw.brand,
|
|
283
|
+
category: raw.categoryName,
|
|
284
|
+
price: raw.salePrice,
|
|
285
|
+
listPrice: raw.listPrice,
|
|
286
|
+
stock: raw.quantity,
|
|
287
|
+
images: raw.images?.map(i => i.url) || [],
|
|
288
|
+
approved: raw.approved,
|
|
289
|
+
onSale: raw.onSale,
|
|
290
|
+
url: `https://www.trendyol.com/p/-p-${raw.id}`
|
|
291
|
+
};
|
|
292
|
+
}
|
|
282
293
|
}
|
|
283
294
|
|
|
284
295
|
// Singleton instance
|
|
@@ -303,5 +314,6 @@ export const trendyolApi = {
|
|
|
303
314
|
async updatePrice(barcode, price) { return instance?.updatePrice(barcode, price); },
|
|
304
315
|
async updateStock(barcode, qty) { return instance?.updateStock(barcode, qty); },
|
|
305
316
|
async getOrders(params) { return instance?.getOrders(params); },
|
|
306
|
-
async getCompetitors(barcode) { return instance?.getCompetitorPrices(barcode); }
|
|
317
|
+
async getCompetitors(barcode) { return instance?.getCompetitorPrices(barcode); },
|
|
318
|
+
async testConnection() { return instance?.testConnection(); }
|
|
307
319
|
};
|