Multi-warehouse operations

Companies that stock the same products in more than one warehouse need three things standard Odoo does not fully provide out of the box: a controlled way to move goods between warehouses through an arbitrary number of pick/pack/ship steps, the ability to source individual sales order lines from different warehouses instead of one warehouse per order, and a webshop that pools availability across several warehouses instead of a single one. The eYssen multi-warehouse modules add all three, plus carrier-specific pickup/delivery address logic for internal transfers shipped through the eYssen Custom and GLS delivery integrations.

Key features

Inter-warehouse transfers

Draft Internal Transfer form with source/destination warehouse and carrier

A new stock.internal.transfer record represents one shipment of goods from a Source Warehouse to a Destination Warehouse, both of which must be flagged as usable for internal transit (see Configuration). The record is automatically classified as an Intracompany transfer or an Intercompany transfer depending on whether the two warehouses belong to the same company, and it tracks a Carrier, a sequence-based Transfer Reference (IT000001, …) and a rollup of the transferred quantities.

An internal transfer moves through the following states: DraftWaiting for Source WarehouseSource ProcessingIn TransitDestination ProcessingDone (with a Reconciliation Required side state and a Cancelled state). Draft transfers cannot be deleted once they leave the draft state.

  • For an intracompany transfer, Create Picking generates the first stock picking directly, using the first configured out-step of the source warehouse.

  • For an intercompany transfer, Create Orders instead creates a linked Source Order (a sales order on the source company) and a Destination Order (a purchase order on the destination company), and finding the right cross-company partner records automatically where possible.

  • Start Transfer confirms the first picking and moves the transfer to Waiting for Source Warehouse.

Multi-step routing between warehouses

Warehouse form, Inter Warehouse Transfer tab with In/Out steps and validity banner

Each warehouse that can act as a source or destination of an internal transfer defines its own chain of Out Steps (how goods leave the warehouse toward the transit location) and In Steps (how goods arrive from the transit location into the warehouse). Every step is a stock.warehouse.step record pointing to an Operation Type; source and destination locations are read from that operation type.

The system automatically renumbers and validates the chain whenever steps are added, edited or removed:

  • the first out step must start at the warehouse’s stock location, and the last out step must end at a transit location;

  • the first in step must start at a transit location, and the last in step must end at the warehouse’s stock location;

  • consecutive steps must connect (each step’s destination must equal the next step’s source), and the chain may not contain loops.

The warehouse form shows a live validity banner (it_settings_valid_msg) summarizing any problem found; Inter Warehouse Transfer fields other than the toggle are hidden until Can be used for internal transit is checked. As an internal transfer’s pickings are validated one by one, action_next_step automatically creates the next picking in the chain — carrying over open moves, package levels and move-to-move links — until the goods reach the destination warehouse’s stock location, at which point the transfer is marked Done (or Reconciliation Required if any quantity was under-delivered along the way).

Internal Transfer form, Pickings tab with a chain of pickings across steps

Note

A stock.internal.transfer.template model exists to pre-fill a warehouse’s step chain from a reusable template, but only the template’s Name is currently implemented — the template selector on the warehouse form (Create Steps from Template) does not yet populate the steps.

Packaging, unpacking and reverse pickings

Operation Type form with Package In / Package Out / Allow Reverse Picking options

Each Operation Type gains four extra options used by the transfer chain:

  • Package In — the picking must have every move covered by a package before it can be validated (button_validate raises an error otherwise); when this is set on the step the transfer’s carrier is copied onto the picking automatically.

  • Package Out — the picking must be fully unpacked (no remaining package levels) before it can be validated.

  • All In Packing — reserved flag for packaging rules (no validation logic yet).

  • Allow Reverse Picking and Reverse Picking Type — when a picking is validated with a shortfall (delivered quantity lower than demanded), the shortfall is automatically split into a reverse picking on the chosen operation type (or the same one if none is set), returning the missing quantity to the original source location(s). If the missing quantity had come from more than one source location in the original picking, an activity is scheduled on the reverse picking asking a warehouse user to double-check the split.

