gitignore propre
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
package dev.lions.unionflow.server.api.dto.dashboard;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* DTO principal pour toutes les données du dashboard
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DashboardDataDTO {
|
||||
|
||||
@JsonProperty("stats")
|
||||
private DashboardStatsDTO stats;
|
||||
|
||||
@JsonProperty("recentActivities")
|
||||
private List<RecentActivityDTO> recentActivities;
|
||||
|
||||
@JsonProperty("upcomingEvents")
|
||||
private List<UpcomingEventDTO> upcomingEvents;
|
||||
|
||||
@JsonProperty("userPreferences")
|
||||
private Map<String, Object> userPreferences;
|
||||
|
||||
@JsonProperty("organizationId")
|
||||
private String organizationId;
|
||||
|
||||
@JsonProperty("userId")
|
||||
private String userId;
|
||||
|
||||
// Méthodes utilitaires
|
||||
public Integer getTodayEventsCount() {
|
||||
if (upcomingEvents == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) upcomingEvents.stream()
|
||||
.filter(event -> event.getIsToday() != null && event.getIsToday())
|
||||
.count();
|
||||
}
|
||||
|
||||
public Integer getTomorrowEventsCount() {
|
||||
if (upcomingEvents == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) upcomingEvents.stream()
|
||||
.filter(event -> event.getIsTomorrow() != null && event.getIsTomorrow())
|
||||
.count();
|
||||
}
|
||||
|
||||
public Integer getRecentActivitiesCount() {
|
||||
if (recentActivities == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) recentActivities.stream()
|
||||
.filter(activity -> activity.getIsRecent() != null && activity.getIsRecent())
|
||||
.count();
|
||||
}
|
||||
|
||||
public Integer getTodayActivitiesCount() {
|
||||
if (recentActivities == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) recentActivities.stream()
|
||||
.filter(activity -> activity.getIsToday() != null && activity.getIsToday())
|
||||
.count();
|
||||
}
|
||||
|
||||
public Boolean getHasUpcomingEvents() {
|
||||
return upcomingEvents != null && !upcomingEvents.isEmpty();
|
||||
}
|
||||
|
||||
public Boolean getHasRecentActivities() {
|
||||
return recentActivities != null && !recentActivities.isEmpty();
|
||||
}
|
||||
|
||||
public String getThemePreference() {
|
||||
if (userPreferences == null) {
|
||||
return "royal_teal";
|
||||
}
|
||||
return (String) userPreferences.getOrDefault("theme", "royal_teal");
|
||||
}
|
||||
|
||||
public String getLanguagePreference() {
|
||||
if (userPreferences == null) {
|
||||
return "fr";
|
||||
}
|
||||
return (String) userPreferences.getOrDefault("language", "fr");
|
||||
}
|
||||
|
||||
public Boolean getNotificationsEnabled() {
|
||||
if (userPreferences == null) {
|
||||
return true;
|
||||
}
|
||||
return (Boolean) userPreferences.getOrDefault("notifications", true);
|
||||
}
|
||||
|
||||
public Boolean getAutoRefreshEnabled() {
|
||||
if (userPreferences == null) {
|
||||
return true;
|
||||
}
|
||||
return (Boolean) userPreferences.getOrDefault("autoRefresh", true);
|
||||
}
|
||||
|
||||
public Integer getRefreshInterval() {
|
||||
if (userPreferences == null) {
|
||||
return 300; // 5 minutes par défaut
|
||||
}
|
||||
return (Integer) userPreferences.getOrDefault("refreshInterval", 300);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package dev.lions.unionflow.server.api.dto.dashboard;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* DTO pour les statistiques du dashboard
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DashboardStatsDTO {
|
||||
|
||||
@JsonProperty("totalMembers")
|
||||
private Integer totalMembers;
|
||||
|
||||
@JsonProperty("activeMembers")
|
||||
private Integer activeMembers;
|
||||
|
||||
@JsonProperty("totalEvents")
|
||||
private Integer totalEvents;
|
||||
|
||||
@JsonProperty("upcomingEvents")
|
||||
private Integer upcomingEvents;
|
||||
|
||||
@JsonProperty("totalContributions")
|
||||
private Integer totalContributions;
|
||||
|
||||
@JsonProperty("totalContributionAmount")
|
||||
private Double totalContributionAmount;
|
||||
|
||||
@JsonProperty("pendingRequests")
|
||||
private Integer pendingRequests;
|
||||
|
||||
@JsonProperty("completedProjects")
|
||||
private Integer completedProjects;
|
||||
|
||||
@JsonProperty("monthlyGrowth")
|
||||
private Double monthlyGrowth;
|
||||
|
||||
@JsonProperty("engagementRate")
|
||||
private Double engagementRate;
|
||||
|
||||
@JsonProperty("lastUpdated")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
|
||||
private LocalDateTime lastUpdated;
|
||||
|
||||
// Méthodes utilitaires
|
||||
public String getFormattedContributionAmount() {
|
||||
if (totalContributionAmount == null) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
if (totalContributionAmount >= 1_000_000) {
|
||||
return String.format("%.1fM", totalContributionAmount / 1_000_000);
|
||||
} else if (totalContributionAmount >= 1_000) {
|
||||
return String.format("%.0fK", totalContributionAmount / 1_000);
|
||||
} else {
|
||||
return String.format("%.0f", totalContributionAmount);
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean getHasGrowth() {
|
||||
return monthlyGrowth != null && monthlyGrowth > 0;
|
||||
}
|
||||
|
||||
public Boolean getIsHighEngagement() {
|
||||
return engagementRate != null && engagementRate > 0.7;
|
||||
}
|
||||
|
||||
public Double getInactiveMembers() {
|
||||
if (totalMembers == null || activeMembers == null) {
|
||||
return 0.0;
|
||||
}
|
||||
return (double) (totalMembers - activeMembers);
|
||||
}
|
||||
|
||||
public Double getActiveMemberPercentage() {
|
||||
if (totalMembers == null || activeMembers == null || totalMembers == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
return (double) activeMembers / totalMembers * 100;
|
||||
}
|
||||
|
||||
public Double getEngagementPercentage() {
|
||||
if (engagementRate == null) {
|
||||
return 0.0;
|
||||
}
|
||||
return engagementRate * 100;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package dev.lions.unionflow.server.api.dto.dashboard;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
/**
|
||||
* DTO pour les activités récentes du dashboard
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RecentActivityDTO {
|
||||
|
||||
@JsonProperty("id")
|
||||
private String id;
|
||||
|
||||
@JsonProperty("type")
|
||||
private String type;
|
||||
|
||||
@JsonProperty("title")
|
||||
private String title;
|
||||
|
||||
@JsonProperty("description")
|
||||
private String description;
|
||||
|
||||
@JsonProperty("userName")
|
||||
private String userName;
|
||||
|
||||
@JsonProperty("timestamp")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
|
||||
private LocalDateTime timestamp;
|
||||
|
||||
@JsonProperty("userAvatar")
|
||||
private String userAvatar;
|
||||
|
||||
@JsonProperty("actionUrl")
|
||||
private String actionUrl;
|
||||
|
||||
// Méthodes utilitaires
|
||||
public String getTimeAgo() {
|
||||
if (timestamp == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
long minutes = ChronoUnit.MINUTES.between(timestamp, now);
|
||||
long hours = ChronoUnit.HOURS.between(timestamp, now);
|
||||
long days = ChronoUnit.DAYS.between(timestamp, now);
|
||||
|
||||
if (minutes < 60) {
|
||||
return minutes + "min";
|
||||
} else if (hours < 24) {
|
||||
return hours + "h";
|
||||
} else if (days < 7) {
|
||||
return days + "j";
|
||||
} else {
|
||||
long weeks = days / 7;
|
||||
return weeks + "sem";
|
||||
}
|
||||
}
|
||||
|
||||
public String getActivityIcon() {
|
||||
if (type == null) {
|
||||
return "help_outline";
|
||||
}
|
||||
|
||||
switch (type.toLowerCase()) {
|
||||
case "member":
|
||||
return "person";
|
||||
case "event":
|
||||
return "event";
|
||||
case "contribution":
|
||||
return "payment";
|
||||
case "organization":
|
||||
return "business";
|
||||
case "system":
|
||||
return "settings";
|
||||
default:
|
||||
return "info";
|
||||
}
|
||||
}
|
||||
|
||||
public String getActivityColor() {
|
||||
if (type == null) {
|
||||
return "#6B7280"; // grey
|
||||
}
|
||||
|
||||
switch (type.toLowerCase()) {
|
||||
case "member":
|
||||
return "#10B981"; // success
|
||||
case "event":
|
||||
return "#3B82F6"; // info
|
||||
case "contribution":
|
||||
return "#008B8B"; // teal blue
|
||||
case "organization":
|
||||
return "#4169E1"; // royal blue
|
||||
case "system":
|
||||
return "#6B7280"; // grey
|
||||
default:
|
||||
return "#6B7280"; // grey
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean getIsRecent() {
|
||||
if (timestamp == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
long hours = ChronoUnit.HOURS.between(timestamp, now);
|
||||
return hours < 24;
|
||||
}
|
||||
|
||||
public Boolean getIsToday() {
|
||||
if (timestamp == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
return timestamp.toLocalDate().equals(now.toLocalDate());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package dev.lions.unionflow.server.api.dto.dashboard;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* DTO pour les événements à venir du dashboard
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UpcomingEventDTO {
|
||||
|
||||
@JsonProperty("id")
|
||||
private String id;
|
||||
|
||||
@JsonProperty("title")
|
||||
private String title;
|
||||
|
||||
@JsonProperty("description")
|
||||
private String description;
|
||||
|
||||
@JsonProperty("startDate")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
|
||||
private LocalDateTime startDate;
|
||||
|
||||
@JsonProperty("endDate")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
|
||||
private LocalDateTime endDate;
|
||||
|
||||
@JsonProperty("location")
|
||||
private String location;
|
||||
|
||||
@JsonProperty("maxParticipants")
|
||||
private Integer maxParticipants;
|
||||
|
||||
@JsonProperty("currentParticipants")
|
||||
private Integer currentParticipants;
|
||||
|
||||
@JsonProperty("status")
|
||||
private String status;
|
||||
|
||||
@JsonProperty("imageUrl")
|
||||
private String imageUrl;
|
||||
|
||||
@JsonProperty("tags")
|
||||
private List<String> tags;
|
||||
|
||||
// Méthodes utilitaires
|
||||
public String getDaysUntilEvent() {
|
||||
if (startDate == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
long days = ChronoUnit.DAYS.between(now, startDate);
|
||||
long hours = ChronoUnit.HOURS.between(now, startDate);
|
||||
|
||||
if (days == 0) {
|
||||
if (hours < 0) {
|
||||
return "En cours";
|
||||
} else if (hours < 2) {
|
||||
return "Bientôt";
|
||||
} else {
|
||||
return "Aujourd'hui";
|
||||
}
|
||||
} else if (days == 1) {
|
||||
return "Demain";
|
||||
} else if (days < 7) {
|
||||
return "Dans " + days + " jours";
|
||||
} else {
|
||||
long weeks = days / 7;
|
||||
return "Dans " + weeks + " semaine" + (weeks > 1 ? "s" : "");
|
||||
}
|
||||
}
|
||||
|
||||
public Double getFillPercentage() {
|
||||
if (maxParticipants == null || currentParticipants == null || maxParticipants == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
return (double) currentParticipants / maxParticipants * 100;
|
||||
}
|
||||
|
||||
public Boolean getIsFull() {
|
||||
if (maxParticipants == null || currentParticipants == null) {
|
||||
return false;
|
||||
}
|
||||
return currentParticipants >= maxParticipants;
|
||||
}
|
||||
|
||||
public Boolean getIsAlmostFull() {
|
||||
Double fillPercentage = getFillPercentage();
|
||||
return fillPercentage >= 80.0 && fillPercentage < 100.0;
|
||||
}
|
||||
|
||||
public Boolean getIsToday() {
|
||||
if (startDate == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
return startDate.toLocalDate().equals(now.toLocalDate());
|
||||
}
|
||||
|
||||
public Boolean getIsTomorrow() {
|
||||
if (startDate == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
return startDate.toLocalDate().equals(now.toLocalDate().plusDays(1));
|
||||
}
|
||||
|
||||
public String getStatusColor() {
|
||||
if (status == null) {
|
||||
return "#6B7280"; // grey
|
||||
}
|
||||
|
||||
switch (status.toLowerCase()) {
|
||||
case "confirmed":
|
||||
return "#10B981"; // success
|
||||
case "open":
|
||||
return "#3B82F6"; // info
|
||||
case "cancelled":
|
||||
return "#EF4444"; // error
|
||||
case "postponed":
|
||||
return "#F59E0B"; // warning
|
||||
default:
|
||||
return "#6B7280"; // grey
|
||||
}
|
||||
}
|
||||
|
||||
public String getStatusLabel() {
|
||||
if (status == null) {
|
||||
return "Inconnu";
|
||||
}
|
||||
|
||||
switch (status.toLowerCase()) {
|
||||
case "confirmed":
|
||||
return "Confirmé";
|
||||
case "open":
|
||||
return "Ouvert";
|
||||
case "cancelled":
|
||||
return "Annulé";
|
||||
case "postponed":
|
||||
return "Reporté";
|
||||
default:
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getAvailableSpots() {
|
||||
if (maxParticipants == null || currentParticipants == null) {
|
||||
return 0;
|
||||
}
|
||||
return Math.max(0, maxParticipants - currentParticipants);
|
||||
}
|
||||
|
||||
public String getParticipationSummary() {
|
||||
if (maxParticipants == null || currentParticipants == null) {
|
||||
return "0/0 participants";
|
||||
}
|
||||
return currentParticipants + "/" + maxParticipants + " participants";
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import jakarta.validation.constraints.Past;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@@ -103,7 +104,7 @@ public class MembreDTO extends BaseDTO {
|
||||
|
||||
/** Identifiant de l'association à laquelle appartient le membre */
|
||||
@NotNull(message = "L'association est obligatoire")
|
||||
private Long associationId;
|
||||
private UUID associationId;
|
||||
|
||||
/** Nom de l'association (lecture seule) */
|
||||
private String associationNom;
|
||||
@@ -260,11 +261,11 @@ public class MembreDTO extends BaseDTO {
|
||||
this.statut = statut;
|
||||
}
|
||||
|
||||
public Long getAssociationId() {
|
||||
public UUID getAssociationId() {
|
||||
return associationId;
|
||||
}
|
||||
|
||||
public void setAssociationId(Long associationId) {
|
||||
public void setAssociationId(UUID associationId) {
|
||||
this.associationId = associationId;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package dev.lions.unionflow.server.api.service.dashboard;
|
||||
|
||||
import dev.lions.unionflow.server.api.dto.dashboard.DashboardDataDTO;
|
||||
import dev.lions.unionflow.server.api.dto.dashboard.DashboardStatsDTO;
|
||||
import dev.lions.unionflow.server.api.dto.dashboard.RecentActivityDTO;
|
||||
import dev.lions.unionflow.server.api.dto.dashboard.UpcomingEventDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Interface de service pour la gestion des données du dashboard
|
||||
*
|
||||
* <p>Cette interface définit le contrat pour récupérer les données du dashboard,
|
||||
* incluant les statistiques, activités récentes et événements à venir.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-15
|
||||
*/
|
||||
public interface DashboardService {
|
||||
|
||||
/**
|
||||
* Récupère toutes les données du dashboard pour une organisation et un utilisateur
|
||||
*
|
||||
* @param organizationId L'identifiant de l'organisation
|
||||
* @param userId L'identifiant de l'utilisateur
|
||||
* @return Les données complètes du dashboard
|
||||
*/
|
||||
DashboardDataDTO getDashboardData(String organizationId, String userId);
|
||||
|
||||
/**
|
||||
* Récupère uniquement les statistiques du dashboard
|
||||
*
|
||||
* @param organizationId L'identifiant de l'organisation
|
||||
* @param userId L'identifiant de l'utilisateur
|
||||
* @return Les statistiques du dashboard
|
||||
*/
|
||||
DashboardStatsDTO getDashboardStats(String organizationId, String userId);
|
||||
|
||||
/**
|
||||
* Récupère les activités récentes
|
||||
*
|
||||
* @param organizationId L'identifiant de l'organisation
|
||||
* @param userId L'identifiant de l'utilisateur
|
||||
* @param limit Le nombre maximum d'activités à retourner
|
||||
* @return La liste des activités récentes
|
||||
*/
|
||||
List<RecentActivityDTO> getRecentActivities(String organizationId, String userId, int limit);
|
||||
|
||||
/**
|
||||
* Récupère les événements à venir
|
||||
*
|
||||
* @param organizationId L'identifiant de l'organisation
|
||||
* @param userId L'identifiant de l'utilisateur
|
||||
* @param limit Le nombre maximum d'événements à retourner
|
||||
* @return La liste des événements à venir
|
||||
*/
|
||||
List<UpcomingEventDTO> getUpcomingEvents(String organizationId, String userId, int limit);
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import dev.lions.unionflow.server.api.dto.evenement.EvenementDTO;
|
||||
import dev.lions.unionflow.server.api.dto.solidarite.DemandeAideDTO;
|
||||
import dev.lions.unionflow.server.api.dto.solidarite.PropositionAideDTO;
|
||||
import dev.lions.unionflow.server.api.dto.solidarite.aide.AideDTO;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.evenement.PrioriteEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.StatutEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.TypeEvenementMetier;
|
||||
@@ -74,17 +74,7 @@ class CompilationTest {
|
||||
assertThat(proposition.getMontantMaximum()).isInstanceOf(BigDecimal.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test compilation AideDTO (deprecated)")
|
||||
void testCompilationAideDTO() {
|
||||
@SuppressWarnings("deprecation")
|
||||
AideDTO aide = new AideDTO();
|
||||
aide.setTitre("Test Aide");
|
||||
|
||||
// Test des méthodes métier
|
||||
assertThat(aide.getTypeAideLibelle()).isNotNull();
|
||||
assertThat(aide.getStatutLibelle()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test compilation ValidationConstants")
|
||||
|
||||
Reference in New Issue
Block a user