Во живо · статус OK
Документација · OW Agenda v1.3.1

OW Agenda
Документација

Закажување термини во WordPress што не дозволува никој залудно да ти ги зафаќа термините.

v1.3.1GPL-2.0-or-laterДокументација

OW Agenda — Документација

Онлајн закажување термини и секојдневната агенда, во WordPress, без претплата. Автор: OptionWeb — Julien Daniel Страница на додатокот: https://optionweb.dev/mk/addons/ow-agenda/ Лиценца: GPL-2.0-or-later Верзија покриена со овој документ: 1.3.1


Содржина

  1. Преглед
  2. Инсталација
  3. Брз почеток
  4. Текот на резервацијата
  5. Двојната потврда по е-пошта
  6. Одобрувањето на барањата
  7. Страницата Агенда
  8. Именикот на клиенти
  9. Поканите за сеанса
  10. Е-пошти и календарска датотека (ICS)
  11. Потсетници и закажана задача
  12. Анти-спам и ограничувања на брзината
  13. GDPR
  14. Shortcode-ови
  15. REST API
  16. Референца на поставките
  17. Зачувани податоци
  18. Интернационализација
  19. Деинсталација
  20. Решавање проблеми
  21. ЧПП
  22. Changelog

Преглед

OW Agenda му додава на WordPress целосен систем за термини: јавна страница на која посетителот го избира својот ден, а потоа и часот, и страница «Агенда» заштитена со најава, замислена да се користи од телефон, на која вие го водите денот.

Сè останува во сајтот. Без надворешен сервис, без API од трета страна, без претплата: термините ги пресметува вашиот сервер, состаноците живеат во вашите MySQL табели, е-поштата тргнува преку wp_mail().

Што е испорачано (сè е бесплатно, GPL-2):

  • Онлајн резервација: избор на ден, избор на термин, краток формулар, поле за GDPR согласност
  • Двојна потврда по е-пошта: барањето станува вистинско дури по клик на линкот за потврда — ботовите никогаш не стигнуваат до агендата
  • Рачно одобрување (препорачано) или автоматска потврда, со копчиња Потврди / Одбиј директно во известувањето по е-пошта (линкови потпишани со HMAC, без најава)
  • Mobile-first страница «Агенда»: преглед на денот, барања на чекање, термини земени по телефон и внесени рачно, блокирање термини, презакажување, статуси завршено / не се појави
  • Именик на клиенти: пребарување, создавање, уредување, бришење; се полни автоматски од потврдените термини
  • Покани за сеанса: приватен линк му овозможува на постоен клиент сам да го избере датумот на својата сеанса, за услуга и времетраење што вие ги одредувате
  • Уредни HTML е-пошти со ICS прилог (додавање во календарот на телефонот со еден потег), автоматски потсетник претходниот ден, онлајн откажување од страна на клиентот
  • Автоматска анонимизација на минатите термини, чистење на барањата што никогаш не биле потврдени
  • Целосна REST API под namespace owag/v1

Што намерно не прави:

  • Без онлајн плаќање: OW Agenda го закажува терминот, не наплаќа капар (користете WooCommerce ако тоа ви треба)
  • Само една агенда: без управување со повеќе практичари или повеќе ресурси; додатокот опишува еден распоред, оној на сајтот
  • Без двонасочна синхронизација со Google Calendar или Outlook: календарот на клиентот се ажурира преку ICS датотека (еднонасочно), а вашата лична недостапност се внесува како блокади
  • Без каталог на услуги од страна на посетителот: јавната резервација се однесува на една единствена услуга (со подесив назив и времетраење); останатите услуги одат преку поканите за сеанса
  • Без повторливи термини, без видеоконференции, без чекална

Овој список е архитектонски избор, а не скриен roadmap: едноставна агенда што никогаш не греши со терминот вреди повеќе од сложена машинерија што никој не смее да ја допре.


Инсталација

Од .zip

  1. Преземете ow-agenda-1.3.1.zip од https://optionweb.dev/mk/addons/ow-agenda/
  2. Plugins → Add New → Upload Plugin
  3. Изберете ја датотеката, кликнете Install Now, потоа Activate

Преку FTP

Отпакувајте ја архивата и ставете ја папката ow-agenda во /wp-content/plugins/, потоа активирајте го додатокот од Plugins.

Предуслови

  • WordPress 6.3 или понов
  • PHP 7.4 или понов (8.1+ препорачано)
  • MySQL 5.7+ / MariaDB 10.2+ — функциите GET_LOCK() / RELEASE_LOCK() се користат за серијализирање на истовремените резервации
  • Испраќање на е-пошта што функционира. Тоа е единствената вистинска зависност на додатокот: целиот тек (потврда, одобрување, потсетник, откажување) минува низ е-поштата. На споделен хостинг, инсталирајте SMTP додаток пред да ја пуштите агендата во живо.

Што се инсталира

При активирање, OW Agenda создава три табели:

ТабелаСодржина
{prefix}_owag_appointmentsСите настани од агендата: веб консултации, сеанси произлезени од покана, термини внесени рачно, блокирани термини
{prefix}_owag_invitesПриватните линкови «изберете го датумот на вашата сеанса»
{prefix}_owag_customersИменикот на клиенти

…и, само првиот пат, две објавени страници:

  • «Закажи термин» — ја содржи shortcode [ow_agenda]
  • «Агенда» — ја содржи shortcode [ow_agenda_admin]

Нивните идентификатори се памтат во опциите owag_page_booking и owag_page_admin; знаменцето owag_pages_created гарантира дека деактивирање проследено со повторно активирање нема да создаде дупликати. Можете да ги преименувате овие страници, да ги преместите во мени, да го смените нивниот permalink: додатокот ги следи преку нивниот ID.

Активирањето додава и:

  • capability owag_manage на улогата administrator — таа, а не manage_options, ја отвора агендата и административните REST рути;
  • стандардните поставки во опцијата owag_settings;
  • часовната закажана задача owag_hourly_event (првото извршување е 5 минути по активирањето).

HMAC тајна (owag_admin_secret, 64 знаци, не се вчитува автоматски) се генерира при првото известување до администраторот: таа ги потпишува копчињата Потврди / Одбиј во е-поштите.

Давање пристап на некој друг

Страницата Агенда е видлива за секој најавен корисник што има owag_manage. За да ѝ ја отворите агендата на асистентка без да ѝ ги дадете клучевите од сајтот:

// À exécuter une fois (mu-plugin, ou plugin de gestion des rôles).
$role = get_role( 'editor' );
if ( $role ) { $role->add_cap( 'owag_manage' ); }

Брз почеток

По активирањето, отворете OW Agenda (главно мени на администрацијата). Екранот со поставки собира на една страница; пет минути се доволни.

1. Работното време

За секој ден од неделата, внесете еден интервал (09:00 → 18:00) и, ако правите пауза на пладне, втор интервал (14:00 → 18:30). Ден оставен празен е затворен ден. Стандардно: од понеделник до петок, 09:00–18:00; сабота и недела затворено.

Работното време се толкува во временската зона на сајтот (Settings → General → Timezone). Проверете ја пред да ја отворите резервацијата: сите датуми се чуваат во локално време.

