Enabled product bundles

This commit is contained in:
Nedim Uka
2018-06-29 14:40:28 +02:00
parent e0514f7f57
commit b5475ff2f1
12004 changed files with 1694047 additions and 1610 deletions

View File

@@ -0,0 +1,127 @@
<?php
/**
* Booster for WooCommerce - Reports - Currency
*
* @version 2.5.7
* @author Algoritmika Ltd.
*/
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! class_exists( 'WCJ_Currency_Reports' ) ) :
class WCJ_Currency_Reports {
/**
* Constructor.
*/
function __construct() {
add_filter( 'woocommerce_reports_get_order_report_data_args', array( $this, 'filter_reports'), PHP_INT_MAX, 1 );
add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_reports'), PHP_INT_MAX, 2 );
add_action( 'admin_bar_menu', array( $this, 'add_reports_currency_to_admin_bar' ), PHP_INT_MAX );
}
/**
* add_reports_currency_to_admin_bar.
*
* @version 2.5.2
*/
function add_reports_currency_to_admin_bar( $wp_admin_bar ) {
if ( isset( $_GET['page'] ) && 'wc-reports' === $_GET['page'] ) {
$the_current_code = isset( $_GET['currency'] ) ? $_GET['currency'] : get_woocommerce_currency();
$parent = 'reports_currency_select';
$args = array(
'parent' => false,
'id' => $parent,
'title' => __( 'Reports currency:', 'woocommerce-jetpack' ) . ' ' . $the_current_code,
'href' => false,
'meta' => array( 'title' => __( 'Show reports only in', 'woocommerce-jetpack' ) . ' ' . $the_current_code, ),
);
$wp_admin_bar->add_node( $args );
$currency_symbols = array();
$currency_symbols[ $the_current_code ] = $the_current_code;
$currency_symbols[ get_woocommerce_currency() ] = get_woocommerce_currency();
if ( wcj_is_module_enabled( 'price_by_country' ) ) {
for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_price_by_country_total_groups_number', 1 ) ); $i++ ) {
$the_code = get_option( 'wcj_price_by_country_exchange_rate_currency_group_' . $i );
$currency_symbols[ $the_code ] = $the_code;
}
}
if ( wcj_is_module_enabled( 'multicurrency' ) ) {
for ( $i = 1; $i <= apply_filters( 'booster_option', 2, get_option( 'wcj_multicurrency_total_number', 2 ) ); $i++ ) {
$the_code = get_option( 'wcj_multicurrency_currency_' . $i );
$currency_symbols[ $the_code ] = $the_code;
}
}
/* if ( wcj_is_module_enabled( 'multicurrency_base_price' ) ) {
for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_multicurrency_base_price_total_number', 1 ) ); $i++ ) {
$the_code = get_option( 'wcj_multicurrency_base_price_currency_' . $i );
$currency_symbols[ $the_code ] = $the_code;
}
} */
if ( wcj_is_module_enabled( 'payment_gateways_currency' ) ) {
global $woocommerce;
$available_gateways = $woocommerce->payment_gateways->payment_gateways();
foreach ( $available_gateways as $key => $gateway ) {
$the_code = get_option( 'wcj_gateways_currency_' . $key );
if ( 'no_changes' != $the_code ) {
$currency_symbols[ $the_code ] = $the_code;
}
}
}
sort( $currency_symbols );
$currency_symbols['merge'] = 'merge';
foreach ( $currency_symbols as $code ) {
$args = array(
'parent' => $parent,
'id' => $parent . '_' . $code,
'title' => $code,
'href' => add_query_arg( 'currency', $code ),
'meta' => array( 'title' => __( 'Show reports only in', 'woocommerce-jetpack' ) . ' ' . $code, ),
);
$wp_admin_bar->add_node( $args );
}
}
}
/**
* change_currency_symbol_reports.
*/
function change_currency_symbol_reports( $currency_symbol, $currency ) {
if ( isset( $_GET['page'] ) && 'wc-reports' === $_GET['page'] ) {
if ( isset( $_GET['currency'] ) ) {
return ( 'merge' === $_GET['currency'] ) ? '' : wcj_get_currency_symbol( $_GET['currency'] );
}
}
return $currency_symbol;
}
/**
* filter_reports.
*
* @version 2.5.7
*/
function filter_reports( $args ) {
if ( isset( $_GET['page'] ) && 'wc-reports' === $_GET['page'] ) {
if ( isset( $_GET['currency'] ) && 'merge' === $_GET['currency'] ) {
return $args;
}
$args['where_meta'] = array(
array(
'meta_key' => '_order_currency',
'meta_value' => isset( $_GET['currency'] ) ? $_GET['currency'] : get_woocommerce_currency(),
'operator' => '=',
),
);
}
return $args;
}
}
endif;
return new WCJ_Currency_Reports();

View File

@@ -0,0 +1,54 @@
<?php
/**
* Booster for WooCommerce Country Sets
*
* @version 3.3.0
* @author Algoritmika Ltd.
* @todo recheck if all countries are included in sets; recheck for overlapping sets
* @todo move to `wcj-functions-country.php`
* @todo use in "Price by Country" module for automatic group creation
* @todo add translations (`__`)
* @todo clean up
*/
return array(
'Africa' => array(
'AO', 'BF', 'BI', 'BJ', 'BW', 'CD', 'CF', 'CG', 'CI', 'CM', 'CV', 'DJ', 'DZ', 'EG', 'EH', 'ER', 'ET', 'GA', 'GH', 'GM', 'GN', 'GQ', 'GW', 'YT', 'KE', 'KM', 'LY', 'LR', 'LS', 'MA', 'MG', 'ML', 'MR', 'MU', 'MW', 'MZ', 'NA', 'NE', 'NG', 'RE', 'RW', 'SC', 'SD', 'SH', 'SL', 'SN', 'SO', 'ST', 'SZ', 'TD', 'TG', 'TN', 'TZ', 'UG', 'ZA', 'ZM', 'ZW', 'TF',
),
'Asia' => array(
'AE', 'AF', 'AM', 'AP', 'AZ', 'BD', 'BH', 'BN', 'BT', 'CC', 'CY', 'CN', 'CX', 'GE', 'HK', 'ID', 'IL', 'IN', 'IO', 'IQ', 'IR', 'YE', 'JO', 'JP', 'KG', 'KH', 'KP', 'KR', 'KW', 'KZ', 'LA', 'LB', 'LK', 'MY', 'MM', 'MN', 'MO', 'MV', 'NP', 'OM', 'PH', 'PK', 'PS', 'QA', 'SA', 'SG', 'SY', 'TH', 'TJ', 'TL', 'TM', 'TW', 'UZ', 'VN',
),
'European Union' => array(
'AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HU', 'HR', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK',
),
'Europe' => array(
'AD', 'AL', 'AT', 'AX', 'BA', 'BE', 'BG', 'BY', 'CH', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FO', 'FR', 'FX', 'GB', 'GG', 'GI', 'GR', 'HR', 'HU', 'IE', 'IM', 'IS', 'IT', 'JE', 'LI', 'LT', 'LU', 'LV', 'MC', 'MD', 'ME', 'MK', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'RS', 'RU', 'SE', 'SI', 'SJ', 'SK', 'SM', 'TR', 'UA', 'VA',
),
/*'Europe excl EU' => array(
'AD', 'AL', 'AX', 'BA', 'BY', 'CH', 'FO', 'FX', 'GG', 'GI', 'IM', 'IS', 'JE', 'LI', 'MC', 'MD', 'ME', 'MK', 'NO', 'RS', 'RU', 'SJ', 'SM', 'TR', 'UA', 'VA',
),*/
'Central America' => array(
'AG', 'AI', 'AN', 'AW', 'BB', 'BL', 'BM', 'BS', 'BZ', 'CR', 'CU', 'DM', 'DO', 'GD', 'GL', 'GP', 'GT', 'HN', 'HT', 'JM', 'KY', 'KN', 'LC', 'MF', 'MQ', 'MS', 'NI', 'PA', 'PM', 'PR', 'SV', 'TC', 'TT', 'VC', 'VG', 'VI',
),
'North America' => array(
'CA', 'MX', 'US',
),
'Oceania' => array(
'AS', 'AU', 'CK', 'FJ', 'FM', 'GU', 'KI', 'MH', 'MP', 'NC', 'NF', 'NR', 'NU', 'NZ', 'PF', 'PG', 'PN', 'PW', 'SB', 'TK', 'TO', 'TV', 'UM', 'VU', 'WF', 'WS',
),
'South America' => array(
'AR', 'BO', 'BR', 'CL', 'CO', 'EC', 'FK', 'GF', 'GY', 'GY', 'PE', 'PY', 'SR', 'UY', 'VE',
),
'Antarctica' => array(
'AQ',
),
);

View File

