added prototype dev settings with test import and db wipe
This commit is contained in:
@ -60,6 +60,7 @@ if ($method === 'POST') {
|
||||
$qRows->execute([':qn' => $qnID]);
|
||||
$shortIdMap = []; // shortId -> fullQuestionID
|
||||
$freeTextMaxLen = []; // fullQuestionID -> maxLength
|
||||
$symptomParentMap = qdb_glass_symptom_parent_map($pdo, $qnID);
|
||||
foreach ($qRows->fetchAll(PDO::FETCH_ASSOC) as $qRow) {
|
||||
$fullId = $qRow['questionID'];
|
||||
$parts = explode('__', $fullId);
|
||||
@ -89,6 +90,7 @@ if ($method === 'POST') {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
$sumPoints = 0;
|
||||
$glassByParent = [];
|
||||
$answerInsert = $pdo->prepare("
|
||||
INSERT INTO client_answer (clientCode, questionID, answerOptionID, freeTextValue, numericValue, answeredAt)
|
||||
VALUES (:cc, :qid, :aoid, :ftv, :nv, :at)
|
||||
@ -103,14 +105,25 @@ if ($method === 'POST') {
|
||||
$shortId = trim($a['questionID'] ?? '');
|
||||
if ($shortId === '') continue;
|
||||
|
||||
$answeredAt = isset($a['answeredAt']) ? (int)$a['answeredAt'] : null;
|
||||
|
||||
// Glass-scale symptoms use string keys (not question localIds).
|
||||
if (isset($symptomParentMap[$shortId])) {
|
||||
$label = trim((string)($a['answerOptionKey'] ?? $a['freeTextValue'] ?? ''));
|
||||
if ($label !== '') {
|
||||
$parentId = $symptomParentMap[$shortId];
|
||||
$glassByParent[$parentId][$shortId] = $label;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Resolve short ID to full questionID
|
||||
$fullQID = $shortIdMap[$shortId] ?? null;
|
||||
if ($fullQID === null) continue; // skip unknown questions
|
||||
if ($fullQID === null) continue;
|
||||
|
||||
$answerOptionID = null;
|
||||
$freeTextValue = isset($a['freeTextValue']) ? (string)$a['freeTextValue'] : null;
|
||||
$numericValue = isset($a['numericValue']) ? (float)$a['numericValue'] : null;
|
||||
$answeredAt = isset($a['answeredAt']) ? (int)$a['answeredAt'] : null;
|
||||
|
||||
if ($freeTextValue !== null && $freeTextValue !== '') {
|
||||
$maxLen = $freeTextMaxLen[$fullQID] ?? 2000;
|
||||
@ -138,6 +151,23 @@ if ($method === 'POST') {
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($glassByParent as $parentQID => $symptomLabels) {
|
||||
$existing = $pdo->prepare(
|
||||
'SELECT freeTextValue FROM client_answer WHERE clientCode = :cc AND questionID = :qid'
|
||||
);
|
||||
$existing->execute([':cc' => $clientCode, ':qid' => $parentQID]);
|
||||
$prevJson = $existing->fetchColumn();
|
||||
$merged = qdb_merge_glass_symptom_json($prevJson !== false ? (string)$prevJson : null, $symptomLabels);
|
||||
$answerInsert->execute([
|
||||
':cc' => $clientCode,
|
||||
':qid' => $parentQID,
|
||||
':aoid' => null,
|
||||
':ftv' => $merged,
|
||||
':nv' => null,
|
||||
':at' => $completedAt ?? $startedAt,
|
||||
]);
|
||||
}
|
||||
|
||||
// Upsert completed_questionnaire record
|
||||
$pdo->prepare("
|
||||
INSERT INTO completed_questionnaire (clientCode, questionnaireID, assignedByCoach, status, startedAt, completedAt, sumPoints)
|
||||
|
||||
57
handlers/dev.php
Normal file
57
handlers/dev.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* Admin-only dev fixture import (local / test environments).
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../lib/dev_fixture.php';
|
||||
|
||||
$tokenRec = require_valid_token_web();
|
||||
require_role(['admin'], $tokenRec);
|
||||
|
||||
if ($method !== 'POST') {
|
||||
json_error('METHOD_NOT_ALLOWED', 'Method not allowed', 405);
|
||||
}
|
||||
|
||||
$body = read_json_body();
|
||||
$action = trim((string)($body['action'] ?? 'import'));
|
||||
|
||||
try {
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open(true);
|
||||
|
||||
if ($action === 'remove') {
|
||||
$result = qdb_remove_dev_test_data($pdo, [
|
||||
'usernamePrefix' => $body['usernamePrefix'] ?? 'dev_',
|
||||
'clientCodePrefix' => $body['clientCodePrefix'] ?? 'DEV-CL-',
|
||||
]);
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success($result);
|
||||
}
|
||||
|
||||
if ($action === 'wipeExceptAdmins') {
|
||||
$result = qdb_wipe_all_data_except_admins($pdo);
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success($result);
|
||||
}
|
||||
|
||||
$fixture = $body['fixture'] ?? null;
|
||||
if (!is_array($fixture)) {
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
json_error('MISSING_FIELDS', 'fixture object is required for import', 400);
|
||||
}
|
||||
|
||||
$result = qdb_import_dev_fixture($pdo, $fixture);
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success($result);
|
||||
} catch (Throwable $e) {
|
||||
if (isset($tmpDb, $lockFp)) {
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
}
|
||||
$labels = [
|
||||
'remove' => 'Remove',
|
||||
'wipeExceptAdmins' => 'Wipe',
|
||||
'import' => 'Import',
|
||||
];
|
||||
$label = $labels[$action ?? 'import'] ?? 'Operation';
|
||||
error_log("dev fixture $label: " . $e->getMessage());
|
||||
json_error('SERVER_ERROR', "$label failed: " . $e->getMessage(), 500);
|
||||
}
|
||||
@ -34,7 +34,7 @@ if (!$questionnaire) {
|
||||
json_error('NOT_FOUND', 'Questionnaire not found', 404);
|
||||
}
|
||||
|
||||
$qStmt = $pdo->prepare("SELECT questionID, defaultText, orderIndex FROM question WHERE questionnaireID = :id ORDER BY orderIndex");
|
||||
$qStmt = $pdo->prepare("SELECT questionID, defaultText, type, orderIndex FROM question WHERE questionnaireID = :id ORDER BY orderIndex");
|
||||
$qStmt->execute([':id' => $qnID]);
|
||||
$questions = $qStmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$questionIDs = array_column($questions, 'questionID');
|
||||
@ -94,20 +94,8 @@ foreach ($clients as $c) {
|
||||
|
||||
foreach ($questions as $q) {
|
||||
$qid = $q['questionID'];
|
||||
if (isset($answerMap[$qid])) {
|
||||
$a = $answerMap[$qid];
|
||||
if ($a['answerOptionID'] && isset($optionTextMap[$a['answerOptionID']])) {
|
||||
$row[$q['defaultText']] = $optionTextMap[$a['answerOptionID']];
|
||||
} elseif ($a['freeTextValue'] !== null && $a['freeTextValue'] !== '') {
|
||||
$row[$q['defaultText']] = $a['freeTextValue'];
|
||||
} elseif ($a['numericValue'] !== null) {
|
||||
$row[$q['defaultText']] = $a['numericValue'];
|
||||
} else {
|
||||
$row[$q['defaultText']] = '';
|
||||
}
|
||||
} else {
|
||||
$row[$q['defaultText']] = '';
|
||||
}
|
||||
$a = $answerMap[$qid] ?? null;
|
||||
$row[$q['defaultText']] = qdb_format_client_answer_display($q, $a, $optionTextMap);
|
||||
}
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ if (!$questionnaire) {
|
||||
}
|
||||
|
||||
$qStmt = $pdo->prepare("
|
||||
SELECT questionID, defaultText, type, orderIndex, isRequired
|
||||
SELECT questionID, defaultText, type, orderIndex, isRequired, configJson
|
||||
FROM question WHERE questionnaireID = :id ORDER BY orderIndex
|
||||
");
|
||||
$qStmt->execute([':id' => $qnID]);
|
||||
|
||||
Reference in New Issue
Block a user