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.

magento2-module Compatibility: Not yet tested Code Quality: Pending Tests: N/A Security: Pending proprietary
Viewing version 1.2.2. Latest version is 1.3.0. Switch to latest

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_eta attribute 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_eta text 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)

  1. Unzip etechflow-module-backorder-eta-display-1.0.1.zip into:

    <magento-root>/app/code/ETechFlow/BackorderEtaDisplay/
    

    Directory MUST be ETechFlow (capital E, T, F) — case-sensitive on Linux.

  2. 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

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.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:upgrade always has SOMETHING to register in patch_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 where setup:upgrade aborts post-patch, data_version
    never advances, and DbStatusValidator returns 500 on every request
    until rollback.

    Future releases copy this template (V123ReleaseMarker, etc).

Changed

  • RenameBackorderEtaToRestockDate docblock rewritten to make
    clear that this patch ONLY relabels the attribute (the
    frontend_label and note), 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 the manufacturer code 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 dangling patch_list rows).
    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 ETARestock Date (the field merchants fill in on every product edit page). Renamed via a new idempotent RenameBackorderEtaToRestockDate data patch — existing installs automatically pick up the new label on next setup:upgrade. The DB column backorder_eta is unchanged (renaming would break every install's data).
  • Admin config labels in Stores → Configuration → eTechFlow → Backorder ETA Display:
    • Default ETA TextDefault Restock Date
    • Label 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)"
    • backorder kept 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::resolve at 1.4 µs/call, BackorderDetector::isBackordered at 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 existing EtaResolverTest + LicenseValidatorTest + OrderEmailItemsPluginTest didn'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.md for 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:verify 12/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_eta attribute now visible AND filterable in the product grid. Merchants can scan the catalog at a glance for which products have ETAs set vs missing. New EnableBackorderEtaGridColumn data patch upgrades existing installs; fresh installs get the flags via AddBackorderEtaAttribute.

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 entire system.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.json suggest updated: dropped the reference to the deprecated ETechFlow_BackorderShippingRestrictor module; 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 to docs/_archive/ (excluded from the shipped zip). Current install instructions live in README.md + docs/USER_GUIDE.md only — single source of truth, easier to keep current.

i18n

  • i18n/en_US.csv expanded 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 clampgetBadgeStyle() now validates against ['warning', 'info', 'neutral'] and falls back to warning for 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-nowrap so long product names don't break layout
  • HyvaCheckoutEta ViewModel now returns text-colour utility classes (e.g. text-amber-600) for SVG currentColor inheritance, 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_eta product 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
Versions
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.

License
proprietary
Authors

More from etechflow

View vendor
Make it pay

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.