@@ -0,0 +1,169 @@
<?php
/**
* Booster for WooCommerce - Reports - Customers
*
* @version 3.3.0
* @author Algoritmika Ltd.
*/
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! class_exists( 'WCJ_Reports_Customers' ) ) :
class WCJ_Reports_Customers {
public $country_sets;
/**
* Constructor.
*/
function __construct( $args = null ) {
$this->country_sets = ( isset( $args['group_countries'] ) && 'yes' === $args['group_countries'] ) ?
include( 'countries/wcj-country-sets.php' ) : array();
}
/**
* get_report function.
*/
function get_report() {
$report_type = isset( $_GET['country'] ) ? $_GET['country'] : 'all_countries';
$html = '';
// Get customers
$customers = get_users( 'role=customer&orderby=registered&order=DESC' );
$total_customers = count( $customers );
if ( $total_customers < 1 ) {
return '<h5>' . __( 'No customers found.', 'woocommerce-jetpack' ) . '</h5>';
}
// Count data
$the_data = $this->get_data( $customers, $report_type );
// Get HTML
$html = $this->get_html( $the_data, $total_customers, $report_type );
/*
$no_sales_countries = array();
foreach( WC_Countries::get_countries() as $country_code => $country_name ) {
if ( ! isset( $the_data[ $country_code ] ) ) $no_sales_countries[] = $country_code;// . ' - ' . $country_name;
}
return $html . count( $no_sales_countries ) . ': ' . implode( '<br>', $no_sales_countries );
*/
return $html;
}
/**
* get_data function.
*/
function get_data( $customers, $report_type = 'all_countries' ) {
foreach ( $customers as $customer ) {
// Get country (billing or shipping)
$user_meta = get_user_meta( $customer->ID );
$billing_country = isset( $user_meta['billing_country'][0] ) ? $user_meta['billing_country'][0] : '';
$shipping_country = isset( $user_meta['shipping_country'][0] ) ? $user_meta['shipping_country'][0] : '';
$customer_country = ( '' == $billing_country ) ? $shipping_country : $billing_country;
// If available - change to country set instead
foreach ( $this->country_sets as $id => $countries ) {
if ( in_array( $customer_country, $countries ) ) {
$customer_country = $id;
break;
}
}
// N/A
if ( '' == $customer_country ) {
$customer_country = __( 'Non Available', 'woocommerce-jetpack' );
}
if ( 'all_countries' === $report_type ) {
// Counter
if ( ! isset( $result[ $customer_country ]['customer_counter'] ) ) {
$result[ $customer_country ]['customer_counter'] = 0;
}
$result[ $customer_country ]['customer_counter']++;
} else { // single country
if ( ! isset( $result[ $customer_country ]['total_spent'] ) ) {
$result[ $customer_country ]['total_spent'] = array(
array(
__( 'Customer Name', 'woocommerce-jetpack' ),
__( 'Email', 'woocommerce-jetpack' ),
__( 'Total Spent', 'woocommerce-jetpack' ),
__( 'Registered', 'woocommerce-jetpack' ),
),
);
}
$customer_total_spent = wc_get_customer_total_spent( $customer->ID );
// if ( '' != $customer_total_spent ) {
$result[ $customer_country ]['total_spent'][] = array(
$customer->data->display_name,
$customer->data->user_email,
$customer_total_spent,
$customer->data->user_registered,
);
// }
}
}
if ( 'all_countries' === $report_type ) {
uasort( $result, array( $this, 'custom_sort_for_data' ) );
}
return $result;
}
/**
* custom_sort_for_data.
*/
function custom_sort_for_data( $a, $b ) {
if ( $a['customer_counter'] == $b['customer_counter'] ) {
return 0;
}
return ( $a['customer_counter'] > $b['customer_counter'] ) ? -1 : 1;
}
/**
* get_data function.
*
* @version 3.3.0
*/
function get_html( $data, $total_customers, $report_type = 'all_countries' ) {
$html = '';
if ( 'all_countries' === $report_type ) {
$html .= '<h5>' . __( 'Total customers', 'woocommerce-jetpack' ) . ': ' . $total_customers . '</h5>';
$html .= '<table class="widefat" style="width:100% !important;"><tbody>';
$html .= '<tr>';
$html .= '<th></th>';
$html .= '<th>' . __( 'Country Code', 'woocommerce-jetpack' ) . '</th>';
$html .= '<th>' . __( 'Customers Count', 'woocommerce-jetpack' ) . '</th>';
$html .= '<th>' . __( 'Percent of total', 'woocommerce-jetpack' ) . '</th>';
$html .= '<th></th>';
$html .= '<th></th>';
$html .= '</tr>';
$i = 0;
foreach ( $data as $country_code => $result ) {
$result = $result['customer_counter'];
$html .= '<tr>';
$html .= '<td>' . ++$i . '</td>';
$country_code_link = '<a href="' . add_query_arg( array ( 'country' => $country_code ) ) . '">' . $country_code . '</a>';
$html .= ( 2 == strlen( $country_code ) ) ? '<td>' . $country_code_link . '</td>' : '<td>' . $country_code . '</td>' ;
$html .= '<td>' . $result . '</td>';
$html .= ( 0 != $total_customers ) ? '<td>' . number_format( ( $result / $total_customers ) * 100, 2 ) . '%' . '</td>' : '<td></td>';
$country_flag_img = wcj_get_country_flag_by_code( $country_code );
$country_flag_img_link = '<a href="' . add_query_arg( array ( 'country' => $country_code ) ) . '">' .
$country_flag_img . ' ' . wcj_get_country_name_by_code( $country_code ) . '</a>';
$html .= ( 2 == strlen( $country_code ) ) ? '<td>' . $country_flag_img_link . '</td>' : '<td></td>';
$html .= '</tr>';
}
$html .= '</tbody></table>';
} else { // single country
$country_code = $report_type;
$html .= '<h5>' . __( 'Report for:', 'woocommerce-jetpack' ) . ' ' . wcj_get_country_name_by_code( $country_code ) . ' [' . $country_code . ']' . '</h5>';
$html .= ( 2 == strlen( $country_code ) ) ? wcj_get_table_html( $data[ $country_code ]['total_spent'], array( 'table_class' => 'widefat', ) ) : '';
}
return $html;
}
}
endif;

View File

