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