Veřejné sklady Interní dokumentace & monitoring

Pokrytí projektové dokumentace

Každý požadavek z původní projektové dokumentace (interaktivní prezentace zadání) je zde namapován na konkrétní implementaci v tomto kódu – soubor/službu, kde je pravidlo skutečně vynuceno. Cílem je udržet aplikaci v souladu se zadáním 1:1 a mít vždy po ruce odpověď „kde přesně je to řešeno“.

77
Implementováno
0
Částečně
2
Naplánováno

Rezervační proces

Hotovo  Zobrazení dostupných lokalit s počtem volných boxů v reálném čase
GET /api/public/locations → reservationService.listLocationsWithAvailability
Hotovo  Přehled boxů v lokalitě – volné/obsazené s kapacitou a cenou/kaucí
GET /api/public/locations/:id/boxes → reservationService.listBoxesForLocation
Naplánováno  Interaktivní vizualizace výběru boxu (analogie boxbox.cz)
"Varianta B" v nabídce – samostatná položka nad rámec základního objednávkového formuláře (fáze 12/15 v plánu)
Hotovo  Dočasná blokace boxu na 15 minut po výběru
reservationService.selectBox (TEMP_HOLD_MINUTES = tvrdý strop) + jobs/clearTempHolds.js (každou minutu). Nad rámec zadání: box se uvolní hned při odchodu ze stránky (pagehide → POST /release) a nejpozději ~2 min po tom, co se formulář přestane hlásit (heartbeat každých 30 s, TEMP_HOLD_INACTIVITY_SECONDS)
Hotovo  Kalendář: povolený rozsah dat nástupu per provozovna, ostatní data zašedlá
reservationService.getLocationRules + setDatesAndDuration; ve formuláři /box/:id má datum min/max dle pravidel pobočky (box-order.js)
Hotovo  Kalkulace ceny v reálném čase, server jako jediný zdroj pravdy o ceně
pricingService.calculateReservationPrice/assertPriceMatches
Hotovo  Registrace/přihlášení zákazníka v průběhu rezervace (bez nutnosti účtu předem)
reservationService.setContactInfo + paymentService (účet vzniká až po platbě); přihlášení během rezervace přes /prihlaseni?next=/box/:id – blokace boxu zůstává (reservationService.selectBox znovu použije blokaci téže relace)
Hotovo  Platba přes Comgate (karta, QR kód, bankovní tlačítka)
comgateService.createPayment (mock i skeleton ostrého API)
Hotovo  Odsouhlasení obchodních podmínek před platbou
Krok Rekapitulace (box-order.js: tlačítko „Zaplatit“ aktivní až po zaškrtnutí) + server-side povinné termsAccepted=true (validation/schemas.createPaymentSchema na POST /api/reservations/:id/payment); odkaz na podmínky = Nastavení → business.termsUrl
Hotovo  Nastavení boxu jako nedostupný po úspěšné platbě
paymentService.handleReservationPaymentResult → boxesRepo.setStatus(occupied)

Zákazník a přístup

Hotovo  Registrace automaticky až PO úspěšné platbě (ne dříve) – u veřejného webu
paymentService.handleReservationPaymentResult (usersRepo.create z pending_* polí). Výjimka: admin/správce může účet i rezervaci založit ručně mimo web (viz Administrace a správa).
Hotovo  Kontrola duplicity emailu – vyzvání k přihlášení
reservationService.setContactInfo (ConflictError „přihlaste se prosím“) → v kroku Kontakt se zobrazí výzva s odkazem na přihlášení a návratem zpět do rozpracované rezervace (box-order.js)
Hotovo  Povinná pole: jméno, příjmení, adresa, email, telefon, číslo účtu; B2B: firma/IČO/DIČ skryté
validation/schemas.js contactSchema
Hotovo  Heslo negeneruje zákazník, dostane ho emailem po platbě
authService.generateRandomPassword + paymentService notifikace
Hotovo  Automatické odeslání SMS s přístupovým kódem (24/7, mimo denní okno)
notificationService.IMMEDIATE_24_7_TYPES + paymentService.sendReservationConfirmedNotifications
Hotovo  Přístupový kód platný po dobu rezervace, deaktivace po expiraci
jobs/expireReservations.js (access_code_active=false)
Hotovo  Zákaznický profil s historií rezervací a fakturami
Klientská zóna GET /ucet (views/customer/account.ejs + account.js) nad GET /api/account/reservations a /api/account/invoices; faktury PDF i ISDOC ke stažení (customerController.downloadInvoicePdf/downloadInvoiceIsdoc), úprava údajů, změna hesla, GDPR export
Hotovo  Prodloužení pronájmu online, opakovaně, bez nové kauce
paymentService.createExtensionPayment; v klientské zóně tlačítko „Prodloužit pronájem“ (volba délky dle ceníku boxu → Comgate → /rezervace/dokonceno)
Hotovo  Přihlašovací lockout (5 pokusů / 15 min) se zbývajícím počtem pokusů v hlášce
authService.login
Hotovo  Reset hesla emailem (platnost 60 min, jednorázové)
authService.requestPasswordReset/resetPassword; stránka /prihlaseni (pohledy přihlášení / zapomenuté heslo / nové heslo dle schválené předlohy), odkaz z emailu vede na /reset-hesla?token=
Hotovo  GDPR: export dat, výmaz s anonymizací (finanční záznamy zachovány)
customerController.gdprExport/gdprDelete + usersRepo.anonymize; na žádost zákazníka provede totéž admin v detailu zákazníka (adminController.deleteCustomer)

