Joomla rozšíření (package = plugin + komponenta) pro povinné tlačítko „Odstoupit od smlouvy“ dle směrnice EU 2023/2673 (účinnost 19. 6. 2026).
Existují dvě varianty:
| Varianta | Joomla | VirtueMart | PHP | Aktuální verze |
|---|---|---|---|---|
| J4/5/6 | 4.x, 5.x, 6.x | 4.x | 8.1+ | 1.6.0 |
| J3 | 3.x | 3.x | 7.0+ | 1.5.2 |
1. Požadavky
Varianta J4/5/6 + VM4
- Joomla 4.x, 5.x nebo 6.x
- VirtueMart 4.x
- PHP 8.1 nebo novější
- MySQL 5.7+ / MariaDB 10.3+
Varianta J3 + VM3
- Joomla 3.x
- VirtueMart 3.x
- PHP 7.0 nebo novější
- MySQL 5.6+ / MariaDB 10.1+
2. Instalace
Získání instalačního balíčku
Stáhněte správný ZIP soubor:
- J4/5/6:
pkg_semavmwithdrawal.zip(nebosemavmwithdrawal_vX.Y.Z.zip) - J3:
pkg_semavmwithdrawal.zipz J3 buildu (nebosemavmwithdrawal_vX.Y.Z_j3.zip)
Postup instalace
- Přihlaste se do administrace Joomla.
- Přejděte do System > Install > Extensions (J4/5/6) nebo Extensions > Manage > Install (J3).
- Nahrajte ZIP soubor
pkg_semavmwithdrawal.zip. - Joomla nainstaluje oba díly najednou:
- Plugin:
plg_system_semavmwithdrawal(System – SemaVirtueMart Odstoupení od smlouvy) - Komponenta:
com_semavmwithdrawal(Odstoupení od smlouvy – administrační přehled)
- Plugin:
Upgrade: Stejný postup jako instalace. Joomla použije
method="upgrade"a spustí migrační SQL automaticky. Data v tabulce#__sema_withdrawalszůstanou zachována.
3. Aktivace pluginu
Po instalaci je nutné plugin ručně povolit:
J4/5/6
- System > Manage > Plugins
- Vyhledejte
semavmwithdrawalneboOdstoupení. - Klikněte na název pluginu a nastavte Status = Enabled.
- Alternativně: klikněte přímo na červenou ikonu ve sloupci Status.
J3
- Extensions > Plugins
- Vyhledejte
semavmwithdrawal. - Povolte plugin (zelená fajfka).
Po povolení se na frontendu webu ihned objeví plovoucí tlačítko (pokud je nastavena pozice float-right nebo float-left).
4. Základní nastavení
Otevřete nastavení pluginu:
- J4/5/6: System > Plugins > klik na název pluginu
- J3: Extensions > Plugins > klik na název pluginu
Povinné / doporučené parametry
| Parametr | Výchozí | Popis |
|---|---|---|
| Název e-shopu | (prázdné = název webu) | Zobrazí se v potvrzovacím e-mailu zákazníkovi. |
| E-mail pro notifikace | (prázdné = systémový odesílatel) | Kam přijde upozornění na nové odstoupení. |
| Text tlačítka | „Odstoupit od smlouvy“ | Text na tlačítku. Musí obsahovat text – samotná ikona zákona nestačí. |
| Umístění tlačítka | Plovoucí vpravo dole | Kde se tlačítko na webu zobrazí (viz sekce 6). |
| Délka lhůty (dny) | 14 | Zákonná lhůta pro odstoupení ve dnech. |
| Režim ladění | Vypnuto | V provozu VŽDY vypnout. Zapněte jen při řešení problémů. |
Další parametry
| Parametr | Výchozí | Popis |
|---|---|---|
| Nabídnout výběr způsobu řešení | Ano | Zákazník si může vybrat: vrácení peněz / výměna / oprava / sleva. |
| Výběr je povinný | Ano | Zákazník musí zvolit způsob řešení před odesláním. |
| Kontrola lhůty | Upozornit, ale umožnit | Nehlídat = žádná kontrola; Upozornit = zobrazí varování, ale nebrání odeslání. |
| Odkaz na obchodní podmínky | (prázdné) | URL obchodních podmínek. Zobrazí se v modalu i v e-mailu. |
5. Firemní údaje
Sekce „Firemní údaje“ v nastavení pluginu. Tyto údaje se zobrazují v potvrzovacím e-mailu zákazníkovi:
| Parametr | Popis |
|---|---|
| Logo firmy | Obrázek v záhlaví e-mailu. Doporučená šířka max. 200 px. |
| IČO | Identifikační číslo firmy. |
| Adresa / sídlo | Sídlo firmy (patička e-mailu). |
| Adresa pro vrácení zboží | Kam má zákazník poslat vrácené zboží. Pokud prázdné, použije se adresa sídla. |
| Telefon | Kontaktní telefon (patička e-mailu). |
| Kontaktní e-mail | E-mail v patičce. Pokud prázdné, použije se systémový odesílatel. |
Doporučení: Vyplňte všechny firemní údaje. Potvrzovací e-mail slouží jako trvalý nosič (durable medium) dle zákona a měl by obsahovat kompletní identifikaci prodejce.
6. Tlačítko – umístění a vzhled
Pozice tlačítka
| Hodnota | Chování |
|---|---|
| Plovoucí vpravo dole | Fixně umístěné tlačítko v pravém dolním rohu obrazovky. Vždy viditelné. |
| Plovoucí vlevo dole | Fixně umístěné tlačítko v levém dolním rohu. |
| V patičce (statické) | Tlačítko se vloží před uzavírací tag </body> jako statické. |
| Nevkládat (ručně) | Plugin nevkládá tlačítko. Musíte jej umístit ručně do šablony (viz sekce 13). |
Barva tlačítka
Parametr „Barva tlačítka a ovládacích prvků“ (color picker, výchozí #1f6feb) určuje:
- barvu plovoucího tlačítka
- barvu ovládacích prvků v modálním okně (potvrzovací tlačítko, checkboxy, aktivní stavy)
- hover stav se automaticky ztmaví
Barva se aplikuje přes CSS custom property --vmw-accent.
7. Způsoby řešení (resolution)
Pokud je zapnuto „Nabídnout výběr způsobu řešení“, zákazník ve 2. kroku formuláře vidí rozbalovací nabídku.
Výchozí možnosti:
refund=Vrácení peněz (odstoupení od smlouvy)
exchange=Výměna zboží
repair=Oprava zboží
discount=Přiměřená sleva z ceny
Formát: klíč=Popisek (jeden řádek = jedna možnost). Popisek se uloží do auditu a pošle v e-mailu.
Možnosti lze libovolně upravit, přidat nebo odebrat v nastavení pluginu.
8. Lhůta pro odstoupení
- Délka lhůty: Výchozí 14 dnů (parametr
period_days). - Režim kontroly: Určuje, co se stane, když je objednávka starší než nastavená lhůta.
- Nehlídat: Žádná kontrola, formulář se vždy odešle bez upozornění.
- Upozornit, ale umožnit: Zobrazí zákazníkovi varování „MIMO odhadovanou lhůtu“, ale neblokuje odeslání.
Důležité: Plugin NIKDY neblokuje odstoupení. Lhůta se právně počítá od převzetí zboží (ne od objednání), což plugin nemůže přesně ověřit. Proto jen varuje – konečné rozhodnutí je na e-shopu.
9. Administrace – přehled odstoupení
Po instalaci se v administraci objeví nová položka v menu:
- J4/5/6: v bočním menu Components > Odstoupení od smlouvy (Contract Withdrawals)
- J3: Components > Odstoupení od smlouvy
Tabulka záznamů
| Sloupec | Popis |
|---|---|
| ID | Pořadové číslo záznamu. |
| Objednávka | Číslo objednávky z VirtueMart. Pokud je u objednávky více odstoupení, zobrazí se štítek „Duplicita (N×)“. |
| Stav | Rozbalovací nabídka pro změnu stavu vyřízení (Čeká / V procesu / Vyřízeno). |
| Zákazník | Jméno zákazníka. |
| E-mail zákazníka. | |
| Řešení | Zvolený způsob řešení (nebo „—“ pokud nebylo zvoleno). |
| Položky | Přehled vybraných položek, nebo štítek „Celá objednávka“. |
| Ve lhůtě | Zda bylo odstoupení podáno v zákonné lhůtě (Ano / Ověřit). |
| Potvrzení odesláno | Zda byl zákazníkovi odeslán potvrzovací e-mail (Ano / Ne). |
| Přijato | Datum a čas přijetí odstoupení. |
Změna stavu
- Změňte stav ve sloupci „Stav“ u příslušných záznamů.
- Klikněte na tlačítko „Uložit stavy“ v panelu nástrojů.
- Zobrazí se potvrzení „Stavy uloženy.“
Výchozí stavy (konfigurovatelné v nastavení pluginu):
pending=Čeká na vyřízení
in_progress=V procesu
resolved=Vyřízeno
Vyhledávání a řazení
- Vyhledávání: Fulltextové hledání v čísle objednávky, jménu zákazníka a e-mailu.
- Řazení: Kliknutím na záhlaví sloupce (ID, Objednávka, Stav, Zákazník, E-mail, Řešení, Ve lhůtě, Potvrzení, Přijato).
- Stránkování: Nastavitelná velikost stránky přes Joomla pagination.
10. CSV export
- V administračním přehledu odstoupení klikněte na tlačítko „Export CSV“ v panelu nástrojů.
- Stáhne se CSV soubor se všemi záznamy (respektuje aktuální vyhledávací filtr).
- Kódování UTF-8, oddělovač středník (
;).
CSV export vyžaduje oprávnění
core.managena komponentě.
11. Bezpečnost
CSRF ochrana
Každý AJAX požadavek z frontendu obsahuje Joomla form token. Server token ověří před zpracováním. Pokud token nesouhlasí (např. po vypršení session), zákazník dostane chybu „Požadavek se nepodařilo zpracovat.“
Po upgradu: Zákazníci mohou potřebovat provést hard refresh (Ctrl+Shift+R), aby se načetl nový JavaScript s tokenem.
Rate limiting
Ochrana proti nadměrnému počtu pokusů z jedné IP adresy. Při překročení limitu zákazník dostane zprávu „Příliš mnoho pokusů. Zkuste to za několik minut.“
Honeypot
Skryté pole ve formuláři. Pokud jej vyplní bot, požadavek se odmítne.
IP adresa za proxy
Pokud web běží za reverse proxy (Cloudflare, nginx apod.), nastavte parametr „Hlavička IP z proxy“:
| Hodnota | Použití |
|---|---|
| Žádná (REMOTE_ADDR) | Výchozí, nejbezpečnější. Použijte, pokud web NENÍ za proxy. |
| HTTP_CF_CONNECTING_IP | Pro weby za Cloudflare. |
| HTTP_X_FORWARDED_FOR | Pro weby za nginx/Apache reverse proxy. |
| HTTP_X_REAL_IP | Pro weby za nginx s proxy_set_header X-Real-IP. |
Varování: Nastavení špatné hlavičky umožní útočníkům spoofovat IP. Použijte jen tu hlavičku, kterou vaše proxy skutečně nastavuje.
12. E-maily
Plugin odesílá dva typy e-mailu:
Potvrzení zákazníkovi (HTML)
- Příjemce: E-mail zákazníka (z objednávky VM).
- Předmět: „Potvrzení o přijetí odstoupení od smlouvy – objednávka [číslo]“
- Obsah:
- Záhlaví s logem firmy (pokud nastaveno)
- Potvrzení o přijetí odstoupení
- Číslo objednávky, datum objednávky, datum přijetí
- Informace o lhůtě (ve lhůtě / mimo odhad)
- Zvolený způsob řešení (pokud byl zvolen)
- Seznam vybraných položek a celková částka (pokud byly zvoleny)
- Text zákonné deklarace o odstoupení
- Adresa pro vrácení zboží
- Odkaz na obchodní podmínky (pokud nastaven)
- Patička s firemními údaji (IČO, adresa, telefon, e-mail)
Tento e-mail slouží jako trvalý nosič (durable medium) dle směrnice – je zákonným důkazem o přijetí odstoupení.
Notifikace e-shopu (plain text)
- Příjemce: E-mail z parametru „E-mail pro notifikace“ (nebo systémový odesílatel).
- Předmět: „Nové odstoupení od smlouvy – objednávka [číslo]“
- Obsah: Stručný přehled – číslo objednávky, zákazník, e-mail, řešení, položky, datum.
Fallback kontaktu v patičce e-mailu
E-mail v patičce se určuje kaskádově:
- Parametr „Kontaktní e-mail“ (
company_email_contact) - Pokud prázdný: parametr „E-mail pro notifikace“ (
notify_email) - Pokud prázdný: systémový odesílatel Joomla (
mailfrom)
13. Ruční umístění tlačítka
Pokud zvolíte pozici „Nevkládat (ručně)“, musíte tlačítko vložit přímo do šablony webu.
Vložte tento HTML kód na požadované místo:
<button type="button" id="vmw-trigger" class="vmw-trigger">
Odstoupit od smlouvy
</button>
Podmínky:
- Element MUSÍ mít
id="vmw-trigger"(JavaScript na něj naslouchá). - Třída
vmw-triggerzajistí základní stylování (volitelné, můžete použít vlastní CSS). - Text tlačítka můžete změnit, ale musí být čitelný (zákonný požadavek).
Plugin i při volbě „Nevkládat“ stále vloží do stránky modal, JavaScript a CSS – jen nevkládá samotné tlačítko.
14. Odinstalace
Postup
- J4/5/6: System > Manage > Extensions > vyhledejte
SemaVMwithdrawal> Odinstalovat. - J3: Extensions > Manage > vyhledejte
SemaVMwithdrawal> Odinstalovat.
Co se smaže
- Plugin
plg_system_semavmwithdrawal(PHP, JS, CSS, jazykové soubory) - Komponenta
com_semavmwithdrawal(admin soubory) - Tabulka
#__sema_withdrawal_ratelimit(rate limit záznamy)
Co ZŮSTANE zachováno
- Tabulka
#__sema_withdrawals(auditní záznamy o odstoupeních) - Tabulka
#__sema_withdrawal_items(položky k odstoupením)
Proč se data nemažou? Záznamy o odstoupeních jsou zákonným důkazem. Automatické smazání při odinstalaci by mohlo způsobit právní problémy. Pokud tabulky skutečně chcete odstranit, proveďte to ručně přes phpMyAdmin:
DROP TABLE IF EXISTS `#__sema_withdrawal_items`; DROP TABLE IF EXISTS `#__sema_withdrawals`;(nahraďte
#__vaším skutečným prefixem tabulek)
15. Specifická J3 verze
Rozdíly oproti J4/5/6
| Aspekt | J4/5/6 | J3 |
|---|---|---|
| Aktuální verze | 1.6.0 | 1.5.2 |
| PHP | 8.1+ (namespaces, typy) | 7.0+ (bez namespaces) |
| MVC vzor | Modern Joomla (DI, services/) | Legacy (JFactory, JControllerLegacy) |
| Admin šablona | Bootstrap 5 | Bootstrap 2 |
| Form pole tel/email | Nativní typy | Textové pole |
| Jazykové soubory | Standardní autoload | script.php + runtime fallback |
Jazykové soubory v J3
J3 má známý problém s načítáním českých jazykových souborů pro system pluginy. Řešení:
- Instalační script (
script.php) kopíruje.inisoubory doadministrator/language/při instalaci. - Runtime fallback (
ensureAdminLanguageFiles()) kontroluje a kopíruje soubory za běhu, pokud chybí. - Trojitý fallback v
loadPluginLanguage(): JLanguage > cs-CZ fallback > parse_ini_file s injekcí.
Pokud se některé texty v administraci J3 zobrazují anglicky místo česky, je to očekávané chování. Plugin Manager může přepsat české řetězce anglickými.
Frontend
Frontend chování (tlačítko, modal, formulář) je identické v obou variantách – stejný JavaScript i CSS.
16. Řešení problémů
Tlačítko se nezobrazuje
- Ověřte, že plugin je povolený (Status = Enabled / zelená fajfka).
- Zkontrolujte parametr „Umístění tlačítka“ – není nastaveno na „Nevkládat“?
- Ověřte, že na stránce není jiný plugin/modul, který blokuje
onAfterRender. - Zkontrolujte konzoli prohlížeče (F12) na JavaScript chyby.
Chyba „Požadavek se nepodařilo zpracovat“
- Po upgradu: Zákazník musí provést hard refresh (Ctrl+Shift+R) pro načtení nového JS s CSRF tokenem.
- Vypršela session: Obnovení stránky obnoví token.
- Zapněte Režim ladění v nastavení pluginu pro detailnější chybovou hlášku.
Chyba „Příliš mnoho pokusů“
Rate limiting. Zákazník musí počkat několik minut. Pokud je to legitimní provoz za proxy, nastavte správnou hlavičku IP z proxy.
E-mail se nedoručí
- Ověřte nastavení Joomla mailu: System > Global Configuration > Server > Mail Settings (J4/5/6) nebo System > Global Configuration > Server (J3).
- Zkontrolujte spam složku.
- Ověřte, že parametr „E-mail pro notifikace“ je správně vyplněný.
- Zapněte Režim ladění – v odpovědi AJAX se objeví informace, zda mail byl odeslán.
Objednávka nenalezena
- Zákazník musí zadat přesné číslo objednávky z VirtueMart a e-mail, který je u objednávky evidován.
- Plugin hledá v tabulce
#__virtuemart_ordersspojením na#__virtuemart_order_userinfos(typ BT).
Admin – menu „Odstoupení od smlouvy“ se nezobrazuje
- Ověřte, že je nainstalována komponenta
com_semavmwithdrawal. - Ověřte oprávnění uživatele – potřebuje
core.managena komponentě.
J3 – české texty se zobrazují anglicky
Známý problém s načítáním češtiny v J3 system pluginech. Možná řešení:
- Přejděte do Extensions > Manage > Discover a klikněte na Discover (znovu najde jazykové soubory).
- Ručně zkopírujte soubory z
plugins/system/semavmwithdrawal/language/cs-CZ/doadministrator/language/cs-CZ/. - Restart Joomla cache.
Jak formulář funguje (z pohledu zákazníka)
- Zákazník klikne na tlačítko „Odstoupit od smlouvy“ na libovolné stránce e-shopu.
- Otevře se modální okno.
- Krok 1 – Ověření objednávky: Zákazník zadá číslo objednávky a e-mail. Klikne na „Ověřit objednávku“.
- Plugin ověří údaje proti VirtueMart databázi.
- Krok 2 – Potvrzení: Zobrazí se souhrn objednávky:
- Číslo objednávky, datum, celková částka
- Seznam položek s checkboxy (pro částečné odstoupení) a počtem kusů
- Výběr způsobu řešení (pokud je zapnut)
- Upozornění na duplicitu (pokud již existuje odstoupení pro tuto objednávku)
- Upozornění na lhůtu (pokud je objednávka starší než nastavený počet dnů)
- Zákazník vybere položky, zvolí řešení a klikne na „Potvrdit odstoupení“.
- Zobrazí se potvrzení s referenčním číslem a adresou pro vrácení zboží.
- Zákazníkovi je odeslán potvrzovací e-mail. E-shopu je odeslána notifikace.
Kontrolní seznam pro spuštění
- Plugin nainstalován a povolen
- Název e-shopu vyplněn
- E-mail pro notifikace vyplněn
- Firemní údaje vyplněny (logo, IČO, adresa, telefon, e-mail)
- Adresa pro vrácení zboží vyplněna
- Odkaz na obchodní podmínky nastaven
- Umístění tlačítka zvoleno
- Režim ladění VYPNUT
- Hlavička IP z proxy nastavena (pokud web běží za proxy)
- Testovací odstoupení provedeno a e-mail doručen
- Obchodní podmínky aktualizovány o informaci o možnosti odstoupení přes tlačítko na webu