Version OK

This commit is contained in:
dahoud
2025-10-05 14:26:15 +00:00
parent 291847924c
commit 8cec643361
7 changed files with 77 additions and 100 deletions

View File

@@ -38,8 +38,12 @@ class DioClient {
onRequest: (options, handler) async { onRequest: (options, handler) async {
// Ajouter le token d'authentification si disponible // Ajouter le token d'authentification si disponible
final token = await _secureStorage.read(key: 'keycloak_webview_access_token'); final token = await _secureStorage.read(key: 'keycloak_webview_access_token');
print('🔑 Token: ${token != null ? "EXISTS (${token.length} chars)" : "NULL"}');
if (token != null) { if (token != null) {
options.headers['Authorization'] = 'Bearer $token'; options.headers['Authorization'] = 'Bearer $token';
print('✅ Authorization header added');
} else {
print('❌ No token available');
} }
handler.next(options); handler.next(options);
}, },
@@ -63,17 +67,17 @@ class DioClient {
}, },
)); ));
// Logger pour le développement (désactivé en production) // Logger pour le développement
// _dio.interceptors.add( _dio.interceptors.add(
// LogInterceptor( LogInterceptor(
// requestHeader: true, requestHeader: true,
// requestBody: true, requestBody: true,
// responseBody: true, responseBody: true,
// responseHeader: false, responseHeader: false,
// error: true, error: true,
// logPrint: (obj) => print('DIO: $obj'), logPrint: (obj) => print('🔵 DIO: $obj'),
// ), ),
// ); );
} }
/// Rafraîchit le token d'authentification /// Rafraîchit le token d'authentification

View File

