Nakon dosta testiranja, komentara i prijedloga iz WooCommerce Hrvatska grupe, došli smo do prve javne verzije plugina MX Contract Withdrawal for WooCommerce.
Ovo je plugin za WooCommerce shopove koji žele imati jasniji tok za zaprimanje zahtjeva za jednostrani raskid ugovora. Drugim riječima, pokriva ono što se u novom EU/HR kontekstu sve češće spominje kao funkcija za jednostrani raskid, obrazac za raskid ugovora ili “gumb za raskid ugovora”.
Namjerno kažem “tehnički tok”, a ne “pravni alat”. Plugin ne daje pravne savjete i ne odlučuje umjesto trgovca. Umjesto toga, kupcu daje jasan način da pošalje zahtjev, a trgovcu uredan zapis, potvrdu, e-mailove, admin pregled, statuse i trag što se dogodilo.
Važno je odmah reći da plugin ne rješava logistiku povrata robe, refundiranje, povratne naljepnice ni odluku o tome treba li zahtjev prihvatiti ili odbiti. Fokus je na zahtjevu za jednostrani raskid ugovora, potvrdi primitka, evidenciji i obradi zahtjeva u WooCommerce adminu.
Zašto je ovo uopće potrebno?
Razlog za ovaj plugin nije bio “ajmo napraviti još jednu formu za WooCommerce”. Povod je konkretna promjena koja dolazi iz EU i hrvatske regulative. Pravo potrošača na jednostrani raskid ugovora nije novo. U Hrvatskoj već postoji pravo potrošača da, uz određene uvjete i iznimke, raskine ugovor sklopljen na daljinu u roku od 14 dana.
Međutim, sada se dodatno mijenja način na koji se to pravo treba moći ostvariti u online okruženju. Na razini EU donesena je Direktiva (EU) 2023/2673, kojom se mijenjaju pravila za ugovore sklopljene na daljinu. Jedna od praktičnih posljedica je jasnija funkcija za jednostrani raskid ugovora putem online sučelja.
U Hrvatskoj se to prenosi kroz izmjene Zakona o zaštiti potrošača. U službenim materijalima i javnoj raspravi spominje se tzv. “gumb za jednostrani raskid”. Ukratko, potrošač bi ugovor sklopljen putem interneta trebao moći raskinuti jednostavno, u nekoliko klikova, slično kao što ga je i sklopio. Zato više nije idealno razmišljati samo u stilu “imamo kontakt e-mail u footeru” ili “kupac može poslati poruku preko kontakt forme”. Web shopu treba jasniji, dostupniji i uredniji način da kupac pošalje zahtjev za jednostrani raskid ugovora.
Tu nastaje problem za WooCommerce trgovine. WooCommerce ima narudžbe, kupce, e-mailove i povrate, ali nema poseban workflow za ovakav zahtjev. Nema posebnu funkciju za zaprimanje izjave, povezivanje zahtjeva s narudžbom, slanje potvrde kupcu, admin obradu, statuse, audit trag i evidenciju.
Upravo zato je nastao MX Contract Withdrawal for WooCommerce. Nije zamišljen kao pravni savjet i nije garancija da je shop automatski usklađen. Zamišljen je kao praktičan WooCommerce alat koji pomaže tehnički pokriti zaprimanje zahtjeva, potvrdu primitka, povezivanje s narudžbom, evidenciju i admin obradu.
Zašto je nastao ovaj plugin?
Zato što se oko ove teme sve više vrti ista rasprava: EU direktiva, izmjene hrvatskog Zakona o zaštiti potrošača, funkcija za jednostrani raskid ugovora i pitanje što web shop tehnički treba imati na stranici.
Dosad se puno shopova snalazilo s kontakt formom, PDF obrascem, mailom ili linkom u uvjetima poslovanja. I to u nekim slučajevima možda izgleda “dovoljno”, barem na prvu.
Ali kad kreneš gledati što se realno događa u WooCommerce shopu, obična kontakt forma brzo postane nedovoljna:
- ne znaš je li osoba stvarno vezana uz narudžbu
- nemaš uredno povezivanje zahtjeva s WooCommerce narudžbom
- nemaš automatsku potvrdu kupcu u WooCommerce stilu
- nemaš status zahtjeva
- nemaš audit trag
- nemaš pregled po narudžbama
- nemaš zaštitu za guest narudžbe
- nemaš dobar način za djelomični raskid ili odabir stavki
- nemaš kontrolu nad starijim narudžbama
- nemaš centralno mjesto u adminu gdje se zahtjevi obrađuju
Zato sam krenuo graditi plugin koji neće biti samo “još jedna forma”, nego konkretan WooCommerce workflow.
Što plugin radi?
Ukratko: kupac može pokrenuti zahtjev za raskid ugovora preko javne stranice, preko My Account dijela ili preko linka iz WooCommerce e-maila. Plugin zatim provjeri osnovne podatke, vodi kupca kroz odabir narudžbe i stavki, prikaže pregled prije slanja, spremi izjavu, pošalje potvrdu kupcu i obavijesti admina.
U adminu se zahtjev može pregledati, označiti statusom, dodati interne napomene, poslati poruku kupcu, otvoriti povezanu narudžbu i zadržati trag događaja.
Bitno je da plugin ne pokušava automatski “presuditi” je li kupac u pravu ili nije. Ako nešto nije jasno, ide prema ručnoj provjeri. To mi je bilo važno od početka, jer u praksi postoji puno rubnih slučajeva: higijenski proizvodi, personalizirani proizvodi, otvoreni proizvodi, stari zahtjevi, nejasni datumi dostave i slično.
Frontend: kako izgleda tok za kupca?

