Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ playwright-report/
test-results/
.agents/*
skills-lock.json
secure
secure
.DS_Store
78 changes: 76 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,35 @@
"BANK_MOCK_PORT": "10300"
}
},
{
"name": "Debug ORIS Mock Server",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "node",
"runtimeArgs": [
"--import",
"tsx"
],
"args": [
"mocks/oris/src/server.ts"
],
"console": "integratedTerminal",
"skipFiles": [
"<node_internals>/**"
],
"env": {
"ORIS_MOCK_HOST": "0.0.0.0",
"ORIS_MOCK_PORT": "10301",
"ORIS_MOCK_DB_HOST": "db",
"ORIS_MOCK_DB_PORT": "3306",
"ORIS_MOCK_DB_USER": "root",
"ORIS_MOCK_DB_PASSWORD": "dev4password",
"ORIS_MOCK_DB_NAME": "oris_mock",
"ORIS_MOCK_DEFAULT_CLUB_ID": "205",
"ORIS_MOCK_DEFAULT_CLUB_ABBR": "ZBM"
}
},
{
"name": "Debug Bank Mock Server (Watch)",
"type": "node",
Expand All @@ -57,18 +86,63 @@
}
},
{
"name": "Start Bank Mock Server",
"name": "Debug ORIS Mock Server (Watch)",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "node",
"runtimeArgs": [
"--import",
"tsx",
"--watch"
],
"args": [
"mocks/oris/src/server.ts"
],
"console": "integratedTerminal",
"restart": true,
"skipFiles": [
"<node_internals>/**"
],
"env": {
"ORIS_MOCK_HOST": "0.0.0.0",
"ORIS_MOCK_PORT": "10301",
"ORIS_MOCK_DB_HOST": "db",
"ORIS_MOCK_DB_PORT": "3306",
"ORIS_MOCK_DB_USER": "root",
"ORIS_MOCK_DB_PASSWORD": "dev4password",
"ORIS_MOCK_DB_NAME": "oris_mock",
"ORIS_MOCK_DEFAULT_CLUB_ID": "205",
"ORIS_MOCK_DEFAULT_CLUB_ABBR": "ZBM"
}
},
{
"name": "Run Bank Mock Server",
"type": "node-terminal",
"request": "launch",
"command": "npm run mock:bank",
"cwd": "${workspaceFolder}"
},
{
"name": "Start Bank Mock Server (Watch)",
"name": "Run ORIS Mock Server",
"type": "node-terminal",
"request": "launch",
"command": "npm run mock:oris",
"cwd": "${workspaceFolder}"
},
{
"name": "Run Bank Mock Server (Watch)",
"type": "node-terminal",
"request": "launch",
"command": "npm run mock:bank:watch",
"cwd": "${workspaceFolder}"
},
{
"name": "Run ORIS Mock Server (Watch)",
"type": "node-terminal",
"request": "launch",
"command": "npm run mock:oris:watch",
"cwd": "${workspaceFolder}"
}
]
}
24 changes: 20 additions & 4 deletions Docs/Development.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,21 @@ Bank mock pro vývoj:
docker compose -p members-dev -f docker-compose.dev.yml exec web npm run mock:bank
```

* admin UI: [http://127.0.0.1:10300/__admin](http://127.0.0.1:10300/__admin)
* admin UI: [http://127.0.0.1:10300/__testbench](http://127.0.0.1:10300/__testbench)
* API endpoint pro PHP konektor: `http://127.0.0.1:10300/rbcz/premium/api`
* vývojová konfigurace v `docker/config/dev/_cfg.php` už používá `RaiffeisenbankMockConnector`

ORIS mock pro vývoj:

```bash
docker compose -p members-dev -f docker-compose.dev.yml exec web npm run mock:oris
```

* admin UI: [http://127.0.0.1:10301/__testbench](http://127.0.0.1:10301/__testbench)
* API endpoint pro ORIS mock: `http://127.0.0.1:10301/`
* vývojová konfigurace v `docker/config/dev/_cfg.php` už používá mock server `http://127.0.0.1:10301/`


## Automatické testy

V kořenovém adresáři `members` spusť:
Expand All @@ -53,19 +64,24 @@ docker compose -p members-autotest -f docker-compose.autotest.yml exec web npm r
docker compose -p members-autotest -f docker-compose.autotest.yml down
```

Přepínač `--wait` počká, až budou kontejnery označené jako `healthy`. V autotest stacku to znamená, že je připravená databáze, běží web a bank mock odpovídá na health endpoint, takže testy můžeš spustit hned po startu bez ruční prodlevy.
Přepínač `--wait` počká, až budou kontejnery označené jako `healthy`. V autotest stacku to znamená, že je připravená databáze, běží web a bank a ORIS mock odpovídají na health endpoint, takže testy můžeš spustit hned po startu bez další prodlevy.

## Manuální testy

Pro ruční pozorování běžící aplikace a databáze přidej override soubor `docker-compose.autotest.observe.yml`:
Pro manuální testy nebo analýzu automatických testů přidej override soubor `docker-compose.autotest.observe.yml`:

```bash
docker compose -p members-autotest -f docker-compose.autotest.yml -f docker-compose.autotest.observe.yml up -d --build --wait
...
```
Je potřeba ručně přenastavit _cfg.php na $g_baseadr='http://127.0.0.1:10090/members/';

Dostupné služby:

* [members](http://127.0.0.1:10090/members)
* [phpMyAdmin](http://127.0.0.1:10091)
* [bank](http://127.0.0.1:10093/_admin)
* [bank](http://127.0.0.1:10093/__testbench)
* [ORIS](http://127.0.0.1:10094/__testbench)

## Minimální konfigurace

Expand Down
3 changes: 3 additions & 0 deletions Docs/X_cfg.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@
$g_external_race_transport_default = 0;
$g_external_race_accommodation_default = 0;

$g_oris_base_url = 'https://oris.ceskyorientak.cz/';
$g_oris_club_key = '';

$g_custom_entry_list_text = '';

?>
3 changes: 2 additions & 1 deletion _SQL/zmeny.sql.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?
$action = $_REQUEST['action'] ?? null;
$action = $_REQUEST['action'] ?? null;

$zmeny_list = array();
function AddZmenyFile($version)
Expand Down Expand Up @@ -28,6 +28,7 @@ function AddZmenyFile($version)
AddZmenyFile('3.4.5.651');
AddZmenyFile('3.4.5.652');
AddZmenyFile('3.4.5.655');
AddZmenyFile('3.4.5.658');
AddZmenyFile('3.4.6.656');
AddZmenyFile('3.4.7.660');
//#############################################################################
Expand Down
24 changes: 24 additions & 0 deletions _SQL/zmeny_3.4.5.658.sql.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?
// zmeny pro verzi 3.4.5.658 - ORIS API integration

$version_upd = '3.4.5.658';

//#############################################################################

require_once ('prepare.inc.php');

//#############################################################################
// SQL dotazy pro zmenu db. na novejsi verzi
//############################################################################
$sql[0] = "ALTER TABLE `".TBL_ZAVXUS."`
ADD COLUMN `entry_id` INT UNSIGNED NULL,
ADD COLUMN `sync_status` ENUM('LOCAL_ONLY', 'SYNCED', 'PENDING_CREATE', 'PENDING_UPDATE', 'PENDING_DELETE', 'FAILED_CREATE', 'FAILED_UPDATE', 'FAILED_DELETE') NOT NULL DEFAULT 'LOCAL_ONLY',
ADD COLUMN `sync_timestamp` DATETIME NULL,
ADD COLUMN `sync_error_payload` TEXT NULL,
ADD INDEX `sync_status` (`sync_status`)";

$sql[1] = "ALTER TABLE `".TBL_RACE."`
ADD COLUMN `entry_start` DATETIME NULL";

require_once ('action.inc.php');
?>
30 changes: 18 additions & 12 deletions ads_oris.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,25 @@ 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 = OrisIntegrationServiceFactory::create();
$orisWriteEnabled = $service->hasClubKey();
$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
Expand Down Expand Up @@ -138,7 +142,9 @@ function startsWith( $haystack, $needle ) {
$oris_user_id = $arr_oris["user"][$fullreg]->getUserId();
$local_si = $zaznam['si'];
$local_id = $zaznam['id'];
$oris_si .= "&nbsp;<a href=\"ads_oris_si_sync.php?oris_id=$oris_user_id&id=$local_id\" title=\"Synchronizovat SI do ORISu (nastavit na $local_si)\">[<<]</a>";
if ($orisWriteEnabled) {
$oris_si .= "&nbsp;<a href=\"ads_oris_si_sync.php?oris_id=$oris_user_id&id=$local_id\" title=\"Synchronizovat SI do ORISu (nastavit na $local_si)\">[<<]</a>";
}
}
$row[] = $oris_si;
$arr_oris["members"][$fullreg]=1;
Expand Down
30 changes: 12 additions & 18 deletions ads_oris_si_sync.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
require_once ("./sess.inc.php");
require_once ("./cfg/_cfg.php");
require_once ("./common.inc.php"); // For GetFirstEmail
require_once ("./lib/OrisIntegrationService.php");

if (!IsLoggedSmallAdmin())
{
Expand All @@ -27,11 +28,7 @@
if ($zaznam)
{
$params = array(
'format' => 'json',
'method' => 'editPerson',
'userid' => $oris_id,
'si' => $zaznam['si_chip'],
'clubkey' => $g_oris_club_key,
'firstname' => $zaznam['jmeno'],
'lastname' => $zaznam['prijmeni'],
'email' => GetFirstEmail($zaznam['email']),
Expand All @@ -40,27 +37,24 @@
'zip' => $zaznam['psc'],
'country' => (!empty($zaznam['narodnost']) ? $zaznam['narodnost'] : 'CZ')
);

$url = "https://oris.ceskyorientak.cz/API/?" . http_build_query($params);

// Use file_get_contents
$response = file_get_contents($url);
$result = json_decode($response);

if ($result && $result->Status == 'OK') {
if (!empty($zaznam['si_chip']) && $zaznam['si_chip'] != 0 && $zaznam['si_chip'] !== '0') {
$params['si'] = $zaznam['si_chip'];
}

$service = OrisIntegrationServiceFactory::create();

try {
$service->editPerson($params);
// Success
header("location: ".$g_baseadr."index.php?id="._SMALL_ADMIN_GROUP_ID_."&subid=2");
} else {
} catch (OrisException $e) {
// Error
require_once ("./header.inc.php");
DrawPageTitle('Chyba synchronizace s ORIS');
echo "Nepodařilo se aktualizovat údaje v systému ORIS.<br>";
echo "<b>Debug info:</b><br>";
echo "URL: " . $url . "<br>";
echo "Raw response: " . htmlspecialchars($response) . "<br>";
echo "Odpověď serveru: " . ($result ? $result->Status : "Unknown error") . "<br>";
if (isset($result->Message)) echo "Zpráva: " . $result->Message . "<br>";
if (!isset($g_oris_club_key) || empty($g_oris_club_key)) echo "<b>Warning: API key is empty!</b><br>";
echo "API URL: " . htmlspecialchars($service->getApiUrl()) . "<br>";
echo "Zpráva: " . htmlspecialchars($e->getMessage()) . "<br>";
echo "<br><a href=\"".$g_baseadr."index.php?id="._SMALL_ADMIN_GROUP_ID_."&subid=2\">Zpět</a>";
HTML_Footer();
}
Expand Down
3 changes: 2 additions & 1 deletion cfg/_cfg.php.default
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ $g_external_is_club_id = '';
$g_external_race_transport_default = 0;
$g_external_race_accommodation_default = 0;

$g_oris_club_key = 'orisClubKey';
$g_oris_base_url = 'https://oris.ceskyorientak.cz/';
$g_oris_club_key = '';

// Identifikator C oblasti v informacnim systemu e.g. JM
$g_external_is_region_C = '';
Expand Down
48 changes: 33 additions & 15 deletions common_race.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,25 +116,43 @@ function CreateNotifyTypeNumber(&$notify)
return $result;
}

function CreateRaceTypeNumber(&$racetype)
{
global $g_racetype_cnt;
global $g_racetype;
$result = 0;
function CreateRaceTypeNumber(&$racetype)
{
global $g_racetype_cnt;
global $g_racetype;

$result = 0;
for($ii=0; $ii<$g_racetype_cnt; $ii++)
{
if(isset($racetype[$ii]) && $racetype[$ii] == 1)
$result += $g_racetype [$ii]['id'];
}
return $result;
}

function CreateModifyFlag(&$mflags)
{
global $g_modify_flag_cnt;
global $g_modify_flag;

}
return $result;
}

function EntryStart2Sql($text)
{
$text = trim((string)$text);
if ($text === '') {
return '';
}

$formats = ['d.m.Y H:i:s', 'j.n.Y H:i:s', 'Y-m-d H:i:s'];
foreach ($formats as $format) {
$date = DateTime::createFromFormat($format, $text);
if ($date !== false && $date->format($format) === $text) {
return $date->format('Y-m-d H:i:s');
}
}

return $text;
}

function CreateModifyFlag(&$mflags)
{
global $g_modify_flag_cnt;
global $g_modify_flag;

$result = 0;
for($ii=0; $ii<$g_modify_flag_cnt; $ii++)
{
Expand Down
Loading