Files
Omika/docs/niveau-3-modele-canonique.md
2026-10-23 18:46:50 +02:00

12 KiB

Niveau 3 — Modèle métier canonique et contrats API

Rôle des dossiers de Omika.Core

Domain/

Le domaine contient les entités métier canoniques, indépendantes du stockage.

Elles correspondent aux concepts fonctionnels de l'application :

  • Client, Adresse, Contact, Site ;
  • Societe, Collaborateur, Equipe, Utilisateur ;
  • Dossier, Intervention, ActionIntervention, CompteRendu, Checklist ;
  • RendezVous et ses éléments associés ;
  • Document et modèles de courrier/rapport ;
  • Role, Permission, DroitAcces ;
  • ParametreMetier, ParametreApplication, PreferenceUtilisateur.

Elles ne portent :

  • aucun attribut HFSQL ;
  • aucun préfixe de rubrique physique (CL_, IN_, PL_, RDV_…) ;
  • aucun champ zombie.

Les objets de valeur (ValueObjects/) représentent des valeurs sans identité :

  • ReferenceValue (valeur de référentiel configurable) ;
  • DateTimeRange (plage horaire validée) ;
  • PostalAddress, ContactDetails ;
  • ExternalReference (référence vers Batigest / base externe).

Les exceptions (Exceptions/) portent les erreurs de validation du domaine.

Contracts/

Les contrats sont utilisés entre Omika.Api et Omika.App.

