Ga naar inhoud

Notificaties & e-mails

Vrijwel alle uitgaande communicatie van de webshop verloopt via e-mail. Er is geen push- of SMS-notificatiesysteem. De e-mails vallen uiteen in twee groepen: transactionele mails (rechtstreeks getriggerd door een handeling, zoals een orderbevestiging) en geautomatiseerde mails (door een cron, zoals de verjaardagsmails). De inhoud komt uit een gelaagd templatesysteem dat de templates in de database bewaart.

E-mailtemplatesysteem

Het templatesysteem staat onder src/Atraxion/Module/EmailTemplate/. Templates en layouts worden als Doctrine-entiteiten in de database opgeslagen (geen bestanden op schijf):

  • Model/Template.php — een template met een handle, taal, een layout-FK en content-FK;
  • Model/Layout.php — een herbruikbare omhullende layout (teaser, content, css);
  • Model/Content.php — het onderwerp + de body-HTML, 1-op-1 aan een template;
  • Model/AbstractTemplate.php — de basisklasse.

De gelaagdheid werkt zo: een template levert de eigenlijke inhoud, een layout omhult die met een vaste opmaak. Bij het renderen (Renderer/TwigEmailTemplateRenderer.php) worden de template-HTML en de layout-HTML uit de DB-strings in Twig's ArrayLoader geladen (geen schijfbestanden), waarna de template met de context wordt gerenderd en in de layout wordt gewikkeld. Eenvoudige {variabele}-plaatshouders worden ook via str_replace_vars ingevuld; het onderwerp komt uit Content::getSubject().

EmailTemplateService (Service/EmailTemplateService.php) zoekt de template op uitsluitend handle via findOneByHandle() — zonder taalparameter (EmailTemplateService.php:83). De taalafhankelijke opzoeking (findOneByHandleLanguage) zit uitsluitend in de hulpfunctie \Atraxion\mailTemplate(handle, ontvangers, variabelen, taal) (src/namespaced_functions.php:381), die door de hele codebase wordt gebruikt en vervolgens EmailTemplateService::render() aanroept met de gevonden template.

Verzenden

De feitelijke verzending gaat via SendMail (src/Atraxion/Mail/SendMail.php), een PHPMailer-wrapper met steun voor to/cc/bcc, bijlagen en tags. SendMailFactory (src/Atraxion/Mail/SendMailFactory.php) kiest het transport per domein: Postmark-SMTP voor atraxion.com, tyrecloud.be en wheelcloud.be; een lokale Mailpit in dev (docker-compose.yml:47, image axllent/mailpit). In non-prod stuurt SendMail alle mail om naar MAIL_SELF, zodat er geen echte mails vertrekken.

Transactionele mails

Deze worden rechtstreeks vanuit een handeling getriggerd:

Template-handle Mail Getriggerd in
orderconfirmation Orderbevestiging naar de klant OrderService ← checkout / betaalcallback
orderconfirmation-internal Orderkennisgeving naar tyres@atraxion.com idem
passwordforgotten Wachtwoord-resetlink RecoverPasswordService::recoverPassword()
minishop_neworder Nieuwe-orderkennisgeving → mini-shop-eigenaar ArticleDetailController::processMiniShopOrder()
minishop_orderconfirmation Orderbevestiging → bezoeker/klant van de mini-shop-eigenaar idem
minishop-licence-expired Waarschuwing aflopende mini-shop-licentie MiniShopLicenseExpirationNotifier (cron)
sepa-email SEPA-mandaat (PDF-bijlage) SepaService
business-owner-x-coins X-Coins-onboarding LoyaltyProgramController
login-changed-notification Login/e-mail gewijzigd door Odoo-sync Odoo/Service/SynchronisePartners.php

Daarnaast bestaan er kennisgevingen rond klantregistratie (goedgekeurd/geweigerd via AdminBorderPatrolController, aangemaakt via AdminUserController) en een garantieformulier-mail (GuaranteeMail).

Orderbevestigingen in de orderflow

De orderbevestiging wordt op verschillende plekken getriggerd, afhankelijk van het betaalpad:

  • Reguliere checkout: CartController::doFinishOrder() (rond regel 1702) verstuurt zowel de klant- als de interne mail via OrderService::sendOrderMail();
  • Gesplitste checkout (eerste deelorder): CartController::splitCartByProductCategories() (rond regel 1180) verstuurt ook beide mails via dezelfde methode;
  • Gesplitste checkout (restorder): alleen de interne mail;
  • Betaalcallback (Pay.nl): CheckPaymentStatus::checkPaymentStatus() (src/Atraxion/Exchange/Service/CheckPaymentStatus.php:113) verstuurt na een geslaagde betaling beide mails — zie Betalingen;
  • EDI- en distributeur-orders: alleen de interne mail.

Mini-shop-orders

Een bestelling op een mini-shop wordt per e-mail afgehandeld (zie Mini-shops). In ArticleDetailController::processMiniShopOrder() (_core/controller/classes/atx/articles/ArticleDetailController.php rond regel 757) worden twee mails verstuurd: één naar de mini-shop-eigenaar (template minishop_neworder, naar channel->getSendOrdersTo(), BCC naar logs@atraxion.com) en één naar de bezoeker (template minishop_orderconfirmation, met de bedrijfsnaam van de eigenaar als afzender).

Geautomatiseerde mails: verjaardagsmails

De verjaardagsmails draaien via src/Atraxion/Module/BirthdayEmailQueue/. Het systeem werkt met een wachtrij:

  • Model/BirthdayEmail.php — een wachtrij-record (gebruiker, klant, type, geplande datum, status pending/sent/failed);
  • Model/BirthdayEmailTemplate.php — de inhoud per type/taal, gekoppeld aan een EmailTemplate-Content;
  • Service/BirthdayEmailService.phpgenerateBirthdayQueue() en sendPendingBirthdayEmails().

Er zijn twee actieve types: TYPE_WITH_REVENUE (verstuurd vanaf jan@atraxion.com) en TYPE_WITHOUT_REVENUE (vanaf info@atraxion.com).

De cron draait per uur via ./cli.php (src/Atraxion/Module/BirthdayEmailQueue/Command/SendBirthdayEmailsCommand.php:14, commando app:birthday:send-emails):

  • op :00 — de wachtrij genereren (app:birthday:send-emails --generate-queue);
  • op :05 — de openstaande mails versturen (app:birthday:send-emails).

De templates zelf worden eenmalig aangemaakt via app:birthday:create-templates (Command/CreateBirthdayEmailTemplatesCommand.php).

Algemene queue (atx_queue)

Let op: e-mails lopen niet via de generieke job-queue. De tabel atx_queue (_core/model/dbclasses/atx/job/QueueDAO.php, _core/model/classes/atx/job/Queue.php) is een algemene job-wachtrij (types general, app, R6, R6_async) voor onder meer ERP-sync en platformorders. E-mailverzending gebeurt synchroon binnen het request of rechtstreeks door een CLI-commando. Zie Crons & queue voor de verwerking van die queue.

Zie ook