Le modèle de données
Créer la base de données de l'app, les trois tables du CRM et le modèle avec les relations que tout le reste de la plateforme va utiliser.
L'app Gestion de Clients existe et elle est vide. Cette étape lui donne ses
fondations : la base de données où vivent les enregistrements, les tables
contas, contactos et oportunidades, et le Modèle qui relie tout — la
carte que les APIs, les écrans et les scripts liront désormais.
À la fin de cette page, vous avez de vraies données : trois tables créées, reliées entre elles, et une console où les requêtes renvoient des lignes.
Deux couches, et il vaut mieux ne pas les confondre
Keplin travaille les données sur deux couches superposées. Elles font des choses différentes et se manipulent à des endroits différents :
| Couche | Ce que c'est | Où on la manipule |
|---|---|---|
| Datasource | La base de données elle-même — la connexion, les tables, les colonnes, les lignes. | Panneau Données ▸ Datasources |
| Modèle | Le portrait de cette base de données dans la plateforme : entités, champs aux noms conviviaux et relations. | L'onglet du datasource, dans le canvas du modèle |
La distinction est pratique. Créer une colonne touche à la base de données. Importer une table dans le modèle ne touche à rien dans la base de données — cela dit seulement à la plateforme « cette table m'intéresse, et voilà comment elle se lit ». C'est le modèle qui alimente l'API GraphQL de l'app, les APIs de table et, à travers elles, les écrans.
Nota
Dans ce guide, la base de données est créée de zéro, à l'intérieur de l'app. Si votre organisation a déjà une base de données avec les clients dedans, le chemin est le même à partir de l'étape « Importer les tables dans le modèle » — enregistrez la connexion et importez les tables qui existent. Le chapitre Connecter des bases de données traite de ce cas.
Créer le datasource Dados CRM
La première chose à faire est d'enregistrer la base de données de l'app. Comme nous n'allons rien connecter d'externe, nous utilisons le type que la plateforme crée et conserve avec l'app elle-même : il ne demande ni serveur, ni port, ni utilisateur, ni mot de passe.
Dans l'espace de travail de l'app, choisissez le panneau Données au bas de la barre latérale.
Dans la section Datasources, cliquez sur le bouton + ( Nouveau datasource). La boîte de dialogue Nouveau datasource s'ouvre — « Connectez une base de données à cette app. Tout est chiffré au repos. »
Dans Nom interne, écrivez
Dados CRM. C'est par ce nom — exactement celui-là — que les APIs et les scripts se référeront à la connexion plus loin dans le guide.Ouvrez la liste Type. Elle montre tous les moteurs pris en charge ; choisissez celui de la base de données locale, celle qui reste stockée avec l'app. Remarquez ce qui se passe ensuite : les champs de serveur, port, utilisateur et mot de passe disparaissent — il n'y a rien à connecter.

La liste des types de base de données dans la boîte de dialogue Nouveau datasource : les six moteurs pris en charge. Il reste un champ, Importer une base de données (facultatif). Laissez-le vide : « Sans fichier, une base de données vide est créée. » C'est ce que nous voulons.
Cliquez sur Tester la connexion pour confirmer — la réponse est Connexion OK.
Cliquez sur Créer. Le datasource apparaît dans l'arborescence et son onglet s'ouvre aussitôt, avec le canvas du modèle — encore vide.

Atenção
Le Nom interne est un identifiant, pas une étiquette. Le changer plus
tard oblige à revoir les scripts qui appellent db("Dados CRM") et les
étapes SQL qui ont choisi la connexion par l'ancien nom.
Créer la table contas
Une fois le datasource créé, les tables se font sans quitter la plateforme.
- Dans l'arborescence, ouvrez le menu ⋯ du datasource Dados CRM et choisissez Nouvelle table.
- Dans Nom de la table, écrivez
contas. Laissez Schéma (facultatif) vide. - Dans Description de la table, écrivez
Empresas clientes e potenciais clientes. C'est facultatif, mais c'est ce que vous relirez dans un an. - La liste Colonnes contient déjà une colonne
id, de typeinteger, avec Clé primaire (PK) et Auto-incrément activés. Laissez-la telle quelle — c'est l'identité de chaque enregistrement. - Cliquez sur le + de Colonnes pour chaque nouvelle colonne et remplissez Nom, Type et les interrupteurs. Le tableau ci-dessous dit quoi écrire.
- Confirmez avec Créer la table. La table naît dans la base de données et apparaît désormais dans l'arborescence des objets.