@@ -61,7 +61,7 @@ enum PrioriteEvenement {
@JsonSerializable() @JsonSerializable()
class EvenementModel extends Equatable { class EvenementModel extends Equatable {
/// Identifiant unique /// Identifiant unique
final String? id; final int? id;
/// Titre de l'événement /// Titre de l'événement
final String titre; final String titre;
@@ -106,7 +106,7 @@ class EvenementModel extends Equatable {
/// ID de l'organisateur /// ID de l'organisateur
@JsonKey(name: 'organisateurId') @JsonKey(name: 'organisateurId')
final String? organisateurId; final int? organisateurId;
/// Nom de l'organisateur (pour affichage) /// Nom de l'organisateur (pour affichage)
@JsonKey(name: 'organisateurNom') @JsonKey(name: 'organisateurNom')
@@ -114,7 +114,7 @@ class EvenementModel extends Equatable {
/// ID de l'organisation /// ID de l'organisation
@JsonKey(name: 'organisationId') @JsonKey(name: 'organisationId')
final String? organisationId; final int? organisationId;
/// Nom de l'organisation (pour affichage) /// Nom de l'organisation (pour affichage)
@JsonKey(name: 'organisationNom') @JsonKey(name: 'organisationNom')
@@ -203,7 +203,7 @@ class EvenementModel extends Equatable {
/// Copie avec modifications /// Copie avec modifications
EvenementModel copyWith({ EvenementModel copyWith({
String? id, int? id,
String? titre, String? titre,
String? description, String? description,
DateTime? dateDebut, DateTime? dateDebut,
@@ -216,9 +216,9 @@ class EvenementModel extends Equatable {
StatutEvenement? statut, StatutEvenement? statut,
int? maxParticipants, int? maxParticipants,
int? participantsActuels, int? participantsActuels,
String? organisateurId, int? organisateurId,
String? organisateurNom, String? organisateurNom,
String? organisationId, int? organisationId,
String? organisationNom, String? organisationNom,
PrioriteEvenement? priorite, PrioriteEvenement? priorite,
bool? estPublic, bool? estPublic,

View File

@@ -8,7 +8,7 @@ part of 'evenement_model.dart';
EvenementModel _$EvenementModelFromJson(Map<String, dynamic> json) => EvenementModel _$EvenementModelFromJson(Map<String, dynamic> json) =>
EvenementModel( EvenementModel(
id: json['id'] as String?, id: (json['id'] as num?)?.toInt(),
titre: json['titre'] as String, titre: json['titre'] as String,
description: json['description'] as String?, description: json['description'] as String?,
dateDebut: DateTime.parse(json['dateDebut'] as String), dateDebut: DateTime.parse(json['dateDebut'] as String),
@@ -23,9 +23,9 @@ EvenementModel _$EvenementModelFromJson(Map<String, dynamic> json) =>
StatutEvenement.planifie, StatutEvenement.planifie,
maxParticipants: (json['maxParticipants'] as num?)?.toInt(), maxParticipants: (json['maxParticipants'] as num?)?.toInt(),
participantsActuels: (json['participantsActuels'] as num?)?.toInt() ?? 0, participantsActuels: (json['participantsActuels'] as num?)?.toInt() ?? 0,
organisateurId: json['organisateurId'] as String?, organisateurId: (json['organisateurId'] as num?)?.toInt(),
organisateurNom: json['organisateurNom'] as String?, organisateurNom: json['organisateurNom'] as String?,
organisationId: json['organisationId'] as String?, organisationId: (json['organisationId'] as num?)?.toInt(),
organisationNom: json['organisationNom'] as String?, organisationNom: json['organisationNom'] as String?,
priorite: priorite:
$enumDecodeNullable(_$PrioriteEvenementEnumMap, json['priorite']) ?? $enumDecodeNullable(_$PrioriteEvenementEnumMap, json['priorite']) ??

View File

@@ -0,0 +1,27 @@
-- Script de configuration PostgreSQL pour UnionFlow
-- Exécuter en tant que superuser (postgres)
-- Créer l'utilisateur unionflow s'il n'existe pas
DO $$
BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_user WHERE usename = 'unionflow') THEN
CREATE USER unionflow WITH PASSWORD 'unionflow123';
END IF;
END
$$;
-- Créer la base de données unionflow si elle n'existe pas
SELECT 'CREATE DATABASE unionflow OWNER unionflow'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'unionflow')\gexec
-- Donner tous les privilèges à l'utilisateur unionflow
GRANT ALL PRIVILEGES ON DATABASE unionflow TO unionflow;
-- Se connecter à la base unionflow et donner les privilèges sur le schéma public
\c unionflow
GRANT ALL ON SCHEMA public TO unionflow;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO unionflow;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO unionflow;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO unionflow;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO unionflow;

View File

@@ -64,74 +64,19 @@ public class EvenementResource {
.build(); .build();
} }
/** Endpoint de debug pour vérifier le chargement des données */
/** Endpoint temporaire pour les événements à venir (sans authentification) */
@GET @GET
@Path("/a-venir-public") @Path("/count")
@Operation( @Operation(summary = "Compter les événements", description = "Compte le nombre d'événements dans la base")
summary = "Événements à venir (public)", @APIResponse(responseCode = "200", description = "Nombre d'événements")
description = "Liste des événements à venir sans authentification") public Response countEvenements() {
@APIResponse(responseCode = "200", description = "Liste des événements")
public Response getEvenementsAVenirPublic(
@QueryParam("page") @DefaultValue("0") @Min(0) int page,
@QueryParam("size") @DefaultValue("10") @Min(1) int size) {
try { try {
LOG.infof("GET /api/evenements/a-venir-public - page: %d, size: %d", page, size); long count = Evenement.count();
return Response.ok(Map.of("count", count, "status", "success")).build();
// Créer des données de test pour l'application mobile (format List direct)
List<Map<String, Object>> evenements = new ArrayList<>();
Map<String, Object> event1 = new HashMap<>();
event1.put("id", "1");
event1.put("titre", "Assemblée Générale 2025");
event1.put("description", "Assemblée générale annuelle de l'union");
event1.put("dateDebut", "2025-02-15T09:00:00");
event1.put("dateFin", "2025-02-15T17:00:00");
event1.put("lieu", "Salle de conférence principale");
event1.put("statut", "PLANIFIE");
event1.put("typeEvenement", "ASSEMBLEE_GENERALE");
event1.put("inscriptionRequise", false);
event1.put("visiblePublic", true);
event1.put("actif", true);
evenements.add(event1);
Map<String, Object> event2 = new HashMap<>();
event2.put("id", "2");
event2.put("titre", "Formation Gestion Financière");
event2.put("description", "Formation sur la gestion financière des unions");
event2.put("dateDebut", "2025-02-20T14:00:00");
event2.put("dateFin", "2025-02-20T18:00:00");
event2.put("lieu", "Centre de formation");
event2.put("statut", "PLANIFIE");
event2.put("typeEvenement", "FORMATION");
event2.put("inscriptionRequise", true);
event2.put("visiblePublic", true);
event2.put("actif", true);
evenements.add(event2);
Map<String, Object> event3 = new HashMap<>();
event3.put("id", "3");
event3.put("titre", "Réunion Mensuelle");
event3.put("description", "Réunion mensuelle des membres");
event3.put("dateDebut", "2025-02-25T19:00:00");
event3.put("dateFin", "2025-02-25T21:00:00");
event3.put("lieu", "Siège de l'union");
event3.put("statut", "PLANIFIE");
event3.put("typeEvenement", "REUNION");
event3.put("inscriptionRequise", false);
event3.put("visiblePublic", true);
event3.put("actif", true);
evenements.add(event3);
// Retourner directement la liste (pas d'objet de pagination)
return Response.ok(evenements).build();
} catch (Exception e) { } catch (Exception e) {
LOG.errorf("Erreur lors de la récupération des événements publics: %s", e.getMessage()); LOG.errorf("Erreur count: %s", e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR) return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des événements")) .entity(Map.of("error", e.getMessage()))
.build(); .build();
} }
} }
@@ -143,7 +88,7 @@ public class EvenementResource {
description = "Récupère la liste paginée des événements actifs") description = "Récupère la liste paginée des événements actifs")
@APIResponse(responseCode = "200", description = "Liste des événements actifs") @APIResponse(responseCode = "200", description = "Liste des événements actifs")
@APIResponse(responseCode = "401", description = "Non authentifié") @APIResponse(responseCode = "401", description = "Non authentifié")
@RolesAllowed({"ADMIN", "PRESIDENT", "SECRETAIRE", "ORGANISATEUR_EVENEMENT", "MEMBRE"}) // @RolesAllowed({"ADMIN", "PRESIDENT", "SECRETAIRE", "ORGANISATEUR_EVENEMENT", "MEMBRE"}) // Temporairement désactivé
public Response listerEvenements( public Response listerEvenements(
@Parameter(description = "Numéro de page (0-based)", example = "0") @Parameter(description = "Numéro de page (0-based)", example = "0")
@QueryParam("page") @QueryParam("page")

View File

@@ -74,11 +74,12 @@ quarkus.log.category."io.quarkus".level=INFO
# ======================================== # ========================================
# Profil de développement # Profil de développement
%dev.quarkus.datasource.db-kind=h2 %dev.quarkus.datasource.db-kind=postgresql
%dev.quarkus.datasource.username=sa %dev.quarkus.datasource.username=skyfile
%dev.quarkus.datasource.password= %dev.quarkus.datasource.password=skyfile
%dev.quarkus.datasource.jdbc.url=jdbc:h2:mem:unionflow_dev;DB_CLOSE_DELAY=-1;MODE=PostgreSQL %dev.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/unionflow
%dev.quarkus.hibernate-orm.database.generation=drop-and-create %dev.quarkus.hibernate-orm.database.generation=drop-and-create
%dev.quarkus.hibernate-orm.sql-load-script=import.sql
%dev.quarkus.hibernate-orm.log.sql=true %dev.quarkus.hibernate-orm.log.sql=true
%dev.quarkus.flyway.migrate-at-start=false %dev.quarkus.flyway.migrate-at-start=false
%dev.quarkus.log.category."dev.lions.unionflow".level=DEBUG %dev.quarkus.log.category."dev.lions.unionflow".level=DEBUG

View File

@@ -41,17 +41,17 @@ INSERT INTO cotisations (id, numero_reference, membre_id, type_cotisation, monta
(15, 'COT-2024-015', 7, 'MENSUELLE', 25000.00, 0.00, 'EN_RETARD', '2024-09-30', '2024-09-01 10:00:00', 'Septembre 2024', 'Cotisation mensuelle septembre', 2024, 9, 'XOF', true, 4); (15, 'COT-2024-015', 7, 'MENSUELLE', 25000.00, 0.00, 'EN_RETARD', '2024-09-30', '2024-09-01 10:00:00', 'Septembre 2024', 'Cotisation mensuelle septembre', 2024, 9, 'XOF', true, 4);
-- Insertion d'événements initiaux -- Insertion d'événements initiaux
INSERT INTO evenements (titre, description, date_debut, date_fin, lieu, adresse, type_evenement, statut, capacite_max, prix, inscription_requise, date_limite_inscription, instructions_particulieres, contact_organisateur, visible_public, actif, date_creation) VALUES INSERT INTO evenements (id, titre, description, date_debut, date_fin, lieu, adresse, type_evenement, statut, capacite_max, prix, inscription_requise, date_limite_inscription, instructions_particulieres, contact_organisateur, visible_public, actif, date_creation) VALUES
('Assemblée Générale Annuelle 2025', 'Assemblée générale annuelle de l''union pour présenter le bilan de l''année et les perspectives futures.', '2025-11-15 09:00:00', '2025-11-15 17:00:00', 'Salle de Conférence du Palais des Congrès', 'Boulevard de la République, Abidjan', 'ASSEMBLEE_GENERALE', 'PLANIFIE', 200, 0.00, true, '2025-11-10 23:59:59', 'Merci de confirmer votre présence avant le 10 novembre. Tenue formelle exigée.', 'secretariat@unionflow.ci', true, true, '2024-01-01 10:00:00'), (1, 'Assemblee Generale Annuelle 2025', 'Assemblee generale annuelle de l''union pour presenter le bilan de l''annee et les perspectives futures.', '2025-11-15 09:00:00', '2025-11-15 17:00:00', 'Salle de Conference du Palais des Congres', 'Boulevard de la Republique, Abidjan', 'ASSEMBLEE_GENERALE', 'PLANIFIE', 200, 0.00, true, '2025-11-10 23:59:59', 'Merci de confirmer votre presence avant le 10 novembre. Tenue formelle exigee.', 'secretariat@unionflow.ci', true, true, '2024-01-01 10:00:00'),
('Formation Leadership et Gestion d''Équipe', 'Formation intensive sur les techniques de leadership moderne et la gestion d''équipe efficace.', '2025-10-20 08:00:00', '2025-10-22 18:00:00', 'Centre de Formation Lions', 'Cocody, Abidjan', 'FORMATION', 'CONFIRME', 50, 25000.00, true, '2025-10-15 23:59:59', 'Formation sur 3 jours. Hébergement et restauration inclus. Apporter un ordinateur portable.', 'formation@unionflow.ci', true, true, '2024-01-01 10:00:00'), (2, 'Formation Leadership et Gestion d''Equipe', 'Formation intensive sur les techniques de leadership moderne et la gestion d''equipe efficace.', '2025-10-20 08:00:00', '2025-10-22 18:00:00', 'Centre de Formation Lions', 'Cocody, Abidjan', 'FORMATION', 'CONFIRME', 50, 25000.00, true, '2025-10-15 23:59:59', 'Formation sur 3 jours. Hebergement et restauration inclus. Apporter un ordinateur portable.', 'formation@unionflow.ci', true, true, '2024-01-01 10:00:00'),
('Conférence sur la Santé Communautaire', 'Conférence avec des experts de la santé sur les enjeux de santé publique en Côte d''Ivoire.', '2025-10-25 14:00:00', '2025-10-25 18:00:00', 'Auditorium de l''Université', 'Cocody, Abidjan', 'CONFERENCE', 'PLANIFIE', 300, 0.00, false, null, 'Entrée libre. Certificat de participation disponible.', 'sante@unionflow.ci', true, true, '2024-01-01 10:00:00'), (3, 'Conference sur la Sante Communautaire', 'Conference avec des experts de la sante sur les enjeux de sante publique en Cote d''Ivoire.', '2025-10-25 14:00:00', '2025-10-25 18:00:00', 'Auditorium de l''Universite', 'Cocody, Abidjan', 'CONFERENCE', 'PLANIFIE', 300, 0.00, false, null, 'Entree libre. Certificat de participation disponible.', 'sante@unionflow.ci', true, true, '2024-01-01 10:00:00'),
('Atelier Développement Personnel', 'Atelier pratique sur le développement personnel et la gestion du stress.', '2025-11-05 09:00:00', '2025-11-05 13:00:00', 'Salle Polyvalente', 'Plateau, Abidjan', 'ATELIER', 'PLANIFIE', 30, 5000.00, true, '2025-11-01 23:59:59', 'Places limitées. Inscription obligatoire.', 'ateliers@unionflow.ci', true, true, '2024-01-01 10:00:00'), (4, 'Atelier Developpement Personnel', 'Atelier pratique sur le developpement personnel et la gestion du stress.', '2025-11-05 09:00:00', '2025-11-05 13:00:00', 'Salle Polyvalente', 'Plateau, Abidjan', 'ATELIER', 'PLANIFIE', 30, 5000.00, true, '2025-11-01 23:59:59', 'Places limitees. Inscription obligatoire.', 'ateliers@unionflow.ci', true, true, '2024-01-01 10:00:00'),
('Soirée de Gala de Fin d''Année', 'Grande soirée de gala pour célébrer les réalisations de l''année et renforcer les liens entre membres.', '2025-12-20 19:00:00', '2025-12-20 23:59:59', 'Hôtel Ivoire', 'Cocody, Abidjan', 'EVENEMENT_SOCIAL', 'PLANIFIE', 150, 50000.00, true, '2025-12-10 23:59:59', 'Tenue de soirée obligatoire. Dîner et animations inclus.', 'gala@unionflow.ci', true, true, '2024-01-01 10:00:00'), (5, 'Soiree de Gala de Fin d''Annee', 'Grande soiree de gala pour celebrer les realisations de l''annee et renforcer les liens entre membres.', '2025-12-20 19:00:00', '2025-12-20 23:59:59', 'Hotel Ivoire', 'Cocody, Abidjan', 'EVENEMENT_SOCIAL', 'PLANIFIE', 150, 50000.00, true, '2025-12-10 23:59:59', 'Tenue de soiree obligatoire. Diner et animations inclus.', 'gala@unionflow.ci', true, true, '2024-01-01 10:00:00'),
('Réunion Mensuelle - Octobre 2025', 'Réunion mensuelle de coordination des activités et suivi des projets en cours.', '2025-10-10 18:00:00', '2025-10-10 20:00:00', 'Siège de l''Union', 'Plateau, Abidjan', 'REUNION', 'TERMINE', 40, 0.00, false, null, 'Réservé aux membres du bureau et responsables de commissions.', 'secretariat@unionflow.ci', false, true, '2024-01-01 10:00:00'), (6, 'Reunion Mensuelle - Octobre 2025', 'Reunion mensuelle de coordination des activites et suivi des projets en cours.', '2025-10-10 18:00:00', '2025-10-10 20:00:00', 'Siege de l''Union', 'Plateau, Abidjan', 'REUNION', 'TERMINE', 40, 0.00, false, null, 'Reserve aux membres du bureau et responsables de commissions.', 'secretariat@unionflow.ci', false, true, '2024-01-01 10:00:00'),
('Séminaire sur l''Entrepreneuriat Social', 'Séminaire de deux jours sur l''entrepreneuriat social et l''innovation au service de la communauté.', '2025-11-25 08:00:00', '2025-11-26 17:00:00', 'Centre d''Innovation', 'Yopougon, Abidjan', 'SEMINAIRE', 'PLANIFIE', 80, 15000.00, true, '2025-11-20 23:59:59', 'Séminaire sur 2 jours. Pause-café et déjeuner inclus. Supports de formation fournis.', 'entrepreneuriat@unionflow.ci', true, true, '2024-01-01 10:00:00'), (7, 'Seminaire sur l''Entrepreneuriat Social', 'Seminaire de deux jours sur l''entrepreneuriat social et l''innovation au service de la communaute.', '2025-11-25 08:00:00', '2025-11-26 17:00:00', 'Centre d''Innovation', 'Yopougon, Abidjan', 'SEMINAIRE', 'PLANIFIE', 80, 15000.00, true, '2025-11-20 23:59:59', 'Seminaire sur 2 jours. Pause-cafe et dejeuner inclus. Supports de formation fournis.', 'entrepreneuriat@unionflow.ci', true, true, '2024-01-01 10:00:00'),
('Journée Caritative - Soutien aux Écoles', 'Manifestation caritative pour collecter des fournitures scolaires et des dons pour les écoles défavorisées.', '2025-10-30 08:00:00', '2025-10-30 16:00:00', 'Place de la République', 'Plateau, Abidjan', 'MANIFESTATION', 'CONFIRME', 500, 0.00, false, null, 'Apportez vos dons de fournitures scolaires. Bénévoles bienvenus.', 'charite@unionflow.ci', true, true, '2024-01-01 10:00:00'), (8, 'Journee Caritative - Soutien aux Ecoles', 'Manifestation caritative pour collecter des fournitures scolaires et des dons pour les ecoles defavorisees.', '2025-10-30 08:00:00', '2025-10-30 16:00:00', 'Place de la Republique', 'Plateau, Abidjan', 'MANIFESTATION', 'CONFIRME', 500, 0.00, false, null, 'Apportez vos dons de fournitures scolaires. Benevoles bienvenus.', 'charite@unionflow.ci', true, true, '2024-01-01 10:00:00'),
('Célébration 50 ans de l''Union', 'Grande célébration pour les 50 ans d''existence de l''union avec spectacles et témoignages.', '2025-12-15 15:00:00', '2025-12-15 22:00:00', 'Stade Félix Houphouët-Boigny', 'Abidjan', 'CELEBRATION', 'PLANIFIE', 5000, 10000.00, true, '2025-12-01 23:59:59', 'Événement historique. Spectacles, animations, buffet. Tenue festive recommandée.', 'anniversaire@unionflow.ci', true, true, '2024-01-01 10:00:00'), (9, 'Celebration 50 ans de l''Union', 'Grande celebration pour les 50 ans d''existence de l''union avec spectacles et temoignages.', '2025-12-15 15:00:00', '2025-12-15 22:00:00', 'Stade Felix Houphouet-Boigny', 'Abidjan', 'CELEBRATION', 'PLANIFIE', 5000, 10000.00, true, '2025-12-01 23:59:59', 'Evenement historique. Spectacles, animations, buffet. Tenue festive recommandee.', 'anniversaire@unionflow.ci', true, true, '2024-01-01 10:00:00'),
('Journée Portes Ouvertes', 'Découvrez les activités de l''union et rencontrez nos membres. Activités pour toute la famille.', '2025-11-01 10:00:00', '2025-11-01 18:00:00', 'Siège de l''Union', 'Plateau, Abidjan', 'AUTRE', 'PLANIFIE', 1000, 0.00, false, null, 'Entrée libre. Animations, stands d''information, démonstrations.', 'info@unionflow.ci', true, true, '2024-01-01 10:00:00'); (10, 'Journee Portes Ouvertes', 'Decouvrez les activites de l''union et rencontrez nos membres. Activites pour toute la famille.', '2025-11-01 10:00:00', '2025-11-01 18:00:00', 'Siege de l''Union', 'Plateau, Abidjan', 'AUTRE', 'PLANIFIE', 1000, 0.00, false, null, 'Entree libre. Animations, stands d''information, demonstrations.', 'info@unionflow.ci', true, true, '2024-01-01 10:00:00');
-- Mise à jour des séquences pour éviter les conflits -- Mise à jour des séquences pour éviter les conflits
ALTER SEQUENCE membres_SEQ RESTART WITH 50; ALTER SEQUENCE membres_SEQ RESTART WITH 50;