false, 'ERROR' => 'missing_grantid', 'MESSAGE' => 'GrantID is required.']); } if ($userId <= 0) { apiAbort(['OK' => false, 'ERROR' => 'not_authenticated']); } $qGrant = queryOne( "SELECT g.*, b.UserID AS OwnerUserID FROM ServicePointGrants g JOIN Businesses b ON b.ID = g.OwnerBusinessID WHERE g.ID = ? LIMIT 1", [$grantID] ); if (!$qGrant) { apiAbort(['OK' => false, 'ERROR' => 'not_found', 'MESSAGE' => 'Grant not found.']); } if ((int) $qGrant['OwnerUserID'] !== $userId) { apiAbort(['OK' => false, 'ERROR' => 'not_owner', 'MESSAGE' => 'Only the owner business can update grant terms.']); } $statusID = (int) $qGrant['StatusID']; if ($statusID !== 0 && $statusID !== 1) { apiAbort(['OK' => false, 'ERROR' => 'bad_state', 'MESSAGE' => 'Only pending or active grants can be updated.']); } $setClauses = []; $setParams = []; $previousData = []; $newData = []; $validEconomics = ['none', 'flat_fee', 'percent_of_orders']; $validEligibility = ['public', 'employees', 'guests', 'internal']; $validTimePolicy = ['always', 'schedule', 'date_range', 'event']; // Economics if (isset($data['EconomicsType']) || isset($data['EconomicsValue'])) { $eType = trim($data['EconomicsType'] ?? $qGrant['EconomicsType']); $eValue = (float) ($data['EconomicsValue'] ?? $qGrant['EconomicsValue']); if (!in_array($eType, $validEconomics)) $eType = $qGrant['EconomicsType']; if ($eType !== $qGrant['EconomicsType'] || $eValue != (float) $qGrant['EconomicsValue']) { $previousData['EconomicsType'] = $qGrant['EconomicsType']; $previousData['EconomicsValue'] = (float) $qGrant['EconomicsValue']; $newData['EconomicsType'] = $eType; $newData['EconomicsValue'] = $eValue; $setClauses[] = 'EconomicsType = ?'; $setParams[] = $eType; $setClauses[] = 'EconomicsValue = ?'; $setParams[] = $eValue; } } // Eligibility if (isset($data['EligibilityScope'])) { $eScope = trim($data['EligibilityScope']); if (!in_array($eScope, $validEligibility)) $eScope = $qGrant['EligibilityScope']; if ($eScope !== $qGrant['EligibilityScope']) { $previousData['EligibilityScope'] = $qGrant['EligibilityScope']; $newData['EligibilityScope'] = $eScope; $setClauses[] = 'EligibilityScope = ?'; $setParams[] = $eScope; } } // Time policy if (isset($data['TimePolicyType']) || isset($data['TimePolicyData'])) { $tType = trim($data['TimePolicyType'] ?? $qGrant['TimePolicyType']); if (!in_array($tType, $validTimePolicy)) $tType = $qGrant['TimePolicyType']; $tData = $data['TimePolicyData'] ?? $qGrant['TimePolicyData']; $changed = ($tType !== $qGrant['TimePolicyType']); if (!$changed && is_array($tData)) { $changed = (json_encode($tData) !== ($qGrant['TimePolicyData'] ?? '')); } if ($changed) { $previousData['TimePolicyType'] = $qGrant['TimePolicyType']; $previousData['TimePolicyData'] = $qGrant['TimePolicyData'] ?? ''; $newData['TimePolicyType'] = $tType; $newData['TimePolicyData'] = $tData; $setClauses[] = 'TimePolicyType = ?'; $setParams[] = $tType; $tDataJson = null; if (is_array($tData) && !empty($tData)) { $tDataJson = json_encode($tData); } elseif (is_string($tData) && trim($tData) !== '') { $tDataJson = $tData; } $setClauses[] = 'TimePolicyData = ?'; $setParams[] = $tDataJson; } } if (empty($setClauses)) { apiAbort(['OK' => true, 'MESSAGE' => 'No changes detected.', 'GrantID' => $grantID]); } $setParams[] = $grantID; queryTimed( "UPDATE ServicePointGrants SET " . implode(', ', $setClauses) . " WHERE ID = ?", $setParams ); // Determine action name for history $action = 'updated'; if (isset($newData['EconomicsType']) || isset($newData['EconomicsValue'])) $action = 'updated_economics'; if (isset($newData['EligibilityScope'])) $action = 'updated_eligibility'; if (isset($newData['TimePolicyType'])) $action = 'updated_time_policy'; recordGrantHistory( $grantID, $action, $userId, (int) $qGrant['OwnerBusinessID'], $previousData, $newData ); jsonResponse([ 'OK' => true, 'GrantID' => $grantID, 'MESSAGE' => 'Grant updated.', ]);