query( "SELECT c.coachID, c.username, c.supervisorID FROM coach c ORDER BY c.username" )->fetchAll(PDO::FETCH_ASSOC); } else { $stmt = $pdo->prepare( "SELECT c.coachID, c.username, c.supervisorID FROM coach c WHERE c.supervisorID = :sid ORDER BY c.username" ); $stmt->execute([':sid' => $entityID]); $coaches = $stmt->fetchAll(PDO::FETCH_ASSOC); } // Clients visible to this user [$clause, $params] = rbac_client_filter($tokenRec); $clientStmt = $pdo->prepare( "SELECT cl.clientCode, cl.coachID, co.username AS coachUsername FROM client cl LEFT JOIN coach co ON co.coachID = cl.coachID WHERE $clause ORDER BY cl.clientCode" ); foreach ($params as $k => $v) $clientStmt->bindValue($k, $v); $clientStmt->execute(); $clients = $clientStmt->fetchAll(PDO::FETCH_ASSOC); $pdo = null; qdb_discard($tmpDb, $lockFp); echo json_encode(["coaches" => $coaches, "clients" => $clients]); } catch (Throwable $e) { if (isset($tmpDb, $lockFp)) qdb_discard($tmpDb, $lockFp); http_response_code(500); echo json_encode(["error" => "Server error"]); } exit; } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $raw = file_get_contents("php://input"); $in = json_decode($raw, true) ?: []; $clientCodes = $in['clientCodes'] ?? []; $coachID = trim($in['coachID'] ?? ''); if (empty($clientCodes) || $coachID === '') { http_response_code(400); echo json_encode(["error" => "clientCodes and coachID required"]); exit; } if (!is_array($clientCodes)) { $clientCodes = [$clientCodes]; } try { [$pdo, $tmpDb, $lockFp] = qdb_open(true); // Verify coach exists and is visible if ($role === 'supervisor') { $chk = $pdo->prepare("SELECT coachID FROM coach WHERE coachID = :cid AND supervisorID = :sid"); $chk->execute([':cid' => $coachID, ':sid' => $entityID]); } else { $chk = $pdo->prepare("SELECT coachID FROM coach WHERE coachID = :cid"); $chk->execute([':cid' => $coachID]); } if (!$chk->fetch()) { qdb_discard($tmpDb, $lockFp); http_response_code(400); echo json_encode(["error" => "Coach not found or not authorized"]); exit; } // Only allow reassignment of clients the caller can already see [$rbacClause, $rbacParams] = rbac_client_filter($tokenRec); $pdo->beginTransaction(); $updStmt = $pdo->prepare( "UPDATE client SET coachID = :cid WHERE clientCode = :cc AND ($rbacClause)" ); $count = 0; foreach ($clientCodes as $cc) { $cc = trim($cc); if ($cc === '') continue; $updStmt->execute(array_merge([':cid' => $coachID, ':cc' => $cc], $rbacParams)); $count += $updStmt->rowCount(); } $pdo->commit(); $pdo = null; qdb_save($tmpDb, $lockFp); echo json_encode(["success" => true, "assigned" => $count]); } catch (Throwable $e) { if (isset($tmpDb, $lockFp)) qdb_discard($tmpDb, $lockFp); http_response_code(500); echo json_encode(["error" => "Server error"]); } exit; } http_response_code(405); echo json_encode(["error" => "Method not allowed"]);