2. Услугата што се резервира онлајн

  • Назив на консултацијата — она што посетителот го гледа како наслов на виџетот («Консултација», «Прв термин», «Проценка»…)
  • Времетраење на консултацијата — 60 минути стандардно. Токму тоа времетраење се блокира во агендата.
  • Чекор на термините — растојанието меѓу два понудени часа (30 минути стандардно). Со времетраење од 60 и чекор од 30, нудите 9:00, 9:30, 10:00… а првиот термин земен во 9:30 ги брише 9:00 и 10:00 од списокот.
  • Пауза меѓу два термина — минути за здив додадени од двете страни на секој кандидат-термин (0 стандардно).

3. Роковите

  • Минимална најава за резервација — 24 ч стандардно: посетителот не може да резервира за за еден час.
  • Хоризонт на резервација — 60 дена стандардно: подалеку од тоа, ништо повеќе не се нуди.
  • Онлајн откажување од клиентот — до 24 ч пред терминот; по тој рок, страницата за откажување поканува да ви се јават.

4. Одобрувањето и е-поштите

  • Потврда на барањата: рачно одобрување (препорачано) или автоматска потврда.
  • Двојна потврда по е-пошта: оставете ја штиклирана. Тоа е најдобрата анти-бот заштита во додатокот.
  • Административните известувања се праќаат на: вашата адреса. Стандардно, административната е-пошта на сајтот.

Зачувајте, потоа отворете ја страницата «Закажи термин»: виџетот ги прикажува следните 14 дена и вашите слободни термини. Во живо сте.

5. Агендата на телефон

Отворете ја страницата «Агенда» на вашиот телефон, најавете се, потоа употребете «Додај на почетен екран». Додатокот објавува манифест за апликација: страницата тогаш се отвора на цел екран, без лента на прелистувачот, како апликација.


Текот на резервацијата

