etechflow / module-backorder-eta-display
etechflow/module-backorder-eta-display
Shows expected restock or shipping ETA for backorder items on product pages, in cart, at checkout, and in order confirmation emails. Reduces uncertainty for customers and cuts merchant support tickets.
Backorder ETA Display for Magento 2
Show customers when their backordered items will actually ship.
Turns "this item is on backorder" from a customer-service nightmare into a clear, dated promise. Renders on product page, cart, checkout, and order confirmation email.
What's new
The full version history lives in CHANGELOG.md. Highlights:
- v1.1.0 — Module Status banner at the top of admin (shows whether the module is actually active), inline tooltips on every field,
backorder_etaattribute now visible + filterable in the product grid, expanded i18n CSV, stale install guides removed. - v1.0.2 — Production Environment toggle for non-standard dev domains.
What it does
Magento's default backorder message tells customers nothing — just "available for backorder", no date. Customers either don't notice (then complain when packages are late) or they cancel rather than wait an unknown amount of time. This module:
- Adds a per-product
backorder_etatext attribute ("Ships in 5-7 business days", "Available Dec 15", "Pre-order — January 5") - Falls back to a configurable store-wide default ETA if a product has no specific value
- Renders the ETA in four places: product detail page badge, cart summary, checkout summary, order confirmation email
- Three colour styles to match your store branding: warning (amber), info (blue), neutral (grey)
- Fully Hyvä compatible with dark-mode support
Requirements
| Magento | Open Source 2.4.4+ OR Adobe Commerce 2.4.4+ |
| PHP | 8.1, 8.2, 8.3, or 8.4 |
| Compatible themes | Luma (default) + Hyvä + Hyvä Checkout |
Installation
Option A — Composer (recommended)
composer require etechflow/module-backorder-eta-display:^1.0
bin/magento module:enable ETechFlow_BackorderEtaDisplay
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
Option B — Manual (from zip)
-
Unzip
etechflow-module-backorder-eta-display-1.0.1.zipinto:<magento-root>/app/code/ETechFlow/BackorderEtaDisplay/Directory MUST be
ETechFlow(capital E, T, F) — case-sensitive on Linux. -
Enable and set up:
bin/magento module:enable ETechFlow_BackorderEtaDisplay bin/magento setup:upgrade bin/magento setup:di:compile bin/magento cache:flush
After install — quick start
1. License key
Admin → Stores → Configuration → eTechFlow → Backorder ETA Display → License
Paste the key from your purchase email. Skip this on dev/staging — see USER_GUIDE for the auto-bypass patterns.
2. Enable + set defaults
Same admin page:
- General → Enabled = Yes
- General → Default ETA = "Ships in 5-7 business days" (or whatever your default backorder window is)
- General → ETA Label Prefix = "Estimated delivery: " (or leave blank if you prefer the raw ETA)
- Display → Badge Style = warning / info / neutral (pick the colour that matches your branding)
- Display → Show on PDP / Cart / Checkout / Order Email = all Yes (or pick the ones you want)
Save Config.
3. (Optional) Customise per product
Edit any product → eTechFlow Shipping → Backorder ETA field. Type whatever ETA you want for that specific product (e.g. "Available December 15" for a pre-order). Save.
Products with no custom ETA fall back to your store-wide default.
What customers will see
| Where | Renders as |
|---|---|
| Product detail page (PDP) | Badge below price with truck icon + ETA text |
| Cart page | Summary block at top listing each backorder item + its ETA |
| Checkout shipping step | Same summary block |
| Order confirmation email | Styled HTML table appended below items list |
The module only renders when a product is genuinely on backorder AND has a non-empty ETA. In-stock products show nothing.
Documentation
| File | Read when |
|---|---|
README.md (this file) |
First — overview + install |
docs/installation_guide.html |
Detailed install walkthrough with screenshots |
docs/USER_GUIDE.md |
Configuration + usage + troubleshooting |
CHANGELOG.md |
What changed in each version |
LICENSE.txt |
Licence terms |
Support
- Email: [email protected] — typically responds within one business day
- Website: https://etechflow.com
License
Proprietary — see LICENSE.txt. Licensed per Magento installation. Unlimited dev/staging environments included.
Changelog — Backorder ETA Display
All notable changes to this module. Adheres to Semantic Versioning.
[1.2.3] — 2026-05-30 — Optional next-day-eligibility suppression on PDP
Resolves a real-world contradiction merchants hit when running both
this module and etechflow/module-next-day-eligibility: a product can
show both the green "Next Day Eligible" badge AND the amber "Ships in
5-7 business days" badge on the same PDP, confusing customers with
contradictory delivery promises. Surfaced live on Keystation.
Added
- New admin field under Stores → Configuration → eTechFlow →
Backorder ETA Display → Display Locations:
"Hide PDP Badge When Product is Next Day Eligible" (Yes/No,
default No).
When set to Yes AND the product'snext_day_eligibleattribute
equals1,EtaBadge::isVisible()returns false on the PDP — the
Next-Day-Eligible badge wins the messaging slot, the slow ETA is
suppressed. Only product page is affected; cart/checkout/email still
fire on every backorder line regardless. - Soft-detected NDE integration — no hard module dependency, no FQCN
reference. The check reads the product attribute viagetData(). If
NDE isn't installed, the attribute doesn't exist, the check
no-ops, BED remains fully standalone-capable. Safe to set Yes even on
installs that may uninstall NDE later. Setup/Patch/Data/V123ReleaseMarker.php— continues the always-a-
patch discipline. Depends onV122ReleaseMarkerso patches run in
version order.
Changed
Model/Config.php: newXML_PATH_HIDE_IF_NEXT_DAYconstant,
NEXT_DAY_ELIGIBLE_ATTRpublic const,isHideIfNextDayEligible()
getter.Block/Product/EtaBadge.php::isVisible(): extra check between the
backorder gate and the display-text gate. Five new LOC.Console/Command/VerifyCommand.php: version literal 1.2.2 → 1.2.3.
Not changed
- No schema changes, no DI changes, no API breakage. Drop-in
upgrade from 1.2.2. - Default behaviour is identical to 1.2.2 — the new toggle
defaults to No. Existing installs see no change unless they opt in.
Migration
composer require etechflow/module-backorder-eta-display:^1.2.3
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
To opt in: Stores → Configuration → eTechFlow → Backorder ETA Display →
Display Locations → Hide PDP Badge When Product is Next Day Eligible
→ Yes → Save → flush cache.
When you should turn it on
You should turn it on if all three are true:
- You have
etechflow/module-next-day-eligibilityinstalled - Some of your products are flagged Next-Day-Eligible AND would also be
on backorder (e.g. drop-ship products where NDE auto-enables backorders) - You'd rather customers see "Next Day Eligible" alone than both
badges fighting each other
If you don't have NDE installed, leave it at No — the toggle does
nothing in that case anyway.
[1.2.2] — 2026-05-25 — Always-a-patch discipline + clarify rename patch docblock
Two additive changes, no behaviour change, no schema/API change. Drop-in
upgrade from 1.2.1.
Added
-
Setup/Patch/Data/V122ReleaseMarker.php— no-op release marker.
Establishes the discipline that every BED release ships at least one
data patch, even if it has nothing to do. This guarantees
setup:upgradealways has SOMETHING to register inpatch_list,
surfacing FS / permissions / DI errors during the patch phase (which
retries cleanly) instead of at the end of the upgrade (which doesn't).Same pattern shipped in NDE v1.7.1 after the v1.7.0 Keystation deploy
incident — a version bump with zero patches risks the same site-down
condition wheresetup:upgradeaborts post-patch,data_version
never advances, and DbStatusValidator returns 500 on every request
until rollback.Future releases copy this template (
V123ReleaseMarker, etc).
Changed
-
RenameBackorderEtaToRestockDatedocblock rewritten to make
clear that this patch ONLY relabels the attribute (the
frontend_labelandnote), NOT the attribute_code. The class name
is misleading —attribute_code = 'backorder_eta'is deliberately
permanent because renaming it would orphan every saved value and
break custom themes / integrations / SQL queries. Same reason
Magento core kept themanufacturercode unchanged when its label
was relabelled to "Brand".Class name kept as-is (renaming would either re-fire the patch on
installs that already ran it or leave danglingpatch_listrows).
Docblock now warns future readers.
Files added
Setup/Patch/Data/V122ReleaseMarker.php
Files modified
Setup/Patch/Data/RenameBackorderEtaToRestockDate.php (docblock only)
etc/module.xml (1.2.1 → 1.2.2)
composer.json (1.2.1 → 1.2.2)
Upgrade
composer require etechflow/module-backorder-eta-display:^1.2.2
bin/magento setup:upgrade
# Watch for warnings — if any appear, do NOT cache:flush yet.
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:flush
Pre-flight check after upgrade:
SELECT module, schema_version, data_version FROM setup_module
WHERE module='ETechFlow_BackorderEtaDisplay';
Both columns should read 1.2.2. If data_version is stale, re-run
setup:upgrade before flushing cache.
[1.2.1] — 2026-05-18 — Friendly-language pass
Customer-facing copy now leads with shopper-friendly phrasing instead of trade jargon. "Backorder ETA" was the right phrase for the original spec but "restock date" / "available date" / "temporarily sold out" lands better with actual shoppers. Drop-in upgrade — no behaviour change, just labels and copy.
Changed
- Product attribute label:
Backorder ETA→Restock Date(the field merchants fill in on every product edit page). Renamed via a new idempotentRenameBackorderEtaToRestockDatedata patch — existing installs automatically pick up the new label on nextsetup:upgrade. The DB columnbackorder_etais unchanged (renaming would break every install's data). - Admin config labels in
Stores → Configuration → eTechFlow → Backorder ETA Display:Default ETA Text→Default Restock DateLabel Prefix (Default ETA Only)→Label Prefix (default text only)- Every admin help-note rewritten to say "sold-out / backorder products" instead of just "backorder products"
- Marketing README (
marketing/BackorderEtaDisplay/README.md) rewritten end-to-end:- Tagline now leads with "Turn 'out of stock' into 'ships in 2 weeks'"
- Top of file states the module's customer-facing positioning is "Restock Date Display" even though the internal name stays as-is
- Adobe Marketplace listing title proposal updated to "Restock Date Display (for backorder / pre-order items)"
backorderkept in tags + secondary mentions for SEO discoverability (merchants do search for that term)
- FAQ snippet updated so "What if the product isn't on backorder?" becomes "What if the product is in stock?"
Unchanged (deliberately)
- Storefront templates — the customer-visible badge and summary blocks already used shopper-friendly phrasing (the heading reads "Estimated delivery times", the badge text is the merchant-typed restock date directly). No template changes.
- Internal class names, file paths, namespaces, composer package name (
etechflow/module-backorder-eta-display) — renaming would break backward-compat for everyone who installed via composer. - The EAV attribute code (
backorder_eta) — DB column name; renaming breaks every install's stored data.
Schema
One new idempotent data patch: Setup/Patch/Data/RenameBackorderEtaToRestockDate.php. Updates eav_attribute.frontend_label and note for the backorder_eta attribute. Idempotent — re-running setup:upgrade is a no-op. Dependency declared on AddBackorderEtaAttribute so the rename only fires after the original attribute exists.
[1.2.0] — 2026-05-18 — STR-parity quality pass
After v1.1.0 reached UX parity with NDE, the v1.2.0 work brings BED's overall quality bar to match STR's recent v1.1.0 release: a verify CLI, deeper test coverage, 8-locale i18n stubs, a troubleshooting doc, performance numbers, and an honest pricing pivot. The module's runtime behaviour is unchanged from v1.1.0 — every change in this release is in the surrounding infrastructure that makes BED easier to install, debug, translate, and trust.
Added
bin/magento etechflow:bed:verify— headless 12-step end-to-end verifier matching the pattern from STR and NDE. Exercises Config + EtaResolver (per-product / default-fallback / empty / display-prefix) + BackorderDetector (in-stock / out-of-stock / backorder-allowed-depleted / container types skipped) against the LIVE DB. Self-contained: seeds a test product, runs checks, cleans up via raw DB delete (skips ProductRepository to avoid url_rewrite orphans).docs/bed-troubleshooting.md— pre-emptive support: 10+ common BED tickets with diagnostic ladders ("ETA doesn't show on PDP" / "ETA shows on in-stock product" / "Default ETA shows when I set a per-product ETA" / "Hyvä Checkout doesn't show the ETA but Luma does" / "License inactive" / etc.).docs/performance.md— Module: BED section. Documents per-method latencies:EtaResolver::resolveat 1.4 µs/call,BackorderDetector::isBackorderedat 8.9 µs/call. A 50-product catalog page renders all its BED badges in ~0.5 ms of CPU — <2% of a typical Magento page-render budget.- 8 locale starter CSVs — de_DE / fr_FR / es_ES / it_IT / nl_NL / pt_BR / ja_JP / zh_Hans_CN. ~20 high-confidence translations per locale covering admin labels, badge style names, and the most common storefront strings (Ships in / Backorder ETA / Dismiss / etc.). Each file opens with a
_DRAFT_NOTICE_<LOCALE>sentinel in the target language documenting draft status. Help-note long-form text remains in English (Magento falls back to source string) — same strategy as STR's i18n stubs. - 4 new unit-test classes —
BackorderDetectorTest,ConfigTest,Model/Source/BadgeStyleTest,ViewModel/HyvaCheckoutEtaTest— closes the coverage gap for the engine + Config + ViewModel that the existingEtaResolverTest+LicenseValidatorTest+OrderEmailItemsPluginTestdidn't cover. Test count went from 63 to 106 (+43 tests, +77 assertions).
Changed
- Pricing pivot $295 → $99/yr (single-SKU model). BED has a much smaller feature surface than NDE / STR (4 user-visible features, 1 EAV attribute, vs STR's full rate-engine surface). The earlier $295 was anchored to NDE's tier; honest feature-for-feature comparison puts BED at roughly 1/3 of STR's $179. Renewal $49/yr (50%). 3-module bundle $379/yr. See
marketing/BackorderEtaDisplay/README.mdfor full pricing rationale. - CHANGELOG entry replaced with the proper
[1.2.0]release block (was sitting in[Unreleased]).
Test count + coverage
- Unit tests: 63 → 106 (+43)
- Assertions: 80 → 157 (+77)
etechflow:bed:verify12/12 steps pass end-to-end against the live DB- PHPStan level 4 workspace-clean
Schema
No schema changes. The backorder_eta EAV attribute + the
AddBackorderEtaAttribute / EnableBackorderEtaGridColumn setup
patches from v1.1.0 are unchanged.
Compatibility
Unchanged from v1.1.0: Magento Open Source 2.4.4+ / Adobe Commerce
2.4.4+ / PHP 8.1-8.4 / Hyvä Theme + Hyvä Checkout native.
[1.1.0] — 2026-05-15
Added — UX overhaul (parity with NextDayEligibility v1.3.0)
- Module Status banner at the top of the admin config section. Six states with plain-language explanations and what-to-do guidance:
- ✅ Module is active (green) — licence valid + module enabled
- ⚪ Licence valid, module is disabled (grey) — Enable Module toggled off
- ⚠️ Licence key missing (amber) — production host, no key entered
- ⚠️ Licence key invalid for this host (amber) — key entered but wrong for the current domain
- ℹ️ Dev host bypass active (blue) — current host matches a dev pattern (
*.test,localhost,staging.*, etc.) - ℹ️ Production Environment = No (blue) — toggle off, licence not enforced
Removes the "I installed it but nothing's happening" mystery for first-time installers.
- Inline tooltips on every admin field — every comment now explicitly explains what Yes vs No does, what each badge style option means, and what each display-location toggle controls. Merchants no longer need to read external docs to configure correctly.
backorder_etaattribute now visible AND filterable in the product grid. Merchants can scan the catalog at a glance for which products have ETAs set vs missing. NewEnableBackorderEtaGridColumndata patch upgrades existing installs; fresh installs get the flags viaAddBackorderEtaAttribute.
Changed
LicenseValidator::isDevHost()exposed as public so the new Module Status block can show bypass status.- Admin field labels and
<comment>text expanded across the entiresystem.xml— for example "Show on Product Page" now explains exactly which theme(s) it affects and what happens to the other display locations when toggled. composer.jsonsuggestupdated: dropped the reference to the deprecatedETechFlow_BackorderShippingRestrictormodule; the NDE entry now describes the "complete loop" positioning of the 2-module bundle.
Removed (from the dist zip)
docs/Installation_Guide.docx,docs/installation_guide.html,docs/installation_guide.md— three v1.0.0-era install guides that hadn't been updated for v1.0.x changes. Moved todocs/_archive/(excluded from the shipped zip). Current install instructions live inREADME.md+docs/USER_GUIDE.mdonly — single source of truth, easier to keep current.
i18n
i18n/en_US.csvexpanded from 4 → 26 strings, covering all admin labels, field labels, badge style options, and storefront strings introduced through v1.0.x.
[1.0.2] — 2026-05-15
Added
- "Production Environment" toggle in admin (Stores → Configuration → eTechFlow → Backorder ETA Display → License). Set to "No" on any dev/staging install to run the module at full features without a licence key. Default: Yes.
- 4 new unit tests covering toggle behaviour.
Changed
- Admin License section now has two fields: Production Environment (new) + License Key (existing).
[1.0.1] — 2026-05-15
Fixed
- N+1 query elimination on cart, checkout, and order email — products are now bulk-loaded in a single collection query instead of one repository call per cart line. Significant TTFB improvement on carts with 10+ items.
- Order email plugin return type — defensive cast to string ensures we never return a non-string value upstream, eliminating a potential TypeError on emails sent through third-party customisations.
- Badge style whitelist clamp —
getBadgeStyle()now validates against['warning', 'info', 'neutral']and falls back towarningfor any unrecognised value. Prevents a malformed admin value from rendering as a raw CSS class.
Changed
- Hyvä template upgrades:
- Added inline SVG icons (clock, truck) instead of coloured dot indicators
- Added dark-mode variants (
dark:bg-amber-900/20,dark:text-amber-200, etc.) across all templates - Added Alpine.js fade-in transitions that respect
prefers-reduced-motion - Added
aria-live="polite"on cart/checkout summaries for screen readers - Added
truncate+whitespace-nowrapso long product names don't break layout
- HyvaCheckoutEta ViewModel now returns text-colour utility classes (e.g.
text-amber-600) for SVGcurrentColorinheritance, with corresponding dark-mode variants
Added
www.prefix normalization in license validation- Expanded dev-host pattern detection for auto-bypass
- Bundle license key support
- Hyvä-first templates alongside Luma — Magento auto-uses the correct variant based on the active theme
- Tailwind safelist comments in templates that consume ViewModel-returned classes (protects against Hyvä build purge)
Composer
- Magento framework version range extended to
^103.0||^104.0
[1.0.0] — 2026-05-11
Initial release.
backorder_etaproduct attribute (per-store, text)- Backorder detection (out-of-stock, partial-backorder, qty-depleted with backorders enabled)
- ETA resolver (per-product → store default fallback, with optional label prefix)
- Product detail page badge (Luma)
- Cart summary block (Luma)
- Hyvä Checkout integration via ViewModel
- Order confirmation email HTML section (inline styles for email-client compatibility)
- Admin config: enable, default ETA, label prefix, badge style, per-location display toggles
- HMAC-based per-domain license key system
| Version | Stability | QA Status | Compatibility | Released |
|---|---|---|---|---|
| 1.3.0 | stable | Fail | Magento 2.4.7-2.4.8 Details | 2026-06-02 12:40:37 |
| 1.2.3 | stable | Not tested | Not yet tested Details | 2026-05-30 13:53:07 |
| 1.2.2 | stable | Not tested | Not yet tested Details | 2026-05-25 13:36:35 |
| 1.2.1 | stable | Not tested | Not yet tested Details | 2026-05-20 12:25:15 |
Requires 12
| Package | Constraint |
|---|---|
| magento/framework | ^103.0||^104.0 |
| magento/module-bundle | ^101.0||^102.0 |
| magento/module-catalog | ^104.0||^105.0 |
| magento/module-catalog-inventory | ^100.4||^101.0 |
| magento/module-checkout | ^100.4||^101.0 |
| magento/module-config | ^101.2||^102.0 |
| magento/module-configurable-product | ^100.4||^101.0 |
| magento/module-eav | ^102.1||^103.0 |
| magento/module-quote | ^101.2||^102.0 |
| magento/module-sales | ^103.0||^104.0 |
| magento/module-store | ^101.1||^102.0 |
| php | ~8.1.0||~8.2.0||~8.3.0||~8.4.0 |
Suggests 2
| Package | Reason |
|---|---|
| etechflow/module-next-day-eligibility | Pair with Next Day Eligibility (v1.1.0+) for the complete backorder loop — NDE removes the broken fast-shipping option, BED tells the customer when to expect the item instead. |
| hyva-themes/magento2-default-theme | Hyvä Theme support is built in — install Hyvä to enable Tailwind-styled templates automatically. |
No QA results yet
QA pipelines haven't run for this version. Compatibility and quality results appear here once the vendor publishes a tagged release that gets ingested.
More from etechflow
View vendorDynamic 'View Other Options/Finishes/Sizes' PDP buttons driven by per-product link attributes; replaces hardcoded in-description buttons and strips the old ones at render time.
Theme-agnostic mega menu for Magento 2. Renders on Hyvä, Luma, Adobe Commerce default and custom themes via automatic runtime detection. Provides a JSON endpoint for lazy-loaded subcategory + featured-product data.
EtechFlow Store Locator — admin-managed store/branch finder for Magento 2 with a Leaflet + OpenStreetMap map and postcode proximity search (postcodes.io). Hyva and Luma compatible. No paid map API key required.
Universal Product Fitment Finder for Magento 2 — Make/Model/Year/Part filtering on any fitment domain (automotive, motorcycle, marine, RV, phone cases, watches, appliance parts, anywhere a customer asks "will this fit my X?"). Admin-configurable labels + URL prefix so the same module rebrands to any merchant domain. Includes PDP fitment badge, SEO URLs, customer garage with cross-device sync, OEM/part-number search, and admin tooltips throughout. Theme-agnostic — Hyvä, Luma, custom themes. Renamed from "module-vehicle-compat" in v2.0.0.
Turn an existing module into recurring revenue.
If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.