Skip to content

Buy Online, Pick Up in Store

Hyvä POS is in closed beta

Hyvä POS is currently in a closed beta (pilot phase) with a small group of merchants. It is not yet generally available: the App Store release follows the pilot, and features and configuration may still change - possibly in backwards-incompatible ways - before the general release. Want to take part? Sign up at hyva.io/pos.

A customer orders on the webshop in the evening, picks your store instead of home delivery, and walks up to the counter the next day. The register has been expecting them: the order sits in the location's pickup queue, the order screen says whether the goods can be handed over, and completing the pickup is one action that ships the order, deducts stock from the right source and sends the confirmation email. No middleware, no export - the storefront and the counter read the same Magento order.

This page covers the whole chain: the Magento settings that make Pick In Store appear at checkout, what the register needs to see the order, and the handover itself.

Magento Prerequisites

In-store pickup is standard Magento: the Inventory In-Store Pickup modules ship with every 2.4 install, so nothing extra is needed on the storefront side. What is not automatic is having it appear. The option only shows at checkout when a chain of inventory settings all line up, and every link in that chain fails silently - no error, no log entry, the method is quietly not offered. Work through the settings below in order.

Enable In-Store Delivery

Set Stores → Configuration → Sales → Delivery Methods → In-Store Delivery to Yes. This is the carrier the pickup step rides on; the same section holds the search radius customers get when they look up a store.

Flag the Source as a Pickup Location

Open Stores → Inventory → Sources - the top-level Stores menu, not Stores → Configuration - and edit the source that represents your store:

  • Use as Pickup Location: Yes
  • a full street address
  • latitude and longitude filled in

The coordinates are not optional: checkout hides any source without them, even when everything else is correct.

Take the Website off Default Stock

A website running on Magento's built-in Default Stock never shows pickup sources - Magento excludes Default Stock from pickup entirely. Most single-store installs run on Default Stock, so this is the step that catches most first setups.

Create a custom stock under Stores → Inventory → Stocks → Add New Stock and fill three fields:

  • Name: anything recognisable
  • Sales Channels → Websites: tick your website. The form itself states the mechanism: all unassigned sales channels are assigned to Default Stock, so ticking the website here is what moves it off.
  • Sources → Assign Sources: add the pickup source

Save, then reindex:

bin/magento indexer:reindex inventory

Afterwards the Manage Stock grid shows your website against the new stock, and Default Stock with none.

Choose a Distance Provider

Checkout searches and sorts pickup locations by distance, so it needs a way to turn a customer's postcode into coordinates. Pick one under Stores → Configuration → Catalog → Inventory → Distance Provider for Distance Based SSA:

  • Offline calculation needs no API key, but it reads a local geonames table that starts empty. Import it once per country the store serves:

    bin/magento inventory-geonames:import nl
    

    Repeat per country code, or space-separate them: nl be de. Skip the import and a search by postcode resolves to nothing - the pickup step shows an empty list of stores.

  • Google works without the import but requires a Google API key.

Assign Every Product to the Source

Magento offers a pickup source at checkout only when every line in the cart has a source item at that source. The quantity is irrelevant - zero is fine - the row just has to exist.

The consequence is a classic support call: pickup "works sometimes". A cart with one product that is not assigned to the store's source hides Pick In Store for the entire cart, with no explanation. When pickup appears for one cart and vanishes for another, check the source assignment of every product in the cart that fails.

Checkout Support

Magento's Luma checkout renders the pickup step natively. Hyvä Checkout has no in-store pickup UI yet, so stores running it cannot offer pickup at online checkout at this time. Support is in development.

This limits where the orders come from, not what the register can do: POS special orders and pickups placed through Luma reach the pickup queue as normal.

POS Prerequisites

The storefront side gets the order placed; three things on the POS side get it to the counter.

The PRO module, and a location on the right source. The pickup queue is a PRO feature: the device needs the module installed and its terminal bound to a location whose Inventory Source is the pickup source customers select at checkout. The queue is scoped by that source code, so a location pointing at a different source shows an empty queue, not an error.

Magento cron must be running. The check that marks pickup orders ready runs every five minutes as a cron job (hyva_pos_auto_ready_backorder_pickups). With cron dead, the order detail on the register never flips to "Ready for collection", no matter how much stock is on the shelf. If there is any doubt about cron on your install, settle it before anything else on this page.

