E-Ticaret Panel
Mağazalar
Mağaza Düzenle
Mağaza Adı
XML Linki
Shopify Store Name
.myshopify.com
Access Token
API Version
2025-07 (En Güncel - Önerilen)
2025-04
2025-01
2024-10
2024-07
2024-04 (Legacy)
2024-01 (Legacy)
Mevcut: 2025-07
Kontrol Süresi
Saniye
Dakika
Saat
Gün
Product Path (Opsiyonel)
XML'de ürünlerin bulunduğu path
🏷️ Vendor (Marka) Filtreleme
📦 Tüm markalar işleniyor
← Ana sayfadan "Filtre Ekle" butonuyla vendor seçimi yapabilirsiniz
Converter Kodunuz
/** * Eyyo Retail XML -> Shopify CSV Converter * XML: https://www.eyyo.com.tr/xml/?R=796043&K=14d3&AltUrun=1&Dislink=1&start=0&limit=99999&pass=hyVk890a * * XML Yapisi: * <products> * <product> * code, ws_code, barcode, name, brand, category_path * stock, price_list_vat_included, price_special_vat_included * detail, product_link * subproducts -> subproduct[] -> code, ws_code, type1(renk), type2(beden), barcode, stock, price_special * </product> * </products> */ module.exports = function convertEyyoRetail(item, utils = {}) { // ============ HELPER FUNCTIONS ============ const trim = v => (v == null ? '' : String(v).trim()); const isUrl = u => /^https?:\/\//i.test(String(u || '')); const toNum = v => { if (v == null || v === '') return null; const str = String(v).replace(/\s/g, '').replace(',', '.'); const n = Number(str); return Number.isFinite(n) ? n : null; }; const money = v => { const n = toNum(v); return n == null || n <= 0 ? '0.00' : n.toFixed(2); }; const toInt = v => { const n = parseInt(String(v || '0').replace(/[^\d]/g, ''), 10); return Number.isFinite(n) && n >= 0 ? n : 0; }; const uniq = arr => Array.from(new Set((arr || []).filter(Boolean))); // Turkce karakter donusumu const turkishToLatin = s => String(s) .replace(/\u011f/g, 'g').replace(/\u011e/g, 'g') .replace(/\u00fc/g, 'u').replace(/\u00dc/g, 'u') .replace(/\u015f/g, 's').replace(/\u015e/g, 's') .replace(/\u0131/g, 'i').replace(/\u0130/g, 'i') .replace(/\u00f6/g, 'o').replace(/\u00d6/g, 'o') .replace(/\u00e7/g, 'c').replace(/\u00c7/g, 'c'); const slugify = (s = '') => { if (utils.slugify) return utils.slugify(s); return turkishToLatin(String(s)) .toLowerCase() .normalize('NFKD') .replace(/[\u0300-\u036f]/g, '') .replace(/[^a-z0-9]+/g, '-') .replace(/(^-|-$)/g, ''); }; const cleanHTML = (s = '') => String(s) .replace(/<script[\s\S]*?<\/script>/gi, '') .replace(/<style[\s\S]*?<\/style>/gi, '') .replace(/ /gi, ' ') .replace(/\s+/g, ' ') .trim(); // xml2js array unwrapper const val = v => { if (Array.isArray(v)) return val(v[0]); if (v && typeof v === 'object' && '_' in v) return val(v._); return v; }; const toArray = v => { if (v == null) return []; return Array.isArray(v) ? v : [v]; }; // Beden siralama const SIZE_ORDER = ['XXS', 'XS', 'S', 'M', 'L', 'XL', '2XL', 'XXL', '3XL', '4XL', '5XL']; const sizeRank = s => { const u = String(s || '').toUpperCase().trim(); const num = parseInt(u, 10); if (!isNaN(num)) return num; const i = SIZE_ORDER.indexOf(u); return i === -1 ? 999 : i; }; // ============ XML WRAPPER UNWRAP ============ // Root wrapper kontrolu - products > product if (item.products) { const products = toArray(item.products.product || item.products); return products.flatMap(p => convertEyyoRetail(p, utils)); } // Alternatif wrapper if (item.product && !item.code && !item.name) { const products = toArray(item.product); return products.flatMap(p => convertEyyoRetail(p, utils)); } // ============ SINGLE PRODUCT CONVERSION ============ // Temel alanlar const productId = trim(val(item.code)) || ''; const wsCode = trim(val(item.ws_code)) || ''; const barcode = trim(val(item.barcode)) || ''; const title = trim(val(item.name)) || 'Isimsiz Urun'; const brand = trim(val(item.brand)) || 'Eyyo'; const detail = cleanHTML(val(item.detail) || ''); const productLink = trim(val(item.product_link)) || ''; // Kategori const categoryPath = trim(val(item.category_path)) || ''; const categoryParts = categoryPath.split(/[\/>,]/).map(s => s.trim()).filter(Boolean); const productType = categoryParts[categoryParts.length - 1] || categoryPath || 'Giyim'; // Stok const totalStock = toInt(val(item.stock)); // Fiyat (TL) const salePrice = toNum(val(item.price_special_vat_included)) || toNum(val(item.price_special)) || 0; const listPrice = toNum(val(item.price_list_vat_included)) || toNum(val(item.price_list)) || 0; const compareAtPrice = listPrice > salePrice ? listPrice : 0; // Renk (subproduct'lardan al) let colorName = ''; // Gorseller const images = []; let imagesNode = item.images; if (Array.isArray(imagesNode)) { imagesNode = imagesNode[0]; } if (imagesNode && imagesNode.img_item) { const imgArray = toArray(imagesNode.img_item); imgArray.forEach(img => { const src = trim(val(img)); if (isUrl(src) && !images.includes(src)) { images.push(src); } }); } // Tags const tags = uniq([ brand, ...categoryParts ]).filter(Boolean).join(', '); // Handle olustur const handle = utils.toHandle ? utils.toHandle(productId + '-' + title) : slugify(productId + '-' + title); const PRODUCT_KEY = productId || handle; // ============ VARYANT ISLEME ============ let variants = []; let subproductsNode = item.subproducts; if (Array.isArray(subproductsNode)) { subproductsNode = subproductsNode[0]; } if (subproductsNode && subproductsNode.subproduct) { const subArray = toArray(subproductsNode.subproduct); variants = subArray.map(sub => { const subCode = trim(val(sub.code)); const subWsCode = trim(val(sub.ws_code)) || wsCode; const subBarcode = trim(val(sub.barcode)) || ''; const subStock = toInt(val(sub.stock)); const subPrice = toNum(val(sub.price_special)) || salePrice; const color = trim(val(sub.type1)) || ''; const size = trim(val(sub.type2)) || 'STD'; // Ilk rengi kaydet if (!colorName && color) { colorName = color; } return { id: subCode, sku: subWsCode, ean: subBarcode, stock: subStock, price: subPrice, color: color, optionName: 'Beden', optionValue: size.toUpperCase() }; }).filter(v => v.optionValue); } // Varyant yoksa varsayilan olustur if (variants.length === 0) { variants = [{ id: productId, sku: wsCode || productId, ean: barcode, stock: totalStock, price: salePrice, color: '', optionName: 'Title', optionValue: 'Default Title' }]; } // Bedenleri sirala variants.sort((a, b) => sizeRank(a.optionValue) - sizeRank(b.optionValue)); // Tags'e renk ekle const finalTags = colorName ? tags + ', ' + colorName : tags; // ============ CSV SATIRLARI OLUSTUR ============ const rows = []; // Ilk varyantin option name'ini kullan const mainOptionName = variants[0].optionName; variants.forEach((variant, idx) => { const isFirst = idx === 0; const variantPrice = money(variant.price); const variantCompareAt = compareAtPrice > variant.price ? money(compareAtPrice) : ''; const row = { __PRODUCT_KEY: PRODUCT_KEY, Handle: handle, Title: isFirst ? title : '', 'Body (HTML)': isFirst ? detail : '', Vendor: isFirst ? brand : '', Type: isFirst ? productType : '', Tags: isFirst ? finalTags : '', Published: 'TRUE', 'Option1 Name': isFirst ? mainOptionName : '', 'Option1 Value': variant.optionValue, 'Option2 Name': '', 'Option2 Value': '', 'Option3 Name': '', 'Option3 Value': '', 'Variant SKU': variant.sku, 'Variant Inventory Qty': variant.stock, 'Variant Price': variantPrice, 'Variant Compare At Price': variantCompareAt, 'Variant Barcode': variant.ean, 'Image Src': isFirst && images[0] ? images[0] : '', 'Image Position': isFirst && images[0] ? '1' : '', 'Variant Image': isFirst && images[0] ? images[0] : '', Status: isFirst ? 'active' : '' }; rows.push(row); }); // Ek gorseller (ilk gorsel haric) images.slice(1).forEach((src, idx) => { rows.push({ __PRODUCT_KEY: PRODUCT_KEY, Handle: handle, 'Image Src': src, 'Image Position': String(idx + 2) }); }); return rows; };
Güncelle
İptal
İstatistikler
Toplam Çalışma
436
Başarı Oranı
99%
İşlenen Ürün
0
Push Edilen
0