Од страна на посетителот, страницата за резервација е самостојна компонента (JavaScript без framework, помалку од 10 KB) што разговара со јавните endpoint-и owag/v1/public/*.

Чекор 1 — денот

При вчитување, виџетот ја бара достапноста за 14 дена од денес и прикажува лента од денови на кои може да се кликне. Ден без слободен термин е засивен и не може да се кликне. Копчето «Види ги следните датуми» ги вчитува следните 14 дена, онолку пати колку што е потребно до конфигурираниот хоризонт.

Датумите во виџетот се градат во локалното време на прелистувачот, никогаш во UTC. Тоа е поправка од 1.3.0: претходно, посетител источно од UTC што ја отвораше страницата кратко по полноќ го гледаше списокот како почнува претходниот ден и губеше цел ден достапност.

Чекор 2 — часот

Кликот на ден го повикува /public/slots и ги прикажува слободните почетни часови. Термин се нуди кога сите овие услови се исполнети:

  1. паѓа во интервал од работното време на тој ден;
  2. целиот термин (почеток + времетраење) собира пред затворањето;
  3. почнува по сега + минималната најава;
  4. денот е во рамките на хоризонтот на резервација;
  5. не се преклопува со ниту еден активен настан, вклучувајќи ја и паузата — а „активен настан“ ги опфаќа потврдените термини, барањата на чекање, блокадите, термините земени по телефон и внесени рачно, и уште непотврдените барања што сè уште го задржуваат својот термин.

Тоа е важната точка: сè што ја зафаќа агендата го затвора онлајн терминот. Термин земен по телефон и запишан во агендата веднаш исчезнува од термините понудени на сајтот.

Чекор 3 — формуларот

Четири полиња, од кои три задолжителни: име (најмалку 2 знаци), телефон (најмалку 8 цифри), е-пошта (валидирана), слободна порака. Задолжително е и поле за GDPR согласност, кое не е штиклирано однапред.

Формуларот носи со себе и две полиња невидливи за посетителот — замка за ботови и временски печат од отворањето на страницата — опишани во делот Анти-спам.

Чекор 4 — одговорот

Според вашата конфигурација, три исходи:

КонфигурацијаСоздаден статусПрикажана порака
Двојна потврда по е-пошта активна (стандардно)unverified«Уште еден потег: штотуку ви е испратена е-пошта…»
Потврдата исклучена + рачно одобрувањеpending«Вашето барање е примено!»
Потврдата исклучена + автоматска потврдаconfirmed«Вашиот термин е потврден!»

Ако терминот бил зафатен помеѓу прикажувањето на списокот и испраќањето на формуларот, посетителот добива јасна порака (owag_slot_taken, HTTP 409) и списокот на денови се превчитува автоматски. Двајца посетители не можат да го добијат истиот термин: критичната секција е серијализирана со именувано MySQL заклучување, специфично за вашата база и за вашиот префикс на табели, што важи и на споделен хостинг.


Двојната потврда по е-пошта

Тоа е функцијата што го одделува OW Agenda од преправен контакт формулар.

Кога Двојна потврда по е-пошта е активна (поставка email_verify, вклучена стандардно):

  1. Барањето се запишува со статус unverified. Администраторот не добива известување. Терминот не се појавува како барање за обработка.
  2. Посетителот добива е-пошта «Уште еден потег…» со копче за потврда.
  3. Терминот е задржан 45 минути. По тој рок без потврда, тој повторно станува достапен за сите — значи бот не може да ви го замрзне денот.
  4. Кликот на копчето отвора самостојна страница (?owag_verify=<uid>) што го прикажува резимето на терминот и копче «Го потврдувам моето барање». Потврдата тргнува само на клик: антивирусите и скенерите на линкови што ги посетуваат URL-адресите од е-поштите не потврдуваат ништо.
  5. Барањето тогаш станува pending (рачно одобрување) или confirmed (автоматска потврда), клиентот ја добива соодветната е-пошта, и дури тогаш тргнува известувањето до администраторот.
  6. Барањата што никогаш не биле потврдени се бришат по 48 ч од часовната задача. Тие не оставаат ниту трага ниту лични податоци.

Ако, помеѓу испраќањето и кликот, терминот го зел некој друг (прозорецот од 45 минути е поминат), потврдата враќа јасна грешка и барањето се откажува — никогаш фантомски термин врз веќе зафатено место.

Практична последица: невалидна адреса за е-пошта не создава никаков термин. Повеќе не губите време да враќате повици на лажни броеви. Цената е еден дополнителен клик за клиентот; искуството покажува дека стапката на откажување е далеку помала од стапката на лажни термини што таа ја спречува.

Резервациите произлезени од покана за сеанса го прескокнуваат овој чекор: клиентот веќе докажал дека си ја чита поштата кликајќи на приватниот линк што го добил.


Одобрувањето на барањата

Рачно одобрување (препорачано)

Стандардна поставка: auto_confirm = 0. Потврдено барање пристигнува со статус pending. На клиентот ништо не му е ветено додека вие не сте направиле ништо — но терминот е веќе блокиран, никој не може да ве престигне.

Добивате е-пошта «За потврда: <клиент> — <датум>» со целосно резиме (услуга, датум, име, телефон, е-пошта, порака од клиентот) и две копчиња:

  • Потврди го терминот — цијан
  • Одбиј — со црвена контура

Копчињата во е-поштата: линкови потпишани со HMAC

Овие копчиња не бараат никаква најава. Тие водат кон вашиот сајт со три параметри: owag_admin_action (confirm или refuse), uid (случајниот идентификатор на терминот) и sig, потпис HMAC-SHA256 на uid|action пресметан со приватната тајна на сајтот (owag_admin_secret).

  • Потписот се проверува пред да се прикаже и најмалиот детал: манипулиран линк не прикажува ништо друго освен «Невалиден линк».
  • Споредбата користи hash_equals() — без истекување на информации преку времето на одговор.
  • Страницата прикажува резиме и копче; дејството се извршува само на клик. Значи скенер на линкови не потврдува ништо наместо вас.
  • Веќе обработено барање враќа «Веќе обработено (статус: …)» наместо грешка.

Потврдувањето автоматски ја испраќа е-поштата за потврда до клиентот, со календарската датотека. Одбивањето ја испраќа е-поштата за откажување. Во двата случаја, агендата е ажурирана пред да сте го оставиле телефонот.

Овие линкови остануваат валидни сè додека терминот е на чекање. Ако ја избришете опцијата owag_admin_secret (делумно враќање на базата, рачно чистење), сите веќе испратени линкови престануваат да работат: се генерира нова тајна и старите потписи повеќе не се совпаѓаат. Тогаш работете преку страницата Агенда.

Автоматска потврда

Поставка auto_confirm = 1. Слободен термин се потврдува веднаш: клиентот ја добива својата потврда со календарската датотека, вие добивате известување «Нов термин». Резервирано за дејности каде што секој отворен термин е прифатлив термин.

Двете поставки се комбинираат со двојната потврда: дури и при автоматска потврда, барањето прво минува низ unverified ако email_verify е активна.


Страницата Агенда

Страницата «Агенда» ([ow_agenda_admin]) е алатката за секој ден. Таа е замислена прво за телефон: широки копчиња, една колона, без табела што се лизга хоризонтално, а се разбира работи подеднакво добро и на компјутерски екран.

Заштитена е: ненајавен посетител гледа линк за најава, најавен корисник без capability owag_manage гледа «Пристапот е резервиран за тимот». Страницата е noindex,nofollow: никогаш нема да заврши во Google.

Јазиче Агенда — прегледот на денот

Тековниот ден, настан по настан, со часот, времетраењето, називот, статусот и потеклото (сајт, покана, рачен внес). Навигација од ден на ден, копче Денес. На секој термин:

  • Детали — контакт податоци на клиентот, порака оставена при резервацијата, и блок со внатрешни белешки (никогаш видливи за клиентот) што се зачувуваат без да се испрати ниту една е-пошта
  • Потврди ✓ — за барање што е сè уште на чекање; е-поштата за потврда тргнува
  • Завршено / Не се појави (no-show) — статуси на крајот од терминот
  • Помести — нов датум, нов час, евентуално изменето времетраење. Додатокот ве прашува дали клиентот треба да биде известен по е-пошта; ако да, тој добива ажурирана потврда и календарска датотека што го поправа настанот што веќе е на неговиот телефон
  • Откажи го терминот — повторно со избор дали да го известите клиентот или не
  • Избриши ја блокадата — за блокиран термин

Кога некое дејство создава преклопување (преместување врз зафатен термин), додатокот предупредува и бара потврда: можете да форсирате. Тоа е вашиот распоред, вие знаете што правите — заштитата е блокирачка само за посетителите.

Додавање термин или блокада

Копчето «Додај термин» отвора единствен образец што служи за две употреби:

  • Термин — клиентот ви се јавил. Име, телефон, е-пошта (изборно), услуга, датум, час, времетраење, внатрешни белешки. Ако внесете адреса за е-пошта и ја штиклирате опцијата, клиентот ја добива потврдата со својата календарска датотека, како да резервирал онлајн. Терминот го полни и именикот на клиенти.
  • Блокада (одмор, пауза…) — причина, датум, час, времетраење. Без е-пошта, без картон на клиент, но терминот веднаш исчезнува од онлајн резервацијата. Така се внесува недела одмор, обука, или пладневниот термин што не сакате да биде резервиран.

Јазиче На чекање

Списокот на потврдени барања што ја чекаат вашата одлука, за сите денови заедно (веќе поминатите термини се исклучени). Две копчиња по ред: Потврди и Одбиј. Тоа е првиот екран што се отвора наутро.

Совет: агендата како апликација

На страницата Агенда, додатокот објавува манифест за веб апликација (?owag_manifest=1) со името на сајтот, иконата на сајтот и бојата на темата. И на Android и на iOS, менито на прелистувачот тогаш нуди «Додај на почетен екран»: добивате икона, отворање на цел екран, и никогаш повеќе да ја куцате URL-адресата.


Именикот на клиенти

Третото јазиче на страницата Агенда е лесен именик, намерно минимален: име, телефон, е-пошта, слободни белешки.

  • Се полни сам. Штом еден термин е потврден (проверена онлајн резервација, сеанса по покана, рачен внес), клиентот се поврзува со постоен картон преку неговата е-пошта, а потоа преку неговиот телефон. Ако не постои, картонот се создава; ако постои, се дополнуваат само празните полиња — додатокот никогаш не го препишува тоа што сте го внеле рачно.
  • Пребарување по име, телефон или е-пошта (максимум 200 прикажани картони).
  • Рачно создавање и уредување, со поле за белешки за историјата, преференциите, мерките на претпазливост.
  • Две кратенки по картон: Нов термин (го пополнува однапред образецот за рачен внес) и Покани на сеанса (ја пополнува однапред поканата).
  • Бришење на картон: минатите термини остануваат во агендата, исчезнува само картонот од именикот.

Овој именик не е CRM и не се преправа дека е. Тој одговара на едно прашање: „Која беше, всушност, госпоѓата во 14 ч?“


Поканите за сеанса

Случајот на употреба: постоен клиент има право на сеанса — контрола, корекција, услуга продадена на друго место — и вие сакате тој сам да го избере својот датум без да минува низ јавната резервација, за услуга и времетраење што вие ги одредувате.

Од јазичето Покани:

  1. Внесете го името на клиентот, називот на сеансата (задолжителни), нејзиното времетраење (15 до 720 минути) и, ако сакате, неговата е-пошта и телефон.
  2. Изберете ја важноста на линкот: 60 дена стандардно, од 1 до 365.
  3. Штиклирајте по потреба «Испрати му го линкот на клиентот по е-пошта» — клиентот добива е-пошта «Изберете го датумот на вашата сеанса» со називот, времетраењето, датумот на истекување и копче.
  4. Инаку, копирајте го линкот и испратете го преку SMS, WhatsApp, или преку нативното копче за споделување на телефонот.

Линкот води кон вашата страница за резервација со приватен токен (?owag_invite=<token>, 32 хексадецимални знаци извлечени од криптографски генератор). Виџетот тогаш го прикажува називот и времетраењето на сеансата, а не на стандардната консултација. Клиентот го пополнува истиот краток формулар.

Правила што управуваат со еден линк за покана:

  • Еднократна употреба. Штом сеансата е резервирана, линкот одговара «Овој линк веќе е искористен» (HTTP 410). Две истовремени отворања со ист токен не можат да создадат две сеанси: трошењето на токенот се одвива под истото заклучување како и резервацијата на терминот.
  • Со рок. По истекувањето, линкот поканува повторно да ве контактираат (HTTP 410).
  • Без двојна потврда. Клиентот веќе го добил овој линк преку канал што вие го контролирате: сеансата се создава директно како confirmed, со потврда и календарска датотека.
  • Рециклиран при откажување. Ако сеансата се откаже (од вас или од клиентот), поканата се ослободува: линкот повторно станува активен и поканата повторно се појавува во списокот на отворени покани. Тоа е поправка од 1.3.0 — претходно, откажувањето го убиваше линкот засекогаш и мораше да се прави нов.
  • Отповиклив. Бришењето на покана од списокот го деактивира линкот веднаш.

Е-пошти и календарска датотека (ICS)

Трансакциските е-пошти

Сите пораки се во HTML, со распоред во табели компатибилен со Gmail и Outlook: бела картичка на светла позадина, име на сајтот во заглавието, резиме во рамка со цијан раб, копчиња во облик на пилула. Се испраќаат преку wp_mail(), значи ја почитуваат вашата SMTP конфигурација и вообичаените WordPress филтри.

Е-поштаПримачАктивирач
Потврда на барањетоКлиентВеб резервација кога двојната потврда е активна
Барањето е применоКлиентПотврдено барање, ја чека вашата одлука
Терминот е потврденКлиентПотврда (рачна, автоматска, админ внес, преместување) — со ICS прилог
Терминот е откажанКлиентОткажување од клиентот, одбивање или откажување од администраторот — со ICS прилог за откажување
ПотсетникКлиентАвтоматски, помеѓу 12 и 36 ч пред терминот
Изберете го датумот на вашата сеансаКлиентСоздавање покана со испраќање по е-пошта
За потврда: …АдминНово потврдено барање на чекање — со копчињата Потврди / Одбиј
Нов термин: …АдминНов потврден термин (автоматска потврда, покана)
Откажување од клиент: …АдминКлиентот самиот откажал преку својата е-пошта

Адресата за административни известувања е поставката notify_email (стандардно административната е-пошта на сајтот). Е-поштите до клиентот тргнуваат само ако адресата е валидна, и никогаш за блокиран термин.

Е-поштите за потврда и за откажување му потсетуваат на клиентот дека може да откаже онлајн, со бројот на часови најава што е навистина конфигуриран.

ICS прилогот

Датотеката .ics прикачена на потврдите е она што ја претвора една е-пошта во термин навистина присутен во телефонот на клиентот: еден потег на прилогот, и настанот е во неговиот календар, со свој сопствен потсетник.

Датотеката е усогласена со RFC 5545 и содржи сè што е потребно за календарските клиенти (Google, Outlook, Apple) правилно да ги обработат ажурирањата:

  • METHOD:REQUEST при создавање и при секоја измена на распоредот, METHOD:CANCEL при откажување;
  • стабилен UID изведен од идентификаторот на терминот и од доменот на сајтот — токму тој ѝ овозможува на една измена да го замени постоечкиот настан наместо да создаде втор;
  • растечки SEQUENCE изведен од датумот на последната измена, сведен на апсолутен момент: преминот на зимско време не може да го врати назад бројот на ревизијата (а откажувањето додава 1, за да остане повисоко од измена настаната во истата секунда);
  • ORGANIZER (вашата адреса за известувања) и ATTENDEE (клиентот);
  • DTSTART / DTEND во UTC, STATUS:CONFIRMED или STATUS:CANCELLED;
  • превиткување на редовите на 75 бајти без никогаш да се пресече UTF-8 знак.

Преместувањето на потврден термин значи испраќање на нова датотека што го поправа настанот што веќе е кај клиентот; откажувањето испраќа датотека што го брише. Тоа е поправка од 1.3.0: претходно старото време остануваше во календарот на клиентот.

Датотеката се запишува во привремениот директориум на серверот — никогаш во wp-content/uploads/, кој се служи јавно — преку WordPress API за датотеки, и се брише веднаш штом испраќањето заврши, вклучително и ако испраќањето не успее. Таа го носи името и е-поштата на клиентот: нема што да прави на дискот ниту секунда подолго од потребното.


Потсетници и закажана задача

Една единствена закажана задача, owag_hourly_event, што се извршува на секој час. Таа прави три работи.

1. Потсетникот од претходниот ден

Потсетникот тргнува кога терминот почнува за 12 до 36 часа. Тоа не е фиксен часовен прозорец, и тоа е намерно: WP-Cron се активира само при посета на страница. Сајт без сообраќај навечер ги губеше засекогаш потсетниците за следниот ден. Со подвижен прозорец, потсетникот тргнува при првото достапно извршување и го надоместува задоцнувањето.

Услови: потврден термин, внесена адреса за е-пошта, не е блокада, и потсетникот не е веќе испратен.

Секој потсетник е атомски резервиран пред испраќањето (условен UPDATE врз знаменцето reminder_sent): две извршувања на cron што се преклопуваат не можат двапати да ја испратат истата порака. Ако испраќањето не успее, резервацијата се враќа и потсетникот ќе биде обиден повторно при следното извршување. Кратко заклучување (10 минути) дополнително спречува две истовремени поминувања да го поминат истиот список.

Преместувањето на термин го враќа знаменцето на нула: клиентот навистина добива потсетник за новото време.

2. Чистењето на непотврдените барања

Барањата што останале unverified повеќе од 48 часа се бришат. (Нивниот термин, пак, беше веќе ослободен по 45 минути.)

3. GDPR анонимизацијата

Видете го делот GDPR.

Заштитната мрежа

WP-Cron настан може да исчезне: оптимизација на базата, делумно враќање, додаток за чистење, ресетирање на опцијата cron. OW Agenda при секое вчитување проверува дали задачата е добро закажана и ја презакажува ако не е. Потсетниците, чистењето и задржувањето не можат да запрат тивко.

Користење на вистински системски cron

WP-Cron зависи од сообраќајот. На слабо посетен сајт, подобро е системски cron:

// wp-config.php
define( 'DISABLE_WP_CRON', true );
# crontab -e — toutes les 15 minutes
*/15 * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/null

