Files
Omika/docs/architecture-solution.md
T
2026-10-23 18:46:50 +02:00

17 KiB

Architecture de la solution Omika

Ce document décrit la structure initiale de la solution .NET Omika, son organisation en projets, les dépendances entre eux, et les conventions retenues pour la suite (migration HFSQL, application mobile, API, futur Windows).

Portée : phase d'architecture. Les modèles métier détaillés et la connexion HFSQL réelle ne sont pas encore développés (voir les sections dédiées).


1. Vue d'ensemble

┌────────────────────────────────────────────────────────────┐
│                        Omika.App                           │
│   Application Avalonia (code partagé UI / ViewModels)      │
│   Cibles : Android · iOS · Windows (desktop)               │
└───────────────┬─────────────────────────────┬──────────────┘
                │                             │
                ▼                             ▼
        Omika.App.Desktop              Omika.App.Android
        Omika.App.iOS                  (hôtes plateformes)
        (hôtes plateformes)
                │
                │  ProjectReference
                ▼
┌─────────────────────────────────────────────┐        ┌──────────────────────────────┐
│                 Omika.Core                  │        │           Omika.Api          │
│  Modèles · Interfaces · Constantes ·        │◄───────│      API ASP.NET Core        │
│  Logique métier (indépendant UI/API)        │        │  Endpoints / DI / OpenAPI    │
└──────────────────┬──────────────────────────┘        └──────────────┬───────────────┘
                   │ ProjectReference                                │ ProjectReference
                   ▼                                                 ▼
┌─────────────────────────────────────────────┐        ┌──────────────────────────────┐
│                 Omika.Data                  │        │          Omika.Tests         │
│  Connexion HFSQL · Repositories · Mapping   │        │  Tests unitaires (xUnit)     │
│  Migration Batik/OMIKA                      │        └──────────────────────────────┘
└─────────────────────────────────────────────┘

2. Projets créés

Projet Type Rôle
Omika.App Bibliothèque Avalonia (net10.0) Code UI partagé (Views, ViewModels, Services). Cible commune aux hôtes Android / iOS / Windows.
Omika.App.Desktop Exécutable Avalonia (net10.0) Hôte desktop Windows/Linux/macOS. Point d'entrée pour le futur client Windows.
Omika.App.Android Exécutable Avalonia (net10.0-android) Hôte Android (APK/AAB).
Omika.App.iOS Exécutable Avalonia (net10.0-ios) Hôte iOS (simulateur/appareil). La compilation d'un .app pour iOS exige macOS + Xcode.
Omika.Api API ASP.NET Core (net10.0) Expose les fonctionnalités métier et données via HTTP + OpenAPI.
Omika.Core Bibliothèque (net10.0) Modèles communs, interfaces, constantes, types partagés, logique métier. Aucune dépendance UI/API.
Omika.Data Bibliothèque (net10.0) Accès aux données HFSQL : options de connexion, contrats, repositories, mapping de tables, migration Batik/OMIKA.
Omika.Tests xUnit (net10.0) Tests unitaires des éléments critiques (Result, validation HFSQL, mapping de tables).

3. Dépendances entre projets

Omika.App.Desktop ──► Omika.App ──► Omika.Core
Omika.App.Android ──► Omika.App ──► Omika.Core
Omika.App.iOS     ──► Omika.App ──► Omika.Core

Omika.Api          ──► Omika.Core
                    ──► Omika.Data

Omika.Data         ──► Omika.Core

