etechflow / module-in-store-pickup

etechflow/module-in-store-pickup

Click & Collect / in-store pickup for Magento 2. Multi-store admin (stores, holidays, tags, amenities, pickup windows). Hyvä Checkout Magewire-native. Auto-fills shipping address from picked store (kills the wrong-tax bug). Standalone — works without any other ETechFlow module — and integrates richer when paired with NDE / DD / BED.

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

ETechFlow_InStorePickup

Click & Collect for Magento 2. Multi-store admin (stores, holidays, tags, amenities, pickup windows). Hyvä Checkout Magewire-native. Auto-fills shipping address from the picked store — the killer feature every other C&C module misses.

Status: v1.0.0 Phase 1 (foundation only — admin CRUD ships in Phase 2-4).

Why this exists

Every existing Magento 2 C&C module shares the same structural bug: when a customer picks "in-store collection", they're still required to fill in a shipping address. They type their home address, Magento charges tax based on it, the merchant has to manually fix every order. We searched the market and 8+ vendors all have this same problem.

ETechFlow_InStorePickup solves it: when the customer picks a store, the shipping address auto-fills with the store's address. Tax calculation works. Order export works. Refund routing works. No manual cleanup.

Features

Multi-store admin (stores, hours, holidays, tags, amenities, pickup windows) Phase 2-4
Auto-fill shipping address from picked store Phase 6
Hyvä Checkout Magewire-native store picker Phase 7
Hyvä Theme + Luma fallback templates Phase 7
Per-installation HMAC license + bundle key ✅ Phase 1
Verify CLI (etechflow:isp:verify) ✅ Phase 1
Tideways profiler instrumentation (ETechFlow_ISP_* spans) ✅ Phase 1
Pickup-ready email + 6-digit verification code Phase 8
Optional NDE / DD / BED integrations Phase 9
Holiday import CLI (etechflow:isp:import-holidays) Phase 10

Standalone — and better when paired

This module works fully standalone. It does NOT require any other eTechFlow module.

When the sibling modules ARE installed, soft-detection kicks in:

Optional pairing Standalone With pairing
+ NDE Reads MSI stock Uses NDE's eligibility engine (drop-ship + supplier rules)
+ DD Own pickup windows Optional: reuse DD's time intervals (consolidated UX)
+ BED Generic "available once restocked" Per-product backorder ETA shown on pickup options

Compatibility

Platform Status
Magento Open Source 2.4.4 – 2.4.8
Adobe Commerce 2.4.4 – 2.4.8
Hyvä Theme + Hyvä Checkout ✓ Magewire-native
PHP 8.1 / 8.2 / 8.3 / 8.4

Installation

composer require etechflow/module-in-store-pickup:^1.0
bin/magento module:enable ETechFlow_InStorePickup
bin/magento setup:upgrade
bin/magento setup:di:compile      # production mode only
bin/magento cache:flush

setup:upgrade creates 11 tables prefixed etechflow_isp_.

Smoke test

bin/magento etechflow:isp:verify

Phase 1 verify confirms license + config + all 11 tables exist.

License

Proprietary — see LICENSE.txt. Commercial licenses available at https://etechflow.com.

Changelog — ETechFlow In-Store Pickup

All notable changes to this module. Adheres to Semantic Versioning.


[1.0.1] — 2026-05-20 — Install-on-Hyvä hotfix

Two real bugs surfaced during the first install on a Hyvä client store. Both fixed.