Анти-спам и ограничувања на брзината

Резервацијата е јавна по природа: без сметка, без најава, без можен nonce. Затоа пет независни заштити работат однапред.

1. Замката за ботови (honeypot)

Формуларот содржи текстуално поле надвор од екранот, невидливо за човек и примамливо за бот. Полето мора да биде присутно и празно. Пополнето поле — или отсутно, што издава директно испраќање до API — враќа суво одбивање (HTTP 403), без искористливи детали.

2. Времето на пополнување

Страницата го пренесува временскиот печат од своето прикажување. Испраќање пристигнато помалку од 4 секунди по вчитувањето се одбива. И тука, отсутен или неисправен временски печат значи одбивање: во 1.3.0, овие две полиња станаа задолжителни — нивното изоставување едноставно ја исклучуваше контролата.

3. Часовната квота по адреса

5 резервации на час и по опсег. Кај IPv4, опсегот е адресата; кај IPv6, тоа е префиксот /64 — таму напаѓачот располага со 2⁶⁴ адреси, броењето на целата адреса не би ограничило ништо.

Бројачот се зголемува само по валидацијата на формуларот: посетител што трипати по ред ја погрешил е-поштата повеќе не е блокиран еден час за ништо.

4. Дневната горна граница на непотврдени барања

Најмногу 3 барања што чекаат потврда по е-пошта можат да задржат термин во ист ден. Без оваа граница, неколку испраќања беа доволни за да ги замрзнат сите термини на еден датум. Над неа, посетителот добива покана да проба подоцна или да избере друг ден (HTTP 429).