@@ -0,0 +1,357 @@
<?php
/**
* Booster for WooCommerce - Reports - Monthly Sales (with Currency Conversion)
*
* @version 3.6.0
* @since 2.4.7
* @author Algoritmika Ltd.
*/
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! class_exists( 'WCJ_Reports_Monthly_Sales' ) ) :
class WCJ_Reports_Monthly_Sales {
/**
* Constructor.
*
* @version 2.7.0
* @since 2.4.7
*/
function __construct( $args = null ) {
return true;
}
/**
* get_report.
*
* @version 2.9.1
* @since 2.4.7
*/
function get_report() {
$html = '';
if ( isset( $_POST['wcj_save_currency_rates'] ) && isset( $_POST['wcj_save_currency_rates_array'] ) && is_array( $_POST['wcj_save_currency_rates_array'] ) ) {
// Save rates
update_option( 'wcj_reports_currency_rates', array_replace_recursive( get_option( 'wcj_reports_currency_rates', array() ), $_POST['wcj_save_currency_rates_array'] ) );
$html .= '<div class="notice notice-success is-dismissible"><p><strong>' . __( 'Currency rates saved.', 'woocommerce-jetpack' ) . '</strong></p></div>';
} elseif ( isset( $_POST['wcj_reset_currency_rates'] ) ) {
// Delete rates
delete_option( 'wcj_reports_currency_rates' );
$html .= '<div class="notice notice-success is-dismissible"><p><strong>' . __( 'Currency rates deleted.', 'woocommerce-jetpack' ) . '</strong></p></div>';
}
// Show report
$this->year = isset( $_GET['year'] ) ? $_GET['year'] : date( 'Y' );
$html .= $this->get_monthly_sales_report();
return $html;
}
/*
* get_saved_exchange_rate.
*
* @version 2.9.1
* @since 2.4.7
*/
function get_saved_exchange_rate( $currency_from, $currency_to, $start_date, $end_date ) {
// Same currency
if ( $currency_from == $currency_to ) {
return 1.0;
}
// Saved values
$saved_rates = get_option( 'wcj_reports_currency_rates', array() );
if ( ! empty( $saved_rates ) ) {
if ( isset( $saved_rates[ $currency_from ][ $currency_to ][ $start_date ][ $end_date ] ) ) {
return $saved_rates[ $currency_from ][ $currency_to ][ $start_date ][ $end_date ];
}
}
// Fallback rate
return 1.0;
}
/*
* get_monthly_sales_report.
*
* @version 3.6.0
* @since 2.4.7
* @todo (maybe) visible rows selection by admin (as option)
* @todo (maybe) take not monthly average, but "Close" of closest day (probably create new "Daily Sales (with Currency Conversion)" report)
*/
function get_monthly_sales_report() {
$execution_time_start = microtime( true );
$months_array = array( '' );
$months_days_array = array( __( 'Days', 'woocommerce-jetpack' ) );
$total_orders_array = array( __( 'Total Orders', 'woocommerce-jetpack' ) );
$total_orders_average_array = array( __( 'Orders Average / Day', 'woocommerce-jetpack' ) );
$total_orders_sum_array = array( __( 'Total Sum', 'woocommerce-jetpack' ) );
$total_orders_sum_excl_tax_array = array( __( 'Total Sum (excl. TAX)', 'woocommerce-jetpack' ) );
$total_orders_sum_average_order_array = array( __( 'Average / Order (excl. TAX)', 'woocommerce-jetpack' ) );
$total_orders_sum_average_array = array( __( 'Average / Day (excl. TAX)', 'woocommerce-jetpack' ) );
$currency_rates_array = array( __( 'Currency Rates', 'woocommerce-jetpack' ) );
$orders_by_currency_array = array( __( 'Orders by Currency', 'woocommerce-jetpack' ) );
$total_months_days = 0;
$total_orders_total = 0;
$total_orders_sum_total = 0;
$total_orders_sum_excl_tax_total = 0;
$order_currencies_array = array();
$order_currencies_array_totals = array();
$report_currency = ( isset( $_GET['currency'] ) && 'merge' != $_GET['currency'] ) ? $_GET['currency'] : get_woocommerce_currency();
$block_size = 256;
$table_data = array();
$do_forecast = ( 'yes' === get_option( 'wcj_reports_orders_monthly_sales_forecast', 'no' ) );
$do_include_today = ( 'yes' === get_option( 'wcj_reports_orders_monthly_sales_include_today', 'no' ) );
for ( $i = 1; $i <= 12; $i++ ) {
$current_months_averages = array();
$total_orders = 0;
$total_orders_sum = 0;
$total_orders_sum_excl_tax = 0;
$offset = 0;
$is_current_month = ( $i == date( 'm' ) && $this->year == date( 'Y' ) );
$day_for_average = ( $is_current_month ?
( $do_include_today ? date( 'd' ) : ( date( 'd' ) - 1 ) ) : // today or yesterday
date( 't', strtotime( $this->year . '-' . sprintf( '%02d', $i ) . '-' . '01' ) ) // last day of the month
);
if ( 0 == $day_for_average ) {
$months_array[] = date_i18n( 'F', mktime( 0, 0, 0, $i, 1, $this->year ) );
$months_days_array[] = '-';
$total_orders_array[] = '-';
$total_orders_average_array[] = '-';
$total_orders_sum_array[] = '-';
$total_orders_sum_excl_tax_array[] = '-';
$total_orders_sum_average_order_array[] = '-';
$total_orders_sum_average_array[] = '-';
$currency_rates_array[] = '';
$orders_by_currency_array[] = '';
continue;
}
while( true ) {
$args_orders = array(
'post_type' => 'shop_order',
'post_status' => 'wc-completed',
'posts_per_page' => $block_size,
'orderby' => 'date',
'order' => 'DESC',
'offset' => $offset,
'fields' => 'ids',
'date_query' => array(
'after' => array(
'year' => $this->year,
'month' => $i,
'day' => 1,
),
'before' => array(
'year' => $this->year,
'month' => $i,
'day' => $day_for_average,
),
'inclusive' => true,
),
);
$loop_orders = new WP_Query( $args_orders );
if ( ! $loop_orders->have_posts() ) {
break;
}
foreach ( $loop_orders->posts as $order_id ) {
$order = wc_get_order( $order_id );
$order_currency = wcj_get_order_currency( $order );
// Orders by currency by month
if ( ! isset( $order_currencies_array[ $i ][ $order_currency ] ) ) {
$order_currencies_array[ $i ][ $order_currency ] = 0;
}
$order_currencies_array[ $i ][ $order_currency ]++;
// Orders by currency total
if ( ! isset( $order_currencies_array_totals[ $order_currency ] ) ) {
$order_currencies_array_totals[ $order_currency ] = 0;
}
$order_currencies_array_totals[ $order_currency ]++;
$total_orders++;
$order_total = $order->get_total();
$order_total_excl_tax = $order->get_total() - $order->get_total_tax();
if ( ! isset( $current_months_averages[ $order_currency ][ $report_currency ] ) ) {
$start_date = $this->year . '-' . sprintf( '%02d', $i ) . '-' . '01';
$end_date = date( 'Y-m-t', strtotime( $start_date ) );
$the_rate = $this->get_saved_exchange_rate( $order_currency, $report_currency, $start_date, $end_date );
if ( 0 == $the_rate ) {
$the_rate = 1;
}
$current_months_averages[ $order_currency ][ $report_currency ] = $the_rate;
}
$total_orders_sum += $order_total * $current_months_averages[ $order_currency ][ $report_currency ];
$total_orders_sum_excl_tax += $order_total_excl_tax * $current_months_averages[ $order_currency ][ $report_currency ];
}
$offset += $block_size;
}
// Month Name
$months_array[] = date_i18n( 'F', mktime( 0, 0, 0, $i, 1, $this->year ) );
// Month Days
$months_days_array[] = ( date( 'm' ) >= $i || $this->year != date( 'Y' ) ? $day_for_average : '-' );
$total_months_days += ( date( 'm' ) >= $i || $this->year != date( 'Y' ) ? $day_for_average : 0 );
// Sales
$average_sales_result = $total_orders / $day_for_average;
if ( $is_current_month && $do_forecast ) {
$forecast_total_orders = ( $average_sales_result ) * ( date( 't', strtotime( $this->year . '-' . sprintf( '%02d', $i ) . '-' . '01' ) ) );
}
$total_orders_array[] = ( $total_orders > 0 ? $total_orders . ( $is_current_month && $do_forecast ?
wc_help_tip( sprintf( __( 'Forecast: %s', 'woocommerce-jetpack' ), round( $forecast_total_orders ) ), true ) : ''
) : ''
);
$total_orders_total += $total_orders;
// Sales Average
$total_orders_average_array[] = ( $average_sales_result > 0 ? number_format( $average_sales_result, 2, '.', ',' ) : '-' );
// Sum
$total_orders_sum_array[] = ( $total_orders_sum > 0 ? $report_currency . ' ' . number_format( $total_orders_sum, 2, '.', ',' ) : '-' );
$total_orders_sum_total += $total_orders_sum;
// Sum excl. Tax
$total_orders_sum_excl_tax_array[] = ( $total_orders_sum_excl_tax > 0 ?
$report_currency . ' ' . number_format( $total_orders_sum_excl_tax, 2, '.', ',' ) . ( $is_current_month && $do_forecast ?
wc_help_tip( sprintf( __( 'Forecast: %s', 'woocommerce-jetpack' ), $report_currency . ' ' .
number_format( $forecast_total_orders * $total_orders_sum_excl_tax / $total_orders, 2 ) ), true ) : ''
) : ''
);
$total_orders_sum_excl_tax_total += $total_orders_sum_excl_tax;
// Order Average
$total_orders_sum_average_order_array[] = ( $total_orders_sum_excl_tax > 0 && $total_orders > 0 ?
$report_currency . ' ' . number_format( $total_orders_sum_excl_tax / $total_orders, 2, '.', ',' ) : '-' );
// Sum Average
$average_result = $total_orders_sum_excl_tax / $day_for_average;
$total_orders_sum_average_array[] = ( $average_result > 0 ? $report_currency . ' ' . number_format( $average_result, 2, '.', ',' ) : '-' );
// Currency Rates
ksort( $current_months_averages );
$currency_rates_html = '<pre style="font-size:x-small;">';
foreach ( $current_months_averages as $currency_from => $currencies_to ) {
foreach ( $currencies_to as $currency_to => $rate ) {
if ( $currency_from != $currency_to ) {
$input_id = sanitize_title( $currency_from . '_' . $currency_to . '_' . $start_date . '_' . $end_date );
$currency_rates_html .= '<a class="wcj_grab_average_currency_exchange_rate" href="#" title="' . __( 'Grab average rate', 'woocommerce-jetpack' ) .
'" currency_from="' . $currency_from .
'" currency_to="' . $currency_to .
'" start_date="' . $start_date .
'" end_date="' . $end_date .
'" input_id="' . $input_id .
'">' . $currency_from . $currency_to .
'</a> ' .
'<input id="' . $input_id . '" style="width:50px;font-size:x-small;" type="number" ' .
'name="wcj_save_currency_rates_array[' . $currency_from . '][' . $currency_to . '][' . $start_date . '][' . $end_date . ']" ' .
'value="' . $rate . '" step="0.000001">' .
'<br>';
}
}
}
$currency_rates_html .= '</pre>';
$currency_rates_array[] = $currency_rates_html;
// Orders by Currency by Month
if ( isset( $order_currencies_array[ $i ] ) ) {
ksort( $order_currencies_array[ $i ] );
$orders_by_currency_html = '<pre style="font-size:x-small;">';
foreach ( $order_currencies_array[ $i ] as $_order_currency => $total_orders_by_currency ) {
$orders_by_currency_html .= $_order_currency . ' ' . $total_orders_by_currency . '<br>';
}
$orders_by_currency_html .= '</pre>';
$orders_by_currency_array[] = $orders_by_currency_html;
} else {
$orders_by_currency_array[] = '';
}
}
// Orders by Currency Total
$order_currencies_totals_html = '';
if ( ! empty ( $order_currencies_array_totals ) ) {
ksort( $order_currencies_array_totals );
$order_currencies_totals_html = '<pre style="font-size:x-small;">';
foreach ( $order_currencies_array_totals as $_order_currency => $total_orders_by_currency ) {
$order_currencies_totals_html .= $_order_currency . ' ' . $total_orders_by_currency . '<br>';
}
$order_currencies_totals_html .= '</pre>';
}
// Totals
if ( $do_forecast ) {
$part_of_the_year_for_forecast = ( $total_months_days > 0 ? ( date( 'z', strtotime( date( 'Y-12-31' ) ) ) + 1 ) / $total_months_days : 0 );
$forecast_total_orders_year = ( $part_of_the_year_for_forecast > 0 && date( 'Y' ) == $this->year ?
wc_help_tip( sprintf( __( 'Forecast: %s', 'woocommerce-jetpack' ), round( $part_of_the_year_for_forecast * $total_orders_total ) ), true ) : '' );
$forecast_total_orders_sum_excl_tax_total = ( $part_of_the_year_for_forecast > 0 && date( 'Y' ) == $this->year ?
wc_help_tip( sprintf( __( 'Forecast: %s', 'woocommerce-jetpack' ),
$report_currency . ' ' . number_format( $part_of_the_year_for_forecast * $total_orders_sum_excl_tax_total, 2, '.', ',' ) ), true ) : '' );
}
$months_array[] = __( 'Totals', 'woocommerce-jetpack' );
$months_days_array[] = $total_months_days;
$total_orders_array[] = $total_orders_total .
( $do_forecast ? $forecast_total_orders_year : '' );
$total_orders_average_array[] = ( $total_months_days > 0 ? number_format( ( $total_orders_total / $total_months_days ), 2, '.', ',' ) : '-' );
$total_orders_sum_array[] = $report_currency . ' ' . number_format( $total_orders_sum_total, 2, '.', ',' );
$total_orders_sum_excl_tax_array[] = $report_currency . ' ' . number_format( $total_orders_sum_excl_tax_total, 2, '.', ',' ) .
( $do_forecast ? $forecast_total_orders_sum_excl_tax_total : '' );
$total_orders_sum_average_order_array[] = ( $total_orders_total > 0 ?
$report_currency . ' ' . number_format( ( $total_orders_sum_excl_tax_total / $total_orders_total ), 2, '.', ',' ) : '-' );
$total_orders_sum_average_array[] = ( $total_months_days > 0 ?
$report_currency . ' ' . number_format( ( $total_orders_sum_excl_tax_total / $total_months_days ), 2, '.', ',' ) : '-' );
$currency_rates_array[] = '';
$orders_by_currency_array[] = $order_currencies_totals_html;
// Table
$table_data[] = $months_array;
$table_data[] = $months_days_array;
$table_data[] = $total_orders_array;
$table_data[] = $total_orders_average_array;
$table_data[] = $total_orders_sum_array;
$table_data[] = $total_orders_sum_excl_tax_array;
$table_data[] = $total_orders_sum_average_order_array;
$table_data[] = $total_orders_sum_average_array;
$table_data[] = $currency_rates_array;
$table_data[] = $orders_by_currency_array;
$execution_time_end = microtime( true );
// HTML
$html = '';
$menu = '';
$menu .= '<p>';
$menu .= '<ul class="subsubsub">';
$menu .= '<li><a href="' . add_query_arg( 'year', date( 'Y' ) ) . '" class="' .
( ( $this->year == date( 'Y' ) ) ? 'current' : '' ) . '">' . date( 'Y' ) . '</a> | </li>';
$menu .= '<li><a href="' . add_query_arg( 'year', ( date( 'Y' ) - 1 ) ) . '" class="' .
( ( $this->year == ( date( 'Y' ) - 1 ) ) ? 'current' : '' ) . '">' . ( date( 'Y' ) - 1 ) . '</a> | </li>';
$menu .= '<li><a href="' . add_query_arg( 'year', ( date( 'Y' ) - 2 ) ) . '" class="' .
( ( $this->year == ( date( 'Y' ) - 2 ) ) ? 'current' : '' ) . '">' . ( date( 'Y' ) - 2 ) . '</a> | </li>';
$menu .= '</ul>';
$menu .= '</p>';
$menu .= '<br class="clear">';
$html .= $menu;
$html .= '<h4>' . __( 'Report currency', 'woocommerce-jetpack' ) . ': ' . $report_currency . '</h4>';
$months_styles = array();
for ( $i = 1; $i <= 12; $i++ ) {
$months_styles[] = ( $i == date( 'm' ) && $this->year == date( 'Y' ) ? 'width:8%;' : 'width:6%;' );
}
$html .= '<form method="post" action="">';
$html .= wcj_get_table_html( $table_data, array(
'table_class' => 'widefat striped',
'table_heading_type' => 'horizontal',
'columns_styles' => array_merge(
array( 'width:16%;' ),
$months_styles,
array( ( $this->year == date( 'Y' ) ? 'width:10%;' : 'width:12%;' ) . 'font-weight:bold;' )
),
) );
$html .= '<p style="font-size:x-small;"><em>' . sprintf( __( 'Report generated in: %s s', 'woocommerce-jetpack' ),
number_format( ( $execution_time_end - $execution_time_start ), 2, '.', ',' ) ) . '</em></p>';
$html .= '<p><input name="wcj_save_currency_rates" type="submit" class="button button-primary" value="' .
__( 'Save Currency Rates', 'woocommerce-jetpack' ) . '"></p>';
$html .= '</form>';
$html .= '<form method="post" action="">' .
'<input name="wcj_reset_currency_rates" type="submit" class="button button-primary" value="' .
__( 'Reset Currency Rates', 'woocommerce-jetpack' ) . '" onclick="return confirm(\'' . __( 'Are you sure?', 'woocommerce-jetpack' ) . '\')">' .
'</form>';
return $html;
}
}
endif;

