--- title: "WooCommerce reserved stock: show units tied up in unshipped orders" description: WooCommerce shows one stock number, not how many units are already committed to unshipped orders. Here is the small plugin that adds that count. source: https://steem.dev/blog/woocommerce-reserved-stock-plugin published: 2026-10-07 updated: 2026-10-07 alternative_to: ATUM Inventory Management site: Steem — AI WordPress plugin generator --- # WooCommerce reserved stock: show units tied up in unshipped orders WooCommerce manages stock as a single number. When a customer places an order, that number goes down. There is no built-in way to see how many of those deducted units are still on a shelf waiting to be packed versus how many have physically left the warehouse. For small stores that process every order as it arrives, this is not a problem. For stores that batch-pick, pack on a schedule, or have any gap between order confirmation and shipment, the missing context is exactly this: how many units are reserved in orders that have not yet shipped. Commercial platforms like Shopware show this alongside available stock as a dedicated reserved field. WooCommerce does not. A small plugin that adds a reserved count to the products admin list and to the product edit screen fills that gap without requiring a full inventory management extension. ## What one build covers - A Reserved column in the WooCommerce Products list showing units in processing, on-hold, or pending payment orders - A note in the product Inventory tab showing the same count when units are currently reserved - Variable products: reserved units totalled across all variations in the list column ## What it does not cover - Physical stock as a separately recorded field: the physical count is derived from WooCommerce stock plus reserved, not tracked independently - Variation-level reserved counts broken out individually in the products list column - Custom order statuses: only processing, on-hold, and pending payment are included - Performance at scale: querying all open orders per page load will be slow for stores with many concurrent orders - Purchase order receiving, stock reconciliation, or any inbound inventory workflow ## The prompt ```text Build a WooCommerce plugin called Reserved Stock for WooCommerce. Plugin Name: Reserved Stock for WooCommerce. Description: Shows how many units of each product are tied up in unshipped orders. Single PHP file. No dependencies beyond WooCommerce. Write a function rswoo_load_map() that returns a static array mapping product IDs (integers) to reserved unit counts (integers). On the first call: fetch all orders using wc_get_orders( [ 'status' => [ 'wc-processing', 'wc-on-hold', 'wc-pending' ], 'limit' => -1, 'return' => 'objects' ] ). For each order, call get_items() and loop the line items. For each line item, determine the parent product ID: if get_variation_id() returns a non-zero value, the parent product ID is the value returned by get_product_id() (WooCommerce stores the parent ID in that field for variation line items); otherwise use get_product_id() directly. Add get_quantity() to $map[ $parent_id ]. Store $map in a static variable so subsequent calls return without re-querying. Return the map. Add a column to the products admin list. Use filter manage_edit-product_columns to insert a column with key rswoo_reserved and heading Reserved, positioned after the column with key woocommerce-stock. In action manage_product_posts_custom_column, when the column key is rswoo_reserved: call rswoo_load_map() and look up $reserved = $map[ $post->ID ] ?? 0. Load the product with wc_get_product( $post->ID ). If get_manage_stock() is true, output the integer as plain text, wrapped in if it is greater than zero. If get_manage_stock() is false, output —. Hook into woocommerce_product_options_stock to add a note on the product edit screen. Call rswoo_load_map() and look up the count for get_the_ID(). If the count is greater than zero, output:

{$reserved} units reserved in unshipped orders (processing, on-hold, pending payment).

where {$reserved} is the actual integer. No settings page, no AJAX endpoints, no inline CSS, no inline JS. ``` ## Why one stock number causes confusion during fulfillment When the WooCommerce stock field reads 8, that number could mean several things. It could mean 8 units are available to sell with nothing committed yet. It could mean you had 12, four orders are in processing, and 8 remain uncommitted. Without checking every open order individually, there is no way to know from the products screen alone. The problem shows up most clearly during a stock audit or a reorder decision. If you count 12 units on the shelf but WooCommerce shows 8, you have to figure out whether the discrepancy is a data error or just four units sitting in unshipped processing orders. That verification, which should take a second, can take several minutes when orders are spread across multiple pages. The concept the user needs is reserved stock: units that have been deducted from the available count because an order exists for them, but that have not physically left the warehouse yet. Available plus reserved equals physical. WooCommerce tracks available. This plugin surfaces reserved. ## What the plugin adds to WooCommerce A Reserved column in the WooCommerce Products admin list. For each product with stock management enabled, the column shows how many units appear across orders with status processing, on-hold, or pending payment. A zero means nothing is currently committed. A dash means the product does not use WooCommerce stock tracking. A note on the product edit screen, inside the Inventory tab, directly below the stock quantity field. If units are reserved, it reads: 4 units reserved in unshipped orders (processing, on-hold, pending payment). If nothing is reserved the note does not appear, so the edit screen is unchanged for the common case where there is nothing to show. For variable products, the column totals reserved units across all variations and shows a single number against the parent product. Individual variation-level reserved counts are not broken out in the list, though they are visible by opening the relevant orders. ## When a dedicated inventory plugin makes more sense This plugin reads reserved counts each time the products list loads by fetching all open orders once per page request and summing line items. For a small store with a handful of processing orders at any moment, that is fast enough to be invisible. For a store with hundreds of concurrent processing orders, the products list will take noticeably longer to load. The plugin also does not track physical stock as a separate recorded field you update when goods arrive. The physical count it implies (WooCommerce stock plus reserved) is derived, not stored. If your receiving workflow matters, meaning you want to log purchase orders, record deliveries against them, and reconcile discrepancies, this is the wrong tool. ATUM Inventory Management is built for that, with a dedicated stock table and purchase order module. Custom order statuses are not covered either. If your workflow uses a status like packed or ready-to-ship between processing and completed, units in those statuses will not count as reserved. The plugin checks the three built-in WooCommerce statuses only. ## Questions ### Why does the Reserved column show a dash for some products? The plugin only shows a count for products with WooCommerce stock management enabled. If a product does not track stock, there is no meaningful reserved count to display, so the column shows a dash. ### Does the count include variable product variations correctly? Yes. Reserved quantities are rolled up to the parent product, so the column shows a single total across all variations. If you need to know which specific variation the reserved units belong to, open the relevant orders. ### The products list loads slowly after installing this. Why? The plugin fetches all open orders once per page request to calculate reserved counts. For a store with many concurrent processing orders, that fetch adds load time. If it is causing problems, ATUM Inventory Management reads reserved stock from a dedicated database table, which is faster at scale. ### Can I include custom order statuses in the reserved count? Not in this build. It checks processing, on-hold, and pending payment only. If your workflow uses a custom status for orders that are packed but not yet shipped, you would need to add that status to the wc_get_orders call inside rswoo_load_map. --- Source: https://steem.dev/blog/woocommerce-reserved-stock-plugin Build this plugin: https://steem.dev/app