const sdk = require('node-appwrite'); const client = new sdk.Client(); const databases = new sdk.Databases(client); const ENDPOINT = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'http://localhost/v1'; const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69bedced002971103d13'; const API_KEY = process.env.APPWRITE_API_KEY || 'standard_2350cc147ace39b0e3fb2c42d1447bc00effb4d5e6115cd682b0d215297a3b35b2ce82e312bd35cff1b738d5eb3462c5b28887937acf217eca6c2143aa0bf4e85ab183350db830901edc0d80d17755d1de5524b945d0c4cb11871af8d33df7f7cdbdfea4237dfc8a47e3c71ac79b3e5172834cc09d451d687a3db74e839ec7a7'; client .setEndpoint(ENDPOINT) .setProject(PROJECT_ID) .setKey(API_KEY); const delay = ms => new Promise(res => setTimeout(res, ms)); const dbId = 'almeira'; async function setupV2() { try { console.log('========================================'); console.log('Almeira Web — Setup v2'); console.log('========================================\n'); // ───────────────────────────────────────────────────────────── // 1. PAÍSES // ───────────────────────────────────────────────────────────── console.log('[1/10] Creando colección: Países...'); try { await databases.createCollection(dbId, 'countries', 'Países', [], false); } catch(e){ console.log(' >', e.message); } await delay(500); try { await databases.createStringAttribute(dbId, 'countries', 'codigo', 10, true); } catch(e){} try { await databases.createStringAttribute(dbId, 'countries', 'descripcion', 100, true); } catch(e){} await delay(1000); // ───────────────────────────────────────────────────────────── // 2. DEPARTAMENTOS // ───────────────────────────────────────────────────────────── console.log('[2/10] Creando colección: Departamentos...'); try { await databases.createCollection(dbId, 'departments', 'Departamentos', [], false); } catch(e){ console.log(' >', e.message); } await delay(500); try { await databases.createStringAttribute(dbId, 'departments', 'codigo', 10, true); } catch(e){} try { await databases.createStringAttribute(dbId, 'departments', 'descripcion', 100, true); } catch(e){} try { await databases.createStringAttribute(dbId, 'departments', 'pais_id', 255, true); } catch(e){} // FK → countries.$id await delay(1000); // ───────────────────────────────────────────────────────────── // 3. CIUDADES // ───────────────────────────────────────────────────────────── console.log('[3/10] Creando colección: Ciudades...'); try { await databases.createCollection(dbId, 'cities', 'Ciudades', [], false); } catch(e){ console.log(' >', e.message); } await delay(500); try { await databases.createStringAttribute(dbId, 'cities', 'codigo', 10, true); } catch(e){} try { await databases.createStringAttribute(dbId, 'cities', 'descripcion', 100, true); } catch(e){} try { await databases.createStringAttribute(dbId, 'cities', 'departamento_id', 255, true); } catch(e){} // FK → departments.$id await delay(1000); // ───────────────────────────────────────────────────────────── // 4. TIPOS DE PUBLICACIÓN // ───────────────────────────────────────────────────────────── console.log('[4/10] Creando colección: Tipos de Publicación...'); try { await databases.createCollection(dbId, 'publication_types', 'Tipos de Publicación', [], false); } catch(e){ console.log(' >', e.message); } await delay(500); try { await databases.createStringAttribute(dbId, 'publication_types', 'codigo', 50, true); } catch(e){} try { await databases.createStringAttribute(dbId, 'publication_types', 'descripcion', 255, true); } catch(e){} await delay(1500); // Datos iniciales — Tipos de Publicación console.log(' Insertando datos iniciales de Tipos de Publicación...'); const tiposPublicacion = [ { codigo: 'NOTICIA', descripcion: 'Noticia' }, { codigo: 'EVENTO', descripcion: 'Evento' }, { codigo: 'CLASIFICADO', descripcion: 'Clasificado' }, { codigo: 'DISPLAY_BANNER', descripcion: 'Display Banner' }, { codigo: 'DISPLAY_SLIDER', descripcion: 'Display Slider' }, ]; for (const t of tiposPublicacion) { try { await databases.createDocument(dbId, 'publication_types', sdk.ID.unique(), t); console.log(` ✓ ${t.descripcion}`); } catch(e){ console.log(` x ${t.descripcion}:`, e.message); } await delay(300); } // ───────────────────────────────────────────────────────────── // 5. CATEGORÍAS // ───────────────────────────────────────────────────────────── console.log('[5/10] Creando colección: Categorías...'); try { await databases.createCollection(dbId, 'categories', 'Categorías', [], false); } catch(e){ console.log(' >', e.message); } await delay(500); try { await databases.createStringAttribute(dbId, 'categories', 'nombre', 100, true); } catch(e){} try { await databases.createStringAttribute(dbId, 'categories', 'slug', 100, true); } catch(e){} await delay(1000); // ───────────────────────────────────────────────────────────── // 6. POSTS ↔ CATEGORÍAS (tabla puente many-to-many) // ───────────────────────────────────────────────────────────── console.log('[6/10] Creando colección: Posts-Categorías (relación N:M)...'); try { await databases.createCollection(dbId, 'posts_categories', 'Posts-Categorías', [], false); } catch(e){ console.log(' >', e.message); } await delay(500); try { await databases.createStringAttribute(dbId, 'posts_categories', 'post_id', 255, true); } catch(e){} // FK → posts.$id try { await databases.createStringAttribute(dbId, 'posts_categories', 'categoria_id', 255, true); } catch(e){} // FK → categories.$id await delay(1000); // ───────────────────────────────────────────────────────────── // 7. TIPOS DE CLIENTE // ───────────────────────────────────────────────────────────── console.log('[7/10] Creando colección: Tipos de Cliente...'); try { await databases.createCollection(dbId, 'client_types', 'Tipos de Cliente', [], false); } catch(e){ console.log(' >', e.message); } await delay(500); try { await databases.createStringAttribute(dbId, 'client_types', 'codigo', 50, true); } catch(e){} try { await databases.createStringAttribute(dbId, 'client_types', 'descripcion', 100, true); } catch(e){} await delay(1500); // Datos iniciales — Tipos de Cliente console.log(' Insertando datos iniciales de Tipos de Cliente...'); const tiposCliente = [ { codigo: 'INSTITUCIONAL', descripcion: 'Institucional' }, { codigo: 'COMERCIAL', descripcion: 'Comercial' }, ]; for (const t of tiposCliente) { try { await databases.createDocument(dbId, 'client_types', sdk.ID.unique(), t); console.log(` ✓ ${t.descripcion}`); } catch(e){ console.log(` x ${t.descripcion}:`, e.message); } await delay(300); } // ───────────────────────────────────────────────────────────── // 8. FORMAS DE PAGO // ───────────────────────────────────────────────────────────── console.log('[8/10] Creando colección: Formas de Pago...'); try { await databases.createCollection(dbId, 'payment_methods', 'Formas de Pago', [], false); } catch(e){ console.log(' >', e.message); } await delay(500); try { await databases.createStringAttribute(dbId, 'payment_methods', 'codigo', 50, true); } catch(e){} try { await databases.createStringAttribute(dbId, 'payment_methods', 'descripcion', 255, true); } catch(e){} try { await databases.createIntegerAttribute(dbId, 'payment_methods', 'numero_dias', true); } catch(e){} await delay(1000); // ───────────────────────────────────────────────────────────── // 9. CONTRATOS // ───────────────────────────────────────────────────────────── console.log('[9/10] Creando colección: Contratos...'); try { await databases.createCollection(dbId, 'contracts', 'Contratos', [], false); } catch(e){ console.log(' >', e.message); } await delay(500); try { await databases.createStringAttribute(dbId, 'contracts', 'numero_contrato', 100, true); } catch(e){} try { await databases.createStringAttribute(dbId, 'contracts', 'estado', 50, true); } catch(e){} // Activo, En Mora, Finalizado try { await databases.createStringAttribute(dbId, 'contracts', 'cliente_id', 255, true); } catch(e){} // FK → clients.$id try { await databases.createStringAttribute(dbId, 'contracts', 'descripcion', 2000, true); } catch(e){} try { await databases.createDatetimeAttribute(dbId, 'contracts', 'fecha_inicial', true); } catch(e){} try { await databases.createDatetimeAttribute(dbId, 'contracts', 'fecha_final', true); } catch(e){} try { await databases.createFloatAttribute(dbId, 'contracts', 'valor_contrato', true); } catch(e){} try { await databases.createStringAttribute(dbId, 'contracts', 'forma_pago_id', 255, true); } catch(e){} // FK → payment_methods.$id await delay(1000); // ───────────────────────────────────────────────────────────── // 10. DETALLE DEL CONTRATO // ───────────────────────────────────────────────────────────── console.log('[10/10] Creando colección: Detalle del Contrato...'); try { await databases.createCollection(dbId, 'contract_details', 'Detalle del Contrato', [], false); } catch(e){ console.log(' >', e.message); } await delay(500); try { await databases.createStringAttribute(dbId, 'contract_details', 'contrato_id', 255, true); } catch(e){} // FK → contracts.$id try { await databases.createStringAttribute(dbId, 'contract_details', 'tipo_publicacion_id', 255, true); } catch(e){} // FK → publication_types.$id try { await databases.createStringAttribute(dbId, 'contract_details', 'cantidad_periodo', 50, true); } catch(e){} try { await databases.createIntegerAttribute(dbId, 'contract_details', 'cantidad_total', true); } catch(e){} await delay(1000); // ───────────────────────────────────────────────────────────── // MODIFICACIONES A COLECCIONES EXISTENTES // ───────────────────────────────────────────────────────────── // --- Colección: posts --- // Nota: Appwrite no permite modificar el campo 'required' de un atributo existente. // Para hacer cliente_id no requerido, hay que eliminar y recrear. console.log('\n[MOD] Modificando colección: posts...'); console.log(' Reconstruyendo cliente_id como opcional...'); try { await databases.deleteAttribute(dbId, 'posts', 'cliente_id'); await delay(1500); await databases.createStringAttribute(dbId, 'posts', 'cliente_id', 255, false); // no requerido console.log(' ✓ cliente_id ahora es opcional'); } catch(e){ console.log(' x cliente_id:', e.message); } console.log(' Agregando tipo_publicacion_id a posts...'); try { await databases.createStringAttribute(dbId, 'posts', 'tipo_publicacion_id', 255, true); // FK → publication_types.$id console.log(' ✓ tipo_publicacion_id creado'); } catch(e){ console.log(' x tipo_publicacion_id:', e.message); } await delay(1000); // --- Colección: clients --- console.log('\n[MOD] Modificando colección: clients...'); try { await databases.createStringAttribute(dbId, 'clients', 'nit', 30, false); console.log(' ✓ nit');} catch(e){ console.log(' x nit:', e.message); } await delay(300); try { await databases.createStringAttribute(dbId, 'clients', 'tipo_cliente_id', 255, true); console.log(' ✓ tipo_cliente_id (req)'); } catch(e){ console.log(' x tipo_cliente_id:', e.message); } // FK → client_types.$id await delay(300); try { await databases.createStringAttribute(dbId, 'clients', 'direccion', 500, false); console.log(' ✓ direccion');} catch(e){ console.log(' x direccion:', e.message); } await delay(300); try { await databases.createStringAttribute(dbId, 'clients', 'ciudad_id', 255, false); console.log(' ✓ ciudad_id');} catch(e){ console.log(' x ciudad_id:', e.message); } // FK → cities.$id await delay(300); try { await databases.createEmailAttribute(dbId, 'clients', 'correo_electronico', false); console.log(' ✓ correo_electronico');} catch(e){ console.log(' x correo_electronico:', e.message); } await delay(300); try { await databases.createUrlAttribute(dbId, 'clients', 'sitio_web', false); console.log(' ✓ sitio_web');} catch(e){ console.log(' x sitio_web:', e.message); } await delay(300); console.log('\n========================================'); console.log('✅ Setup v2 completado con éxito!'); console.log('========================================'); } catch(e) { console.error('\n❌ Error global:', e.message); } } setupV2();