implemented scoring system
Some checks failed
PHPUnit / test (push) Has been cancelled

This commit is contained in:
2026-06-08 19:10:23 +02:00
parent 4589be119c
commit 63adef79df
19 changed files with 2873 additions and 36 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', 6);
define('QDB_VERSION', 9);
function qdb_table_exists(PDO $pdo, string $table): bool {
$stmt = $pdo->prepare(
@ -126,6 +126,92 @@ function qdb_apply_migrations(PDO $pdo, string $schemaSql): bool {
$changed = true;
}
if (!qdb_table_exists($pdo, 'question_score_rule')) {
$pdo->exec("
CREATE TABLE question_score_rule (
ruleID TEXT NOT NULL PRIMARY KEY,
questionID TEXT NOT NULL,
scopeKey TEXT NOT NULL DEFAULT '',
levelKey TEXT NOT NULL,
points INTEGER NOT NULL DEFAULT 0,
FOREIGN KEY(questionID) REFERENCES question(questionID) ON DELETE CASCADE,
UNIQUE(questionID, scopeKey, levelKey)
)
");
$pdo->exec('CREATE INDEX IF NOT EXISTS idx_score_rule_question ON question_score_rule(questionID)');
$changed = true;
}
if (!qdb_table_exists($pdo, 'scoring_profile')) {
$pdo->exec("
CREATE TABLE scoring_profile (
profileID TEXT NOT NULL PRIMARY KEY,
name TEXT NOT NULL DEFAULT '',
description TEXT NOT NULL DEFAULT '',
isActive INTEGER NOT NULL DEFAULT 1,
greenMin INTEGER NOT NULL DEFAULT 0,
greenMax INTEGER NOT NULL DEFAULT 12,
yellowMin INTEGER NOT NULL DEFAULT 13,
yellowMax INTEGER NOT NULL DEFAULT 36,
redMin INTEGER NOT NULL DEFAULT 37,
createdAt INTEGER NOT NULL DEFAULT 0,
updatedAt INTEGER NOT NULL DEFAULT 0
)
");
$changed = true;
}
if (!qdb_table_exists($pdo, 'scoring_profile_questionnaire')) {
$pdo->exec("
CREATE TABLE scoring_profile_questionnaire (
profileID TEXT NOT NULL,
questionnaireID TEXT NOT NULL,
weight REAL NOT NULL DEFAULT 1.0,
orderIndex INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (profileID, questionnaireID),
FOREIGN KEY(profileID) REFERENCES scoring_profile(profileID) ON DELETE CASCADE,
FOREIGN KEY(questionnaireID) REFERENCES questionnaire(questionnaireID) ON DELETE CASCADE
)
");
$changed = true;
}
if (!qdb_table_exists($pdo, 'client_scoring_profile_result')) {
$pdo->exec("
CREATE TABLE client_scoring_profile_result (
clientCode TEXT NOT NULL,
profileID TEXT NOT NULL,
weightedTotal REAL NOT NULL DEFAULT 0,
band TEXT NOT NULL DEFAULT '',
computedAt INTEGER NOT NULL DEFAULT 0,
questionnaireSnapshot TEXT NOT NULL DEFAULT '{}',
coachBand TEXT NOT NULL DEFAULT '',
coachReviewedAt INTEGER NOT NULL DEFAULT 0,
coachReviewedByUserID TEXT NOT NULL DEFAULT '',
PRIMARY KEY (clientCode, profileID),
FOREIGN KEY(clientCode) REFERENCES client(clientCode) ON DELETE CASCADE,
FOREIGN KEY(profileID) REFERENCES scoring_profile(profileID) ON DELETE CASCADE
)
");
$pdo->exec('CREATE INDEX IF NOT EXISTS idx_client_profile_result_profile ON client_scoring_profile_result(profileID)');
$changed = true;
}
if (qdb_table_exists($pdo, 'client_scoring_profile_result')) {
if (!qdb_column_exists($pdo, 'client_scoring_profile_result', 'coachBand')) {
$pdo->exec("ALTER TABLE client_scoring_profile_result ADD COLUMN coachBand TEXT NOT NULL DEFAULT ''");
$changed = true;
}
if (!qdb_column_exists($pdo, 'client_scoring_profile_result', 'coachReviewedAt')) {
$pdo->exec('ALTER TABLE client_scoring_profile_result ADD COLUMN coachReviewedAt INTEGER NOT NULL DEFAULT 0');
$changed = true;
}
if (!qdb_column_exists($pdo, 'client_scoring_profile_result', 'coachReviewedByUserID')) {
$pdo->exec("ALTER TABLE client_scoring_profile_result ADD COLUMN coachReviewedByUserID TEXT NOT NULL DEFAULT ''");
$changed = true;
}
}
if (qdb_table_exists($pdo, 'questionnaire_submission')) {
require_once __DIR__ . '/lib/submissions.php';
if (qdb_backfill_submissions_from_live($pdo)) {
@ -133,6 +219,43 @@ function qdb_apply_migrations(PDO $pdo, string $schemaSql): bool {
}
}
$currentVersion = (int)$pdo->query('PRAGMA user_version')->fetchColumn();
if ($currentVersion < 7 && qdb_table_exists($pdo, 'question_score_rule')) {
require_once __DIR__ . '/lib/scoring.php';
if (qdb_backfill_glass_score_rules($pdo) > 0) {
$changed = true;
}
if (qdb_recompute_all_questionnaire_scores($pdo) > 0) {
$changed = true;
}
if (qdb_seed_default_rhs_scoring_profile($pdo) !== null) {
$changed = true;
}
}
$currentVersion = (int)$pdo->query('PRAGMA user_version')->fetchColumn();
if ($currentVersion < 8 && qdb_table_exists($pdo, 'scoring_profile')) {
if (!qdb_column_exists($pdo, 'scoring_profile', 'greenMin')) {
$pdo->exec('ALTER TABLE scoring_profile ADD COLUMN greenMin INTEGER NOT NULL DEFAULT 0');
$changed = true;
}
if (!qdb_column_exists($pdo, 'scoring_profile', 'yellowMin')) {
$pdo->exec('ALTER TABLE scoring_profile ADD COLUMN yellowMin INTEGER NOT NULL DEFAULT 13');
$changed = true;
}
if (!qdb_column_exists($pdo, 'scoring_profile', 'redMin')) {
$pdo->exec('ALTER TABLE scoring_profile ADD COLUMN redMin INTEGER NOT NULL DEFAULT 37');
$changed = true;
}
$pdo->exec(
'UPDATE scoring_profile SET
greenMin = COALESCE(greenMin, 0),
yellowMin = greenMax + 1,
redMin = yellowMax + 1'
);
$changed = true;
}
$currentVersion = (int)$pdo->query('PRAGMA user_version')->fetchColumn();
if ($currentVersion < 6 && qdb_table_exists($pdo, 'questionnaire_submission')) {
$pdo->exec(