/// migrate((app) => { // ── 0. Collection users (auth) ─────────────────────────── const users = new Collection({ name: "users", type: "auth" }); app.save(users); const usersId = users.id; // ── 1. Étapes pipeline ─────────────────────────────────── const etapes = new Collection({ name: "etapes_pipeline", type: "base", fields: [ { name: "user", type: "relation", required: true, options: { collectionId: usersId, maxSelect: 1, cascadeDelete: true } }, { name: "nom", type: "text", required: true }, { name: "ordre", type: "number", required: true }, { name: "couleur", type: "text" }, { name: "is_terminal", type: "bool" } ], listRule: "@request.auth.id != '' && user = @request.auth.id", viewRule: "@request.auth.id != '' && user = @request.auth.id", createRule: "@request.auth.id != ''", updateRule: "@request.auth.id != '' && user = @request.auth.id", deleteRule: "@request.auth.id != '' && user = @request.auth.id" }); app.save(etapes); // ── 2. Contacts ────────────────────────────────────────── const contacts = new Collection({ name: "contacts", type: "base", fields: [ { name: "user", type: "relation", required: true, options: { collectionId: usersId, maxSelect: 1, cascadeDelete: true } }, { name: "nom", type: "text", required: true }, { name: "prenom", type: "text" }, { name: "societe", type: "text" }, { name: "categorie", type: "select", required: true, options: { maxSelect: 1, values: ["notaire","agent_immo","artisan_gros_oeuvre","artisan_second_oeuvre","artisan_finitions","banquier","courtier","diagnostiqueur","geometre","avocat","comptable","vendeur","acheteur","autre"] } }, { name: "specialite", type: "text" }, { name: "telephone", type: "text" }, { name: "telephone_2", type: "text" }, { name: "email", type: "email" }, { name: "ville", type: "text" }, { name: "zone_intervention", type: "text" }, { name: "note", type: "number", options: { min: 1, max: 5 } }, { name: "recommande", type: "bool" }, { name: "taux_horaire", type: "number" }, { name: "notes", type: "text" }, { name: "is_favori", type: "bool" } ], listRule: "@request.auth.id != '' && user = @request.auth.id", viewRule: "@request.auth.id != '' && user = @request.auth.id", createRule: "@request.auth.id != ''", updateRule: "@request.auth.id != '' && user = @request.auth.id", deleteRule: "@request.auth.id != '' && user = @request.auth.id" }); app.save(contacts); // ── 3. Biens ───────────────────────────────────────────── const biens = new Collection({ name: "biens", type: "base", fields: [ { name: "user", type: "relation", required: true, options: { collectionId: usersId, maxSelect: 1, cascadeDelete: true } }, { name: "etape", type: "relation", options: { collectionId: etapes.id, maxSelect: 1 } }, { name: "source_contact", type: "relation", options: { collectionId: contacts.id, maxSelect: 1 } }, { name: "titre", type: "text" }, { name: "type_bien", type: "select", options: { maxSelect: 1, values: ["appartement","maison","immeuble","terrain","local_commercial","parking","cave","autre"] } }, { name: "adresse", type: "text" }, { name: "code_postal", type: "text" }, { name: "ville", type: "text" }, { name: "latitude", type: "number" }, { name: "longitude", type: "number" }, { name: "surface_habitable", type: "number" }, { name: "surface_totale", type: "number" }, { name: "nb_pieces", type: "number" }, { name: "nb_chambres", type: "number" }, { name: "annee_construction", type: "number" }, { name: "dpe_lettre", type: "select", options: { maxSelect: 1, values: ["A","B","C","D","E","F","G"] } }, { name: "dpe_valeur", type: "number" }, { name: "source", type: "select", options: { maxSelect: 1, values: ["particulier","agence","notaire","tribunal","succession","reseau","autre"] } }, { name: "url_annonce", type: "url" }, { name: "statut", type: "select", options: { maxSelect: 1, values: ["actif","abandonne","vendu"] } }, { name: "priorite", type: "number" }, { name: "is_off_market", type: "bool" }, { name: "date_premiere_visite", type: "text" }, { name: "date_offre", type: "text" }, { name: "date_compromis", type: "text" }, { name: "date_acte", type: "text" }, { name: "description", type: "text" }, { name: "points_forts", type: "text" }, { name: "points_faibles", type: "text" }, { name: "photo_principale", type: "file", options: { maxSelect: 1, maxSize: 10485760, mimeTypes: ["image/jpeg","image/png","image/webp"] } } ], listRule: "@request.auth.id != '' && user = @request.auth.id", viewRule: "@request.auth.id != '' && user = @request.auth.id", createRule: "@request.auth.id != ''", updateRule: "@request.auth.id != '' && user = @request.auth.id", deleteRule: "@request.auth.id != '' && user = @request.auth.id" }); app.save(biens); // ── 4. Analyses financières ─────────────────────────────── const analyses = new Collection({ name: "analyses_financieres", type: "base", fields: [ { name: "user", type: "relation", required: true, options: { collectionId: usersId, maxSelect: 1, cascadeDelete: true } }, { name: "bien", type: "relation", required: true, options: { collectionId: biens.id, maxSelect: 1, cascadeDelete: true } }, { name: "prix_achat", type: "number" }, { name: "type_bien_fiscal", type: "select", options: { maxSelect: 1, values: ["ancien","neuf"] } }, { name: "frais_notaire", type: "number" }, { name: "frais_agence_achat", type: "number" }, { name: "budget_travaux", type: "number" }, { name: "reserve_imprevus_pct", type: "number" }, { name: "duree_portage_mois", type: "number" }, { name: "taux_credit", type: "number" }, { name: "taxe_fonciere_annuelle", type: "number" }, { name: "charges_copropriete_mensuelle", type: "number" }, { name: "prix_revente_cible", type: "number" }, { name: "frais_agence_vente_pct", type: "number" }, { name: "taux_impot", type: "number" }, { name: "marge_brute", type: "number" }, { name: "marge_brute_pct", type: "number" }, { name: "marge_nette", type: "number" }, { name: "marge_nette_pct", type: "number" }, { name: "notes", type: "text" } ], listRule: "@request.auth.id != '' && user = @request.auth.id", viewRule: "@request.auth.id != '' && user = @request.auth.id", createRule: "@request.auth.id != ''", updateRule: "@request.auth.id != '' && user = @request.auth.id", deleteRule: "@request.auth.id != '' && user = @request.auth.id" }); app.save(analyses); // ── 5. Visites ──────────────────────────────────────────── const visites = new Collection({ name: "visites", type: "base", fields: [ { name: "user", type: "relation", required: true, options: { collectionId: usersId, maxSelect: 1, cascadeDelete: true } }, { name: "bien", type: "relation", required: true, options: { collectionId: biens.id, maxSelect: 1, cascadeDelete: true } }, { name: "date_visite", type: "date", required: true }, { name: "duree_minutes", type: "number" }, { name: "type_visite", type: "select", options: { maxSelect: 1, values: ["premiere","seconde","expert","contradiction"] } }, { name: "notes_brutes", type: "text" }, { name: "rapport_genere", type: "text" }, { name: "checklist_reponses", type: "json" }, { name: "estimation_travaux_min", type: "number" }, { name: "estimation_travaux_max", type: "number" }, { name: "avis_global", type: "select", options: { maxSelect: 1, values: ["coup_de_coeur","interessant","neutre","a_eviter"] } }, { name: "score_opportunite", type: "number", options: { min: 1, max: 10 } }, { name: "photos", type: "file", options: { maxSelect: 20, maxSize: 10485760, mimeTypes: ["image/jpeg","image/png","image/webp"] } } ], listRule: "@request.auth.id != '' && user = @request.auth.id", viewRule: "@request.auth.id != '' && user = @request.auth.id", createRule: "@request.auth.id != ''", updateRule: "@request.auth.id != '' && user = @request.auth.id", deleteRule: "@request.auth.id != '' && user = @request.auth.id" }); app.save(visites); // ── 6. Tâches ───────────────────────────────────────────── const taches = new Collection({ name: "taches", type: "base", fields: [ { name: "user", type: "relation", required: true, options: { collectionId: usersId, maxSelect: 1, cascadeDelete: true } }, { name: "bien", type: "relation", options: { collectionId: biens.id, maxSelect: 1 } }, { name: "contact", type: "relation", options: { collectionId: contacts.id, maxSelect: 1 } }, { name: "titre", type: "text", required: true }, { name: "description", type: "text" }, { name: "type_tache", type: "select", options: { maxSelect: 1, values: ["visite","appel","email","relance","administratif","travaux","banque","autre"] } }, { name: "priorite", type: "number" }, { name: "statut", type: "select", options: { maxSelect: 1, values: ["a_faire","en_cours","fait","annule"] } }, { name: "date_echeance", type: "date" }, { name: "date_rappel", type: "date" }, { name: "is_urgent", type: "bool" } ], listRule: "@request.auth.id != '' && user = @request.auth.id", viewRule: "@request.auth.id != '' && user = @request.auth.id", createRule: "@request.auth.id != ''", updateRule: "@request.auth.id != '' && user = @request.auth.id", deleteRule: "@request.auth.id != '' && user = @request.auth.id" }); app.save(taches); // ── 7. Notes biens ──────────────────────────────────────── const notes = new Collection({ name: "notes_biens", type: "base", fields: [ { name: "user", type: "relation", required: true, options: { collectionId: usersId, maxSelect: 1, cascadeDelete: true } }, { name: "bien", type: "relation", required: true, options: { collectionId: biens.id, maxSelect: 1, cascadeDelete: true } }, { name: "contenu", type: "text", required: true }, { name: "type_note", type: "select", options: { maxSelect: 1, values: ["libre","contact_vendeur","negociation","info_marche"] } } ], listRule: "@request.auth.id != '' && user = @request.auth.id", viewRule: "@request.auth.id != '' && user = @request.auth.id", createRule: "@request.auth.id != ''", updateRule: "@request.auth.id != '' && user = @request.auth.id", deleteRule: "@request.auth.id != '' && user = @request.auth.id" }); app.save(notes); // ── 8. Documents biens ──────────────────────────────────── const documents = new Collection({ name: "documents_biens", type: "base", fields: [ { name: "user", type: "relation", required: true, options: { collectionId: usersId, maxSelect: 1, cascadeDelete: true } }, { name: "bien", type: "relation", required: true, options: { collectionId: biens.id, maxSelect: 1, cascadeDelete: true } }, { name: "nom", type: "text", required: true }, { name: "type_document", type: "select", options: { maxSelect: 1, values: ["compromis","acte","dpe","diagnostics","devis","facture","titre_propriete","autre"] } }, { name: "date_document", type: "date" }, { name: "notes", type: "text" }, { name: "fichier", type: "file", required: true, options: { maxSelect: 1, maxSize: 52428800, mimeTypes: ["application/pdf","image/jpeg","image/png"] } } ], listRule: "@request.auth.id != '' && user = @request.auth.id", viewRule: "@request.auth.id != '' && user = @request.auth.id", createRule: "@request.auth.id != ''", updateRule: "@request.auth.id != '' && user = @request.auth.id", deleteRule: "@request.auth.id != '' && user = @request.auth.id" }); app.save(documents); // ── 9. Devis travaux ────────────────────────────────────── const devis = new Collection({ name: "devis_travaux", type: "base", fields: [ { name: "user", type: "relation", required: true, options: { collectionId: usersId, maxSelect: 1, cascadeDelete: true } }, { name: "bien", type: "relation", required: true, options: { collectionId: biens.id, maxSelect: 1, cascadeDelete: true } }, { name: "contact", type: "relation", options: { collectionId: contacts.id, maxSelect: 1 } }, { name: "lot", type: "text", required: true }, { name: "description", type: "text" }, { name: "montant_ht", type: "number" }, { name: "taux_tva", type: "number" }, { name: "montant_ttc", type: "number" }, { name: "statut", type: "select", options: { maxSelect: 1, values: ["en_attente","refuse","accepte","en_cours","termine","paye"] } }, { name: "date_devis", type: "date" }, { name: "date_debut", type: "date" }, { name: "date_fin_prevu", type: "date" }, { name: "notes", type: "text" }, { name: "fichier_pdf", type: "file", options: { maxSelect: 1, maxSize: 10485760, mimeTypes: ["application/pdf"] } } ], listRule: "@request.auth.id != '' && user = @request.auth.id", viewRule: "@request.auth.id != '' && user = @request.auth.id", createRule: "@request.auth.id != ''", updateRule: "@request.auth.id != '' && user = @request.auth.id", deleteRule: "@request.auth.id != '' && user = @request.auth.id" }); app.save(devis); }, (app) => { for (const name of ["devis_travaux","documents_biens","notes_biens","taches","visites","analyses_financieres","biens","contacts","etapes_pipeline","users"]) { try { app.delete(app.findCollectionByNameOrId(name)); } catch(_) {} } });