Initial commit: Club DynaSQY

This commit is contained in:
2026-08-23 09:04:47 +00:00
commit 0875890dc7
145 changed files with 16947 additions and 0 deletions
+203
View File
@@ -0,0 +1,203 @@
const pool = require('../config/db');
exports.dashboard = async (req, res) => {
try {
const { filter } = req.query;
let dateCondition;
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
if (filter === 'year') {
dateCondition = `r.date >= '${year}-01-01'`;
} else if (filter === 'month') {
dateCondition = `r.date >= '${year}-${month}-01'`;
} else {
dateCondition = `r.date >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)`;
}
const nextEventPromise = pool.query(`
SELECT e.date, e.nom_evenement,
(SELECT COUNT(*) FROM invites WHERE date_club = e.date) AS invites,
(SELECT SUM(statut = 'acceptee') FROM invites WHERE date_club = e.date) AS acceptees,
(SELECT SUM(statut = 'refusee') FROM invites WHERE date_club = e.date) AS refusees,
(SELECT SUM(visit_number >= 2) FROM invites WHERE date_club = e.date) AS secondes_visites
FROM evenements e
WHERE e.nom_evenement = 'Club d''Affaires' AND e.date >= CURDATE()
ORDER BY e.date ASC LIMIT 1
`);
const honorsPromise = pool.query(
"SELECT mh.*, u.prenom, u.nom, u.societe AS membre_societe FROM mises_en_honneur mh LEFT JOIN users u ON u.id = mh.membre_id WHERE mh.date >= CURDATE() ORDER BY mh.date ASC LIMIT 5"
);
const eventsPromise = pool.query(
'SELECT * FROM evenements WHERE date >= CURDATE() ORDER BY date ASC LIMIT 3'
);
const recsPromise = pool.query(`
SELECT r.id, r.date, r.nom_prospect, r.type, r.transformee, r.ca_realise,
m.prenom AS membre_prenom, m.nom AS membre_nom,
d.prenom AS dest_prenom, d.nom AS dest_nom
FROM recommandations r
LEFT JOIN users m ON m.id = r.membre_id
LEFT JOIN users d ON d.id = r.destinataire_id
WHERE ${dateCondition}
ORDER BY r.date DESC
`);
const countPromise = pool.query(`
SELECT
COUNT(*) AS total,
SUM(CASE WHEN r.type='donnee' THEN 1 ELSE 0 END) AS donnees,
SUM(CASE WHEN r.type='recue' THEN 1 ELSE 0 END) AS recues,
SUM(r.transformee) AS transformees,
SUM(COALESCE(r.ca_realise,0)) AS ca_total
FROM recommandations r
WHERE ${dateCondition}
`);
const memberRecsPromise = pool.query(`
SELECT
u.id, u.prenom, u.nom, u.societe,
COUNT(r.id) AS total_recs,
SUM(r.transformee) AS total_transformees,
SUM(COALESCE(r.ca_realise,0)) AS total_ca
FROM users u
LEFT JOIN recommandations r ON r.membre_id = u.id AND ${dateCondition}
WHERE u.actif = 1
GROUP BY u.id
ORDER BY total_recs DESC
`);
const guestCountPromise = pool.query(`
SELECT i.invite_par_id, u.prenom, u.nom, COUNT(i.id) AS total_invites
FROM invites i
JOIN users u ON u.id = i.invite_par_id
WHERE i.date_club >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
GROUP BY i.invite_par_id, u.prenom, u.nom
ORDER BY total_invites DESC
`);
const echeancePromise = pool.query(
"SELECT id, prenom, nom, societe, date_echeance FROM users WHERE actif = 1 AND date_echeance IS NOT NULL AND date_echeance BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 30 DAY) ORDER BY date_echeance ASC"
);
const [nextEvent] = await nextEventPromise;
const [honors] = await honorsPromise;
const [events] = await eventsPromise;
const [recs] = await recsPromise;
const [counts] = await countPromise;
const [memberRecs] = await memberRecsPromise;
const [guestCounts] = await guestCountPromise;
const guestMetricsPromise = pool.query(`
SELECT
COUNT(*) AS total_invites,
SUM(CASE WHEN statut = 'acceptee' THEN 1 ELSE 0 END) AS acceptees,
SUM(CASE WHEN statut = 'refusee' THEN 1 ELSE 0 END) AS refusees,
SUM(CASE WHEN visit_number >= 2 THEN 1 ELSE 0 END) AS secondes_visites
FROM invites
`);
const [echeances] = await echeancePromise;
const [guestMetricsRows] = await guestMetricsPromise;
let top_absences = [];
if (req.user.role === 'admin') {
const [absRows] = await pool.query(`
SELECT u.id, u.prenom, u.nom, COUNT(a.id) AS total_absences
FROM users u
LEFT JOIN absences a ON a.membre_id = u.id
WHERE u.actif = 1
GROUP BY u.id
HAVING total_absences > 0
ORDER BY total_absences DESC
LIMIT 5
`);
top_absences = absRows;
}
let top_conversion = [];
const [convRows] = await pool.query(`
SELECT u.id, u.prenom, u.nom, COUNT(m.id) AS total_convertis
FROM users u
JOIN users m ON m.invite_par_id = u.id
WHERE u.actif = 1
GROUP BY u.id
ORDER BY total_convertis DESC
LIMIT 15
`);
top_conversion = convRows;
const [candRows] = await pool.query(
'SELECT id, prenom, nom, societe, created_at FROM invites WHERE statut_candidature = ? ORDER BY created_at DESC',
['candidature']
);
const candidatures = candRows;
const total = Number(counts[0].total) || 0;
const transformees = Number(counts[0].transformees) || 0;
const tauxTransformation = total > 0 ? ((transformees / total) * 100).toFixed(1) : 0;
const topDonnees = [...memberRecs].filter(m => m.total_recs > 0).sort((a, b) => b.total_recs - a.total_recs).slice(0, 15);
const topInvites = [...guestCounts].sort((a, b) => b.total_invites - a.total_invites).slice(0, 15);
const flopDonnees = [...memberRecs].sort((a, b) => a.total_recs - b.total_recs).slice(0, 5);
res.json({
prochaine_seance: nextEvent.length > 0 ? {
date: nextEvent[0].date,
nom: nextEvent[0].nom_evenement,
invites: Number(nextEvent[0].invites) || 0,
acceptees: Number(nextEvent[0].acceptees) || 0,
refusees: Number(nextEvent[0].refusees) || 0,
secondes_visites: Number(nextEvent[0].secondes_visites) || 0,
} : null,
counts: {
total,
donnees: Number(counts[0].donnees) || 0,
recues: Number(counts[0].recues) || 0,
transformees,
ca_total: Number(counts[0].ca_total) || 0,
taux_transformation: tauxTransformation,
},
top_donnees: topDonnees,
top_invites: topInvites,
flop_donnees: flopDonnees,
prochaines_honors: honors,
prochains_evenements: events,
alertes_echeance: echeances,
guest_metrics: {
total_invites: Number(guestMetricsRows[0].total_invites) || 0,
acceptees: Number(guestMetricsRows[0].acceptees) || 0,
refusees: Number(guestMetricsRows[0].refusees) || 0,
secondes_visites: Number(guestMetricsRows[0].secondes_visites) || 0,
},
top_absences,
top_conversion,
candidatures,
});
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Server error' });
}
};
exports.memberStats = async (req, res) => {
try {
const userId = req.params.id || req.user.id;
const [recs] = await pool.query(`
SELECT r.*, d.prenom AS dest_prenom, d.nom AS dest_nom
FROM recommandations r
LEFT JOIN users d ON d.id = r.destinataire_id
WHERE r.membre_id = ?
ORDER BY r.date DESC
`, [userId]);
const [guests] = await pool.query(
'SELECT * FROM invites WHERE invite_par_id = ? ORDER BY created_at DESC',
[userId]
);
res.json({ recommandations: recs, invites: guests });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Server error' });
}
};