Skip to content

Commit

Permalink
Implement stock stats report to filter by seller
Browse files Browse the repository at this point in the history
  • Loading branch information
mrabbani committed Aug 30, 2024
1 parent 2c05bf0 commit 30bc3c4
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 1 deletion.
2 changes: 1 addition & 1 deletion includes/Analytics/Reports/BaseQueryFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ protected function add_where_subquery_for_seller_filter( array $clauses ): array
*
* @return int
*/
protected function get_seller_id() {
public function get_seller_id() {
if ( ! is_user_logged_in() ) {
return 0;
}
Expand Down
166 changes: 166 additions & 0 deletions includes/Analytics/Reports/Stock/Stats/WcDataStore.php
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 tests/php/src/Analytics/Reports/Stock/Stats/QueryFilterTest.php
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'] );
}
}

0 comments on commit 30bc3c4

Please sign in to comment.