extended metadata on questionnaires
Some checks failed
PHPUnit / test (push) Has been cancelled

This commit is contained in:
2026-07-01 09:13:32 +02:00
parent e589b46a8a
commit 13119f300a
4 changed files with 78 additions and 13 deletions

View File

@ -13,7 +13,7 @@ if (defined('QDB_TEST_UPLOADS')) {
define('QDB_LOCK', QDB_UPLOADS_DIR . '/.qdb_lock');
}
define('QDB_SCHEMA', __DIR__ . '/schema.sql');
define('QDB_VERSION', 14);
define('QDB_VERSION', 15);
function qdb_table_exists(PDO $pdo, string $table): bool {
$stmt = $pdo->prepare(
@ -107,6 +107,33 @@ function qdb_apply_migrations(PDO $pdo, string $schemaSql): bool {
$pdo->exec("ALTER TABLE questionnaire_submission ADD COLUMN structureSnapshotJson TEXT NOT NULL DEFAULT '{}'");
$changed = true;
}
if (!qdb_column_exists($pdo, 'questionnaire_submission', 'programCycleNumber')) {
$pdo->exec('ALTER TABLE questionnaire_submission ADD COLUMN programCycleNumber INTEGER');
$changed = true;
}
if (!qdb_column_exists($pdo, 'questionnaire_submission', 'programSessionID')) {
$pdo->exec('ALTER TABLE questionnaire_submission ADD COLUMN programSessionID TEXT');
$changed = true;
}
if (!qdb_column_exists($pdo, 'questionnaire_submission', 'programSessionNumber')) {
$pdo->exec('ALTER TABLE questionnaire_submission ADD COLUMN programSessionNumber INTEGER');
$changed = true;
}
}
if (qdb_table_exists($pdo, 'completed_questionnaire')) {
if (!qdb_column_exists($pdo, 'completed_questionnaire', 'programCycleNumber')) {
$pdo->exec('ALTER TABLE completed_questionnaire ADD COLUMN programCycleNumber INTEGER');
$changed = true;
}
if (!qdb_column_exists($pdo, 'completed_questionnaire', 'programSessionID')) {
$pdo->exec('ALTER TABLE completed_questionnaire ADD COLUMN programSessionID TEXT');
$changed = true;
}
if (!qdb_column_exists($pdo, 'completed_questionnaire', 'programSessionNumber')) {
$pdo->exec('ALTER TABLE completed_questionnaire ADD COLUMN programSessionNumber INTEGER');
$changed = true;
}
}
if (qdb_table_exists($pdo, 'questionnaire_structure_snapshot')

View File

@ -95,6 +95,16 @@ if ($method === 'POST') {
$startedAt = isset($body['startedAt']) ? (int)$body['startedAt'] : null;
$completedAt = isset($body['completedAt']) ? (int)$body['completedAt'] : null;
$programCycleNumber = isset($body['programCycleNumber']) ? (int)$body['programCycleNumber'] : null;
$programSessionID = isset($body['programSessionID'])
? trim((string)$body['programSessionID'])
: null;
if ($programSessionID === '') {
$programSessionID = null;
}
$programSessionNumber = isset($body['programSessionNumber'])
? (int)$body['programSessionNumber']
: null;
try {
$opened = qdb_open_write_or_fail();
@ -297,14 +307,21 @@ if ($method === 'POST') {
: qdb_compute_questionnaire_score($pdo, $clientCode, $qnID);
$pdo->prepare("
INSERT INTO completed_questionnaire (clientCode, questionnaireID, assignedByCoach, status, startedAt, completedAt, sumPoints)
VALUES (:cc, :qn, :abc, 'completed', :sa, :ca, :sp)
INSERT INTO completed_questionnaire (
clientCode, questionnaireID, assignedByCoach, status,
startedAt, completedAt, sumPoints,
programCycleNumber, programSessionID, programSessionNumber
)
VALUES (:cc, :qn, :abc, 'completed', :sa, :ca, :sp, :pcn, :psid, :psn)
ON CONFLICT(clientCode, questionnaireID) DO UPDATE SET
assignedByCoach = excluded.assignedByCoach,
status = 'completed',
startedAt = COALESCE(excluded.startedAt, startedAt),
completedAt = excluded.completedAt,
sumPoints = excluded.sumPoints
sumPoints = excluded.sumPoints,
programCycleNumber = COALESCE(excluded.programCycleNumber, programCycleNumber),
programSessionID = COALESCE(excluded.programSessionID, programSessionID),
programSessionNumber = COALESCE(excluded.programSessionNumber, programSessionNumber)
")->execute([
':cc' => $clientCode,
':qn' => $qnID,
@ -312,6 +329,9 @@ if ($method === 'POST') {
':sa' => $startedAt,
':ca' => $completedAt,
':sp' => $sumPoints,
':pcn' => $programCycleNumber,
':psid'=> $programSessionID,
':psn' => $programSessionNumber,
]);
require_once __DIR__ . '/../lib/submissions.php';
@ -326,7 +346,11 @@ if ($method === 'POST') {
$assignedByCoach,
$submitRev,
$submitManifest,
array_keys($submittedQuestionIds)
array_keys($submittedQuestionIds),
null,
$programCycleNumber,
$programSessionID,
$programSessionNumber
);
qdb_recompute_profile_scores_for_client($pdo, $clientCode, $qnID);

View File

@ -131,7 +131,10 @@ function qdb_record_submission_after_submit(
int $structureRevision = 1,
?array $structureManifest = null,
?array $questionIdsToCopy = null,
?int $submittedAt = null
?int $submittedAt = null,
?int $programCycleNumber = null,
?string $programSessionID = null,
?int $programSessionNumber = null
): string {
$version = qdb_next_submission_version($pdo, $clientCode, $questionnaireID);
$submissionID = bin2hex(random_bytes(16));
@ -155,11 +158,13 @@ function qdb_record_submission_after_submit(
submissionID, clientCode, questionnaireID, version, submittedAt,
submittedByUserID, submittedByRole, assignedByCoach,
status, startedAt, completedAt, sumPoints,
programCycleNumber, programSessionID, programSessionNumber,
structureRevision, structureSnapshotJson
) VALUES (
:sid, :cc, :qn, :ver, :sat,
:uid, :role, :abc,
:st, :sa, :ca, :sp,
:pcn, :psid, :psn,
:srev, :snap
)'
)->execute([
@ -175,6 +180,9 @@ function qdb_record_submission_after_submit(
':sa' => $startedAt,
':ca' => $completedAt,
':sp' => $sumPoints,
':pcn' => $programCycleNumber,
':psid' => $programSessionID,
':psn' => $programSessionNumber,
':srev' => max(1, $structureRevision),
':snap' => $snapshotJson,
]);

View File

@ -104,13 +104,16 @@ CREATE TABLE IF NOT EXISTS client_answer (
);
CREATE TABLE IF NOT EXISTS completed_questionnaire (
clientCode TEXT NOT NULL,
questionnaireID TEXT NOT NULL,
assignedByCoach TEXT,
status TEXT NOT NULL DEFAULT '',
startedAt INTEGER,
completedAt INTEGER,
sumPoints INTEGER,
clientCode TEXT NOT NULL,
questionnaireID TEXT NOT NULL,
assignedByCoach TEXT,
status TEXT NOT NULL DEFAULT '',
startedAt INTEGER,
completedAt INTEGER,
sumPoints INTEGER,
programCycleNumber INTEGER,
programSessionID TEXT,
programSessionNumber INTEGER,
PRIMARY KEY (clientCode, questionnaireID),
FOREIGN KEY(clientCode) REFERENCES client(clientCode),
FOREIGN KEY(questionnaireID) REFERENCES questionnaire(questionnaireID),
@ -168,6 +171,9 @@ CREATE TABLE IF NOT EXISTS questionnaire_submission (
startedAt INTEGER,
completedAt INTEGER,
sumPoints INTEGER,
programCycleNumber INTEGER,
programSessionID TEXT,
programSessionNumber INTEGER,
structureRevision INTEGER NOT NULL DEFAULT 1,
structureSnapshotJson TEXT NOT NULL DEFAULT '{}',
FOREIGN KEY(clientCode) REFERENCES client(clientCode),