false, 'ERROR' => 'missing_grantid', 'MESSAGE' => 'GrantID is required.']); } if ($userId <= 0) { apiAbort(['OK' => false, 'ERROR' => 'not_authenticated']); } $qGrant = queryOne( "SELECT g.*, ob.Name AS OwnerBusinessName, gb.Name AS GuestBusinessName, sp.Name AS ServicePointName, sp.TypeID AS ServicePointTypeID, cu.FirstName AS CreatedByFirstName, cu.LastName AS CreatedByLastName, au.FirstName AS AcceptedByFirstName, au.LastName AS AcceptedByLastName FROM ServicePointGrants g JOIN Businesses ob ON ob.ID = g.OwnerBusinessID JOIN Businesses gb ON gb.ID = g.GuestBusinessID JOIN ServicePoints sp ON sp.ID = g.ServicePointID LEFT JOIN Users cu ON cu.ID = g.CreatedByUserID LEFT JOIN Users au ON au.ID = g.AcceptedByUserID WHERE g.ID = ? LIMIT 1", [$grantID] ); if (!$qGrant) { apiAbort(['OK' => false, 'ERROR' => 'not_found', 'MESSAGE' => 'Grant not found.']); } // Load history $historyRows = queryTimed( "SELECT h.*, u.FirstName, u.LastName FROM ServicePointGrantHistory h LEFT JOIN Users u ON u.ID = h.ActorUserID WHERE h.GrantID = ? ORDER BY h.CreatedOn DESC", [$grantID] ); $history = []; foreach ($historyRows as $row) { $history[] = [ 'ID' => (int) $row['ID'], 'Action' => $row['Action'], 'ActorUserID' => (int) $row['ActorUserID'], 'ActorName' => trim(($row['FirstName'] ?? '') . ' ' . ($row['LastName'] ?? '')), 'ActorBusinessID' => (int) $row['ActorBusinessID'], 'PreviousData' => $row['PreviousData'] ?? '', 'NewData' => $row['NewData'] ?? '', 'CreatedOn' => $row['CreatedOn'], ]; } $grant = [ 'GrantID' => (int) $qGrant['ID'], 'UUID' => $qGrant['UUID'], 'OwnerBusinessID' => (int) $qGrant['OwnerBusinessID'], 'GuestBusinessID' => (int) $qGrant['GuestBusinessID'], 'ServicePointID' => (int) $qGrant['ServicePointID'], 'StatusID' => (int) $qGrant['StatusID'], 'EconomicsType' => $qGrant['EconomicsType'], 'EconomicsValue' => (float) $qGrant['EconomicsValue'], 'EligibilityScope' => $qGrant['EligibilityScope'], 'TimePolicyType' => $qGrant['TimePolicyType'], 'TimePolicyData' => $qGrant['TimePolicyData'] ?? '', 'CreatedOn' => $qGrant['CreatedOn'], 'AcceptedOn' => $qGrant['AcceptedOn'] ?? '', 'RevokedOn' => $qGrant['RevokedOn'] ?? '', 'LastEditedOn' => $qGrant['LastEditedOn'], 'OwnerBusinessName' => $qGrant['OwnerBusinessName'], 'GuestBusinessName' => $qGrant['GuestBusinessName'], 'ServicePointName' => $qGrant['ServicePointName'], 'ServicePointTypeID' => (int) $qGrant['ServicePointTypeID'], 'CreatedByName' => trim(($qGrant['CreatedByFirstName'] ?? '') . ' ' . ($qGrant['CreatedByLastName'] ?? '')), 'AcceptedByName' => trim(($qGrant['AcceptedByFirstName'] ?? '') . ' ' . ($qGrant['AcceptedByLastName'] ?? '')), ]; jsonResponse([ 'OK' => true, 'Grant' => $grant, 'History' => $history, ]);