View File

@@ -0,0 +1,302 @@
<?php
/**
* Booster for WooCommerce - Reports - Product Sales (Daily)
*
* @version 3.2.4
* @since 2.9.0
* @author Algoritmika Ltd.
*/
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! class_exists( 'WCJ_Reports_Product_Sales_Daily' ) ) :
class WCJ_Reports_Product_Sales_Daily {
/**
* Constructor.
*
* @version 2.9.0
* @since 2.9.0
*/
function __construct( $args = null ) {
return true;
}
/**
* get_report.
*
* @version 2.9.0
* @since 2.9.0
*/
function get_report() {
$this->get_report_args();
$this->get_report_data();
return $this->output_report_data();
}
/*
* get_report_args.
*
* @version 3.2.4
* @since 2.9.0
*/
function get_report_args() {
$current_time = (int) current_time( 'timestamp' );
$this->start_date = isset( $_GET['start_date'] ) ? $_GET['start_date'] : date( 'Y-m-d', strtotime( '-7 days', $current_time ) );
$this->end_date = isset( $_GET['end_date'] ) ? $_GET['end_date'] : date( 'Y-m-d', $current_time );
$this->product_title = isset( $_GET['product_title'] ) ? $_GET['product_title'] : '';
}
/*
* get_report_data.
*
* @version 2.9.0
* @since 2.9.0
* @todo (maybe) currency conversion
* @todo recheck if `wc_get_product_purchase_price()` working correctly for variations
*/
function get_report_data() {
$include_taxes = ( 'yes' === get_option( 'wcj_reports_products_sales_daily_include_taxes', 'no' ) );
$count_variations = ( 'yes' === get_option( 'wcj_reports_products_sales_daily_count_variations', 'no' ) );
$order_statuses = get_option( 'wcj_reports_products_sales_daily_order_statuses', '' );
if ( empty( $order_statuses ) ) {
$order_statuses = 'any';
} elseif ( 1 == count( $order_statuses ) ) {
$order_statuses = $order_statuses[0];
}
$this->sales_by_day = array();
$this->total_sales_by_day = array();
$this->purchase_data = array();
$this->last_sale_data = array();
$this->total_orders = 0;
$offset = 0;
$block_size = 512;
while( true ) {
$args_orders = array(
'post_type' => 'shop_order',
'post_status' => $order_statuses,
'posts_per_page' => $block_size,
'orderby' => 'date',
'order' => 'DESC',
'offset' => $offset,
'fields' => 'ids',
'date_query' => array(
array(
'after' => $this->start_date,
'before' => $this->end_date,
'inclusive' => true,
),
),
);
$loop_orders = new WP_Query( $args_orders );
if ( ! $loop_orders->have_posts() ) {
break;
}
foreach ( $loop_orders->posts as $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
// Filtering by product title
if ( '' != $this->product_title && false === stripos( $item['name'], $this->product_title ) ) {
continue;
}
// Preparing data
$product_id = ( 0 != $item['variation_id'] && $count_variations ) ? $item['variation_id'] : $item['product_id'];
$order_day_date = get_the_date( 'Y-m-d', $order_id );
$sale_line_total = $item['line_total'] + ( $include_taxes ? $item['line_tax'] : 0 );
// Total sales by day
if ( ! isset( $this->total_sales_by_day[ $order_day_date ] ) ) {
$this->total_sales_by_day[ $order_day_date ] = array( 'qty' => 0, 'sum' => 0 );
}
$this->total_sales_by_day[ $order_day_date ]['qty'] += $item['qty'];
$this->total_sales_by_day[ $order_day_date ]['sum'] += $sale_line_total;
// Sales by day by product
if ( ! isset( $this->sales_by_day[ $order_day_date ] ) ) {
$this->sales_by_day[ $order_day_date ] = array();
}
if ( ! isset( $this->sales_by_day[ $order_day_date ][ $product_id ] ) ) {
$this->sales_by_day[ $order_day_date ][ $product_id ] = array( 'qty' => 0, 'sum' => 0 );
}
if ( $count_variations ) {
$this->sales_by_day[ $order_day_date ][ $product_id ]['name'] = $item['name'];
} else {
$this->sales_by_day[ $order_day_date ][ $product_id ]['name'][] = $item['name'];
}
$this->sales_by_day[ $order_day_date ][ $product_id ]['qty'] += $item['qty'];
$this->sales_by_day[ $order_day_date ][ $product_id ]['sum'] += $sale_line_total;
// Purchase data
if ( ! isset( $this->purchase_data[ $product_id ] ) ) {
$this->purchase_data[ $product_id ] = wc_get_product_purchase_price( $product_id );
}
// Last Sale Time
if ( ! isset( $this->last_sale_data[ $product_id ] ) ) {
$this->last_sale_data[ $product_id ]['date'] = get_the_time( 'Y-m-d H:i:s', $order_id );
$this->last_sale_data[ $product_id ]['order_id'] = $order_id;
$this->last_sale_data[ $product_id ]['order_status'] = get_post_status( $order_id );
}
}
$this->total_orders++;
}
$offset += $block_size;
}
}
/*
* output_report_data.
*
* @version 2.9.0
* @since 2.9.0
*/
function output_report_data() {
return $this->output_report_header() . $this->output_report_results();
}
/*
* output_report_header.
*
* @version 2.9.0
* @since 2.9.0
*/
function output_report_header() {
// Settings link and dates menu
$settings_link = '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=reports' ) . '">' .
'<< ' . __( 'Reports Settings', 'woocommerce-jetpack' ) . '</a>';
$menu = '';
$menu .= '<ul class="subsubsub">';
foreach ( array_merge( wcj_get_reports_standard_ranges(), wcj_get_reports_custom_ranges() ) as $custom_range ) {
$menu .= '<li><a ' .
'href="' . add_query_arg( array( 'start_date' => $custom_range['start_date'], 'end_date' => $custom_range['end_date'] ) ) . '" ' .
'class="' . ( ( $this->start_date == $custom_range['start_date'] && $this->end_date == $custom_range['end_date'] ) ? 'current' : '' ) . '"' .
'>' . $custom_range['title'] . '</a> | </li>';
}
$menu .= '</ul>';
$menu .= '<br class="clear">';
// Product and date filter form
$filter_form = '';
$filter_form .= '<form method="get" action="">';
$filter_form .= '<input type="hidden" name="page" value="' . $_GET['page'] . '" />';
$filter_form .= '<input type="hidden" name="tab" value="' . $_GET['tab'] . '" />';
$filter_form .= '<input type="hidden" name="report" value="' . $_GET['report'] . '" />';
$filter_form .= '<label style="font-style:italic;" for="start_date">' . __( 'From:', 'woocommerce-jetpack' ) . '</label>' . ' ' .
'<input type="text" display="date" dateformat="' . wcj_date_format_php_to_js( 'Y-m-d' ) . '" name="start_date" title="" value="' . $this->start_date . '" />';
$filter_form .= ' ';
$filter_form .= '<label style="font-style:italic;" for="end_date">' . __( 'To:', 'woocommerce-jetpack' ) . '</label>' . ' ' .
'<input type="text" display="date" dateformat="' . wcj_date_format_php_to_js( 'Y-m-d' ) . '" name="end_date" title="" value="' . $this->end_date . '" />';
$filter_form .= ' ';
$filter_form .= '<label style="font-style:italic;" for="product_title">' . __( 'Product:', 'woocommerce-jetpack' ) . '</label>' . ' ' .
'<input type="text" name="product_title" id="product_title" title="" value="' . $this->product_title . '" />';
$filter_form .= '<input type="submit" value="' . __( 'Filter', 'woocommerce-jetpack' ) . '" />';
$filter_form .= '</form>';
// Final result
return '<p>' . $settings_link . '</p>' . '<p>' . $menu . '</p>' . '<p>' . $filter_form . '</p>';
}
/*
* output_report_results.
*
* @version 2.9.0
* @since 2.9.0
*/
function output_report_results() {
$table_data = array();
$table_header = array();
$all_columns = wcj_get_product_sales_daily_report_columns();
$report_columns = get_option( 'wcj_reports_products_sales_daily_columns', '' );
if ( empty( $report_columns ) ) {
$report_columns = array_keys( $all_columns );
}
foreach ( $report_columns as $report_column ) {
$table_header[] = $all_columns[ $report_column ];
}
$table_data[] = $table_header;
$totals = array(
'qty' => 0,
'sum' => 0,
'profit' => 0,
);
foreach ( $this->sales_by_day as $day_date => $day_sales ) {
$day_date_info['date'] = $day_date;
$day_date_info['daily_total_sum'] = wc_price( $this->total_sales_by_day[ $day_date ]['sum'] );
$day_date_info['daily_total_quantity'] = $this->total_sales_by_day[ $day_date ]['qty'];
foreach ( $day_sales as $product_id => $product_day_sales ) {
$row = array();
foreach ( $report_columns as $report_column ) {
switch ( $report_column ) {
case 'date':
$row[] = $day_date_info['date'];
$day_date_info['date'] = '';
break;
case 'daily_total_sum':
$row[] = $day_date_info['daily_total_sum'];
$day_date_info['daily_total_sum'] = '';
break;
case 'daily_total_quantity':
$row[] = $day_date_info['daily_total_quantity'];
$day_date_info['daily_total_quantity'] = '';
break;
case 'product_id':
$row[] = '<a target="_blank" href="' . get_permalink( $product_id ) . '">' . $product_id . '</a>';
break;
case 'item_title':
$row[] = ( is_array( $product_day_sales['name'] ) ? implode( ', ', array_unique( $product_day_sales['name'] ) ) : $product_day_sales['name'] );
break;
case 'item_quantity':
$row[] = $product_day_sales['qty'];
$totals['qty'] += $product_day_sales['qty'];
break;
case 'sum':
$row[] = wc_price( $product_day_sales['sum'] );
$totals['sum'] += $product_day_sales['sum'];
break;
case 'profit':
$profit = $product_day_sales['sum'] - $this->purchase_data[ $product_id ] * $product_day_sales['qty'];
$row[] = wc_price( $profit );
$totals['profit'] += $profit;
break;
case 'last_sale':
$row[] = $this->last_sale_data[ $product_id ]['date'];
break;
case 'last_sale_order_id':
$row[] = $this->last_sale_data[ $product_id ]['order_id'];
break;
case 'last_sale_order_status':
$row[] = $this->last_sale_data[ $product_id ]['order_status'];
break;
}
}
$table_data[] = $row;
}
}
$display_totals = false;
$totals_row = array();
foreach ( $report_columns as $report_column ) {
switch ( $report_column ) {
case 'item_quantity':
$totals_row[] = '<strong>' . sprintf( __( 'Total: %d', 'woocommerce-jetpack' ), $totals['qty'] ) . '</strong>';
$display_totals = true;
break;
case 'sum':
$totals_row[] = '<strong>' . sprintf( __( 'Total: %s', 'woocommerce-jetpack' ), wc_price( $totals['sum'] ) ) . '</strong>';
$display_totals = true;
break;
case 'profit':
$totals_row[] = '<strong>' . sprintf( __( 'Total: %s', 'woocommerce-jetpack' ), wc_price( $totals['profit'] ) ) . '</strong>';
$display_totals = true;
break;
default:
$totals_row[] = '';
}
}
if ( $display_totals ) {
$table_data[] = $totals_row;
}
$result = ( ! empty( $this->sales_by_day ) ) ?
wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'none' ) ) .
'<p><em>' . sprintf( __( 'Total orders: %d', 'woocommerce-jetpack' ), $this->total_orders ) . '</em></p>' :
'<p><em>' . __( 'No sales data for current period.', 'woocommerce-jetpack' ) . '</em></p>';
return $result;
}
}
endif;

