Add thesis status column for two-phase commit lifecycle tracking

This commit is contained in:
Pontoporeia
2026-06-11 12:09:24 +02:00
parent 11a6f6a9f2
commit f4a3e26901
5 changed files with 47 additions and 7 deletions

View File

@@ -0,0 +1,14 @@
-- 039: Add a status column to theses to track submission lifecycle
--
-- Lifecycle:
-- draft — thesis row created, file operations not yet completed (or failed)
-- active — all file operations succeeded, submission is complete
--
-- Separate from is_published (visibility). The admin can filter drafts
-- to find orphaned/broken submissions and the cleanup-drafts job targets
-- status='draft' rows older than a threshold.
ALTER TABLE theses ADD COLUMN status TEXT NOT NULL DEFAULT 'active';
-- Existing theses already have files → they are active.
-- New theses start as draft and are promoted to active after file ops succeed.

View File

@@ -93,13 +93,14 @@ class ThesisCreateController
* recapitulatif.php?id=<n>. On validation or DB failure, throws an Exception
* (caller must flash the message and redirect back to the form).
*
* Execution order:
* Two-phase execution:
* 1. Validate + sanitise POST fields
* 2. Find/create author record
* 3. INSERT thesis row + link author (inside transaction)
* 3. INSERT thesis row (status='draft') + link author (inside transaction)
* 4. Link jury, languages, formats, tags (inside transaction)
* 5. COMMIT
* 5. COMMIT (thesis visible only as draft)
* 6. Handle file uploads: cover, thesis files (outside transaction)
* 7. UPDATE status to 'active' (confirms file operations succeeded)
*
* @param array $post Sanitised $_POST array.
* @param array $files $_FILES array.
@@ -226,6 +227,14 @@ class ThesisCreateController
// ── 6. Website URL — stored as thesis_files row ──────────────────────
$this->handleWebsiteUrl($thesisId, $post);
// ── 7. Two-phase commit: mark submission complete ──────────────────
// The thesis was committed as status='draft' before file operations.
// Now that all files are safely in place, promote to 'active'.
// If any file operation had thrown, the draft would remain orphaned
// for the periodic cleanup job (just cleanup-drafts).
$this->db->setThesisStatus($thesisId, 'active');
error_log("[ThesisCreate] ACTIVE — thesis_id=$thesisId | all file operations succeeded");
return $thesisId;
}

View File

@@ -1682,6 +1682,22 @@ class Database
Audit::log($this, Audit::actor(), 'UPDATE', 'theses', $thesisId, $old, $new);
}
/**
* Set the submission lifecycle status of a single thesis.
*
* Valid statuses: 'draft' (files not yet moved / failed) → 'active' (complete).
*/
public function setThesisStatus(int $thesisId, string $status): void
{
require_once __DIR__ . '/Audit.php';
$old = $this->fetchRow('theses', $thesisId);
$this->pdo->prepare(
'UPDATE theses SET status = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?'
)->execute([$status, $thesisId]);
$new = $this->fetchRow('theses', $thesisId);
Audit::log($this, Audit::actor(), 'UPDATE', 'theses', $thesisId, $old, $new);
}
/**
* Set the published state for multiple theses at once.
* @param int[] $thesisIds
@@ -2242,12 +2258,12 @@ class Database
baiu_link, license_id, license_custom,
access_type_id,
objet,
is_published,
is_published, status,
remarks, jury_points,
exemplaire_baiu, exemplaire_erg,
cc2r,
submitted_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, "draft", ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
');
$validObjet = ['tfe', 'thèse', 'frart'];

View File

@@ -97,6 +97,7 @@ CREATE TABLE IF NOT EXISTS theses (
defense_date DATETIME,
published_at DATETIME,
is_published BOOLEAN DEFAULT 0,
status TEXT NOT NULL DEFAULT 'active',
baiu_link TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,