5. Заклучувањето на резервацијата

Резервирањето на термин и трошењето на покана се одвиваат во критична секција серијализирана со именувано MySQL заклучување, чие име е изведено од вашата база и од вашиот префикс на табели (значи два сајта на ист споделен хостинг не се блокираат меѓусебно). Ако заклучувањето не се добие за 5 секунди, барањето враќа јасен HTTP 503 наместо двоен термин.

Ова заклучување ја заменува, од 1.3.0, трансакцијата што се потпираше на гол SELECT: под REPEATABLE READ, тој не поставува никакво заклучување на редот, и двајца истовремени посетители можеа да го резервираат истото време.

А двојната потврда

Тоа е најефикасниот слој: дури и ако помине сè претходно, бот никогаш не стигнува до вашата агенда ниту до вашето сандаче, бидејќи известувањето до администраторот се испраќа само по клик на линк примен по е-пошта. Видете Двојната потврда по е-пошта.


GDPR

Агендата за термини ракува со потенцијални здравствени податоци, со контакт податоци и со историјати. Стандардните поставки се намерно конзервативни.

Согласност

Полето за согласност е задолжително и не е штиклирано однапред на јавниот формулар: «Се согласувам моите контакт податоци да се користат за управување со мојот термин.» Резервација без согласност се одбива на страна на серверот, не само во прелистувачот.

Минимизација

  • Ниту една IP адреса не се чува во базата. Часовната квота користи привремен бројач (transient) чиј клуч е отпечаток од мрежниот опсег, избришан по еден час.
  • Никаков user agent, никаков tracker, никакво колаче поставено од додатокот.
  • Ниту еден податок не се испраќа до сервис од трета страна: без CDN, без надворешен повик, без телеметрија.
  • Барањата што никогаш не биле потврдени се бришат по 48 часа — тие не оставаат никакви податоци зад себе.
  • Откажаните термини повеќе не се враќаат од API на агендата: непотребните лични податоци не циркулираат.

Автоматска анонимизација

Поставка retention_months, 24 месеци стандардно. На секој час, завршените термини постари од тој рок се анонимизираат на самото место: името се заменува со «Анонимизирано», телефонот и е-поштата се празнат, пораката од клиентот и внатрешните белешки се бришат. Редот останува, што ја зачувува статистичката историја на дејноста (колку термини, кога, за која услуга) без да се чува ниту еден личен податок.

Ставете 0 за да ја исклучите автоматската анонимизација — со целосна свест за тоа.

Забелешка: анонимизацијата ги цели термините што носат адреса за е-пошта. Термин внесен рачно без е-пошта (само име и телефон) не е зафатен од автоматското чистење; избришете го рачно ако вашата политика на задржување го бара тоа.

Право на пристап и право на бришење

Додатокот не ги приклучува нативните WordPress извозници/бришачи (тие работат врз кориснички сметки, а клиентите немаат такви). За да обработите барање:

  • Пристап — побарајте ја личноста во именикот на клиенти (име, телефон или е-пошта) и поминете ги нејзините термини во агендата. Администраторите на базата можат и директно да ги пребараат {prefix}_owag_appointments и {prefix}_owag_customers по колоната customer_email / email.
  • Бришење — избришете го картонот од именикот, потоа откажете ги или оставете да се анонимизираат соодветните термини. Итно бришење се прави во базата по customer_email.
-- Effacement manuel des données personnelles d'une personne (adaptez le préfixe).
UPDATE wp_owag_appointments
   SET customer_name = 'Anonymisé', customer_phone = '', customer_email = '',
       customer_msg = NULL, admin_notes = NULL
 WHERE customer_email = 'personne@example.com';

DELETE FROM wp_owag_customers WHERE email = 'personne@example.com';

Регистар на обработки

За вашиот регистар: цел управување со термини; правен основ согласност (онлајн резервација) или извршување на договор / преддоговорни мерки (термин земен по телефон); категории идентитет, контакт податоци, содржина на пораката, внатрешни белешки; времетраење 24 месеци стандардно, потоа анонимизација; примачи ниту еден обработувач освен вашиот хостинг провајдер и вашата служба за испраќање е-пошта.


Shortcode-ови

[ow_agenda] — резервацијата за посетители

Се става на јавна страница. Без атрибути: услугата, времетраењето и работното време доаѓаат од поставките. Shortcode-от ги вчитува својот стилски лист и својата скрипта (вкупно под 12 KB, без зависности) и исцртува контејнер што се пополнува по првиот повик до API.

[ow_agenda]

Токму овој shortcode го толкува URL параметарот ?owag_invite=<token>: истата страница ја служи и стандардната консултација и сеансите по покана.

[ow_agenda_admin] — страницата за управување

Се става на посветена страница. Без атрибути. Shortcode-от сам го управува пристапот:

  • ненајавен посетител → линк за најава што враќа на страницата;
  • најавен без capability owag_manage → порака за ограничен пристап;
  • најавен со capability → целосниот интерфејс (агенда, на чекање, клиенти, покани).
[ow_agenda_admin]

Двете страници се создаваат автоматски при активирањето со овие shortcode-ови. Ако сте ги избришале, доволно е да создадете страница и да го залепите shortcode-от во неа — тогаш не заборавајте да ја ажурирате опцијата owag_page_admin (или owag_page_booking) за линковите во е-поштите и манифестот да покажуваат на вистинското место.

Самостојните страници

Четири URL параметри, пресретнати на која било страница од сајтот, произведуваат самостојни страници што се служат надвор од темата (минимално исцртување, noindex,nofollow):

URLУлога
?owag_verify=<uid>Потврда на барањето од клиентот (двојна потврда)
?owag_cancel=<uid>Онлајн откажување од клиентот
?owag_admin_action=confirm|refuse&uid=…&sig=…Потврда / одбивање од административната е-пошта
?owag_manifest=1Манифест за апликација на страницата Агенда

Овие страници никогаш не извршуваат дејство при вчитување: тие прикажуваат резиме и копче. Ниту еден бот, ниту еден антивирус за пошта, ниту еден prefetch на прелистувач не може да потврди или откаже термин наместо човек.


REST API

