Skip to content

Delivery Delay Notifications

Flow ID: SY-15 | Module(s): job, eshop | Complexity: Medium Last Updated: 2026-04-04

Business Overview

When orders experience shipping delays, the platform proactively notifies customers via email before they contact support. The system identifies orders that have been pending shipment for too long (2+ or 3+ days depending on configuration) and sends an apology/information email. This builds customer trust by acknowledging delays transparently.

Two operating modes:

  1. Standard delay (withWarningDelay=false): Targets orders 2+ days old without a delivery warning flag
  2. Extended delay (withWarningDelay=true): Targets orders 3+ days old that have the delivery warning flag set

The delivery_warning flag on orders allows merchants to manually flag orders expected to have longer processing times, giving those orders an extra day before the automated notification fires.


Architecture

AdvSendEmailForDeliveryDelay (JobCommand)
  |
  +--> order_model::sendMailForDelayOrderToCustomers($withWarningDelay)
         |
         +--> Query eligible orders:
         |      shop_order JOIN shop_customer
         |      status NOT IN (CANCELED, PENDING)
         |      store_id IS NULL
         |      delivery_warning = $withWarningDelay
         |      delivery_warning_msg_status = false
         |      invoised_date_time IS NULL
         |      canceled_date IS NULL
         |      entry_datetime >= 2019-01-01
         |      entry_datetime <= (now - 2 days) or (now - 3 days)
         |
         +--> For each order:
                adv_mailer::sendCustomerInformDelay($order)
                  |
                  +--> order_model::setDeliveryWarningMsgStatus(1, $orderSerial)
                  +--> send email via orderInformDelay template

Job Classes

ClassFilePurpose
AdvSendEmailForDeliveryDelayecommercen/job/libraries/AdvSendEmailForDeliveryDelay.phpBase job implementation
SendEmailForDeliveryDelayapplication/modules/job/libraries/SendEmailForDeliveryDelay.phpClient-overridable subclass

Supporting Classes

ClassFileRole
Adv_order_modelecommercen/eshop/models/Adv_order_model.phpOrder query and status update logic
Adv_mailerapplication/models/Adv_mailer.phpEmail dispatch with delay template

Code Flow

1. Job Initialization

The job is lightweight -- no constructor, just inline model loading in executeCommand():

executeCommand:
  parse withWarningDelay option (bool, defaults to false)
  load eshop/order_model
  load adv_mailer
  call order_model->sendMailForDelayOrderToCustomers($withWarningDelay)

2. Calculate Cutoff Date

In sendMailForDelayOrderToCustomers():

date = now - 2 days
if withWarningDelay:
    date = now - 3 days (additional -1 day)
toDate = date formatted as Y-m-d

3. Query Eligible Orders

The method builds a query with these conditions:

ConditionPurpose
status NOT IN ('CANCELED', 'PENDING')Only process active, accepted orders
store_id IS NULLExclude store-pickup orders (those have different logistics)
delivery_warning = $withWarningDelayMatch the delay tier (standard vs. flagged)
delivery_warning_msg_status = falseOnly orders not yet notified
invoised_date_time IS NULLExclude already-invoiced orders (they shipped)
canceled_date IS NULLExclude canceled orders
entry_datetime >= '2019-01-01'Safety floor to exclude very old legacy data
entry_datetime <= $toDateOnly orders older than the threshold

Results are ordered by entry_datetime ASC (oldest first) and include customer email and language from shop_customer.

4. Send Notifications

For each eligible order, calls adv_mailer->sendCustomerInformDelay($order):

  1. Validates that the order has order_serial and mail properties
  2. Marks processed first: calls order_model->setDeliveryWarningMsgStatus(1, $orderSerial) before sending -- this prevents reprocessing even if the email fails
  3. Sends email using:
    • Template: orderInformDelay
    • Data: the full order object
    • Subject: EMAIL_SUBJECTS.CUSTOMER_INFORM_DELAY (supports %s for order serial)
    • SMTP profile: EMAIL_SHOP_MAILER

Data Model

Primary Table: shop_order

ColumnTypeRole
idintPK
order_serialvarcharHuman-readable order number
statusvarcharOrder status
entry_datetimedatetimeWhen the order was placed
delivery_warningbooleanManually flagged for expected delay (gives extra day)
delivery_warning_msg_statusbooleanWhether delay notification has been sent
store_idint/nullNULL = courier delivery; non-null = store pickup
invoised_date_timedatetime/nullWhen invoiced (NULL = not yet shipped)
canceled_datedatetime/nullWhen canceled (NULL = not canceled)
customer_idintFK to shop_customer
TableRelationshipPurpose
shop_customercustomer_id -> idCustomer email (mail) and language (lang)

Configuration

Job Scheduling (application/config/jobs.php)

Two entries are typically configured -- one for each delay tier:

php
// Standard delay (2+ days):
// ['command' => 'SendEmailForDeliveryDelay', 'schedule' => '0 10 * * *', 'graceTime' => 300, 'retryTimes' => 3],

// Extended delay (3+ days, for flagged orders):
// ['command' => 'SendEmailForDeliveryDelay', 'schedule' => '0 10 * * *', 'graceTime' => 300, 'retryTimes' => 3, 'options' => ['withWarningDelay' => true]],

Commented out by default (client opt-in).

Job Options

OptionTypeRequiredDescription
withWarningDelayboolNoWhen true, targets orders 3+ days old with delivery_warning=true. Defaults to false (2+ days, no warning flag)

Registry Settings

GroupKeyPurpose
EMAIL_SUBJECTSCUSTOMER_INFORM_DELAYEmail subject template (supports %s for order serial)
EMAIL_SHOP_MAILER(group)SMTP configuration for outbound shop emails

Email Templates

Template keyDescription
orderInformDelayApology/information email about the shipping delay

Client Extension Points

  1. Override the job class: Create SendEmailForDeliveryDelay in application/modules/job/libraries/ extending AdvSendEmailForDeliveryDelay. Override executeCommand() to change delay thresholds or add custom filtering.

  2. Override the order model: Override sendMailForDelayOrderToCustomers() in Order_model to change the query criteria (e.g., exclude specific payment methods, adjust the date threshold, add status filters).

  3. Override the mailer: Extend Adv_mailer in application/models/ to customize sendCustomerInformDelay() behavior (e.g., add admin CC, change template).

  4. Override email template: Place a custom orderInformDelay view file in application/views/ to change the email content.

  5. Dual-tier scheduling: Configure both standard and extended delay jobs with different schedules for granular control.


Business Rules

RuleDescription
Two delay tiersStandard (2+ days) and extended (3+ days with delivery_warning flag)
One notification per orderdelivery_warning_msg_status flag prevents duplicate notifications
Courier orders onlystore_id IS NULL excludes store-pickup orders from delay notifications
Active orders onlyExcludes CANCELED and PENDING statuses, as well as already-invoiced and canceled orders
Mark-before-sendThe status flag is set before the email is sent, preventing reprocessing on partial failures
Legacy data floorOrders before 2019-01-01 are excluded via a hardcoded date floor
Per-client opt-inBoth job variants are commented out by default