View File

@@ -0,0 +1,166 @@
<?php
/**
* Booster for WooCommerce - Reports - Product Sales - Gateways
*
* @version 3.6.0
* @since 3.6.0
* @author Algoritmika Ltd.
*/
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! class_exists( 'WCJ_Reports_Product_Sales_Gateways' ) ) :
class WCJ_Reports_Product_Sales_Gateways {
/**
* Constructor.
*
* @version 3.6.0
* @since 3.6.0
*/
function __construct( $args = null ) {
return true;
}
/**
* get_report.
*
* @version 3.6.0
* @since 3.6.0
*/
function get_report() {
$this->get_report_args();
$this->get_report_data();
return $this->output_report_data();
}
/*
* get_report_args.
*
* @version 3.6.0
* @since 3.6.0
*/
function get_report_args() {
$current_time = (int) current_time( 'timestamp' );
$this->start_date = isset( $_GET['start_date'] ) ? $_GET['start_date'] : date( 'Y-m-d', strtotime( '-7 days', $current_time ) );
$this->end_date = isset( $_GET['end_date'] ) ? $_GET['end_date'] : date( 'Y-m-d', $current_time );
}
/*
* get_report_data.
*
* @version 3.6.0
* @since 3.6.0
* @todo by "order status"
*/
function get_report_data() {
$this->gateways = array();
$offset = 0;
$block_size = 1024;
while( true ) {
$args_orders = array(
'post_type' => 'shop_order',
'post_status' => 'any',
'posts_per_page' => $block_size,
'orderby' => 'ID',
'order' => 'DESC',
'offset' => $offset,
'fields' => 'ids',
'date_query' => array(
array(
'after' => $this->start_date,
'before' => $this->end_date,
'inclusive' => true,
),
),
);
$loop_orders = new WP_Query( $args_orders );
if ( ! $loop_orders->have_posts() ) {
break;
}
foreach ( $loop_orders->posts as $order_id ) {
if ( '' == ( $payment_gateway = get_post_meta( $order_id, '_payment_method_title', true ) ) ) {
$payment_gateway = __( 'N/A', 'woocommerce-jetpack' );
}
if ( ! isset( $this->gateways[ $payment_gateway ] ) ) {
$this->gateways[ $payment_gateway ] = 0;
}
$this->gateways[ $payment_gateway ]++;
}
$offset += $block_size;
}
}
/*
* output_report_data.
*
* @version 3.6.0
* @since 3.6.0
*/
function output_report_data() {
return $this->output_report_header() . $this->output_report_results();
}
/*
* output_report_header.
*
* @version 3.6.0
* @since 3.6.0
*/
function output_report_header() {
// Settings link and dates menu
$settings_link = '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=reports' ) . '">' .
'<< ' . __( 'Reports Settings', 'woocommerce-jetpack' ) . '</a>';
$menu = '';
$menu .= '<ul class="subsubsub">';
foreach ( array_merge( wcj_get_reports_standard_ranges(), wcj_get_reports_custom_ranges() ) as $custom_range ) {
$menu .= '<li><a ' .
'href="' . add_query_arg( array( 'start_date' => $custom_range['start_date'], 'end_date' => $custom_range['end_date'] ) ) . '" ' .
'class="' . ( ( $this->start_date == $custom_range['start_date'] && $this->end_date == $custom_range['end_date'] ) ? 'current' : '' ) . '"' .
'>' . $custom_range['title'] . '</a> | </li>';
}
$menu .= '</ul>';
$menu .= '<br class="clear">';
// Date filter form
$filter_form = '';
$filter_form .= '<form method="get" action="">';
$filter_form .= '<input type="hidden" name="page" value="' . $_GET['page'] . '" />';
$filter_form .= '<input type="hidden" name="tab" value="' . $_GET['tab'] . '" />';
$filter_form .= '<input type="hidden" name="report" value="' . $_GET['report'] . '" />';
$filter_form .= '<label style="font-style:italic;" for="start_date">' . __( 'From:', 'woocommerce-jetpack' ) . '</label>' . ' ' .
'<input type="text" display="date" dateformat="' . wcj_date_format_php_to_js( 'Y-m-d' ) . '" name="start_date" title="" value="' . $this->start_date . '" />';
$filter_form .= ' ';
$filter_form .= '<label style="font-style:italic;" for="end_date">' . __( 'To:', 'woocommerce-jetpack' ) . '</label>' . ' ' .
'<input type="text" display="date" dateformat="' . wcj_date_format_php_to_js( 'Y-m-d' ) . '" name="end_date" title="" value="' . $this->end_date . '" />';
$filter_form .= ' ';
$filter_form .= '<input type="submit" value="' . __( 'Filter', 'woocommerce-jetpack' ) . '" />';
$filter_form .= '</form>';
// Final result
return '<p>' . $settings_link . '</p>' . '<p>' . $menu . '</p>' . '<p>' . $filter_form . '</p>';
}
/*
* output_report_results.
*
* @version 3.6.0
* @since 3.6.0
*/
function output_report_results() {
if ( ! empty( $this->gateways ) ) {
$table_data = array();
$table_data[] = array(
'<strong><em>' . __( 'Gateway', 'woocommerce-jetpack' ) . '</em></strong>', '<strong><em>' . __( 'Orders', 'woocommerce-jetpack' ) . '</em></strong>' );
foreach ( $this->gateways as $gateway => $total ) {
$table_data[] = array( '<em>' . $gateway . '</em>', $total );
}
$result = wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'none' ) ) .
'<p><em>' . sprintf( __( 'Total orders: %d', 'woocommerce-jetpack' ), array_sum( $this->gateways ) ) . '</em></p>';
} else {
$result = '<p><em>' . __( 'No sales data for current period.', 'woocommerce-jetpack' ) . '</em></p>';
}
return $result;
}
}
endif;

View File