Platby a finance

Hotovo  Online platba kartou, QR kódem, bankovními tlačítky (Comgate)
comgateService (mock režim plně funkční, ostré API skeleton)
Hotovo  Kauce jako vratná záloha, konkrétní částka nastavená per box
boxes.deposit_amount (DB), pricingService
Hotovo  Automatické generování faktur s DPH (21 % pronájem, 0 % kauce)
invoicingService.createInvoice + invoicePdfBuilder
Hotovo  Faktura odeslána zákazníkovi (PDF), správci+ekonomovi (PDF+ISDOC)
paymentService.sendReservationConfirmedNotifications
Hotovo  „Neplaťte, faktura je uhrazena“, bez QR k platbě, s Comgate transID a číslem objednávky
invoicePdfBuilder.buildInvoicePdf
Hotovo  Vrácení kauce manuálně ekonomem po fyzické kontrole správcem
boxReturnService.recordDepositDecision; v administraci vede k oběma krokům přímá akce z dashboardu, seznamu boxů i detailu rezervace (barevný stavový pruh „co udělat“)
Hotovo  QR platba pro rychlé vrácení kauce ekonomem
qrPaymentService.generateDepositRefundQr (SPD formát, výpočet IBAN)
Hotovo  Export faktur pro účetnictví (CSV, ISDOC)
accountantController.exportInvoicesCsv/downloadInvoiceIsdoc

Administrace a správa