Kupac kreće od javne stranice s obrascem. Unosi broj narudžbe i e-mail adresu korištenu za tu narudžbu. Plugin prihvaća broj narudžbe s # ili bez njega, npr. #1234 i 1234, jer kupci naravno neće svi upisati broj na isti način.
Ako je uključena sigurnija guest provjera, kupac nakon osnovne provjere dobiva sigurni (“magic”) link na e-mail i nastavlja preko tog linka. To smanjuje rizik da netko samo pogodi broj narudžbe i e-mail te odmah vidi detalje narudžbe.
Logirani kupci odmah vide pregled svojih narudžbi i mogu pokrenuti zahtjev za raskid direktno sa stranice (ili iz My accounta)

Slijedi provjera podataka kupca i odabir stavki

Nakon provjere kupac vidi svoje podatke i stavke iz narudžbe. Može odabrati proizvode za koje šalje zahtjev, a podržan je i odabir količine po stavci. To je bitno jer u stvarnom shopu kupac ne mora nužno raskidati cijelu narudžbu.
Ovo nije “rješavanje povrata robe” u logističkom smislu, nego odabir stavki na koje se zahtjev za raskid odnosi. Što će trgovac dalje napraviti s povratom, refundom ili provjerom stanja proizvoda, to ostaje dio poslovnog procesa trgovca.

Prije finalnog slanja postoji pregled. Kupac vidi što šalje, koje stavke su odabrane i koji podaci ulaze u izjavu. Tu se mogu prikazati i uvjeti raskida, link na stranicu s uvjetima ili PDF, ovisno o postavkama shopa.

Nakon slanja kupac dobiva potvrdu da je zahtjev zaprimljen, referencu zahtjeva i, ako je uključeno, mogućnost ispisa ili spremanja zapisa kao PDF kroz browser.
Zašto nije samo kontakt forma?
Ovo je najčešći komentar koji se pojavi kad se priča o ovoj temi: “Pa staviš kontakt formu i gotovo.”
Možeš, naravno. Isto kao što možeš narudžbe primati običnim mailom. Ali zato i koristimo WooCommerce: jer nije poanta samo nešto zaprimiti, nego imati proces.
Kontakt forma obično samo pošalje poruku. Ovaj plugin radi puno više:
- povezuje zahtjev s narudžbom
- provjerava billing e-mail
- radi sigurniji guest flow preko magic linka
- sprema zahtjev u vlastite tablice
- sprema stavke zahtjeva
- šalje potvrdu kupcu
- šalje obavijest adminu
- ima statuse obrade
- ima audit timeline
- ima CSV export
- ima attachment upload
- ima print/PDF zapis
- ima WooCommerce order notes
- ima My Account integraciju
- ima opcije za e-mailove
- ima privacy exporter/eraser integraciju
- ima retention/anonymization logiku.
Drugim riječima, kontakt forma je ulaz. Ovdje je cilj imati cijeli tok.
I još jedna bitna razlika: kod obične kontakt forme kupac često mora sam pisati što želi, admin mora ručno tražiti narudžbu, uspoređivati podatke, kopirati sadržaj u neku evidenciju i naknadno slati potvrde. Ovdje je zahtjev odmah strukturiran oko WooCommerce narudžbe, stavki, kupca i statusa obrade.
Pregled tabova postavki
Stranica i prikaz

