package dev.lions.unionflow.server.entity; import jakarta.persistence.*; import jakarta.validation.constraints.*; import java.math.BigDecimal; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; /** * Entité LigneEcriture pour les lignes d'une écriture comptable * * @author UnionFlow Team * @version 3.0 * @since 2025-01-29 */ @Entity @Table( name = "lignes_ecriture", indexes = { @Index(name = "idx_ligne_ecriture_ecriture", columnList = "ecriture_id"), @Index(name = "idx_ligne_ecriture_compte", columnList = "compte_comptable_id") }) @Data @NoArgsConstructor @AllArgsConstructor @Builder @EqualsAndHashCode(callSuper = true) public class LigneEcriture extends BaseEntity { /** Numéro de ligne */ @NotNull @Min(value = 1, message = "Le numéro de ligne doit être positif") @Column(name = "numero_ligne", nullable = false) private Integer numeroLigne; /** Montant débit */ @DecimalMin(value = "0.0", message = "Le montant débit doit être positif ou nul") @Digits(integer = 12, fraction = 2) @Column(name = "montant_debit", precision = 14, scale = 2) private BigDecimal montantDebit; /** Montant crédit */ @DecimalMin(value = "0.0", message = "Le montant crédit doit être positif ou nul") @Digits(integer = 12, fraction = 2) @Column(name = "montant_credit", precision = 14, scale = 2) private BigDecimal montantCredit; /** Libellé de la ligne */ @Column(name = "libelle", length = 500) private String libelle; /** Référence */ @Column(name = "reference", length = 100) private String reference; // Relations @NotNull @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "ecriture_id", nullable = false) private EcritureComptable ecriture; @NotNull @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "compte_comptable_id", nullable = false) private CompteComptable compteComptable; /** Méthode métier pour vérifier que la ligne a soit un débit soit un crédit (pas les deux) */ public boolean isValide() { boolean aDebit = montantDebit != null && montantDebit.compareTo(BigDecimal.ZERO) > 0; boolean aCredit = montantCredit != null && montantCredit.compareTo(BigDecimal.ZERO) > 0; return aDebit != aCredit; // XOR : soit débit, soit crédit, pas les deux } /** Méthode métier pour obtenir le montant (débit ou crédit) */ public BigDecimal getMontant() { if (montantDebit != null && montantDebit.compareTo(BigDecimal.ZERO) > 0) { return montantDebit; } if (montantCredit != null && montantCredit.compareTo(BigDecimal.ZERO) > 0) { return montantCredit; } return BigDecimal.ZERO; } /** Callback JPA avant la persistance */ @PrePersist protected void onCreate() { super.onCreate(); if (montantDebit == null) { montantDebit = BigDecimal.ZERO; } if (montantCredit == null) { montantCredit = BigDecimal.ZERO; } } }