almeira-web/scripts/migrate_clean_titles.js

151 lines
6.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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();