Appearance
Waiting List Notifications
Flow ID: SY-13 | Module(s): job, eshop, Product domain | Complexity: Low Last Updated: 2026-04-04
Business Overview
When customers subscribe to out-of-stock products via the storefront waiting list, the system stores their email and product reference. A daily cron job checks whether subscribed products have returned to stock, then sends grouped email notifications to each customer listing all their now-available products. This converts interest signals into purchase opportunities without manual intervention.
What the job does:
- Scans the
shop_waiting_listtable for unsent entries where the product is active and in stock - Groups available products by customer email to send one consolidated email per customer
- Sends the notification email using the
waitingListSuccesstemplate - Marks all processed entries as sent with a timestamp
Business value: Recovers lost sales from out-of-stock situations by automatically re-engaging interested customers the moment inventory is restored.
Architecture
AdvSendEmailForWaitingList (JobCommand)
|
+--> waiting_list_model::getRecordsToSendEmails($lang)
| joins: shop_waiting_list + shop_product + product_codes + shop_product_mui + shop_vendor + shop_vendor_mui
| filters: waiting_status=0, product active=1, stock>0 OR negative_stock=1
|
+--> Group records by customer email
|
+--> adv_mailer::sendEmailForWaitingList($email, $data, $lang)
| template: waitingListSuccess
| subject: registry EMAIL_SUBJECTS.WAITING_LIST
|
+--> waiting_list_model::markAsSent($ids)
sets waiting_status=1, email_sent_date=nowJob Classes
| Class | File | Purpose |
|---|---|---|
AdvSendEmailForWaitingList | ecommercen/job/libraries/AdvSendEmailForWaitingList.php | Base job implementation |
SendEmailForWaitingList | application/modules/job/libraries/SendEmailForWaitingList.php | Client-overridable subclass |
Supporting Classes
| Class | File | Role |
|---|---|---|
Adv_waiting_list_model | ecommercen/eshop/models/Adv_waiting_list_model.php | Legacy model with query logic |
Waiting_list_model | application/modules/eshop/models/Waiting_list_model.php | Client-overridable model |
Adv_mailer | application/models/Adv_mailer.php | Email dispatch |
Entity | src/Domains/Product/WaitingList/Repository/Entity.php | Modern domain entity |
Repository | src/Domains/Product/WaitingList/Repository/Repository.php | Modern domain repository |
WriteRepository | src/Domains/Product/WaitingList/Repository/WriteRepository.php | Write operations |
Code Flow
1. Job Initialization
The job loads the waiting list model, mailer, and refreshes the registry to get live configuration:
constructor:
load waiting_list_model
load adv_mailer
registry->live() (refresh from DB for latest config)2. Query Eligible Records
getRecordsToSendEmails($lang) builds a multi-table join:
- Base table:
shop_waiting_listwherewaiting_status = 0(not yet notified) - Product check: joins
shop_productwhereactive = 1 - Stock check: joins
product_codeswherestock > 0OR product allowsnegative_stock = 1 - Language filter: matches the
langcolumn on the waiting list entry, product MUI, and vendor MUI - Data enrichment: selects product name, slug, vendor slug, and admin thumbnail image
- Grouping:
GROUP BY shop_product.idto deduplicate product codes per product - Ordering: by email ASC, then creation_date ASC
3. Group by Customer
The job iterates results and groups them by email address so each customer receives a single email listing all their available products.
4. Send Notifications
For each customer email, calls adv_mailer->sendEmailForWaitingList():
- Builds a customer data object with
mail,lang, andid=null(no customer account required) - Uses the
waitingListSuccessemail template - Subject line from registry:
EMAIL_SUBJECTS.WAITING_LIST - SMTP profile:
EMAIL_SHOP_MAILER
5. Mark as Sent
After all emails are dispatched, calls markAsSent($ids) with all processed record IDs:
- Sets
waiting_status = 1 - Sets
email_sent_dateto current datetime
Data Model
Primary Table: shop_waiting_list
| Column | Type | Role |
|---|---|---|
id | int | PK, auto-increment |
email | varchar | Customer email address |
lang | varchar | Language code (e.g., el, en) |
product_id | int | FK to shop_product.id |
creation_date | datetime | When the subscription was created |
waiting_status | int | 0 = waiting, 1 = notified, 2 = deleted/canceled |
email_sent_date | datetime/null | When notification was sent |
Related Tables
| Table | Relationship | Purpose |
|---|---|---|
shop_product | product_id -> id | Product active status and negative_stock flag |
product_codes | product_id -> product_id | Stock quantity check |
shop_product_mui | product_id -> product_id | Product name and slug (language-specific) |
shop_vendor | vendor_id -> id (via product) | Vendor lookup |
shop_vendor_mui | vendor_id -> vendor_id | Vendor slug (language-specific) |
Waiting Status Values
| Value | Meaning |
|---|---|
| 0 | Waiting (not yet notified) |
| 1 | Notified (email sent) |
| 2 | Deleted/canceled by admin |
Configuration
Job Scheduling (application/config/jobs.php)
php
['command' => 'SendEmailForWaitingList', 'schedule' => '0 11 * * *', 'graceTime' => 300, 'retryTimes' => 3, 'options' => ['lang' => 'el']],Default schedule: daily at 11:00. The lang option scopes notifications to a specific language. For multi-language sites, multiple job entries may be configured with different lang values.
Job Options
| Option | Type | Required | Description |
|---|---|---|---|
lang | string | No | Language abbreviation to filter notifications. Defaults to site's language_abbr config |
Registry Settings
| Group | Key | Purpose |
|---|---|---|
EMAIL_SUBJECTS | WAITING_LIST | Email subject line for waiting list notifications |
EMAIL_SHOP_MAILER | (group) | SMTP configuration for outbound shop emails |
Email Templates
| Template key | Description |
|---|---|
waitingListSuccess | Email body listing products that are back in stock, with links |
Client Extension Points
Override the job class: Create
SendEmailForWaitingListinapplication/modules/job/libraries/extendingAdvSendEmailForWaitingList. OverrideexecuteCommand()to add custom logic (e.g., additional filters, custom grouping).Override the model: Create
Waiting_list_modelinapplication/modules/eshop/models/extendingAdv_waiting_list_model. OverridegetRecordsToSendEmails()to change the stock-check query (e.g., add minimum stock threshold).Override the mailer: Extend
Adv_mailerinapplication/models/to customize the email content, add CC recipients, or change the template.Override email template: Place a custom
waitingListSuccessview file inapplication/views/to change the email layout.Multi-language scheduling: Add multiple job entries in
jobs.phpwith differentlangoptions to send notifications per language at different times.
Business Rules
| Rule | Description |
|---|---|
| Stock-or-negative | Products qualify when product_codes.stock > 0 OR shop_product.negative_stock = 1 |
| Active products only | Only active products (active = 1) trigger notifications |
| Language scoping | Notifications are filtered by language, matching the waiting list entry's lang field |
| One notification per entry | Each shop_waiting_list row is sent exactly once; waiting_status flag prevents reprocessing |
| Grouped per customer | Multiple products for the same email are consolidated into a single email |
| No account required | Waiting list uses email-only identification; no customer account is needed |
| Duplicate prevention | The isInWaitingList() check prevents duplicate subscriptions (same email + product + status=0) |
Related Flows
- CF-15 Waiting List -- storefront subscription UI and REST API
- SY-01 Cron Job Framework -- job scheduling and execution
- SY-24 Email Dispatch System --
Adv_mailerinternals, SMTP routing, and template rendering used to send back-in-stock notifications - AD-13 Settings -- registry configuration for email subjects