@@ -0,0 +1,355 @@
<?php
/**
* Booster for WooCommerce - Reports - Sales
*
* @version 3.2.4
* @author Algoritmika Ltd.
*/
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! class_exists( 'WCJ_Reports_Sales' ) ) :
class WCJ_Reports_Sales {
/**
* Constructor.
*
* @version 2.6.0
* @since 2.3.0
*/
function __construct( $args = null ) {
return true;
}
/**
* get_report.
*
* @version 2.3.9
* @since 2.3.0
*/
function get_report() {
$html = '';
$this->year = isset( $_GET['year'] ) ? $_GET['year'] : date( 'Y' );
$this->product_title = isset( $_GET['product_title'] ) ? $_GET['product_title'] : '';
$html .= $this->get_products_sales();
return $html;
}
/*
* sort_by_title.
*
* @version 2.5.7
* @since 2.5.7
*/
function sort_by_title( $a, $b ) {
return strcmp( strip_tags( $a['title'] ), strip_tags( $b['title'] ) );
}
/*
* do_product_parent_exist.
*
* @version 3.2.4
* @since 3.2.4
*/
function do_product_parent_exist( $_product ) {
if ( WCJ_IS_WC_VERSION_BELOW_3 ) {
return is_object( $_product->parent );
} else {
return ( 0 != ( $parent_id = $_product->get_parent_id() ) ? is_object( wc_get_product( $parent_id ) ) : false );
}
}
/*
* get_products_sales.
*
* @version 3.2.4
* @since 2.3.0
* @todo fix when variable and variations are all (wrongfully) counted in total sums
* @todo display more info for "Parent product deleted" and "Product deleted"
* @todo (maybe) currency conversion
* @todo (maybe) `sort_by_total_sales` instead of `sort_by_title`
* @todo (maybe) `if ( 0 == $product_purchase_price ) { if ( 0 != $the_data['sales'] ) { $product_purchase_price = ( $the_data['total_sum'] / $the_data['sales'] ) * 0.80; } $_product = wc_get_product( $the_data['product_id'] ); if ( is_object( $_product ) ) { $product_purchase_price = $_product->get_price(); } }`
*/
function get_products_sales() {
// Get report data
$products_data = array();
$totals_data = array();
$years = array();
$total_orders = 0;
$offset = 0;
$block_size = 512;
while( true ) {
$args_orders = array(
'post_type' => 'shop_order',
'post_status' => 'wc-completed',
'posts_per_page' => $block_size,
'orderby' => 'date',
'order' => 'DESC',
'offset' => $offset,
'date_query' => array(
array(
'year' => $this->year,
),
),
'fields' => 'ids',
);
$loop_orders = new WP_Query( $args_orders );
if ( ! $loop_orders->have_posts() ) {
break;
}
foreach ( $loop_orders->posts as $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
if ( ! apply_filters( 'wcj_reports_products_sales_check_product', true, $item['product_id'] ) ) {
continue;
}
$product_ids = array( $item['product_id'] );
if ( 0 != $item['variation_id'] && 'yes' === get_option( 'wcj_reports_products_sales_count_variations', 'no' ) ) {
$product_ids[] = $item['variation_id'];
}
foreach ( $product_ids as $product_id ) {
// Title
if ( ! isset( $products_data[ $product_id ][ 'title' ] ) ) {
$products_data[ $product_id ][ 'title' ] = '';
$_product = wc_get_product( $product_id );
if ( is_object( $_product ) ) {
$products_data[ $product_id ][ 'title' ] .= $_product->get_title();
if ( 'WC_Product_Variation' === get_class( $_product ) && $this->do_product_parent_exist( $_product ) ) {
$products_data[ $product_id ][ 'title' ] .= '<br><em>' . wcj_get_product_formatted_variation( $_product, true ) . '</em>';
} elseif ( 'WC_Product_Variation' === get_class( $_product ) ) {
// Parent product deleted
$products_data[ $product_id ][ 'title' ] .= $item['name'] . '<br><em>' . __( 'Variation', 'woocommerce-jetpack' ) . '</em>';
$products_data[ $product_id ][ 'title' ] = '<del>' . $products_data[ $product_id ][ 'title' ] . '</del>';
}
} else {
// Product deleted
$products_data[ $product_id ][ 'title' ] .= $item['name'];
$products_data[ $product_id ][ 'title' ] = '<del>' . $products_data[ $product_id ][ 'title' ] . '</del>';
}
}
if ( ! ( '' == $this->product_title || false !== stripos( $products_data[ $product_id ][ 'title' ], $this->product_title ) ) ) {
unset( $products_data[ $product_id ] );
continue;
}
// Total Sales
if ( ! isset( $products_data[ $product_id ][ 'sales' ] ) ) {
$products_data[ $product_id ][ 'sales' ] = 0;
}
$products_data[ $product_id ][ 'sales' ] += $item['qty'];
// Total Sum
if ( ! isset( $products_data[ $product_id ][ 'total_sum' ] ) ) {
$products_data[ $product_id ][ 'total_sum' ] = 0;
}
$products_data[ $product_id ][ 'total_sum' ] += ( $item['line_total'] + ( 'yes' === get_option( 'wcj_reports_products_sales_include_taxes', 'no' ) ?
$item['line_tax'] : 0 ) );
// Sales by Month
$month = date( 'n', get_the_time( 'U', $order_id ) );
$year = date( 'Y', get_the_time( 'U', $order_id ) );
$years[ $year ] = true;
if ( ! isset( $products_data[ $product_id ][ 'sales_by_month' ][ $year ][ $month ] ) ) {
$products_data[ $product_id ][ 'sales_by_month' ][ $year ][ $month ] = 0;
}
$products_data[ $product_id ][ 'sales_by_month' ][ $year ][ $month ] += $item['qty'];
// Sales by Month - Sum
if ( ! isset( $products_data[ $product_id ][ 'sales_by_month_sum' ][ $year ][ $month ] ) ) {
$products_data[ $product_id ][ 'sales_by_month_sum' ][ $year ][ $month ] = 0;
}
$products_data[ $product_id ][ 'sales_by_month_sum' ][ $year ][ $month ] += $item['line_total'] +
( 'yes' === get_option( 'wcj_reports_products_sales_include_taxes', 'no' ) ? $item['line_tax'] : 0 );
// Sales by Month (Totals)
if ( ! isset( $totals_data[ 'sales_by_month' ][ $year ][ $month ] ) ) {
$totals_data[ 'sales_by_month' ][ $year ][ $month ] = 0;
}
$totals_data[ 'sales_by_month' ][ $year ][ $month ] += $item['qty'];
// Sales by Month - Sum (Totals)
if ( ! isset( $totals_data[ 'sales_by_month_sum' ][ $year ][ $month ] ) ) {
$totals_data[ 'sales_by_month_sum' ][ $year ][ $month ] = 0;
}
$totals_data[ 'sales_by_month_sum' ][ $year ][ $month ] += $item['line_total'] +
( 'yes' === get_option( 'wcj_reports_products_sales_include_taxes', 'no' ) ? $item['line_tax'] : 0 );
// Last Sale Time
if ( ! isset( $products_data[ $product_id ][ 'last_sale' ] ) ) {
$products_data[ $product_id ][ 'last_sale' ] = date( 'Y-m-d H:i:s', get_the_time( 'U', $order_id ) );
}
// Product ID
if ( ! isset( $products_data[ $product_id ][ 'product_id' ] ) ) {
$products_data[ $product_id ][ 'product_id' ] = $product_id;
}
}
}
$total_orders++;
}
$offset += $block_size;
}
usort( $products_data, array( $this, 'sort_by_title' ) );
// Output report table
$table_data = array();
$the_header = array(
__( 'ID', 'woocommerce-jetpack' ),
__( 'Product', 'woocommerce-jetpack' ),
__( 'Last Sale', 'woocommerce-jetpack' ),
__( 'Total', 'woocommerce-jetpack' ),
);
foreach ( $years as $year => $value ) {
if ( $year != $this->year ) continue;
for ( $i = 12; $i >= 1; $i-- ) {
$the_header[] = sprintf( '%04d.%02d', $year, $i );
}
}
$total_profit = 0;
$table_data[] = $the_header;
foreach ( $products_data as $the_data ) {
$product_purchase_price = wc_get_product_purchase_price( $the_data['product_id'] );
$profit = $the_data['total_sum'] - $product_purchase_price * $the_data['sales'];
$total_profit += $profit;
$the_row = array(
$the_data['product_id'],
$the_data['title'],
$the_data['last_sale'],
'<strong>' . $the_data['sales'] . '</strong>',
);
$the_row2 = array(
$the_data['product_id'],
$the_data['title'],
$the_data['last_sale'],
'<strong>' . wc_price( $the_data['total_sum'] ) . '</strong>',
);
$the_row3 = array(
$the_data['product_id'],
$the_data['title'],
$the_data['last_sale'],
'<strong>' . wc_price( $profit ) . '</strong>',
);
foreach ( $years as $year => $value ) {
if ( $year != $this->year ) continue;
for ( $i = 12; $i >= 1; $i-- ) {
if ( isset( $the_data['sales_by_month'][ $year ][ $i ] ) ) {
// Sales
if ( $i > 1 ) {
$prev_month_data = ( isset( $the_data['sales_by_month'][ $year ][ $i - 1 ] ) ) ?
$the_data['sales_by_month'][ $year ][ $i - 1 ] :
0;
$color = ( $prev_month_data >= $the_data['sales_by_month'][ $year ][ $i ] ) ? 'red' : 'green';
} else {
$color = 'green';
}
$the_row[] = '<span style="color:' . $color . ';">' . $the_data['sales_by_month'][ $year ][ $i ] . '</span>';
// Sum
if ( $i > 1 ) {
$prev_month_data = ( isset( $the_data['sales_by_month_sum'][ $year ][ $i - 1 ] ) ) ?
$the_data['sales_by_month_sum'][ $year ][ $i - 1 ] :
0;
$color = ( $prev_month_data >= $the_data['sales_by_month_sum'][ $year ][ $i ] ) ? 'red' : 'green';
} else {
$color = 'green';
}
$the_row2[] = '<span style="color:' . $color . ';">' . wc_price( $the_data['sales_by_month_sum'][ $year ][ $i ] ) . '</span>';
// Profit
if ( ! isset( $totals_data['profit_by_month'][ $year ][ $i ] ) ) {
$totals_data['profit_by_month'][ $year ][ $i ] = 0;
}
$profit_by_month_for_product = $the_data['sales_by_month_sum'][ $year ][ $i ] - $product_purchase_price * $the_data['sales_by_month'][ $year ][ $i ];
$totals_data['profit_by_month'][ $year ][ $i ] += $profit_by_month_for_product;
if ( $i > 1 ) {
$prev_month_data = ( isset( $the_data['sales_by_month_sum'][ $year ][ $i - 1 ] ) ) ?
$the_data['sales_by_month_sum'][ $year ][ $i - 1 ] - $product_purchase_price * $the_data['sales_by_month'][ $year ][ $i - 1 ] :
0;
$color = ( $prev_month_data >= $profit_by_month_for_product ) ? 'red' : 'green';
} else {
$color = 'green';
}
$the_row3[] = '<span style="color:' . $color . ';">' . wc_price( $profit_by_month_for_product ) . '</span>';
} else {
$the_row[] = '';
$the_row2[] = '';
$the_row3[] = '';
}
}
}
if ( 'yes' === get_option( 'wcj_reports_products_sales_display_sales', 'yes' ) ) {
$table_data[] = $the_row;
}
if ( 'yes' === get_option( 'wcj_reports_products_sales_display_sales_sum', 'yes' ) ) {
$table_data[] = $the_row2;
}
if ( 'yes' === get_option( 'wcj_reports_products_sales_display_profit', 'no' ) ) {
$table_data[] = $the_row3;
}
}
// Totals
$totals_row = array();
$totals_row2 = array();
$totals_row3 = array();
$totals_sales_by_month = 0;
$totals_sales_by_month_sum = 0;
foreach ( $years as $year => $value ) {
if ( $year != $this->year ) continue;
for ( $i = 12; $i >= 1; $i-- ) {
if ( isset( $totals_data['sales_by_month'][ $year ][ $i ] ) ) {
$totals_row[] = '<strong>' . $totals_data['sales_by_month'][ $year ][ $i ] . '</strong>';
$totals_row2[] = '<strong>' . wc_price( $totals_data['sales_by_month_sum'][ $year ][ $i ] ) . '</strong>';
$totals_row3[] = '<strong>' . wc_price( $totals_data['profit_by_month'][ $year ][ $i ] ) . '</strong>';
$totals_sales_by_month += $totals_data['sales_by_month'][ $year ][ $i ];
$totals_sales_by_month_sum += $totals_data['sales_by_month_sum'][ $year ][ $i ];
} else {
$totals_row[] = '';
$totals_row2[] = '';
$totals_row3[] = '';
}
}
}
if ( 'yes' === get_option( 'wcj_reports_products_sales_display_sales', 'yes' ) ) {
$table_data[] = array_merge( array( '', '', '<strong>' . __( 'Total Items', 'woocommerce-jetpack' ) . '</strong>',
'<strong>' . $totals_sales_by_month . '</strong>' ), $totals_row );
}
if ( 'yes' === get_option( 'wcj_reports_products_sales_display_sales_sum', 'yes' ) ) {
$table_data[] = array_merge( array( '', '', '<strong>' . __( 'Total Sum', 'woocommerce-jetpack' ) . '</strong>',
'<strong>' . wc_price( $totals_sales_by_month_sum . '</strong>' ) ), $totals_row2 );
}
if ( 'yes' === get_option( 'wcj_reports_products_sales_display_profit', 'no' ) ) {
$table_data[] = array_merge( array( '', '', '<strong>' . __( 'Total Profit', 'woocommerce-jetpack' ) .
'</strong>', '<strong>' . wc_price( $total_profit . '</strong>' ) ), $totals_row3 );
}
$settings_link = '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=reports' ) . '">' .
'<< ' . __( 'Reports Settings', 'woocommerce-jetpack' ) . '</a>';
$menu = '';
$menu .= '<ul class="subsubsub">';
$menu .= '<li><a href="' . add_query_arg( 'year', date( 'Y' ) ) . '" class="' .
( ( $this->year == date( 'Y' ) ) ? 'current' : '' ) . '">' . date( 'Y' ) . '</a> | </li>';
$menu .= '<li><a href="' . add_query_arg( 'year', ( date( 'Y' ) - 1 ) ) . '" class="' .
( ( $this->year == ( date( 'Y' ) - 1 ) ) ? 'current' : '' ) . '">' . ( date( 'Y' ) - 1 ) . '</a> | </li>';
$menu .= '<li><a href="' . add_query_arg( 'year', ( date( 'Y' ) - 2 ) ) . '" class="' .
( ( $this->year == ( date( 'Y' ) - 2 ) ) ? 'current' : '' ) . '">' . ( date( 'Y' ) - 2 ) . '</a></li>';
$menu .= '</ul>';
$menu .= '<br class="clear">';
$filter_form = '';
$filter_form .= '<form method="get" action="">';
$filter_form .= '<input type="hidden" name="page" value="' . $_GET['page'] . '" />';
$filter_form .= '<input type="hidden" name="tab" value="' . $_GET['tab'] . '" />';
$filter_form .= '<input type="hidden" name="report" value="' . $_GET['report'] . '" />';
$filter_form .= '<input type="hidden" name="year" value="' . $this->year . '" />';
$filter_form .= '<input type="text" name="product_title" title="" value="' . $this->product_title . '" />' .
'<input type="submit" value="' . __( 'Filter products', 'woocommerce-jetpack' ) . '" />';
$filter_form .= '</form>';
$the_results = ( ! empty( $products_data ) ) ?
wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) ) :
'<p><em>' . __( 'No sales data for current period.' ) . '</em></p>';
return '<p>' . $settings_link . '</p>' . '<p>' . $menu . '</p>' . '<p>' . $filter_form . '</p>' . $the_results;
}
}
endif;