Ovdje se bira javna stranica na kojoj je shortcode: [mx_contract_withdrawal_form]
Plugin može pomoći kreirati draft stranicu, ali je ne objavljuje automatski. To mi je bilo važno jer ne želim da plugin sam od sebe objavi pravno osjetljivu stranicu bez da ju trgovac pregleda.
U ovom tabu su i opcije za:
- javnu stranicu za raskid
- shortcode
- preview/edit page akcije
- footer link
- link za raskid u WooCommerce e-mailovima narudžbe
- prikaz uvjeta raskida
- link ili PDF s uvjetima
- opcionalnu potvrdu da je kupac pročitao uvjete
Ovo je tab koji se prvi podešava.
Podaci trgovca

Ovdje se unose podaci trgovca koji ulaze u kontekst izjave i e-mailova:
- pravni naziv trgovca
- OIB
- sjedište
- kontakt telefon
- kontakt e-mail
- adresa za eventualni povrat robe, ako se razlikuje od sjedišta.
Ako je adresa za eventualni povrat ista kao sjedište, može ostati prazna. Ako shop koristi posebnu adresu za povrate, npr. skladište ili poslovnicu, može se upisati posebno.
Ovo ne znači da plugin rješava logistiku povrata robe. To je samo podatak koji trgovcu može biti koristan u komunikaciji i dokumentaciji oko zahtjeva.
Pravila provjere

Ovaj tab ne služi tome da plugin automatski odbija kupce. Služi za procjenu i ručnu provjeru.
Može se podesiti:
- kako se procjenjuje rok
- koliko dana traje period raskida
- dodatni delivery buffer
- koliko dugo se gumb/link prikazuje kupcu
- mogu li starije narudžbe ipak ući u manual review
- koji statusi narudžbe smiju ući u lookup flow
Pristup gostiju i privatnost

Ovdje se podešava sigurniji “magic” link za goste i razdoblje čuvanja zahtjeva.
Najvažnija opcija je sigurni link za goste. Kad je uključena, gost nakon unosa broja narudžbe i billing e-maila dobiva link na e-mail i tek preko njega nastavlja dalje.
To je bolje od toga da se detalji narudžbe odmah pokažu svakome tko zna/pogodi broj narudžbe i e-mail.
Zadana vrijednost za razdoblje čuvanja podtaka je postavljena na 10 godina kao praktičan default za Hrvatsku, ali trgovac to mora uskladiti sa svojim stvarnim obvezama i internim pravilima.
Dodatni prilozi

Ovo je novi 2.0 tab.
Prilozi se mogu potpuno isključiti ili uključiti kao opcionalni dio procesa. Mogu se prikazati uvijek, nakon odabira razloga ili samo za odabrane razloge.
Postavke uključuju:
- omogućavanje privitaka
- kada se prikazuju
- za koje razloge se prikazuju
- maksimalan broj datoteka
- maksimalnu veličinu po datoteci
- dopuštene tipove datoteka
- prikaz broja privitaka u admin e-mailu
Datoteke se spremaju u WordPress uploads direktorij unutar posebnog foldera plugina. Plugin dodaje osnovnu zaštitu za Apache okruženja, ali kod nginx/CDN/proxy setupa treba dodatno provjeriti server pravila, pogotovo ako se očekuju osjetljivi dokumenti.
Ispis zahtjeva

