When questions such as “How do you save the product stock inventory history?” pop up in our private Business Bloomer Club slack channel for WooCommerce developers, I can’t really do without thinking of coding it myself!
This neat customization saves the stock quantity of a simple product or a variable product variation before there is a stock change, due to a manual stock quantity edit or a customer order.
Please bear in mind that if you have hundreds of stock movements per product this may slow down your backend and/or database, so the snippet may need some sort of optimization or limitation (“last 10 movements”).
So, let’s see how it works. Enjoy!
PHP Snippet: Display Stock Inventory Movements @ Product Edit Page
/**
* @snippet Save & Show Product Stock History
* @how-to businessbloomer.com/woocommerce-customization
* @author Rodolfo Melogli, Business Bloomer
* @testedwith WooCommerce 7
* @community https://businessbloomer.com/club/
*/
add_action( 'woocommerce_product_before_set_stock', 'bbloomer_historical_stock_product_parent' );
add_action( 'woocommerce_variation_before_set_stock', 'bbloomer_historical_stock_product_parent' );
function bbloomer_historical_stock_product_parent( $product ) {
$stock_history = get_post_meta( $product->get_id(), '_stock_history', true ) ? get_post_meta( $product->get_id(), '_stock_history', true ) : array();
$stock_history[time()] = (int)get_post_meta( $product->get_id(), '_stock', true );
update_post_meta( $product->get_id(), '_stock_history', $stock_history );
}
add_action( 'add_meta_boxes', 'bbloomer_product_meta_box' );
function bbloomer_product_meta_box() {
add_meta_box( 'stock_history', 'Stock History', 'bbloomer_display_stock_history', 'product', 'advanced', 'high' );
}
function bbloomer_display_stock_history() {
global $post;
$product = wc_get_product( $post->ID );
if ( $product->get_type() == 'variable' ) {
foreach ( $product->get_available_variations() as $key ) {
$products[] = $key['variation_id'];
}
} else $products[] = $post->ID;
foreach ( $products as $product_id ) {
$product = wc_get_product( $product_id );
echo '<h3>' . $product->get_name() . '</h3>';
$stock_history = get_post_meta( $product_id, '_stock_history', true );
if ( $stock_history ) {
foreach ( $stock_history as $timestamp => $stockvalue ) {
if ( ! $stockvalue ) continue;
echo '<p>' . date( DATE_COOKIE, $timestamp ) . ': <b>' . $stockvalue . '</b></p>';
}
};
echo '<p>Current Stock: <b>' . $product->get_stock_quantity() . '</b></p>';
}
}
It’s only showing the current stock, which is not what I want the snippet to do. No stock movements are showing?
https://keelyw.tinytake.com/msc/OTk5MDYzMF8yMzY1ODE2MQ
Hello Keely! This is not retroactive, so it should show the history once you do the first stock change. Does this help?
This is great. It wil be perfect if there will be a custom tab under Products Menu – Stock history, to sort by date, etc. Thx
Thank you!
Hello,
showcase of your snippet is showing also Date of stock movement, but for me is not showing.
Can you tell me, where is the problem?
Thank you in advance.
Hi Jacob, can you share a screenshot please?
Hello and thank you for the great snippet, 2 questions,
1) How to add the “last 10 movements”
2) Can I record who user did the stock changes?
Thank you very much!
Hi Dorothy, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!
Hello Rodolfo,
Very interesting solution.
Is there a way to pull/display the name of the customer or shop manager after updating stock. This can go befor ar after rhe date.
My customer needs this to track who wes behid updating the stock.
Thanks a ot in advance!
Hi Mustapha, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!
Hello,
Is this putting a lot of stress on wordpress?
Only if you have thousands of products and a lot of stock changes, in which case this needs to be recoded and maybe use custom DB tables