= 0 (0 or null = no limit) * - If quota not yet achieved, client can set any value * - If quota already achieved, client can only INCREASE (not decrease) * - Sum of all selection quotas cannot exceed project sample_size * - Increasing quota after it was achieved will re-activate remaining URLs */ require_once 'client-session.php'; requireClientLogin(); header('Content-Type: application/json'); if ($_SERVER['REQUEST_METHOD'] !== 'POST') { echo json_encode(['success' => false, 'message' => 'Invalid request method']); exit; } try { $data = json_decode(file_get_contents('php://input'), true); $selection_id = (int)($data['selection_id'] ?? 0); $quota_limit = isset($data['quota_limit']) ? (int)$data['quota_limit'] : null; if (!$selection_id) { throw new Exception('Invalid selection ID'); } // Treat 0 or empty as NULL (no limit) if ($quota_limit !== null && $quota_limit <= 0) { $quota_limit = null; } $pdo = getClientDBConnection(); // Get selection with project info $stmt = $pdo->prepare(" SELECT ps.*, p.project_id AS project_code, p.sample_size AS project_sample_size, p.id AS proj_db_id FROM project_selections ps JOIN projects p ON ps.project_id = p.id WHERE ps.id = ? AND ps.client_id = ? "); $stmt->execute([$selection_id, $_SESSION['client_id']]); $selection = $stmt->fetch(PDO::FETCH_ASSOC); if (!$selection) { throw new Exception('Selection not found or access denied'); } $currentQuota = $selection['quota_limit'] !== null ? (int)$selection['quota_limit'] : null; // Count current completes in this selection $stmt = $pdo->prepare(" SELECT COUNT(*) FROM survey_urls WHERE assigned_to_selection_id = ? AND status = 'complete' "); $stmt->execute([$selection_id]); $selCompletes = (int)$stmt->fetchColumn(); // RULE: If quota was already achieved, only allow increase if ($currentQuota !== null && $selCompletes >= $currentQuota) { if ($quota_limit !== null && $quota_limit < $selCompletes) { throw new Exception("Cannot set quota below current completes ($selCompletes). You can only increase the quota."); } if ($quota_limit !== null && $quota_limit < $currentQuota) { throw new Exception("Quota was already achieved ($selCompletes completes). You can only increase from $currentQuota."); } } // RULE: Sum of all selection quotas cannot exceed project sample_size if ($quota_limit !== null && $selection['project_sample_size'] > 0) { // Get sum of quotas for OTHER selections in this project $stmt = $pdo->prepare(" SELECT COALESCE(SUM(quota_limit), 0) as other_quota_sum FROM project_selections WHERE project_id = ? AND id != ? AND quota_limit IS NOT NULL "); $stmt->execute([$selection['project_id'], $selection_id]); $otherQuotaSum = (int)$stmt->fetchColumn(); if (($otherQuotaSum + $quota_limit) > $selection['project_sample_size']) { $remaining = $selection['project_sample_size'] - $otherQuotaSum; throw new Exception("Total quotas across all selections cannot exceed project sample size ({$selection['project_sample_size']}). Other selections use $otherQuotaSum. Maximum for this selection: $remaining."); } } // Update the quota $pdo->beginTransaction(); try { $stmt = $pdo->prepare(" UPDATE project_selections SET quota_limit = ?, updated_at = NOW() WHERE id = ? "); $stmt->execute([$quota_limit, $selection_id]); // If quota was INCREASED after being reached, re-activate quotafull URLs if ($quota_limit !== null && $currentQuota !== null && $selCompletes >= $currentQuota && $quota_limit > $currentQuota) { // Re-activate URLs that were marked quotafull in this selection // Change them back to 'assigned' (they were assigned before being marked quotafull) $stmt = $pdo->prepare(" UPDATE survey_urls SET status = 'assigned', completed_at = NULL WHERE assigned_to_selection_id = ? AND status = 'quotafull' "); $stmt->execute([$selection_id]); $reactivated = $stmt->rowCount(); // Re-activate selection members that were marked quota_full $stmt = $pdo->prepare(" UPDATE selection_members SET sample_status = 'pending' WHERE selection_id = ? AND sample_status = 'quota_full' "); $stmt->execute([$selection_id]); if ($reactivated > 0) { error_log("Quota increased: SelectionID=$selection_id, OldQuota=$currentQuota, NewQuota=$quota_limit, Reactivated=$reactivated URLs"); } } // Log activity $desc = $quota_limit !== null ? "Quota limit set to $quota_limit (was " . ($currentQuota ?? 'none') . ")" : "Quota limit removed (was " . ($currentQuota ?? 'none') . ")"; $stmt = $pdo->prepare(" INSERT INTO selection_activity_log (selection_id, action, description, performed_by, created_at) VALUES (?, 'quota_updated', ?, ?, NOW()) "); $stmt->execute([$selection_id, $desc, $_SESSION['client_id']]); $pdo->commit(); echo json_encode([ 'success' => true, 'message' => $quota_limit !== null ? "Quota limit set to $quota_limit" : "Quota limit removed", 'quota_limit' => $quota_limit, 'completes' => $selCompletes ]); } catch (Exception $e) { $pdo->rollBack(); throw $e; } } catch (Exception $e) { error_log("Update selection quota error: " . $e->getMessage()); echo json_encode([ 'success' => false, 'message' => $e->getMessage() ]); }