stock reports

This commit is contained in:
Mike Jolley 2011-09-20 11:30:21 +01:00
parent ade3f90a92
commit 4cb31cd969
4 changed files with 238 additions and 73 deletions

View File

@ -15,57 +15,7 @@ add_action('right_now_table_end', 'woocommerce_right_now');
function woocommerce_content_right_now() {
global $lowinstock, $outofstock, $woocommerce;
$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 = 1;
$outofstock = array();
$lowinstock = array();
$args = array(
'post_type' => array('product', 'product_variation'),
'post_status' => 'publish',
'ignore_sticky_posts' => 1,
'posts_per_page' => -1
);
$my_query = new WP_Query($args);
if ($my_query->have_posts()) : while ($my_query->have_posts()) : $my_query->the_post();
if ($my_query->post->post_type == 'product_variation') :
$parent = $my_query->post->post_parent;
$_product = &new woocommerce_product_variation( $my_query->post->ID );
else :
$parent = $my_query->post->ID;
$_product = &new woocommerce_product( $my_query->post->ID );
endif;
if (!$_product->managing_stock()) continue;
$thisitem = '<tr class="first">
<td class="first b"><a href="post.php?post='.$parent.'&action=edit">'.$_product->stock.'</a></td>
<td class="t"><a href="post.php?post='.$parent.'&action=edit">'.$my_query->post->post_title.'</a></td>
</tr>';
if ($_product->total_stock<=$nostockamount) :
$outofstock[] = $thisitem;
continue;
endif;
if ($_product->total_stock<=$lowstockamount) $lowinstock[] = $thisitem;
endwhile; endif;
wp_reset_query();
if (sizeof($lowinstock)==0) :
$lowinstock[] = '<tr><td colspan="2">'.__('No products are low in stock.', 'woothemes').'</td></tr>';
endif;
if (sizeof($outofstock)==0) :
$outofstock[] = '<tr><td colspan="2">'.__('No products are out of stock.', 'woothemes').'</td></tr>';
endif;
global $woocommerce;
?>
</table>
<p class="sub woocommerce_sub"><?php _e('Shop Content', 'woothemes'); ?></p>
@ -96,17 +46,11 @@ function woocommerce_content_right_now() {
?></a></td>
<td class="t"><a href="admin.php?page=attributes"><?php _e('Attribute taxonomies', 'woothemes'); ?></a></td>
</tr>
</table>
<p class="sub woocommerce_sub"><?php _e('Low in stock', 'woothemes'); ?></p>
<table>
<?php echo implode('', $lowinstock); ?>
<?php
}
function woocommerce_right_now() {
global $outofstock;
$woocommerce_orders = &new woocommerce_orders();
?>
</table>
@ -128,10 +72,6 @@ function woocommerce_right_now() {
<td class="b"><a href="edit.php?post_type=shop_order&shop_order_status=completed"><span class="total-count"><?php echo $woocommerce_orders->completed_count; ?></span></a></td>
<td class="last t"><a class="complete" href="edit.php?post_type=shop_order&shop_order_status=completed"><?php _e('Completed', 'woothemes'); ?></a></td>
</tr>
</table>
<p class="sub woocommerce_sub"><?php _e('Out of Stock/Backorders', 'woothemes'); ?></p>
<table>
<?php echo implode('', $outofstock); ?>
<?php
}

View File

@ -16,7 +16,8 @@ function woocommerce_reports() {
__('sales', 'woothemes') => array(
array(
'title' => __('Overview', 'woothemes'),
'description' => __('An overview of your sales/order data is shown below. For more detailed views, click on one of the above links.', 'woothemes'),
'description' => '',
'hide_title' => true,
'function' => 'woocommerce_sales_overview'
),
array(
@ -49,8 +50,17 @@ function woocommerce_reports() {
array(
'title' => __('Overview', 'woothemes'),
'description' => '',
'hide_title' => true,
'function' => 'woocommerce_customer_overview'
),
),
__('stock', 'woothemes') => array(
array(
'title' => __('Overview', 'woothemes'),
'description' => '',
'hide_title' => true,
'function' => 'woocommerce_stock_overview'
),
)
);
?>
@ -78,7 +88,7 @@ function woocommerce_reports() {
?></li></ul><br class="clear" /><?php endif; ?>
<?php if (isset($charts[$current_tab][$current_chart])) : ?>
<?php if (sizeof($charts[$current_tab])>1) : ?><h3><?php echo $charts[$current_tab][$current_chart]['title']; ?></h3>
<?php if (!isset($charts[$current_tab][$current_chart]['hide_title']) || $charts[$current_tab][$current_chart]['hide_title']!=true) : ?><h3><?php echo $charts[$current_tab][$current_chart]['title']; ?></h3>
<?php if ($charts[$current_tab][$current_chart]['description']) : ?><p><?php echo $charts[$current_tab][$current_chart]['description']; ?></p><?php endif; ?>
<?php endif; ?>
<?php
@ -1304,4 +1314,193 @@ function woocommerce_customer_overview() {
});
</script>
<?php
}
/**
* Stock overview
*/
function woocommerce_stock_overview() {
global $start_date, $end_date, $woocommerce, $wpdb;
$total_customers = 0;
$total_customer_sales = 0;
$total_guest_sales = 0;
$total_customer_orders = 0;
$total_guest_orders = 0;
$users_query = new WP_User_Query( array(
'fields' => array('user_registered'),
'role' => 'customer'
) );
$customers = $users_query->get_results();
$total_customers = (int) sizeof($customers);
$args = array(
'numberposts' => -1,
'orderby' => 'post_date',
'order' => 'DESC',
'post_type' => 'shop_order',
'post_status' => 'publish' ,
'suppress_filters' => false,
'tax_query' => array(
array(
'taxonomy' => 'shop_order_status',
'terms' => array('completed', 'processing', 'on-hold'),
'field' => 'slug',
'operator' => 'IN'
)
)
);
$orders = get_posts( $args );
foreach ($orders as $order) :
if (get_post_meta( $order->ID, '_customer_user', true )>0) :
$total_customer_sales += get_post_meta($order->ID, '_order_total', true);
$total_customer_orders++;
else :
$total_guest_sales += get_post_meta($order->ID, '_order_total', true);
$total_guest_orders++;
endif;
endforeach;
// 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;
$outofstock = array();
$lowinstock = array();
// 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' => 'slug',
'terms' => array('simple', 'downloadable', 'virtual'),
'operator' => 'IN'
)
)
);
$low_stock_products = (array) get_posts($args);
// Get low stock product variations
$args = array(
'post_type' => 'product_variation',
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'stock',
'value' => $lowstockamount,
'compare' => '<=',
'type' => 'NUMERIC'
),
array(
'key' => 'stock',
'value' => array('', false, null),
'compare' => 'NOT IN'
)
)
);
$low_stock_variations = (array) get_posts($args);
// Finally, get low stock variable products (where stock is set for the parent)
$args = array(
'post_type' => array('product'),
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'manage_stock',
'value' => 'yes'
),
array(
'key' => 'stock',
'value' => $lowstockamount,
'compare' => '<=',
'type' => 'NUMERIC'
)
),
'tax_query' => array(
array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => array('variable'),
'operator' => 'IN'
)
)
);
$low_stock_variable_products = (array) get_posts($args);
// Merge results
$low_in_stock = array_merge($low_stock_products, $low_stock_variations, $low_stock_variable_products);
?>
<div id="poststuff" class="woocommerce-reports-wrap halved">
<div class="woocommerce-reports-left">
<div class="postbox">
<h3><span><?php _e('Low stock', 'woothemes'); ?></span></h3>
<div class="inside">
<?php
if ($low_in_stock) :
echo '<ul class="stock_list">';
foreach ($low_in_stock as $product) :
$stock = get_post_meta($product->ID, 'stock', true);
if ($stock<=$nostockamount) continue;
echo '<li><a href="';
if ($product->post_type=='product') echo admin_url('post.php?post='.$product->ID.'&action=edit'); else echo admin_url('post.php?post='.$product->post_parent.'&action=edit');
echo '"><small>'.$stock.__(' in stock', 'woothemes').'</small> '.$product->post_title.'</a></li>';
endforeach;
echo '</ul>';
else :
echo '<p>'.__('No products are low in stock.', 'woothemes').'</p>';
endif;
?>
</div>
</div>
</div>
<div class="woocommerce-reports-right">
<div class="postbox">
<h3><span><?php _e('Out of stock', 'woothemes'); ?></span></h3>
<div class="inside">
<?php
if ($low_in_stock) :
echo '<ul class="stock_list">';
foreach ($low_in_stock as $product) :
$stock = get_post_meta($product->ID, 'stock', true);
if ($stock>$nostockamount) continue;
echo '<li><a href="';
if ($product->post_type=='product') echo admin_url('post.php?post='.$product->ID.'&action=edit'); else echo admin_url('post.php?post='.$product->post_parent.'&action=edit');
echo '"><small>'.$stock.__(' in stock', 'woothemes').'</small> '.$product->post_title.'</a></li>';
endforeach;
echo '</ul>';
else :
echo '<p>'.__('No products are out in stock.', 'woothemes').'</p>';
endif;
?>
</div>
</div>
</div>
</div>
<?php
}

