Variable product sync

This commit is contained in:
claudiulodro 2017-11-17 08:46:49 -08:00
parent 0eba98a4e7
commit dddf0ee473
3 changed files with 72 additions and 2 deletions

View File

@ -365,7 +365,7 @@ class WC_Product_Variable extends WC_Product {
if ( ! $this->get_manage_stock() ) {
$this->set_stock_quantity( '' );
$this->set_backorders( 'no' );
$this->set_stock_status( $this->child_is_in_stock() ? 'instock' : 'outofstock' );
$this->data_store->sync_stock_status( $this );
// If we are stock managing, backorders are allowed, and we don't have stock, force on backorder status.
} elseif ( $this->get_stock_quantity() <= get_option( 'woocommerce_notify_no_stock_amount', 0 ) && 'no' !== $this->get_backorders() ) {
@ -440,6 +440,16 @@ class WC_Product_Variable extends WC_Product {
return $this->data_store->child_is_in_stock( $this );
}
/**
* Is a child on backorder?
*
* @since 3.3.0
* @return boolean
*/
public function child_is_on_backorder() {
return $this->data_store->child_is_on_backorder( $this );
}
/**
* Does a child have a weight set?
* @return boolean

View File

@ -316,6 +316,20 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
return count( $children ) > $oufofstock_children;
}
/**
* Is a child on backorder?
*
* @since 3.3.0
* @param WC_Product $product Product object.
* @return boolean
*/
public function child_is_on_backorder( $product ) {
global $wpdb;
$children = $product->get_children();
$onbackorder_children = $children ? $wpdb->get_var( "SELECT COUNT( post_id ) FROM $wpdb->postmeta WHERE meta_key = '_stock_status' AND meta_value = 'onbackorder' AND post_id IN ( " . implode( ',', array_map( 'absint', $children ) ) . ' )' ) : 0;
return (bool) $onbackorder_children;
}
/**
* Syncs all variation names if the parent name is changed.
*
@ -404,7 +418,13 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
* @param WC_Product $product Product object.
*/
public function sync_stock_status( &$product ) {
$product->set_stock_status( $product->child_is_in_stock() ? 'instock' : 'outofstock' );
$in_stock = $product->child_is_in_stock();
if ( $in_stock ) {
$on_backorder = $product->child_is_on_backorder();
$product->set_stock_status( $on_backorder ? 'onbackorder' : 'instock' );
} else {
$product->set_stock_status( 'outofstock' );
}
}
/**

View File

@ -71,4 +71,44 @@ class WC_Tests_Product_Variable extends WC_Unit_Test_Case {
$this->assertEquals( 3, $product->get_stock_quantity() );
$this->assertEquals( 'instock', $product->get_stock_status() );
}
/**
* Test that variable products have the correct status when syncing with their children.
*
* @since 3.3.0
*/
public function test_variable_product_stock_status_sync() {
$product = new WC_Product_Variable();
$product->save();
$child1 = new WC_Product_Variation();
$child1->set_parent_id( $product->get_id() );
$child1->save();
$child2 = new WC_Product_Variation();
$child2->set_parent_id( $product->get_id() );
$child2->save();
$product->set_children( array( $child1->get_id(), $child2->get_id() ) );
// Product should be in stock if a child is in stock.
$child1->set_stock_status( 'instock' );
$child1->save();
$child2->set_stock_status( 'outofstock' );
$child2->save();
WC_Product_Variable::sync( $product );
$this->assertEquals( 'instock', $product->get_stock_status() );
// Product should be out of stock if all children are out of stock.
$child1->set_stock_status( 'outofstock' );
$child1->save();
WC_Product_Variable::sync( $product );
$this->assertEquals( 'outofstock', $product->get_stock_status() );
// Product should be on backorder if a child is on backorder.
$child1->set_stock_status( 'onbackorder' );
$child1->save();
WC_Product_Variable::sync( $product );
$this->assertEquals( 'onbackorder', $product->get_stock_status() );
}
}