This commit is contained in:
@ -8,6 +8,7 @@
|
||||
* GET ?clientCode=X&answers=1 -> all completed questionnaire answers for one client (encrypted)
|
||||
* GET ?answersBulk=1 -> all assigned clients' answers in one payload (coach, encrypted)
|
||||
* GET ?scoringProfiles=1 -> active scoring profile definitions (encrypted)
|
||||
* GET ?sessions=1 -> active program session definitions with questionnaire assignments
|
||||
* GET ?scoringReview=1 -> coach review state (coachBand only; computed on device)
|
||||
* POST action=coachScoringReview -> coach agrees with or overrides calculated band (encrypted)
|
||||
* POST -> submit interview answers for a client (coach / supervisor / admin).
|
||||
@ -330,6 +331,10 @@ if ($method === 'POST') {
|
||||
|
||||
qdb_recompute_profile_scores_for_client($pdo, $clientCode, $qnID);
|
||||
|
||||
require_once __DIR__ . '/../lib/program_sessions.php';
|
||||
$cycleAdvanced = qdb_maybe_advance_program_cycle($pdo, $clientCode);
|
||||
$cycle = qdb_client_program_cycle_get($pdo, $clientCode);
|
||||
|
||||
$pdo->commit();
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
|
||||
@ -338,6 +343,8 @@ if ($method === 'POST') {
|
||||
'sumPoints' => $sumPoints,
|
||||
'structureRevision' => $submitRev,
|
||||
'legacySubmit' => $isLegacySubmit,
|
||||
'cycleAdvanced' => $cycleAdvanced,
|
||||
'cycleNumber' => $cycle['cycleNumber'],
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Submit questionnaire', $pdo ?? null, $tmpDb ?? null, $lockFp ?? null);
|
||||
@ -357,9 +364,17 @@ $fetchClients = $_GET['clients'] ?? '';
|
||||
$fetchAnswers = $_GET['answers'] ?? '';
|
||||
$fetchAnswersBulk = $_GET['answersBulk'] ?? '';
|
||||
$fetchScoringProfiles = $_GET['scoringProfiles'] ?? '';
|
||||
$fetchProgramSessions = $_GET['sessions'] ?? '';
|
||||
$fetchScoringReview = $_GET['scoringReview'] ?? '';
|
||||
$clientCode = trim($_GET['clientCode'] ?? '');
|
||||
|
||||
if ($fetchProgramSessions) {
|
||||
require_once __DIR__ . '/../lib/program_sessions.php';
|
||||
json_success(qdb_app_program_sessions_payload($pdo));
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($fetchScoringProfiles) {
|
||||
require_role(['coach'], $tokenRec);
|
||||
require_once __DIR__ . '/../lib/scoring.php';
|
||||
@ -468,10 +483,12 @@ if ($fetchClients) {
|
||||
}
|
||||
}
|
||||
|
||||
$clients = array_map(function ($code) use ($completions) {
|
||||
require_once __DIR__ . '/../lib/program_sessions.php';
|
||||
$clients = array_map(function ($code) use ($completions, $pdo) {
|
||||
return [
|
||||
'clientCode' => $code,
|
||||
'clientCode' => $code,
|
||||
'completedQuestionnaires' => $completions[$code] ?? [],
|
||||
'programProgress' => qdb_client_program_progress($pdo, $code),
|
||||
];
|
||||
}, $clientCodes);
|
||||
|
||||
|
||||
172
handlers/program_sessions.php
Normal file
172
handlers/program_sessions.php
Normal file
@ -0,0 +1,172 @@
|
||||
<?php
|
||||
/**
|
||||
* Program session CRUD — define which questionnaires belong to each session.
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../lib/program_sessions.php';
|
||||
|
||||
$tokenRec = require_valid_token_web();
|
||||
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
try {
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_read_or_fail();
|
||||
$sessionID = trim($_GET['id'] ?? '');
|
||||
if ($sessionID !== '') {
|
||||
$session = qdb_get_program_session($pdo, $sessionID);
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
if (!$session) {
|
||||
json_error('NOT_FOUND', 'Session not found', 404);
|
||||
}
|
||||
json_success([
|
||||
'session' => $session,
|
||||
'settings' => qdb_program_session_settings_get($pdo),
|
||||
]);
|
||||
}
|
||||
json_success([
|
||||
'sessions' => qdb_list_program_sessions($pdo),
|
||||
'settings' => qdb_program_session_settings_get($pdo),
|
||||
]);
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'List program sessions', null, $tmpDb ?? null, $lockFp ?? null);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
require_role(['admin', 'supervisor'], $tokenRec);
|
||||
$body = read_json_body();
|
||||
$name = trim($body['name'] ?? '');
|
||||
if ($name === '') {
|
||||
json_error('BAD_REQUEST', 'name is required', 400);
|
||||
}
|
||||
$sessionNumber = max(1, (int)($body['sessionNumber'] ?? 1));
|
||||
$orderIndex = max(0, (int)($body['orderIndex'] ?? 0));
|
||||
$members = qdb_parse_program_session_questionnaires($body['questionnaires'] ?? []);
|
||||
try {
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
|
||||
$err = qdb_validate_program_session_questionnaires($pdo, $members);
|
||||
if ($err !== null) {
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
json_error('INVALID_FIELD', $err, 400);
|
||||
}
|
||||
$sessionID = bin2hex(random_bytes(16));
|
||||
$now = time();
|
||||
$pdo->prepare(
|
||||
'INSERT INTO program_session
|
||||
(sessionID, name, description, sessionNumber, orderIndex, isActive, createdAt, updatedAt)
|
||||
VALUES (:id, :name, :desc, :num, :ord, :act, :ca, :ua)'
|
||||
)->execute([
|
||||
':id' => $sessionID,
|
||||
':name' => $name,
|
||||
':desc' => trim($body['description'] ?? ''),
|
||||
':num' => $sessionNumber,
|
||||
':ord' => $orderIndex,
|
||||
':act' => !empty($body['isActive']) || !array_key_exists('isActive', $body) ? 1 : 0,
|
||||
':ca' => $now,
|
||||
':ua' => $now,
|
||||
]);
|
||||
qdb_sync_program_session_questionnaires($pdo, $sessionID, $members);
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success(['session' => qdb_get_program_session($pdo, $sessionID)]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Create program session', $pdo ?? null, $tmpDb ?? null, $lockFp ?? null);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
require_role(['admin', 'supervisor'], $tokenRec);
|
||||
$body = read_json_body();
|
||||
$sessionID = trim($body['sessionID'] ?? '');
|
||||
if ($sessionID === '') {
|
||||
json_error('BAD_REQUEST', 'sessionID is required', 400);
|
||||
}
|
||||
try {
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
|
||||
$existing = qdb_get_program_session($pdo, $sessionID);
|
||||
if (!$existing) {
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
json_error('NOT_FOUND', 'Session not found', 404);
|
||||
}
|
||||
$name = trim($body['name'] ?? $existing['name']);
|
||||
if ($name === '') {
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
json_error('BAD_REQUEST', 'name is required', 400);
|
||||
}
|
||||
$members = array_key_exists('questionnaires', $body)
|
||||
? qdb_parse_program_session_questionnaires($body['questionnaires'])
|
||||
: null;
|
||||
if ($members !== null) {
|
||||
$err = qdb_validate_program_session_questionnaires($pdo, $members);
|
||||
if ($err !== null) {
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
json_error('INVALID_FIELD', $err, 400);
|
||||
}
|
||||
}
|
||||
$pdo->prepare(
|
||||
'UPDATE program_session SET
|
||||
name = :name,
|
||||
description = :desc,
|
||||
sessionNumber = :num,
|
||||
orderIndex = :ord,
|
||||
isActive = :act,
|
||||
updatedAt = :ua
|
||||
WHERE sessionID = :id'
|
||||
)->execute([
|
||||
':name' => $name,
|
||||
':desc' => trim($body['description'] ?? $existing['description']),
|
||||
':num' => isset($body['sessionNumber'])
|
||||
? max(1, (int)$body['sessionNumber'])
|
||||
: $existing['sessionNumber'],
|
||||
':ord' => isset($body['orderIndex'])
|
||||
? max(0, (int)$body['orderIndex'])
|
||||
: $existing['orderIndex'],
|
||||
':act' => isset($body['isActive'])
|
||||
? (!empty($body['isActive']) ? 1 : 0)
|
||||
: $existing['isActive'],
|
||||
':ua' => time(),
|
||||
':id' => $sessionID,
|
||||
]);
|
||||
if ($members !== null) {
|
||||
qdb_sync_program_session_questionnaires($pdo, $sessionID, $members);
|
||||
}
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success(['session' => qdb_get_program_session($pdo, $sessionID)]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Update program session', $pdo ?? null, $tmpDb ?? null, $lockFp ?? null);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'PATCH':
|
||||
require_role(['admin', 'supervisor'], $tokenRec);
|
||||
$body = read_json_body();
|
||||
try {
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
|
||||
$settings = qdb_program_session_settings_save($pdo, $body);
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success(['settings' => $settings]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Update program session settings', $pdo ?? null, $tmpDb ?? null, $lockFp ?? null);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'DELETE':
|
||||
require_role(['admin', 'supervisor'], $tokenRec);
|
||||
$body = read_json_body();
|
||||
$sessionID = trim($body['sessionID'] ?? '');
|
||||
if ($sessionID === '') {
|
||||
json_error('BAD_REQUEST', 'sessionID is required', 400);
|
||||
}
|
||||
try {
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open_write_or_fail();
|
||||
$pdo->prepare('DELETE FROM program_session WHERE sessionID = :id')->execute([':id' => $sessionID]);
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
json_success(['deleted' => true]);
|
||||
} catch (Throwable $e) {
|
||||
qdb_handler_fail($e, 'Delete program session', $pdo ?? null, $tmpDb ?? null, $lockFp ?? null);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
json_error('METHOD_NOT_ALLOWED', 'Method not allowed', 405);
|
||||
}
|
||||
Reference in New Issue
Block a user