import java.time.LocalDate; import java.time.temporal.ChronoUnit; public class Location { // ── Attributs privés ── private int id; private Vehicule voiture; private Client client; private LocalDate dateDebut; private LocalDate dateFin; // date de fin prévue private LocalDate dateRetour; // date réelle de retour (null si pas encore rendu) private double prixTotal; private StatutLocation statut; // ── Compteur statique pour les IDs ── private static int compteur = 0; // ── Constructeur ── public Location(Vehicule voiture, Client client, LocalDate dateDebut, LocalDate dateFin) { this.id = ++compteur; this.voiture = voiture; this.client = client; this.dateDebut = dateDebut; this.dateFin = dateFin; this.dateRetour = null; this.statut = StatutLocation.EN_COURS; this.prixTotal = calculerPrix(); voiture.louer(); } // ── Méthodes métier ── // Retourne le nombre de jours prévus (dateDebut -> dateFin) public long getDuree() { return ChronoUnit.DAYS.between(dateDebut, dateFin); } // Calcule le prix total : durée × prix par jour du véhicule public double calculerPrix() { return getDuree() * voiture.getPrixJour(); } // Vérifie si la location est en retard public boolean isEnRetard() { if (dateRetour != null) { return dateRetour.isAfter(dateFin); } return LocalDate.now().isAfter(dateFin); } // Retourne la pénalité de retard : jours de retard × prixJour × 1.5 public double getPenaliteRetard() { if (!isEnRetard()) return 0; LocalDate reference = (dateRetour != null) ? dateRetour : LocalDate.now(); long joursRetard = ChronoUnit.DAYS.between(dateFin, reference); return joursRetard * voiture.getPrixJour() * 1.5; } // Termine la location : enregistre la date de retour réelle et met à jour le statut public void terminerLocation() { this.dateRetour = LocalDate.now(); voiture.retourner(); if (isEnRetard()) { this.statut = StatutLocation.EN_RETARD; } else { this.statut = StatutLocation.TERMINEE; } this.prixTotal = calculerPrix() + getPenaliteRetard(); } // Annule la location (si elle est encore en cours) public void annulerLocation() { if (this.statut == StatutLocation.EN_COURS) { this.statut = StatutLocation.ANNULEE; voiture.retourner(); } } // Affichage formaté public void afficherLocation() { System.out.println("──────────────────────────────────"); System.out.println(" Location N° : " + id); System.out.println(" Client : " + client.getPrenom() + " " + client.getNom()); System.out.println(" Date début : " + dateDebut); System.out.println(" Date fin prévue : " + dateFin); System.out.println(" Date retour : " + (dateRetour != null ? dateRetour : "En cours")); System.out.println(" Durée prévue : " + getDuree() + " jour(s)"); System.out.println(" Prix total : " + prixTotal + " €"); if (isEnRetard()) { System.out.println(" Pénalité retard : " + getPenaliteRetard() + " €"); } System.out.println(" Statut : " + statut); System.out.println("──────────────────────────────────"); } // ── Getters ── public int getId() { return id; } public Vehicule getVoiture() { return voiture; } public Client getClient() { return client; } public LocalDate getDateDebut() { return dateDebut; } public LocalDate getDateFin() { return dateFin; } public LocalDate getDateRetour() { return dateRetour; } public double getPrixTotal() { return prixTotal; } public StatutLocation getStatut() { return statut; } // ── Setter statut (utile pour forcer un état depuis AgenceLocation) ── public void setStatut(StatutLocation statut) { this.statut = statut; } // ── toString ── @Override public String toString() { return "Location #" + id + " | " + client.getNom() + " | " + voiture.toString() + " | " + dateDebut + " → " + dateFin + " | " + statut; } }