151 lines
6.5 KiB
JavaScript
151 lines
6.5 KiB
JavaScript
const sdk = require('node-appwrite');
|
||
|
||
const client = new sdk.Client()
|
||
.setEndpoint('https://appwrite.almeira.com.co/v1')
|
||
.setProject('69b84df5003bd8957c5c')
|
||
.setKey('standard_cce3cdb866ea6433888d40cedd24dc45987372308fdc3dd0697de08648c0e5c7e04b02c3bcee271403fd656b00a5820f04c08b51631284a6e8a3582d8aed2aa33234f3c29cc777e9b162eb54810b789251b0d006a9a3b081ebc2da53b9baa94614b124b3508ad849fd9a4187cc6094f506d4b57f409b69d9562a74df594f3ec3');
|
||
|
||
const dbs = new sdk.Databases(client);
|
||
const DB_ID = 'sneakers_multistore_db';
|
||
const COLLECTION_ID = 'products';
|
||
|
||
function cleanTitle(rawTitle, fallbackBrand = 'Sneakers') {
|
||
if (!rawTitle || typeof rawTitle !== 'string') {
|
||
return fallbackBrand && fallbackBrand !== 'Urbano / Variado' && fallbackBrand !== 'Desconocida'
|
||
? `${fallbackBrand} Urban Edition`
|
||
: 'Sneakers Urban Classic';
|
||
}
|
||
|
||
// 0. Normalizar fuentes estilizadas (Unicode Mathematical / Bold fonts como 𝐍𝐈𝐊𝐄 𝐒𝐁 𝐏𝐋𝐔𝐌𝐀)
|
||
let cleaned = rawTitle.normalize('NFKD').trim();
|
||
|
||
// 1. Quitar emojis y pictogramas de todo tipo
|
||
cleaned = cleaned
|
||
.replace(/[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{27BF}]|[\u{2300}-\u{23FF}]|[\u{200D}\u{FE0F}]|\*/gu, ' ')
|
||
.replace(/[🔥🔴‼️✨🌸👑💎🛍️🌟💸💰💵💲⭐🌹⚡💥👖👩🏻👫👻☀️🔝🙋🏻♀️😍🎩💕⏰🌎]/g, ' ');
|
||
|
||
// 2. Quitar códigos de bodega/proveedor: "Cod: 734-732 Bbo", "Cod: 2236", "Cod: 668/833 Bbo"
|
||
cleaned = cleaned.replace(/\bcod(?:igo)?\s*[:\-–—]?\s*[\d\s\-\/]+(?:\s*bbo)?\b/gi, ' ');
|
||
|
||
// 3. Quitar paréntesis o corchetes con tallas o números
|
||
cleaned = cleaned
|
||
.replace(/\(\s*(?:tallas?|euro|eur|talla|disponibles?|del)?[^\)]*\b(?:3[2-9]|4[0-9]|5[0-6])\b[^\)]*\)/gi, ' ')
|
||
.replace(/\([^\)]*\b(?:euro|eur|talla|tallas|mil)\b[^\)]*\)/gi, ' ')
|
||
.replace(/\(\s*\)|\[\s*\]/g, ' ');
|
||
|
||
// 4. Quitar rangos y expresiones de tallas
|
||
cleaned = cleaned.replace(/\bdel\s+(?:3[0-9]|4[0-9])\s+al\s+(?:3[0-9]|4[0-9])(?:\s*(?:eur|eu|euro))?\b/gi, ' ');
|
||
cleaned = cleaned.replace(/\b(?:euro|eur|eu)\s*[:\-–—\/\s]+(?:3[0-9]|4[0-9])(?:\s*(?:-|–|—|a|al|\/)\s*(?:3[0-9]|4[0-9]))*/gi, ' ');
|
||
cleaned = cleaned.replace(/\b(?:3[0-9]|4[0-9])\s+al\s+(?:3[0-9]|4[0-9])(?:\s*(?:eur|eu|euro))\b/gi, ' ');
|
||
cleaned = cleaned.replace(/\b(?:3[2-9]|4[0-9]|5[0-6])\s*(?:&|y|\/|\-)\s*(?:hombre\s+)?(?:3[2-9]|4[0-9]|5[0-6])(?:\s*(?:eur|eu|euro))?\b/gi, ' ');
|
||
cleaned = cleaned.replace(/\b(?:3[2-9]|4[0-9]|5[0-6])(?:\s*[-–—\/]\s*(?:3[2-9]|4[0-9]|5[0-6]))+\b/gi, ' ');
|
||
cleaned = cleaned.replace(/\b(?:talla|tallas|eur|euro|eu)\s+(?:3[2-9]|4[0-8])\b/gi, ' ');
|
||
cleaned = cleaned.replace(/\bhasta\s+(?:talla\s+)?(?:3[2-9]|4[0-9]|5[0-6])(?:\s*(?:eur|eu|euro))?\b/gi, ' ');
|
||
cleaned = cleaned.replace(/\b(?:solo\s+)?tallas?\s*(?:[:\-–—\s]+(?:hasta|desde|de|disponibles?|al\s+\d+))?\b/gi, ' ');
|
||
cleaned = cleaned.replace(/\b(?:al|a)\s+(?:3[2-9]|4[0-8])\b/gi, ' ');
|
||
cleaned = cleaned.replace(/\b(?:hasta|desde|tallas?|talla|disponibles?)\b/gi, ' ');
|
||
cleaned = cleaned.replace(/\(\s*(?:vienen?|viene)?\s*reducid[oa]s?\s*\)/gi, ' ');
|
||
|
||
// 5. Quitar '.000' residual y precios monetarios
|
||
cleaned = cleaned
|
||
.replace(/(?:^|[\s\(\[\.,\-_])(?:[1-9]\d{0,2})?\.000\b/gi, ' ')
|
||
.replace(/\b\d{2,3}[\.,]\d{3}\b|\b\d{2,3}k\b|\b\d{2,3}\s*mil\b|\$\s*\d+/gi, ' ')
|
||
.replace(/\.000\b/gi, ' ');
|
||
|
||
// 6. Quitar palabras residuales
|
||
cleaned = cleaned
|
||
.replace(/dama\s*y\s*caballero|recarga|nueva\s*mercanc[ií]a|[uú]ltima\s*unidad/gi, ' ')
|
||
.replace(/\b(costo|precio|valor|al\s*por\s*mayor|mayorista)\b/gi, ' ')
|
||
.replace(/\b(hombre|dama|caballero)\b/gi, ' ')
|
||
.replace(/\b(eur|euro|eu|mil)\b/gi, ' ');
|
||
|
||
// 7. Limpiar símbolos residuales y ampersands al inicio y final
|
||
cleaned = cleaned
|
||
.replace(/\s+&\s*$/g, '')
|
||
.replace(/^\s*&\s+/g, '')
|
||
.replace(/^[#*_\-•—–~:;,\s\.\/&]+|[#*_\-•—–~:;,\s\.\/&]+$/g, '')
|
||
.replace(/\s+/g, ' ')
|
||
.trim();
|
||
|
||
// 8. Fallback si quedó genérico o vacío
|
||
const cleanLower = cleaned.toLowerCase();
|
||
const isGeneric =
|
||
cleaned.length < 3 ||
|
||
/^[\d\s\-.,/&]+$/.test(cleaned) ||
|
||
['euro', 'eur', 'zapatillas', 'sneakers', 'calzado', 'estilo', 'moda', 'solo', 'sin producto'].includes(cleanLower) ||
|
||
cleanLower.startsWith('solo ') ||
|
||
cleanLower.startsWith('euro ') ||
|
||
cleanLower.startsWith('sin producto');
|
||
|
||
if (isGeneric) {
|
||
return fallbackBrand && fallbackBrand !== 'Urbano / Variado' && fallbackBrand !== 'Desconocida' && fallbackBrand !== 'Generica'
|
||
? `${fallbackBrand} Urban Edition`
|
||
: 'Sneakers Urban Classic';
|
||
}
|
||
|
||
// 9. Capital Case limpio conservando siglas comerciales
|
||
return cleaned
|
||
.split(' ')
|
||
.filter(Boolean)
|
||
.map((w) => {
|
||
if (/^(OG|SE|SB|TN|CL|GT|RS-X|BB|LV|NB|XT-6|CR7|V2K|V5K|9060|550|530|1906R|2002R)$/i.test(w)) {
|
||
return w.toUpperCase();
|
||
}
|
||
if (/^[A-Z0-9]+$/i.test(w) && w.length <= 4 && !/[aeiou]/i.test(w)) {
|
||
return w.toUpperCase();
|
||
}
|
||
return w.charAt(0).toUpperCase() + w.slice(1).toLowerCase();
|
||
})
|
||
.join(' ');
|
||
}
|
||
|
||
async function migrate() {
|
||
console.log('🚀 Iniciando migración y saneamiento profundo de títulos en Appwrite...');
|
||
let allDocs = [];
|
||
let cursor = null;
|
||
|
||
while (true) {
|
||
const queries = [sdk.Query.limit(100)];
|
||
if (cursor) {
|
||
queries.push(sdk.Query.cursorAfter(cursor));
|
||
}
|
||
const res = await dbs.listDocuments(DB_ID, COLLECTION_ID, queries);
|
||
const docs = res.documents || [];
|
||
if (docs.length === 0) break;
|
||
allDocs.push(...docs);
|
||
cursor = docs[docs.length - 1].$id;
|
||
if (docs.length < 100) break;
|
||
}
|
||
|
||
console.log(`📦 Total documentos recuperados de Appwrite: ${allDocs.length}`);
|
||
let updatedCount = 0;
|
||
|
||
for (const doc of allDocs) {
|
||
const oldName = doc.name || '';
|
||
const oldModel = doc.modelName || '';
|
||
const brand = doc.brand || 'Sneakers';
|
||
|
||
const newName = cleanTitle(oldName, brand);
|
||
const newModel = cleanTitle(oldModel || oldName, brand);
|
||
|
||
if (oldName !== newName || oldModel !== newModel) {
|
||
try {
|
||
await dbs.updateDocument(DB_ID, COLLECTION_ID, doc.$id, {
|
||
name: newName,
|
||
modelName: newModel,
|
||
});
|
||
console.log(`✅ [FIXED] ${doc.$id}:`);
|
||
console.log(` OLD: "${oldName}"`);
|
||
console.log(` NEW: "${newName}"`);
|
||
updatedCount++;
|
||
} catch (err) {
|
||
console.error(`❌ [ERROR] ${doc.$id}:`, err.message);
|
||
}
|
||
}
|
||
}
|
||
|
||
console.log(`\n🎉 Migración finalizada con éxito: ${updatedCount} productos saneados en Appwrite.`);
|
||
}
|
||
|
||
migrate();
|