Custom and GLS delivery for internal transfers

Picking form for an internal-transfer leg with the internal-transfer header and smart button

Pickings that belong to an internal transfer use a dedicated header (Mark as Todo, Check Availability, Validate, Print) instead of the standard one, and expose a View Int.Transfer smart button; the same button is added to sales order and purchase order forms whenever they are linked to a transfer.

When the Custom or GLS delivery modules build the shipping label for a picking that belongs to an internal transfer, the pickup and delivery addresses are taken from the transfer’s source and destination warehouse partners instead of the sale order’s customer:

  • eyssen_stock_multi_warehouse_delivery_custom overrides custom_pickupaddress / custom_deliveryaddress on stock.picking to resolve the source/destination warehouse partner.

  • eyssen_stock_multi_warehouse_delivery_gls overrides gls_pickupaddress / gls_deliveryaddress the same way, additionally prefixing the resulting name with the warehouse’s company name (<Company> - <Partner>) so the GLS label clearly shows which company location is shipping or receiving.

Internal-transfer picking with a GLS-tracked package

For GLS, once every package on a picking reaches GLS tracking status 05 (handed over), the picking is validated automatically — this lets a multi-step transfer leg complete itself as soon as GLS confirms all parcels have moved, without a warehouse user manually clicking Validate. GLS parcel identifiers (gls_parcel_id, gls_parcel_number) are also carried over onto the repackaged package created for each next step, and the transfer list/search can look transfers up by GLS tracking number.

Splitting sales orders across warehouses

Sales order lines with a per-line Warehouse column

eyssen_sale_multiple_warehouse adds a required Warehouse field directly on sales order lines, defaulting to the salesperson’s default warehouse. This lets a single order be delivered from several warehouses at once — for example, one order line shipped from the main warehouse and another from a regional one — instead of forcing the whole order onto a single Warehouse at header level:

  • changing the order-level Warehouse field propagates that warehouse to every existing order line;

  • the line-level warehouse is passed into procurement (_prepare_procurement_values), so each line generates its delivery from its own warehouse; and

  • the Make to Order indicator on a line is computed from that line’s own warehouse route, not the order’s.

The Warehouse column is only shown to users in the Multiple Warehouses group (stock.group_stock_multi_warehouses, enabled automatically by Odoo once a company has more than one warehouse) and becomes read-only once the order leaves the Quotation / Quotation Sent stage.

Webshop stock pooling across warehouses

Website settings with the More Warehouses field under Shop - Products

eyssen_website_sale_multiple_warehouse lets a website draw stock availability from several warehouses instead of the single core Warehouse field. A website with one or more More Warehouses selected pools its availability across all of them:

  • on a product page, the displayed free_qty (used for the “in stock” / quantity widgets) is the sum of the forecasted quantity of the product across every warehouse in More Warehouses, read from the pre-aggregated stock figures maintained by eyssen_stock_advanced_stock;

  • in the cart, the same pooled quantity is used to validate that a requested cart quantity does not exceed what is available across those warehouses, instead of only the single website warehouse.

If a website has no More Warehouses configured, availability falls back to the order’s own Warehouse, matching the standard single-warehouse website_sale_stock behavior.

