eReal
Evidence nemovitostí a náběrů pro jednu realitní kancelář. Makléři, 116 polí, upravitelné číselníky, přílohy, historie, archiv požadavků Realman a XML monitoring iRMonitor v6. JSON úložiště; kompatibilita Realman exportu čeká na ověření.
Documentation and check-in manual
Releases
Older versions (3)
README
# eReal 0.1.0-alpha.1
eReal je instalovatelná první verze evidence realitních nabídek a náběrů pro jednu kancelář a více makléřů. Používá PHP, Composer, pavel852/php-templates a JSON soubory. Neobsahuje nájemní agendu ani veřejný realitní web.
## Co je hotové
| Část | Funkce |
| --- | --- |
| Přehled | Počty nemovitostí, rezervace, náběry, končící smlouvy, poslední změny |
| Nemovitosti | Založení a editace, 116 polí, stav zakázky, hledání, filtry, tabulka a karty, stažení výběru do JSON |
| Majitel | Kontakty, IČO, adresa, smlouva a její platnost jako součást zakázky |
| Číselníky | 29 upravitelných sad, vlastní hodnoty, názvy a mapování externích kódů |
| Přílohy | Fotografie a dokumenty do 10 MiB, soukromé soubory, kontrola přístupu při stažení |
| Historie | Posledních 50 verzí zakázky, obnova údajů, posledních 2 000 systémových událostí |
| Makléři | Administrátor celé kanceláře, makléř pouze vlastních zakázek, vypnutí účtu, změna hesla |
| Realman | Příjem na `/import`, archiv požadavku v JSON, původní tělo v Base64, náhled mapování a potvrzený import |
| iRMonitor | XML export v6 podle dokumentace 1.7, exportní heslo exwbps, kontakty, historie cen, opakované načítání a převod na náběr |
| Zálohy | Posledních 10 datových stavů před změnou, datový JSON pro správce, plná záloha přes eWeb |
| Instalace | Distribuční manifest pro eUpdate → eWeb, předem přibalené závislosti, inicializace soukromého úložiště |
**Výchozí číselníky a model nejsou prohlášeny za úplnou kopii aktuálního Realmanu.** Pro ověření stejných položek, jejich podmíněného zobrazování, povinnosti a přesných kódů je stále nutný skutečný export a přehled formulářů/číselníků vaší licence. Veškerá zdrojová data importu zůstávají zachována i mimo normalizovaná pole.
## Požadavky
- PHP 8.1–8.x; ověřeno na PHP 8.3.6.
- Rozšíření json, mbstring, fileinfo, curl, dom, zip, ctype.
- Zapisovatelná soukromá složka domény `private/`.
- Bez databázového serveru; stavový JSON má aplikační limit 64 MiB. Pro rozsáhlý provoz plánujte archivaci nebo pozdější databázový adaptér.
- Odchozí HTTPS na `www.irmonitor.cz`, platné exportní oprávnění a samostatné exportní heslo.
- Pro lokální testy navíc Python 3 a PHP CLI s pcntl; není požadováno pro provoz přes FPM.
Závislosti jsou převzaté z dostupného balíčku eSite RC17. Composer 2.7.1 vytvořil optimalizovaný autoload. Přesné SHA-256 knihoven jsou v `resources/dependency-provenance.json`. Samostatná síťová instalace závislostí pomocí Composeru se při instalaci do eWebu nespouští; balíček je úplný.
## Instalace přes eUpdate do eWebu
1. Do projektu eReal v eUpdate vložte **celý tento ZIP**, se zachovaným `install.json` v kořeni. Typ vydání: hlavní aplikace, cíl `hosting`, systém `source`. `software_id` musí zůstat `ereal`.
2. Z eUpdate zkopírujte skutečný instalační odkaz projektu/vydání. V eWebu ho vložte v Domény → eUpdate u cílové domény. Balíček v této konverzaci zatím nebyl zveřejněn v eUpdate ani nasazen na doménu.
3. V náhledu zkontrolujte aplikaci a webový kořen `public`. eWeb nasadí její obsah do `web/`. Databázi nezakládejte.
4. Otevřete doménu nebo `/admin`. První požadavek ověří instalační archiv SHA-256, rozbalí kód do `private/ereal/releases/` a připraví `private/ereal/shared/`.
5. Ve správci souborů eWebu přečtěte `private/ereal/shared/setup-token.txt`. Token vložte do webového průvodce a zvolte heslo prvního správce. Přihlašovací jméno je `admin`. Instalační token se po založení správce odstraní. Balíček nemá veřejné výchozí heslo.
6. V Nastavení zadejte název kanceláře; v Makléři a uživatelé vytvořte účty.
eWeb 0.8.44 má v Nginxu zákaz veřejného přístupu ke složce `/private/`. Při provozu mimo eWeb nastavte stejný zákaz; pro Apache jsou přibalené `.htaccess`. PHP vývojový router směruje všechny požadavky přes kontroler.
Instalační mechanismus je lokálně testován se samotnou veřejnou částí archivu, včetně zachování soukromých dat po opakované instalaci. Skutečná instalace přes váš živý eUpdate/eWeb dosud nebyla provedena.
## Místní spuštění ze zdrojů
```sh
php bin/console.php init
php -S 127.0.0.1:8080 -t public bin/router.php
```
Instalační token je v `var/setup-token.txt`; data v `var/`. Alternativní umístění nastaví proměnná `EREAL_DATA`. Účet je stejný jako při instalaci přes eWeb: login admin, heslo zvolené při prvním spuštění. Přihlášení používá stejné principy jako eSite (PHP relace, hashe, CSRF, role), ale účty jsou samostatné; nejde o společné SSO eWebu/eSite.
## Data, souběh a aktualizace
Po instalaci do eWebu:
```text
private/ereal/
current.json aktivní vydání pro cron
monitor-cron.php stálý CLI vstup pro monitoring
releases/VERSION-HASH/ aplikace včetně vendor/
shared/
state.json uživatelé, zakázky, číselníky, nastavení, monitoring
state.json.lock stálý transakční zámek
captures/ID.json požadavky do /import
uploads/ID neveřejné fotografie a dokumenty
sessions/ PHP relace
backups/ posledních 10 stavů před změnou
rate.json omezení pokusů
```
Veškeré zápisy stavu probíhají pod zámkem a atomickým přejmenováním. Editace zakázky vyžaduje její aktuální číslo verze; starší editace vrátí HTTP 409 a musí se znovu načíst. Import celé dávky se zapisuje jednou transakcí. Historie uchovává 50 předchozích stavů; obnova se týká údajů a přiřazení makléře, přílohy zůstávají aktuální.
Aktualizace v eWebu nahrazuje veřejný vstup a instalační payload. Soukromé `shared/` se nepřepisuje. Před aktualizací proveďte plnou zálohu souborů domény. Pro návrat použijte odpovídající plnou zálohu eWebu; při ruční obnově `state.json` nejprve zastavte zápisy. Samotný datový JSON neobsahuje fyzické přílohy ani archiv zachycených requestů.
**JSON režim je určen pro jeden aktivní uzel.** Více makléřů na témže uzlu je podporováno. Současný zápis z několika serverů do kopií souborů synchronizovaných například Syncthingem podporován není. Doménu a cron směrujte na jeden zapisující uzel; pro souběžné uzly je nutné jiné sdílené úložiště a relace.
## Realman: nejprve zachytit, potom mapovat
Po nasazení bude příjem například `https://is.realsp.cz/import`. Tato adresa v balíčku není pevně nastavená ani dosud nasazená. Přijímají se metody zaslané exportérem, včetně autentizovaných úvodních/probe požadavků.
Autentizace může být:
- HTTP Basic: login a heslo nastavíte v Nastavení.
- Hlavička `X-Import-Key: KLÍČ` nebo `Authorization: Bearer KLÍČ`.
- `https://is.realsp.cz/import/KLÍČ`, pokud exportér neumí hlavičky. Taková URL může skončit v přístupovém logu webového serveru; pro běžný provoz upřednostněte Basic.
Klíč se zobrazuje jen přihlášenému administrátorovi. Požadavek bez platného klíče nebo Basic přihlášení se odmítne. Základní limity: 10 MiB na požadavek, 500 zachycených požadavků, 256 MiB archivu. Správce může jednotlivé požadavky stáhnout nebo smazat.
Archiv `captures/ID.json` obsahuje metodu, čas, Content-Type, IP, redigované hlavičky a parametry, SHA-256 a přesné původní tělo v Base64. Původní tělo může obsahovat i osobní údaje nebo vložené přihlašovací údaje; archiv je proto neveřejný. Multipart PHP zpracovává samo: do JSON se ukládají formulářová pole a obsah jednotlivých souborů v Base64, nikoli bajtově shodná multipart obálka. Vícenásobné soubory pod jedním názvem pole tato verze odmítá s 422; samostatná pole fungují.
Výchozí odpověď je HTTP 202 a JSON s `saved:true`, ID zachycení a `imported:false`. Jde o potvrzení uložení požadavku, **nikoli ověřenou odpověď protokolu Realmanu**. V nastavení lze změnit HTTP stav, MIME a celé tělo odpovědi. Pokud Realman vyžaduje session, XML-RPC operace, další metody nebo jinou autentizaci, doplní se jeho konkrétní adaptér po zachycení požadavků. V této verzi není vzdálený exportér prohlášen za kompatibilní.
V Příjem z Realmanu otevřete záznam. JSON a běžné XML se zobrazí ve stromu; XML atributy mají prefix `@`, opakované prvky jsou pole. Mapování používá tečkové cesty:
```json
{
"items_path": "items",
"id_path": "id",
"fields": {"reference": "rkid", "title": "name", "transaction": "operation", "category": "kind", "price": "price"},
"values": {"transaction": {"P": "sale", "N": "rent"}, "category": {"B": "apartment", "D": "house"}}
}
```
Jde o ilustraci, nikoli tvrzení o skutečných klíčích Realmanu. Konkrétní hodnoty vyplňte podle prvního exportu. Externí číselníky lze místo `values` mapovat také v Číselníky → `external_codes`. Neznámý kód dávku zastaví. Před importem musí být znám typ zakázky a druh nemovitosti. Chybějící RKID/název dostanou technický název RM-ID a stav je bez mapování rozpracovaný.
Nejprve použijte Náhled, pak Potvrdit a importovat. Zdrojové ID je povinné a tvoří spolu se zdrojem stabilní vazbu. Opakovaný totožný export nevytvoří duplicitní zakázku. Ručně změněná pole mají přednost před dalším importem. Stav se nemění jen proto, že položka v další dávce chybí; automatické mazání a stahování vzdálených fotografií není zapnuto. V první verzi má importovanou zakázku správce, který import potvrdil; ten ji může přiřadit makléři.
Pro dokončení parity jsou potřeba aktuální formuláře/číselníky vaší licence a první zachycený export. Připojení ke katastru, generování smluv/PDF, překlady, párování poptávek, hromadné operace a export na realitní portály součástí této první verze nejsou.
## iRMonitor podle dodané dokumentace
Zdroj: dodaný dokument `export_inzeratu_popis1.7.pdf`, 6 stran; implementace odpovídá exportu XML dataver 6 a veřejnému `https://www.irmonitor.cz/Data/AdvertExport_ver6.xsd`. Jeho kopie je v resources/. Dokumentovaný export nepoužívá Bearer klíč ani přihlašovací heslo běžného webového účtu.
V Nastavení vložte **samostatné exportní heslo exwbps**, v konfiguraci nastavte `enabled:true`. Výchozí URL je `https://www.irmonitor.cz/AdvExport.aspx`. Heslo se ukládá neveřejně a při opětovném načtení formuláře se nevrací do prohlížeče. Protokol vyžaduje heslo v parametru HTTP požadavku; aplikace ho nezapisuje do svého logu.
Volání obsahuje:
| Parametr | Hodnota |
| --- | --- |
| exwbps | nastavené exportní heslo |
| extstamp | hodnota `since`, formát yyyy-MM-ddTHH:mm:ss |
| exnewonly | 0 — umožní znovu načíst již exportované hodnoty při opakování po chybě |
| extformat | xml |
| xmlstyle | 2 |
| dataver | 6 |
Výchozí `since` je půlnoc dne prvního spuštění aplikace. Pro historické načtení ji změňte. Po úspěšném zpracování se posune na čas začátku požadavku s dvouminutovým překryvem. Překryv zachytí změny během načítání; duplicity se aktualizují podle ID. Časová zóna aplikace je Europe/Prague; dokumentace posílá datum bez časové zóny.
Při chybě autentizace, neplatném XML, neshodě Count, síťové chybě nebo chybě transakce se checkpoint neposune. `No data` je zpracováno jako prázdný výsledek. Pokud export dosáhne 5000 záznamů, dávka se zpracuje, ale checkpoint zůstane stejný a aplikace oznámí dosažený limit. Rozhraní podle dokumentace nemá stránkování; pro úplné načtení saturovaného výsledku je nutné řešení s poskytovatelem. Export nad 10 MiB aplikace odmítne bez posunutí checkpointu.
Přenášejí se název, cena, řádky textu, lokalita, původní odkaz, všechny kontakty a zdrojové údaje, předchozí ceny, změny ceny/kontaktu a územní ID. Pro zobrazení je vybrán první platný e-mail a seznam telefonů. Původní XML jednotlivého inzerátu zůstává ve zdrojových datech. Uživatel při založení náběru potvrdí druh a typ zakázky; navržené hodnoty vycházejí z dokumentovaných Activity/RealityType.
Do nabídky náběrů se načtou jen aktivity 1, 2, 5, 6 a 7 (prodej, pronájem, nabídkové výměny, nabízené spolubydlení). Poptávky po koupi/pronájmu se vyřadí. XML **nemá příznak RK vs. soukromý inzerent**. V této konfiguraci je `private_feed_confirmed:true`, protože zadavatel výslovně potvrdil, že jeho export obsahuje pouze soukromé inzerenty. Aplikace se spoléhá na toto nastavení poskytovatele; neprovádí vlastní klasifikaci RK. Při přechodu na smíšený export potvrzení vypněte a upravte zdrojová pravidla.
Tlačítko Načíst z API provede jednu synchronizaci. Bez exportního hesla se reálné volání nespustí. Živé placené rozhraní nebylo testováno; ověřeny jsou parser, dávky a chyby na syntetickém XML odpovídajícím dokumentované struktuře. V Nastavení lze zkušebně vložit XML odpověď nebo syntetický JSON.
## Cron v eWebu
Cron nevytváří instalace ZIPu automaticky. Nastavte ho u příslušné domény pod jejím účtem, například každých 15 minut, pokud to umožňuje smlouva s poskytovatelem. Zvolte PHP binárku stejné verze jako FPM domény a její skutečnou cestu:
```sh
/cesta/k/php /var/www/DOMENA/private/ereal/monitor-cron.php
```
První návštěva domény vytvoří tento stálý vstup. Používá aktuální vydání z `current.json`. Běží pouze jeden synchronizační proces; další spuštění při obsazeném zámku skončí s chybou. Výstupem je počet uložených a vyřazených inzerátů a informace o případném limitu.
## Diagnostika a ověření
- Chyby PHP: log PHP-FPM příslušné domény; databázový server není potřeba.
- Data a příjem: `private/ereal/shared/state.json`, `captures/`.
- CLI zdraví ve zdrojové instalaci: `php bin/console.php health`.
- Aplikační kontroly: `php tests/run.php`.
- HTTP kontroly: `python3 tests/http_integration.py`; volitelné proměnné PHP_BINARY a PHP_INI.
- Ověření balíčku a aktuální výsledky: `VALIDATION.json`, `SHA256SUMS`.
Produkční data, přihlašovací údaje ani náhodné instalační tokeny nejsou součástí distribučního archivu. Syntetické XML/JSON ukázky v tests/ a resources/ jsou označené jako testovací data.
## Licence a autor
Autor projektu: PhDr. Pavel Bartoš, LL.M., DBA. Licenci eReal stanoví vlastník projektu. Přibalené knihovny php-templates a latex si zachovávají své MIT licence a jejich úplná znění ve vendor/. Tento balíček neobsahuje zdrojový kód ani grafické podklady Realmanu.