Optimisations to monthly and product reports

This commit is contained in:
Mike Jolley 2012-05-11 00:51:31 +01:00
parent c39e2cff75
commit b6b2da9463
2 changed files with 115 additions and 108 deletions

View File

@ -1050,127 +1050,133 @@ function woocommerce_top_earners() {
*/
function woocommerce_product_sales() {
global $start_date, $end_date, $woocommerce;
global $wpdb, $woocommerce;
$chosen_product_id = (isset($_POST['product_id'])) ? $_POST['product_id'] : '';
$chosen_product_ids = ( isset( $_POST['product_ids'] ) ) ? (array) $_POST['product_ids'] : '';
if ($chosen_product_id) :
$start_date = date('Ym', strtotime( '-12 MONTHS', current_time('timestamp') )).'01';
$end_date = date('Ymd', current_time('timestamp'));
if ( $chosen_product_ids && is_array( $chosen_product_ids ) ) {
$start_date = date( 'Ym', strtotime( '-12 MONTHS', current_time('timestamp') ) ) . '01';
$end_date = date( 'Ymd', current_time( 'timestamp' ) );
$max_sales = $max_totals = 0;
$product_sales = $product_totals = array();
$start_date = strtotime($start_date);
$end_date = strtotime($end_date);
// Get titles and ID's related to product
$chosen_product_titles = array();
$children_ids = array();
// Get orders to display in widget
add_filter( 'posts_where', 'orders_within_range' );
foreach ( $chosen_product_ids as $product_id ) {
$children = (array) get_posts( 'post_parent=' . $product_id . '&fields=ids&post_status=any&numberposts=-1' );
$children_ids = $children_ids + $children;
$chosen_product_titles[] = get_the_title( $product_id );
}
// Get order items
$order_items = $wpdb->get_results("
SELECT meta.meta_value AS items, posts.post_date FROM {$wpdb->posts} AS posts
LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_id )
$args = array(
'numberposts' => -1,
'orderby' => 'post_date',
'order' => 'ASC',
'post_type' => 'shop_order',
'post_status' => 'publish' ,
'suppress_filters'=> 0,
'tax_query' => array(
array(
'taxonomy' => 'shop_order_status',
'terms' => array('completed', 'processing', 'on-hold'),
'field' => 'slug',
'operator' => 'IN'
)
)
);
$orders = get_posts( $args );
WHERE meta.meta_key = '_order_items'
AND posts.post_type = 'shop_order'
AND posts.post_status = 'publish'
AND tax.taxonomy = 'shop_order_status'
AND term.slug IN ('completed', 'processing', 'on-hold')
AND posts.post_date > date_sub( NOW(), INTERVAL 1 YEAR )
ORDER BY posts.post_date ASC
");
$max_sales = 0;
$max_totals = 0;
$product_sales = array();
$product_totals = array();
if ( $order_items ) {
// Get ID's related to product
$chosen_product = new WC_Product( $chosen_product_id );
$child_ids = $chosen_product->get_children();
if ($orders) :
foreach ($orders as $order) :
$date = date('Ym', strtotime( $order->post_date ));
$order_items = (array) get_post_meta( $order->ID, '_order_items', true );
foreach ($order_items as $item) :
if (isset($item['line_total'])) $row_cost = $item['line_total'];
elseif (isset($item['cost'])) $row_cost = $item['cost'] * $item['qty'];
else continue;
if ($item['id']!=$chosen_product_id && !in_array($item['id'], $child_ids)) continue;
$product_sales[$date] = isset($product_sales[$date]) ? $product_sales[$date] + $item['qty'] : $item['qty'];
$product_totals[$date] = isset($product_totals[$date]) ? $product_totals[$date] + $row_cost : $row_cost;
if ($product_sales[$date] > $max_sales) $max_sales = $product_sales[$date];
if ($product_totals[$date] > $max_totals) $max_totals = $product_totals[$date];
endforeach;
endforeach;
endif;
remove_filter( 'posts_where', 'orders_within_range' );
endif;
?>
<form method="post" action="">
<p><label for="from"><?php _e('Product:', 'woocommerce'); ?></label>
<select name="product_id" id="product_id">
<?php
echo '<option value="">'.__('Choose an product&hellip;', 'woocommerce').'</option>';
foreach ( $order_items as $order_item ) {
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'post_status' => 'publish',
'post_parent' => 0,
'order' => 'ASC',
'orderby' => 'title'
);
$products = get_posts( $args );
$date = date( 'Ym', strtotime( $order_item->post_date ) );
$items = maybe_unserialize( $order_item->items );
if ($products) foreach ($products as $product) :
foreach ( $items as $item ) {
if ( ! in_array( $item['id'], $chosen_product_ids ) && ! in_array( $item['id'], $children_ids ) )
continue;
$sku = get_post_meta($product->ID, '_sku', true);
if ( isset( $item['line_total'] ) ) $row_cost = $item['line_total'];
else $row_cost = $item['cost'] * $item['qty'];
if ($sku) $sku = ' SKU: '.$sku;
if ( ! $row_cost ) continue;
$product_sales[ $date ] = isset( $product_sales[ $date ] ) ? $product_sales[$date] + $item['qty'] : $item['qty'];
$product_totals[ $date ] = isset( $product_totals[ $date ] ) ? $product_totals[ $date ] + $row_cost : $row_cost;
echo '<option value="'.$product->ID.'" '.selected($chosen_product_id, $product->ID, false).'>'.$product->post_title.$sku.' (#'.$product->ID.''.$sku.')</option>';
if ( $product_sales[ $date ] > $max_sales ) $max_sales = $product_sales[ $date ];
if ( $product_totals[ $date ] > $max_totals ) $max_totals = $product_totals[ $date ];
}
}
}
?>
<h4><?php printf( __( 'Sales for %s:', 'woocommerce' ), implode( ', ', $chosen_product_titles ) ); ?></h4>
<table class="bar_chart">
<thead>
<tr>
<th><?php _e('Month', 'woocommerce'); ?></th>
<th colspan="2"><?php _e('Sales', 'woocommerce'); ?></th>
</tr>
</thead>
<tbody>
<?php
if (sizeof($product_sales)>0) foreach ($product_sales as $date => $sales) :
$width = ($sales>0) ? (round($sales) / round($max_sales)) * 100 : 0;
$width2 = ($product_totals[$date]>0) ? (round($product_totals[$date]) / round($max_totals)) * 100 : 0;
$orders_link = admin_url('edit.php?s&post_status=all&post_type=shop_order&action=-1&s=' . urlencode(get_the_title($chosen_product_id)) . '&m=' . date('Ym', strtotime($date.'01')) . '&shop_order_status=completed,processing,on-hold');
echo '<tr><th><a href="'.$orders_link.'">'.date_i18n('F', strtotime($date.'01')).'</a></th>
<td width="1%"><span>'.$sales.'</span><span class="alt">'.woocommerce_price($product_totals[$date]).'</span></td>
<td class="bars">
<span style="width:'.$width.'%">&nbsp;</span>
<span class="alt" style="width:'.$width2.'%">&nbsp;</span>
</td></tr>';
endforeach; else echo '<tr><td colspan="3">'.__('No sales :(', 'woocommerce').'</td></tr>';
?>
</tbody>
</table>
<?php
} else {
?>
<form method="post" action="">
<p><select id="product_ids" name="product_ids[]" class="ajax_chosen_select_products" multiple="multiple" data-placeholder="<?php _e('Search for a product...', 'woocommerce'); ?>" style="width: 400px;"></select> <input type="submit" style="vertical-align: top;" class="button" value="<?php _e('Show', 'woocommerce'); ?>" /></p>
<script type="text/javascript">
jQuery(function(){
// Ajax Chosen Product Selectors
jQuery("select.ajax_chosen_select_products").ajaxChosen({
method: 'GET',
url: '<?php echo admin_url('admin-ajax.php'); ?>',
dataType: 'json',
afterTypeDelay: 100,
data: {
action: 'woocommerce_json_search_products',
security: '<?php echo wp_create_nonce("search-products"); ?>'
}
}, function (data) {
endforeach;
?>
</select> <input type="submit" class="button" value="<?php _e('Show', 'woocommerce'); ?>" /></p>
</form>
<?php if ($chosen_product_id) : ?>
<table class="bar_chart">
<thead>
<tr>
<th><?php _e('Month', 'woocommerce'); ?></th>
<th colspan="2"><?php _e('Sales', 'woocommerce'); ?></th>
</tr>
</thead>
<tbody>
<?php
if (sizeof($product_sales)>0) foreach ($product_sales as $date => $sales) :
$width = ($sales>0) ? (round($sales) / round($max_sales)) * 100 : 0;
$width2 = ($product_totals[$date]>0) ? (round($product_totals[$date]) / round($max_totals)) * 100 : 0;
$orders_link = admin_url('edit.php?s&post_status=all&post_type=shop_order&action=-1&s=' . urlencode(get_the_title($chosen_product_id)) . '&m=' . date('Ym', strtotime($date.'01')) . '&shop_order_status=completed,processing,on-hold');
echo '<tr><th><a href="'.$orders_link.'">'.date_i18n('F', strtotime($date.'01')).'</a></th>
<td width="1%"><span>'.$sales.'</span><span class="alt">'.woocommerce_price($product_totals[$date]).'</span></td>
<td class="bars">
<span style="width:'.$width.'%">&nbsp;</span>
<span class="alt" style="width:'.$width2.'%">&nbsp;</span>
</td></tr>';
endforeach; else echo '<tr><td colspan="3">'.__('No sales :(', 'woocommerce').'</td></tr>';
?>
</tbody>
</table>
<?php
endif;
var terms = {};
jQuery.each(data, function (i, val) {
terms[i] = val;
});
return terms;
});
});
</script>
</form>
<?php
}
}

View File

@ -149,6 +149,7 @@ Yes you can! Join in on our [GitHub repository](http://github.com/woothemes/wooc
= 1.5.6 =
* Tweak - When the count of available shipping methods changes, reset to default
* Tweak - Optimisations to monthly and product reports
= 1.5.5 - 10/05/2012 =
* Feature - New 'default' sorting order using menu_order, with drag and drop sorting (based on http://wordpress.org/extend/plugins/simple-page-ordering/)