Configuration

  1. Enable multi-warehouse mode. This is a standard Odoo mechanism, not an eYssen setting: creating a second warehouse for a company (Inventory ‣ Configuration ‣ Warehouses ‣ New) automatically activates the Storage Locations setting and grants the Multiple Warehouses access group to internal users. The per-line Warehouse column on sales orders and the website’s More Warehouses field are only visible to users in this group.

  2. Flag the warehouses used for internal transfers. On each source and destination warehouse (Inventory ‣ Configuration ‣ Warehouses), open the Inter Warehouse Transfer tab and check Can be used for internal transit.

  3. Configure the Out/In step chain for each of those warehouses in the same tab (or globally under Inventory ‣ Configuration ‣ Warehouse Steps), picking an Operation Type per step. The banner on the warehouse form must turn green (Step settings are valid.) before the warehouse can be used as a transfer source or destination — stock.internal.transfer restricts its Source Warehouse / Destination Warehouse fields to warehouses with a valid, transit-enabled step chain.

  4. Set packaging behavior on the relevant operation types (Inventory ‣ Configuration ‣ Operation Types): enable Package In on outgoing steps that must be packed before shipping (e.g. before handing off to GLS), Package Out on incoming steps that must be fully unpacked, and Allow Reverse Picking (with an optional dedicated Reverse Picking Type) wherever short deliveries should generate a reverse picking automatically.

  5. Install the matching delivery module if internal-transfer pickings should carry carrier-specific pickup/delivery addresses: eyssen_stock_multi_warehouse_delivery_custom for the eYssen Custom carrier, eyssen_stock_multi_warehouse_delivery_gls for GLS. Both simply extend eyssen_stock_multi_warehouse and require the corresponding base delivery module (eyssen_delivery_custom / eyssen_delivery_gls) to already be installed.

  6. Enable per-line warehouses on quotations by installing eyssen_sale_multiple_warehouse — no extra settings screen is involved; the Warehouse order-line column appears as soon as the Multiple Warehouses group (step 1) is active.

  7. Enable webshop stock pooling by installing eyssen_website_sale_multiple_warehouse (which requires eyssen_stock_advanced_stock), then go to Website ‣ Configuration ‣ Settings, scroll to the Shop - Products section, and fill in More Warehouses next to the standard Warehouse field.

Usage

Running an internal transfer

  1. Go to Inventory ‣ Transfers ‣ Internal Transfers and create a new record.

  2. Set the Source Warehouse, Destination Warehouse and Carrier. The Type (Intracompany transfer / Intercompany transfer) is computed automatically from the two warehouses’ companies.

  3. For an intracompany transfer, click Create Picking, then open the picking and add the products and quantities to move; for an intercompany transfer, click Create Orders to generate the linked sales/purchase orders instead.

  4. Click Start Transfer to confirm the first picking. The transfer moves to Waiting for Source Warehouse.

  5. Process and validate each picking in turn from the Pickings tab (or from the picking’s own View Int.Transfer smart button). Each validated picking automatically spawns the next step’s picking until the goods reach the destination warehouse, at which point the transfer reaches Done.

  6. If a picking is under-delivered on an operation type with Allow Reverse Picking enabled, a reverse picking is created for the shortfall automatically; if it needs manual attention (multiple source locations), a to-do activity is scheduled on that reverse picking.

Selling from multiple warehouses on one order

  1. On a sales order, add order lines as usual. Each line defaults to the salesperson’s default warehouse.

  2. Show or edit the Warehouse column on the order line list (or set it on each line’s form) to route individual lines to a different warehouse, as long as the order is still a quotation.

  3. Confirm the order — each line generates its delivery from its own warehouse.

Selling across pooled warehouses on the webshop

  1. Configure More Warehouses on the website as described in Configuration.

  2. On the shop, the quantity/availability shown for a storable product reflects the sum of forecasted stock across all of those warehouses, not just one.

  3. When a customer adds a quantity to the cart, availability is validated against the same pooled total.

Scope and modules

  • eyssen_stock_multi_warehouse — the stock.internal.transfer model, warehouse step configuration, the Internal Transfers and Warehouse Steps menus, and the packaging/reverse-picking operation-type options.

  • eyssen_stock_multi_warehouse_delivery_custom — routes internal-transfer pickup/delivery addresses through the transfer’s warehouses for the eYssen Custom carrier.

  • eyssen_stock_multi_warehouse_delivery_gls — the same address routing for GLS, plus GLS-parcel-aware auto-validation and package re-creation along the transfer chain.

  • eyssen_sale_multiple_warehouse — adds the per-order-line Warehouse field on sales orders.

  • eyssen_website_sale_multiple_warehouse — pools webshop stock availability and cart validation across a website’s configured More Warehouses.