diff --git a/.gitignore b/.gitignore index af3d87c..06f335c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,5 @@ _tables.php _globals.php _cfg.php /logs -.agents/* +.agents skills-lock.json diff --git a/_SQL/zmeny.sql.php b/_SQL/zmeny.sql.php index 35dd03d..89a4d19 100644 --- a/_SQL/zmeny.sql.php +++ b/_SQL/zmeny.sql.php @@ -29,6 +29,7 @@ function AddZmenyFile($version) AddZmenyFile('3.4.5.652'); AddZmenyFile('3.4.5.655'); AddZmenyFile('3.4.6.656'); +AddZmenyFile('3.4.5.658'); //############################################################################# require_once ('connect.inc.php'); diff --git a/_SQL/zmeny_3.4.5.658.sql.php b/_SQL/zmeny_3.4.5.658.sql.php new file mode 100644 index 0000000..3dbf46a --- /dev/null +++ b/_SQL/zmeny_3.4.5.658.sql.php @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/adm_oris_sync.php b/adm_oris_sync.php new file mode 100644 index 0000000..7cbf612 --- /dev/null +++ b/adm_oris_sync.php @@ -0,0 +1,44 @@ + + + + + ORIS Sync Daemon Manual Trigger + + + +

Manual ORIS Sync Execution

+

Executing daemon...

+
+getMessage() . "\n"; +} +$output = ob_get_clean(); + +// Display standard output +echo htmlspecialchars($output); +?> +
+
+ Return to System + + \ No newline at end of file diff --git a/ads_oris.inc.php b/ads_oris.inc.php index 3fcd481..bc73598 100644 --- a/ads_oris.inc.php +++ b/ads_oris.inc.php @@ -46,21 +46,24 @@ function startsWith( $haystack, $needle ) { return substr( $haystack, 0, $length ) === $needle; } -$json = file_get_contents('https://oris.orientacnisporty.cz/API/?format=json&method=getRegistration&sport=1&year='.$ORIS_year); -$obj = json_decode($json); +require_once './lib/OrisIntegrationService.php'; +$service = new OrisIntegrationService(null); +$obj = $service->getRegistration(1, $ORIS_year); $arr_oris = array(); -foreach ($obj->Data as $key=>$value) -{ - $user = new User(); - $user->create($value->UserID, $value->FirstName, $value->LastName, $value->RegNo, $value->SI, $value->ClubID); - - $reg = $value->RegNo; - if (startsWith($reg, $g_shortcut)) +if (is_array($obj) || is_object($obj)) { + foreach ($obj as $key=>$value) { - $arr_oris["user"] [$reg]= $user; - $arr_oris["members"][$reg] = 0; + $user = new User(); + $user->create($value['UserID'], $value['FirstName'], $value['LastName'], $value['RegNo'], $value['SI'], $value['ClubID']); + + $reg = $value['RegNo']; + if (startsWith($reg, $g_shortcut)) + { + $arr_oris["user"] [$reg]= $user; + $arr_oris["members"][$reg] = 0; + } } } //konec nahrani dat z orisu diff --git a/ads_oris_si_sync.php b/ads_oris_si_sync.php index c8e94aa..37f0b9b 100644 --- a/ads_oris_si_sync.php +++ b/ads_oris_si_sync.php @@ -29,7 +29,6 @@ 'format' => 'json', 'method' => 'editPerson', 'userid' => $oris_id, - 'si' => $zaznam['si_chip'], 'clubkey' => $g_oris_club_key, 'firstname' => $zaznam['jmeno'], 'lastname' => $zaznam['prijmeni'], @@ -39,6 +38,9 @@ 'zip' => $zaznam['psc'], 'country' => (!empty($zaznam['narodnost']) ? $zaznam['narodnost'] : 'CZ') ); + if (!empty($zaznam['si_chip']) && $zaznam['si_chip'] != 0 && $zaznam['si_chip'] !== '0') { + $params['si'] = $zaznam['si_chip']; + } $url = "https://oris.ceskyorientak.cz/API/?" . http_build_query($params); diff --git a/connectors.php b/connectors.php index 69f2456..f91ab7f 100644 --- a/connectors.php +++ b/connectors.php @@ -1,398 +1,153 @@ -ext_id = $data['ext_id'] ?? null; - $this->datum = $data['datum'] ?? null; - $this->datum2 = $data['datum2'] ?? null; - $this->nazev = $data['nazev'] ?? null; - $this->misto = $data['misto'] ?? null; - $this->oblasti = $data['oblasti'] ?? null; - $this->typ = $data['typ'] ?? null; - $this->zebricek2 = $data['zebricek2'] ?? null; - $this->ranking = $data['ranking'] ?? null; - $this->odkaz = $data['odkaz'] ?? null; - $this->prihlasky = $data['prihlasky'] ?? null; - $this->prihlasky1 = $data['prihlasky1'] ?? null; - $this->prihlasky2 = $data['prihlasky2'] ?? null; - $this->prihlasky3 = $data['prihlasky3'] ?? null; - $this->prihlasky4 = $data['prihlasky4'] ?? null; - $this->prihlasky5 = $data['prihlasky5'] ?? null; - $this->koeficient1 = $data['koeficient1'] ?? null; - $this->koeficient2 = $data['koeficient2'] ?? null; - $this->etap = $data['etap'] ?? null; - $this->poznamka = $data['poznamka'] ?? null; - $this->vicedenni = $data['vicedenni'] ?? null; - $this->oddil = $data['oddil'] ?? null; - $this->modify_flag = $data['modify_flag'] ?? null; - $this->kategorie = $data['kategorie'] ?? null; - $this->startovne = $data['startovne'] ?? null; - } -} - -class RacePayement { - public int $raceId; - public RaceOverview $overview; - /** @var array RegNo => User */ - public array $participants = []; - - public function __construct(int $raceId) { - $this->raceId = $raceId; - $this->overview = new RaceOverview(); - } - - public function addPatricipant(RaceParticipant $user): void { - $this->participants[$user->regNo] = $user; - } - - public function addCategory(string $name, int $feeTier, int $fee ): void { - $this->overview->addCategory($name,$feeTier,$fee); - } - - public function addService(string $name, int $fee, int $count ): void { - $this->overview->addService( $name, $fee, $count ); - } -} - -class RaceOverview { - /** @var array> Category => [EntryStop => Fee] */ - public array $categories = []; - - /** @var array> ServiceName => [ Fee => Count ] */ - public array $services = []; - - /** @var array feeTier => exist */ - public array $feeTiers = []; - - public function addCategory(string $name, int $feeTier, int $fee ): void { - - if (!isset($this->categories[$name])) { - $this->categories[$name] = []; - } - $this->categories[$name][$feeTier] = $fee; - - // Store only unique sorted feeTier values - $this->feeTiers[$feeTier] = true; - } - - public function addService(string $name, int $fee, int $count ): void { - if ( isset ( $this->services[$name][$fee] ) ) { - $this->services[$name][$fee] += $count; - } else { - $this->services[$name][$fee] = $count; - } - } -} - -class RaceParticipant { - public string $regNo; - public string $classDesc; - public string $name; - public bool $rentSI; - public string $licence; - public $fee; - public int $feeTier; - - public function __construct(string $regNo, string $classDesc, string $name, bool $rentSI, string|null $licence, int $fee, int $feeTier) { - $this->regNo = $regNo; - $this->classDesc = $classDesc; - $this->name = $name; - $this->rentSI = $rentSI; - $this->licence = $licence ?? ''; - $this->fee = $fee; - $this->feeTier = $feeTier; - } -} - -interface ConnectorInterface { - public function getSystemName(): string; - public function getRaceURL(string $id): string; - public function getRaceInfo(string $id) : ?RaceInfo; - public function getRacesList($fromDate, $toDate); - public function getRacePayement(string $id) : ?RacePayement; -} - -class OrisCZConnector implements ConnectorInterface { - private $sourceUrl = 'https://oris.orientacnisporty.cz/'; - private $apiUrl; - - public function __construct() { - $this->apiUrl = $this->sourceUrl . 'API/'; - } - - // Method to get the system name - public function getSystemName(): string { - return "Oris"; - } - - // RaceInfo URL - public function getRaceURL($raceId) : string { - return $this->sourceUrl . 'Zavod?id=' . $raceId; - } - - private function mapLevelToZebricek2($levelId) { - $map = [ - 1 => 17, // MCR - 3 => 6, // ZB - 4 => 8, // OZ - 7 => 33, // CPS - 8 => 1, // CP - 11 => 24, // OM - 17 => 17 // VET - ]; - return $map[$levelId] ?? 0x0080; // Default to 0x80 if not found - } - - private function mapSport($sportId) { - //sport ID from ORIS : 1=OB, 2=LOB, 3=MTBO, 4=TRAIL - $map = [ - 1 => 1, // OB - 2 => 4, // LOB - 3 => 2, // MTBO - 4 => 8, // TRAIL - ]; - return $map[$sportId] ?? 1; // Default is OB - } - - private function getClubs(&$raceData) { - - $oddily = []; - if (isset($raceData['Org1']['Abbr'])) { - $oddily[] = $raceData['Org1']['Abbr']; - } - if (isset($raceData['Org2']['Abbr'])) { - $oddily[] = $raceData['Org2']['Abbr']; - } - return implode('+', $oddily); - } - - // Method to get race date based on race ID or provided response - public function getRaceDate($raceId, $response = null) { - // If no response provided, fetch it from API - if ($response === null) { - $url = $this->apiUrl . '?format=json&method=getEvent&id=' . $raceId; - $response = $this->makeRequest($url); - } - - if ($response && isset($response['Status']) && $response['Status'] === "OK") { - $raceData = $response['Data']; - return String2DateDMY(formatDate($raceData['Date'])); - } - - return ''; // Return empty string if race not found or error - } - - // Method to get detailed race information based on race ID - public function getRaceInfo($raceId) : RaceInfo { - $url = $this->apiUrl . '?format=json&method=getEvent&id=' . $raceId; - - $response = $this->makeRequest($url); - - if ($response && $response['Status'] == "OK") { - $raceData = $response['Data']; - - $classFees = []; - if (isset($raceData['Classes'])) { - foreach ($raceData['Classes'] as $class) { - if (isset($class['Name'])) { - $name = $class['Name']; - $fee = $class['Fee'] ?? null; // default to null if missing - $classFees[$name] = $fee; - } - } - } - - ksort ( $classFees ); - - $oddily = $this->getClubs($raceData); - $oblasti = []; - if (isset($raceData['Regions'])) { - foreach ($raceData['Regions'] as $tag => $region) { - $oblasti[] = $region['ID']; - } - } - - // Get last Stage date if multistage event - $date2 = ($raceData['Stages'] > 1) ? $this->getRaceDate($raceData['Stage'.$raceData['Stages']], $response) : 0; - // Use associative array to pass data to constructor - return new RaceInfo([ - 'ext_id' => $raceData['ID'], - 'datum' => String2DateDMY(formatDate($raceData['Date'])), - 'datum2' => $date2, - 'nazev' => $raceData['Name'], - 'misto' => $raceData['Place'], -// 'category' => $raceData['Category'], - //typ0 => Typ akce - 'oblasti' => $oblasti, - 'typ0' => 'Z', - 'typ' => $this->mapSport($raceData['Sport']['ID']), - 'zebricek2' => $this->mapLevelToZebricek2($raceData['Level']['ID']), - 'ranking' => $raceData['Ranking'], - 'odkaz' => $this->getRaceURL($raceData['ID']), - 'prihlasky' => strtotime($raceData['EntryDate1']), - 'prihlasky1' => strtotime($raceData['EntryDate2']), - 'prihlasky2' => strtotime($raceData['EntryDate3']), -// 'prihlasky3' => '', -// 'prihlasky4' => '', -// 'prihlasky5' => '', - 'koeficient1' => $raceData['EntryKoef2'], - 'koeficient2' => $raceData['EntryKoef3'], - 'etap' => $raceData['Stages'], -// 'poznamka' => $poznamka, - 'vicedenni' => ($raceData['Stages']>1?1:0), - 'oddil' => $oddily, - 'modify_flag' => 0, - 'kategorie' => implode(';', array_keys ( $classFees ) ), - 'startovne' => $classFees - ]); - } else { - return null; // Return null if race not found or error - } - } - - // Helper method to make HTTP requests - private function makeRequest($url) { - $response = file_get_contents($url); - - // Decode JSON response - return json_decode($response, true); - } - - private function makeRequestCurl($url) { - $ch = curl_init($url); - - // Set curl options - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - $response = curl_exec($ch); - - // Check for errors - if (curl_errno($ch)) { - echo 'Curl error: ' . curl_error($ch); - return null; - } - - curl_close($ch); - - // Decode JSON response - return json_decode($response, true); - } - - function getRacesList($fromDate, $toDate) { - $url = $this->apiUrl.'?format=json&method=getEventList&all=1&datefrom='.$fromDate.'&dateto='.$toDate; -// echo($url.'
'); - $response = $this->makeRequest($url); - - if ($response && $response['Status'] == "OK") { - $racesData = $response['Data']; - $rows = array(); - foreach($racesData as $oneRace) { - $oddily = $this->getClubs($oneRace); - - $row = array(); - $row[] = $oneRace['ID']; - $row[] = $oneRace['Date']; - $row[] = $oneRace['Name']; - $row[] = $oddily; - $rows[] = $row; - } - return $rows; - } else { - return null; // Return null if race not found or error - } - } - - // Method to get detailed race information based on race ID - public function getRacePayement($raceId) : ?RacePayement { - - global $g_external_is_club_id; - - if ( !IsSet ($g_external_is_club_id) || $g_external_is_club_id === '' ) return null; - - $url = $this->apiUrl . '?format=json&method=getEventEntries&clubid=' . $g_external_is_club_id . '&eventid=' . $raceId; - - $response = $this->makeRequest($url); - $racePayement = null; - - if ($response && $response['Status'] == "OK") { - $racePayement = new RacePayement($raceId); - - foreach ($response['Data'] as $entry) { - if (isset($entry['Fee'])) { - if (isset($entry['RegNo']) ) { - $racePayement->addPatricipant( - new RaceParticipant($entry['RegNo'], $entry['ClassDesc'], $entry['Name'], - $entry['RentSI'], $entry['Licence'], (int)$entry['Fee'], $entry['EntryStop'])); - } - if (isset($entry['ClassDesc'])&&isset($entry['ClassDesc'])) { - $racePayement->addCategory($entry['ClassDesc'], $entry['EntryStop'], (int)$entry['Fee']); - } - } - } - } - - $url = $this->apiUrl . '?format=json&method=getEventServiceEntries&clubid=' . $g_external_is_club_id . '&eventid=' . $raceId; - - $response = $this->makeRequest($url); - - if ($response && $response['Status'] == "OK") { - if ( $racePayement === null ) $racePayement = new RacePayement($raceId); - foreach ($response['Data'] as $entry) { - if ( isset ( $entry['Service'] ) ) { - $racePayement->addService($entry['Service']['NameCZ'] ?? 'Name?', $entry['Service']['UnitPrice'] , $entry['Quantity'] ); - } else { - if ( isset ( $entry['Quantity'] ) && isset ( $entry['TotalFee'] ) ) { - $racePayement->addService('Name?', $entry['TotalFee'] / $entry['Quantity'], $entry['Quantity'] ); - } - } - } - } - - //print_r ($racePayement); - - return $racePayement; - } -} - -class ConnectorFactory { - public static function create(): ?ConnectorInterface { - global $g_external_is_connector; - - if ( $g_external_is_connector && class_exists( $g_external_is_connector)) { - return new $g_external_is_connector(); - } - - return null; // Return null explicitly if no valid connector is found - } -} +service = new OrisIntegrationService(null); + } + + public function getSystemName(): string { + return "Oris"; + } + + public function getRaceURL($raceId) : string { + return $this->sourceUrl . 'Zavod?id=' . $raceId; + } + + private function mapLevelToZebricek2($levelId) { + $map = [ + 1 => 17, // MCR + 3 => 6, // ZB + 4 => 8, // OZ + 7 => 33, // CPS + 8 => 1, // CP + 11 => 24, // OM + 17 => 17 // VET + ]; + return $map[$levelId] ?? 0x0080; // Default to 0x80 if not found + } + + private function mapSport($sportId) { + $map = [ + 1 => 1, // OB + 2 => 4, // LOB + 3 => 2, // MTBO + 4 => 8, // TRAIL + ]; + return $map[$sportId] ?? 1; // Default is OB + } + + private function getClubs(&$raceData) { + $oddily = []; + if (isset($raceData['Org1']['Abbr'])) { + $oddily[] = $raceData['Org1']['Abbr']; + } + if (isset($raceData['Org2']['Abbr'])) { + $oddily[] = $raceData['Org2']['Abbr']; + } + return implode('+', $oddily); + } + + public function getRaceDate($raceId) { + try { + $raceData = $this->service->getEvent($raceId); + if (isset($raceData['Date'])) { + return String2DateDMY(formatDate($raceData['Date'])); + } + } catch (OrisException $e) { + // fallback + } + return ''; + } + + public function getRaceInfo($raceId) { + try { + $raceData = $this->service->getEvent($raceId); + + $classNames = []; + if (isset($raceData['Classes'])) { + foreach ($raceData['Classes'] as $class) { + if (isset($class['Name'])) { + $classNames[] = $class['Name']; + } + } + } + + sort($classNames); + $oddily = $this->getClubs($raceData); + + $date2 = ($raceData['Stages'] > 1) ? $this->getRaceDate($raceData['Stage'.$raceData['Stages']]) : 0; + + return new RaceDTO([ + 'ext_id' => $raceData['ID'], + 'datum' => String2DateDMY(formatDate($raceData['Date'])), + 'datum2' => $date2, + 'nazev' => $raceData['Name'], + 'misto' => $raceData['Place'], + 'typ0' => 'Z', + 'typ' => $this->mapSport($raceData['Sport']['ID']), + 'zebricek2' => $this->mapLevelToZebricek2($raceData['Level']['ID']), + 'ranking' => $raceData['Ranking'], + 'odkaz' => $this->getRaceURL($raceData['ID']), + 'prihlasky' => strtotime($raceData['EntryDate1']), + 'prihlasky1' => strtotime($raceData['EntryDate2']), + 'prihlasky2' => strtotime($raceData['EntryDate3']), + 'etap' => $raceData['Stages'], + 'vicedenni' => ($raceData['Stages']>1?1:0), + 'oddil' => $oddily, + 'modify_flag' => 0, + 'kategorie' => implode(';', $classNames ), + 'oris_entry_start' => !empty($raceData['EntryStart']) ? $raceData['EntryStart'] : null + ]); + } catch (OrisException $e) { + return null; + } + } + + function getRacesList($fromDate, $toDate) { + try { + $racesData = $this->service->getEventList($fromDate, $toDate, 1); + $rows = array(); + foreach($racesData as $oneRace) { + $oddily = $this->getClubs($oneRace); + + $row = array(); + $row[] = $oneRace['ID']; + $row[] = $oneRace['Date']; + $row[] = $oneRace['Name']; + $row[] = $oddily; + $rows[] = $row; + } + return $rows; + } catch (OrisException $e) { + return null; + } + } +} + +class ConnectorFactory { + public static function create(): ?ConnectorInterface { + global $g_external_is_connector; + + if ( $g_external_is_connector && class_exists( $g_external_is_connector)) { + return new $g_external_is_connector(); + } + + return null; + } +} diff --git a/lib/OrisDTOs.php b/lib/OrisDTOs.php new file mode 100644 index 0000000..d57f018 --- /dev/null +++ b/lib/OrisDTOs.php @@ -0,0 +1,91 @@ +ext_id = $data['ext_id'] ?? null; + $this->datum = $data['datum'] ?? null; + $this->datum2 = $data['datum2'] ?? null; + $this->nazev = $data['nazev'] ?? null; + $this->misto = $data['misto'] ?? null; + $this->typ = $data['typ'] ?? null; + $this->zebricek2 = $data['zebricek2'] ?? null; + $this->ranking = $data['ranking'] ?? null; + $this->odkaz = $data['odkaz'] ?? null; + $this->prihlasky = $data['prihlasky'] ?? null; + $this->prihlasky1 = $data['prihlasky1'] ?? null; + $this->prihlasky2 = $data['prihlasky2'] ?? null; + $this->prihlasky3 = $data['prihlasky3'] ?? null; + $this->prihlasky4 = $data['prihlasky4'] ?? null; + $this->prihlasky5 = $data['prihlasky5'] ?? null; + $this->etap = $data['etap'] ?? null; + $this->poznamka = $data['poznamka'] ?? null; + $this->vicedenni = $data['vicedenni'] ?? null; + $this->oddil = $data['oddil'] ?? null; + $this->modify_flag = $data['modify_flag'] ?? null; + $this->kategorie = $data['kategorie'] ?? null; + $this->oris_entry_start = $data['oris_entry_start'] ?? null; + $this->typ0 = $data['typ0'] ?? null; + } +} + +class OrisEntryRequestDTO { + public ?string $clubuser; + public ?string $classId; + public ?string $si; + public int $rentSi; + public ?string $note; + public ?string $entryId; + + public function __construct( + ?string $clubuser, + ?string $classId, + ?string $si, + bool $rentSi = false, + ?string $note = null, + ?string $entryId = null + ) { + $this->clubuser = $clubuser; + $this->classId = $classId; + $this->si = $si; + $this->rentSi = $rentSi ? 1 : 0; + $this->note = $note; + $this->entryId = $entryId; + } + + public function toArray(): array { + $data = []; + if ($this->clubuser !== null) $data['clubuser'] = $this->clubuser; + if ($this->classId !== null) $data['class'] = $this->classId; + if ($this->si !== null && $this->si !== '' && $this->si !== '0' && $this->si !== 0) { + $data['si'] = $this->si; + } + $data['rent_si'] = $this->rentSi ? 1 : 0; + if ($this->note !== null && $this->note !== '') $data['note'] = $this->note; + if ($this->entryId !== null) $data['entryid'] = $this->entryId; + return $data; + } +} diff --git a/lib/OrisExceptions.php b/lib/OrisExceptions.php new file mode 100644 index 0000000..4cda17f --- /dev/null +++ b/lib/OrisExceptions.php @@ -0,0 +1,26 @@ +apiStatus = $apiStatus; + $this->apiData = $apiData; + } + + public function getApiStatus() { + return $this->apiStatus; + } + + public function getApiData() { + return $this->apiData; + } +} + +class OrisValidationException extends OrisException {} diff --git a/lib/OrisIntegrationService.php b/lib/OrisIntegrationService.php new file mode 100644 index 0000000..9e379c3 --- /dev/null +++ b/lib/OrisIntegrationService.php @@ -0,0 +1,120 @@ +clubKey = $clubKey; + } + + /** + * Internal generic HTTP request method. + */ + private function makeRequest($method, $params = [], $isPost = false) { + $params['method'] = $method; + $params['format'] = 'json'; + if ($this->clubKey) { + $params['clubkey'] = $this->clubKey; + } + + $ch = curl_init(); + + if ($isPost) { + $postData = http_build_query($params); + curl_setopt($ch, CURLOPT_URL, $this->apiUrl); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); + } else { + $url = $this->apiUrl . '?' . http_build_query($params); + curl_setopt($ch, CURLOPT_URL, $url); + } + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); + + $response = curl_exec($ch); + + if(curl_errno($ch)){ + $error = curl_error($ch); + curl_close($ch); + throw new OrisNetworkException('cURL Error: ' . $error); + } + + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + $decoded = json_decode($response, true); + + if ($httpCode >= 200 && $httpCode < 300 && isset($decoded['Status']) && $decoded['Status'] === 'OK') { + return $decoded['Data'] ?? $decoded; + } else { + $apiStatus = $decoded['Status'] ?? 'Unknown'; + $apiData = $decoded['Data'] ?? null; + $msg = "API Error or HTTP {$httpCode}. Status: {$apiStatus}"; + if ($isPost) { + $msg .= "\nPOST Data sent: " . print_r($params, true); + } + if (is_string($apiData)) { + $msg .= " - " . $apiData; + } + throw new OrisApiException($msg, $apiStatus, $apiData); + } + } + + // --- Write/Mutating Operations (Phase C) --- + + public function createEntry(OrisEntryRequestDTO $dto) { + return $this->makeRequest('createEntry', $dto->toArray(), true); + } + + public function updateEntry(OrisEntryRequestDTO $dto) { + return $this->makeRequest('updateEntry', $dto->toArray(), true); + } + + public function deleteEntry($entryId) { + return $this->makeRequest('deleteEntry', ['entryid' => $entryId], true); + } + + // --- Read-Only and Protected Read Endpoints (Phase A & B) --- + + public function getUser($rgnum) { + return $this->makeRequest('getUser', ['rgnum' => $rgnum]); + } + + public function getClubUsers($userId) { + return $this->makeRequest('getClubUsers', ['user' => $userId]); + } + + public function getEventEntries($eventId) { + return $this->makeRequest('getEventEntries', ['eventid' => $eventId]); + } + + public function getEvent($eventId) { + return $this->makeRequest('getEvent', ['id' => $eventId]); + } + + public function getEventList($fromDate, $toDate, $all = 1) { + return $this->makeRequest('getEventList', [ + 'all' => $all, + 'datefrom' => $fromDate, + 'dateto' => $toDate + ]); + } + + public function getRegistration($sport, $year) { + return $this->makeRequest('getRegistration', [ + 'sport' => $sport, + 'year' => $year + ]); + } +} diff --git a/lib/oris_sync.inc.php b/lib/oris_sync.inc.php new file mode 100644 index 0000000..44a64d5 --- /dev/null +++ b/lib/oris_sync.inc.php @@ -0,0 +1,370 @@ +getUser($rgnum); + if (is_array($userApiRes) && isset($userApiRes['ID'])) { + $globalUserId = $userApiRes['ID']; + + // Now get the club user ID + try { + $clubUsersRes = $service->getClubUsers($globalUserId); + if (is_array($clubUsersRes)) { + $clubUsers = $clubUsersRes; + // Check if it's associative array representing a single user directly + if (isset($clubUsers['ID'])) { + $clubUsers = [$clubUsers]; + } + + // We must find the correct clubuser entry for the current club + // First, try to fetch current club key from config + global $g_external_is_club_id; + $clubId = $g_external_is_club_id ?? null; + + foreach ($clubUsers as $cu) { + if (isset($cu['ID'])) { + // If club ID is known, prefer that match + if ($clubId && isset($cu['ClubID']) && $cu['ClubID'] == $clubId) { + $clubuser = $cu['ID']; + break; + } + // Otherwise, just take the first one or valid one + if (empty($clubuser)) { + $clubuser = $cu['ID']; + } + } + } + } + } catch (Exception $e) { + $errMsg = $e->getMessage(); + logMessage(" - Warning: getClubUsers failed for user ID $globalUserId: $errMsg"); + if ($e instanceof OrisNetworkException || ($e instanceof OrisApiException && strpos($errMsg, 'API Error or HTTP 5') !== false)) { + logMessage(" - Network error getting club users. Skipping to keep PENDING."); + return 'queued'; + } + } + + if (empty($clubuser)) { + logMessage(" - Warning: Could not resolve ORIS Club User ID for user ID $globalUserId"); + } + } else { + logMessage(" - Warning: Could not resolve ORIS User ID for rgnum $rgnum"); + } + } catch (Exception $e) { + $errMsg = $e->getMessage(); + logMessage(" - Warning: getUser failed for rgnum $rgnum: $errMsg"); + if ($e instanceof OrisNetworkException || ($e instanceof OrisApiException && strpos($errMsg, 'API Error or HTTP 5') !== false)) { + logMessage(" - Network error getting user. Skipping to keep PENDING."); + return 'queued'; + } + } + } + } + } + + // Get Race ORIS ID + $raceQuery = "SELECT * FROM `" . TBL_RACE . "` WHERE `id` = " . (int)$raceId; + $raceRes = query_db($raceQuery); + $raceRow = mysqli_fetch_assoc($raceRes); + + // Ensure the race was imported from ORIS + $comp = $raceRow['ext_id'] ?? null; + if (empty($comp)) { + logMessage(" - Skipped: Race $raceId is not imported from ORIS (no ext_id). Marking LOCAL_ONLY."); + $updateQuery = "UPDATE `" . TBL_ZAVXUS . "` SET `sync_status` = 'LOCAL_ONLY' WHERE `id` = " . (int)$id; + query_db($updateQuery); + return; + } + + // Ignore relays and sprint relays + // S is typically for štafety (relays) in local DB + if ($raceRow && isset($raceRow['typ0']) && $raceRow['typ0'] === 'S') { + logMessage(" - Skipped: Race $raceId is a relay (typ0 = S). Marking LOCAL_ONLY."); + $updateQuery = "UPDATE `" . TBL_ZAVXUS . "` SET `sync_status` = 'LOCAL_ONLY' WHERE `id` = " . (int)$id; + query_db($updateQuery); + return; + } + + // Fetch Classes from ORIS Event to map the string category (e.g. H21) to the ORIS class ID + $classId = null; + $katName = $row['kat']; + if (!empty($comp)) { + try { + $eventRes = $service->getEvent($comp); + if (is_array($eventRes) && isset($eventRes['Classes'])) { + $classes = is_array($eventRes['Classes']) ? $eventRes['Classes'] : []; + + foreach ($classes as $cls) { + if (!is_array($cls)) continue; + $clsName = $cls['Name'] ?? ''; + // Some categories might have different spacing or case + if (trim($clsName) === trim($katName)) { + $classId = $cls['ID'] ?? null; + break; + } + } + } + } catch (Exception $e) { + $errMsg = $e->getMessage(); + logMessage(" - Warning: getEvent failed for event $comp: $errMsg"); + if ($e instanceof OrisNetworkException || ($e instanceof OrisApiException && strpos($errMsg, 'API Error or HTTP 5') !== false)) { + logMessage(" - Network error getting event. Skipping to keep PENDING."); + return 'queued'; + } + } + } + + if (empty($classId)) { + logMessage(" - Warning: Could not resolve ORIS Class ID for category '$katName'"); + $errorPayload = correct_sql_string(json_encode(['status' => 'error', 'message' => "Nelze spárovat kategorii '$katName' s ORISem."])); + $failedStatus = 'FAILED_' . strtoupper($action); + $updateQuery = "UPDATE `" . TBL_ZAVXUS . "` + SET `sync_status` = '$failedStatus', + `sync_error_payload` = '$errorPayload' + WHERE `id` = " . (int)$id; + query_db($updateQuery); + return false; + } + + $si = $row['si_chip']; + if (empty($si) && !empty($userRow['si_chip'])) { + $si = $userRow['si_chip']; + } + $rentSi = $row['rent_si'] ?? 0; // assuming rent_si is added or mapped + $note = $row['pozn'] ?? ''; + + $response = []; + logMessage(" - Sending $action request to ORIS API. clubuser: $clubuser, class: $classId (mapped from $katName), si: $si"); + + if (empty($clubuser)) { + logMessage(" - Failed: Cannot perform action '$action' because ORIS Club User ID (clubuser) could not be resolved."); + $errorPayload = correct_sql_string(json_encode(['status' => 'error', 'message' => 'Chybí ORIS ID uživatele v klubu (clubuser).'])); + $failedStatus = 'FAILED_' . strtoupper($action); + $updateQuery = "UPDATE `" . TBL_ZAVXUS . "` + SET `sync_status` = '$failedStatus', + `sync_error_payload` = '$errorPayload' + WHERE `id` = " . (int)$id; + query_db($updateQuery); + return false; + } + + try { + if ($action === 'create') { + // Check if it already exists before creating to avoid "Již přihlášen" + $existingEntryId = null; + if (!empty($comp) && !empty($clubuser)) { + try { + $entriesRes = $service->getEventEntries($comp); + if (is_array($entriesRes)) { + $entries = $entriesRes; + foreach ($entries as $entry) { + if (isset($entry['ClubUserID']) && $entry['ClubUserID'] == $clubuser) { + $existingEntryId = $entry['ID']; + logMessage(" - Found existing ORIS Entry ID $existingEntryId for clubuser $clubuser during create. Switching to update."); + break; + } + } + } + } catch (Exception $e) { + logMessage(" - Warning: getEventEntries failed: " . $e->getMessage()); + } + } + + if (!empty($existingEntryId)) { + $updateDto = new OrisEntryRequestDTO($clubuser, $classId, $si, (bool)$rentSi, $note, $existingEntryId); + $response = $service->updateEntry($updateDto); + // Also update the action string so log messages below make sense + $action = 'update'; + } else { + $createDto = new OrisEntryRequestDTO($clubuser, $classId, $si, (bool)$rentSi, $note); + $response = $service->createEntry($createDto); + } + } elseif ($action === 'update') { + $entryIdToUpdate = $row['oris_entry_id'] ?? null; + + if (empty($entryIdToUpdate) && !empty($comp) && !empty($clubuser)) { + logMessage(" - Warning: Missing ORIS Entry ID for update. Attempting to fetch from ORIS."); + try { + $entriesRes = $service->getEventEntries($comp); + if (is_array($entriesRes)) { + $entries = $entriesRes; + foreach ($entries as $entry) { + if (isset($entry['ClubUserID']) && $entry['ClubUserID'] == $clubuser) { + $entryIdToUpdate = $entry['ID']; + logMessage(" - Found ORIS Entry ID $entryIdToUpdate for clubuser $clubuser"); + break; + } + } + } + } catch (Exception $e) { + logMessage(" - Warning: getEventEntries failed: " . $e->getMessage()); + } + } + + if (empty($entryIdToUpdate)) { + // It was never created on ORIS side successfully, so let's fall back to create instead of failing + logMessage(" - Warning: Missing ORIS Entry ID for update. Falling back to create."); + $createDto = new OrisEntryRequestDTO($clubuser, $classId, $si, (bool)$rentSi, $note); + $response = $service->createEntry($createDto); + } else { + $updateDto = new OrisEntryRequestDTO($clubuser, $classId, $si, (bool)$rentSi, $note, $entryIdToUpdate); + $response = $service->updateEntry($updateDto); + } + } elseif ($action === 'delete') { + $entryIdToDelete = $row['oris_entry_id'] ?? null; + + // If we don't have the entry ID locally, we must fetch it from ORIS first + if (empty($entryIdToDelete) && !empty($comp) && !empty($clubuser)) { + logMessage(" - Warning: Missing ORIS Entry ID for delete. Attempting to fetch from ORIS."); + try { + $entriesRes = $service->getEventEntries($comp); + if (is_array($entriesRes)) { + $entries = $entriesRes; + foreach ($entries as $entry) { + if (isset($entry['ClubUserID']) && $entry['ClubUserID'] == $clubuser) { + $entryIdToDelete = $entry['ID']; + logMessage(" - Found ORIS Entry ID $entryIdToDelete for clubuser $clubuser"); + break; + } + } + } + } catch (Exception $e) { + logMessage(" - Warning: getEventEntries failed: " . $e->getMessage()); + } + } + + if (empty($entryIdToDelete)) { + // Already doesn't exist remotely or could not be found + logMessage(" - Warning: Could not find ORIS Entry ID to delete. Assuming already deleted."); + $response = ['ID' => null]; + } else { + $response = $service->deleteEntry($entryIdToDelete); + } + } + + // Log the exact raw payload sent to ORIS if available (custom debug info) + if (isset($response['request'])) { + logMessage(" - Raw POST Data: " . $response['request']); + } + + // Action succeeded since no exception was thrown + // 'create' usually returns ID in $response['ID'] + // 'update' might not return the ID, so we use the one we just found/used + $entryId = $response['ID'] ?? null; + if (empty($entryId)) { + if ($action === 'update' && !empty($entryIdToUpdate)) { + $entryId = $entryIdToUpdate; + } elseif ($action === 'update' && !empty($existingEntryId)) { // from the create fallback block + $entryId = $existingEntryId; + } else { + $entryId = $row['oris_entry_id']; + } + } + + logMessage(" - Success: Action $action completed. ORIS Entry ID: " . ($entryId ?: "N/A")); + + if ($action === 'delete') { + // Remove the row locally after successful delete + $updateQuery = "DELETE FROM `" . TBL_ZAVXUS . "` WHERE `id` = " . (int)$id; + query_db($updateQuery); + } else { + // Update the row + $updateQuery = "UPDATE `" . TBL_ZAVXUS . "` + SET `sync_status` = 'SYNCED', + `oris_entry_id` = " . ($entryId ? (int)$entryId : "NULL") . ", + `sync_timestamp` = NOW(), + `sync_error_payload` = NULL + WHERE `id` = " . (int)$id; + query_db($updateQuery); + } + return true; + + } catch (Exception $e) { + $errMsg = $e->getMessage(); + logMessage(" - Failed: Action $action encountered an error: $errMsg"); + + if ($e instanceof OrisNetworkException || ($e instanceof OrisApiException && strpos($errMsg, 'API Error or HTTP 5') !== false)) { + // It's a temporary network error or 5xx server error, keep it as PENDING and retry later + logMessage(" - Will keep entry in PENDING status for retry later because it is a network error."); + return 'queued'; + } + + $errorData = [ + 'status' => 'error', + 'message' => $errMsg, + 'api_status' => ($e instanceof OrisApiException) ? $e->getApiStatus() : 'Exception' + ]; + $errorPayload = correct_sql_string(json_encode($errorData)); + $failedStatus = 'FAILED_' . strtoupper($action); + $updateQuery = "UPDATE `" . TBL_ZAVXUS . "` + SET `sync_status` = '$failedStatus', + `sync_error_payload` = '$errorPayload' + WHERE `id` = " . (int)$id; + query_db($updateQuery); + return false; + } +} + +function getOrisSyncError($id) { + $q = query_db("SELECT sync_error_payload FROM `" . TBL_ZAVXUS . "` WHERE `id` = " . (int)$id); + if ($q && $r = mysqli_fetch_assoc($q)) { + if (!empty($r['sync_error_payload'])) { + $err = json_decode($r['sync_error_payload'], true); + return $err['message'] ?? 'Neznámá chyba'; + } + } + return 'Neznámá chyba'; +} +?> diff --git a/nav.inc.php b/nav.inc.php index 218bcde..df810fa 100644 --- a/nav.inc.php +++ b/nav.inc.php @@ -100,6 +100,8 @@ function DrawMenuGroupHeader($name) DrawMenuGroupHeader('Menu přihlašovatele'); DrawMenuItem('Přihlášky na závody',_REGISTRATOR_GROUP_ID_,1); DrawMenuItem('Editace závodů',_REGISTRATOR_GROUP_ID_,4); + DrawMenuItemStatic('Synchronizuj přihlášky s ORISem', 'adm_oris_sync.php'); + DrawMenuItemStatic('ORIS Sync Log', 'rg_oris_sync_log.php'); } if(IsLoggedManager()) { diff --git a/oris_sync_daemon.php b/oris_sync_daemon.php new file mode 100644 index 0000000..1552854 --- /dev/null +++ b/oris_sync_daemon.php @@ -0,0 +1,70 @@ += DATE_SUB(CURDATE(), INTERVAL 1 DAY) OR r.datum IS NULL) + ORDER BY ISNULL(r.oris_entry_start), r.oris_entry_start ASC + "; +$res = query_db($query); + +while ($row = mysqli_fetch_assoc($res)) { + $entryStartStr = $row['oris_entry_start']; + if (!empty($entryStartStr)) { + $entryStartTime = strtotime($entryStartStr); + $now = time(); + if ($entryStartTime > $now) { + $diff = $entryStartTime - $now; + if ($diff <= 65) { // 65 seconds buffer for cron running every minute + logMessage("Prihlasky se oteviraji za $diff seconds (at $entryStartStr). Jdu sapt pred pokracovanim..."); + sleep($diff); + } else { + // Race is not open yet and more than a minute away, skip for now + logMessage("Preskakuju prihlasku ID {$row['id']} - Zavod otevira prihlasky v $entryStartStr (za $diff s)."); + continue; + } + } + } + + $action = ''; + if ($row['sync_status'] === 'PENDING_CREATE' || $row['sync_status'] === 'FAILED_CREATE') { + $action = 'create'; + } elseif ($row['sync_status'] === 'PENDING_UPDATE' || $row['sync_status'] === 'FAILED_UPDATE') { + $action = 'update'; + } elseif ($row['sync_status'] === 'PENDING_DELETE' || $row['sync_status'] === 'FAILED_DELETE') { + $action = 'delete'; + } + + if (!empty($action)) { + processEntry($row, $action, $service); + } +} +?> diff --git a/race_edit.php b/race_edit.php index 4fe2f4d..02e36fa 100644 --- a/race_edit.php +++ b/race_edit.php @@ -372,6 +372,11 @@ function toggleButtonState() { +oris_entry_start !== null) { + echo ''; +} +?> + $zaznam['z_id'], 'action' => $action]; + } + } + } + } +} + +$sync_errors = []; +if ($has_ext_id && count($sync_queue) > 0) { + global $g_oris_club_key; + if (!empty($g_oris_club_key)) { + $service = new OrisIntegrationService($g_oris_club_key); + foreach ($sync_queue as $sq) { + $rowQuery = query_db("SELECT * FROM `" . TBL_ZAVXUS . "` WHERE `id` = " . (int)$sq['id']); + if ($rowQuery && $syncRow = mysqli_fetch_assoc($rowQuery)) { + $syncRes = processEntry($syncRow, $sq['action'], $service); + if ($syncRes !== true && $syncRes !== 'queued') { + $sync_errors[] = "Záznam " . $sq['id'] . ": " . getOrisSyncError($sq['id']); + } } } } @@ -40,6 +75,11 @@ ?> + +
+ Chyby při synchronizaci s ORIS:

+ ', array_map('htmlspecialchars', $sync_errors)); ?> +

+ Zpět na přehled +
+ diff --git a/rg_oris_sync_log.php b/rg_oris_sync_log.php new file mode 100644 index 0000000..56e9189 --- /dev/null +++ b/rg_oris_sync_log.php @@ -0,0 +1,33 @@ +'; +if (file_exists($logFile)) { + $content = file_get_contents($logFile); + if ($content !== false) { + echo nl2br(htmlspecialchars($content)); + } else { + echo "Error reading log file."; + } +} else { + echo "Log file does not exist yet."; +} +echo ''; + +echo '
Zpět
'; + +HTML_Footer(); +?> \ No newline at end of file diff --git a/us_race_regoff_exc.php b/us_race_regoff_exc.php index 4b72cd9..a0554f4 100644 --- a/us_race_regoff_exc.php +++ b/us_race_regoff_exc.php @@ -4,6 +4,7 @@ require_once ("./connect.inc.php"); require_once ("./sess.inc.php"); +require_once ("./lib/oris_sync.inc.php"); if (!IsLogged()) { @@ -25,18 +26,53 @@ if (!$entry_lock) { - @$vysledek=query_db("DELETE FROM ".TBL_ZAVXUS." WHERE id_zavod = '$id_zav' AND id_user = '$id_us'"); - if ($vysledek !== false && mysqli_affected_rows($db_conn) > 0) { - query_db("UPDATE ".TBL_RACE." SET prihlasenych = GREATEST(0, prihlasenych - 1) WHERE id = '$id_zav'"); + $vysledek_z=query_db("SELECT ext_id FROM ".TBL_RACE." WHERE id='$id_zav'"); + $zaznam_z = mysqli_fetch_array($vysledek_z); + $has_ext_id = !empty($zaznam_z['ext_id']); + + $vysledek_zx=query_db("SELECT id, sync_status FROM ".TBL_ZAVXUS." WHERE id_zavod='$id_zav' AND id_user='$id_us'"); + $zaznam_zx = mysqli_fetch_array($vysledek_zx); + + $sync_error_msg = null; + if ($zaznam_zx) { + $zx_id = $zaznam_zx['id']; + $sync_status = $zaznam_zx['sync_status']; + + if ($has_ext_id && $sync_status !== 'PENDING_CREATE') { + $vysledek = query_db("UPDATE ".TBL_ZAVXUS." SET sync_status='PENDING_DELETE' WHERE id = '$zx_id'"); + if ($vysledek !== false) { + global $g_oris_club_key; + if (!empty($g_oris_club_key)) { + $service = new OrisIntegrationService($g_oris_club_key); + $rowQuery = query_db("SELECT * FROM `" . TBL_ZAVXUS . "` WHERE `id` = '$zx_id'"); + if ($rowQuery && $syncRow = mysqli_fetch_assoc($rowQuery)) { + $syncRes = processEntry($syncRow, 'delete', $service); + if ($syncRes === true || $syncRes === 'queued') { + query_db("UPDATE ".TBL_RACE." SET prihlasenych = GREATEST(0, prihlasenych - 1) WHERE id = '$id_zav'"); + } else { + $sync_error_msg = getOrisSyncError($zx_id); + } + } + } + } + } else { + @$vysledek=query_db("DELETE FROM ".TBL_ZAVXUS." WHERE id = '$zx_id'"); + if ($vysledek !== false && mysqli_affected_rows($db_conn) > 0) { + query_db("UPDATE ".TBL_RACE." SET prihlasenych = GREATEST(0, prihlasenych - 1) WHERE id = '$id_zav'"); + } + } } } ?> \ No newline at end of file + diff --git a/us_race_regon_exc.php b/us_race_regon_exc.php index 795bf99..0fa2fdc 100644 --- a/us_race_regon_exc.php +++ b/us_race_regon_exc.php @@ -6,6 +6,7 @@ require_once ("./sess.inc.php"); require_once ("./common.inc.php"); require_once ("./common_race.inc.php"); +require_once ("./lib/oris_sync.inc.php"); if (!IsLogged()) { @@ -34,7 +35,7 @@ $pozn=correct_sql_string($pozn); $pozn2=correct_sql_string($pozn2); - @$vysledek_z=query_db("SELECT datum, vicedenni, prihlasky, prihlasky1, prihlasky2, prihlasky3, prihlasky4, prihlasky5, transport FROM ".TBL_RACE." WHERE id=$id_zav"); + @$vysledek_z=query_db("SELECT datum, vicedenni, prihlasky, prihlasky1, prihlasky2, prihlasky3, prihlasky4, prihlasky5, transport, ext_id FROM ".TBL_RACE." WHERE id=$id_zav"); $zaznam_z = mysqli_fetch_array($vysledek_z); $termin = raceterms::GetCurr4RegTerm($zaznam_z); @@ -59,32 +60,99 @@ $ubytovani = !isset($ubytovani)? 'null': 1; $novy = !isset($novy)? 0: (int)$novy; + $has_ext_id = !empty($zaznam_z['ext_id']); + $inserted_or_updated_id = 0; + $sync_action = ''; + $is_new_insert = false; + $previous_state = null; + if ($novy) { $vysledek=query_db("SELECT * FROM ".TBL_ZAVXUS." WHERE id_zavod='$id_zav' and id_user='$id_us'"); if ($vysledek != FALSE && ($zaznam = mysqli_fetch_array($vysledek)) != FALSE ) { // latest new == update - query_db("UPDATE ".TBL_ZAVXUS." SET kat='$kat', pozn='$pozn', pozn_in='$pozn2', termin='$termin', transport=$transport, sedadel=$sedadel, ubytovani=$ubytovani WHERE id='".$zaznam['id']."'"); + $previous_state = $zaznam; + $sync_status_update = ($has_ext_id && $zaznam['sync_status'] !== 'PENDING_CREATE') ? ", sync_status='PENDING_UPDATE'" : ""; + $sync_action = ($has_ext_id && $zaznam['sync_status'] === 'PENDING_CREATE') ? 'create' : 'update'; + query_db("UPDATE ".TBL_ZAVXUS." SET kat='$kat', pozn='$pozn', pozn_in='$pozn2', termin='$termin', transport=$transport, sedadel=$sedadel, ubytovani=$ubytovani".$sync_status_update." WHERE id='".$zaznam['id']."'"); + $inserted_or_updated_id = $zaznam['id']; } else { // really new - $vysledek = query_db("INSERT INTO ".TBL_ZAVXUS." (id_user, id_zavod, kat, pozn, pozn_in, termin, transport, sedadel, ubytovani) VALUES ('$id_us','$id_zav','$kat','$pozn','$pozn2','$termin',$transport, $sedadel, $ubytovani)"); + $is_new_insert = true; + $sync_status = $has_ext_id ? 'PENDING_CREATE' : 'LOCAL_ONLY'; + $sync_action = $has_ext_id ? 'create' : ''; + $vysledek = query_db("INSERT INTO ".TBL_ZAVXUS." (id_user, id_zavod, kat, pozn, pozn_in, termin, transport, sedadel, ubytovani, sync_status) VALUES ('$id_us','$id_zav','$kat','$pozn','$pozn2','$termin',$transport, $sedadel, $ubytovani, '$sync_status')"); if ($vysledek !== false && mysqli_affected_rows($db_conn) > 0) { + $inserted_or_updated_id = mysqli_insert_id($db_conn); query_db("UPDATE ".TBL_RACE." SET prihlasenych = prihlasenych + 1 WHERE id = '$id_zav'"); } } } else { // update - query_db("UPDATE ".TBL_ZAVXUS." SET kat='$kat', pozn='$pozn', pozn_in='$pozn2', transport=$transport, sedadel=$sedadel, ubytovani=$ubytovani WHERE id='".$id_z."'"); + $vysledek=query_db("SELECT * FROM ".TBL_ZAVXUS." WHERE id='".$id_z."'"); + if ($vysledek != FALSE && ($zaznam = mysqli_fetch_array($vysledek)) != FALSE ) + { + $previous_state = $zaznam; + $sync_status_update = ($has_ext_id && $zaznam['sync_status'] !== 'PENDING_CREATE') ? ", sync_status='PENDING_UPDATE'" : ""; + $sync_action = ($has_ext_id && $zaznam['sync_status'] === 'PENDING_CREATE') ? 'create' : 'update'; + query_db("UPDATE ".TBL_ZAVXUS." SET kat='$kat', pozn='$pozn', pozn_in='$pozn2', transport=$transport, sedadel=$sedadel, ubytovani=$ubytovani".$sync_status_update." WHERE id='".$id_z."'"); + $inserted_or_updated_id = $id_z; + } + } + + $sync_error_msg = null; + if ($has_ext_id && $inserted_or_updated_id > 0 && $sync_action !== '') { + global $g_oris_club_key; + if (!empty($g_oris_club_key)) { + $service = new OrisIntegrationService($g_oris_club_key); + $rowQuery = query_db("SELECT * FROM `" . TBL_ZAVXUS . "` WHERE `id` = " . (int)$inserted_or_updated_id); + if ($rowQuery && $syncRow = mysqli_fetch_assoc($rowQuery)) { + $syncRes = processEntry($syncRow, $sync_action, $service); + if ($syncRes !== true && $syncRes !== 'queued') { + $sync_error_msg = getOrisSyncError($inserted_or_updated_id); + // Rollback changes + if ($is_new_insert) { + query_db("DELETE FROM ".TBL_ZAVXUS." WHERE id = '$inserted_or_updated_id'"); + query_db("UPDATE ".TBL_RACE." SET prihlasenych = prihlasenych - 1 WHERE id = '$id_zav'"); + } else if ($previous_state) { + $prev_kat = correct_sql_string($previous_state['kat']); + $prev_pozn = correct_sql_string($previous_state['pozn']); + $prev_pozn_in = correct_sql_string($previous_state['pozn_in']); + $prev_termin = (int)$previous_state['termin']; + $prev_transport = (int)$previous_state['transport']; + $prev_sedadel = (!isset($previous_state['sedadel']) || $previous_state['sedadel'] === null) ? 'null' : (int)$previous_state['sedadel']; + $prev_ubytovani = (!isset($previous_state['ubytovani']) || $previous_state['ubytovani'] === null) ? 'null' : (int)$previous_state['ubytovani']; + $prev_sync_status = correct_sql_string($previous_state['sync_status']); + + query_db("UPDATE ".TBL_ZAVXUS." SET kat='$prev_kat', pozn='$prev_pozn', pozn_in='$prev_pozn_in', termin='$prev_termin', transport=$prev_transport, sedadel=$prev_sedadel, ubytovani=$prev_ubytovani, sync_status='$prev_sync_status' WHERE id='$inserted_or_updated_id'"); + } + } + } + } } } } } ?> + +
+ Chyba při synchronizaci s ORIS:

+ +

+ Zpět na přehled +
+ + \ No newline at end of file +