Omika.Tests        ──► Omika.Core
                    ──► Omika.Data
  • Omika.Core n'a aucune dépendance : c'est le noyau partagé.
  • Omika.Data dépend de Omika.Core (interfaces, constantes, types).
  • Omika.Api dépend de Omika.Core et Omika.Data.
  • Omika.App et ses hôtes dépendent de Omika.Core (les appels à l'API se feront via HTTP, pas par référence directe au projet Data).
  • Omika.Tests référence Omika.Core et Omika.Data.

4. Gestion des packages

Le fichier racine Directory.Packages.props active la gestion centralisée des packages (CPM). Toutes les versions NuGet y sont déclarées une seule fois ; les fichiers .csproj référencent les packages sans version.

Groupe Package
Avalonia Avalonia, Avalonia.Themes.Fluent, Avalonia.Fonts.Inter, Avalonia.Desktop, Avalonia.Android, Avalonia.iOS
Diagnostique AvaloniaUI.DiagnosticsSupport
Android Xamarin.AndroidX.Core.SplashScreen
MVVM CommunityToolkit.Mvvm
API Microsoft.AspNetCore.OpenApi
Configuration Microsoft.Extensions.Options.ConfigurationExtensions
Tests xunit, xunit.runner.visualstudio, Microsoft.NET.Test.Sdk, coverlet.collector

5. Structure des dossiers

Omika.slnx                     → solution (format .slnx)
Directory.Packages.props       → versions centralisées des packages NuGet
docs/architecture-solution.md  → ce document
docs/schema-compatibilite-batik-omika.json
                               → dictionnaire machine-readable du schéma (tables, rubriques, liens)
analyse-sources.md             → analyse WINDEV existante
BATIK.md / OMIKA.md            → documentation historique
tools/generate_models.py       → générateur des modèles physiques HFSQL (Batik/Omika)
src/
   Omika.Core/
     Constants/       → constantes applicatives et base de données
     Interfaces/      → contrats (IRepository, IUnitOfWork)
     Abstractions/    → types partagés (Result)
     Runtime/         → version active de la base (BATIK/OMIKA), contexte global
     Models/          → (vide pour l'instant) futurs modèles métier
  Omika.Data/
    Configuration/    → HfsqlOptions + validation
    Connection/       → contrats et squelette de connexion HFSQL
    Repositories/     → base commune des repositories
    Mapping/          → référentiel de tables + mapping Batik/OMIKA
    HfSql/Metadata/   → attributs de mapping HFSQL (Table, Column, PrimaryKey, CompositeKey, LegacyField)
    HfSql/Models/     → modèles physiques générés (Batik/ et Omika/) — 106 classes
    Migrations/       → service de migration Batik → OMIKA
  Omika.Api/
    Endpoints/        → endpoints HTTP (santé, futur métier)
  Omika.App/
    Views/            → MainWindow (desktop) et MainView (partagé)
    ViewModels/       → MainViewModel, ViewModelBase
  Omika.App.Desktop/
  Omika.App.Android/
  Omika.App.iOS/
tests/
  Omika.Tests/        → tests xUnit (47 tests)

6. Conventions et règles

  1. Séparation des responsabilités : l'UI (App) et l'API ne contiennent aucune logique métier ; celle-ci vit dans Omika.Core.
  2. Accès aux données : uniquement via Omika.Data, derrière les interfaces IRepository<TEntity,TId> et IUnitOfWork définies dans Omika.Core.
  3. Pas de dépendance directe App → Data : l'application mobile consommera l'API (HTTP). Si un accès direct est nécessaire (hors ligne), il passera par une façade dédiée à ajouter ultérieurement.
  4. Configuration : les options de connexion HFSQL sont typées (HfsqlOptions, section "Hfsql"), validées avant usage, et remplaçables par la configuration .NET standard (appsettings / user-secrets / variables d'environnement).
  5. Résultats d'opération : les services renvoient Result / Result<T> (Omika.Core) plutôt que de lever des exceptions pour les cas métier.

7. État de la couche HFSQL (phase d'architecture)

À ce stade, aucune connexion HFSQL réelle n'est ouverte. La couche fournit :

  • HfsqlOptions et HfsqlOptionsValidator : préparation et validation des paramètres (serveur, port 4900, base, groupes de protection ProtectionStd / ProtectionPlus, comptes techniques) ;
  • IHfsqlConnection / HfsqlConnection : contrat + implémentation squelette (OpenAsync lève volontairement NotImplementedException) ;
  • RepositoryBase<TEntity,TId> : base commune prête à câbler le provider HFSQL ;
  • LegacyTableMap : référentiel des 58 tables OMIKA et des tables de l'ancienne version (48 tables, e.g. Intervention_Collaborateur supprimée) ;
  • TableAttribute : association future entité → table HFSQL ;
  • IMigrationService / MigrationService : contrat de compatibilité Batik → OMIKA (conversion de clés numériques vers textuelles, suivi ElementModifie / ElementSupprime), non implémenté.

7.1 Modèles physiques générés (Batik / Omika)

Le dictionnaire machine-readable docs/schema-compatibilite-batik-omika.json décrit le schéma WINDEV (tables, rubriques, types HFSQL, liens, marquage zombie). Le générateur tools/generate_models.py produit à partir de ce fichier les 106 modèles physiques dans Omika.Data/HfSql/Models :

Dossier Contenu
HfSql/Models/Batik/ Modèles physiques de l'ancienne base (Isis_BO, 48 tables)
HfSql/Models/Omika/ Modèles physiques de la nouvelle base (OMIKA, 58 tables)

Chaque classe XxxRow porte les attributs de mapping suivants :

  • [HfSqlTable] : nom de la table, nom du fichier disque (.fic), groupes de protection, versions de schéma concernées (Batik et/ou Omika) ;
  • [HfSqlColumn] : nom physique de la rubrique, type HFSQL, longueur, valeur par défaut, marquage « zombie » ou « Omika uniquement » ;
  • [HfSqlPrimaryKey] / [HfSqlCompositeKey] : clé primaire (automatique ou composée) ;
  • [HfSqlLegacyField] : rubrique historique à migrer, avec éventuellement la rubrique de remplacement (ReplacementColumn).

Ces modèles sont purement descriptifs (attributs) : aucune requête n'est exécutée. Ils constituent le socle du futur provider HFSQL et du mapping table → entité.

Pour régénérer les modèles après modification du dictionnaire :

python .\tools\generate_models.py

Prochaine étape HFSQL : choisir et brancher le provider HFSQL (.NET), puis définir les entités du domaine en s'appuyant sur ces modèles physiques.

8. Sélection de base (BATIK / OMIKA)

Le mécanisme de sélection de la base est centralisé dans Omika.Core.Runtime et Omika.Core.Compatibility, en distinguant deux notions :

  • DatabaseSchemaSelection (Omika.Core.Runtime) — enum de la sélection demandée par la configuration :
    • Auto (0) : détection automatique de la base réelle (valeur par défaut sûre) ;
    • Batik (1) : forcer l'ancienne base ;
    • Omika (2) : forcer la nouvelle base.
  • DatabaseSchemaVersion (Omika.Core.Compatibility) — enum de la provenance / version réellement détectée d'une donnée :
    • Unknown (0) : état non déterminé ;
    • Batik (1) : ancienne version ;
    • Omika (2) : nouvelle version. Ce type ne doit pas être confondu avec DatabaseSchemaSelection : l'un décrit la sélection demandée au démarrage (configuration), l'autre la version réellement détectée du schéma dont provient une donnée.
  • DatabaseSchemaSelectionParser — analyse une chaîne de configuration (« Auto », « Batik » ou « Omika », insensible à la casse et aux espaces). Il retourne un Result<DatabaseSchemaSelection> et refuse toute valeur inconnue avec un message d'erreur explicite.
  • ApplicationRuntimeContext — contexte global de l'application :
    • ConfigurationKey : clé conventionnelle "Omika:DatabaseVersion" ;
    • Configure(...) : définit la sélection demandée au démarrage (accepte l'enum ou une chaîne de configuration) ;
    • SetDetectedVersion(...) : fournit la version réellement détectée (Batik / Omika) et la valide contre la sélection demandée ;
    • ValidateDetectedVersion(...) : valide une version détectée sans modifier le contexte global ;
    • Current : accès au contexte actif (propriétés Selection, DetectedVersion, IsBatik, IsOmika) ;
    • FromConfiguration(...) : crée un contexte isolé sans toucher au global (utile pour les tests et les traitements par lot) ;
    • Reset() : réinitialise le contexte global.

Sélection demandée ≠ version active

Une valeur de configuration n'est jamais présentée comme version réellement active : seule la base détectée et validée (DetectedVersion) détermine la base utilisée. Tant que SetDetectedVersion n'a pas été appelé, la version détectée reste Unknown, même si une sélection forcée (Batik / Omika) est configurée.

Comment changer la sélection demandée ?

Méthode Exemple
Fichier de configuration (recommandé pour l'API) Modifier la clé "Omika:DatabaseVersion" dans appsettings.json (valeur "Auto", "Batik" ou "Omika")
Variable d'environnement Omika__DatabaseVersion=Batik (la convention .NET __ est lue automatiquement)
Au démarrage du code ApplicationRuntimeContext.Configure(DatabaseSchemaSelection.Batik) ou Configure("Auto")

Une valeur inconnue lève une erreur explicite au démarrage. En mode Auto, toute version réelle détectée (Batik ou Omika) est acceptée. En mode forcé, la version détectée doit correspondre à la sélection demandée ; dans le cas contraire, SetDetectedVersion retourne un échec explicite et aucune version active n'est affirmée (la version détectée reste Unknown).

9. État des modèles métier

Les modèles physiques HFSQL (rubriques brutes du schéma WINDEV) vivent dans Omika.Data/HfSql/Models (voir § 7.1). Omika.Core/Models, qui accueillera les entités du domaine, est volontairement vide. La prochaine phase devra :

  1. s'appuyer sur l'inventaire machine-readable du schéma (déjà produit) et sur les modèles physiques pour définir les entités du domaine (Client, Dossier, Intervention, RDV, …) ;
  2. distinguer les propriétés utiles au domaine des rubriques « zombie » (conservées pour la lecture d'une base existante, à ne pas utiliser comme référence dans le nouveau domaine) ;
  3. définir les DTO exposés par l'API et consommés par l'application.

10. Commandes utiles

# Restaurer les packages
dotnet restore .\Omika.slnx

# Compiler toute la solution (hôtes desktop + API + bibliothèques + tests)
dotnet build .\Omika.slnx

# Compiler uniquement l'API
dotnet build .\src\Omika.Api\Omika.Api.csproj

# Compiler le client desktop (Windows)
dotnet build .\src\Omika.App.Desktop\Omika.App.Desktop.csproj

# Compiler l'hôte Android (APK)
dotnet build .\src\Omika.App.Android\Omika.App.Android.csproj

# Compiler l'hôte iOS (simulateur) — nécessite macOS + Xcode
dotnet build .\src\Omika.App.iOS\Omika.App.iOS.csproj

# Lancer les tests unitaires
dotnet test .\tests\Omika.Tests\Omika.Tests.csproj

# Lancer l'API en développement
dotnet run --project .\src\Omika.Api\Omika.Api.csproj
# → http://localhost:5xxx/health (état de la solution)

# Lancer le client desktop
dotnet run --project .\src\Omika.App.Desktop\Omika.App.Desktop.csproj

11. Prochaines étapes

  • Choisir et intégrer le provider HFSQL (.NET) dans Omika.Data.
  • Enrichir le dictionnaire docs/schema-compatibilite-batik-omika.json (liens, règles de migration) et régénérer les modèles physiques.
  • Définir les entités métier dans Omika.Core/Models.
  • Implémenter les endpoints métier de Omika.Api.
  • Brancher l'application Avalonia sur l'API (client HTTP) et préparer la navigation mobile.
  • Ajouter un projet Omika.App.Windows si un client Windows dédié est requis (le desktop actuel en tient déjà lieu).