Ovo je također novo u 2.0.
Može se uključiti print-friendly zapis zahtjeva za admina, a opcionalno i za kupca nakon slanja zahtjeva.
Koristi se browser print/save funkcionalnost, bez dodatnih PDF biblioteka. To znači manje komplikacija, manje dependencyja i manje šanse da se nešto razbije na hostingu.
Email obavijesti
Plugin koristi WooCommerce e-mail sustav, ne neki potpuno odvojeni mailer.
Postoje e-mailovi za:
- potvrdu kupcu nakon slanja zahtjeva
- obavijest adminu o novom zahtjevu
- status update kupcu
- sigurni link za goste
- ponovno slanje potvrde kupcu
U ovom tabu su brzi linkovi prema WooCommerce e-mail postavkama, gdje se mogu uređivati subject, heading, tekstovi i aktivacija e-mailova.
Dijagnostika

Tab za dijagnostiku služi za brzu provjeru stanja plugina.
Prikazuje:
- zadnji e-mail event
- zadnji pokušaj slanja
- zadnji WordPress-confirmed success
- tip e-maila
- ID zahtjeva
- error code
- verziju baze
- verziju rewrite pravila
- URL stranice za raskid
Tu je i test e-mail, što je korisno prije nego se forma pusti javno.
Admin obrada zahtjeva

Zahtjevi imaju vlastitu admin listu. Mogu se filtrirati i pretraživati, a dodane su i statistike te CSV export.

Na detalju zahtjeva admin vidi:
- referencu zahtjeva
- povezanu WooCommerce narudžbu
- podatke kupca
- odabrane stavke
- izjavu
- status
- eligibility/manual review oznake
- privitke
- audit timeline
- interne napomene
- opciju slanja poruke kupcu
Promjena statusa ne radi ništa s WooCommerce narudžbom. Nema automatskih povrata, nema automatskog odobravanja, nema automatskog zatvaranja zahtjeva bez admina. To je namjerno.
Plugin je tu da pomogne zaprimiti, zabilježiti i obraditi zahtjev, a ne da sam vodi pravni ili poslovni proces trgovca.
My Account integracija

Za prijavljene kupce plugin dodaje My Account dio za zahtjeve za raskid i može prikazati akciju uz narudžbe dok je to smisleno prema postavkama.
Ako je rok prikaza prošao, može se prikazati neutralnija poruka ili se akcija ne prikazuje. Opet, to nije konačna pravna odluka, nego kontrola korisničkog sučelja.
Također. na My account stranici korisnik može vidjeti povijest i status zahtjeva za raskidom ugovora
Savjetodajne oznake na proizvodima i kategorijama
Još jedna bitna stvar u pluginu su savjetodajne oznake za raskid ugovora.

Na razini proizvoda, a po potrebi i na razini kategorije, trgovac može označiti proizvode koji možda spadaju u neku od iznimki od prava na jednostrani raskid ugovora.
Primjeri su:
- mogući proizvod izrađen po mjeri ili personaliziran proizvod
- mogući zapečaćeni higijenski proizvod
- mogući kvarljivi proizvod
- mogući digitalni sadržaj ili usluga
- druga moguća iznimka od prava na raskid
Namjerno koristim riječ “mogući”, jer plugin ne donosi konačnu pravnu odluku. Oznake su savjetodajne i služe tome da trgovac i kupac odmah vide da za taj proizvod možda postoji posebna situacija. Kupac i dalje može poslati zahtjev.
To mi je bilo važno, jer plugin ne bi smio agresivno blokirati kupca samo zato što je neki proizvod označen kao potencijalna iznimka. U praksi često postoje nijanse: je li proizvod stvarno personaliziran, je li ambalaža otvorena, radi li se o higijenskom proizvodu, je li usluga već izvršena i slično.
Zato plugin koristi fail-open pristup. Ako postoji oznaka, zahtjev se ne blokira, nego se kupcu prikaže informativna napomena, a zahtjev se može označiti za ručnu provjeru.
Na frontendu to znači da kupac kod odabira stavki može vidjeti upozorenje ili savjetodavnu poruku uz proizvod. Poruka mu objašnjava da za taj proizvod možda postoji iznimka ili da će zahtjev trebati ručnu provjeru.
S admin strane, to pomaže trgovcu da odmah vidi zašto zahtjev nije “čist” i zašto ga treba dodatno provjeriti prije odluke.
Dodatno, ako se ista logika odnosi na cijelu grupu proizvoda, oznake se mogu postaviti na kategoriju. To je praktično za shopove koji imaju npr. kategoriju personaliziranih proizvoda, digitalnih proizvoda, higijenskih proizvoda ili sličnih artikala. Oznake s kategorije se tada mogu primijeniti na proizvode unutar te kategorije, bez ručnog označavanja svakog proizvoda posebno.
Ukratko, savjetodajne oznake ne služe za automatsko odbijanje kupca. Služe za bolji kontekst, jasniju komunikaciju i lakšu ručnu obradu zahtjeva.
Link u WooCommerce e-mailovima