Auto-ready is switched on per location under Hyvä POS → Locations → your location → Pickup Configuration, or as the global default under Stores → Configuration → Hyvä POS → Terminal Defaults → Pickup Defaults. Two toggles control it:

  • Auto Ready: Backorder Pickup - the cron checks stock on hand at the location's source and marks the order ready once every line is covered. This is the stock-arrival watcher, and despite the name it serves online pickup orders too.
  • Auto Ready: Online In-Store Pickup - online orders skip the stock check entirely and flip to ready on the first cron run after placement. Checkout already validated the quantity when the customer ordered, so there is nothing left to wait for. Leave this off when staff should confirm the order is picked and packed before the customer is told to collect.

The order must be in a collectable state. The queue lists orders in the processing or pending_payment states. An order paid with an offline method - check / money order, bank transfer - sits in pending until it is invoiced, and a pending order is invisible to the POS: no error, it is just not there. Invoice it in the admin and it joins the queue. Payment methods that invoice automatically, which is most card and PSP payments, need no extra step.

How the Queue Works

The Pickup filter on the Orders tab shows everything awaiting collection at the location. Special orders sold at the counter for later pickup share the same queue, each row marked with its origin. Every entry is classified by one question: can this customer be served right now?

  • Ready: every outstanding item is coverable from stock on hand at the location's source. Hand it over.
  • Awaiting stock: at least one line is short. Nothing to do yet.
  • Stale: open for more than 14 days. These are the ones worth a phone call.

The classification is computed live against stock at the location's source every time the list loads - nothing is stored. A delivery booked into stock moves orders from awaiting to ready without anyone touching them. Reservations are ignored on purpose: the question the queue answers is whether the goods are physically in the store, not whether MSI has promised them elsewhere.

The slice the queue opens on is configurable as the Default Pickup Queue Filter, in the same Pickup Defaults section and overridable per location. The register can also poll for new pickups and show a ready count on the dashboard; polling is off by default, switched on per device under Settings → Checkout → Check for New Pickups.

The Order Banner

Open a pickup order and a banner gives the cashier one of three answers: Awaiting stock, Ready for collection, or Picked up.

The banner and the list answer the same question from different places. The list computes readiness live from stock on every load; the banner waits for the marker the auto-ready cron stamps. That gap shows in one situation: stock has just arrived, or cron has not run yet, or auto-ready is off - the list already says Ready while the order detail still says Awaiting stock. For exactly that case the banner carries a Check stock availability button: it asks the live queue directly and flips the banner to Ready when stock is on hand at the source.

None of this ever blocks a handover. Hand over to customer is always available: when the customer is at the counter and the goods are physically in hand, no software state should stand between them.

Completing a Pickup

Complete pickup is one action: it creates the shipment against the location's source (so MSI deducts stock from the right place), records who completed the handover and where, and moves the order to the configured Post-Pickup Order Status - leave that setting empty and the order keeps whatever status Magento set.

The customer's pickup confirmation email is sent at that moment, not before. Readiness is computed on every load and never stored, so there is no "your order is ready" email in this flow; the one email marks the goods actually changing hands. The email toggle on the completion screen defaults to on.

Troubleshooting

Every failure in this chain is silent, so the table maps each symptom to the setting behind it.

Symptom Cause Fix
Pick In Store missing at checkout In-Store Delivery carrier is off Enable Stores → Configuration → Sales → Delivery Methods → In-Store Delivery.
Pick In Store missing at checkout Source is not a pickup location, or has no coordinates On the source: Use as Pickup Location = Yes, full street address, latitude and longitude filled.
Pick In Store missing at checkout Website runs on Default Stock Create a custom stock with the website as sales channel and the pickup source assigned, then reindex.
Pickup shows for some carts, not others One cart line has no source item at the store's source (the intersection rule) Assign every product to the pickup source; the quantity can be zero, the row must exist.
Store search finds no locations Distance provider cannot resolve the postcode: offline calculation without geonames imported, or Google without an API key Run bin/magento inventory-geonames:import <country> for each served country, or configure the Google key.
Order not in the pickup queue Offline payment, order still pending Invoice the order in the admin; it appears immediately.
Order not in the pickup queue The order's pickup location belongs to a different source than the device's location Check the location's Inventory Source matches the source customers pick at checkout.
List says Ready, order banner says Awaiting stock Auto-ready is off, or Magento cron is not running Tap Check stock availability for the immediate answer; enable Auto Ready: Backorder Pickup on the location and verify cron runs.