View File

@ -73,14 +73,16 @@ table.wp-list-table .column-featured,table.wp-list-table .column-is_in_stock{tex
#dashboard_right_now .complete{color:green;}
#dashboard_right_now .t,#dashboard_right_now .t a{white-space:normal;}
#woocommmerce_dashboard_sales h3 a{float:right;margin-left:8px;}
ul.recent-orders li{overflow:hidden;zoom:1;border-bottom:#ECECEC 1px solid;padding:0 0 8px;margin:0 0 8px;}ul.recent-orders li .order-status{float:right;}
ul.recent-orders li small{color:#999;}
ul.recent-orders li .order-cost,ul.recent-orders li .order-customer{margin-left:8px;}
ul.recent-orders li .completed{color:green;}
ul.recent-orders li .on-hold{color:red;}
ul.recent-orders li .processing{color:#21759B;}
ul.recent-orders li .pending{color:#E66F00;}
ul.recent-orders li .refunded,ul.recent-orders li .cancelled{color:#999;}
ul.recent-orders li,ul.stock_list li{overflow:hidden;zoom:1;border-bottom:#ECECEC 1px solid;padding:0 0 8px;margin:0 0 8px;}ul.recent-orders li .order-status,ul.stock_list li .order-status{float:right;}
ul.recent-orders li small,ul.stock_list li small{color:#999;}
ul.recent-orders li .order-cost,ul.stock_list li .order-cost,ul.recent-orders li .order-customer,ul.stock_list li .order-customer{margin-left:8px;}
ul.recent-orders li .completed,ul.stock_list li .completed{color:green;}
ul.recent-orders li .on-hold,ul.stock_list li .on-hold{color:red;}
ul.recent-orders li .processing,ul.stock_list li .processing{color:#21759B;}
ul.recent-orders li .pending,ul.stock_list li .pending{color:#E66F00;}
ul.recent-orders li .refunded,ul.stock_list li .refunded,ul.recent-orders li .cancelled,ul.stock_list li .cancelled{color:#999;}
ul.recent-orders.stock_list small,ul.stock_list.stock_list small{float:right;}
ul.recent-orders.stock_list a,ul.stock_list.stock_list a{text-decoration:none;}
#woocommmerce_dashboard_recent_reviews li{line-height:1.5em;margin-bottom:12px;}
#woocommmerce_dashboard_recent_reviews h4.meta{line-height:1.4;margin:-0.2em 0 0 0;font-weight:normal;color:#999;}
#woocommmerce_dashboard_recent_reviews blockquote{padding:0;margin:0;}
@ -158,11 +160,14 @@ img.tips{padding:5px 0 0 0;}
#easyTooltip{padding:5px 10px;border:3px solid #3da5d5;background:#288ab7;color:#fff;font-size:12px;-moz-border-radius:4px;-webkit-border-radius:4px;-o-border-radius:4px;-khtml-border-radius:4px;border-radius:4px;max-width:300px;}
img.ui-datepicker-trigger{vertical-align:middle;margin-top:-1px;cursor:pointer;}
.woocommerce_options_panel img.ui-datepicker-trigger{float:left;margin-right:8px;margin-top:4px;margin-left:4px;}
.woocommerce-reports-wrap{margin-left:300px;padding-top:18px;}.woocommerce-reports-wrap .postbox h3{cursor:default !important;}
.woocommerce-reports-wrap{margin-left:300px;padding-top:18px;}.woocommerce-reports-wrap.halved{margin:0;overflow:hidden;zoom:1;}
.woocommerce-reports-wrap .postbox h3{cursor:default !important;}
.woocommerce-reports-wrap .postbox .stat{font-size:1.5em !important;font-weight:bold;text-align:center;}
.woocommerce-reports-wrap .postbox .chart{padding:16px;}
.woocommerce-reports-wrap .woocommerce-reports-main{float:left;min-width:100%;}
.woocommerce-reports-wrap .woocommerce-reports-sidebar{display:inline;width:281px;margin-left:-300px;clear:both;float:left;}
.woocommerce-reports-wrap .woocommerce-reports-left{width:49.5%;float:left;}
.woocommerce-reports-wrap .woocommerce-reports-right{width:49.5%;float:right;}
#tooltip{color:#fff;font-size:12px;-moz-border-radius:4px;-webkit-border-radius:4px;-o-border-radius:4px;-khtml-border-radius:4px;border-radius:4px;opacity:0.8;}
table.bar_chart{width:100%;}table.bar_chart thead th{text-align:left;color:#ccc;padding:6px 0;}
table.bar_chart tbody th{padding:6px 0;width:25%;text-align:left !important;font-weight:normal !important;border-bottom:1px solid #fee;}

View File

@ -393,7 +393,7 @@ table.wp-list-table {
}
}
ul.recent-orders {
ul.recent-orders, ul.stock_list {
li {
overflow: hidden;
zoom: 1;
@ -425,6 +425,14 @@ ul.recent-orders {
color: #999;
}
}
&.stock_list {
small {
float: right;
}
a {
text-decoration: none;
}
}
}
#woocommmerce_dashboard_recent_reviews {
li {
@ -842,6 +850,11 @@ img.ui-datepicker-trigger { vertical-align: middle; margin-top: -1px; cursor: po
.woocommerce-reports-wrap {
margin-left: 300px;
padding-top: 18px;
&.halved {
margin: 0;
overflow: hidden;
zoom: 1;
}
.postbox {
h3 {
cursor: default !important;
@ -866,6 +879,14 @@ img.ui-datepicker-trigger { vertical-align: middle; margin-top: -1px; cursor: po
clear: both;
float: left;
}
.woocommerce-reports-left {
width: 49.5%;
float: left;
}
.woocommerce-reports-right {
width: 49.5%;
float: right;
}
}
/* Chart tooltips */