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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vantuz",
3
- "version": "3.1.2",
3
+ "version": "3.1.3",
4
4
  "description": "Yapay Zeka Destekli E-Ticaret Yönetim Platformu - 7 Pazaryeri + WhatsApp/Telegram",
5
5
  "type": "module",
6
6
  "main": "cli.js",
@@ -42,243 +42,254 @@ export class TrendyolAPI {
42
42
  data,
43
43
  params
44
44
  });
45
- return { success: true, data: response.data };
46
- } catch (error) {
47
- return {
48
- success: false,
49
- error: error.response?.data?.errors || error.message,
50
- status: error.response?.status
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
- const { page = 0, size = 50, barcode, approved, onSale } = params;
61
- return await this._request('GET', `/suppliers/${this.supplierId}/products`, null, {
62
- page, size, barcode, approved, onSale
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
- const result = await this.getProducts({ barcode });
68
- if (result.success && result.data.content?.length > 0) {
69
- return { success: true, data: result.data.content[0] };
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
- // items: [{ barcode, title, productMainId, brandId, categoryId, ... }]
76
- return await this._request('POST', `/suppliers/${this.supplierId}/v2/products`, { items: products });
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
- return await this._request('PUT', `/suppliers/${this.supplierId}/v2/products`, { items: products });
81
- }
91
+ return await this._request('PUT', `/suppliers/${this.supplierId}/v2/products`, { items: products });
92
+ }
82
93
 
83
94
  async deleteProducts(barcodes) {
84
- const items = barcodes.map(barcode => ({ barcode }));
85
- return await this._request('DELETE', `/suppliers/${this.supplierId}/products`, { items });
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
- // items: [{ barcode, quantity, salePrice, listPrice }]
94
- return await this._request('POST', `/suppliers/${this.supplierId}/products/price-and-inventory`, { items });
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
- return await this.updatePriceAndStock([{
99
- barcode,
100
- salePrice,
101
- listPrice: listPrice || salePrice
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
- return await this.updatePriceAndStock([{ barcode, quantity }]);
107
- }
117
+ return await this.updatePriceAndStock([{ barcode, quantity }]);
118
+ }
108
119
 
109
120
  async bulkPriceUpdate(updates) {
110
- // updates: [{ barcode, price, listPrice? }]
111
- const items = updates.map(u => ({
112
- barcode: u.barcode,
113
- salePrice: u.price,
114
- listPrice: u.listPrice || u.price
115
- }));
116
- return await this.updatePriceAndStock(items);
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
- const {
125
- status,
126
- startDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).getTime(), // Son 30 gün
127
- endDate = Date.now(),
128
- page = 0,
129
- size = 50,
130
- orderNumber
131
- } = params;
132
-
133
- return await this._request('GET', `/suppliers/${this.supplierId}/orders`, null, {
134
- status, startDate, endDate, page, size, orderNumber, orderByDirection: 'DESC', orderByField: 'PackageLastModifiedDate'
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
- const result = await this.getOrders({ orderNumber });
140
- if (result.success && result.data.content?.length > 0) {
141
- return { success: true, data: result.data.content[0] };
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
- // lines: [{ lineId, quantity }]
148
- // status: Picking, Invoiced, UnSupplied
149
- const endpoint = `/suppliers/${this.supplierId}/shipment-packages`;
150
-
151
- if (status === 'Picking') {
152
- return await this._request('PUT', endpoint, { lines, status: 'Picking' });
153
- } else if (status === 'Invoiced') {
154
- return await this._request('PUT', endpoint, {
155
- lines,
156
- status: 'Invoiced',
157
- invoiceNumber: params.invoiceNumber
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
- // cargoKey: YURTICI, MNG, ARAS, PTT, SURAT, UPS, HOROZ, CEVA, SENDEO
166
- return await this._request('PUT',
167
- `/suppliers/${this.supplierId}/shipment-packages/${shipmentPackageId}`,
168
- {
169
- trackingNumber,
170
- cargoProviderCode: cargoKey,
171
- status: 'Shipped'
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
- return await this._request('GET', '/shipment-providers');
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
- return await this._request('GET', '/product-categories');
186
- }
196
+ return await this._request('GET', '/product-categories');
197
+ }
187
198
 
188
199
  async getCategoryAttributes(categoryId) {
189
- return await this._request('GET', `/product-categories/${categoryId}/attributes`);
190
- }
200
+ return await this._request('GET', `/product-categories/${categoryId}/attributes`);
201
+ }
191
202
 
192
203
  async searchBrands(name) {
193
- return await this._request('GET', '/brands', null, { name });
194
- }
204
+ return await this._request('GET', '/brands', null, { name });
205
+ }
195
206
 
196
207
  async getBrandsByCategory(categoryId) {
197
- return await this._request('GET', `/product-categories/${categoryId}/brands`);
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
- // Bu endpoint resmi API'de yok, web scraping gerekir
206
- // Alternatif: Brave Search API ile rakip araması
207
- try {
208
- // Trendyol'da aynı ürünü satan diğer satıcıları bul
209
- const searchUrl = `https://www.trendyol.com/sr?q=${barcode}`;
210
- // Not: Bu gerçek scraping gerektirir, burada placeholder
211
- return {
212
- success: true,
213
- competitors: [],
214
- message: 'Rakip analizi için web_search tool kullanın'
215
- };
216
- } catch (error) {
217
- return { success: false, error: error.message };
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
- const { status = 'WAITING_FOR_ANSWER', page = 0, size = 50 } = params;
227
- return await this._request('GET', `/suppliers/${this.supplierId}/questions/filter`, null, {
228
- status, page, size
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
- return await this._request('POST', `/suppliers/${this.supplierId}/questions/${questionId}/answers`, {
234
- text: answer
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
- return await this._request('GET', `/suppliers/${this.supplierId}/webhooks`);
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
- return await this._request('POST', `/suppliers/${this.supplierId}/webhooks`, {
248
- url,
249
- events
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
- const result = await this.getProducts({ page: 0, size: 1 });
259
- return result.success;
260
- }
269
+ const result = await this.getProducts({ page: 0, size: 1 });
270
+ return result.success;
271
+ }
261
272
 
262
- isConnected() {
263
- return !!(this.supplierId && this.apiKey && this.apiSecret);
264
- }
273
+ isConnected() {
274
+ return !!(this.supplierId && this.apiKey && this.apiSecret);
275
+ }
265
276
 
266
- formatProduct(raw) {
267
- return {
268
- id: raw.id,
269
- barcode: raw.barcode,
270
- title: raw.title,
271
- brand: raw.brand,
272
- category: raw.categoryName,
273
- price: raw.salePrice,
274
- listPrice: raw.listPrice,
275
- stock: raw.quantity,
276
- images: raw.images?.map(i => i.url) || [],
277
- approved: raw.approved,
278
- onSale: raw.onSale,
279
- url: `https://www.trendyol.com/p/-p-${raw.id}`
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
  };