140 lines
4.7 KiB
PHP
140 lines
4.7 KiB
PHP
<?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
|
|
]);
|