REST: Update product stock when removing line item from order (#50606)
* REST: Update product stock when removing line item from order This ensures that the REST endpoint behaves the same as the UI when updating an order to remove a line item. Fixes #49651 * Add changefile(s) from automation for the following project(s): woocommerce * phpcs cleanup * Add unit tests * phpcs cleanup * Update plugins/woocommerce/changelog/50606-fix-49651-rest-remove-line-item-stock Co-authored-by: Barry Hughes <3594411+barryhughes@users.noreply.github.com> * Add changefile(s) from automation for the following project(s): woocommerce * Add void return type to new method --------- Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Barry Hughes <3594411+barryhughes@users.noreply.github.com>
This commit is contained in:
parent
6185185589
commit
4ff92e0f1f
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: fix
|
||||
|
||||
Ensure that the orders REST endpoint behaves the same as the UI when updating an order to remove a line item.
|
|
@ -131,7 +131,7 @@ class WC_REST_Orders_Controller extends WC_REST_Orders_V2_Controller {
|
|||
foreach ( $value as $item ) {
|
||||
if ( is_array( $item ) ) {
|
||||
if ( $this->item_is_null( $item ) || ( isset( $item['quantity'] ) && 0 === $item['quantity'] ) ) {
|
||||
$order->remove_item( $item['id'] );
|
||||
$this->remove_item( $order, $key, $item['id'] );
|
||||
} else {
|
||||
$this->set_item( $order, $key, $item );
|
||||
}
|
||||
|
@ -170,6 +170,46 @@ class WC_REST_Orders_Controller extends WC_REST_Orders_V2_Controller {
|
|||
return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}_object", $order, $request, $creating );
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper method to remove order items.
|
||||
* When updating, the item ID provided is checked to ensure it is associated
|
||||
* with the order.
|
||||
*
|
||||
* @param WC_Order $order The order to remove the item from.
|
||||
* @param string $item_type The item type (from the request, not from the item, e.g. 'line_items' rather than 'line_item').
|
||||
* @param int $item_id The ID of the item to remove.
|
||||
*
|
||||
* @return void
|
||||
* @throws WC_REST_Exception If item ID is not associated with order.
|
||||
*/
|
||||
protected function remove_item( WC_Order $order, string $item_type, int $item_id ): void {
|
||||
$item = $order->get_item( $item_id );
|
||||
|
||||
if ( ! $item ) {
|
||||
throw new WC_REST_Exception(
|
||||
'woocommerce_rest_invalid_item_id',
|
||||
esc_html__( 'Order item ID provided is not associated with order.', 'woocommerce' ),
|
||||
400
|
||||
);
|
||||
}
|
||||
|
||||
if ( 'line_items' === $item_type ) {
|
||||
require_once WC_ABSPATH . 'includes/admin/wc-admin-functions.php';
|
||||
wc_maybe_adjust_line_item_product_stock( $item, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow extensions be notified before the item is removed.
|
||||
*
|
||||
* @param WC_Order_Item $item The item object.
|
||||
*
|
||||
* @since 9.3.0.
|
||||
*/
|
||||
do_action( 'woocommerce_rest_remove_order_item', $item );
|
||||
|
||||
$order->remove_item( $item_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an object data.
|
||||
*
|
||||
|
|
|
@ -403,4 +403,81 @@ class WC_REST_Orders_Controller_Tests extends WC_REST_Unit_Test_Case {
|
|||
|
||||
$this->assertIsArray( $decoded_data_object[0]->meta_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testdox When a line item quantity in an order is updated via REST API, the product's stock should also be updated.
|
||||
*/
|
||||
public function test_order_update_line_item_quantity_updates_product_stock() {
|
||||
require_once WC_ABSPATH . 'includes/admin/wc-admin-functions.php';
|
||||
|
||||
$product = WC_Helper_Product::create_simple_product();
|
||||
$product->set_manage_stock( true );
|
||||
$product->set_stock_quantity( 10 );
|
||||
$product->save();
|
||||
|
||||
$order = WC_Helper_Order::create_order( 1, $product, array( 'status' => 'on-hold' ) ); // Initial qty of 4.
|
||||
$items = $order->get_items();
|
||||
$item = reset( $items );
|
||||
wc_maybe_adjust_line_item_product_stock( $item );
|
||||
|
||||
$product = wc_get_product( $product->get_id() );
|
||||
$this->assertEquals( 6, $product->get_stock_quantity() );
|
||||
|
||||
$request = new WP_REST_Request( 'POST', '/wc/v3/orders/' . $order->get_id() );
|
||||
$request->set_body_params(
|
||||
array(
|
||||
'line_items' => array(
|
||||
array(
|
||||
'id' => $item->get_id(),
|
||||
'quantity' => 5,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
$response = $this->server->dispatch( $request );
|
||||
$this->assertEquals( 200, $response->get_status() );
|
||||
|
||||
$product = wc_get_product( $product );
|
||||
$this->assertEquals( 5, $product->get_stock_quantity() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testdox When a line item in an order is removed via REST API, the product's stock should also be updated.
|
||||
*/
|
||||
public function test_order_remove_line_item_updates_product_stock() {
|
||||
require_once WC_ABSPATH . 'includes/admin/wc-admin-functions.php';
|
||||
|
||||
$product = WC_Helper_Product::create_simple_product();
|
||||
$product->set_manage_stock( true );
|
||||
$product->set_stock_quantity( 10 );
|
||||
$product->save();
|
||||
|
||||
$order = WC_Helper_Order::create_order( 1, $product, array( 'status' => 'on-hold' ) ); // Initial qty of 4.
|
||||
$items = $order->get_items();
|
||||
$item = reset( $items );
|
||||
wc_maybe_adjust_line_item_product_stock( $item );
|
||||
|
||||
$product = wc_get_product( $product->get_id() );
|
||||
$this->assertEquals( 6, $product->get_stock_quantity() );
|
||||
|
||||
$request = new WP_REST_Request( 'POST', '/wc/v3/orders/' . $order->get_id() );
|
||||
$request->set_body_params(
|
||||
array(
|
||||
'line_items' => array(
|
||||
array(
|
||||
'id' => $item->get_id(),
|
||||
'quantity' => 0,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
$response = $this->server->dispatch( $request );
|
||||
$this->assertEquals( 200, $response->get_status() );
|
||||
|
||||
$order = wc_get_order( $order );
|
||||
$this->assertEmpty( $order->get_items() );
|
||||
|
||||
$product = wc_get_product( $product );
|
||||
$this->assertEquals( 10, $product->get_stock_quantity() );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue