Premiere commit - Omika
This commit is contained in:
@@ -0,0 +1,318 @@
|
||||
# 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 :
|
||||
|
||||
```powershell
|
||||
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
|
||||
|
||||
```powershell
|
||||
# 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).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user