package dev.lions.models; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; import java.io.Serial; import java.io.Serializable; import java.time.LocalDateTime; import java.util.Objects; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.ToString; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.proxy.HibernateProxy; /** * Représente un témoignage de client pour un projet. */ @Entity @Table(name = "project_testimonials") @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) @Getter @Setter @ToString @Builder @AllArgsConstructor public class Testimonial implements Serializable { @Serial private static final long serialVersionUID = 1L; @Id @NotBlank(message = "L'identifiant du témoignage est obligatoire") private String id; @NotBlank(message = "Le nom du client est obligatoire") @Size(min = 3, max = 100) private String clientName; @NotBlank(message = "Le poste du client est obligatoire") @Size(min = 3, max = 100) private String clientPosition; @NotBlank(message = "Le contenu du témoignage est obligatoire") @Size(min = 10, max = 1000) private String content; @Size(max = 255) private String clientImage; @ManyToOne @JoinColumn(name = "project_id", nullable = false) private Project project; @Builder.Default private int rating = 5; @Builder.Default private boolean isFeatured = false; @Column(name = "completion_date") private LocalDateTime completionDate; @Column(name = "created_at", nullable = false, updatable = false) private LocalDateTime createdAt; @Column(name = "updated_at") private LocalDateTime updatedAt; /** * Constructeur par défaut requis pour JPA. */ public Testimonial() { this.createdAt = LocalDateTime.now(); } /** * Crée une nouvelle instance de témoignage. */ public static Testimonial create(String clientName, String clientPosition, String content, String clientImage, Project project, int rating, boolean isFeatured) { Testimonial testimonial = new Testimonial(); testimonial.setClientName(clientName); testimonial.setClientPosition(clientPosition); testimonial.setContent(content); testimonial.setClientImage(clientImage); testimonial.setProject(project); testimonial.setRating(rating); testimonial.setFeatured(isFeatured); testimonial.setCreatedAt(LocalDateTime.now()); return testimonial; } /** * Builder personnalisé pour permettre d'ajouter un titre de projet. */ public static class TestimonialBuilder { public TestimonialBuilder projectTitle(String title) { if (this.project == null) { this.project = new Project(); } this.project.setTitle(title); return this; } public TestimonialBuilder date(LocalDateTime completionDate) { this.completionDate = completionDate; return this; } } @Override public final boolean equals(Object o) { if (this == o) { return true; } if (o == null) { return false; } Class oEffectiveClass = o instanceof HibernateProxy ? ((HibernateProxy) o).getHibernateLazyInitializer() .getPersistentClass() : o.getClass(); Class thisEffectiveClass = this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer() .getPersistentClass() : this.getClass(); if (thisEffectiveClass != oEffectiveClass) { return false; } Testimonial that = (Testimonial) o; return getId() != null && Objects.equals(getId(), that.getId()); } @Override public final int hashCode() { return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer() .getPersistentClass().hashCode() : getClass().hashCode(); } }