Plugin može dodati link za raskid ugovora u odabrane WooCommerce e-mailove narudžbe.
Poanta je da kupac ne mora kopati po uvjetima poslovanja ili footeru. Link ga vodi na javni lookup obrazac, a može prefillati broj narudžbe i billing e-mail kroz siguran prefill token.
Prefill ne otvara automatski drugi korak i ne zaobilazi provjeru vlasništva narudžbe. Samo štedi kupcu tipkanje.
Privatnost i sigurnost
Od početka sam pokušao držati plugin privacy-first koliko ima smisla za ovakav tip alata.
Neke od stvari koje su ugrađene:
- guest lookup traži broj narudžbe i billing e-mail
- siguran link za goste je preporučen
- prefill token ne izlaže e-mail direktno u URL-u
- IP i user agent se spremaju hashirano
- lookup ima rate limiting
- requesti se spremaju u vlastite tablice
- retention cleanup anonimizira stare zapise
- privacy exporter/eraser hooks su podržani
- uninstall ne briše automatski request history jer trgovac možda mora čuvati evidenciju
Kod privitaka treba biti posebno pažljiv. Ako kupci uploadaju fotografije ili dokumente, to može biti osjetljiv sadržaj. Plugin radi osnovne zaštite, ali hosting, nginx, CDN i cache pravila treba provjeriti prije produkcije.
Kompatibilnost s custom order number pluginovima
Jedan od realnih WooCommerce problema su custom/sequential order number pluginovi.
Kupac vidi jedan broj narudžbe, WooCommerce interno koristi drugi ID, a plugin onda mora paziti da ne poveže krivu narudžbu.
Zato lookup prihvaća broj s # i bez #, normalizira unos i provjerava da javni broj narudžbe odgovara onome što kupac unosi.
Dodana je i osnovna podrška za neke česte meta ključeve, plus filteri za developere:
mx_contract_withdrawal/order_lookup_meta_keysmx_contract_withdrawal/order_number_meta_keysmx_contract_withdrawal/lookup_order_by_number
Ako shop koristi custom order number plugin, prije produkcije obavezno treba testirati javni lookup s brojem koji kupac stvarno vidi u e-mailu ili My Accountu.
Što plugin namjerno ne radi?
Plugin namjerno ne pokušava riješiti sve što se u praksi može dogoditi nakon što kupac pošalje zahtjev.
Ne radi sljedeće:
- nema automatske pravne odluke
- nema automatskog povrata
- ne rješava logistiku povrata robe
- ne generira povratne naljepnice
- ne provjerava fizičko stanje proizvoda
- nema tvrdnje da je shop “100% usklađen”
- ne pokušava zamijeniti pravnika, računovodstvo ili interne procedure trgovca
Ovo je alat za tehnički dio procesa: zaprimanje, potvrdu, zapis, pregled i obradu zahtjeva.
Za koga je ovo?
Za WooCommerce shopove koji prodaju potrošačima i žele imati uređeniji način za jednostrani raskid ugovora od obične kontakt forme.
Posebno za shopove koji žele:
- javnu stranicu za raskid ugovora
- link u WooCommerce e-mailovima
- sigurniji guest flow
- povezivanje s narudžbom
- odabir stavki i količina
- potvrdu kupcu
- admin obradu zahtjeva
- audit timeline
- CSV export
- opcionalne privitke
- print/PDF zapis zahtjeva
- osnovnu privacy/retention logiku.
Nije za one koji traže kompletan RMA sustav, skladišnu obradu povrata, automatske povratne naljepnice ili refund workflow. To su povezane teme, ali nisu isto što i zahtjev za jednostrani raskid ugovora.
Status plugina
Verzija 2.0 je prvi public release.
Do nje smo došli kroz dosta sitnih iteracija, testiranja, prijedloga i rasprava. Dio ideja je došao upravo iz FB grupe WooCommerce Hrvatska, gdje sam kroz zadnje vrijeme skupljao dojmove i feedback.
Ako koristiš WooCommerce i ova tema ti je aktualna, slobodno testiraj plugin na stagingu i javi što nedostaje, što je nejasno ili što bi u stvarnom shopu trebalo bolje riješiti.
Meni je cilj da plugin bude praktičan, normalan za korištenje i dovoljno oprezan za realne edge caseove.
Napomena
Plugin pomaže tehnički podržati workflow za zahtjeve za jednostrani raskid ugovora. Nije pravni savjet i ne jamči pravnu usklađenost shopa. Prije produkcijske upotrebe treba provjeriti vlastite uvjete poslovanja, vrstu proizvoda/usluga, iznimke od prava na jednostrani raskid, rokove i konačne zakonske obveze za konkretan shop.
WooCommerce plugin za raskid ugovora
Možete skinuti besplatan plugin koji omogućava funkcionalnost opisanu u članku. Downloadajte ga, instalirajte ga kao svaki drugi plugin (upload zip datoteke) ili FTP klijentom povučete raspakirani folder plugina u wp-content/plugins folder i aktivirajte u adminu.
Ažuriranja preko vlastitog servera
Plugin se ne distribuira preko WordPress.org repozitorija, nego koristi vlastiti sustav za ažuriranja.
To znači da se nove verzije mogu prikazati direktno u WordPress adminu, slično kao i kod standardnih WordPress pluginova. Kad je dostupna nova verzija, trgovac dobije obavijest u adminu i može pokrenuti update bez ručnog skidanja ZIP datoteke i ponovnog uploadanja plugina.
Zašto vlastiti server? Zato što je plugin specifičan, još se aktivno razvija i želim zadržati bolju kontrolu nad distribucijom, changelogom, testiranjem i bržim izdavanjem popravaka. Također, ovo omogućuje da se važni bugfixevi i sigurnosne dorade lakše isporuče korisnicima koji plugin već koriste.
Ažuriranja preko vlastitog servera ne mijenjaju način rada WordPressa. Plugin se i dalje ažurira kroz poznati WordPress update ekran, samo izvor update informacija nije WordPress.org, nego server s kojeg se plugin distribuira.
Prije svakog većeg updatea i dalje preporučujem standardnu praksu: napraviti backup i, ako je moguće, prvo testirati novu verziju na stagingu. Pogotovo za shopove koji imaju custom checkout, custom order number pluginove, cache/CDN setup ili dodatne integracije oko narudžbi.
Changelog
Sve izmjene, bugfixeve i nove funkcionalnosti pratit ćemo ovdje. Provjeravajte redovito za nove verzije i poboljšanja.
= 2.0.0 =
* Added optional supporting attachments with configurable visibility, reason rules, file-count and size limits, and a restricted JPG, JPEG, PNG, WebP, and PDF allowlist.
* Added secure attachment storage handling, randomized stored filenames, upload-directory protections, validation for real browser uploads, and cleanup during request anonymization.
* Added multi-step frontend attachment selection, selected-file previews, removal controls, upload result notices, and a 2 MB default maximum file size.
* Added an admin attachment gallery, safe attachment deletion, active attachment counts, request-list attachment filters, and attachment count/detail links in admin notification emails.
* Extended the WordPress privacy exporter and eraser to handle supporting attachment metadata without exposing private file paths.
* Added optional browser-native printable request records for administrators and short-lived customer print links after submission, with browser Save as PDF support.
* Added a configurable Return conditions notice with custom title, text, link, Media Library PDF selection, display locations, and optional customer acknowledgement recorded with the request.
* Added Return conditions content to supported frontend, receipt-email, and printable request contexts, including plain-text email URL handling.
* Added settings importance badges for mandatory, recommended, and optional configuration areas, and hid the readiness Mandatory badge once the plugin is ready to accept requests.
* Added an option to show the optional storefront footer link only on WooCommerce shop, product, category, and tag pages.
* Expanded the admin CSV export with human-readable request status and classifications, selected item and quantity summaries, active attachment counts, reason, and customer note.
* Improved CSV export performance by bulk-loading item rows and attachment counts, while preserving current filters and spreadsheet formula-injection protection.
* Improved the Classic and HPOS WooCommerce Orders withdrawal column with the latest request status badge, total request count, and active attachment count.
* Bulk-loaded WooCommerce Orders column summaries to avoid per-order request and attachment queries.
* Hardened custom order-number lookup with broader input normalization, contextual resolver arguments, public-number verification, duplicate-match rejection, and the backward-compatible `mx_contract_withdrawal/order_number_meta_keys` filter alias.
* Hardened the self-hosted updater so updates are offered only when the remote version is strictly newer, same-version notices are removed, and updater caches are cleared after successful updates.
* Rechecked remote version availability before returning self-hosted update package URLs.
* Migrated retention maintenance to WooCommerce Action Scheduler when available, with chained batches, chain-scoped locking, failure reporting, stale submit-lock cleanup, and a bounded WP-Cron fallback.
* Improved retention teardown on deactivation and uninstall by clearing plugin-owned Action Scheduler actions, WP-Cron events, and retention locks.
* Improved retention failure recovery so failed Action Scheduler batches release their matching chain lock before being marked failed.
* Replaced timestamp-only WordPress-local time calls with UTC timestamps where required.
* Prevented customers from continuing to request review when no order item is selected, with both frontend and server-side validation.
* Improved the final confirmation button styling so it inherits the active theme button color instead of using the plugin danger style.
* Improved Croatian translations and regenerated translation files for the new settings, notices, attachments, print views, and admin export fields.
* Updated WordPress and WooCommerce compatibility metadata for the 2.0.0 release.
= 1.0.1 =
* Hardened self-hosted update package URL handling to require HTTPS downloads.
* Improved public form nonce expiry handling with customer-facing recovery notices.
* Improved privacy erasure by removing customer actor identifiers from retained audit log events.
* Aligned release metadata for the 1.0.1 public build.
* Small fixes
= 1.0 =
* First stable release.
* Redesigned the plugin admin settings screen with a cleaner card-based layout, tabbed sections, inline icons, responsive navigation, switch-style toggles, preview actions, and shortcode copy support.
* Reorganized settings into clearer sections for page/display options, merchant details, eligibility and review rules, guest access and privacy, email notifications, and diagnostics.
* Added a dedicated Email notifications section with quick links to the related WooCommerce email settings used by the withdrawal workflow.
* Added privacy-safe email diagnostics for plugin emails, including last attempted send, last confirmed success, email type, request ID, error code, test email support, and a clear diagnostics action.
* Improved email delivery logging so unconfirmed sends and WordPress/PHPMailer errors are recorded more accurately per email type.
* Added CSV export for withdrawal requests using the current status, eligibility, date, and search filters.
* Added admin request overview stats for open requests, requests needing review, unknown deadlines, resolved requests this month, and total requests this month.
* Improved request list and detail badges so manual-review states are easier to understand.
* Changed the default request retention period from 6 years to 10 years.
* Improved retention cleanup so expired records are anonymized through the request repository and stored consumer details and billing snapshots are cleared.
* Added cleanup for stale submit-lock options.
* Improved public order lookup so customers can enter order numbers with or without the # symbol.
* Hardened order number normalization by trimming hidden characters and common punctuation, verifying the public order number, and supporting custom order number variants stored with or without #.
* Added frontend help text explaining where customers can find their order number.
* Reduced order email prefill token lifetime from 7 days to 72 hours.
* Improved expired or already-used secure guest link handling with a clearer message and a Start again action.
* Improved secure guest link handling when a valid guest access session already exists.
* Adjusted guest secure-link email sending so the public lookup flow can redirect before the email is sent.
* Fixed frontend price and currency display so order totals and selected item amounts do not split awkwardly across lines.
* Polished the final request received screen by moving the success checkmark next to the title and normalizing its size.
* Improved personal data export by showing submitted consumer details as readable fields instead of raw JSON.
* Updated privacy policy text and readme documentation for update checks, retention/uninstall behavior, and custom order number compatibility.
* Updated Croatian translations and regenerated translation files.
= 0.3.3 =
* Added an optional contract withdrawal link block for WooCommerce customer order emails.
* Added a new settings section for the order email withdrawal link.
* Added the ability to enable or disable the withdrawal link in order emails.
* Added the ability to choose which WooCommerce customer order emails should include the link.
* The link is shown by default in processing, on-hold, and completed customer order emails.
* Added optional support for showing the link in customer invoice emails.
* Added the ability to display the link as either a button or a plain text link.
* Added a setting for customizing the link/button text.
* The email link now points to the configured contract withdrawal page.
* Added a safe prefill token for order email links.
* The email link no longer exposes the customer e-mail address directly in the URL.
* The prefill token only pre-fills the order number and billing e-mail address in the lookup form.
* The prefill token does not open the second step of the form, does not verify order ownership, and does not bypass the guest secure-link flow.
* Added a 72-hour lifetime for prefill tokens.
* Added the `mx_contract_withdrawal/prefill_token_ttl` filter for changing the prefill token lifetime.
* The email link is not shown when the withdrawal page is missing or not published.
* The email link is not shown when the order already has a withdrawal request.
* The email link is not shown for orders that are not in allowed lookup statuses.
* The email link is not shown for older orders outside the configured action window, unless manual review for older orders is enabled.
* Added protection against rendering the contract withdrawal email block more than once.
* The email block now hooks into multiple WooCommerce e-mail positions for better compatibility with different e-mail templates.
* Improved the e-mail button markup so it works better across e-mail clients.
* The e-mail button now uses inline styling and WooCommerce e-mail colors instead of relying on CSS classes.
* Updated the Croatian default button text to “Pokreni zahtjev za raskid ugovora”.
* Added translation loading before default options are saved on activation, so new Croatian installations can receive Croatian default text.
* Added a new deadline estimation option based on the order received date.
* Added the new “Order received date + delivery buffer” estimation mode.
* Clarified that the existing completed-date estimation option uses the WooCommerce Completed order date.
* Added helper text explaining that WooCommerce Completed date means the date when the order was marked as Completed in WooCommerce.
* Deadline estimation no longer falls back to the order received date when the WooCommerce Completed date is missing; those cases are sent to manual review instead.
* Updated deadline estimation helper text to make it clearer that these options are only review-window estimates and not automatic legal decisions.
* Updated admin deadline notes to clearly show whether the estimate is based on the order received date or the WooCommerce Completed date.
* Updated Croatian translations for the new order email link settings, prefill flow, and deadline estimation text.
= 0.3.2 =
* Maintenance release with packaging/version alignment for the current 0.3.x build.
= 0.3.1 =
* Added a configurable customer-facing order action visibility window for account and public request entry points, without treating it as a legal deadline decision.
* Added a clear My Account withdrawal requests empty state with a link back to customer orders.
* Expanded product and category advisory flags for manual review while keeping flagged items selectable.
* Kept public guest lookup privacy-neutral for old orders and preserved manual-review handling where enabled.
* Secure magic-link guest flow is enabled by default for new installs.
* Polished the frontend withdrawal flow from lookup through success, including consumer detail confirmation before declaration submission.
* Added merchant details including OIB / Tax ID to declaration context and receipt snapshots.
* Added a readiness widget for withdrawal page, merchant identity, shortcode, and email setup.
* Integrated customer/admin/status/secure-link notifications with WooCommerce emails.
* Added WooCommerce order notes and admin notices for request and email events.
* Added cache guidance for customer-specific withdrawal pages.
* Updated Croatian terminology for contract withdrawal contexts.








