SchotzIAD KM Tracker : suivi des trajets kilométriques (Angular + .NET 8)
Application complète de saisie et de suivi des trajets kilométriques avec calcul de distance routière (OpenRouteService), barème kilométrique, résumés et régularisation annuelle. Backend (ASP.NET Core .NET 8, EF Core, SQLite) : - Trajets (CRUD, réordonnancement, insertion), calcul de distance ORS avec fallback Haversine, géométrie d'itinéraire stockée par trajet, recalcul en masse. - Profil, véhicules (avec dénomination), carnet d'adresses nommées, cache d'adresses. - Barème kilométrique : tranches multiples par puissance fiscale, borne max exclusive avec 'illimité' (KmMax nullable), coefficient à 3 décimales, recopie du dernier barème connu. - Résumés mensuel/annuel, montants réglés, régularisation, export PDF. Frontend (Angular 22, zoneless + signals) : - Consultation par jour, navigation temporelle synchronisée, carte Leaflet, formulaire de trajet (adresses nommées, domicile, autocomplétion BAN). - Détection de changement zoneless (indépendante de zone.js). Hébergement : Docker Compose (nginx + backend), scripts run-dev.sh / run-docker.sh.
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
// Modèles Adresses — miroir de AdresseDtos.cs + réponse BAN.
|
||||
|
||||
/** Résultat de recherche BAN proxifié via le backend — miroir de BANAdresseDto. */
|
||||
export interface BANAdresse {
|
||||
label: string;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
postcode: string;
|
||||
city: string;
|
||||
}
|
||||
|
||||
/** Suggestion d'autocomplétion issue du cache local — miroir de AdresseCacheDto. */
|
||||
export interface AdresseCache {
|
||||
adresse: string;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
}
|
||||
|
||||
/** Adresse nommée du carnet d'adresses — miroir de AdresseNommeeDto. */
|
||||
export interface AdresseNommee {
|
||||
id: number;
|
||||
denomination: string;
|
||||
adresse: string;
|
||||
latitude: number | null; // null si le géocodage a échoué
|
||||
longitude: number | null; // null si le géocodage a échoué
|
||||
}
|
||||
|
||||
/** Création / mise à jour d'une adresse nommée — miroir de SaveAdresseNommeeDto. */
|
||||
export interface SaveAdresseNommee {
|
||||
denomination: string; // 1 à 100 car., unique après normalisation
|
||||
adresse: string; // 1 à 255 car.
|
||||
latitude?: number | null; // fournies par le frontend si sélection BAN
|
||||
longitude?: number | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Réponse brute de l'API Base Adresse Nationale (Feature GeoJSON).
|
||||
* Source primaire d'autocomplétion appelée directement par le frontend.
|
||||
*/
|
||||
export interface BANFeature {
|
||||
properties: {
|
||||
label: string; // libellé complet normalisé
|
||||
score: number; // score de pertinence 0–1
|
||||
postcode: string;
|
||||
city: string;
|
||||
context: string;
|
||||
type: string; // 'housenumber' | 'street' | 'locality' | 'municipality'
|
||||
x: number; // longitude
|
||||
y: number; // latitude
|
||||
};
|
||||
geometry: {
|
||||
coordinates: [number, number]; // [longitude, latitude]
|
||||
};
|
||||
}
|
||||
|
||||
/** Enveloppe de la réponse BAN (FeatureCollection GeoJSON). */
|
||||
export interface BANFeatureCollection {
|
||||
features: BANFeature[];
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Modèles Barème & montants — miroir de BaremeDtos.cs.
|
||||
|
||||
/** Tranche de barème kilométrique — miroir de TrancheBaremeDto. */
|
||||
export interface TrancheBareme {
|
||||
id: number;
|
||||
annee: number;
|
||||
puissanceFiscale: number;
|
||||
kmMin: number;
|
||||
kmMax: number | null; // null = illimité (borne max exclusive : [kmMin, kmMax[)
|
||||
coefficient: number;
|
||||
base: number;
|
||||
}
|
||||
|
||||
/** Création / mise à jour d'une tranche — miroir de SaveTrancheBaremeDto. */
|
||||
export interface SaveTrancheBareme {
|
||||
annee: number;
|
||||
puissanceFiscale: number;
|
||||
kmMin: number;
|
||||
kmMax: number | null; // null = illimité
|
||||
coefficient: number;
|
||||
base: number;
|
||||
}
|
||||
|
||||
/** Montant réglé pour une période et un véhicule — miroir de MontantRegleDto. */
|
||||
export interface MontantRegle {
|
||||
annee: number;
|
||||
mois: number;
|
||||
vehiculeId: number;
|
||||
montant: number;
|
||||
}
|
||||
|
||||
/** Indication de versement mensuel prévisionnel — miroir de MontantPrevisionnelDto. */
|
||||
export interface MontantPrevisionnel {
|
||||
annee: number;
|
||||
mois: number;
|
||||
vehiculeId: number;
|
||||
totalAnnuelPartielKm: number;
|
||||
montantBaremePlein: number; // barème plein sur le total partiel
|
||||
montantPrevisionnel: number; // = 80% (indicatif uniquement)
|
||||
}
|
||||
|
||||
/** Ligne mensuelle de la synthèse annuelle — miroir de LigneSyntheseMoisDto. */
|
||||
export interface LigneSyntheseMois {
|
||||
mois: number;
|
||||
kmMois: number;
|
||||
fraisPaye: number; // Montant_Regle du mois (saisi)
|
||||
fraisReelMensuel: number; // km_du_mois × coefficient de la tranche annuelle
|
||||
}
|
||||
|
||||
/** Synthèse annuelle de régularisation — miroir de RegularisationAnnuelleDto. */
|
||||
export interface RegularisationAnnuelle {
|
||||
annee: number;
|
||||
vehiculeId: number;
|
||||
plaque: string;
|
||||
puissanceFiscale: number;
|
||||
coefficientTranche: number;
|
||||
baseTranche: number;
|
||||
trancheLibelle: string;
|
||||
mois: LigneSyntheseMois[]; // 12 lignes
|
||||
totalKmAnnuel: number;
|
||||
totalPaye: number; // somme des Montant_Regle
|
||||
montantReel: number; // barème plein : total_km × coef + base
|
||||
regularisation: number; // montantReel − totalPaye
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Barrel d'export des modèles du domaine (miroir des DTOs backend).
|
||||
export * from './trajet.model';
|
||||
export * from './resume-mensuel.model';
|
||||
export * from './resume-annuel.model';
|
||||
export * from './totaux.model';
|
||||
export * from './vehicule.model';
|
||||
export * from './profil.model';
|
||||
export * from './bareme.model';
|
||||
export * from './adresse.model';
|
||||
@@ -0,0 +1,27 @@
|
||||
// Modèles Profil — miroir de ProfilDtos.cs.
|
||||
|
||||
/** Profil — miroir de ProfilDto. */
|
||||
export interface Profil {
|
||||
nom: string | null;
|
||||
prenom: string | null;
|
||||
matricule: string | null;
|
||||
adresseDomicile: string | null;
|
||||
domicileGeocode: boolean;
|
||||
}
|
||||
|
||||
/** Création / mise à jour du profil — miroir de SaveProfilDto. */
|
||||
export interface SaveProfil {
|
||||
nom?: string | null;
|
||||
prenom?: string | null;
|
||||
matricule?: string | null; // max 8 car.
|
||||
adresseDomicile: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* État de configuration du profil (onboarding première utilisation).
|
||||
* Miroir de EtatProfilDto.
|
||||
* estConfigure = true ssi Profil.Nom et Profil.Prenom non vides ET au moins un Vehicule existe.
|
||||
*/
|
||||
export interface EtatProfil {
|
||||
estConfigure: boolean;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { ResumeMensuel } from './resume-mensuel.model';
|
||||
|
||||
/** Résumé annuel — miroir de ResumeAnnuelDto. */
|
||||
export interface ResumeAnnuel {
|
||||
annee: number;
|
||||
mois: ResumeMensuel[]; // toujours 12 éléments
|
||||
totalKm: number;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Trajet } from './trajet.model';
|
||||
|
||||
/** Résumé mensuel — miroir de ResumeMensuelDto. */
|
||||
export interface ResumeMensuel {
|
||||
annee: number;
|
||||
mois: number;
|
||||
trajets: Trajet[];
|
||||
totalKm: number; // somme des distances, 2 décimales
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/** Totaux affichés dans le Panneau_Totaux — miroir de TotauxDto. */
|
||||
export interface Totaux {
|
||||
date: string; // ISO date
|
||||
vehiculeId: number; // véhicule sur lequel portent les totaux
|
||||
totalJour: number;
|
||||
totalMois: number;
|
||||
totalAnnuelPartiel: number; // cumul de l'année jusqu'au mois inclus
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Modèles Trajet — miroir des DTOs backend (TrajetDtos.cs).
|
||||
|
||||
/**
|
||||
* Création d'un Trajet.
|
||||
* Les coordonnées sont transmises par le Frontend (issues de la sélection BAN) ;
|
||||
* elles sont nulles si l'adresse a été saisie manuellement sans autocomplétion.
|
||||
*/
|
||||
export interface CreateTrajet {
|
||||
date: string; // JJ/MM/AAAA en entrée
|
||||
adresseDepart: string;
|
||||
departLatitude?: number | null;
|
||||
departLongitude?: number | null;
|
||||
adresseArrivee: string;
|
||||
arriveeLatitude?: number | null;
|
||||
arriveeLongitude?: number | null;
|
||||
commentaire?: string | null; // optionnel, max 500 car.
|
||||
vehiculeId?: number | null; // null -> véhicule courant à la date du trajet
|
||||
}
|
||||
|
||||
/** Mise à jour d'un Trajet. */
|
||||
export interface UpdateTrajet {
|
||||
date: string;
|
||||
adresseDepart: string;
|
||||
departLatitude?: number | null;
|
||||
departLongitude?: number | null;
|
||||
adresseArrivee: string;
|
||||
arriveeLatitude?: number | null;
|
||||
arriveeLongitude?: number | null;
|
||||
commentaire?: string | null;
|
||||
vehiculeId?: number | null;
|
||||
}
|
||||
|
||||
/** Réponse Trajet. */
|
||||
export interface Trajet {
|
||||
id: number;
|
||||
date: string; // ISO date (yyyy-MM-dd) renvoyée par l'API
|
||||
adresseDepart: string;
|
||||
adresseArrivee: string;
|
||||
distance: number | null; // km, 2 décimales ; null si non calculable (Exigence 2.4)
|
||||
commentaire: string | null;
|
||||
position: number; // rang dans la journée
|
||||
vehiculeId: number;
|
||||
puissanceFiscale: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trajet enrichi pour l'affichage carte (géométries GeoJSON).
|
||||
* Note : ce DTO ne porte PAS de `commentaire` (le commentaire n'est affiché que
|
||||
* dans la liste des trajets, via l'interface `Trajet`, jamais dans l'infobulle carte).
|
||||
*/
|
||||
export interface TrajetCarte {
|
||||
id: number;
|
||||
date: string;
|
||||
adresseDepart: string;
|
||||
adresseArrivee: string;
|
||||
distance: number;
|
||||
departLatitude?: number | null;
|
||||
departLongitude?: number | null;
|
||||
arriveeLatitude?: number | null;
|
||||
arriveeLongitude?: number | null;
|
||||
geometrieJson: string | null; // GeoJSON LineString ou null
|
||||
}
|
||||
|
||||
/** Position d'un trajet lors d'un réordonnancement. */
|
||||
export interface TrajetPosition {
|
||||
id: number;
|
||||
position: number;
|
||||
}
|
||||
|
||||
/** Réordonnancement manuel des trajets d'une journée. */
|
||||
export interface ReordonnerTrajets {
|
||||
trajets: TrajetPosition[];
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Modèles Véhicule — miroir de VehiculeDtos.cs.
|
||||
|
||||
/** Véhicule — miroir de VehiculeDto. */
|
||||
export interface Vehicule {
|
||||
id: number;
|
||||
denomination: string;
|
||||
plaque: string;
|
||||
puissanceFiscale: number;
|
||||
dateEffet: string; // ISO date
|
||||
}
|
||||
|
||||
/** Création d'un véhicule — miroir de CreateVehiculeDto. */
|
||||
export interface CreateVehicule {
|
||||
denomination: string;
|
||||
plaque: string;
|
||||
puissanceFiscale: number;
|
||||
dateEffet: string; // JJ/MM/AAAA, <= date du jour
|
||||
}
|
||||
|
||||
/**
|
||||
* Réponse à la création d'un véhicule.
|
||||
* Indique s'il faut proposer une réaffectation des trajets existants.
|
||||
*/
|
||||
export interface VehiculeCree {
|
||||
vehicule: Vehicule;
|
||||
reaffectationProposee: boolean; // true si des trajets >= DateEffet ont une autre puissance fiscale
|
||||
nombreTrajetsConcernes: number;
|
||||
}
|
||||
|
||||
/** Requête de réaffectation — miroir de ReaffectationDto. */
|
||||
export interface Reaffectation {
|
||||
vehiculeId: number; // nouveau véhicule
|
||||
accepter: boolean; // true = réaffecter les trajets >= DateEffet ; false = ne rien changer
|
||||
}
|
||||
Reference in New Issue
Block a user