Les colonnes de la table contas :
| Colonne | Type | Autorise NULL | À quoi elle sert |
|---|---|---|---|
id |
integer |
non | Clé primaire, avec auto-incrément |
nome |
text |
non | Le nom de l'entreprise |
nif |
text |
oui | Numéro fiscal |
sector |
text |
oui | Agroalimentaire, Technologie, Santé… |
cidade |
text |
oui | Où se trouve l'entreprise |
telefone |
text |
oui | Contact général |
email |
text |
oui | Contact général |
estado |
text |
non | ativo, prospeto ou inativo |
Dica
Autorise NULL désactivé veut dire obligatoire dans la base de données. Réservez-le à ce qui est vraiment obligatoire — le nom d'une entreprise, le compte auquel un contact appartient. Un champ aujourd'hui facultatif et demain obligatoire se change en un instant ; l'inverse oblige à nettoyer des données.
Créer les tables contactos et oportunidades
Répétez le geste — menu ⋯ du datasource ▸ Nouvelle table — deux fois de plus.
contactos (description : Pessoas de contacto de cada conta) :
| Colonne | Type | Autorise NULL | À quoi elle sert |
|---|---|---|---|
id |
integer |
non | Clé primaire, avec auto-incrément |
nome |
text |
non | Nom de la personne |
cargo |
text |
oui | Directeur Général, Responsable des Achats… |
email |
text |
oui | |
telefone |
text |
oui | |
conta_id |
integer |
non | Le compte auquel la personne appartient |
oportunidades (description : Negócios em curso, por fase) :
| Colonne | Type | Autorise NULL | À quoi elle sert |
|---|---|---|---|
id |
integer |
non | Clé primaire, avec auto-incrément |
titulo |
text |
non | Le nom de l'affaire |
conta_id |
integer |
non | Le compte de l'affaire |
valor |
real |
oui | Montant en euros — nombre à décimales |
fase |
text |
non | La phase de l'affaire (voir plus bas) |
data_fecho |
text |
oui | Date de clôture prévue, en AAAA-MM-JJ |
responsavel |
text |
oui | Qui suit l'affaire |
La colonne fase est une liste fermée de valeurs. Elle se stocke comme du
texte, et les valeurs possibles sont toujours ces six-là :
| Valeur stockée | Ce qu'elle signifie |
|---|---|
prospecao |
Il n'y a pas encore eu de vraie conversation |
qualificacao |
Il y a de l'intérêt et nous évaluons l'adéquation |
proposta |
Proposition remise |
negociacao |
Discussion des conditions |
fechada_ganha |
Affaire conclue |
fechada_perdida |
Affaire perdue |
Nota
Nous stockons la valeur « technique » (fechada_ganha) et nous affichons le
joli libellé (« Gagnée ») à l'écran. C'est cette séparation qui fait
fonctionner le tableau kanban de l'étape suivante : chaque colonne du
tableau est l'une de ces valeurs, avec son libellé et sa couleur. Les
colonnes estado (des comptes) et fase suivent la même idée.
Revoir et modifier la structure d'une table
Vous vous êtes trompé de type, il manque une colonne, le nom n'est pas le meilleur. Rien de tout cela n'est définitif :
- Dans l'arborescence, ouvrez le menu ⋯ de la table et choisissez Modifier la structure.
- La boîte de dialogue a deux onglets : Colonnes et Index. En haut se trouvent le Nom dans la BD, le Nom convivial (apps) — le nom que les écrans afficheront — et la description.
- Cliquez sur une colonne à gauche pour la modifier à droite, ou utilisez le + pour en ajouter. Les nouvelles colonnes sont marquées « Nouvelle colonne — elle est créée lorsque les modifications sont appliquées. » ; les colonnes supprimées sont « Marquée pour suppression (DROP) lors de l'application. », et la suppression s'annule tant que vous n'avez pas appliqué.
- Cliquez sur Appliquer les modifications.

Atenção
Supprimer une colonne supprime ses données. La plateforme n'exécute la modification que lorsque vous cliquez sur Appliquer les modifications — jusque-là tout est brouillon, et fermer la boîte de dialogue ne casse rien.
Voir et semer les données
L'arborescence des objets a une console sous le modèle, et c'est par elle que l'on jette un œil aux données (ou qu'on les sème) :
- Ouvrez le menu ⋯ d'une table et choisissez Voir les données. La
Console SQL s'ouvre en bas, déjà avec un
selectprêt pour cette table. - Cliquez sur Exécuter. Les résultats apparaissent à droite, avec le nombre de lignes et un champ Filtrer….
- Pour mettre les premières lignes, écrivez les
insertque vous voulez dans la console et exécutez. C'est la façon la plus rapide d'avoir des données d'exemple avant d'avoir des écrans pour les créer.