View File

@@ -0,0 +1,339 @@
<?php
/**
* Booster for WooCommerce - Reports - Stock
*
* @version 2.9.1
* @author Algoritmika Ltd.
*/
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! class_exists( 'WCJ_Reports_Stock' ) ) :
class WCJ_Reports_Stock {
/** @var array Possible ranges in days values. */
public $ranges_in_days;
/**
* Constructor.
*
* @todo (maybe) `most_stock_price`, `sales_up`, `good_sales_low_stock`
* @todo (maybe) `echo __( 'Here you can generate reports. Some reports are generated using all your orders and products, so if you have a lot of them - it may take a while.', 'woocommerce-jetpack' );`
* @todo (maybe) get_option( 'woocommerce_manage_stock' ) -> `echo __( 'Please enable stock management in <strong>WooCommerce > Settings > Products > Inventory</strong> to generate stock based reports.', 'woocommerce-jetpack' );`
*/
function __construct( $args = null ) {
$this->ranges_in_days = array( 7, 14, 30, 60, 90, 180, 360 );
$this->report_id = isset( $args['report_id'] ) ? $args['report_id'] : 'on_stock';
$this->range_days = isset( $args['range_days'] ) ? $args['range_days'] : 30;
$this->reports_info = array(
'on_stock' => array(
'id' => 'on_stock',
'title' => __( 'All Products on Stock', 'woocommerce-jetpack' ),
'desc' => __( 'Report shows all products that are on stock and some sales info.', 'woocommerce-jetpack' ),
),
'understocked' => array(
'id' => 'understocked',
'title' => __( 'Understocked', 'woocommerce-jetpack' ),
'desc' => __( 'Report shows all products that are low in stock calculated on product\'s sales data.', 'woocommerce-jetpack' ) . ' ' .
__( 'Threshold for minimum stock is equal to half of the sales in selected days range.', 'woocommerce-jetpack' ),
),
'overstocked' => array(
'id' => 'overstocked',
'title' => __( 'Overstocked', 'woocommerce-jetpack' ),
'desc' => __( 'Report shows all products that are on stock, but have no sales in selected period. Only products added before the start date of selected period are accounted.', 'woocommerce-jetpack' ),
),
);
$this->start_time = microtime( true );
$products_info = array();
$this->gather_products_data( $products_info );
$this->gather_orders_data( $products_info );
$info = $this->get_stock_summary( $products_info );
if ( 'on_stock' === $this->report_id || 'overstocked' === $this->report_id ) {
$this->sort_products_info( $products_info, 'stock_price' );
}
if ( 'understocked' === $this->report_id ) {
$this->sort_products_info( $products_info, 'sales_in_period', $this->range_days );
}
$this->data_products = $products_info;
$this->data_summary = $info;
$this->data_reports = $this->reports_info[ $this->report_id ];
}
/*
* get_submenu_html.
*/
function get_submenu_html() {
$html = '';
$html .= '<ul class="subsubsub">';
foreach ( $this->ranges_in_days as $the_period ) {
$html .= '<li>';
$html .= ( $the_period == $this->range_days ) ? '<strong>' : '';
$html .= '<a href="' . get_admin_url() . 'admin.php?page=wc-reports&tab=stock&report=' . $this->report_id . '&period=' . $the_period . '" class="">' . $the_period . ' days</a>';
$html .= ( $the_period == $this->range_days ) ? '</strong>' : '';
$html .= ' | ';
$html .= '</li>';
}
$html .= '</ul>';
$html .= '<br class="clear">';
return $html;
}
/*
* gather_products_data.
*
* @version 2.9.1
* @todo variations
*/
function gather_products_data( &$products_info ) {
$offset = 0;
$block_size = 256;
while( true ) {
$args = array(
'post_type' => 'product',
'posts_per_page' => $block_size,
'offset' => $offset,
'fields' => 'ids',
);
$loop = new WP_Query( $args );
if ( ! $loop->have_posts() ) {
break;
}
foreach ( $loop->posts as $product_id ) {
$the_product = wc_get_product( $product_id );
$the_price = $the_product->get_price();
$the_stock = wcj_get_product_total_stock( $the_product );
$the_title = get_the_title( $product_id );
$the_categories = ( WCJ_IS_WC_VERSION_BELOW_3 ? $the_product->get_categories() : wc_get_product_category_list( $product_id ) );
$the_date = get_the_date( get_option( 'date_format' ), $product_id );
$the_permalink = get_the_permalink( $product_id );
$post_custom = get_post_custom( $product_id );
$total_sales = isset( $post_custom['total_sales'][0] ) ? $post_custom['total_sales'][0] : 0;
$purchase_price = wc_get_product_purchase_price( $product_id );
$sales_in_day_range = array();
foreach( $this->ranges_in_days as $the_range ) {
$sales_in_day_range[ $the_range ] = 0;
}
$products_info[ $product_id ] = array(
'ID' => $product_id,
'title' => $the_title,
'category' => $the_categories,
'permalink' => $the_permalink,
'price' => $the_price,
'stock' => $the_stock,
'stock_price' => $the_price * $the_stock,
'total_sales' => $total_sales,
'date_added' => $the_date,
'purchase_price' => $purchase_price,
'last_sale' => 0,
'sales_in_period' => $sales_in_day_range,
);
}
$offset += $block_size;
}
}
/*
* gather_orders_data.
*
* @version 2.9.1
*/
function gather_orders_data( &$products_info ) {
$offset = 0;
$block_size = 256;
while( true ) {
$args_orders = array(
'post_type' => 'shop_order',
'post_status' => 'wc-completed',
'posts_per_page' => $block_size,
'offset' => $offset,
'orderby' => 'date',
'order' => 'DESC',
'date_query' => array(
array(
'column' => 'post_date_gmt',
'after' => $this->range_days . ' days ago',
),
),
'fields' => 'ids',
);
$the_period = $this->range_days;
$loop_orders = new WP_Query( $args_orders );
if ( ! $loop_orders->have_posts() ) {
break;
}
foreach ( $loop_orders->posts as $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
if ( ! isset( $products_info[ $item['product_id'] ] ) ) {
// Deleted product
$products_info[ $item['product_id'] ] = array(
'ID' => $item['product_id'],
'title' => $item['name'] . ' (' . __( 'deleted', 'woocommerce-jetpack' ) . ')',
'category' => '',
'permalink' => '',
'price' => '',
'stock' => '',
'stock_price' => '',
'total_sales' => '',
'date_added' => '',
'purchase_price' => '',
'last_sale' => 0,
'sales_in_period' => array( $the_period => 0 ),
);
}
$products_info[ $item['product_id'] ]['sales_in_period'][ $the_period ] += $item['qty'];
if ( 0 == $products_info[ $item['product_id'] ]['last_sale'] ) {
$products_info[ $item['product_id'] ]['last_sale'] = get_the_time( 'U' );
}
}
}
$offset += $block_size;
}
}
/*
* get_stock_summary.
*/
function get_stock_summary( $products_info ) {
$info = array();
$info['total_stock_price'] = 0;
$info['stock_price_average'] = 0;
$info['stock_average'] = 0;
$info['sales_in_period_average'][ $this->range_days ] = 0;
$stock_non_zero_number = 0;
foreach ( $products_info as $product_info ) {
if ( $product_info['stock_price'] > 0 ) {
$info['stock_price_average'] += $product_info['stock_price'];
$info['stock_average'] += $product_info['stock'];
$info['sales_in_period_average'][ $this->range_days ] += $product_info['sales_in_period'][ $this->range_days ];
$stock_non_zero_number++;
}
$info['total_stock_price'] += $product_info['stock_price'];
}
if ( 0 != $stock_non_zero_number ) {
$info['stock_price_average'] /= $stock_non_zero_number;
$info['stock_average'] /= $stock_non_zero_number;
$info['sales_in_period_average'][ $this->range_days ] /= $stock_non_zero_number;
}
return $info;
}
/*
* sort_products_info.
*/
function sort_products_info( &$products_info, $field_name, $second_field_name = '', $order_of_sorting = SORT_DESC ) {
$field_name_array = array();
foreach ( $products_info as $key => $row ) {
$field_name_array[ $key ] = ( '' == $second_field_name ? $row[ $field_name ] : $row[ $field_name ][ $second_field_name ] );
}
array_multisort( $field_name_array, $order_of_sorting, $products_info );
}
/*
* get_report_html.
*
* @version 2.9.1
*/
function get_report_html() {
$products_info = $this->data_products;
$info = $this->data_summary;
$report_info = $this->data_reports;
$html = '';
// Style
$html .= '<style>';
$html .= '.wcj_report_table_sales_columns { background-color: #F6F6F6; }';
$html .= '.widefat { width: 90%; }';
$html .= '</style>';
// Products table - header
$html .= '<table class="widefat"><tbody>';
$html .= '<tr>';
$html .= '<th>#</th>';
$html .= '<th>' . __( 'Product', 'woocommerce-jetpack' ) . '</th>';
$html .= '<th>' . __( 'Category', 'woocommerce-jetpack' ) . '</th>';
$html .= '<th>' . __( 'Price', 'woocommerce-jetpack' ) . '</th>';
$html .= '<th>' . __( 'Stock', 'woocommerce-jetpack' ) . '</th>';
$html .= '<th>' . __( 'Stock price', 'woocommerce-jetpack' ) . '</th>';
$html .= '<th>' . __( 'Total stock price', 'woocommerce-jetpack' ) . '</th>';
$html .= '<th class="wcj_report_table_sales_columns">' . __( 'Last sale', 'woocommerce-jetpack' ) . '</th>';
$html .= '<th class="wcj_report_table_sales_columns">' . sprintf( __( 'Sales in last %s days', 'woocommerce-jetpack' ), $this->range_days ) . '</th>';
$html .= '<th class="wcj_report_table_sales_columns">' . __( 'Total sales', 'woocommerce-jetpack' ) . '</th>';
if ( 'understocked' === $this->report_id ) {
$html .= '<th>' . __( 'Stock to minimum', 'woocommerce-jetpack' ) . '</th>';
}
$html .= '</tr>';
// Products table - info loop
$total_current_stock_price = 0;
$product_counter = 0;
$total_current_stock_purchase_price = 0;
foreach ( $products_info as $product_info ) {
if (
( ( 'on_stock' === $report_info['id'] ) &&
( $product_info['stock'] != 0 ) ) ||
( ( 'overstocked' === $report_info['id'] ) &&
( $product_info['stock'] > 0 ) &&
( ( current_time( 'timestamp' ) - strtotime( $product_info['date_added'] ) ) > $this->range_days * 24 * 60 * 60 ) &&
( 0 === $product_info['sales_in_period'][ $this->range_days ] ) ) ||
( ( 'understocked' === $report_info['id'] ) &&
( '' !== $product_info['stock'] ) &&
( $product_info['sales_in_period'][ $this->range_days ] > 1 ) &&
( $product_info['stock'] < ( $product_info['sales_in_period'][ $this->range_days ] / 2 ) ) )
) {
$total_current_stock_price += $product_info['stock_price'];
$product_counter++;
$html .= '<tr>';
$html .= '<td>' . $product_counter . '</td>';
$html .= '<th>' . '<a href='. $product_info['permalink'] . '>' . $product_info['title'] . '</a>' . '</th>';
$html .= '<th>' . '<a href='. $product_info['permalink'] . '>' . $product_info['category'] . '</a>' . '</th>';
$purchase_price_html = ( $product_info['purchase_price'] > 0 ) ?
'<br><em>' . __( 'purchase price:', 'woocommerce-jetpack' ) . '</em>' . ' ' . wc_price( $product_info['purchase_price'] ) : '';
$html .= '<td>' . wc_price( $product_info['price'] ) . $purchase_price_html . '</td>';
$html .= '<td>' . $product_info['stock'] . '</td>';
$purchase_stock_price_html = ( $product_info['purchase_price'] > 0 ) ?
'<br><em>' . __( 'stock purchase price:', 'woocommerce-jetpack' ) . '</em>' . ' ' . wc_price( $product_info['purchase_price'] * $product_info['stock'] ) : '';
$total_current_stock_purchase_price += ( $product_info['purchase_price'] > 0 ? $product_info['purchase_price'] * $product_info['stock'] : 0 );
$html .= '<td>' . wc_price( $product_info['stock_price'] ) . $purchase_stock_price_html . '</td>';
$html .= '<td>' . wc_price( $total_current_stock_price ) . '</td>';
$html .= '<td class="wcj_report_table_sales_columns">';
if ( 0 == $product_info['last_sale'] ) $html .= __( 'No sales yet', 'woocommerce-jetpack' );
else $html .= date_i18n( get_option( 'date_format' ), $product_info['last_sale'] );
$html .= '</td>';
$profit_html = ( $product_info['purchase_price'] > 0 && $product_info['sales_in_period'][ $this->range_days ] > 0 ) ?
'<br><em>' . __( 'profit:', 'woocommerce-jetpack' ) . '</em>' . ' '
. wc_price( ( $product_info['price'] - $product_info['purchase_price'] ) * $product_info['sales_in_period'][ $this->range_days ] ) :
'';
$html .= '<td class="wcj_report_table_sales_columns">' . $product_info['sales_in_period'][ $this->range_days ] . $profit_html . '</td>';
$html .= '<td class="wcj_report_table_sales_columns">' . $product_info['total_sales'] . '</td>';
if ( $product_info['sales_in_period'][ $this->range_days ] > 0 ) {
$stock_to_minimum = ( $product_info['sales_in_period'][ $this->range_days ] / 2 ) - $product_info['stock'];
$stock_to_minimum = ( $stock_to_minimum > 0 ) ? round( $stock_to_minimum ) : '';
} else {
$stock_to_minimum = '';
}
if ( 'understocked' === $this->report_id ) {
$html .= '<td>' . $stock_to_minimum . '</td>';
}
$html .= '</tr>';
}
}
$html .= '</tbody></table>';
$html_header = '<h4>' . $report_info['title'] . ': ' . $report_info['desc'] . '</h4>';
$html_header .= '<table class="widefat" style="width:30% !important;"><tbody>';
$html_header .= '<tr>' . '<th>' . __( 'Total current stock value', 'woocommerce-jetpack' ) . '</th>' . '<td>' . wc_price( $total_current_stock_price ) . '</td>' . '</tr>';
$html_header .= '<tr>' . '<th>' . __( 'Total stock value', 'woocommerce-jetpack' ) . '</th>' . '<td>' . wc_price( $info['total_stock_price'] ) . '</td>' . '</tr>';
$html_header .= '<tr>' . '<th>' . __( 'Product stock value average', 'woocommerce-jetpack' ) . '</th>' . '<td>' . wc_price( $info['stock_price_average'] ) . '</td>' . '</tr>';
$html_header .= '<tr>' . '<th>' . __( 'Product stock average', 'woocommerce-jetpack' ) . '</th>' . '<td>' . number_format( $info['stock_average'], 2, '.', '' ) . '</td>' . '</tr>';
if ( 0 != $total_current_stock_purchase_price ) {
$html_header .= '<tr>' . '<th>' . __( 'Total current stock purchase price', 'woocommerce-jetpack' ) . '</th>' . '<td>' . wc_price( $total_current_stock_purchase_price ) . '</td>' . '</tr>';
}
$html_header .= '</tbody></table>';
$html_header .= '<br class="clear">';
$time_elapsed_html = '<p><em>' . __( 'Report was generated in: ', 'woocommerce-jetpack' ) . intval( microtime( true ) - $this->start_time ) . ' s' . '</em></p>';
return $this->get_submenu_html() . $html_header . $html . $time_elapsed_html;
}
}
endif;