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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vantuz",
3
- "version": "3.1.3",
3
+ "version": "3.1.4",
4
4
  "description": "Yapay Zeka Destekli E-Ticaret Yönetim Platformu - 7 Pazaryeri + WhatsApp/Telegram",
5
5
  "type": "module",
6
6
  "main": "cli.js",
@@ -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
- 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) { }
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
- 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
+ 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
- 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
+ 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
- // items: [{ barcode, title, productMainId, brandId, categoryId, ... }]
87
- return await this._request('POST', `/suppliers/${this.supplierId}/v2/products`, { items: products });
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
- return await this._request('PUT', `/suppliers/${this.supplierId}/v2/products`, { items: products });
92
- }
85
+ return await this._request('PUT', `/suppliers/${this.supplierId}/v2/products`, { items: products });
86
+ }
93
87
 
94
88
  async deleteProducts(barcodes) {
95
- const items = barcodes.map(barcode => ({ barcode }));
96
- return await this._request('DELETE', `/suppliers/${this.supplierId}/products`, { items });
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
- // items: [{ barcode, quantity, salePrice, listPrice }]
105
- return await this._request('POST', `/suppliers/${this.supplierId}/products/price-and-inventory`, { items });
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
- return await this.updatePriceAndStock([{
110
- barcode,
111
- salePrice,
112
- listPrice: listPrice || salePrice
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
- return await this.updatePriceAndStock([{ barcode, quantity }]);
118
- }
111
+ return await this.updatePriceAndStock([{ barcode, quantity }]);
112
+ }
119
113
 
120
114
  async bulkPriceUpdate(updates) {
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
- }
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
- 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
- }
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
- 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
+ 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
- // 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
- });
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
- return { success: false, error: 'Geçersiz durum' };
173
- }
166
+ return { success: false, error: 'Geçersiz durum' };
167
+ }
174
168
 
175
169
  async shipOrder(shipmentPackageId, trackingNumber, cargoKey = 'YURTICI') {
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
- }
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
- return await this._request('GET', '/shipment-providers');
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
- return await this._request('GET', '/product-categories');
197
- }
190
+ return await this._request('GET', '/product-categories');
191
+ }
198
192
 
199
193
  async getCategoryAttributes(categoryId) {
200
- return await this._request('GET', `/product-categories/${categoryId}/attributes`);
201
- }
194
+ return await this._request('GET', `/product-categories/${categoryId}/attributes`);
195
+ }
202
196
 
203
197
  async searchBrands(name) {
204
- return await this._request('GET', '/brands', null, { name });
205
- }
198
+ return await this._request('GET', '/brands', null, { name });
199
+ }
206
200
 
207
201
  async getBrandsByCategory(categoryId) {
208
- return await this._request('GET', `/product-categories/${categoryId}/brands`);
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
- // 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 };
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
- 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
+ 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
- return await this._request('POST', `/suppliers/${this.supplierId}/questions/${questionId}/answers`, {
245
- text: answer
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
- return await this._request('GET', `/suppliers/${this.supplierId}/webhooks`);
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
- return await this._request('POST', `/suppliers/${this.supplierId}/webhooks`, {
259
- url,
260
- events
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
- const result = await this.getProducts({ page: 0, size: 1 });
270
- return result.success;
271
- }
263
+ const result = await this.getProducts({ page: 0, size: 1 });
264
+ return result.success;
265
+ }
272
266
 
273
- isConnected() {
274
- return !!(this.supplierId && this.apiKey && this.apiSecret);
275
- }
267
+ isConnected() {
268
+ return !!(this.supplierId && this.apiKey && this.apiSecret);
269
+ }
276
270
 
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
- }
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