Ce sont des DTO purs :

  • résumés de liste ;
  • détails ;
  • requêtes de création / modification / recherche ;
  • DTO communs (pagination, enveloppe d'erreur, référence, adresse, coordonnées).

Distinction AddressDto / AdresseDto :

  • AddressDto (Contracts/Common) : adresse postale simple, sans identité (libellé, lignes, code postal, ville, pays). Réutilisée partout où une adresse postale brute est nécessaire.
  • AdresseDto (Contracts/Clients) : adresse d'une entité du domaine Clients, avec identifiant, type, indicateurs (« principale », « archivée ») et une adresse postale optionnelle (AdressePostale). Il ne s'agit pas d'un doublon de AddressDto : l'un est une valeur, l'autre un conteneur d'entité.

Ils ne contiennent :

  • aucun attribut HFSQL ;
  • aucune propriété à préfixe physique ;
  • aucune dépendance vers Omika.Data ;
  • aucun champ zombie ;
  • aucun mot de passe ni objet de connexion ;
  • aucun graphe cyclique.

Compatibility/

Les types de compatibilité conservent la provenance des données sans exposer la structure physique :

  • DatabaseSchemaVersion (Unknown / Batik / Omika) ;
  • DatabaseSource (version + nom logique de base) ;
  • LegacyEntityReference (référence vers l'enregistrement d'origine) ;
  • SchemaCapabilities (capacités déclarées d'un schéma) ;
  • CanonicalMappingResult<T> (résultat d'un mapping physique → canonique).

Interfaces/, Abstractions/, Constants/, Runtime/, Mapping/

  • Interfaces/ : services métier (voir ci-dessous).
  • Abstractions/ : abstractions techniques existantes, non touchées.
  • Constants/ : constantes existantes.
  • Runtime/ : contexte d'exécution existant, non touché.
  • Mapping/ : mappers purs entité métier → DTO.

Différence entre une entité métier et un modèle physique

Modèle physique (Omika.Data) Entité métier (Omika.Core.Domain)
Correspond aux tables HFSQL (Document.fic, Planning_RDV…) Correspond aux concepts fonctionnels (Document, RendezVous…)
Porte des rubriques préfixées (DC_Categorie, PL_PKID…) Porte des propriétés métier nommées sans préfixe
Marque les rubriques zombie Ne contient jamais de champ zombie
Connaît les clés internes et la version physique Connaît uniquement les identifiants canoniques et la provenance

La chaîne attendue :

Modèle physique Batik (Isis_BO)          Modèle physique Omika
            |                                      |
            +----------> Modèle métier canonique <-+
                                |
                                v
                          Contrat API
                                |
                                v
                        Application Avalonia

Le mapping physique → métier reste dans Omika.Data. Le mapping métier → DTO est dans Omika.Core/Mapping.

Différence entre une entité métier et un DTO

Entité métier DTO (contrat)
Évolue dans le temps (classe) Immutable par convention (record avec propriétés init)
Expose des collections contrôlées (Add*) Expose des listes IReadOnlyList<T> en lecture seule
Peut contenir des objets de valeur du domaine Ne contient que des DTO ou types primitifs
Vit dans Domain/ Vit dans Contracts/
N'est jamais sérialisé tel quel Est la frontière de l'API

Stratégie des identifiants

Les identifiants publics des contrats sont des chaînes afin de permettre temporairement :

  • le GUID Omika ;
  • l'identifiant historique Batik (Isis_BO) ;
  • une clé métier.

Le domaine utilise Guid Id (identifiant canonique) plus LegacyEntityReference? SourceReference pour conserver la référence d'origine sans exposer la clé physique.

LegacyEntityReference.PublicIdentifier fournit une représentation publique stable (GUID → clé métier → identifiant numérique → GUID physique → ImportId).

Un helper de représentation publique des identifiants peut être ajouté plus tard si le besoin se fait sentir côté API/mobile.

Stratégie des paramètres métier

Les paramètres métier (type de client, statut, type d'activité, priorité…) sont représentés par ReferenceValue :

  • Key : clé métier stable (nouveau schéma Omika) ;
  • LegacyId : identifiant historique (ancien schéma Batik) ;
  • Code : code court éventuel ;
  • Label : libellé d'affichage.

Ils ne sont pas transformés automatiquement en enum : ils restent configurables. Le passage en enum n'est envisagé que si un paramètre devient vraiment stable et fermé.

Stratégie des champs zombie

Les rubriques physiques obsolètes (anciens identifiants de civilité, de statut, clés internes…) sont marquées zombie dans les modèles physiques de Omika.Data.

Dans Omika.Core :

  • elles n'apparaissent jamais comme propriétés publiques ;
  • le mapper de Omika.Data est responsable de convertir les valeurs en propriétés métier (ReferenceValue, libellés, etc.) ;
  • les tests d'architecture interdisent leur apparition dans les contrats.

Stratégie de compatibilité Batik (Isis_BO) / Omika

  • Le domaine est unique pour les deux bases.
  • La provenance est conservée via LegacyEntityReference / DatabaseSource.
  • SchemaCapabilities permet de savoir, sans connaître la structure physique, si une fonctionnalité est disponible dans la version source (clés métier, GUID, rôles, nouveau modèle de rendez-vous…).
  • CanonicalMappingResult<T> permet à un mapper physique → canonique de retourner la valeur plus les warnings, champs ignorés et erreurs non bloquantes.

Cas particulier des rendez-vous

Un agrégat métier unique RendezVous reçoit les données des deux versions :

  • ancien modèle : Planning_RDV, Planning_RDV_Personne ;
  • nouveau modèle : RDV_Planning, RDV_Collaborateur, RDV_Contact.

L'entité porte :

  • une DateTimeRange Periode ;
  • des AffectationCollaborateur (responsable, période particulière, statut, temps validé) ;
  • des ParticipantRendezVous (contact, coordonnées, type, présence confirmée) ;
  • une AnnulationRendezVous éventuelle ;
  • des liens optionnels vers Client / Site / Dossier / Intervention.

Toute information absente dans une version est nullable.

Le contrat RendezVousDetailsDto est identique pour les deux versions et ne contient aucune notion de Planning_RDV, RDV_Planning, PL_PKID, RDP_GUID ou autre nom physique.

Liste des fichiers créés

Omika.Core/Compatibility

  • DatabaseSchemaVersion.cs
  • DatabaseSource.cs
  • LegacyEntityReference.cs
  • SchemaCapabilities.cs
  • CanonicalMappingResult.cs

Omika.Core/Domain/Common

  • EntityBase.cs

Omika.Core/Domain/ValueObjects

  • ReferenceValue.cs
  • DateTimeRange.cs
  • PostalAddress.cs
  • ContactDetails.cs
  • ExternalReference.cs

Omika.Core/Domain/Exceptions

  • DomainException.cs
  • DomainValidationException.cs

Omika.Core/Domain/Entities

  • Clients/Client.cs, Adresse.cs, Contact.cs, Site.cs
  • Organisation/Societe.cs, Collaborateur.cs, Equipe.cs, Utilisateur.cs
  • Interventions/Dossier.cs, Intervention.cs, ActionIntervention.cs, CompteRendu.cs, EtatIntervention.cs, Checklist.cs, ChecklistItem.cs
  • Planning/RendezVous.cs, AffectationCollaborateur.cs, ParticipantRendezVous.cs, AnnulationRendezVous.cs, SuiviTemps.cs
  • Documents/Document.cs, NoteDocument.cs, MessageInterne.cs, MessageExterne.cs, ModeleMail.cs, ModeleRapport.cs
  • Security/Role.cs, Permission.cs, DroitAcces.cs
  • Configuration/ParametreMetier.cs, ParametreApplication.cs, PreferenceUtilisateur.cs

Omika.Core/Contracts/Common

  • ApiErrorDto.cs, ApiResult.cs, PagedRequest.cs, PagedResult.cs
  • ReferenceValueDto.cs, AddressDto.cs, ContactDetailsDto.cs

Omika.Core/Contracts/Clients

  • ClientSummaryDto.cs, ClientDetailsDto.cs
  • CreateClientRequest.cs, UpdateClientRequest.cs, SearchClientsRequest.cs
  • AdresseDto.cs, ContactDto.cs, SiteDto.cs

Omika.Core/Contracts/Organisation

  • CollaborateurSummaryDto.cs, CollaborateurDetailsDto.cs
  • EquipeDto.cs, SocieteDto.cs, UtilisateurDto.cs

Omika.Core/Contracts/Interventions

  • DossierSummaryDto.cs, DossierDetailsDto.cs
  • InterventionSummaryDto.cs, InterventionDetailsDto.cs
  • CreateInterventionRequest.cs, UpdateInterventionRequest.cs, SearchInterventionsRequest.cs
  • ActionInterventionDto.cs, CompteRenduDto.cs, EtatInterventionDto.cs

Omika.Core/Contracts/Planning

  • RendezVousSummaryDto.cs, RendezVousDetailsDto.cs
  • CreateRendezVousRequest.cs, UpdateRendezVousRequest.cs, SearchRendezVousRequest.cs
  • AffectationCollaborateurDto.cs, ParticipantRendezVousDto.cs, AnnulationRendezVousDto.cs, SuiviTempsDto.cs, CreateSuiviTempsRequest.cs

Omika.Core/Contracts/Documents

  • DocumentSummaryDto.cs, DocumentDetailsDto.cs, CreateDocumentRequest.cs
  • ModeleMailDto.cs, ModeleRapportDto.cs

Omika.Core/Contracts/Security

  • LoginRequest.cs, CurrentUserDto.cs, RoleDto.cs, PermissionDto.cs

Omika.Core/Contracts/Configuration

  • ParametreMetierDto.cs, ApplicationConfigurationDto.cs, PreferenceUtilisateurDto.cs

Omika.Core/Interfaces

  • IClientService.cs, IInterventionService.cs, IRendezVousService.cs, IDocumentService.cs, IReferenceDataService.cs, ICurrentUserService.cs

Omika.Core/Mapping

  • ClientContractMapper.cs, InterventionContractMapper.cs, RendezVousContractMapper.cs, DocumentContractMapper.cs

Omika.Tests

  • Architecture : CoreMustNotReferenceDataTests, CoreMustNotReferenceAvaloniaTests, CoreMustNotReferenceAspNetCoreTests, PublicContractsMustNotContainHfSqlNamesTests, PublicContractsMustNotContainZombieFieldsTests
  • Contrats : PagedResultTests, ClientContractTests, InterventionContractTests, RendezVousContractTests
  • Domaine : DateTimeRangeTests, ClientDomainTests, InterventionDomainTests, RendezVousDomainTests, RendezVousCrossSchemaTests
  • Compatibilité : LegacyEntityReferenceTests, SchemaCapabilitiesTests

Décisions encore à valider

  1. Identifiants publics : chaînes temporaires (GUID / legacy / clé métier). Un helper dédié ou un type valeur « PublicId » reste possible.
  2. États et statuts : conservés en ReferenceValue. À confirmer si certains deviendront des enums stables.
  3. DateTime vs DateTimeOffset : pas de gestion multi-fuseaux documentée pour l'instant ; DateTime est utilisé partout. À revoir si le mobile doit synchroniser sur plusieurs fuseaux.
  4. Collections dans les entités : List<T> privées avec méthodes Add*. À confirmer si des collections doivent devenir remplaçables (remplacement complet lors d'une mise à jour).
  5. Contrat de recherche : SearchClientsRequest hérite de PagedRequest avec des propriétés additionnelles. Les filtres seront consolidés lors de l'implémentation des services.
  6. Sécurité : LoginRequest accepte un mot de passe temporaire, mais aucun service d'authentification n'est implémenté à ce niveau. Le stockage des identifiants (hash, salt) sera décidé au niveau supérieur.
  7. Fichiers physiques des documents : les contrats exposent des identifiants logiques et des métadonnées ; la gestion du téléversement/téléchargement sera définie avec l'API.