Files
SchotzIAD/backend/SchotzIadKmTracker.Api/Data/AppDbContext.cs
T
MadJax 0e6a97ca61 Renommage : TrajetKmTracker -> SchotzIadKmTracker (backend, specs, frontend)
- Backend : projets, solution, namespaces et références
  TrajetKmTracker.Api/.Tests -> SchotzIadKmTracker.Api/.Tests
  (dossiers, .csproj, .sln, .http, namespaces C#). GUID UserSecretsId préservé.
- Specs : dossier .kiro/specs/trajet-km-tracker -> schotziad-km-tracker
  et mise à jour des références internes (chemins, tags de propriétés).
- Frontend : projet Angular trajet-km-tracker -> schotziad-km-tracker
  (package.json, angular.json, chemin dist, Dockerfile), titre applicatif
  'SchotzIAD KM Tracker'.
- Docker et scripts (backend/Dockerfile, frontend/Dockerfile, run-dev.sh) mis à jour.
- Suppression du fichier résiduel package.json.bak.

Backend (solution) et frontend (build production) compilent sans erreur.
2026-09-14 07:50:26 +02:00

115 lines
4.6 KiB
C#

using Microsoft.EntityFrameworkCore;
using SchotzIadKmTracker.Api.Models.Entities;
namespace SchotzIadKmTracker.Api.Data;
/// <summary>
/// Contexte EF Core de l'application. Déclare les <see cref="DbSet{TEntity}"/>, les contraintes CHECK,
/// les index et les index uniques conformément à la section « Schéma SQLite » de la conception.
/// </summary>
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
public DbSet<Trajet> Trajets => Set<Trajet>();
public DbSet<Vehicule> Vehicules => Set<Vehicule>();
public DbSet<Profil> Profil => Set<Profil>();
public DbSet<AdresseCache> AdresseCache => Set<AdresseCache>();
public DbSet<AdresseNommee> AdressesNommees => Set<AdresseNommee>();
public DbSet<TrancheBareme> TranchesBareme => Set<TrancheBareme>();
public DbSet<MontantRegle> MontantsRegles => Set<MontantRegle>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// --- Trajets ---
modelBuilder.Entity<Trajet>(entity =>
{
entity.ToTable("Trajets", t =>
{
// Distance nulle autorisée (Exigence 2.4 : distance non calculable) ; sinon strictement positive.
t.HasCheckConstraint("CK_Trajets_Distance", "\"Distance\" IS NULL OR \"Distance\" > 0");
t.HasCheckConstraint("CK_Trajets_PuissanceFiscale", "\"PuissanceFiscale\" > 0");
});
entity.HasIndex(t => t.Date, "IX_Trajets_Date");
entity.HasIndex(t => new { t.Date, t.Position }, "IX_Trajets_Date_Position");
entity.HasIndex(t => t.VehiculeId, "IX_Trajets_Vehicule");
entity.HasOne(t => t.Vehicule)
.WithMany(v => v.Trajets)
.HasForeignKey(t => t.VehiculeId)
.OnDelete(DeleteBehavior.Restrict);
});
// --- Vehicules ---
modelBuilder.Entity<Vehicule>(entity =>
{
entity.ToTable("Vehicules", t =>
t.HasCheckConstraint("CK_Vehicules_PuissanceFiscale", "\"PuissanceFiscale\" > 0"));
entity.HasIndex(v => v.DateEffet, "IX_Vehicules_DateEffet");
});
// --- Profil (singleton Id = 1) ---
modelBuilder.Entity<Profil>(entity =>
{
entity.ToTable("Profil");
entity.HasKey(p => p.Id);
entity.Property(p => p.Id).ValueGeneratedNever();
entity.HasIndex(p => p.Id, "UX_Profil_Singleton").IsUnique();
});
// --- AdresseCache (Adresse unique) ---
modelBuilder.Entity<AdresseCache>(entity =>
{
entity.ToTable("AdresseCache");
entity.HasIndex(a => a.Adresse).IsUnique();
});
// --- AdressesNommees (unicité sur DenominationNormalisee) ---
modelBuilder.Entity<AdresseNommee>(entity =>
{
entity.ToTable("AdressesNommees");
entity.HasIndex(a => a.DenominationNormalisee, "UX_AdresseNommee_Denomination").IsUnique();
});
// --- TranchesBareme ---
modelBuilder.Entity<TrancheBareme>(entity =>
{
// Convention [KmMin, KmMax[ : borne max EXCLUSIVE, ou NULL = illimité.
// La contrainte tolère KmMax NULL et impose sinon KmMin < KmMax.
// Convention [KmMin, KmMax[ : borne max EXCLUSIVE, ou NULL = illimité.
// Les décimaux sont stockés en TEXT par SQLite : on CAST en REAL pour comparer
// numériquement (sinon "5000" > "20000" en comparaison lexicographique de chaînes).
entity.ToTable("TranchesBareme", t =>
t.HasCheckConstraint(
"CK_TranchesBareme_Km",
"\"KmMax\" IS NULL OR CAST(\"KmMin\" AS REAL) < CAST(\"KmMax\" AS REAL)"));
entity.HasIndex(t => new { t.Annee, t.PuissanceFiscale }, "IX_TranchesBareme_Annee_PF");
});
// --- MontantsRegles ---
modelBuilder.Entity<MontantRegle>(entity =>
{
entity.ToTable("MontantsRegles", t =>
{
t.HasCheckConstraint("CK_MontantsRegles_Montant", "\"Montant\" >= 0");
t.HasCheckConstraint("CK_MontantsRegles_Mois", "\"Mois\" BETWEEN 1 AND 12");
});
entity.HasIndex(m => new { m.Annee, m.Mois, m.VehiculeId }, "UX_MontantsRegles_Periode_Vehicule")
.IsUnique();
entity.HasOne(m => m.Vehicule)
.WithMany()
.HasForeignKey(m => m.VehiculeId)
.OnDelete(DeleteBehavior.Restrict);
});
}
}