Taxes Report: allow segmentation by tax

This commit is contained in:
Paul Sealock 2019-02-14 17:03:00 +13:00
parent e6b0f3476c
commit 62a6b619d9
4 changed files with 90 additions and 17 deletions

View File

@ -3,11 +3,17 @@
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';
import { find } from 'lodash';
/**
* WooCommerce dependencies
*/
import { getIdsFromQuery, stringifyQuery } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
import { getRequestByIdString } from 'lib/async-requests';
import { getTaxCode } from './utils';
import { NAMESPACE } from 'wc-api/constants';
@ -52,15 +58,30 @@ export const filters = [
{ label: __( 'All Taxes', 'wc-admin' ), value: 'all' },
{
label: __( 'Comparison', 'wc-admin' ),
value: 'compare-tax-codes',
value: 'compare-taxes',
chartMode: 'item-comparison',
settings: {
type: 'taxes',
param: 'taxes',
getLabels: getRequestByIdString( NAMESPACE + '/taxes', tax => ( {
id: tax.id,
label: getTaxCode( tax ),
} ) ),
// @TODO: Core /taxes endpoint should support a collection param 'include'.
getLabels: function( queryString = '' ) {
const idList = getIdsFromQuery( queryString );
if ( idList.length < 1 ) {
return Promise.resolve( [] );
}
const payload = stringifyQuery( {
per_page: -1,
} );
return apiFetch( { path: NAMESPACE + '/taxes' + payload } ).then( taxes => {
return idList.map( id => {
const tax = find( taxes, { id } );
return {
id: tax.id,
label: getTaxCode( tax ),
};
} );
} );
},
labels: {
helpText: __( 'Select at least two tax codes to compare', 'wc-admin' ),
placeholder: __( 'Search for tax codes to compare', 'wc-admin' ),

View File

@ -4,6 +4,7 @@
*/
import { Component, Fragment } from '@wordpress/element';
import PropTypes from 'prop-types';
import { __ } from '@wordpress/i18n';
/**
* WooCommerce dependencies
@ -20,22 +21,46 @@ import ReportSummary from 'analytics/components/report-summary';
import TaxesReportTable from './table';
export default class TaxesReport extends Component {
getChartMeta() {
const { query } = this.props;
const isCompareTaxView = 'compare-taxes' === query.filter;
const mode = isCompareTaxView ? 'item-comparison' : 'time-comparison';
const itemsLabel = __( '%d taxes', 'wc-admin' );
return {
itemsLabel,
mode,
};
}
render() {
const { query, path } = this.props;
const { mode, itemsLabel } = this.getChartMeta();
const chartQuery = {
...query,
};
if ( 'item-comparison' === mode ) {
chartQuery.segmentby = 'tax_rate_id';
}
return (
<Fragment>
<ReportFilters query={ query } path={ path } filters={ filters } />
<ReportSummary
charts={ charts }
endpoint="taxes"
query={ query }
query={ chartQuery }
selectedChart={ getSelectedChart( query.chart, charts ) }
/>
<ReportChart
filters={ filters }
charts={ charts }
mode={ mode }
endpoint="taxes"
query={ chartQuery }
path={ path }
query={ query }
itemsLabel={ itemsLabel }
selectedChart={ getSelectedChart( query.chart, charts ) }
/>
<TaxesReportTable query={ query } />

View File

@ -355,6 +355,7 @@ class WC_Admin_Reports_Segmenting {
$args['include'] = $this->query_args['categories'];
}
// @todo: Look into `wc_get_products` or data store methods and not directly touching the database or post types.
$categories = get_categories( $args );
$segments = wp_list_pluck( $categories, 'cat_ID' );
@ -374,15 +375,17 @@ class WC_Admin_Reports_Segmenting {
// 1 -- returning customer
$segments = array( 0, 1 );
} elseif ( 'tax_rate_id' === $this->query_args['segmentby'] ) {
// @todo Do we need to include tax rates that existed in the past, but have never been used? I guess there are other, more pressing problems...
// Current tax rates UNION previously used tax rates.
$tax_rate_ids = $wpdb->get_results(
"SELECT tax_rate_id FROM {$wpdb->prefix}woocommerce_tax_rates
UNION
SELECT DISTINCT meta_value FROM {$wpdb->prefix}woocommerce_order_itemmeta where meta_key='rate_id'",
ARRAY_A
); // WPCS: cache ok, DB call ok, unprepared SQL ok.
$segments = wp_list_pluck( $tax_rate_ids, 'tax_rate_id' );
$args = array();
if ( isset( $this->query_args['taxes'] ) ) {
$args['include'] = $this->query_args['taxes'];
}
$taxes = WC_Admin_Reports_Taxes_Stats_Data_Store::get_taxes( $args );
foreach ( $taxes as $tax ) {
$id = $tax['tax_rate_id'];
$segments[] = $id;
$segment_labels[ $id ] = WC_Tax::get_rate_code( (object) $tax );
}
} else {
// Catch all default.
$segments = array();

View File

@ -102,6 +102,30 @@ class WC_Admin_Reports_Taxes_Stats_Data_Store extends WC_Admin_Reports_Data_Stor
$intervals_params['where_clause'] .= $taxes_where_clause;
}
/**
* Get taxes associated with a store.
*
* @param array $args Array of args to filter the query by. Supports `include`.
* @return array An array of all taxes.
*/
public static function get_taxes( $args ) {
global $wpdb;
$query = "
SELECT
tax_rate_id,
tax_rate_country,
tax_rate_state,
tax_rate_name,
tax_rate_priority
FROM {$wpdb->prefix}woocommerce_tax_rates
";
if ( ! empty( $args['include'] ) ) {
$included_taxes = implode( ',', $args['include'] );
$query .= " WHERE tax_rate_id IN ({$included_taxes})";
}
return $wpdb->get_results( $query, ARRAY_A ); // WPCS: cache ok, DB call ok, unprepared SQL ok.
}
/**
* Returns the report data based on parameters supplied by the user.
*