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 deAddressDto: 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.Dataest 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. SchemaCapabilitiespermet 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.csDatabaseSource.csLegacyEntityReference.csSchemaCapabilities.csCanonicalMappingResult.cs
Omika.Core/Domain/Common
EntityBase.cs
Omika.Core/Domain/ValueObjects
ReferenceValue.csDateTimeRange.csPostalAddress.csContactDetails.csExternalReference.cs
Omika.Core/Domain/Exceptions
DomainException.csDomainValidationException.cs
Omika.Core/Domain/Entities
Clients/Client.cs,Adresse.cs,Contact.cs,Site.csOrganisation/Societe.cs,Collaborateur.cs,Equipe.cs,Utilisateur.csInterventions/Dossier.cs,Intervention.cs,ActionIntervention.cs,CompteRendu.cs,EtatIntervention.cs,Checklist.cs,ChecklistItem.csPlanning/RendezVous.cs,AffectationCollaborateur.cs,ParticipantRendezVous.cs,AnnulationRendezVous.cs,SuiviTemps.csDocuments/Document.cs,NoteDocument.cs,MessageInterne.cs,MessageExterne.cs,ModeleMail.cs,ModeleRapport.csSecurity/Role.cs,Permission.cs,DroitAcces.csConfiguration/ParametreMetier.cs,ParametreApplication.cs,PreferenceUtilisateur.cs
Omika.Core/Contracts/Common
ApiErrorDto.cs,ApiResult.cs,PagedRequest.cs,PagedResult.csReferenceValueDto.cs,AddressDto.cs,ContactDetailsDto.cs
Omika.Core/Contracts/Clients
ClientSummaryDto.cs,ClientDetailsDto.csCreateClientRequest.cs,UpdateClientRequest.cs,SearchClientsRequest.csAdresseDto.cs,ContactDto.cs,SiteDto.cs
Omika.Core/Contracts/Organisation
CollaborateurSummaryDto.cs,CollaborateurDetailsDto.csEquipeDto.cs,SocieteDto.cs,UtilisateurDto.cs
Omika.Core/Contracts/Interventions
DossierSummaryDto.cs,DossierDetailsDto.csInterventionSummaryDto.cs,InterventionDetailsDto.csCreateInterventionRequest.cs,UpdateInterventionRequest.cs,SearchInterventionsRequest.csActionInterventionDto.cs,CompteRenduDto.cs,EtatInterventionDto.cs
Omika.Core/Contracts/Planning
RendezVousSummaryDto.cs,RendezVousDetailsDto.csCreateRendezVousRequest.cs,UpdateRendezVousRequest.cs,SearchRendezVousRequest.csAffectationCollaborateurDto.cs,ParticipantRendezVousDto.cs,AnnulationRendezVousDto.cs,SuiviTempsDto.cs,CreateSuiviTempsRequest.cs
Omika.Core/Contracts/Documents
DocumentSummaryDto.cs,DocumentDetailsDto.cs,CreateDocumentRequest.csModeleMailDto.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
- Identifiants publics : chaînes temporaires (GUID / legacy / clé métier). Un helper dédié ou un type valeur « PublicId » reste possible.
- États et statuts : conservés en
ReferenceValue. À confirmer si certains deviendront des enums stables. DateTimevsDateTimeOffset: pas de gestion multi-fuseaux documentée pour l'instant ;DateTimeest utilisé partout. À revoir si le mobile doit synchroniser sur plusieurs fuseaux.- Collections dans les entités :
List<T>privées avec méthodesAdd*. À confirmer si des collections doivent devenir remplaçables (remplacement complet lors d'une mise à jour). - Contrat de recherche :
SearchClientsRequesthérite dePagedRequestavec des propriétés additionnelles. Les filtres seront consolidés lors de l'implémentation des services. - Sécurité :
LoginRequestaccepte 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. - 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.