Stock reports
This commit is contained in:
parent
225f770cab
commit
aa41255596
|
@ -113,8 +113,20 @@ class WC_Admin_Reports {
|
|||
'stock' => array(
|
||||
'title' => __( 'Stock', 'woocommerce' ),
|
||||
'reports' => array(
|
||||
"stock" => array(
|
||||
'title' => __( 'Stock', 'woocommerce' ),
|
||||
"low_in_stock" => array(
|
||||
'title' => __( 'Low in stock', 'woocommerce' ),
|
||||
'description' => '',
|
||||
'hide_title' => true,
|
||||
'callback' => array( $this, 'get_report' )
|
||||
),
|
||||
"out_of_stock" => array(
|
||||
'title' => __( 'Out of stock', 'woocommerce' ),
|
||||
'description' => '',
|
||||
'hide_title' => true,
|
||||
'callback' => array( $this, 'get_report' )
|
||||
),
|
||||
"most_stocked" => array(
|
||||
'title' => __( 'Most Stocked', 'woocommerce' ),
|
||||
'description' => '',
|
||||
'hide_title' => true,
|
||||
'callback' => array( $this, 'get_report' )
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) )
|
||||
exit; // Exit if accessed directly
|
||||
|
||||
if ( ! class_exists( 'WC_Report_Stock' ) )
|
||||
require_once( 'class-wc-report-stock.php' );
|
||||
|
||||
/**
|
||||
* WC_Report_Low_In_Stock class
|
||||
*
|
||||
* @extends WC_Report_Stock
|
||||
*/
|
||||
class WC_Report_Low_In_Stock extends WC_Report_Stock {
|
||||
|
||||
/**
|
||||
* No items found text
|
||||
*/
|
||||
public function no_items() {
|
||||
_e( 'No low in stock products found.', 'woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Products matching stock criteria
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function get_items( $current_page, $per_page ) {
|
||||
global $wpdb;
|
||||
|
||||
$this->max_items = 0;
|
||||
$this->items = array();
|
||||
|
||||
// Get products using a query - this is too advanced for get_posts :(
|
||||
$stock = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
|
||||
$nostock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );
|
||||
|
||||
$query_from = "FROM {$wpdb->posts} as posts
|
||||
INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id
|
||||
INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id
|
||||
WHERE 1=1
|
||||
AND posts.post_type IN ('product', 'product_variation')
|
||||
AND posts.post_status = 'publish'
|
||||
AND (
|
||||
postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$stock}' AND CAST(postmeta.meta_value AS SIGNED) > '{$nostock}' AND postmeta.meta_value != ''
|
||||
)
|
||||
AND (
|
||||
( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' )
|
||||
)
|
||||
";
|
||||
|
||||
$this->items = $wpdb->get_results( $wpdb->prepare( "SELECT posts.ID as id, posts.post_parent as parent {$query_from} GROUP BY posts.ID ORDER BY posts.post_title DESC LIMIT %d, %d;", ( $current_page - 1 ) * $per_page, $per_page ) );
|
||||
$this->max_items = $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) )
|
||||
exit; // Exit if accessed directly
|
||||
|
||||
if ( ! class_exists( 'WC_Report_Stock' ) )
|
||||
require_once( 'class-wc-report-stock.php' );
|
||||
|
||||
/**
|
||||
* WC_Report_Most_Stocked class
|
||||
*
|
||||
* @extends WC_Report_Stock
|
||||
*/
|
||||
class WC_Report_Most_Stocked extends WC_Report_Stock {
|
||||
|
||||
/**
|
||||
* Get Products matching stock criteria
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function get_items( $current_page, $per_page ) {
|
||||
global $wpdb;
|
||||
|
||||
$this->max_items = 0;
|
||||
$this->items = array();
|
||||
|
||||
// Get products using a query - this is too advanced for get_posts :(
|
||||
$stock = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 0 ) );
|
||||
|
||||
$query_from = "FROM {$wpdb->posts} as posts
|
||||
INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id
|
||||
INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id
|
||||
WHERE 1=1
|
||||
AND posts.post_type IN ('product', 'product_variation')
|
||||
AND posts.post_status = 'publish'
|
||||
AND (
|
||||
postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) > '{$stock}' AND postmeta.meta_value != ''
|
||||
)
|
||||
AND (
|
||||
( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' )
|
||||
)
|
||||
";
|
||||
|
||||
$this->items = $wpdb->get_results( $wpdb->prepare( "SELECT posts.ID as id, posts.post_parent as parent {$query_from} GROUP BY posts.ID ORDER BY CAST(postmeta.meta_value AS SIGNED) DESC LIMIT %d, %d;", ( $current_page - 1 ) * $per_page, $per_page ) );
|
||||
$this->max_items = $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) )
|
||||
exit; // Exit if accessed directly
|
||||
|
||||
if ( ! class_exists( 'WC_Report_Stock' ) )
|
||||
require_once( 'class-wc-report-stock.php' );
|
||||
|
||||
/**
|
||||
* WC_Report_Out_Of_Stock class
|
||||
*
|
||||
* @extends WC_Report_Stock
|
||||
*/
|
||||
class WC_Report_Out_Of_Stock extends WC_Report_Stock {
|
||||
|
||||
/**
|
||||
* No items found text
|
||||
*/
|
||||
public function no_items() {
|
||||
_e( 'No out of stock products found.', 'woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Products matching stock criteria
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function get_items( $current_page, $per_page ) {
|
||||
global $wpdb;
|
||||
|
||||
$this->max_items = 0;
|
||||
$this->items = array();
|
||||
|
||||
// Get products using a query - this is too advanced for get_posts :(
|
||||
$stock = absint( max( get_option( 'woocommerce_notify_no_stock_amount' ), 0 ) );
|
||||
|
||||
$query_from = "FROM {$wpdb->posts} as posts
|
||||
INNER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id
|
||||
INNER JOIN {$wpdb->postmeta} AS postmeta2 ON posts.ID = postmeta2.post_id
|
||||
WHERE 1=1
|
||||
AND posts.post_type IN ('product', 'product_variation')
|
||||
AND posts.post_status = 'publish'
|
||||
AND (
|
||||
postmeta.meta_key = '_stock' AND CAST(postmeta.meta_value AS SIGNED) <= '{$stock}' AND postmeta.meta_value != ''
|
||||
)
|
||||
AND (
|
||||
( postmeta2.meta_key = '_manage_stock' AND postmeta2.meta_value = 'yes' ) OR ( posts.post_type = 'product_variation' )
|
||||
)
|
||||
";
|
||||
|
||||
$this->items = $wpdb->get_results( $wpdb->prepare( "SELECT posts.ID as id, posts.post_parent as parent {$query_from} GROUP BY posts.ID ORDER BY posts.post_title DESC LIMIT %d, %d;", ( $current_page - 1 ) * $per_page, $per_page ) );
|
||||
$this->max_items = $wpdb->get_var( "SELECT COUNT( DISTINCT posts.ID ) {$query_from};" );
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ class WC_Report_Stock extends WP_List_Table {
|
|||
*
|
||||
* @access public
|
||||
*/
|
||||
function __construct(){
|
||||
public function __construct(){
|
||||
parent::__construct( array(
|
||||
'singular' => __( 'Stock', 'woocommerce' ),
|
||||
'plural' => __( 'Stock', 'woocommerce' ),
|
||||
|
@ -23,10 +23,20 @@ class WC_Report_Stock extends WP_List_Table {
|
|||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* No items found text
|
||||
*/
|
||||
public function no_items() {
|
||||
_e( 'No products found.', 'woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't need this
|
||||
*/
|
||||
function display_tablenav() {}
|
||||
public function display_tablenav( $position ) {
|
||||
if ( $position != 'top' )
|
||||
parent::display_tablenav( $position );
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the report
|
||||
|
@ -42,25 +52,78 @@ class WC_Report_Stock extends WP_List_Table {
|
|||
* column_default function.
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $user
|
||||
* @param mixed $item
|
||||
* @param mixed $column_name
|
||||
*/
|
||||
function column_default( $product_id, $column_name ) {
|
||||
function column_default( $item, $column_name ) {
|
||||
global $woocommerce, $wpdb, $product;
|
||||
|
||||
if ( ! $product || $product->id !== $product_id )
|
||||
$product = get_product( $product_id );
|
||||
if ( ! $product || $product->id !== $item->id )
|
||||
$product = get_product( $item->id );
|
||||
|
||||
switch( $column_name ) {
|
||||
case 'stock_status' :
|
||||
|
||||
break;
|
||||
case 'product' :
|
||||
if ( $sku = $product->get_sku() )
|
||||
echo $sku . ' - ';
|
||||
|
||||
echo $product->get_title();
|
||||
|
||||
// Get variation data
|
||||
if ( $product->is_type( 'variation' ) ) {
|
||||
$list_attributes = array();
|
||||
$attributes = $product->get_variation_attributes();
|
||||
|
||||
foreach ( $attributes as $name => $attribute ) {
|
||||
$list_attributes[] = $woocommerce->get_helper( 'attribute' )->attribute_label( str_replace( 'attribute_', '', $name ) ) . ': <strong>' . $attribute . '</strong>';
|
||||
}
|
||||
|
||||
echo '<div class="description">' . implode( ', ', $list_attributes ) . '</div>';
|
||||
}
|
||||
break;
|
||||
case 'parent' :
|
||||
if ( $item->parent )
|
||||
echo get_the_title( $item->parent );
|
||||
else
|
||||
echo '-';
|
||||
break;
|
||||
case 'stock_status' :
|
||||
if ( $product->is_in_stock() ) {
|
||||
echo '<mark class="instock">' . __( 'In stock', 'woocommerce' ) . '</mark>';
|
||||
} else {
|
||||
echo '<mark class="outofstock">' . __( 'Out of stock', 'woocommerce' ) . '</mark>';
|
||||
}
|
||||
break;
|
||||
case 'stock_level' :
|
||||
echo $product->get_stock_quantity();
|
||||
break;
|
||||
case 'wc_actions' :
|
||||
?><p>
|
||||
<?php
|
||||
$actions = array();
|
||||
$action_id = $product->is_type( 'variation' ) ? $item->parent : $item->id;
|
||||
|
||||
$actions['edit'] = array(
|
||||
'url' => admin_url( 'post.php?post=' . $action_id . '&action=edit' ),
|
||||
'name' => __( 'Edit', 'woocommerce' ),
|
||||
'action' => "edit"
|
||||
);
|
||||
|
||||
if ( $product->is_visible() )
|
||||
$actions['view'] = array(
|
||||
'url' => get_permalink( $action_id ),
|
||||
'name' => __( 'View', 'woocommerce' ),
|
||||
'action' => "view"
|
||||
);
|
||||
|
||||
$actions = apply_filters( 'woocommerce_admin_stock_report_product_actions', $actions, $product );
|
||||
|
||||
foreach ( $actions as $action ) {
|
||||
$image = ( isset( $action['image_url'] ) ) ? $action['image_url'] : $woocommerce->plugin_url() . '/assets/images/icons/' . $action['action'] . '.png';
|
||||
printf( '<a class="button tips" href="%s" data-tip="%s"><img src="%s" alt="%s" width="14" /></a>', esc_url( $action['url'] ), esc_attr( $action['name'] ), esc_attr( $image ), esc_attr( $action['name'] ) );
|
||||
}
|
||||
?>
|
||||
</p><?php
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,9 +134,11 @@ class WC_Report_Stock extends WP_List_Table {
|
|||
*/
|
||||
function get_columns(){
|
||||
$columns = array(
|
||||
'stock_status' => __( 'Stock Status', 'woocommerce' ),
|
||||
'product' => __( 'Product', 'woocommerce' ),
|
||||
'stock_level' => __( 'Units in stock', 'woocommerce' ),
|
||||
'product' => __( 'Product', 'woocommerce' ),
|
||||
'parent' => __( 'Parent', 'woocommerce' ),
|
||||
'stock_level' => __( 'Units in stock', 'woocommerce' ),
|
||||
'stock_status' => __( 'Stock status', 'woocommerce' ),
|
||||
'wc_actions' => __( 'Actions', 'woocommerce' ),
|
||||
);
|
||||
|
||||
return $columns;
|
||||
|
@ -85,56 +150,19 @@ class WC_Report_Stock extends WP_List_Table {
|
|||
* @access public
|
||||
*/
|
||||
public function prepare_items() {
|
||||
global $wpdb;
|
||||
|
||||
$current_page = 1;
|
||||
$per_page = 999999999999;
|
||||
|
||||
/**
|
||||
* Init column headers
|
||||
*/
|
||||
$this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );
|
||||
$current_page = absint( $this->get_pagenum() );
|
||||
$per_page = 20;
|
||||
|
||||
$this->get_items( $current_page, $per_page );
|
||||
|
||||
/**
|
||||
* Get Products
|
||||
* Pagination
|
||||
*/
|
||||
// Low/No stock lists
|
||||
$lowstockamount = get_option('woocommerce_notify_low_stock_amount');
|
||||
if (!is_numeric($lowstockamount)) $lowstockamount = 1;
|
||||
|
||||
$nostockamount = get_option('woocommerce_notify_no_stock_amount');
|
||||
if (!is_numeric($nostockamount)) $nostockamount = 0;
|
||||
|
||||
// Get low in stock simple/downloadable/virtual products. Grouped don't have stock. Variations need a separate query.
|
||||
$args = array(
|
||||
'post_type' => 'product',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => -1,
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => '_manage_stock',
|
||||
'value' => 'yes'
|
||||
),
|
||||
array(
|
||||
'key' => '_stock',
|
||||
'value' => $lowstockamount,
|
||||
'compare' => '<=',
|
||||
'type' => 'NUMERIC'
|
||||
)
|
||||
),
|
||||
'tax_query' => array(
|
||||
array(
|
||||
'taxonomy' => 'product_type',
|
||||
'field' => 'name',
|
||||
'terms' => array('simple'),
|
||||
'operator' => 'IN'
|
||||
)
|
||||
),
|
||||
'fields' => 'id=>parent'
|
||||
);
|
||||
|
||||
$low_stock_products = array_flip( (array) get_posts($args) );
|
||||
|
||||
$this->items = $low_stock_products;
|
||||
$this->set_pagination_args( array(
|
||||
'total_items' => $this->max_items,
|
||||
'per_page' => $per_page,
|
||||
'total_pages' => ceil( $this->max_items / $per_page )
|
||||
) );
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -1057,7 +1057,7 @@ ul.wc_coupon_list_block {
|
|||
.column-last_order {
|
||||
width: 11%;
|
||||
}
|
||||
.column-order_actions, .column-user_actions {
|
||||
.column-order_actions, .column-user_actions, .column-wc_actions {
|
||||
width:110px;
|
||||
a.button {
|
||||
float:left;
|
||||
|
@ -2586,6 +2586,15 @@ img.ui-datepicker-trigger { vertical-align: middle; margin-top: -1px; cursor: po
|
|||
overflow: hidden;
|
||||
zoom: 1;
|
||||
}
|
||||
.widefat {
|
||||
td {
|
||||
vertical-align: top;
|
||||
padding: 7px 7px;
|
||||
.description {
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.postbox {
|
||||
&:after {
|
||||
content: ".";
|
||||
|
|
Loading…
Reference in New Issue