Hotovo  Administrační rozhraní s levým panelem, přihlášením a rozdělením dle role
/admin (routes/adminUi.routes.js, views/admin/*, public-assets/admin/*)
Hotovo  Přehled obsazenosti a tržeb v reálném čase (admin i správce)
/admin dashboard → adminController.dashboard, managerController.locationDashboard
Hotovo  Správa boxů (přidání ze šablony typu, úprava, deaktivace, stav V opravě)
/admin/boxy → adminController.createBox (velikost/m²/cena/kauce se přebírá ze zvolené šablony, server ji vždy ověří znovu) /updateBox/setBoxStatus
Hotovo  Role: zákazník, správce provozovny, ekonom, admin
config/constants.ROLES + middleware/auth.requireRole + middleware/webAuth
Hotovo  Více provozoven na správce, jemná oprávnění per provozovna
/admin/provozovny (Správci) → location_managers table + middleware/locationAccess
Hotovo  Export dat pro účetnictví
/admin/faktury → accountantController.exportInvoicesCsv
Hotovo  Ruční reset přístupového kódu správcem/adminem
/admin/boxy → adminController.resetAccessCode (sdíleno s manager.routes)
Hotovo  Nastavení ceníku a kauce per box provozovatelem
/admin/boxy → adminController.createBox/updateBox
Hotovo  Nabízené délky pronájmu per provozovna (strop + krok: čtvrtletně 1/3/6/9/12… dle zadání, nebo po měsících) a volitelná vlastní cena boxu pro každou nabízenou délku zobrazená zákazníkovi jako sleva
locations.max_duration_months + duration_step (migrace 1700000000011), utils/durations.js, pricingService.resolveRentalPrice(box, location, months), box_month_prices; /admin/provozovny/:id → „Délky pronájmu“, /admin/boxy/:id → „Tvorba ceny“
Hotovo  Nastavení číselné řady objednávek per provozovna
/admin/provozovny → locations.order_number_prefix + orderNumberRepo.nextOrderNumber
Hotovo  Editace údajů zákazníka adminem/správcem (jméno, adresa, telefon, číslo účtu) beze ztráty vazby na rezervace/faktury (stabilní customer_id)
/admin/zakaznici/:id → adminController.updateCustomerProfile/managerController.updateCustomerProfile (usersRepo.updateProfile)
Hotovo  Krátký popis provozovny (např. poznámka k příjezdu/trase)
/admin/provozovny/:id → locations.description (migrace 1700000000006)
Hotovo  Audit log administrátorských akcí + admin-wide prohlížeč logu (filtr dle entity/akce/aktora)
/admin/log → logController.js + auditLogRepo.findFiltered
Hotovo  Log plateb (potvrzené i zamítnuté, vč. prodloužení) a přihlášení (klient i zaměstnanec)
paymentService.js → auditService.logSystem; authController.login → auditService.log
Hotovo  Zobrazení aktivity účtu (přihlášení, GDPR, změny) v detailu zákazníka a zaměstnance + úpravy provedené zaměstnancem
detailViewService.buildCustomerDetail, adminController.getStaffDetail
Hotovo  Napojení externích služeb (Comgate, vyfakturuj.cz, SMSbrana.cz, SMTP) přímo z administrace vč. testu spojení, bez zásahu do kódu
/admin/nastaveni → settingsService.js (šifrováno AES-256-GCM v app_settings) + settingsController.js
Hotovo  Prokliknutí provozovna → boxy → detail boxu, rezervace → zákazník/faktury, box → provozovna
/admin/provozovny/:id, /admin/boxy/:id, /admin/rezervace/:id, /admin/zakaznici/:id → detailViewService.js
Hotovo  Přeřazení boxu na jinou provozovnu z jeho detailu (admin), blokováno u boxu s aktivní rezervací
/admin/boxy/:id → adminController.moveBoxLocation + boxesRepo.setLocation
Hotovo  Detail zaměstnance s editací údajů, role, hesla, aktivace a přiřazených provozoven
/admin/zamestnanci/:id → adminController.getStaffDetail/updateStaffProfile/updateStaffRole/setStaffPassword/setStaffActive
Hotovo  Založení libovolného počtu dalších administrátorů
/admin/zamestnanci → adminController.createStaff (role: admin)
Hotovo  Úprava vlastního jména/příjmení/telefonu administrátorem (i ostatními rolemi), nezávisle na změně hesla
PUT /api/auth/me → authController.updateProfile
Hotovo  Ruční založení zákaznického účtu adminem/správcem (mimo automatizovaný web) + vyhledávání/přehled zákazníků dle jména, příjmení, emailu i telefonu
/admin/zakaznici → adminController.listCustomers/createCustomer, usersRepo.searchCustomers
Hotovo  Historie boxu – kdo box v minulosti pronajímal (i ukončené/zrušené rezervace) a historie změn stavu/ceníku boxu
/admin/boxy/:id → detailViewService.buildBoxDetail, reservationsRepo.findByBox, auditLogRepo.findForEntity
Hotovo  Ruční založení rezervace mimo automatizovanou platbu (dohoda telefonicky/na místě), s možností dodatečně vygenerovat Comgate platební odkaz a poslat výzvu k platbě
/admin/boxy/:id → paymentService.createManualReservation/generatePaymentLink/sendPaymentRequestEmail
Hotovo  Ověření telefonu (SMS kód) a emailu (kód emailem) při ručním zakládání zákazníka správcem provozovny – bez obou ověření nelze účet dokončit; admin toto ověření obchází
verificationService.js (assertVerified) → adminController.createCustomer, verificationCodesRepo.js, /customers/verify/start a /customers/verify/confirm v admin.routes.js i manager.routes.js
Hotovo  Šablony boxů (typ s výchozí velikostí/cenou/kaucí) pro rychlé zakládání – jen předvyplnění, box na šabloně nezávisí
/admin/typy-boxu → boxTypesRepo.js + boxTypesController.js
Hotovo  Editovatelné texty emailů (předmět/tělo) s proměnnými, návrat na výchozí text
/admin/email-sablony → emailTemplateService.js

Automatizace

Hotovo  Fyzická kontrola stavu boxu správcem při vrácení (bez AI)
boxReturnService.recordReturnCheck
Hotovo  Box po expiraci → „V přípravě“ (ne rovnou volný), na FE stále „obsazený“
jobs/expireReservations.js + config/constants.BOX_STATUS_PUBLIC_LABEL
Hotovo  Automatické upomínky před expirací (konfigurovatelné dny, výchozí 5+3+1)
jobs/sendExpiryReminders.js + locations.expiry_reminder_days
Hotovo  SMS pouze v denní době (výchozí 8:00–22:00, konfigurovatelné)
notificationService.nextAllowedSendTime
Hotovo  Deaktivace boxu deaktivuje i notifikace
adminController.setBoxStatus → boxesRepo.deactivateAccessCode
Hotovo  Čištění vypršelých dočasných blokací (5 min interval)
jobs/clearTempHolds.js

Bezpečnost a GDPR

Hotovo  Hesla jen jako bcrypt hash
authService (bcryptjs, 12 rounds)
Hotovo  Číslo karty se nikde neukládá (řeší Comgate, PCI DSS)
comgateService – žádné číslo karty neprochází naší aplikací
Hotovo  Webhooku od Comgate se nevěří přímo – server-to-server ověření
comgateService.confirmPaymentStatus
Hotovo  API klíče a další tajemství nikdy v kódu/repozitáři – jen v .env, nebo šifrovaně v DB při nastavení z administrace
.env.example + .gitignore; app_settings.value šifrováno AES-256-GCM (settingsCrypto.js, klíč mimo repo v SETTINGS_ENCRYPTION_KEY)
Naplánováno  Šifrovaná komunikace (HTTPS/TLS) – zajišťuje produkční nasazení
Plesk/Let’s Encrypt SSL při nasazení (fáze 13)
Hotovo  Ochrana proti CSRF, XSS (CSP), brute-force, rate-limit
middleware/csrf.js, middleware/security.js, middleware/rateLimit.js
Hotovo  Faktury a účetní záznamy archivovány, GDPR výmaz zachovává finance
usersRepo.anonymize (osobní údaje pryč, invoices/reservations zůstávají)
Hotovo  Systém neloguje fyzické přístupy do boxu (mechanické zámky)
Záměrně nezaváděno – žádná tabulka/log pro fyzické otevření boxu

Propojení s prezentačním WordPress webem

Hotovo  WordPress plugin zobrazuje dostupnost poboček a boxů z appky
/wordpress-plugin/verejnesklady-connector – shortcody [verejnesklady_locations]/[verejnesklady_boxes], čte GET /api/wordpress/feed
Hotovo  Odkaz z volného boxu přímo na objednávkový formulář daného boxu v appce
wordpressService.buildFeed (reserveUrl per box, plugin přidá ?returnUrl=) → GET /box/:boxId (customerBookingController.boxOrderPage) – rezervační formulář 1:1 dle schválené předlohy rezervace.html, „Zpět na web“/„Změnit box“ vrací na stránku, odkud zákazník přišel
Hotovo  Návratová URL zpět na web (pro přerušení a nový začátek)
?returnUrl= na /box/:boxId, drženo v sessionStorage prohlížeče, zobrazeno jako odkaz "Zpět na web" v každém kroku i na stránce po platbě
Hotovo  Bez košíku – vždy jen jedna rezervace na relaci
Existující architektura jedné hold-session (middleware/holdSession.js) – žádná změna nebyla potřeba
Hotovo  Test propojení webu a appky z administrace
Administrace → Nastavení → WordPress → „Otestovat spojení“ (statusCheckService.checkWordpress) + tlačítko v nastavení pluginu na WordPressu
Hotovo  Data z appky na web se aktualizují téměř nepřetržitě
Okamžitý signál appky při každé změně dostupnosti (wordpressService.notifyAvailabilityChanged → /wp-json/verejnesklady/v1/invalidate), + záloha: WP-Cron obnovení na pozadí každé 2 min + krátký transient cache (výchozí 60 s) + trvalá záloha pro výpadek appky
Hotovo  Box se drží zablokovaný jen po nezbytně nutnou dobu (max. 15 min, nebo do opuštění stránky)
reservationService.selectBox (TEMP_HOLD_MINUTES) + releaseHold (POST /api/reservations/:id/release, volané z box-order.js při odchodu ze stránky)
Hotovo  Prezentační identita pobočky na webu (foto, 24/7 odznak, dopravní dostupnost, vlastnosti, odkaz na detail) dle schválené vizuální předlohy
Migrace 1700000000009, Administrace → Provozovny → detail (location-detail.js), vizuál v wordpress-plugin/.../class-shortcodes.php + assets/style.css dle schvalene-stranky/03-homepage-hifi.dc.html
Hotovo  Log synchronizací v pluginu (kdy naposledy, historie) s automatickým mazáním starším 14 dní
wordpress-plugin/.../includes/class-sync-log.php – zápis při každém načtení dat, denní WP-Cron úklid + průběžné čištění při zápisu

Vygenerováno ze src/docs/coverageData.js. Původní zadání viz interaktivní prezentace projektu (samostatný repozitář dokumentace) – sekce „Zadání projektu“, „Změny 9. 4. 2026“ a jednotlivé tematické stránky (Rezervace boxu, Platby a kauce, Fakturace, Kontrola stavu boxu, Správa a role, Bezpečnost a data, Technické řešení).