using Microsoft.EntityFrameworkCore;
using SchotzIadKmTracker.Api.Models.Entities;
namespace SchotzIadKmTracker.Api.Data;
///
/// Contexte EF Core de l'application. Déclare les , les contraintes CHECK,
/// les index et les index uniques conformément à la section « Schéma SQLite » de la conception.
///
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions options) : base(options)
{
}
public DbSet Trajets => Set();
public DbSet Vehicules => Set();
public DbSet Profil => Set();
public DbSet AdresseCache => Set();
public DbSet AdressesNommees => Set();
public DbSet TranchesBareme => Set();
public DbSet MontantsRegles => Set();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// --- Trajets ---
modelBuilder.Entity(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(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(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(entity =>
{
entity.ToTable("AdresseCache");
entity.HasIndex(a => a.Adresse).IsUnique();
});
// --- AdressesNommees (unicité sur DenominationNormalisee) ---
modelBuilder.Entity(entity =>
{
entity.ToTable("AdressesNommees");
entity.HasIndex(a => a.DenominationNormalisee, "UX_AdresseNommee_Denomination").IsUnique();
});
// --- TranchesBareme ---
modelBuilder.Entity(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(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);
});
}
}