new system prototype

This commit is contained in:
2026-04-15 10:19:42 +02:00
parent e805f225bc
commit 034b108c7e
80 changed files with 12212 additions and 890 deletions

139
api/results.php Normal file
View File

@ -0,0 +1,139 @@
<?php
require_once __DIR__ . '/../common.php';
require_once __DIR__ . '/../db_init.php';
header('Content-Type: application/json; charset=UTF-8');
$tokenRec = require_valid_token();
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
http_response_code(405);
echo json_encode(["error" => "Method not allowed"]);
exit;
}
$qnID = $_GET['questionnaireID'] ?? '';
$clientCode = $_GET['clientCode'] ?? '';
if (!$qnID) {
http_response_code(400);
echo json_encode(["error" => "questionnaireID query param required"]);
exit;
}
[$pdo, $tmpDb, $lockFp] = qdb_open(false);
// Questionnaire metadata
$qn = $pdo->prepare("SELECT * FROM questionnaire WHERE questionnaireID = :id");
$qn->execute([':id' => $qnID]);
$questionnaire = $qn->fetch(PDO::FETCH_ASSOC);
if (!$questionnaire) {
qdb_discard($tmpDb, $lockFp);
http_response_code(404);
echo json_encode(["error" => "Questionnaire not found"]);
exit;
}
// Questions with answer options
$qStmt = $pdo->prepare("
SELECT questionID, defaultText, type, orderIndex, isRequired
FROM question WHERE questionnaireID = :id ORDER BY orderIndex
");
$qStmt->execute([':id' => $qnID]);
$questions = $qStmt->fetchAll(PDO::FETCH_ASSOC);
$questionIDs = array_column($questions, 'questionID');
foreach ($questions as &$q) {
$q['isRequired'] = (int)$q['isRequired'];
$q['orderIndex'] = (int)$q['orderIndex'];
$ao = $pdo->prepare("SELECT answerOptionID, defaultText, points, orderIndex
FROM answer_option WHERE questionID = :qid ORDER BY orderIndex");
$ao->execute([':qid' => $q['questionID']]);
$q['answerOptions'] = $ao->fetchAll(PDO::FETCH_ASSOC);
foreach ($q['answerOptions'] as &$opt) {
$opt['points'] = (int)$opt['points'];
$opt['orderIndex'] = (int)$opt['orderIndex'];
}
}
unset($q);
// RBAC filter
[$rbacClause, $rbacParams] = rbac_client_filter($tokenRec, 'cl');
// Build client list
if ($clientCode) {
$clientSQL = "SELECT cl.clientCode, cl.coachID FROM client cl WHERE cl.clientCode = :cc AND $rbacClause";
$clientParams = array_merge([':cc' => $clientCode], $rbacParams);
} else {
$clientSQL = "SELECT cl.clientCode, cl.coachID FROM client cl WHERE $rbacClause";
$clientParams = $rbacParams;
}
// Only clients that have a completed_questionnaire entry for this questionnaire
$sql = "
SELECT cl.clientCode, cl.coachID,
cq.status, cq.startedAt, cq.completedAt, cq.sumPoints, cq.assignedByCoach
FROM client cl
INNER JOIN completed_questionnaire cq ON cq.clientCode = cl.clientCode AND cq.questionnaireID = :qnid
WHERE $rbacClause
";
$params = array_merge([':qnid' => $qnID], $rbacParams);
if ($clientCode) {
$sql .= " AND cl.clientCode = :cc";
$params[':cc'] = $clientCode;
}
$sql .= " ORDER BY cl.clientCode";
$cStmt = $pdo->prepare($sql);
$cStmt->execute($params);
$clients = $cStmt->fetchAll(PDO::FETCH_ASSOC);
// Build question ID placeholders for answer fetch
if (!empty($questionIDs) && !empty($clients)) {
$qPlaceholders = implode(',', array_fill(0, count($questionIDs), '?'));
$answerStmt = $pdo->prepare("
SELECT clientCode, questionID, answerOptionID, freeTextValue, numericValue, answeredAt
FROM client_answer
WHERE clientCode = ? AND questionID IN ($qPlaceholders)
");
foreach ($clients as &$c) {
$c['sumPoints'] = $c['sumPoints'] !== null ? (int)$c['sumPoints'] : null;
$c['startedAt'] = $c['startedAt'] !== null ? (int)$c['startedAt'] : null;
$c['completedAt'] = $c['completedAt'] !== null ? (int)$c['completedAt'] : null;
$bindParams = array_merge([$c['clientCode']], $questionIDs);
$answerStmt->execute($bindParams);
$answers = $answerStmt->fetchAll(PDO::FETCH_ASSOC);
$answerMap = [];
foreach ($answers as $a) {
$answerMap[$a['questionID']] = [
'answerOptionID' => $a['answerOptionID'],
'freeTextValue' => $a['freeTextValue'],
'numericValue' => $a['numericValue'] !== null ? (float)$a['numericValue'] : null,
'answeredAt' => $a['answeredAt'] !== null ? (int)$a['answeredAt'] : null,
];
}
$c['answers'] = $answerMap;
}
unset($c);
} else {
foreach ($clients as &$c) {
$c['sumPoints'] = $c['sumPoints'] !== null ? (int)$c['sumPoints'] : null;
$c['startedAt'] = $c['startedAt'] !== null ? (int)$c['startedAt'] : null;
$c['completedAt'] = $c['completedAt'] !== null ? (int)$c['completedAt'] : null;
$c['answers'] = (object)[];
}
unset($c);
}
qdb_discard($tmpDb, $lockFp);
echo json_encode([
"success" => true,
"questionnaire" => $questionnaire,
"questions" => $questions,
"clients" => $clients
]);