Importer les tables dans le modèle
Les tables existent, mais la plateforme ne sait pas encore qu'elle veut les utiliser. C'est ce que fait l'import :
- Dans l'arborescence, dépliez Dados CRM ▸ Tables. Les trois sont là.
- Pour chacune, ouvrez le menu ⋯ et choisissez Importer au modèle — ou faites glisser la table de l'arborescence vers le canvas du modèle, ce qui revient au même.
- Chaque table devient une carte sur le canvas : l'entité. La carte montre les champs, le type de chacun et la marque PK sur la clé primaire.

Les noms des entités prennent une majuscule initiale — contas devient
Contas — parce que c'est ainsi qu'ils apparaissent dans les APIs et dans
les écrans. La table dans la base de données continue de s'appeler contas.
Nota
Importer ne copie pas de données et ne crée rien dans la base de données. Et retirer une entité du modèle ne supprime pas non plus la table — « NE modifie PAS la table dans la base de données », comme le dit l'avertissement lui-même.
Relier les entités — les deux relations
Un CRM sans relations, ce sont trois listes détachées. Il manque deux liaisons : chaque contact appartient à un compte, chaque opportunité appartient à un compte.
Pour créer une relation, faites glisser le champ conta_id de l'entité
Contactos vers le champ id de l'entité Contas — l'astuce sur la
carte le rappelle : « Glissez vers un champ d'une autre table pour lier ».
La boîte de dialogue Nouvelle relation s'ouvre, déjà avec les entités et
les colonnes remplies :
| Champ | Quoi choisir | Pourquoi |
|---|---|---|
| Cardinalité | Un-à-plusieurs (1:N) | Un compte a beaucoup de contacts ; chaque contact a un compte. |
| Parent (référencée) | Contas ▸ id |
Le côté « un ». |
| Child (porte la FK) | Contactos ▸ conta_id |
Le côté « plusieurs » — c'est lui qui garde la référence. |
| Type de relation | Physique — crée la FK dans la base de données | La base de données garantit désormais qu'il n'y a pas de contacts orphelins. |
| Navigator sur Contactos → Contas | conta |
Le champ virtuel qui, à partir d'un contact, donne son compte. |
| Navigator sur Contas → Contactos | contactos |
Le champ virtuel qui, à partir d'un compte, donne ses contacts. |
| À la suppression du parent (ON DELETE) | Rien (bloque s'il y a des enfants) | Supprimer un compte qui a des contacts devient refusé — mieux vaut une erreur qu'un trou. |
Confirmez avec Créer la relation et répétez le geste entre
Oportunidades ▸ conta_id et Contas ▸ id, avec le navigator inverse
oportunidades.

Les Navigators sont la partie la plus rentable. Ce sont des champs qui
n'existent pas dans la base de données mais qui existent dans le modèle : avec
eux, une requête d'opportunités renvoie conta.nome sans que personne
n'écrive de join. C'est exactement ce que la table du tableau de bord va
faire à l'étape suivante, dans la colonne Conta.
Dica
Physique crée vraiment la clé étrangère dans la base de données ; Virtuelle — uniquement dans le modèle de la plateforme sert pour les bases de données où vous ne pouvez pas (ou ne voulez pas) toucher au schéma. Dans ce guide la base est la nôtre, donc physique.
Ce qui vient d'être débloqué
Le modèle prêt, l'app a gagné des choses gratuitement :
- L'API GraphQL de l'app connaît déjà Contas, Contactos et Oportunidades, avec les relations — voir L'API GraphQL du modèle.
- Les APIs de table peuvent maintenant pointer vers une entité et générer la lecture et l'écriture sans une ligne de SQL. C'est le premier pas de l'étape suivante.
- Les écrans liront ces APIs à travers des datastores.
Pourquoi pas… ?
- Pourquoi ma table n'apparaît-elle pas dans l'arborescence ? L'arborescence des objets est lue depuis la base de données — utilisez Actualiser les objets dans le menu ⋯ du datasource après avoir bougé quelque chose en dehors de la plateforme.
- Pourquoi n'arrivé-je pas à créer la relation ? Les deux colonnes doivent
être compatibles : une clé primaire
integerse relie à uninteger. Si vous avez glissé sur le mauvais champ, annulez et recommencez — la boîte de dialogue dit qu'il manque de choisir les colonnes. - Pourquoi le champ
contan'apparaît-il pas dans mes données ? Les navigators ne sont pas des colonnes : ils n'existent qu'à travers le modèle. Si vous interrogez par la Console SQL, vous voyez les colonnes réelles ; c'est dans les APIs et dans les écrans que les navigators apparaissent. - Pourquoi la plateforme ne me laisse-t-elle pas supprimer un compte ? Vous avez choisi Rien (bloque s'il y a des enfants) dans le ON DELETE — et il y a des contacts ou des opportunités qui pointent vers lui. Supprimez-les d'abord, ou changez la règle de la relation.
Les fondations sont posées. Prochaine étape : les écrans.