Improve recap page + fix CSV import for jury roles

recapitulatif.php (partage):
- Center .thanks-success and add bottom margin/padding
- Display ALL fields: identifier, synopsis, languages, formats,
  jury (all roles), baiu link, license, access type
- Add validation notice asking user to verify info, with
  xamxam@erg.be contact link (email obfuscated)

StudentEmail:
- Add 'Note contextuelle' and license_custom to email recap
- Rename 'Promoteur·ice(s)' to 'Promoteur·ice(s) interne'
- Change email message to ask student to verify info + contact
  for errors

CSV export/import:
- Add 3 new CSV columns: Lecteur·ice(s) interne,
  Lecteur·ice(s) externe, Promoteur·ice(s) ULB
- Export splits supervisors by role/is_external/is_ulb into
  separate columns
- Import inserts supervisors with correct role, is_external,
  and is_ulb flags (was: all treated as generic supervisors)
- Add header matching for short distinguishers (ulb, externe)
  via str_contains fallback
This commit is contained in:
Pontoporeia
2026-05-10 22:36:28 +02:00
parent 8545daaccc
commit 406752bc6f
8 changed files with 208 additions and 30 deletions

View File

@@ -42,7 +42,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
$headerRowNum = 0;
$knownHeaders = [
'identifiant', 'titre', 'sous-titre', 'auteur', 'contact',
'promoteur', 'format', 'année', 'ap', 'orientation', 'finalité',
'promoteur', 'lecteur', 'ulb', 'externe', 'format', 'année', 'ap', 'orientation', 'finalité',
'mots-clés', 'synopsis', 'contexte', 'remarques', 'langue',
'autorisation', 'licence', 'license', 'points', 'lien baiu',
];
@@ -68,10 +68,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
// Avoid short prefixes matching unrelated words
if ($hlen >= 5 || $cell === $h) { $hits++; $map[$h] = $pos; $used[$pos] = true; break; }
}
// Substring match for short distinguishers (ulb, externe)
if ($hlen >= 3 && $hlen <= 7 && str_contains($cell, $h)) {
$hits++; $map[$h] = $pos; $used[$pos] = true; break;
}
}
}
// Require at least 8 known headers to trust the row.
if ($hits >= 8) { $colIdx = $map; break; }
// Require at least 11 known headers to trust the row.
if ($hits >= 11) { $colIdx = $map; break; }
}
// If no header row found, rewind and fall back to positional (skip 4 rows).
if ($colIdx === null) {
@@ -238,27 +242,30 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
if ($contact !== '' && in_array(strtoupper(trim($contact)), ['NON', 'OUI'], true)) {
$contact = '';
}
$supervisorsRaw = $cell($row, 'promoteur', 5);
$formatsRaw = $cell($row, 'format', 6);
$yearRaw = $cell($row, 'année', 7);
$supervisorsRaw = $cell($row, 'promoteur', 5);
$lecteursInternesRaw = $cell($row, 'lecteur', 6); // first "lecteur" col = interne
$lecteursExternesRaw = $cell($row, 'externe', 7); // contains "externe"
$promoteursUlbRaw = $cell($row, 'ulb', 8); // contains "ulb"
$formatsRaw = $cell($row, 'format', 9);
$yearRaw = $cell($row, 'année', 10);
$year = $yearRaw !== '' ? intval($yearRaw) : 0;
// Fallback: derive year from identifier (e.g. "2024-003" → 2024)
if ($year === 0 && $identifier !== '' && preg_match('/^(\d{4})-/', $identifier, $m)) {
$year = (int)$m[1];
}
$apCode = $cell($row, 'ap', 8);
$orientationCode = $cell($row, 'orientation', 9);
$finalityName = $cell($row, 'finalité', 10);
$keywordsRaw = $cell($row, 'mots-clés', 11);
$synopsis = $cell($row, 'synopsis', 12);
$context = $cell($row, 'contexte', 13);
$remarks = $cell($row, 'remarques', 14);
$languageRaw = $cell($row, 'langue', 15);
$access = $cell($row, 'autorisation', 16);
$license = $cell($row, 'license', 17);
$juryPointsRaw = $cell($row, 'points', 18);
$apCode = $cell($row, 'ap', 11);
$orientationCode = $cell($row, 'orientation', 12);
$finalityName = $cell($row, 'finalité', 13);
$keywordsRaw = $cell($row, 'mots-clés', 14);
$synopsis = $cell($row, 'synopsis', 15);
$context = $cell($row, 'contexte', 16);
$remarks = $cell($row, 'remarques', 17);
$languageRaw = $cell($row, 'langue', 18);
$access = $cell($row, 'autorisation', 19);
$license = $cell($row, 'license', 20);
$juryPointsRaw = $cell($row, 'points', 21);
$juryPoints = $juryPointsRaw !== '' ? floatval($juryPointsRaw) : null;
$baiuLink = $cell($row, 'lien baiu', 19);
$baiuLink = $cell($row, 'lien baiu', 22);
if ($title === '' || $year === 0) {
$missing = [];
@@ -328,12 +335,49 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
}
}
}
// Insert supervisors with proper role/is_external/is_ulb flags
$juryOrder = 0;
// Promoteurs internes
if (!empty($supervisorsRaw)) {
foreach (array_map('trim', explode(',', $supervisorsRaw)) as $idx => $name) {
foreach (array_map('trim', explode(',', $supervisorsRaw)) as $name) {
if ($name) {
$juryOrder++;
$sId = $importDb->findOrCreateSupervisor($name);
$s = $importPdo->prepare("INSERT INTO thesis_supervisors (thesis_id, supervisor_id, supervisor_order) VALUES (?,?,?)");
$s->execute([$thesisId, $sId, $idx + 1]);
$stmt = $importPdo->prepare("INSERT INTO thesis_supervisors (thesis_id, supervisor_id, role, is_external, is_ulb, supervisor_order) VALUES (?,?,?,?,?,?)");
$stmt->execute([$thesisId, $sId, 'promoteur', 0, 0, $juryOrder]);
}
}
}
// Lecteurs internes
if (!empty($lecteursInternesRaw)) {
foreach (array_map('trim', explode(',', $lecteursInternesRaw)) as $name) {
if ($name) {
$juryOrder++;
$sId = $importDb->findOrCreateSupervisor($name);
$stmt = $importPdo->prepare("INSERT INTO thesis_supervisors (thesis_id, supervisor_id, role, is_external, is_ulb, supervisor_order) VALUES (?,?,?,?,?,?)");
$stmt->execute([$thesisId, $sId, 'lecteur', 0, 0, $juryOrder]);
}
}
}
// Lecteurs externes
if (!empty($lecteursExternesRaw)) {
foreach (array_map('trim', explode(',', $lecteursExternesRaw)) as $name) {
if ($name) {
$juryOrder++;
$sId = $importDb->findOrCreateSupervisor($name);
$stmt = $importPdo->prepare("INSERT INTO thesis_supervisors (thesis_id, supervisor_id, role, is_external, is_ulb, supervisor_order) VALUES (?,?,?,?,?,?)");
$stmt->execute([$thesisId, $sId, 'lecteur', 1, 0, $juryOrder]);
}
}
}
// Promoteurs ULB
if (!empty($promoteursUlbRaw)) {
foreach (array_map('trim', explode(',', $promoteursUlbRaw)) as $name) {
if ($name) {
$juryOrder++;
$sId = $importDb->findOrCreateSupervisor($name);
$stmt = $importPdo->prepare("INSERT INTO thesis_supervisors (thesis_id, supervisor_id, role, is_external, is_ulb, supervisor_order) VALUES (?,?,?,?,?,?)");
$stmt->execute([$thesisId, $sId, 'promoteur', 1, 1, $juryOrder]);
}
}
}