package dev.lions.unionflow.server.entity; import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable; import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; /** * Entité JournalComptable pour la gestion des journaux * * @author UnionFlow Team * @version 3.0 * @since 2025-01-29 */ @Entity @Table( name = "journaux_comptables", uniqueConstraints = { @UniqueConstraint(name = "uk_journaux_org_code", columnNames = {"organisation_id", "code"}) }, indexes = { @Index(name = "idx_journal_code", columnList = "code"), @Index(name = "idx_journal_type", columnList = "type_journal"), @Index(name = "idx_journal_periode", columnList = "date_debut, date_fin") }) @Data @NoArgsConstructor @AllArgsConstructor @Builder @EqualsAndHashCode(callSuper = true) public class JournalComptable extends BaseEntity { /** Code du journal (unique par organisation). */ @NotBlank @Column(name = "code", nullable = false, length = 10) private String code; /** Libellé du journal */ @NotBlank @Column(name = "libelle", nullable = false, length = 100) private String libelle; /** Type de journal */ @NotNull @Enumerated(EnumType.STRING) @Column(name = "type_journal", nullable = false, length = 30) private TypeJournalComptable typeJournal; /** Date de début de la période */ @Column(name = "date_debut") private LocalDate dateDebut; /** Date de fin de la période */ @Column(name = "date_fin") private LocalDate dateFin; /** Statut du journal (OUVERT, FERME, ARCHIVE) */ @Builder.Default @Column(name = "statut", length = 20) private String statut = "OUVERT"; /** Description */ @Column(name = "description", length = 500) private String description; /** Organisation propriétaire */ @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "organisation_id") private Organisation organisation; /** Écritures comptables associées */ @JsonIgnore @OneToMany(mappedBy = "journal", cascade = CascadeType.ALL, fetch = FetchType.LAZY) @Builder.Default private List ecritures = new ArrayList<>(); /** Méthode métier pour vérifier si le journal est ouvert */ public boolean isOuvert() { return "OUVERT".equals(statut); } /** Méthode métier pour vérifier si une date est dans la période */ public boolean estDansPeriode(LocalDate date) { if (dateDebut == null || dateFin == null) { return true; // Période illimitée } return !date.isBefore(dateDebut) && !date.isAfter(dateFin); } /** Callback JPA avant la persistance */ @PrePersist protected void onCreate() { super.onCreate(); if (statut == null || statut.isEmpty()) { statut = "OUVERT"; } } }