Сите endpoint-и живеат под namespace owag/v1, на вообичаениот REST корен (https://example.com/wp-json/owag/v1/…).

Јавни endpoint-и

Без автентикација: тоа се рутите на виџетот за резервација и на линковите примени по е-пошта. Нивната безбедност се потпира на случајни токени (32 хексадецимални знаци од криптографски генератор), на HMAC потписи, и на заштитите опишани во Анти-спам.

МетодПатекаПараметриУлога
GET/public/daysfrom (Y-m-d, стандардно: денес), token (покана, изборно)Враќа label, duration и days: 14 дена од from, секој со својот број слободни термини
GET/public/slotsdate (Y-m-d, задолжително), tokenВраќа slots: слободните почетни часови (HH:MM)
POST/public/bookdate, time, name, phone, email, message, consent, website (замка), ts (временски печат), tokenГо создава барањето; враќа status и порака за прикажување
POST/public/verifyuidПотврдува барање со статус unverified
POST/public/canceluidОткажува термин pending или confirmed, во рамките на рокот на најава
POST/public/admin-actionuid, action (confirm|refuse), sigПотврдува или одбива од административната е-пошта (HMAC потпис)

Пример за резервација:

curl -X POST https://example.com/wp-json/owag/v1/public/book \
  -H 'Content-Type: application/json' \
  -d '{
    "date": "2026-09-15",
    "time": "14:30",
    "name": "Marie Dupont",
    "phone": "0470 12 34 56",
    "email": "marie@example.com",
    "message": "Première visite",
    "consent": 1,
    "website": "",
    "ts": 1757942400
  }'
{
  "ok": true,
  "status": "unverified",
  "message": "Un dernier geste : un e-mail vient de vous être envoyé…"
}

Административни endpoint-и

Сите бараат capability owag_manage и валиден WordPress REST nonce (заглавие X-WP-Nonce).

МетодПатекаПараметриУлога
GET/admin/agendafrom, to (Y-m-d)events (бараниот опсег, без откажаните) и pending (сите претстојни барања на чекање)
POST/admin/appointmentkind (manual|block|consult|seance), date, time, duration (5–720 мин), label, name, phone, email, notes, force, send_emailСоздава рачен термин или блокада
POST/admin/appointment/{id}status (pending|confirmed|cancelled|done|noshow), name, phone, email, label, notes, date, time, duration, force, silentАжурира, поместува, менува статус. silent=1 го спречува секое испраќање на е-пошта
GET/admin/customersq (пребарување)Именикот (максимум 200 картони)
POST/admin/customersname (задолжително), phone, email, notesСоздава картон
POST/admin/customers/{id}истоАжурира картон
DELETE/admin/customers/{id}Брише картон
GET/admin/invitesОтворените покани (никогаш искористени или ослободени, неистечени)
POST/admin/invitesname (задолжително), label (задолжително), duration (15–720), days_valid (1–365, стандардно 60), email, phone, send_emailСоздава покана; враќа url и email_sent
DELETE/admin/invites/{id}Брише покана
GET/admin/settingsЕфективните поставки
POST/admin/settingsJSON тело (видете Референца на поставките)Ги зачувува поставките

Секоја рута експлицитно ја декларира својата контрола на пристап; capability се проверува пред извршувањето на која било обработка.

Кодови на грешки

Грешките се стандардни WP_Error, со читлив код и HTTP статус.

КодHTTPЗначење
owag_spam403Замката за ботови е пополнета, или временскиот печат недостасува / е премногу свеж
owag_rate429Часовната квота е достигната за оваа адреса
owag_day_full429Премногу барања што чекаат потврда на овој датум
owag_busy503Заклучувањето за резервација не е добиено — обидете се повторно за миг
owag_slot_taken409Терминот во меѓувреме е зафатен
owag_overlap409Откриено преклопување (админ) — испратете повторно со force
owag_invite_invalid404Непознат токен на покана
owag_invite_used410Поканата е веќе искористена
owag_invite_expired410Поканата истекла
owag_too_late403Онлајн откажување надвор од рокот на најава
owag_bad_sig403Невалиден HMAC потпис
owag_not_found404Терминот или картонот не е пронајден
owag_name, owag_phone, owag_email, owag_consent400Невалидно поле или недостасува согласност
owag_bad_input, owag_bad_date400Невалиден датум, час или внес
owag_noop400Празно барање за ажурирање
owag_insert500Неуспешно запишување во базата

Куки за програмери

Во 1.3.1, OW Agenda не изложува ниту филтер ниту јавен action: нема API за проширување за документирање, и ништо од тоа што следува не треба да се погодува. Единствената употреблива кука е закажаниот настан owag_hourly_event, на кој можете да го закачите своето сопствено одржување:

add_action( 'owag_hourly_event', function () {
    // Votre traitement horaire, exécuté juste après celui du plugin.
} );

За сè останато, REST API е точката за интеграција: таа изложува точно она што го прави интерфејсот, ни повеќе ни помалку.


Референца на поставките

Сите поставки собираат во една единствена опција, owag_settings. Читање и запишување во PHP:

$s = owag_settings();          // réglages effectifs (défauts + enregistrés)
$duree = (int) $s['consult_duration'];

update_option( 'owag_settings', array_merge( owag_settings(), [
    'consult_duration' => 45,
    'buffer'           => 10,
] ) );

Стандардни вредности

[
    // Horaires : clé = 1 (lundi) … 7 (dimanche), valeur = liste de plages [début, fin]
    'hours' => [
        '1' => [ [ '09:00', '18:00' ] ],
        '2' => [ [ '09:00', '18:00' ] ],
        '3' => [ [ '09:00', '18:00' ] ],
        '4' => [ [ '09:00', '18:00' ] ],
        '5' => [ [ '09:00', '18:00' ] ],
        '6' => [],   // samedi fermé
        '7' => [],   // dimanche fermé
    ],
    'slot_step'           => 30,   // granularité des créneaux proposés (minutes)
    'consult_duration'    => 60,   // durée d'une consultation (minutes)
    'buffer'              => 0,    // battement autour de chaque rendez-vous (minutes)
    'min_notice_hours'    => 24,   // délai minimum avant réservation
    'max_advance_days'    => 60,   // horizon maximum de réservation
    'auto_confirm'        => 0,    // 0 = validation manuelle, 1 = confirmation automatique
    'email_verify'        => 1,    // double vérification par e-mail
    'cancel_notice_hours' => 24,   // préavis d'annulation en ligne par le client
    'notify_email'        => get_option( 'admin_email' ),
    'retention_months'    => 24,   // anonymisation des RDV passés (0 = jamais)
    'consult_label'       => 'Consultation',
]

Детали

ПоставкаТипГраници во интерфејсотЕфект
hoursниза1 или 2 интервали дневноДва интервали овозможуваат пладневна пауза. Интервал се прифаќа само ако почетокот и крајот се валидни и ако почеток < крај. Празен ден = затворено
slot_stepцел број5 → 120 минРастојание меѓу понудените часови. Колку е поситно, толку е подолг списокот
consult_durationцел број15 → 480 минВреметраење резервирано во агендата за веб консултација
bufferцел број0 → 120 минПауза применета од двете страни на кандидат-терминот
min_notice_hoursцел број0 → 168 чНишто не се нуди пред сега + овој рок
max_advance_daysцел број7 → 365 дХоризонт над кој повеќе не се нуди ниту еден термин
auto_confirm0 / 1Рачно одобрување или моментална потврда
email_verify0 / 1Двојна потврда по е-пошта (да се остави активна)
cancel_notice_hoursцел број0 → 168 чПо него, онлајн откажувањето се одбива со порака што поканува да се јави
notify_emailе-поштаПримач на административните известувања; служи и како ORGANIZER во ICS датотеките
retention_monthsцел број0 → 120 месециАнонимизација на завршените термини; 0 исклучува
consult_labelтекстНаслов прикажан на виџетот за резервација

