Task 1.2 - Entités JPA fondamentales
- Création de BaseEntity avec audit trail et soft delete - Création de l'entité User avec Quarkus Security JPA - Création de l'entité Client avec informations d'entreprise - Création de l'entité Coach avec informations professionnelles - Relations JPA one-to-one entre User-Client et User-Coach - Migrations Flyway V1, V2, V3 pour les tables - Données de test dans import.sql - Compilation réussie du module d'implémentation
This commit is contained in:
550
src/main/java/com/gbcm/server/impl/entity/Coach.java
Normal file
550
src/main/java/com/gbcm/server/impl/entity/Coach.java
Normal file
@@ -0,0 +1,550 @@
|
||||
package com.gbcm.server.impl.entity;
|
||||
|
||||
import com.gbcm.server.api.enums.ServiceType;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Entité représentant un coach de la plateforme GBCM.
|
||||
* Un coach est associé à un utilisateur et peut offrir différents services.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "coaches", indexes = {
|
||||
@Index(name = "idx_coaches_user_id", columnList = "user_id", unique = true),
|
||||
@Index(name = "idx_coaches_status", columnList = "status"),
|
||||
@Index(name = "idx_coaches_specialization", columnList = "specialization"),
|
||||
@Index(name = "idx_coaches_deleted", columnList = "deleted")
|
||||
})
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "Coach.findByUserId",
|
||||
query = "SELECT c FROM Coach c WHERE c.user.id = :userId AND c.deleted = false"),
|
||||
@NamedQuery(name = "Coach.findByStatus",
|
||||
query = "SELECT c FROM Coach c WHERE c.status = :status AND c.deleted = false"),
|
||||
@NamedQuery(name = "Coach.findBySpecialization",
|
||||
query = "SELECT c FROM Coach c WHERE c.specialization = :specialization AND c.deleted = false"),
|
||||
@NamedQuery(name = "Coach.findAvailableCoaches",
|
||||
query = "SELECT c FROM Coach c WHERE c.status = 'ACTIVE' AND c.availableForBooking = true AND c.deleted = false")
|
||||
})
|
||||
public class Coach extends BaseEntity {
|
||||
|
||||
/**
|
||||
* Identifiant unique du coach.
|
||||
*/
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* Utilisateur associé à ce coach.
|
||||
* Relation one-to-one obligatoire.
|
||||
*/
|
||||
@OneToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(name = "user_id", nullable = false, unique = true,
|
||||
foreignKey = @ForeignKey(name = "fk_coaches_user_id"))
|
||||
@NotNull(message = "L'utilisateur associé est obligatoire")
|
||||
private User user;
|
||||
|
||||
/**
|
||||
* Spécialisation principale du coach.
|
||||
*/
|
||||
@Column(name = "specialization", nullable = false, length = 100)
|
||||
@NotBlank(message = "La spécialisation est obligatoire")
|
||||
@Size(max = 100, message = "La spécialisation ne peut pas dépasser 100 caractères")
|
||||
private String specialization;
|
||||
|
||||
/**
|
||||
* Biographie professionnelle du coach.
|
||||
*/
|
||||
@Column(name = "bio", columnDefinition = "TEXT")
|
||||
private String bio;
|
||||
|
||||
/**
|
||||
* Années d'expérience du coach.
|
||||
*/
|
||||
@Column(name = "years_of_experience")
|
||||
private Integer yearsOfExperience;
|
||||
|
||||
/**
|
||||
* Certifications du coach.
|
||||
*/
|
||||
@Column(name = "certifications", columnDefinition = "TEXT")
|
||||
private String certifications;
|
||||
|
||||
/**
|
||||
* Langues parlées par le coach.
|
||||
*/
|
||||
@Column(name = "languages", length = 255)
|
||||
@Size(max = 255, message = "Les langues ne peuvent pas dépasser 255 caractères")
|
||||
private String languages;
|
||||
|
||||
/**
|
||||
* Tarif horaire du coach pour les sessions individuelles.
|
||||
*/
|
||||
@Column(name = "hourly_rate", precision = 10, scale = 2)
|
||||
private BigDecimal hourlyRate;
|
||||
|
||||
/**
|
||||
* Statut du coach.
|
||||
*/
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "status", nullable = false, length = 20)
|
||||
@NotNull(message = "Le statut est obligatoire")
|
||||
private CoachStatus status = CoachStatus.ACTIVE;
|
||||
|
||||
/**
|
||||
* Disponibilité pour les réservations.
|
||||
*/
|
||||
@Column(name = "available_for_booking", nullable = false)
|
||||
private boolean availableForBooking = true;
|
||||
|
||||
/**
|
||||
* Types de services offerts par le coach.
|
||||
*/
|
||||
@ElementCollection(targetClass = ServiceType.class)
|
||||
@CollectionTable(name = "coach_service_types",
|
||||
joinColumns = @JoinColumn(name = "coach_id"),
|
||||
foreignKey = @ForeignKey(name = "fk_coach_service_types_coach_id"))
|
||||
@Column(name = "service_type", length = 30)
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Set<ServiceType> serviceTypes;
|
||||
|
||||
/**
|
||||
* Heures de travail - début.
|
||||
*/
|
||||
@Column(name = "working_hours_start")
|
||||
private LocalTime workingHoursStart;
|
||||
|
||||
/**
|
||||
* Heures de travail - fin.
|
||||
*/
|
||||
@Column(name = "working_hours_end")
|
||||
private LocalTime workingHoursEnd;
|
||||
|
||||
/**
|
||||
* Jours de travail (format: MONDAY,TUESDAY,WEDNESDAY...).
|
||||
*/
|
||||
@Column(name = "working_days", length = 100)
|
||||
@Size(max = 100, message = "Les jours de travail ne peuvent pas dépasser 100 caractères")
|
||||
private String workingDays;
|
||||
|
||||
/**
|
||||
* Fuseau horaire du coach.
|
||||
*/
|
||||
@Column(name = "timezone", length = 50)
|
||||
@Size(max = 50, message = "Le fuseau horaire ne peut pas dépasser 50 caractères")
|
||||
private String timezone;
|
||||
|
||||
/**
|
||||
* Date de début d'activité comme coach.
|
||||
*/
|
||||
@Column(name = "start_date")
|
||||
private LocalDate startDate;
|
||||
|
||||
/**
|
||||
* Date de fin d'activité comme coach.
|
||||
*/
|
||||
@Column(name = "end_date")
|
||||
private LocalDate endDate;
|
||||
|
||||
/**
|
||||
* Note moyenne du coach (calculée à partir des évaluations).
|
||||
*/
|
||||
@Column(name = "average_rating", precision = 3, scale = 2)
|
||||
private BigDecimal averageRating;
|
||||
|
||||
/**
|
||||
* Nombre total d'évaluations reçues.
|
||||
*/
|
||||
@Column(name = "total_ratings", nullable = false)
|
||||
private int totalRatings = 0;
|
||||
|
||||
/**
|
||||
* Nombre total de sessions effectuées.
|
||||
*/
|
||||
@Column(name = "total_sessions", nullable = false)
|
||||
private int totalSessions = 0;
|
||||
|
||||
/**
|
||||
* Revenus totaux générés.
|
||||
*/
|
||||
@Column(name = "total_revenue", precision = 15, scale = 2)
|
||||
private BigDecimal totalRevenue = BigDecimal.ZERO;
|
||||
|
||||
/**
|
||||
* Notes internes sur le coach.
|
||||
*/
|
||||
@Column(name = "notes", columnDefinition = "TEXT")
|
||||
private String notes;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut.
|
||||
*/
|
||||
public Coach() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec les champs obligatoires.
|
||||
*
|
||||
* @param user l'utilisateur associé
|
||||
* @param specialization la spécialisation du coach
|
||||
*/
|
||||
public Coach(User user, String specialization) {
|
||||
this();
|
||||
this.user = user;
|
||||
this.specialization = specialization;
|
||||
this.startDate = LocalDate.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Active le coach.
|
||||
*/
|
||||
public void activate() {
|
||||
this.status = CoachStatus.ACTIVE;
|
||||
this.availableForBooking = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Désactive le coach.
|
||||
*/
|
||||
public void deactivate() {
|
||||
this.status = CoachStatus.INACTIVE;
|
||||
this.availableForBooking = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Met le coach en congé.
|
||||
*/
|
||||
public void setOnLeave() {
|
||||
this.status = CoachStatus.ON_LEAVE;
|
||||
this.availableForBooking = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Termine l'activité du coach.
|
||||
*/
|
||||
public void terminate() {
|
||||
this.status = CoachStatus.TERMINATED;
|
||||
this.availableForBooking = false;
|
||||
this.endDate = LocalDate.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour la note moyenne après une nouvelle évaluation.
|
||||
*
|
||||
* @param newRating la nouvelle note reçue
|
||||
*/
|
||||
public void updateRating(BigDecimal newRating) {
|
||||
if (newRating != null && newRating.compareTo(BigDecimal.ZERO) > 0) {
|
||||
if (averageRating == null) {
|
||||
averageRating = newRating;
|
||||
totalRatings = 1;
|
||||
} else {
|
||||
BigDecimal totalScore = averageRating.multiply(new BigDecimal(totalRatings));
|
||||
totalScore = totalScore.add(newRating);
|
||||
totalRatings++;
|
||||
averageRating = totalScore.divide(new BigDecimal(totalRatings), 2, java.math.RoundingMode.HALF_UP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Incrémente le nombre de sessions effectuées.
|
||||
*/
|
||||
public void incrementSessionCount() {
|
||||
this.totalSessions++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute des revenus au total.
|
||||
*
|
||||
* @param amount le montant à ajouter
|
||||
*/
|
||||
public void addRevenue(BigDecimal amount) {
|
||||
if (amount != null && amount.compareTo(BigDecimal.ZERO) > 0) {
|
||||
this.totalRevenue = this.totalRevenue.add(amount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le coach est disponible pour les réservations.
|
||||
*
|
||||
* @return true si disponible, false sinon
|
||||
*/
|
||||
public boolean isAvailableForBooking() {
|
||||
return availableForBooking && status == CoachStatus.ACTIVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le coach offre un type de service spécifique.
|
||||
*
|
||||
* @param serviceType le type de service à vérifier
|
||||
* @return true si le coach offre ce service, false sinon
|
||||
*/
|
||||
public boolean offersService(ServiceType serviceType) {
|
||||
return serviceTypes != null && serviceTypes.contains(serviceType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Méthode de recherche par ID utilisateur.
|
||||
*
|
||||
* @param userId l'ID de l'utilisateur
|
||||
* @return le coach trouvé ou null
|
||||
*/
|
||||
public static Coach findByUserId(Long userId) {
|
||||
return find("#Coach.findByUserId", userId).firstResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Méthode de recherche par statut.
|
||||
*
|
||||
* @param status le statut à rechercher
|
||||
* @return la liste des coaches avec ce statut
|
||||
*/
|
||||
public static List<Coach> findByStatus(CoachStatus status) {
|
||||
return find("#Coach.findByStatus", status).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Méthode de recherche par spécialisation.
|
||||
*
|
||||
* @param specialization la spécialisation à rechercher
|
||||
* @return la liste des coaches avec cette spécialisation
|
||||
*/
|
||||
public static List<Coach> findBySpecialization(String specialization) {
|
||||
return find("#Coach.findBySpecialization", specialization).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Méthode de recherche des coaches disponibles.
|
||||
*
|
||||
* @return la liste des coaches disponibles pour réservation
|
||||
*/
|
||||
public static List<Coach> findAvailableCoaches() {
|
||||
return find("#Coach.findAvailableCoaches").list();
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getSpecialization() {
|
||||
return specialization;
|
||||
}
|
||||
|
||||
public void setSpecialization(String specialization) {
|
||||
this.specialization = specialization;
|
||||
}
|
||||
|
||||
public String getBio() {
|
||||
return bio;
|
||||
}
|
||||
|
||||
public void setBio(String bio) {
|
||||
this.bio = bio;
|
||||
}
|
||||
|
||||
public Integer getYearsOfExperience() {
|
||||
return yearsOfExperience;
|
||||
}
|
||||
|
||||
public void setYearsOfExperience(Integer yearsOfExperience) {
|
||||
this.yearsOfExperience = yearsOfExperience;
|
||||
}
|
||||
|
||||
public String getCertifications() {
|
||||
return certifications;
|
||||
}
|
||||
|
||||
public void setCertifications(String certifications) {
|
||||
this.certifications = certifications;
|
||||
}
|
||||
|
||||
public String getLanguages() {
|
||||
return languages;
|
||||
}
|
||||
|
||||
public void setLanguages(String languages) {
|
||||
this.languages = languages;
|
||||
}
|
||||
|
||||
public BigDecimal getHourlyRate() {
|
||||
return hourlyRate;
|
||||
}
|
||||
|
||||
public void setHourlyRate(BigDecimal hourlyRate) {
|
||||
this.hourlyRate = hourlyRate;
|
||||
}
|
||||
|
||||
public CoachStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(CoachStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public void setAvailableForBooking(boolean availableForBooking) {
|
||||
this.availableForBooking = availableForBooking;
|
||||
}
|
||||
|
||||
public Set<ServiceType> getServiceTypes() {
|
||||
return serviceTypes;
|
||||
}
|
||||
|
||||
public void setServiceTypes(Set<ServiceType> serviceTypes) {
|
||||
this.serviceTypes = serviceTypes;
|
||||
}
|
||||
|
||||
public LocalTime getWorkingHoursStart() {
|
||||
return workingHoursStart;
|
||||
}
|
||||
|
||||
public void setWorkingHoursStart(LocalTime workingHoursStart) {
|
||||
this.workingHoursStart = workingHoursStart;
|
||||
}
|
||||
|
||||
public LocalTime getWorkingHoursEnd() {
|
||||
return workingHoursEnd;
|
||||
}
|
||||
|
||||
public void setWorkingHoursEnd(LocalTime workingHoursEnd) {
|
||||
this.workingHoursEnd = workingHoursEnd;
|
||||
}
|
||||
|
||||
public String getWorkingDays() {
|
||||
return workingDays;
|
||||
}
|
||||
|
||||
public void setWorkingDays(String workingDays) {
|
||||
this.workingDays = workingDays;
|
||||
}
|
||||
|
||||
public String getTimezone() {
|
||||
return timezone;
|
||||
}
|
||||
|
||||
public void setTimezone(String timezone) {
|
||||
this.timezone = timezone;
|
||||
}
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDate startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public LocalDate getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
public void setEndDate(LocalDate endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
public BigDecimal getAverageRating() {
|
||||
return averageRating;
|
||||
}
|
||||
|
||||
public void setAverageRating(BigDecimal averageRating) {
|
||||
this.averageRating = averageRating;
|
||||
}
|
||||
|
||||
public int getTotalRatings() {
|
||||
return totalRatings;
|
||||
}
|
||||
|
||||
public void setTotalRatings(int totalRatings) {
|
||||
this.totalRatings = totalRatings;
|
||||
}
|
||||
|
||||
public int getTotalSessions() {
|
||||
return totalSessions;
|
||||
}
|
||||
|
||||
public void setTotalSessions(int totalSessions) {
|
||||
this.totalSessions = totalSessions;
|
||||
}
|
||||
|
||||
public BigDecimal getTotalRevenue() {
|
||||
return totalRevenue;
|
||||
}
|
||||
|
||||
public void setTotalRevenue(BigDecimal totalRevenue) {
|
||||
this.totalRevenue = totalRevenue;
|
||||
}
|
||||
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
}
|
||||
|
||||
public void setNotes(String notes) {
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Coach{" +
|
||||
"id=" + id +
|
||||
", specialization='" + specialization + '\'' +
|
||||
", status=" + status +
|
||||
", availableForBooking=" + availableForBooking +
|
||||
", averageRating=" + averageRating +
|
||||
", totalSessions=" + totalSessions +
|
||||
", totalRevenue=" + totalRevenue +
|
||||
'}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Énumération des statuts de coach.
|
||||
*/
|
||||
public enum CoachStatus {
|
||||
/**
|
||||
* Coach actif et disponible.
|
||||
*/
|
||||
ACTIVE,
|
||||
|
||||
/**
|
||||
* Coach inactif temporairement.
|
||||
*/
|
||||
INACTIVE,
|
||||
|
||||
/**
|
||||
* Coach en congé.
|
||||
*/
|
||||
ON_LEAVE,
|
||||
|
||||
/**
|
||||
* Coach dont le contrat est terminé.
|
||||
*/
|
||||
TERMINATED
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user