Fixed

  • ShippingAddressAutofillPlugin::afterSetShippingMethod strict return type. The method signature used : Address strict return type and unconditionally returned $result. If any third-party plugin earlier in the plugin chain returned null / false / a non-Address value (legal under Magento's plugin contract), our plugin would emit a TypeError mid-response. Because the fatal happened after output buffering started, nginx saw a 200 status with malformed chunked output — and var/log/exception.log stayed empty because a TypeError isn't an Exception. Symptom: admin/category pages randomly broken with "Backend fetch failed" while no error appeared in logs.
    • Fix: removed the strict return type. Added an instanceof Address guard before our autofill logic runs. Non-Address $result values now pass through unchanged.
  • magewirephp/magewire was in suggest instead of require. The Magewire/Checkout/StorePicker.php class extends \Magewirephp\Magewire\Component. On a store without Magewire installed (Hyvä Theme without Hyvä Checkout, or a clean Open Source install), bin/magento setup:di:compile would attempt to compile the class against the missing parent and either fail or produce broken interceptors in generated/code/. The CHANGELOG entry for v1.0.0 incorrectly claimed the file would "sit inert on disk" — di:compile scans every class regardless.
    • Fix: moved magewirephp/magewire: ^1.0||^2.0 into require. Composer will now install it transitively (it's a tiny package — single PHP file plus a few helper classes — and it's the parent of every Hyvä Checkout component anyway).

Migration

composer update etechflow/module-in-store-pickup
bin/magento setup:upgrade
bin/magento setup:di:compile
docker exec <php-fpm-container> kill -USR2 1   # or restart php-fpm — clears OPcache

If you're upgrading from v1.0.0 on a host with opcache.validate_timestamps=0, you MUST restart php-fpm after setup:di:compile — otherwise stale compiled interceptors stay in memory and you see the same "two workers returning different output sizes" symptom that masked Bug 1.


[1.0.0] — 2026-05-20 — Click & Collect for Magento 2

First commercial release. Click & Collect / in-store pickup module with the differentiators competing modules can't ship: auto-fill shipping address from the picked store (kills the wrong-tax bug 8+ competitors all have) and a standalone-first architecture that gets richer when paired with the rest of the eTechFlow suite.

The differentiator competitors can't match

Every existing Magento 2 C&C module (Amasty, MageWorx, WebKul, Magenest, Wyomind, Fooman, MageDelight, Mageants, Setubridge, FME, Meetanshi…) bolts onto Magento's shipping system, which requires a shipping address. So they all force the customer to type one when picking C&C. Customers type their home address, Magento charges tax based on it, the merchant has to manually fix every order.

ETechFlow_InStorePickup solves this: when the customer picks a pickup method, our plugin overwrites the shipping address with the store's address — silently. Tax calculation is then correct out of the box. No manual cleanup.

Added

Foundation

  • registration.php, composer.json (proprietary licence, soft-dependencies on NDE / DD / BED / Hyvä Checkout)
  • etc/module.xml setup_version 1.0.0
  • DB schema (etc/db_schema.xml) — 11 tables: stores, hours, exceptions, holidays, store_holiday_exclusion, amenities, store_amenity, tags, store_tag, pickup_windows, store_pickup_windows. All FKs CASCADE on store delete. Indexes on hot-path columns.
  • Admin config (etc/adminhtml/system.xml) — License section + General Settings + eTechFlow Suite Integrations + Notifications, all with plain-English tooltips.

Licensing + Module Infrastructure

  • Model/LicenseValidator — per-domain HMAC + bundle key. MODULE_ID = in-store-pickup. Shares BUNDLE_SECRET with every eTechFlow module.
  • Model/Config — license-aware isEnabled(). Soft-detection of optional integrations (NDE, DD, BED) via class_exists.
  • Model/Performance/Profiler — Tideways span helper, tags ETechFlow_ISP_*.

Entities + Service Contracts

  • Full Api/Data + Api/Repository contracts for 5 entities: Store, Tag, Amenity, PickupWindow, Holiday. Every method has a docblock (per our standards).
  • Model + ResourceModel + Collection + Repository implementations for all 5.

Stores Admin (CRUD)

  • Magento UI Component listing grid (search, filters, sortable columns, bookmarks, mass actions: Delete / Enable / Disable, inline edit on name/active/sort_order)
  • Tabbed edit form (General / Address / About & Contact)
  • 9 controllers: Index, NewAction, Edit, Save, Delete, InlineEdit, MassDelete, MassEnable, MassDisable
  • Form action buttons (Save / Save & Continue / Back / Delete), all license-aware

Shipping Carrier

  • Model/Carrier/InStorePickup — registered as etechflow_isp. Returns one method per active store (Pick up at <store name> at £0).
  • Standard getAllowedMethods() + collectRates() pattern. Safe-fails to "no rates" on any error so checkout never breaks.

THE KILLER FEATURE

  • Plugin/Quote/ShippingAddressAutofillPluginafter-plugin on Magento\Quote\Model\Quote\Address::setShippingMethod. When the method matches etechflow_isp_<store_code>, overwrites the customer's shipping address with the store's address. Forces tax recalculation. Solves the universal C&C wrong-tax bug.

Notifications

  • Model/PickupOrderDetector — central helper for "is this order a pickup?" + "which store?"
  • Model/PickupCodeGenerator — cryptographically random 4-8 digit pickup-verification codes (length configurable)
  • Model/Notification/StaffAlertSender + view/frontend/email/staff_alert.html — emails the staff at the picked store when a new pickup order arrives.
  • Observer/StaffAlertObserver on sales_order_place_after — fires the alert. Pickup orders only; non-pickup short-circuits at zero cost.

Optional eTechFlow Suite Adapters

  • Model/Adapter/NdeEligibilityAdapter — when NDE is installed + admin opted in, ISP defers to NDE's stock-eligibility rules engine (drop-ship + supplier mode + force-standard overrides). Falls back to MSI source-stock when NDE isn't present.

Verify CLI

  • bin/magento etechflow:isp:verify — 13 checks covering license, config, all 11 DB tables, all 5 repositories via DI, carrier instantiation, auto-fill plugin presence. Exit 0 on full pass, 1 on any failure.

Standalone-first architecture

This module works fully standalone. The integrations with NDE / DD / BED are opt-in enhancements soft-detected via class_exists — if the sibling module isn't installed, ISP falls back to its own self-contained logic.

Optional pairing Standalone With pairing
+ NDE Reads MSI source stock directly Uses NDE's rules engine (drop-ship + supplier mode + force-standard)
+ DD Own simple pickup windows Optional: reuse DD's time intervals (consolidated UX)
+ BED Generic "available once restocked" Per-product backorder ETA on pickup options

Compatibility

  • Magento Open Source 2.4.4 – 2.4.8
  • Adobe Commerce 2.4.4 – 2.4.8
  • PHP 8.1 / 8.2 / 8.3 / 8.4
  • Hyvä Theme + Hyvä Checkout (Magewire integration ships in v1.1)

Known limitations (deferred to v1.1)

  • Tag / Amenity / Pickup Window / Holiday admin UIs — entities exist; admin grids ship in v1.1. Configure these via direct DB seed or via the Holiday import CLI for v1.0.
  • Per-store Hours / Exception days editor as sub-tabs on Store form — schema is in place; admin sub-tabs ship in v1.1. Configure via direct DB seed for v1.0.
  • Customer "Pickup Ready" email + admin "Mark Ready" button — needs schema columns on sales_order for pickup_code + pickup_status; deferred to v1.1.
  • Hyvä Checkout Magewire-native store picker — DD already has a Magewire date picker (v1.4.0); same pattern applies here in v1.1. v1.0 customers using Hyvä Checkout get the standard Magento checkout's shipping-method radio list, with one method per store.
  • Holiday import CLI (etechflow:isp:import-holidays --country=GB) — deferred to v1.1.
  • Map view (Leaflet, lazy-loaded) — v1.2.
Versions
Version Stability QA Status Compatibility Released
2.2.0 stable Fail Magento 2.4.7-2.4.8 Details 2026-06-06 14:14:39
2.1.2 stable Not tested Not yet tested Details 2026-06-04 20:21:29
2.0.2 stable Not tested Not yet tested Details 2026-06-04 19:54:12
1.3.2 stable Not tested Not yet tested Details 2026-06-04 19:38:19
2.1.1 stable Not tested Not yet tested Details 2026-06-03 10:08:42
2.1.0 stable Not tested Not yet tested Details 2026-06-03 08:18:01
2.0.1 stable Not tested Not yet tested Details 2026-05-26 16:35:48
2.0.0 stable Not tested Not yet tested Details 2026-05-26 16:16:15
1.3.1 stable Not tested Not yet tested Details 2026-05-22 11:11:01
1.3.0 stable Not tested Not yet tested Details 2026-05-22 10:18:08
1.2.1 stable Not tested Not yet tested Details 2026-05-22 09:54:50
1.2.0 stable Not tested Not yet tested Details 2026-05-22 09:26:30
1.1.15 stable Not tested Not yet tested Details 2026-05-22 06:12:14
1.1.14 stable Not tested Not yet tested Details 2026-05-22 05:50:20
1.1.13 stable Not tested Not yet tested Details 2026-05-22 05:13:16
1.1.12 stable Not tested Not yet tested Details 2026-05-21 22:21:30
1.1.11 stable Not tested Not yet tested Details 2026-05-21 22:02:24
1.1.10 stable Not tested Not yet tested Details 2026-05-21 21:16:14
1.1.9 stable Not tested Not yet tested Details 2026-05-21 20:06:23
1.1.8 stable Not tested Not yet tested Details 2026-05-21 19:52:51
1.1.7 stable Not tested Not yet tested Details 2026-05-21 19:09:18
1.1.6 stable Not tested Not yet tested Details 2026-05-21 18:18:08
1.1.5 stable Not tested Not yet tested Details 2026-05-21 17:56:32
1.1.4 stable Not tested Not yet tested Details 2026-05-21 16:53:10
1.1.2 stable Not tested Not yet tested Details 2026-05-21 16:02:13
1.1.1 stable Not tested Not yet tested Details 2026-05-21 14:56:46
1.1.0 stable Not tested Not yet tested Details 2026-05-21 14:18:12
1.0.1 stable Not tested Not yet tested Details 2026-05-20 16:09:21

Requires 13

Package Constraint
magento/framework ^103.0||^104.0
magento/module-backend ^102.0||^103.0
magento/module-catalog-inventory ^100.4||^101.0
magento/module-config ^101.2||^102.0
magento/module-customer ^103.0||^104.0
magento/module-eav ^102.1||^103.0
magento/module-quote ^101.2||^102.0
magento/module-sales ^103.0||^104.0
magento/module-shipping ^100.4||^101.0
magento/module-store ^101.1||^102.0
magento/module-ui ^101.2||^102.0
magewirephp/magewire ^1.0||^2.0
php ~8.1.0||~8.2.0||~8.3.0||~8.4.0

Suggests 4

Package Reason
etechflow/module-backorder-eta-display Optional. When installed, the pickup-ready date for backorder items pulls from BED's per-product ETA.
etechflow/module-delivery-date Optional. When installed, ISP can reuse DD's time intervals as pickup-window slots — consolidated admin UX.
etechflow/module-next-day-eligibility Optional. When installed, ISP uses NDE's stock-eligibility rules engine for richer per-product picklability checks (drop-ship, supplier mode, force-standard overrides).
hyva-themes/magento2-hyva-checkout Hyvä Checkout activates the Magewire-native store picker. Plain Hyvä Theme / Luma use Alpine + server-rendered fallback.

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.