Две неконфигурабилни константи вреди да се знаат, бидејќи тие го управуваат однесувањето на двојната потврда: терминот на непотврдено барање се задржува 45 минути, а барањето се брише по 48 часа.

Зачувувањето преку REST API ги прифаќа истите клучеви во JSON; целите броеви се сведуваат на минимум нула, адресата за известување се прифаќа само ако е валидна, а секој временски интервал се ревалидира на страна на серверот.


Зачувани податоци

Три табели, сите со префиксот на вашата инсталација. Датумите се DATETIME во локално време на сајтот, никогаш во UTC — токму тоа ги прави барањата читливи, а споредбите на времиња тривијални.

{prefix}_owag_appointments

КолонаТипБелешки
idBIGINTПримарен клуч
uidCHAR(32)Уникатен јавен токен (хексадецимален, криптографски генератор). Служи како клуч на линковите за потврда, откажување и административно дејство, и како ICS UID
kindVARCHAR(16)consult, seance, manual, block
service_labelVARCHAR(120)Прикажан назив
customer_name, customer_phone, customer_emailVARCHARКонтакт податоци
customer_msgTEXTПорака оставена од клиентот
admin_notesTEXTВнатрешни белешки, никогаш испратени до клиентот
start_dt, end_dtDATETIMEГраници на терминот (индексирани по start_dt)
statusVARCHAR(16)unverified, pending, confirmed, cancelled, done, noshow
sourceVARCHAR(16)web, invite, admin
invite_idBIGINTИзворната покана, ако ја има
reminder_sentTINYINTЗнаменце за потсетник (се враќа на 0 при преместување)
created_at, updated_atDATETIMEupdated_at го храни бројот на ICS ревизијата

{prefix}_owag_invites

id, token (CHAR(32), уникатен), контакт податоци на клиентот, service_label, duration_min, expires_at, appointment_id (се пополнува кога линкот е искористен, се враќа на NULL ако терминот се откаже), created_at.

{prefix}_owag_customers

id, name, phone, email, notes, created_at, updated_at. Индекс на name и email.

Само една опција ја носи конфигурацијата (owag_settings); останатите се технички: owag_admin_secret (HMAC тајна), owag_db_version, owag_pages_created, owag_page_booking, owag_page_admin.


Интернационализација

Целиот интерфејс може да се преведе: административните поставки, виџетот за резервација, страницата Агенда, самостојните страници, пораките на API и шаблоните за е-пошта. Изворниот јазик е англискиот; додатокот го декларира доменот за превод ow-agenda и патеката /languages.

Пакетот го испорачува шаблонот languages/ow-agenda.pot. Обезбеден е целосен француски превод, изработен од оригиналната формулација на интерфејсот.

Рачно инсталирање превод

Компајлирајте го .po и ставете го .mo во папката со преводи на WordPress:

msgfmt ow-agenda-fr_FR.po -o ow-agenda-fr_FR.mo
# puis : wp-content/languages/plugins/ow-agenda-fr_FR.mo

WordPress го вчитува каталогот при првиот преведен текст; не е потребен никаков рачен повик.

Две стапици за преведувачите

  • Текстовите наменети за JavaScript користат нумерирани ознаки (%1$s, %2$s) и никогаш гол %s: малиот форматер вграден во скриптите ги разбира само тие. Ненумерирана ознака би се прикажала буквално.
  • Два текста се PHP формати за датум, не реченици: l, F j, Y \a\t g:i a и l j F Y \a\t H:i. Преведете ги како формати (преуредување на токените, escape на буквалните букви со обратна коса црта). Францускиот користи l j F Y \à H\hi.

Деинсталација

Деактивирањето на додатокот прави само едно: ја брише часовната закажана задача. Вашите податоци, вашите поставки и вашите страници остануваат недопрени, и сè продолжува при повторното активирање.

Бришењето на додатокот од WordPress ја извршува целосната деинсталација:

  • бришење на трите табели (owag_appointments, owag_invites, owag_customers);
  • бришење на опциите owag_settings, owag_admin_secret, owag_db_version, owag_pages_created, owag_page_booking, owag_page_admin;
  • бришење на закажаната задача;
  • одземање на capability owag_manage од улогата administrator.

Двете страници создадени при активирањето не се бришат — тие можеби се преработени, ставени во мени, индексирани. На вас е да ги фрлите во корпата ако повеќе не ги сакате.

Бришењето на табелите е неповратно. Извезете ја вашата база претходно ако историјата на термините има вредност за вас.


Решавање проблеми

Ниту еден термин не се појавува на страницата за резервација

Поминете го списокот по редослед:

  1. Дали е внесено работното време за тој ден? Празен ден е затворен ден.
  2. Минималната најава (24 ч стандардно) нужно ги крие денес и дел од утре.
  3. Дали времетраењето собира во интервалот? Со интервал 09:00–12:00 и времетраење од 240 минути, не може да постои ниту еден термин.
  4. Хоризонтот: деновите над max_advance_days никогаш не се нудат.
  5. Паузата: широка пауза врз натоварен распоред може сè да затвори.
  6. Некоја блокада можеби го покрива денот. Отворете ја страницата Агенда на тој ден.
  7. Временската зона на сајтот (Settings → General): погрешно поставена зона ги поместува сите пресметки.

Е-поштите не пристигнуваат

Тоа речиси секогаш е испорачливоста, а не додатокот.

  1. Проверете дали терминот навистина постои на страницата Агенда: ако е таму, додатокот си ја завршил работата.
  2. Инсталирајте SMTP додаток (Fluent SMTP, WP Mail SMTP…). Функцијата mail() на PHP се одбива од огромното мнозинство приемни сервери.
  3. Проверете ги SPF, DKIM и DMARC за вашиот домен.
  4. Тестирајте ја адресата во OW Agenda → Административните известувања се праќаат на: невалидна адреса тивко ги блокира известувањата.

Потсетникот од претходниот ден не тргнал

Потсетникот зависи од WP-Cron, кој зависи од сообраќајот. На слабо посетен сајт, префрлете се на вистински системски cron (видете Потсетници и закажана задача). Проверете исто така дали терминот е навистина потврден, дали носи адреса за е-пошта и дали не е блокада.

Страницата Агенда прикажува «Пристапот е резервиран за тимот»

Најавениот корисник ја нема capability owag_manage. Таа им се дава на администраторите при активирањето; за другите улоги, видете Инсталација.

Копчето «Потврди» во е-поштата прикажува «Невалиден линк»

Три можни причини: линкот е скратен од клиентот за пошта (обидете се да ја копирате целата URL-адреса), терминот е веќе обработен (пораката го прецизира тоа), или HMAC тајната на сајтот е регенерирана. Во последниот случај, работете преку страницата Агенда: старите линкови повеќе не можат да се потврдат, по конструкција.

Два термина се наоѓаат на исто место

Од 1.3.0, тоа е невозможно преку онлајн резервацијата. Меѓутоа, администраторот може да форсира преклопување од страницата Агенда (додатокот го сигнализира тоа и бара потврда): прво проверете дали не станува збор за намерно форсирање. Проверете и дали вашата база навистина поддржува GET_LOCK() — егзотичен хостинг тогаш би враќал грешки 503 при резервацијата наместо дупликати.

