$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); }