Catalogue & product data
Multi-Location Inventory Management
Indicative price, not an offer: €30–60/month
Generated from docs/plan/paid/multi-location-inventory-management/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.
Merged from duplicate proposals: “Multi-Location Inventory”, “Multi-location inventory (sources and stocks)”
Paid inventory plugin for merchants with multiple fulfillment locations (warehouse + retail store, or multi-warehouse). Tracks stock levels per location, reserves inventory when an order is placed, suggests fulfillment from the closest location, and enables location-based reporting. Most merchants ship from one location; this opens the multi-warehouse use case and justifies a support commitment.
The problem
I have stock in a warehouse and a retail store. I need real-time availability per location, fulfillment routed to the closest warehouse, and visibility into which location holds each SKU. Manual multi-location tracking wastes time and loses sales.
What it does
- Define locations: name, address, type (warehouse, retail, drop-ship), distance/routing data (lat/long or postcode), is_active (boolean)
- Per-location stock: each product variant tracks stock_by_location { location_id: integer, qty: integer, reserved: integer, available: integer }
- Reserve inventory on order placement: deduct from the source location’s available stock, record reservation
- Fulfillment suggestion: given an order and customer address, suggest the closest location with sufficient stock (using lat/long or postcode distance)
- Fulfillment routing: assign an order to a location, update that location’s reserved and fulfilled counts
- Location-based reporting: stock by location (single view of all locations), low-stock alerts per location, overstock alerts
- Transfer stock between locations: record inter-location movements with audit trail (who, when, qty, from, to)
- Shipment tracking per location: show orders fulfilled from each location, shipment metrics (avg time to ship, cost per shipment)
- Reorder points per location: set minimum stock levels and generate purchase orders by location
- Location-based cost tracking: per-shipment cost, per-location logistics cost, variance analysis
- Sync with external warehouse management systems via webhook (advanced option)
- Public API: GET /locations, GET /locations/:id/inventory, POST /locations/:id/stock-transfer
What it deliberately does NOT do
Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.
- Multi-currency pricing per location — pricing is global; tax may differ by destination, not by fulfillment location
- Local currency payment per location — all transactions settle in the shop’s base currency
- Location-specific product catalogs — all locations sell the same SKUs; availability per location differs, but pricing and descriptions are global
- Cross-location order consolidation (ship from multiple locations to one customer) — orders fulfill from one location only
- Real-time inventory sync with wholesale suppliers — integrations are custom and per-supplier
Data model
New entities: location (id, name, type: enum[‘warehouse’|‘retail’|‘drop-ship’], address, lat: nullable, lon: nullable, is_active: boolean, created_at), stock_by_location (product_variant_id, location_id, qty: integer, reserved: integer), location_transfer (id, from_location_id, to_location_id, product_variant_id, qty: integer, created_at, created_by: user_id), fulfillment_assignment (order_id, location_id, created_at). Adds field to order: fulfilled_from_location_id (foreign key, nullable until assigned). Migration: existing products have all stock mapped to a default ‘primary warehouse’ location.
API
- GET /locations — list all locations with address and active status
- POST /locations — create a new location (admin only)
- PUT /locations/:id — update location details (admin only)
- GET /locations/:id/inventory — list stock by variant for a location
- PUT /locations/:id/stock/:variant_id — update stock qty for a variant at a location
- POST /locations/:id/transfer — transfer stock from this location to another
- GET /locations/:id/transfer-history — audit trail of all transfers in/out
- POST /orders/:id/suggest-fulfillment-location — compute best location by distance and availability
- POST /orders/:id/assign-fulfillment-location/:location_id — assign order to location and reserve stock
- GET /locations/:id/fulfillment-metrics — shipments, avg time, cost per location
- GET /inventory/by-location?product_id=X — show stock for product across all locations
Every route added here must also appear in src/pages/openapi.json.ts — a test
fails the build if it does not.
Admin
Paid plugin admin gains: (1) Locations management page (create, edit, mark inactive), (2) Inventory matrix view (products × locations as a spreadsheet), (3) Stock transfer UI (from/to location, product, qty, audit trail), (4) Order fulfillment assignment (manual or auto-suggest by distance), (5) Location dashboard (stock levels, low-stock alerts, pending transfers), (6) Fulfillment metrics report (shipments per location, avg ship time, cost). Operators see a ‘Closest location’ suggestion when packing an order.
The seam — why this is paid
Paid tier owns locations, multi-location stock tracking, fulfillment routing logic, transfer audit, and metrics reporting. Core owns the order model, the ability to attach a fulfilled_from_location_id, and inventory reservation at checkout (paid tier plugs into core’s reserve-on-checkout hook). A merchant without multi-location can ignore the feature; core still works with a single default location.
Most merchants ship from one location. Multi-location requires inventory sync, location logic, fulfillment routing. Justifies paid because value is logistics optimization.
Dependencies
- inventory-system (core; must exist and support reservation logic)
- order-system (core; to track fulfilled_from_location_id)
- webhook-system (core; paid tier listens to order.placed to auto-assign fulfillment location)
- audit-log (core; to record stock transfers)
Acceptance checks
Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.
- Two locations exist: ‘Warehouse’ (lat=50.1, lon=10.2) and ‘Store’ (lat=50.15, lon=10.25). An order for a customer at (50.12, lon=10.23) suggests ‘Store’ (closer distance).
- A product variant has stock: Warehouse=100, Store=5. An order for qty=10 is placed, fulfillment assigned to Warehouse. Warehouse stock becomes available=90, reserved=10.
- Transferring 20 units from Warehouse to Store creates a location_transfer audit entry; Warehouse available becomes 70, Store becomes 25.
- A location marked inactive does not appear in fulfillment suggestions, but historical fulfillments from that location remain queryable.
- GET /inventory/by-location?product_id=123 returns stock across all active locations in a single response.
- Low-stock alert at Warehouse (threshold=50, current=45) is triggered; no alert at Store (current=25, threshold=50 not set for Store).
- Fulfillment metrics show: Warehouse shipped 150 orders in 30 days (avg 2.5 days), Store shipped 30 orders (avg 1 day).
- A transfer between locations is rejected if source location has insufficient available stock (reserved qty counts against it).
Risks
Over-booking if the paid plugin and core inventory system disagree on reservation logic. Distance-based fulfillment suggestions fail if location coordinates are missing or stale. A merchant with many locations and frequent transfers can overwhelm the audit log. If a location is incorrectly marked inactive, orders may no longer suggest fulfillment from that location, silently orphaning stock.
Commercial context
| Suggested price | €30–60/month |
| Rival anchor | Magento Open Source (not included); Adobe Commerce Inventory Management (paid) |
The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.
Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full
catalogue and ../../AI-GUIDE.md for how to work on this repository.