Страниците «Закажи термин» и «Агенда» не се создадени

Тие се создаваат само еднаш, при првото активирање. Ако сте ги избришале, создадете две страници со shortcode-овите [ow_agenda] и [ow_agenda_admin], потоа насочете ги кон нив опциите owag_page_booking и owag_page_admin за да останат точни линковите во е-поштите:

update_option( 'owag_page_booking', 42 );  // ID de votre page de réservation
update_option( 'owag_page_admin', 43 );    // ID de votre page Agenda

Календарската датотека не е прикачена

Датотеката се запишува во привремениот директориум на серверот преку WordPress API за датотеки. Ако тој директориум не е достапен за запишување (квота, дозволи, заклучен хостинг), е-поштата тргнува без прилог наместо да падне. Проверете ги дозволите за запишување и просторот на дискот.

Времињата се поместени за еден час

Settings → General → Timezone. Изберете град (Europe/Skopje) наместо фиксен UTC поместок: само именувана зона го управува преминот на летно време.


ЧПП

Дали OW Agenda е навистина бесплатен? Да. GPL-2.0-or-later, може да се преземе како .zip од https://optionweb.dev/mk/addons/ow-agenda/. Без Pro верзија, без лиценцен клуч, без заклучена функција, без сметка за отворање, без квота на термини.

Дали онлајн термините ги земаат предвид термините земени по телефон? Да. Секој настан од агендата — веб резервација, термин внесен рачно, сеанса по покана, блокада — го прави својот временски период недостапен за онлајн резервација.

Мора ли клиентот да создаде сметка? Не. Без сметка, без лозинка. Сите дејства на клиентот (потврда, откажување) минуваат низ приватни линкови примени по е-пошта.

Може ли да се управуваат повеќе практичари или повеќе простории? Не. OW Agenda опишува само еден распоред. За два независни распореди, потребни се два сајта (или два сајта од multisite мрежа).

Дали се синхронизира со Google Calendar? Во смисла што е важна за клиентот: да. Секоја потврда носи стандардна календарска датотека што го додава — и го ажурира, и го брише — настанот во Google Calendar, Outlook или календарот на iPhone. Меѓутоа, додатокот не ги чита вашите надворешни календари: вашата лична недостапност се внесува како блокади.

Може ли да се наплати капар при резервацијата? Не, тоа е надвор од свесно поставениот опфат на додатокот.

Колку услуги може да се понудат онлајн? Само една, чиј назив и времетраење вие ги избирате. Останатите услуги одат преку поканите за сеанса, кои ви дозволуваат да го определите називот и времетраењето од случај до случај. Овој избор е намерен: мени со услуги на јавна страница ги умножува лошо насочените барања.

Дали работи на multisite? Да. Секој сајт од мрежата има свои табели, свои поставки и своја агенда.

Дали додатокот го забавува сајтот? Не. Никаква скрипта не се вчитува надвор од двете засегнати страници; виџетот за резервација тежи под 12 KB, без jQuery и без framework. Периодичната работа собира во една часовна задача.

Што се случува ако клиент никогаш не ја потврди својата е-пошта? Неговиот термин станува достапен по 45 минути, а неговото барање се брише по 48 часа. Вие никогаш не слушате за тоа.

Каде да се најде поддршка?


Changelog

1.3.1

Усогласеност

  • Самостојните страници за дејство, за потврда и за откажување повеќе не го печатат својот CSS ниту својот JavaScript инлајн: и двете сега се регистрирани датотеки што се служат преку WordPress enqueue API. Двете променливи бои на копчињата минуваат низ прилагодени CSS својства, а скриптата се конфигурира преку wp_localize_script().
  • Каталозите со преводи повеќе не се вградени: се испорачува само languages/ow-agenda.pot, а францускиот се дистрибуира преку јазичните пакети на WordPress.org што се хранат од translate.wordpress.org.
  • Минималната верзија на WordPress се враќа на 6.3: ништо во пакетот повеќе не зависи од откривањето на вградените преводи воведено во 6.7.

REST API

  • Секоја административна рута сега го декларира својот permission_callback експлицитно наместо да го дели преку array_merge(). Контролата на capability и претходно се применуваше; сега е видлива за статичка анализа.

Без промена во однесувањето.

1.3.0

Интернационализација

  • Додатокот е целосно преводлив (домен ow-agenda, англискиот како изворен јазик): поставки, јавни страници, пораки на API, е-пошти и JavaScript интерфејс.
  • Испорачан шаблон languages/ow-agenda.pot и целосен француски превод.

Безбедност

  • Јавните идентификатори на термините и токените на поканите се генерираат со криптографски генератор (random_bytes()). Тие токени се единствената автентикација на линковите за откажување, потврда и покана.
  • Замката за ботови и временскиот печат станаа задолжителни: нивното изоставување ги исклучуваше анти-спам контролите.
  • Часовната квота се агрегира по /64 префикс кај IPv6, а дневна горна граница ги ограничува непотврдените барања — посетител повеќе не може да ги задржи сите термини на еден ден.
  • Квотата се одбива дури по валидацијата на формуларот: печатна грешка повеќе не блокира легитимен посетител цел час.

Сигурност

  • Истовремените резервации на ист термин се серијализираат со именувано MySQL заклучување. Претходната трансакција не поставуваше никакво заклучување на редот: двајца посетители можеа да го резервираат истото време.
  • Потсетникот од претходниот ден користи подвижен прозорец од 12 до 36 ч и го надоместува своето задоцнување; секое испраќање е атомски резервирано, две извршувања на cron повеќе не можат двапати да го испратат истиот потсетник.
  • Часовната задача се презакажува автоматски ако исчезне: потсетниците, чистењето и анонимизацијата повеќе не можат да запрат тивко.
  • Преместувањето на термин го ажурира календарот на клиентот (SEQUENCE, METHOD:REQUEST, организатор и учесник); откажувањето испраќа METHOD:CANCEL што го брише настанот.
  • Датумите во виџетот се пресметуваат во локално време, а не во UTC: нема повеќе изгубен ден за посетителите источно од UTC.
  • Откажувањето на термин произлезен од покана ја ослободува поканата, која повторно станува употреблива.
  • Откажаните термини и истечените непотврдени барања повеќе не се враќаат во агендата: помалку лични податоци во одговорите, нема повеќе фантомски термини.

1.2.1

  • Усогласеност со Plugin Check: escape на излезите, чистење на влезовите, nonce на поставките, readme.
  • Деинсталацијата ја брише и табелата на именикот на клиенти и HMAC тајната.

1.2.0

  • HTML е-пошти (распоред во картичка, акцентна боја на сајтот) за сите известувања.
  • Копчиња Потврди / Одбиј во административната е-пошта (линкови потпишани со HMAC).
  • Именик на клиенти: пребарување, создавање, уредување, бришење, кратенки кон нов термин и кон покана.

1.1.0

  • Двојна потврда по е-пошта против ботовите (терминот се задржува 45 минути, чистење по 48 часа).

1.0.0

  • Првична верзија: онлајн резервација, mobile-first административна агенда, покани за сеанса, е-пошти со календарска датотека и потсетник од претходниот ден.

Создадено од OptionWeb — Julien Daniel, Châtelet, Белгија.