feat(backend): consolidation finale Spec 001 LCB-FT + Flyway V1-V5
Migrations Flyway (consolidées) : - V1 : Schéma complet (69 tables, 1322 lignes) - V2 : Colonnes BaseEntity (cree_par, modifie_par) - V3 : Colonnes métier manquantes (adresses, alert_configuration) - V4 : Correction system_logs (renommage colonnes, ajout timestamp) - V5 : Nettoyage alert_configuration (suppression colonnes obsolètes) - Suppression V2-V6 obsolètes (fragmentés) Entités LCB-FT : - AlerteLcbFt : Alertes anti-blanchiment - AlertConfiguration : Configuration alertes - SystemAlert : Alertes système - SystemLog : Logs techniques (DÉJÀ COMMITÉE avec super.onCreate fix) Services LCB-FT (T015, T016) : - AlerteLcbFtService + Resource : Dashboard alertes admin - AlertMonitoringService : Surveillance transactions - SystemLoggingService : Logs centralisés - FileStorageService : Upload documents Repositories : - AlerteLcbFtRepository - AlertConfigurationRepository - SystemAlertRepository - SystemLogRepository Tests : - GlobalExceptionMapperTest : 17 erreurs corrigées (toResponse()) Spec 001 : 27/27 tâches (100%) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Entité singleton pour la configuration des alertes système.
|
||||
* Une seule ligne en base de données.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2026-03-15
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "alert_configuration")
|
||||
@Getter
|
||||
@Setter
|
||||
public class AlertConfiguration extends BaseEntity {
|
||||
|
||||
/**
|
||||
* Alerte CPU activée
|
||||
*/
|
||||
@Column(name = "cpu_high_alert_enabled", nullable = false)
|
||||
private Boolean cpuHighAlertEnabled = true;
|
||||
|
||||
/**
|
||||
* Seuil CPU en pourcentage (0-100)
|
||||
*/
|
||||
@Column(name = "cpu_threshold_percent", nullable = false)
|
||||
private Integer cpuThresholdPercent = 80;
|
||||
|
||||
/**
|
||||
* Durée en minutes avant déclenchement alerte CPU
|
||||
*/
|
||||
@Column(name = "cpu_duration_minutes", nullable = false)
|
||||
private Integer cpuDurationMinutes = 5;
|
||||
|
||||
/**
|
||||
* Alerte mémoire faible activée
|
||||
*/
|
||||
@Column(name = "memory_low_alert_enabled", nullable = false)
|
||||
private Boolean memoryLowAlertEnabled = true;
|
||||
|
||||
/**
|
||||
* Seuil mémoire en pourcentage (0-100)
|
||||
*/
|
||||
@Column(name = "memory_threshold_percent", nullable = false)
|
||||
private Integer memoryThresholdPercent = 85;
|
||||
|
||||
/**
|
||||
* Alerte erreur critique activée
|
||||
*/
|
||||
@Column(name = "critical_error_alert_enabled", nullable = false)
|
||||
private Boolean criticalErrorAlertEnabled = true;
|
||||
|
||||
/**
|
||||
* Alerte erreur activée
|
||||
*/
|
||||
@Column(name = "error_alert_enabled", nullable = false)
|
||||
private Boolean errorAlertEnabled = true;
|
||||
|
||||
/**
|
||||
* Alerte échec de connexion activée
|
||||
*/
|
||||
@Column(name = "connection_failure_alert_enabled", nullable = false)
|
||||
private Boolean connectionFailureAlertEnabled = true;
|
||||
|
||||
/**
|
||||
* Seuil d'échecs de connexion
|
||||
*/
|
||||
@Column(name = "connection_failure_threshold", nullable = false)
|
||||
private Integer connectionFailureThreshold = 100;
|
||||
|
||||
/**
|
||||
* Fenêtre temporelle en minutes pour les échecs de connexion
|
||||
*/
|
||||
@Column(name = "connection_failure_window_minutes", nullable = false)
|
||||
private Integer connectionFailureWindowMinutes = 5;
|
||||
|
||||
/**
|
||||
* Notifications par email activées
|
||||
*/
|
||||
@Column(name = "email_notifications_enabled", nullable = false)
|
||||
private Boolean emailNotificationsEnabled = true;
|
||||
|
||||
/**
|
||||
* Notifications push activées
|
||||
*/
|
||||
@Column(name = "push_notifications_enabled", nullable = false)
|
||||
private Boolean pushNotificationsEnabled = false;
|
||||
|
||||
/**
|
||||
* Notifications SMS activées
|
||||
*/
|
||||
@Column(name = "sms_notifications_enabled", nullable = false)
|
||||
private Boolean smsNotificationsEnabled = false;
|
||||
|
||||
/**
|
||||
* Liste des emails destinataires des alertes (séparés par virgule)
|
||||
*/
|
||||
@Column(name = "alert_email_recipients", length = 1000)
|
||||
private String alertEmailRecipients = "admin@unionflow.test";
|
||||
|
||||
/**
|
||||
* S'assurer qu'il n'y a qu'une seule configuration
|
||||
*/
|
||||
@PrePersist
|
||||
@PreUpdate
|
||||
protected void ensureSingleton() {
|
||||
// La logique singleton sera gérée par le repository
|
||||
}
|
||||
}
|
||||
122
src/main/java/dev/lions/unionflow/server/entity/AlerteLcbFt.java
Normal file
122
src/main/java/dev/lions/unionflow/server/entity/AlerteLcbFt.java
Normal file
@@ -0,0 +1,122 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Entité représentant une alerte LCB-FT (Lutte Contre le Blanchiment et Financement du Terrorisme).
|
||||
* Les alertes sont générées automatiquement lors de transactions dépassant les seuils configurés.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2026-03-15
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "alertes_lcb_ft", indexes = {
|
||||
@Index(name = "idx_alerte_lcb_ft_organisation", columnList = "organisation_id"),
|
||||
@Index(name = "idx_alerte_lcb_ft_type", columnList = "type_alerte"),
|
||||
@Index(name = "idx_alerte_lcb_ft_date", columnList = "date_alerte"),
|
||||
@Index(name = "idx_alerte_lcb_ft_traitee", columnList = "traitee")
|
||||
})
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AlerteLcbFt extends BaseEntity {
|
||||
|
||||
/**
|
||||
* Organisation concernée par l'alerte
|
||||
*/
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "organisation_id", nullable = false)
|
||||
private Organisation organisation;
|
||||
|
||||
/**
|
||||
* Membre concerné par l'alerte
|
||||
*/
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "membre_id")
|
||||
private Membre membre;
|
||||
|
||||
/**
|
||||
* Type d'alerte : SEUIL_DEPASSE, JUSTIFICATION_MANQUANTE, etc.
|
||||
*/
|
||||
@Column(name = "type_alerte", nullable = false, length = 50)
|
||||
private String typeAlerte;
|
||||
|
||||
/**
|
||||
* Date et heure de génération de l'alerte
|
||||
*/
|
||||
@Column(name = "date_alerte", nullable = false)
|
||||
private LocalDateTime dateAlerte;
|
||||
|
||||
/**
|
||||
* Description de l'alerte
|
||||
*/
|
||||
@Column(name = "description", length = 500)
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* Détails supplémentaires (JSON ou texte)
|
||||
*/
|
||||
@Column(name = "details", columnDefinition = "TEXT")
|
||||
private String details;
|
||||
|
||||
/**
|
||||
* Montant de la transaction ayant généré l'alerte
|
||||
*/
|
||||
@Column(name = "montant", precision = 15, scale = 2)
|
||||
private BigDecimal montant;
|
||||
|
||||
/**
|
||||
* Seuil qui a été dépassé
|
||||
*/
|
||||
@Column(name = "seuil", precision = 15, scale = 2)
|
||||
private BigDecimal seuil;
|
||||
|
||||
/**
|
||||
* Type d'opération : DEPOT, RETRAIT, TRANSFERT, etc.
|
||||
*/
|
||||
@Column(name = "type_operation", length = 50)
|
||||
private String typeOperation;
|
||||
|
||||
/**
|
||||
* Référence de la transaction concernée (UUID)
|
||||
*/
|
||||
@Column(name = "transaction_ref", length = 100)
|
||||
private String transactionRef;
|
||||
|
||||
/**
|
||||
* Niveau de gravité : INFO, WARNING, CRITICAL
|
||||
*/
|
||||
@Column(name = "severite", nullable = false, length = 20)
|
||||
private String severite;
|
||||
|
||||
/**
|
||||
* Indique si l'alerte a été traitée
|
||||
*/
|
||||
@Column(name = "traitee", nullable = false)
|
||||
private Boolean traitee = false;
|
||||
|
||||
/**
|
||||
* Date de traitement de l'alerte
|
||||
*/
|
||||
@Column(name = "date_traitement")
|
||||
private LocalDateTime dateTraitement;
|
||||
|
||||
/**
|
||||
* Utilisateur ayant traité l'alerte
|
||||
*/
|
||||
@Column(name = "traite_par", length = 100)
|
||||
private String traitePar;
|
||||
|
||||
/**
|
||||
* Commentaire sur le traitement
|
||||
*/
|
||||
@Column(name = "commentaire_traitement", columnDefinition = "TEXT")
|
||||
private String commentaireTraitement;
|
||||
}
|
||||
118
src/main/java/dev/lions/unionflow/server/entity/SystemAlert.java
Normal file
118
src/main/java/dev/lions/unionflow/server/entity/SystemAlert.java
Normal file
@@ -0,0 +1,118 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Entité pour les alertes système.
|
||||
* Enregistre les alertes de seuils dépassés, erreurs critiques, etc.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2026-03-15
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "system_alerts", indexes = {
|
||||
@Index(name = "idx_system_alert_timestamp", columnList = "timestamp"),
|
||||
@Index(name = "idx_system_alert_level", columnList = "level"),
|
||||
@Index(name = "idx_system_alert_acknowledged", columnList = "acknowledged"),
|
||||
@Index(name = "idx_system_alert_source", columnList = "source")
|
||||
})
|
||||
@Getter
|
||||
@Setter
|
||||
public class SystemAlert extends BaseEntity {
|
||||
|
||||
/**
|
||||
* Niveau de l'alerte (CRITICAL, ERROR, WARNING, INFO)
|
||||
*/
|
||||
@Column(name = "level", nullable = false, length = 20)
|
||||
private String level;
|
||||
|
||||
/**
|
||||
* Titre court de l'alerte
|
||||
*/
|
||||
@Column(name = "title", nullable = false, length = 255)
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* Message détaillé de l'alerte
|
||||
*/
|
||||
@Column(name = "message", nullable = false, length = 1000)
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* Date/heure de création de l'alerte
|
||||
*/
|
||||
@Column(name = "timestamp", nullable = false)
|
||||
private LocalDateTime timestamp;
|
||||
|
||||
/**
|
||||
* Alerte acquittée ou non
|
||||
*/
|
||||
@Column(name = "acknowledged", nullable = false)
|
||||
private Boolean acknowledged = false;
|
||||
|
||||
/**
|
||||
* Email de l'utilisateur ayant acquitté l'alerte
|
||||
*/
|
||||
@Column(name = "acknowledged_by", length = 255)
|
||||
private String acknowledgedBy;
|
||||
|
||||
/**
|
||||
* Date/heure d'acquittement
|
||||
*/
|
||||
@Column(name = "acknowledged_at")
|
||||
private LocalDateTime acknowledgedAt;
|
||||
|
||||
/**
|
||||
* Source de l'alerte (CPU, MEMORY, DISK, DATABASE, etc.)
|
||||
*/
|
||||
@Column(name = "source", length = 100)
|
||||
private String source;
|
||||
|
||||
/**
|
||||
* Type d'alerte (THRESHOLD, INFO, ERROR, etc.)
|
||||
*/
|
||||
@Column(name = "alert_type", length = 50)
|
||||
private String alertType;
|
||||
|
||||
/**
|
||||
* Valeur actuelle ayant déclenché l'alerte
|
||||
*/
|
||||
@Column(name = "current_value")
|
||||
private Double currentValue;
|
||||
|
||||
/**
|
||||
* Valeur seuil dépassée
|
||||
*/
|
||||
@Column(name = "threshold_value")
|
||||
private Double thresholdValue;
|
||||
|
||||
/**
|
||||
* Unité de mesure (%, MB, GB, ms, etc.)
|
||||
*/
|
||||
@Column(name = "unit", length = 20)
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* Actions recommandées pour résoudre l'alerte
|
||||
*/
|
||||
@Column(name = "recommended_actions", columnDefinition = "TEXT")
|
||||
private String recommendedActions;
|
||||
|
||||
/**
|
||||
* Initialisation automatique du timestamp
|
||||
*/
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
if (timestamp == null) {
|
||||
timestamp = LocalDateTime.now();
|
||||
}
|
||||
if (acknowledged == null) {
|
||||
acknowledged = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user