Merge pull request woocommerce/woocommerce-admin#1426 from woocommerce/update/1323-handle-report-regeneration-fail
Use Action Scheduler for lookup table updates & schedule retries.
This commit is contained in:
commit
0711ed85f8
|
@ -37,6 +37,11 @@ class WC_Admin_Api_Init {
|
|||
*/
|
||||
const ORDERS_LOOKUP_BATCH_INIT = 'wc-admin_orders_lookup_batch_init';
|
||||
|
||||
/**
|
||||
* Action hook for processing a batch of orders.
|
||||
*/
|
||||
const SINGLE_ORDER_ACTION = 'wc-admin_process_order';
|
||||
|
||||
/**
|
||||
* Queue instance.
|
||||
*
|
||||
|
@ -59,19 +64,16 @@ class WC_Admin_Api_Init {
|
|||
add_filter( 'rest_endpoints', array( 'WC_Admin_Api_Init', 'filter_rest_endpoints' ), 10, 1 );
|
||||
add_filter( 'woocommerce_debug_tools', array( 'WC_Admin_Api_Init', 'add_regenerate_tool' ) );
|
||||
|
||||
// Initialize Orders data store class's static vars.
|
||||
add_action( 'woocommerce_after_register_post_type', array( 'WC_Admin_Api_Init', 'orders_data_store_init' ), 20 );
|
||||
// Initialize Customers Report data store sync hooks.
|
||||
// Note: we need to hook in before `wc_current_user_is_active`.
|
||||
// See: https://github.com/woocommerce/woocommerce/blob/942615101ba00c939c107c3a4820c3d466864872/includes/wc-user-functions.php#L749.
|
||||
add_action( 'wp_loaded', array( 'WC_Admin_Api_Init', 'customers_report_data_store_init' ) );
|
||||
// Initialize syncing hooks.
|
||||
add_action( 'wp_loaded', array( __CLASS__, 'orders_lookup_update_init' ) );
|
||||
|
||||
// Initialize scheduled action handlers.
|
||||
add_action( self::QUEUE_BATCH_ACTION, array( __CLASS__, 'queue_batches' ), 10, 3 );
|
||||
add_action( self::QUEUE_DEPEDENT_ACTION, array( __CLASS__, 'queue_dependent_action' ), 10, 2 );
|
||||
add_action( self::QUEUE_DEPEDENT_ACTION, array( __CLASS__, 'queue_dependent_action' ), 10, 3 );
|
||||
add_action( self::CUSTOMERS_BATCH_ACTION, array( __CLASS__, 'customer_lookup_process_batch' ) );
|
||||
add_action( self::ORDERS_BATCH_ACTION, array( __CLASS__, 'orders_lookup_process_batch' ) );
|
||||
add_action( self::ORDERS_LOOKUP_BATCH_INIT, array( __CLASS__, 'orders_lookup_batch_init' ) );
|
||||
add_action( self::SINGLE_ORDER_ACTION, array( __CLASS__, 'orders_lookup_process_order' ) );
|
||||
|
||||
// Add currency symbol to orders endpoint response.
|
||||
add_filter( 'woocommerce_rest_prepare_shop_order_object', array( __CLASS__, 'add_currency_symbol_to_order_response' ) );
|
||||
|
@ -433,7 +435,7 @@ class WC_Admin_Api_Init {
|
|||
// so that the orders can be associated with the `customer_id` column.
|
||||
self::customer_lookup_batch_init();
|
||||
// Queue orders lookup to occur after customers lookup generation is done.
|
||||
self::queue_dependent_action( self::ORDERS_LOOKUP_BATCH_INIT, self::CUSTOMERS_BATCH_ACTION );
|
||||
self::queue_dependent_action( self::ORDERS_LOOKUP_BATCH_INIT, array(), self::CUSTOMERS_BATCH_ACTION );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -457,16 +459,58 @@ class WC_Admin_Api_Init {
|
|||
}
|
||||
|
||||
/**
|
||||
* Init orders data store.
|
||||
* Schedule an action to process a single Order.
|
||||
*
|
||||
* @param int $order_id Order ID.
|
||||
* @return void
|
||||
*/
|
||||
public static function orders_data_store_init() {
|
||||
public static function schedule_single_order_process( $order_id ) {
|
||||
if ( 'shop_order' !== get_post_type( $order_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This can get called multiple times for a single order, so we look
|
||||
// for existing pending jobs for the same order to avoid duplicating efforts.
|
||||
$existing_jobs = self::queue()->search(
|
||||
array(
|
||||
'status' => 'pending',
|
||||
'per_page' => 1,
|
||||
'claimed' => false,
|
||||
'search' => "[{$order_id}]",
|
||||
)
|
||||
);
|
||||
|
||||
if ( $existing_jobs ) {
|
||||
$existing_job = current( $existing_jobs );
|
||||
|
||||
// Bail out if there's a pending single order action, or a pending dependent action.
|
||||
if (
|
||||
( self::SINGLE_ORDER_ACTION === $existing_job->get_hook() ) ||
|
||||
(
|
||||
self::QUEUE_DEPEDENT_ACTION === $existing_job->get_hook() &&
|
||||
in_array( self::SINGLE_ORDER_ACTION, $existing_job->get_args() )
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We want to ensure that customer lookup updates are scheduled before order updates.
|
||||
self::queue_dependent_action( self::SINGLE_ORDER_ACTION, array( $order_id ), self::CUSTOMERS_BATCH_ACTION );
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach order lookup update hooks.
|
||||
*/
|
||||
public static function orders_lookup_update_init() {
|
||||
// Activate WC_Order extension.
|
||||
WC_Admin_Order::add_filters();
|
||||
// Initialize data stores.
|
||||
|
||||
add_action( 'save_post_shop_order', array( __CLASS__, 'schedule_single_order_process' ) );
|
||||
add_action( 'woocommerce_order_refunded', array( __CLASS__, 'schedule_single_order_process' ) );
|
||||
|
||||
WC_Admin_Reports_Orders_Stats_Data_Store::init();
|
||||
WC_Admin_Reports_Products_Data_Store::init();
|
||||
WC_Admin_Reports_Taxes_Data_Store::init();
|
||||
WC_Admin_Reports_Coupons_Data_Store::init();
|
||||
WC_Admin_Reports_Customers_Data_Store::init();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -512,19 +556,35 @@ class WC_Admin_Api_Init {
|
|||
$order_ids = $order_query->get_orders();
|
||||
|
||||
foreach ( $order_ids as $order_id ) {
|
||||
// @todo: schedule single order update if this fails?
|
||||
WC_Admin_Reports_Orders_Stats_Data_Store::sync_order( $order_id );
|
||||
WC_Admin_Reports_Products_Data_Store::sync_order_products( $order_id );
|
||||
WC_Admin_Reports_Coupons_Data_Store::sync_order_coupons( $order_id );
|
||||
WC_Admin_Reports_Taxes_Data_Store::sync_order_taxes( $order_id );
|
||||
self::orders_lookup_process_order( $order_id );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init customers report data store.
|
||||
* Process a single order to update lookup tables for.
|
||||
* If an error is encountered in one of the updates, a retry action is scheduled.
|
||||
*
|
||||
* @param int $order_id Order ID.
|
||||
* @return void
|
||||
*/
|
||||
public static function customers_report_data_store_init() {
|
||||
WC_Admin_Reports_Customers_Data_Store::init();
|
||||
public static function orders_lookup_process_order( $order_id ) {
|
||||
$result = array_sum(
|
||||
array(
|
||||
WC_Admin_Reports_Orders_Stats_Data_Store::sync_order( $order_id ),
|
||||
WC_Admin_Reports_Products_Data_Store::sync_order_products( $order_id ),
|
||||
WC_Admin_Reports_Coupons_Data_Store::sync_order_coupons( $order_id ),
|
||||
WC_Admin_Reports_Taxes_Data_Store::sync_order_taxes( $order_id ),
|
||||
)
|
||||
);
|
||||
|
||||
// If all updates were either skipped or successful, we're done.
|
||||
// The update methods return -1 for skip, or a boolean success indicator.
|
||||
if ( 4 === absint( $result ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise assume an error occurred and reschedule.
|
||||
self::schedule_single_order_process( $order_id );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -592,9 +652,10 @@ class WC_Admin_Api_Init {
|
|||
* Queue an action to run after another.
|
||||
*
|
||||
* @param string $action Action to run after prerequisite.
|
||||
* @param array $action_args Action arguments.
|
||||
* @param string $prerequisite_action Prerequisite action.
|
||||
*/
|
||||
public static function queue_dependent_action( $action, $prerequisite_action ) {
|
||||
public static function queue_dependent_action( $action, $action_args, $prerequisite_action ) {
|
||||
$blocking_jobs = self::queue()->search(
|
||||
array(
|
||||
'status' => 'pending',
|
||||
|
@ -613,10 +674,10 @@ class WC_Admin_Api_Init {
|
|||
self::queue()->schedule_single(
|
||||
$after_blocking_job,
|
||||
self::QUEUE_DEPEDENT_ACTION,
|
||||
array( $action, $prerequisite_action )
|
||||
array( $action, $action_args, $prerequisite_action )
|
||||
);
|
||||
} else {
|
||||
self::queue()->schedule_single( time() + 5, $action );
|
||||
self::queue()->schedule_single( time() + 5, $action, $action_args );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,15 +51,6 @@ class WC_Admin_Reports_Coupons_Data_Store extends WC_Admin_Reports_Data_Store im
|
|||
$this->report_columns['orders_count'] = str_replace( 'order_id', $table_name . '.order_id', $this->report_columns['orders_count'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up all the hooks for maintaining and populating table data.
|
||||
*/
|
||||
public static function init() {
|
||||
add_action( 'save_post', array( __CLASS__, 'sync_order_coupons' ) );
|
||||
add_action( 'clean_post_cache', array( __CLASS__, 'sync_order_coupons' ) );
|
||||
add_action( 'woocommerce_order_refunded', array( __CLASS__, 'sync_order_coupons' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns comma separated ids of included coupons, based on query arguments from the user.
|
||||
*
|
||||
|
@ -315,19 +306,21 @@ class WC_Admin_Reports_Coupons_Data_Store extends WC_Admin_Reports_Data_Store im
|
|||
*
|
||||
* @since 3.5.0
|
||||
* @param int $order_id Order ID.
|
||||
* @return void
|
||||
* @return int|bool Returns -1 if order won't be processed, or a boolean indicating processing success.
|
||||
*/
|
||||
public static function sync_order_coupons( $order_id ) {
|
||||
global $wpdb;
|
||||
|
||||
$order = wc_get_order( $order_id );
|
||||
if ( ! $order ) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
$coupon_items = $order->get_items( 'coupon' );
|
||||
$num_updated = 0;
|
||||
|
||||
foreach ( $coupon_items as $coupon_item ) {
|
||||
$wpdb->replace(
|
||||
$result = $wpdb->replace(
|
||||
$wpdb->prefix . self::TABLE_NAME,
|
||||
array(
|
||||
'order_id' => $order_id,
|
||||
|
@ -342,7 +335,11 @@ class WC_Admin_Reports_Coupons_Data_Store extends WC_Admin_Reports_Data_Store im
|
|||
'%s',
|
||||
)
|
||||
);
|
||||
|
||||
$num_updated += intval( $result );
|
||||
}
|
||||
|
||||
return ( count( $coupon_items ) === $num_updated );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -73,10 +73,6 @@ class WC_Admin_Reports_Orders_Stats_Data_Store extends WC_Admin_Reports_Data_Sto
|
|||
* Set up all the hooks for maintaining and populating table data.
|
||||
*/
|
||||
public static function init() {
|
||||
add_action( 'save_post', array( __CLASS__, 'sync_order' ) );
|
||||
// @todo: this is required as order update skips save_post.
|
||||
add_action( 'clean_post_cache', array( __CLASS__, 'sync_order' ) );
|
||||
add_action( 'woocommerce_order_refunded', array( __CLASS__, 'sync_order' ) );
|
||||
add_action( 'woocommerce_refund_deleted', array( __CLASS__, 'sync_on_refund_delete' ), 10, 2 );
|
||||
add_action( 'delete_post', array( __CLASS__, 'delete_order' ) );
|
||||
}
|
||||
|
@ -360,18 +356,19 @@ class WC_Admin_Reports_Orders_Stats_Data_Store extends WC_Admin_Reports_Data_Sto
|
|||
* Add order information to the lookup table when orders are created or modified.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @return int|bool Returns -1 if order won't be processed, or a boolean indicating processing success.
|
||||
*/
|
||||
public static function sync_order( $post_id ) {
|
||||
if ( 'shop_order' !== get_post_type( $post_id ) ) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
$order = wc_get_order( $post_id );
|
||||
if ( ! $order ) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
self::update( $order );
|
||||
return self::update( $order );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -388,14 +385,14 @@ class WC_Admin_Reports_Orders_Stats_Data_Store extends WC_Admin_Reports_Data_Sto
|
|||
* Update the database with stats data.
|
||||
*
|
||||
* @param WC_Order $order Order to update row for.
|
||||
* @return int|bool|null Number or rows modified or false on failure.
|
||||
* @return int|bool Returns -1 if order won't be processed, or a boolean indicating processing success.
|
||||
*/
|
||||
public static function update( $order ) {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . self::TABLE_NAME;
|
||||
|
||||
if ( ! $order->get_id() || ! $order->get_date_created() ) {
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
$data = array(
|
||||
|
@ -450,7 +447,9 @@ class WC_Admin_Reports_Orders_Stats_Data_Store extends WC_Admin_Reports_Data_Sto
|
|||
}
|
||||
|
||||
// Update or add the information to the DB.
|
||||
return $wpdb->replace( $table_name, $data, $format );
|
||||
$result = $wpdb->replace( $table_name, $data, $format );
|
||||
|
||||
return ( 1 === $result );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,15 +82,6 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
|
|||
$this->report_columns['orders_count'] = str_replace( 'order_id', $table_name . '.order_id', $this->report_columns['orders_count'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up all the hooks for maintaining and populating table data.
|
||||
*/
|
||||
public static function init() {
|
||||
add_action( 'save_post', array( __CLASS__, 'sync_order_products' ) );
|
||||
add_action( 'clean_post_cache', array( __CLASS__, 'sync_order_products' ) );
|
||||
add_action( 'woocommerce_order_refunded', array( __CLASS__, 'sync_order_products' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills ORDER BY clause of SQL request based on user supplied parameters.
|
||||
*
|
||||
|
@ -319,7 +310,7 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
|
|||
*
|
||||
* @since 3.5.0
|
||||
* @param int $order_id Order ID.
|
||||
* @return void
|
||||
* @return int|bool Returns -1 if order won't be processed, or a boolean indicating processing success.
|
||||
*/
|
||||
public static function sync_order_products( $order_id ) {
|
||||
global $wpdb;
|
||||
|
@ -328,10 +319,13 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
|
|||
|
||||
// This hook gets called on refunds as well, so return early to avoid errors.
|
||||
if ( ! $order || 'shop_order_refund' === $order->get_type() ) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
foreach ( $order->get_items() as $order_item ) {
|
||||
$order_items = $order->get_items();
|
||||
$num_updated = 0;
|
||||
|
||||
foreach ( $order_items as $order_item ) {
|
||||
$order_item_id = $order_item->get_id();
|
||||
$quantity_refunded = $order->get_item_quantity_refunded( $order_item );
|
||||
$amount_refunded = $order->get_item_amount_refunded( $order_item );
|
||||
|
@ -355,13 +349,13 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
|
|||
$net_revenue = $order_item->get_subtotal( 'edit' ) - $amount_refunded;
|
||||
|
||||
if ( $quantity_refunded >= $order_item->get_quantity( 'edit' ) ) {
|
||||
$wpdb->delete(
|
||||
$result = $wpdb->delete(
|
||||
$wpdb->prefix . self::TABLE_NAME,
|
||||
array( 'order_item_id' => $order_item_id ),
|
||||
array( '%d' )
|
||||
); // WPCS: cache ok, DB call ok.
|
||||
} else {
|
||||
$wpdb->replace(
|
||||
$result = $wpdb->replace(
|
||||
$wpdb->prefix . self::TABLE_NAME,
|
||||
array(
|
||||
'order_item_id' => $order_item_id,
|
||||
|
@ -398,7 +392,11 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
|
|||
)
|
||||
); // WPCS: cache ok, DB call ok, unprepared SQL ok.
|
||||
}
|
||||
|
||||
$num_updated += intval( $result );
|
||||
}
|
||||
|
||||
return ( count( $order_items ) === $num_updated );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -66,15 +66,6 @@ class WC_Admin_Reports_Taxes_Data_Store extends WC_Admin_Reports_Data_Store impl
|
|||
$this->report_columns['orders_count'] = str_replace( 'order_id', $table_name . '.order_id', $this->report_columns['orders_count'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up all the hooks for maintaining and populating table data.
|
||||
*/
|
||||
public static function init() {
|
||||
add_action( 'save_post', array( __CLASS__, 'sync_order_taxes' ) );
|
||||
add_action( 'clean_post_cache', array( __CLASS__, 'sync_order_taxes' ) );
|
||||
add_action( 'woocommerce_order_refunded', array( __CLASS__, 'sync_order_taxes' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the database query with parameters used for Taxes report: categories and order status.
|
||||
*
|
||||
|
@ -255,17 +246,20 @@ class WC_Admin_Reports_Taxes_Data_Store extends WC_Admin_Reports_Data_Store impl
|
|||
* Create or update an entry in the wc_order_tax_lookup table for an order.
|
||||
*
|
||||
* @param int $order_id Order ID.
|
||||
* @return void
|
||||
* @return int|bool Returns -1 if order won't be processed, or a boolean indicating processing success.
|
||||
*/
|
||||
public static function sync_order_taxes( $order_id ) {
|
||||
global $wpdb;
|
||||
$order = wc_get_order( $order_id );
|
||||
if ( ! $order ) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
foreach ( $order->get_items( 'tax' ) as $tax_item ) {
|
||||
$wpdb->replace(
|
||||
$tax_items = $order->get_items( 'tax' );
|
||||
$num_updated = 0;
|
||||
|
||||
foreach ( $tax_items as $tax_item ) {
|
||||
$result = $wpdb->replace(
|
||||
$wpdb->prefix . self::TABLE_NAME,
|
||||
array(
|
||||
'order_id' => $order->get_id(),
|
||||
|
@ -284,7 +278,11 @@ class WC_Admin_Reports_Taxes_Data_Store extends WC_Admin_Reports_Data_Store impl
|
|||
'%f',
|
||||
)
|
||||
);
|
||||
|
||||
$num_updated += intval( $result );
|
||||
}
|
||||
|
||||
return ( count( $tax_items ) === $num_updated );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Init Class Test
|
||||
*
|
||||
* @package WooCommerce\Tests\API
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WC_Tests_API_Init
|
||||
*/
|
||||
class WC_Tests_API_Init extends WC_REST_Unit_Test_Case {
|
||||
/**
|
||||
* Set up.
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->queue = new WC_Admin_Test_Action_Queue();
|
||||
WC_Admin_Api_Init::set_queue( $this->queue );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down.
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
WC_Admin_Api_Init::set_queue( null );
|
||||
$this->queue->actions = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cause a failure when updating order stats for the test order, without deleting it.
|
||||
*
|
||||
* @param string $query Query.
|
||||
* @return string
|
||||
*/
|
||||
public function filter_order_query( $query ) {
|
||||
if (
|
||||
0 === strpos( $query, 'REPLACE INTO' ) &&
|
||||
false !== strpos( $query, WC_Admin_Reports_Orders_Stats_Data_Store::TABLE_NAME )
|
||||
) {
|
||||
remove_filter( 'query', array( $this, 'filter_order_query' ) );
|
||||
return 'THIS WONT MATCH';
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a retry job is scheduled for a failed sync.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_order_sync_retries_on_failure() {
|
||||
// Create a test Order.
|
||||
$product = new WC_Product_Simple();
|
||||
$product->set_name( 'Test Product' );
|
||||
$product->set_regular_price( 25 );
|
||||
$product->save();
|
||||
|
||||
$order = WC_Helper_Order::create_order( 1, $product );
|
||||
$order->set_status( 'completed' );
|
||||
$order->set_total( 100 ); // $25 x 4.
|
||||
$order->save();
|
||||
|
||||
// Clear the existing action queue (the above save adds an action).
|
||||
$this->queue->actions = array();
|
||||
|
||||
// Force a failure by sabotaging the query run after retreiving order coupons.
|
||||
add_filter( 'query', array( $this, 'filter_order_query' ) );
|
||||
|
||||
// Initiate sync.
|
||||
WC_Admin_Api_Init::orders_lookup_process_order( $order->get_id() );
|
||||
|
||||
// Verify that a retry job was scheduled.
|
||||
$this->assertCount( 1, $this->queue->actions );
|
||||
$this->assertArraySubset(
|
||||
array(
|
||||
'hook' => WC_Admin_Api_Init::SINGLE_ORDER_ACTION,
|
||||
'args' => array( $order->get_id() ),
|
||||
),
|
||||
$this->queue->actions[0]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -64,6 +64,8 @@ class WC_Tests_API_Reports_Categories extends WC_REST_Unit_Test_Case {
|
|||
$order->set_total( 100 ); // $25 x 4.
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$uncategorized_term = get_term_by( 'slug', 'uncategorized', 'product_cat' );
|
||||
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
|
||||
|
|
|
@ -87,6 +87,8 @@ class WC_Tests_API_Reports_Coupons_Stats extends WC_REST_Unit_Test_Case {
|
|||
$order_2c->set_date_created( $time );
|
||||
$order_2c->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$request = new WP_REST_Request( 'GET', $this->endpoint );
|
||||
$request->set_query_params(
|
||||
array(
|
||||
|
|
|
@ -82,6 +82,8 @@ class WC_Tests_API_Reports_Coupons extends WC_REST_Unit_Test_Case {
|
|||
$order_2c->calculate_totals();
|
||||
$order_2c->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
|
||||
$coupon_reports = $response->get_data();
|
||||
|
||||
|
|
|
@ -126,6 +126,8 @@ class WC_Tests_API_Reports_Customers_Stats extends WC_REST_Unit_Test_Case {
|
|||
$order->set_total( 9.12 );
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$request = new WP_REST_Request( 'GET', $this->endpoint );
|
||||
$response = $this->server->dispatch( $request );
|
||||
$reports = $response->get_data();
|
||||
|
|
|
@ -134,6 +134,8 @@ class WC_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
|
|||
$order->set_total( 100 );
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$request = new WP_REST_Request( 'GET', $this->endpoint );
|
||||
$request->set_query_params(
|
||||
array(
|
||||
|
|
|
@ -67,6 +67,8 @@ class WC_Tests_API_Reports_Orders extends WC_REST_Unit_Test_Case {
|
|||
$order->set_total( 100 ); // $25 x 4.
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$expected_customer_id = WC_Admin_Reports_Customers_Data_Store::get_customer_id_by_user_id( 1 );
|
||||
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
|
||||
|
|
|
@ -84,6 +84,8 @@ class WC_Tests_API_Reports_Performance_Indicators extends WC_REST_Unit_Test_Case
|
|||
$object->set_user_ip_address( '1.2.3.4' );
|
||||
$object->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$time = time();
|
||||
$request = new WP_REST_Request( 'GET', $this->endpoint );
|
||||
$request->set_query_params(
|
||||
|
|
|
@ -71,6 +71,8 @@ class WC_Tests_API_Reports_Products_Stats extends WC_REST_Unit_Test_Case {
|
|||
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$request = new WP_REST_Request( 'GET', $this->endpoint );
|
||||
$request->set_query_params(
|
||||
array(
|
||||
|
|
|
@ -67,6 +67,8 @@ class WC_Tests_API_Reports_Products extends WC_REST_Unit_Test_Case {
|
|||
$order->set_total( 100 ); // $25 x 4.
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
|
||||
$reports = $response->get_data();
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ class WC_Tests_API_Reports_Taxes extends WC_REST_Unit_Test_Case {
|
|||
)
|
||||
);
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
|
||||
$reports = $response->get_data();
|
||||
|
||||
|
|
|
@ -65,6 +65,8 @@ class WC_Tests_API_Reports_Variations extends WC_REST_Unit_Test_Case {
|
|||
$order->set_total( 100 ); // $25 x 4.
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', $this->endpoint ) );
|
||||
$reports = $response->get_data();
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ class WC_Tests_Reports_Regenerate_Batching extends WC_REST_Unit_Test_Case {
|
|||
// insert a blocking job.
|
||||
WC_Admin_Api_Init::queue()->schedule_single( time(), 'blocking_job', array( 'stuff' ) );
|
||||
// queue an action that depends on blocking job.
|
||||
WC_Admin_Api_Init::queue_dependent_action( 'dependent_action', 'blocking_job' );
|
||||
WC_Admin_Api_Init::queue_dependent_action( 'dependent_action', array(), 'blocking_job' );
|
||||
// verify that the action was properly blocked.
|
||||
$this->assertEmpty(
|
||||
WC_Admin_Api_Init::queue()->search(
|
||||
|
@ -151,13 +151,13 @@ class WC_Tests_Reports_Regenerate_Batching extends WC_REST_Unit_Test_Case {
|
|||
WC_Admin_Api_Init::queue()->search(
|
||||
array(
|
||||
'hook' => WC_Admin_Api_Init::QUEUE_DEPEDENT_ACTION,
|
||||
'args' => array( 'dependent_action', 'blocking_job' ),
|
||||
'args' => array( 'dependent_action', array(), 'blocking_job' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// queue an action that isn't blocked.
|
||||
WC_Admin_Api_Init::queue_dependent_action( 'another_dependent_action', 'nonexistant_blocking_job' );
|
||||
WC_Admin_Api_Init::queue_dependent_action( 'another_dependent_action', array(), 'nonexistant_blocking_job' );
|
||||
// verify that the dependent action was queued.
|
||||
$this->assertCount(
|
||||
1,
|
||||
|
@ -172,7 +172,7 @@ class WC_Tests_Reports_Regenerate_Batching extends WC_REST_Unit_Test_Case {
|
|||
WC_Admin_Api_Init::queue()->search(
|
||||
array(
|
||||
'hook' => WC_Admin_Api_Init::QUEUE_DEPEDENT_ACTION,
|
||||
'args' => array( 'another_dependent_action', 'nonexistant_blocking_job' ),
|
||||
'args' => array( 'another_dependent_action', array(), 'nonexistant_blocking_job' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -123,3 +123,4 @@ wc_test_includes();
|
|||
require_once dirname( __FILE__ ) . '/framework/helpers/class-wc-helper-reports.php';
|
||||
require_once dirname( __FILE__ ) . '/framework/helpers/class-wc-helper-admin-notes.php';
|
||||
require_once dirname( __FILE__ ) . '/framework/helpers/class-wc-test-action-queue.php';
|
||||
require_once dirname( __FILE__ ) . '/framework/helpers/class-wc-helper-queue.php';
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* Helper code for wc-admin unit tests.
|
||||
*
|
||||
* @package WooCommerce\Tests\Framework\Helpers
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WC_Helper_Queue.
|
||||
*
|
||||
* This helper class should ONLY be used for unit tests!.
|
||||
*/
|
||||
class WC_Helper_Queue {
|
||||
/**
|
||||
* Run all pending queued actions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function run_all_pending() {
|
||||
$jobs = WC()->queue()->search(
|
||||
array(
|
||||
'per_page' => -1,
|
||||
'status' => 'pending',
|
||||
'claimed' => false,
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $jobs as $job ) {
|
||||
$job->execute();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -54,6 +54,8 @@ class WC_Tests_Reports_Coupons_Stats extends WC_Unit_Test_Case {
|
|||
$order_2c->calculate_totals();
|
||||
$order_2c->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Coupons_Stats_Data_Store();
|
||||
$start_time = date( 'Y-m-d 00:00:00', $order->get_date_created()->getOffsetTimestamp() );
|
||||
$end_time = date( 'Y-m-d 23:59:59', $order->get_date_created()->getOffsetTimestamp() );
|
||||
|
|
|
@ -54,6 +54,8 @@ class WC_Tests_Reports_Coupons extends WC_Unit_Test_Case {
|
|||
$order_2c->calculate_totals();
|
||||
$order_2c->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Coupons_Data_Store();
|
||||
$start_time = date( 'Y-m-d 00:00:00', $order->get_date_created()->getOffsetTimestamp() );
|
||||
$end_time = date( 'Y-m-d 23:59:59', $order->get_date_created()->getOffsetTimestamp() );
|
||||
|
|
|
@ -41,6 +41,8 @@ class WC_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
|
|||
)
|
||||
);
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Orders_Stats_Data_Store();
|
||||
|
||||
$start_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
|
||||
|
@ -176,10 +178,13 @@ class WC_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
|
|||
$order->set_shipping_total( 0 );
|
||||
$order->set_cart_tax( 0 );
|
||||
$order->save();
|
||||
|
||||
// Wait one second to avoid potentially ambiguous new/returning customer.
|
||||
sleep( 1 );
|
||||
}
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Orders_Stats_Data_Store();
|
||||
|
||||
$start_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
|
||||
|
@ -203,8 +208,8 @@ class WC_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
|
|||
'taxes' => 0,
|
||||
'shipping' => 0,
|
||||
'net_revenue' => 100,
|
||||
'num_returning_customers' => 0,
|
||||
'num_new_customers' => 1,
|
||||
'num_returning_customers' => 1,
|
||||
'num_new_customers' => 0,
|
||||
'products' => 1,
|
||||
'segments' => array(),
|
||||
),
|
||||
|
@ -226,8 +231,8 @@ class WC_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
|
|||
'num_items_sold' => 4,
|
||||
'avg_items_per_order' => 4,
|
||||
'avg_order_value' => 100,
|
||||
'num_returning_customers' => 0,
|
||||
'num_new_customers' => 1,
|
||||
'num_returning_customers' => 1,
|
||||
'num_new_customers' => 0,
|
||||
'segments' => array(),
|
||||
),
|
||||
),
|
||||
|
@ -483,6 +488,8 @@ class WC_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
|
|||
}
|
||||
}
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Orders_Stats_Data_Store();
|
||||
|
||||
// Tests for before & after set to current hour.
|
||||
|
@ -1697,6 +1704,8 @@ class WC_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
|
|||
$returning_order->set_date_created( $order_1_time + 1 ); // This is guaranteed to belong to the same hour by the adjustment to $order_1_time.
|
||||
$returning_order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$query_args = array(
|
||||
'after' => $current_hour_start->format( WC_Admin_Reports_Interval::$sql_datetime_format ), // I don't think this makes sense.... date( 'Y-m-d H:i:s', $orders[0]->get_date_created()->getOffsetTimestamp() + 1 ), // Date after initial order to get a returning customer.
|
||||
'before' => $current_hour_end->format( WC_Admin_Reports_Interval::$sql_datetime_format ),
|
||||
|
@ -3324,6 +3333,8 @@ class WC_Tests_Reports_Orders_Stats extends WC_Unit_Test_Case {
|
|||
$order_2->calculate_totals();
|
||||
$order_2->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Orders_Stats_Data_Store();
|
||||
|
||||
// Tests for before & after set to current hour.
|
||||
|
|
|
@ -38,6 +38,8 @@ class WC_Tests_Reports_Products extends WC_Unit_Test_Case {
|
|||
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Products_Data_Store();
|
||||
$start_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
|
||||
$end_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() + HOUR_IN_SECONDS );
|
||||
|
@ -113,6 +115,8 @@ class WC_Tests_Reports_Products extends WC_Unit_Test_Case {
|
|||
$order_2->set_date_created( $date_created_2 );
|
||||
$order_2->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Products_Data_Store();
|
||||
$start_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
|
||||
$end_time = date( 'Y-m-d H:00:00', $order_2->get_date_created()->getOffsetTimestamp() + HOUR_IN_SECONDS );
|
||||
|
@ -211,6 +215,9 @@ class WC_Tests_Reports_Products extends WC_Unit_Test_Case {
|
|||
$order->set_shipping_tax( 2 );
|
||||
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Products_Data_Store();
|
||||
$start_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
|
||||
$end_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() + HOUR_IN_SECONDS );
|
||||
|
@ -289,6 +296,8 @@ class WC_Tests_Reports_Products extends WC_Unit_Test_Case {
|
|||
break;
|
||||
}
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Products_Data_Store();
|
||||
$start_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
|
||||
$end_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() + HOUR_IN_SECONDS );
|
||||
|
|
|
@ -37,6 +37,8 @@ class WC_Admin_Tests_Reports_Revenue_Stats extends WC_Unit_Test_Case {
|
|||
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
// /reports/revenue/stats is mapped to Orders_Data_Store.
|
||||
$data_store = new WC_Admin_Reports_Orders_Stats_Data_Store();
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ class WC_Tests_Reports_Variations extends WC_Unit_Test_Case {
|
|||
$order->set_status( 'completed' );
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Variations_Data_Store();
|
||||
$start_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
|
||||
$end_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() + HOUR_IN_SECONDS );
|
||||
|
@ -106,6 +108,8 @@ class WC_Tests_Reports_Variations extends WC_Unit_Test_Case {
|
|||
$order->set_status( 'completed' );
|
||||
$order->save();
|
||||
|
||||
WC_Helper_Queue::run_all_pending();
|
||||
|
||||
$data_store = new WC_Admin_Reports_Variations_Data_Store();
|
||||
$start_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
|
||||
$end_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() + HOUR_IN_SECONDS );
|
||||
|
|
Loading…
Reference in New Issue