-
Notifications
You must be signed in to change notification settings - Fork 200
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement stock stats report to filter by seller
- Loading branch information
Showing
3 changed files
with
220 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
<?php | ||
|
||
namespace WeDevs\Dokan\Analytics\Reports\Stock\Stats; | ||
|
||
use Automattic\WooCommerce\Admin\API\Reports\Stock\Stats\DataStore as StockStatsDataStore; | ||
|
||
class WcDataStore extends StockStatsDataStore { | ||
/** | ||
* Get stock counts for the whole store. | ||
* | ||
* @param array $query Not used for the stock stats data store, but needed for the interface. | ||
* @return array Array of counts. | ||
*/ | ||
public function get_data( $query ) { | ||
$seller_id = $this->get_seller_id(); | ||
|
||
$report_data = array(); | ||
$cache_expire = DAY_IN_SECONDS * 30; | ||
// Set seller specific key. | ||
$low_stock_transient_name = 'wc_admin_stock_count_lowstock' . $seller_id; | ||
$low_stock_count = get_transient( $low_stock_transient_name ); | ||
|
||
if ( false === $low_stock_count ) { | ||
$low_stock_count = $this->get_low_stock_count(); | ||
set_transient( $low_stock_transient_name, $low_stock_count, $cache_expire ); | ||
} else { | ||
$low_stock_count = intval( $low_stock_count ); | ||
} | ||
|
||
$report_data['lowstock'] = $low_stock_count; | ||
|
||
$status_options = wc_get_product_stock_status_options(); | ||
foreach ( $status_options as $status => $label ) { | ||
// Set seller specific key. | ||
$transient_name = 'wc_admin_stock_count_' . $status . $seller_id; | ||
$count = get_transient( $transient_name ); | ||
if ( false === $count ) { | ||
$count = $this->get_count( $status ); | ||
set_transient( $transient_name, $count, $cache_expire ); | ||
} else { | ||
$count = intval( $count ); | ||
} | ||
$report_data[ $status ] = $count; | ||
} | ||
|
||
// Set seller specific key. | ||
$product_count_transient_name = 'wc_admin_product_count' . $seller_id; | ||
$product_count = get_transient( $product_count_transient_name ); | ||
if ( false === $product_count ) { | ||
$product_count = $this->get_product_count(); | ||
set_transient( $product_count_transient_name, $product_count, $cache_expire ); | ||
} else { | ||
$product_count = intval( $product_count ); | ||
} | ||
$report_data['products'] = $product_count; | ||
return $report_data; | ||
} | ||
|
||
/** | ||
* Get low stock count (products with stock < low stock amount, but greater than no stock amount). | ||
* | ||
* @return int Low stock count. | ||
*/ | ||
protected function get_low_stock_count() { | ||
global $wpdb; | ||
|
||
$no_stock_amount = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) ); | ||
$low_stock_amount = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) ); | ||
$seller_where = $this->get_seller_where_query(); | ||
|
||
return (int) $wpdb->get_var( | ||
$wpdb->prepare( | ||
" | ||
SELECT count( DISTINCT posts.ID ) FROM {$wpdb->posts} posts | ||
LEFT JOIN {$wpdb->wc_product_meta_lookup} wc_product_meta_lookup ON posts.ID = wc_product_meta_lookup.product_id | ||
LEFT JOIN {$wpdb->postmeta} low_stock_amount_meta ON posts.ID = low_stock_amount_meta.post_id AND low_stock_amount_meta.meta_key = '_low_stock_amount' | ||
WHERE posts.post_type IN ( 'product', 'product_variation' ) | ||
AND wc_product_meta_lookup.stock_quantity IS NOT NULL | ||
AND wc_product_meta_lookup.stock_status = 'instock' | ||
AND ( | ||
( | ||
low_stock_amount_meta.meta_value > '' | ||
AND wc_product_meta_lookup.stock_quantity <= CAST(low_stock_amount_meta.meta_value AS SIGNED) | ||
AND wc_product_meta_lookup.stock_quantity > %d | ||
) | ||
OR ( | ||
( | ||
low_stock_amount_meta.meta_value IS NULL OR low_stock_amount_meta.meta_value <= '' | ||
) | ||
AND wc_product_meta_lookup.stock_quantity <= %d | ||
AND wc_product_meta_lookup.stock_quantity > %d | ||
) | ||
) | ||
{$seller_where} | ||
", | ||
$no_stock_amount, | ||
$low_stock_amount, | ||
$no_stock_amount | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Get count for the passed in stock status. | ||
* | ||
* @param string $status Status slug. | ||
* @return int Count. | ||
*/ | ||
protected function get_count( $status ) { | ||
global $wpdb; | ||
|
||
$seller_where = $this->get_seller_where_query(); | ||
|
||
return (int) $wpdb->get_var( | ||
$wpdb->prepare(// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared | ||
" | ||
SELECT count( DISTINCT posts.ID ) FROM {$wpdb->posts} posts | ||
LEFT JOIN {$wpdb->wc_product_meta_lookup} wc_product_meta_lookup ON posts.ID = wc_product_meta_lookup.product_id | ||
WHERE posts.post_type IN ( 'product', 'product_variation' ) | ||
AND wc_product_meta_lookup.stock_status = %s {$seller_where} | ||
", | ||
$status | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Get product count for the store. | ||
* | ||
* @return int Product count. | ||
*/ | ||
protected function get_product_count() { | ||
$query_args = array(); | ||
$query_args['post_type'] = array( 'product', 'product_variation' ); | ||
$seller_id = $this->get_seller_id(); | ||
|
||
if ( $seller_id ) { | ||
$query_args['author'] = $seller_id; | ||
} | ||
|
||
$query = new \WP_Query(); | ||
$query->query( $query_args ); | ||
|
||
return intval( $query->found_posts ); | ||
} | ||
|
||
protected function get_seller_id(): int { | ||
return (int) dokan()->get_container()->get( \WeDevs\Dokan\Analytics\Reports\Stock\QueryFilter::class )->get_seller_id(); | ||
} | ||
|
||
protected function get_seller_where_query() { | ||
$seller_id = $this->get_seller_id(); | ||
$where = ''; | ||
|
||
if ( $seller_id ) { | ||
global $wpdb; | ||
|
||
$where = $wpdb->prepare( | ||
' AND posts.post_author = %d ', | ||
$seller_id | ||
); | ||
} | ||
|
||
return $where; | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
tests/php/src/Analytics/Reports/Stock/Stats/QueryFilterTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
|
||
namespace WeDevs\Dokan\Test\Analytics\Reports\Stock\Stats; | ||
|
||
use WeDevs\Dokan\Test\DokanTestCase; | ||
|
||
/** | ||
* @group analytics | ||
*/ | ||
class QueryFilterTest extends DokanTestCase { | ||
|
||
public function tests_stock_stats_report() { | ||
$seller1_prod_ids = $this->factory()->product | ||
->set_seller_id( $this->seller_id1 ) | ||
->create_many( 5 ); | ||
|
||
$seller2_prod_ids = $this->factory()->product | ||
->set_seller_id( $this->seller_id2 ) | ||
->create_many( 5 ); | ||
|
||
wp_set_current_user( $this->admin_id ); | ||
|
||
$query = new \Automattic\WooCommerce\Admin\API\Reports\Stock\Stats\Query(); | ||
|
||
$data = $query->get_data(); | ||
$total = count( $seller1_prod_ids ) + count( $seller2_prod_ids ); | ||
|
||
$this->assertEquals( $total, $data['instock'] ); | ||
$this->assertEquals( $total, $data['products'] ); | ||
} | ||
|
||
public function tests_stock_stats_report_by_seller_filter() { | ||
$seller1_prod_ids = $this->factory()->product | ||
->set_seller_id( $this->seller_id1 ) | ||
->create_many( 5 ); | ||
|
||
$seller2_prod_ids = $this->factory()->product | ||
->set_seller_id( $this->seller_id2 ) | ||
->create_many( 5 ); | ||
|
||
wp_set_current_user( $this->admin_id ); | ||
|
||
$_GET['sellers'] = $this->seller_id1; | ||
|
||
$query = new \Automattic\WooCommerce\Admin\API\Reports\Stock\Stats\Query(); | ||
|
||
$data = $query->get_data(); | ||
$total = count( $seller1_prod_ids ); | ||
|
||
$this->assertEquals( $total, $data['instock'] ); | ||
$this->assertEquals( $total, $data['products'] ); | ||
} | ||
} |