mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-09-25 01:53:03 +02:00
(heure de dépôt was showing UTC) - feat: add date_depot column (real TFE deposit date) with CSV round-trip + Brussels→UTC sanitization - fix: keep PHP default tz at UTC to preserve token/share-link expiry consistency; convert to Brussels only in db_datetime()
130 lines
5.7 KiB
PHP
130 lines
5.7 KiB
PHP
<?php
|
|
/**
|
|
* Migration 044 — add `date_depot` column to `theses`.
|
|
*
|
|
* `submitted_at` was historically used as "when the record entered the system"
|
|
* (set to CURRENT_TIMESTAMP on create/CSV import). That conflates two concepts:
|
|
* the *system* submission time and the *student's* real TFE deposit date. When
|
|
* theses were bulk-imported via CSV, every imported row got stamped with the
|
|
* same CURRENT_TIMESTAMP, losing the real deposit date.
|
|
*
|
|
* This migration:
|
|
* 1. Adds a nullable `date_depot DATETIME` column to hold the real deposit date.
|
|
* 2. Backfills `date_depot` from `submitted_at` for theses that have not been
|
|
* bulk-imported (i.e. where submitted_at differs from the import time) —
|
|
* this is conservative: it copies the existing value so nothing is lost,
|
|
* while real per-thesis values must be re-supplied via a CSV import
|
|
* (or the admin edit form) since the bulk import already flattened them.
|
|
* 3. Recreates v_theses_full to expose the new column.
|
|
*
|
|
* Idempotent: safe to re-run (guards on existing column).
|
|
*/
|
|
|
|
defined('APP_ROOT') || define('APP_ROOT', dirname(__DIR__, 2));
|
|
defined('STORAGE_ROOT') || define('STORAGE_ROOT', APP_ROOT . '/storage');
|
|
|
|
$dbPath = $argv[1] ?? (APP_ROOT . '/storage/xamxam.db');
|
|
if (!file_exists($dbPath)) {
|
|
echo "ERROR: database not found at $dbPath\n";
|
|
exit(1);
|
|
}
|
|
|
|
$pdo = new PDO('sqlite:' . $dbPath);
|
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
|
|
|
// 1. Add the column if missing.
|
|
$cols = array_column($pdo->query("PRAGMA table_info(theses)")->fetchAll(), 'name');
|
|
if (!in_array('date_depot', $cols, true)) {
|
|
$pdo->exec("ALTER TABLE theses ADD COLUMN date_depot DATETIME");
|
|
echo "Added column theses.date_depot\n";
|
|
} else {
|
|
echo "Column theses.date_depot already present\n";
|
|
}
|
|
|
|
// 2. Backfill: for any thesis with a submitted_at but no date_depot, copy it.
|
|
// (Conservative — preserves the value so display still works; the real
|
|
// deposit date must be supplied via a later CSV import for bulk-imported rows.)
|
|
$updated = $pdo->exec(
|
|
"UPDATE theses SET date_depot = submitted_at WHERE date_depot IS NULL AND submitted_at IS NOT NULL"
|
|
);
|
|
echo "Backfilled date_depot from submitted_at for {$updated} row(s)\n";
|
|
|
|
// 3. Recreate v_theses_full so it exposes date_depot.
|
|
$pdo->exec("DROP VIEW IF EXISTS v_theses_full");
|
|
$pdo->exec(
|
|
"CREATE VIEW v_theses_full AS
|
|
SELECT
|
|
t.id,
|
|
t.identifier,
|
|
t.title,
|
|
t.subtitle,
|
|
t.year,
|
|
t.is_doctoral,
|
|
t.objet,
|
|
o.name as orientation,
|
|
ap.name as ap_program,
|
|
ft.name as finality_type,
|
|
t.synopsis,
|
|
t.context_note,
|
|
t.duration_pages,
|
|
t.duration_minutes,
|
|
t.has_annexes,
|
|
at.name as access_type,
|
|
lt.name as license_type,
|
|
t.license_id,
|
|
t.license_custom,
|
|
t.access_type_id,
|
|
t.jury_points,
|
|
t.submitted_at,
|
|
t.date_depot,
|
|
t.defense_date,
|
|
t.published_at,
|
|
t.is_published,
|
|
t.baiu_link,
|
|
t.exemplaire_baiu,
|
|
t.exemplaire_erg,
|
|
t.cc2r,
|
|
t.remarks,
|
|
t.jury_note_added,
|
|
t.contact_visible,
|
|
GROUP_CONCAT(DISTINCT a.name ORDER BY a.name ASC) as authors,
|
|
GROUP_CONCAT(DISTINCT s.name) as supervisors,
|
|
GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'president' THEN s.name END) as jury_president,
|
|
GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' AND ts.is_ulb = 0 THEN s.name END) as jury_promoteurs,
|
|
GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'promoteur' AND ts.is_ulb = 1 THEN s.name END) as jury_promoteurs_ulb,
|
|
GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' AND ts.is_external = 0 THEN s.name END) as jury_lecteurs_internes,
|
|
GROUP_CONCAT(DISTINCT CASE WHEN ts.role = 'lecteur' AND ts.is_external = 1 THEN s.name END) as jury_lecteurs_externes,
|
|
GROUP_CONCAT(DISTINCT l.name) as languages,
|
|
GROUP_CONCAT(DISTINCT fmt.name) as formats,
|
|
GROUP_CONCAT(DISTINCT tg.name) as keywords,
|
|
(SELECT a2.email FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as contact_interne,
|
|
(SELECT a2.show_contact FROM authors a2 JOIN thesis_authors ta2 ON a2.id = ta2.author_id WHERE ta2.thesis_id = t.id ORDER BY ta2.author_order LIMIT 1) as contact_public
|
|
FROM theses t
|
|
LEFT JOIN orientations o ON t.orientation_id = o.id
|
|
LEFT JOIN ap_programs ap ON t.ap_program_id = ap.id
|
|
LEFT JOIN finality_types ft ON t.finality_id = ft.id
|
|
LEFT JOIN access_types at ON t.access_type_id = at.id
|
|
LEFT JOIN license_types lt ON t.license_id = lt.id
|
|
LEFT JOIN thesis_authors ta ON t.id = ta.thesis_id
|
|
LEFT JOIN authors a ON ta.author_id = a.id
|
|
LEFT JOIN thesis_supervisors ts ON t.id = ts.thesis_id
|
|
LEFT JOIN supervisors s ON ts.supervisor_id = s.id
|
|
LEFT JOIN thesis_languages tl ON t.id = tl.thesis_id
|
|
LEFT JOIN languages l ON tl.language_id = l.id
|
|
LEFT JOIN thesis_formats tf ON t.id = tf.thesis_id
|
|
LEFT JOIN format_types fmt ON tf.format_id = fmt.id
|
|
LEFT JOIN thesis_tags tt ON t.id = tt.thesis_id
|
|
LEFT JOIN tags tg ON tt.tag_id = tg.id
|
|
GROUP BY t.id;"
|
|
);
|
|
echo "Recreated v_theses_full with date_depot\n";
|
|
|
|
// v_theses_public is SELECT * FROM v_theses_full, so it inherits the new column
|
|
// automatically; re-assert it in case the old view is still cached.
|
|
$pdo->exec("DROP VIEW IF EXISTS v_theses_public");
|
|
$pdo->exec("CREATE VIEW IF NOT EXISTS v_theses_public AS SELECT * FROM v_theses_full WHERE is_published = 1;");
|
|
echo "Recreated v_theses_public\n";
|
|
|
|
echo "Migration 044 complete.\n";
|