Add progress bars to Historical Data Import screen (https://github.com/woocommerce/woocommerce-admin/pull/2312)

* Hook up import/status endpoint to Historical Data Import screen

* Fix PHP tests

* Add speak message when the import is complete

* Several fixes

* Cleanup

* Update progress bars every 3 seconds and bugfixes

* Rename ongoingImport to activeImport

* Use timestamp to identify queries

* Use timestamps for historical data state

* Add 'initializing' status

* Cleanup

* Pass less props around

* Refactor getStatus

* Set stop timestamp on request error

* Typo
This commit is contained in:
Albert Juhé Lluveras 2019-06-11 14:47:53 +02:00 committed by GitHub
parent 3123c4e047
commit 5d01cee56c
13 changed files with 424 additions and 152 deletions

View File

@ -7,19 +7,18 @@ import { Button } from '@wordpress/components';
import { Fragment } from '@wordpress/element';
function HistoricalDataActions( {
customersProgress,
customersTotal,
hasImportedData,
inProgress,
importDate,
onDeletePreviousData,
onReimportData,
onStartImport,
onStopImport,
ordersProgress,
ordersTotal,
status,
} ) {
const getActions = () => {
const importDisabled = status !== 'ready';
// An import is currently in progress
if ( inProgress ) {
if ( [ 'initializing', 'customers', 'orders', 'finalizing' ].includes( status ) ) {
return (
<Fragment>
<Button
@ -44,42 +43,34 @@ function HistoricalDataActions( {
);
}
// Has no imported data
if ( ! hasImportedData ) {
// @todo When the import status endpoint is hooked up,
// the 'Delete Previously Imported Data' button should be
// removed from this section.
if ( [ 'ready', 'nothing' ].includes( status ) ) {
if ( importDate ) {
return (
<Fragment>
<Button isPrimary onClick={ onStartImport } disabled={ importDisabled }>
{ __( 'Start', 'woocommerce-admin' ) }
</Button>
<Button isDefault onClick={ onDeletePreviousData }>
{ __( 'Delete Previously Imported Data', 'woocommerce-admin' ) }
</Button>
</Fragment>
);
}
return (
<Fragment>
<Button isPrimary onClick={ onStartImport }>
<Button isPrimary onClick={ onStartImport } disabled={ importDisabled }>
{ __( 'Start', 'woocommerce-admin' ) }
</Button>
<Button isDefault onClick={ onDeletePreviousData }>
{ __( 'Delete Previously Imported Data', 'woocommerce-admin' ) }
</Button>
</Fragment>
);
}
// Has imported all possible data
if ( customersProgress === customersTotal && ordersProgress === ordersTotal ) {
return (
<Fragment>
<Button isDefault onClick={ () => null }>
{ __( 'Re-import Data', 'woocommerce-admin' ) }
</Button>
<Button isDefault onClick={ onDeletePreviousData }>
{ __( 'Delete Previously Imported Data', 'woocommerce-admin' ) }
</Button>
</Fragment>
);
}
// It's not in progress and has some imported data
return (
<Fragment>
<Button isPrimary onClick={ onStartImport }>
{ __( 'Start', 'woocommerce-admin' ) }
<Button isDefault onClick={ onReimportData }>
{ __( 'Re-import Data', 'woocommerce-admin' ) }
</Button>
<Button isDefault onClick={ onDeletePreviousData }>
{ __( 'Delete Previously Imported Data', 'woocommerce-admin' ) }

View File

@ -6,6 +6,7 @@ import { __ } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';
import { Component } from '@wordpress/element';
import moment from 'moment';
import { withSpokenMessages } from '@wordpress/components';
/**
* WooCommerce dependencies
@ -25,7 +26,11 @@ class HistoricalData extends Component {
this.dateFormat = __( 'MM/DD/YYYY', 'woocommerce-admin' );
this.state = {
inProgress: false,
// Whether there is an active import (which might have been stopped)
// that matches the period and skipChecked settings
activeImport: null,
lastImportStartTimestamp: 0,
lastImportStopTimestamp: 0,
period: {
date: moment().format( this.dateFormat ),
label: 'all',
@ -34,7 +39,10 @@ class HistoricalData extends Component {
};
this.makeQuery = this.makeQuery.bind( this );
this.onImportFinished = this.onImportFinished.bind( this );
this.onImportStarted = this.onImportStarted.bind( this );
this.onDeletePreviousData = this.onDeletePreviousData.bind( this );
this.onReimportData = this.onReimportData.bind( this );
this.onStartImport = this.onStartImport.bind( this );
this.onStopImport = this.onStopImport.bind( this );
this.onDateChange = this.onDateChange.bind( this );
@ -50,15 +58,38 @@ class HistoricalData extends Component {
addNotice( { status: 'success', message: response.message } );
} else {
addNotice( { status: 'error', message: errorMessage } );
this.setState( {
activeImport: false,
lastImportStopTimestamp: Date.now(),
} );
}
} )
.catch( error => {
if ( error && error.message ) {
addNotice( { status: 'error', message: error.message } );
this.setState( {
activeImport: false,
lastImportStopTimestamp: Date.now(),
} );
}
} );
}
onImportFinished() {
const { debouncedSpeak } = this.props;
debouncedSpeak( 'Import complete' );
this.setState( {
lastImportStopTimestamp: Date.now(),
} );
}
onImportStarted() {
this.setState( {
activeImport: true,
lastImportStartTimestamp: Date.now(),
} );
}
onDeletePreviousData() {
const path = '/wc/v4/reports/import/delete';
const errorMessage = __(
@ -66,24 +97,33 @@ class HistoricalData extends Component {
'woocommerce-admin'
);
this.makeQuery( path, errorMessage );
this.setState( {
activeImport: false,
} );
}
onReimportData() {
this.setState( {
activeImport: false,
} );
}
onStartImport() {
const { period, skipChecked } = this.state;
this.setState( {
inProgress: true,
} );
const path = '/wc/v4/reports/import' + stringifyQuery( formatParams( period, skipChecked ) );
const path =
'/wc/v4/reports/import' +
stringifyQuery( formatParams( this.dateFormat, period, skipChecked ) );
const errorMessage = __(
'There was a problem rebuilding your report data.',
'woocommerce-admin'
);
this.makeQuery( path, errorMessage );
this.onImportStarted();
}
onStopImport() {
this.setState( {
inProgress: false,
lastImportStopTimestamp: Date.now(),
} );
const path = '/wc/v4/reports/import/cancel';
const errorMessage = __(
@ -95,6 +135,7 @@ class HistoricalData extends Component {
onPeriodChange( val ) {
this.setState( {
activeImport: false,
period: {
...this.state.period,
label: val,
@ -104,6 +145,7 @@ class HistoricalData extends Component {
onDateChange( val ) {
this.setState( {
activeImport: false,
period: {
date: val,
label: 'custom',
@ -113,21 +155,33 @@ class HistoricalData extends Component {
onSkipChange( val ) {
this.setState( {
activeImport: false,
skipChecked: val,
} );
}
render() {
const { inProgress, period, skipChecked } = this.state;
const {
activeImport,
lastImportStartTimestamp,
lastImportStopTimestamp,
period,
skipChecked,
} = this.state;
return (
<HistoricalDataLayout
activeImport={ activeImport }
dateFormat={ this.dateFormat }
inProgress={ inProgress }
onImportFinished={ this.onImportFinished }
onImportStarted={ this.onImportStarted }
lastImportStartTimestamp={ lastImportStartTimestamp }
lastImportStopTimestamp={ lastImportStopTimestamp }
onPeriodChange={ this.onPeriodChange }
onDateChange={ this.onDateChange }
onSkipChange={ this.onSkipChange }
onDeletePreviousData={ this.onDeletePreviousData }
onReimportData={ this.onReimportData }
onStartImport={ this.onStartImport }
onStopImport={ this.onStopImport }
period={ period }
@ -137,4 +191,4 @@ class HistoricalData extends Component {
}
}
export default HistoricalData;
export default withSpokenMessages( HistoricalData );

View File

@ -4,11 +4,14 @@
*/
import { __ } from '@wordpress/i18n';
import { Component, Fragment } from '@wordpress/element';
import { isNil } from 'lodash';
import { SECOND } from '@fresh-data/framework';
/**
* Internal dependencies
*/
import { formatParams } from './utils';
import { DEFAULT_REQUIREMENT } from 'wc-api/constants';
import { formatParams, getStatus } from './utils';
import HistoricalDataActions from './actions';
import HistoricalDataPeriodSelector from './period-selector';
import HistoricalDataProgress from './progress';
@ -18,46 +21,18 @@ import withSelect from 'wc-api/with-select';
import './style.scss';
class HistoricalDataLayout extends Component {
getStatus() {
const {
customersProgress,
customersTotal,
inProgress,
ordersProgress,
ordersTotal,
} = this.props;
if ( inProgress ) {
if ( customersProgress < customersTotal ) {
return 'customers';
}
if ( ordersProgress < ordersTotal ) {
return 'orders';
}
return 'finalizing';
}
if (
( customersTotal > 0 || ordersTotal > 0 ) &&
customersProgress === customersTotal &&
ordersProgress === ordersTotal
) {
return 'finished';
}
return 'ready';
}
render() {
const {
customersProgress,
customersTotal,
dateFormat,
hasImportedData,
importDate,
inProgress,
onPeriodChange,
onDateChange,
onSkipChange,
onDeletePreviousData,
onReimportData,
onStartImport,
onStopImport,
ordersProgress,
@ -65,14 +40,13 @@ class HistoricalDataLayout extends Component {
period,
skipChecked,
} = this.props;
const hasImportedAllData =
! inProgress &&
hasImportedData &&
customersProgress === customersTotal &&
ordersProgress === ordersTotal;
// @todo When the import status endpoint is hooked up,
// this bool should be removed and assume it's true.
const showImportStatus = false;
const status = getStatus( {
customersProgress,
customersTotal,
inProgress,
ordersProgress,
ordersTotal,
} );
return (
<Fragment>
@ -88,7 +62,7 @@ class HistoricalDataLayout extends Component {
'woocommerce-admin'
) }
</span>
{ ! hasImportedAllData && (
{ status !== 'finished' && (
<Fragment>
<HistoricalDataPeriodSelector
dateFormat={ dateFormat }
@ -102,37 +76,28 @@ class HistoricalDataLayout extends Component {
checked={ skipChecked }
onChange={ onSkipChange }
/>
{ showImportStatus && (
<Fragment>
<HistoricalDataProgress
label={ __( 'Registered Customers', 'woocommerce-admin' ) }
progress={ customersProgress }
total={ customersTotal }
/>
<HistoricalDataProgress
label={ __( 'Orders', 'woocommerce-admin' ) }
progress={ ordersProgress }
total={ ordersTotal }
/>
</Fragment>
) }
<HistoricalDataProgress
label={ __( 'Registered Customers', 'woocommerce-admin' ) }
progress={ customersProgress }
total={ customersTotal }
/>
<HistoricalDataProgress
label={ __( 'Orders', 'woocommerce-admin' ) }
progress={ ordersProgress }
total={ ordersTotal }
/>
</Fragment>
) }
{ showImportStatus && (
<HistoricalDataStatus importDate={ importDate } status={ this.getStatus() } />
) }
<HistoricalDataStatus importDate={ importDate } status={ status } />
</div>
</div>
<HistoricalDataActions
customersProgress={ customersProgress }
customersTotal={ customersTotal }
hasImportedData={ hasImportedData }
inProgress={ inProgress }
importDate={ importDate }
onDeletePreviousData={ onDeletePreviousData }
onReimportData={ onReimportData }
onStartImport={ onStartImport }
onStopImport={ onStopImport }
ordersProgress={ ordersProgress }
ordersTotal={ ordersTotal }
status={ status }
/>
</Fragment>
);
@ -140,19 +105,75 @@ class HistoricalDataLayout extends Component {
}
export default withSelect( ( select, props ) => {
const { getImportTotals } = select( 'wc-api' );
const { period, skipChecked } = props;
const { getImportStatus, isGetImportStatusRequesting, getImportTotals } = select( 'wc-api' );
const {
activeImport,
dateFormat,
lastImportStartTimestamp,
lastImportStopTimestamp,
onImportStarted,
onImportFinished,
period,
skipChecked,
} = props;
const { customers: customersTotal, orders: ordersTotal } = getImportTotals(
formatParams( period, skipChecked )
const inProgress =
( typeof lastImportStartTimestamp !== 'undefined' &&
typeof lastImportStopTimestamp === 'undefined' ) ||
lastImportStartTimestamp > lastImportStopTimestamp;
const params = formatParams( dateFormat, period, skipChecked );
// Use timestamp to invalidate previous totals when the import finished/stopped
const { customers, orders } = getImportTotals( params, lastImportStopTimestamp );
const requirement = inProgress
? {
freshness: 3 * SECOND,
timeout: 3 * SECOND,
}
: DEFAULT_REQUIREMENT;
// Use timestamp to invalidate previous status when a new import starts
const {
customers_count: customersProgress,
customers_total: customersTotal,
imported_from: importDate,
is_importing: isImporting,
orders_count: ordersProgress,
orders_total: ordersTotal,
} = getImportStatus( lastImportStartTimestamp, requirement );
const isStatusLoading = isGetImportStatusRequesting( lastImportStartTimestamp );
const hasImportStarted = Boolean(
! lastImportStartTimestamp && ! isStatusLoading && ! inProgress && isImporting === true
);
if ( hasImportStarted ) {
onImportStarted();
}
const hasImportFinished = Boolean(
! isStatusLoading &&
inProgress &&
isImporting === false &&
( ( customersProgress === customersTotal && customersTotal > 0 ) ||
( ordersProgress === ordersTotal && ordersTotal > 0 ) )
);
if ( hasImportFinished ) {
onImportFinished();
}
if ( ! activeImport ) {
return {
customersTotal: customers,
importDate,
ordersTotal: orders,
};
}
return {
customersProgress: 0,
customersTotal,
hasImportedData: false,
importDate: '2019-04-01',
ordersProgress: 0,
ordersTotal,
customersProgress,
customersTotal: isNil( customersTotal ) ? customers : customersTotal,
importDate,
inProgress,
ordersProgress,
ordersTotal: isNil( ordersTotal ) ? orders : ordersTotal,
};
} )( HistoricalDataLayout );

View File

@ -10,13 +10,12 @@ function HistoricalDataProgress( { label, progress, total } ) {
label,
} );
const labelCounters =
! isNil( progress ) && ! isNil( total )
? sprintf( __( '%(progress)s of %(total)s', 'woocommerce-admin' ), {
progress,
total,
} )
: null;
const labelCounters = ! isNil( total )
? sprintf( __( '%(progress)s of %(total)s', 'woocommerce-admin' ), {
progress: progress || 0,
total,
} )
: null;
return (
<div className="woocommerce-settings-historical-data__progress">
@ -29,7 +28,7 @@ function HistoricalDataProgress( { label, progress, total } ) {
<progress
className="woocommerce-settings-historical-data__progress-bar"
max={ total }
value={ progress }
value={ progress || 0 }
/>
</div>
);

View File

@ -16,13 +16,15 @@ const HISTORICAL_DATA_STATUS_FILTER = 'woocommerce_admin_import_status';
function HistoricalDataStatus( { importDate, status } ) {
const statusLabels = applyFilters( HISTORICAL_DATA_STATUS_FILTER, {
nothing: __( 'Nothing To Import', 'woocommerce-admin' ),
ready: __( 'Ready To Import', 'woocommerce-admin' ),
initializing: [ __( 'Initializing', 'woocommerce-admin' ), <Spinner key="spinner" /> ],
customers: [ __( 'Importing Customers', 'woocommerce-admin' ), <Spinner key="spinner" /> ],
orders: [ __( 'Importing Orders', 'woocommerce-admin' ), <Spinner key="spinner" /> ],
finalizing: [ __( 'Finalizing', 'woocommerce-admin' ), <Spinner key="spinner" /> ],
finished: sprintf(
__( 'Historical data from %s onward imported', 'woocommerce-admin' ),
moment( importDate ).format( 'll' )
importDate !== '-1' ? moment( importDate ).format( 'll' ) : ''
),
} );

View File

@ -4,10 +4,10 @@
display: grid;
grid-column-gap: $gap-large;
grid-template-columns: calc(50% - #{$gap-large/2}) calc(50% - #{$gap-large/2});
margin-top: $gap-small;
.woocommerce-settings-historical-data__column {
align-self: end;
margin-top: $gap-small;
// Auto-position fix for IE11.
@include set-grid-item-position( 2, 2 );
}

View File

@ -0,0 +1,123 @@
/** @format */
/**
* External dependencies
*/
import moment from 'moment';
/**
* Internal dependencies
*/
import { formatParams, getStatus } from '../utils';
describe( 'formatParams', () => {
it( 'returns empty object when skipChecked is false and period is all', () => {
expect( formatParams( 'YYYY-MM-DD', { label: 'all' }, false ) ).toEqual( {} );
} );
it( 'returns skip_existing param', () => {
expect( formatParams( 'YYYY-MM-DD', { label: 'all' }, true ) ).toEqual( {
skip_existing: true,
} );
} );
it( 'returns correct days param based on period label', () => {
expect( formatParams( 'YYYY-MM-DD', { label: '30' }, false ) ).toEqual( { days: 30 } );
} );
it( 'returns correct days param based on period date', () => {
const date = '2018-01-01';
const days = Math.floor( moment().diff( moment( date, 'YYYY-MM-DD' ), 'days', true ) );
expect( formatParams( 'YYYY-MM-DD', { label: 'custom', date }, false ) ).toEqual( { days } );
} );
it( 'returns both params', () => {
expect( formatParams( 'YYYY-MM-DD', { label: '30' }, true ) ).toEqual( {
skip_existing: true,
days: 30,
} );
} );
} );
describe( 'getStatus', () => {
it( 'returns `initializing` when no progress numbers are defined', () => {
expect(
getStatus( {
customersTotal: 1,
inProgress: true,
ordersTotal: 1,
} )
).toEqual( 'initializing' );
} );
it( 'returns `customers` when importing customers', () => {
expect(
getStatus( {
customersProgress: 0,
customersTotal: 1,
inProgress: true,
ordersProgress: 0,
ordersTotal: 1,
} )
).toEqual( 'customers' );
} );
it( 'returns `orders` when importing orders', () => {
expect(
getStatus( {
customersProgress: 1,
customersTotal: 1,
inProgress: true,
ordersProgress: 0,
ordersTotal: 1,
} )
).toEqual( 'orders' );
} );
it( 'returns `finalizing` when customers and orders are already imported', () => {
expect(
getStatus( {
customersProgress: 1,
customersTotal: 1,
inProgress: true,
ordersProgress: 1,
ordersTotal: 1,
} )
).toEqual( 'finalizing' );
} );
it( 'returns `finished` when customers and orders are already imported and inProgress is false', () => {
expect(
getStatus( {
customersProgress: 1,
customersTotal: 1,
inProgress: false,
ordersProgress: 1,
ordersTotal: 1,
} )
).toEqual( 'finished' );
} );
it( 'returns `ready` when there are customers or orders to import', () => {
expect(
getStatus( {
customersProgress: 0,
customersTotal: 1,
inProgress: false,
ordersProgress: 0,
ordersTotal: 1,
} )
).toEqual( 'ready' );
} );
it( 'returns `nothing` when there are no customers or orders to import', () => {
expect(
getStatus( {
customersProgress: 0,
customersTotal: 0,
inProgress: false,
ordersProgress: 0,
ordersTotal: 0,
} )
).toEqual( 'nothing' );
} );
} );

View File

@ -2,17 +2,18 @@
/**
* External dependencies
*/
import { isNil } from 'lodash';
import moment from 'moment';
export const formatParams = ( period, skipChecked ) => {
export const formatParams = ( dateFormat, period, skipChecked ) => {
const params = {};
if ( skipChecked ) {
params.skip_existing = true;
}
if ( period.label !== 'all' ) {
if ( period.label === 'custom' ) {
const daysDifference = moment().diff( moment( period.date, this.dateFormat ), 'days', true );
params.days = Math.ceil( daysDifference );
const daysDifference = moment().diff( moment( period.date, dateFormat ), 'days', true );
params.days = Math.floor( daysDifference );
} else {
params.days = parseInt( period.label, 10 );
}
@ -20,3 +21,36 @@ export const formatParams = ( period, skipChecked ) => {
return params;
};
export const getStatus = ( {
customersProgress,
customersTotal,
inProgress,
ordersProgress,
ordersTotal,
} ) => {
if ( inProgress ) {
if (
isNil( customersProgress ) ||
isNil( ordersProgress ) ||
isNil( customersTotal ) ||
isNil( ordersTotal )
) {
return 'initializing';
}
if ( customersProgress < customersTotal ) {
return 'customers';
}
if ( ordersProgress < ordersTotal ) {
return 'orders';
}
return 'finalizing';
}
if ( customersTotal > 0 || ordersTotal > 0 ) {
if ( customersProgress === customersTotal && ordersProgress === ordersTotal ) {
return 'finished';
}
return 'ready';
}
return 'nothing';
};

View File

@ -3,6 +3,7 @@
* External dependencies
*/
import apiFetch from '@wordpress/api-fetch';
import { omit } from 'lodash';
/**
* WooCommerce dependencies
@ -12,25 +13,35 @@ import { stringifyQuery } from '@woocommerce/navigation';
/**
* Internal dependencies
*/
import { isResourcePrefix, getResourceIdentifier } from '../utils';
import { getResourcePrefix, getResourceIdentifier } from '../utils';
import { NAMESPACE } from '../constants';
const typeEndpointMap = {
'import-status': 'reports/import/status',
'import-totals': 'reports/import/totals',
};
function read( resourceNames, fetch = apiFetch ) {
const filteredNames = resourceNames.filter( name => isResourcePrefix( name, 'import-totals' ) );
const filteredNames = resourceNames.filter( name => {
const prefix = getResourcePrefix( name );
return Boolean( typeEndpointMap[ prefix ] );
} );
return filteredNames.map( async resourceName => {
const prefix = getResourcePrefix( resourceName );
const endpoint = typeEndpointMap[ prefix ];
const query = getResourceIdentifier( resourceName );
const fetchArgs = {
parse: false,
path: NAMESPACE + '/reports/import/totals' + stringifyQuery( query ),
path: NAMESPACE + `/${ endpoint }${ stringifyQuery( omit( query, [ 'timestamp' ] ) ) }`,
};
try {
const response = await fetch( fetchArgs );
const totals = await response.json();
const data = await response.json();
return {
[ resourceName ]: totals,
[ resourceName ]: { data },
};
} catch ( error ) {
return { [ resourceName ]: { error } };

View File

@ -1,4 +1,8 @@
/** @format */
/**
* External dependencies
*/
import { isNil } from 'lodash';
/**
* Internal dependencies
@ -6,14 +10,37 @@
import { getResourceName } from '../utils';
import { DEFAULT_REQUIREMENT } from '../constants';
const getImportTotals = ( getResource, requireResource ) => (
query = {},
const getImportStatus = ( getResource, requireResource ) => (
timestamp,
requirement = DEFAULT_REQUIREMENT
) => {
const resourceName = getResourceName( 'import-totals', query );
return requireResource( requirement, resourceName ) || { customers: null, orders: null };
const resourceName = getResourceName( 'import-status', timestamp );
return requireResource( requirement, resourceName ).data || {};
};
const isGetImportStatusRequesting = getResource => timestamp => {
const resourceName = getResourceName( 'import-status', timestamp );
const { lastRequested, lastReceived } = getResource( resourceName );
if ( isNil( lastRequested ) || isNil( lastReceived ) ) {
return true;
}
return lastRequested > lastReceived;
};
const getImportTotals = ( getResource, requireResource ) => (
query = {},
timestamp,
requirement = DEFAULT_REQUIREMENT
) => {
const identifier = { ...query, timestamp };
const resourceName = getResourceName( 'import-totals', identifier );
return requireResource( requirement, resourceName ).data || {};
};
export default {
getImportStatus,
isGetImportStatusRequesting,
getImportTotals,
};

View File

@ -187,7 +187,7 @@ class WC_Admin_REST_Reports_Import_Controller extends WC_Admin_REST_Reports_Cont
'type' => 'integer',
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
'minimum' => 1,
'minimum' => 0,
);
$params['skip_existing'] = array(
'description' => __( 'Skip importing existing order data.', 'woocommerce-admin' ),
@ -284,10 +284,10 @@ class WC_Admin_REST_Reports_Import_Controller extends WC_Admin_REST_Reports_Cont
public function get_import_status( $request ) {
$result = array(
'is_importing' => WC_Admin_Reports_Sync::is_importing(),
'customers_total' => get_option( 'wc_admin_import_customers_total', 0 ),
'customers_count' => get_option( 'wc_admin_import_customers_count', 0 ),
'orders_total' => get_option( 'wc_admin_import_orders_total', 0 ),
'orders_count' => get_option( 'wc_admin_import_orders_count', 0 ),
'customers_total' => (int) get_option( 'wc_admin_import_customers_total', 0 ),
'customers_count' => (int) get_option( 'wc_admin_import_customers_count', 0 ),
'orders_total' => (int) get_option( 'wc_admin_import_orders_total', 0 ),
'orders_count' => (int) get_option( 'wc_admin_import_orders_count', 0 ),
'imported_from' => get_option( 'wc_admin_imported_from_date', false ),
);

View File

@ -161,12 +161,14 @@ class WC_Admin_Reports_Sync {
*/
public static function get_import_totals( $days, $skip_existing ) {
$orders = self::get_orders( 1, 1, $days, $skip_existing );
$customer_roles = apply_filters( 'woocommerce_admin_import_customer_roles', array( 'customer' ) );
$customer_query = self::get_user_ids_for_batch(
$days,
$skip_existing,
array(
'fields' => 'ID',
'number' => 1,
'fields' => 'ID',
'number' => 1,
'role__in' => $customer_roles,
)
);
@ -187,6 +189,7 @@ class WC_Admin_Reports_Sync {
'status' => 'pending',
'per_page' => 1,
'claimed' => false,
'search' => 'import',
'group' => self::QUEUE_GROUP,
)
);
@ -235,6 +238,13 @@ class WC_Admin_Reports_Sync {
// Delete customers after order data is deleted.
self::queue_dependent_action( self::CUSTOMERS_DELETE_BATCH_INIT, array(), self::ORDERS_DELETE_BATCH_INIT );
// Delete import options.
delete_option( 'wc_admin_import_customers_count' );
delete_option( 'wc_admin_import_orders_count' );
delete_option( 'wc_admin_import_customers_total' );
delete_option( 'wc_admin_import_orders_total' );
delete_option( 'wc_admin_imported_from_date' );
return __( 'Report table data is being deleted.', 'woocommerce-admin' );
}
@ -334,9 +344,9 @@ class WC_Admin_Reports_Sync {
public static function get_orders( $limit = 10, $page = 1, $days = false, $skip_existing = false ) {
global $wpdb;
$where_clause = '';
$offset = $page > 1 ? $page * $limit : 0;
$offset = $page > 1 ? ( $page - 1 ) * $limit : 0;
if ( $days ) {
if ( is_int( $days ) ) {
$days_ago = date( 'Y-m-d 00:00:00', time() - ( DAY_IN_SECONDS * $days ) );
$where_clause .= " AND post_date >= '{$days_ago}'";
}
@ -564,7 +574,7 @@ class WC_Admin_Reports_Sync {
$query_args = array();
}
if ( $days ) {
if ( is_int( $days ) ) {
$query_args['date_query'] = array(
'after' => date( 'Y-m-d 00:00:00', time() - ( DAY_IN_SECONDS * $days ) ),
);
@ -587,7 +597,7 @@ class WC_Admin_Reports_Sync {
* Init customer lookup table update (in batches).
*
* @param int|bool $days Number of days to process.
* @param bool $skip_existing Skip exisiting records.
* @param bool $skip_existing Skip existing records.
*/
public static function customer_lookup_import_batch_init( $days, $skip_existing ) {
$batch_size = self::get_batch_size( self::CUSTOMERS_IMPORT_BATCH_ACTION );

View File

@ -330,8 +330,9 @@ class WC_Tests_API_Reports_Import extends WC_REST_Unit_Test_Case {
$report = $response->get_data();
$user_query = new WP_User_Query(
array(
'fields' => 'ID',
'number' => 1,
'fields' => 'ID',
'number' => 1,
'role__in' => array( 'customer' ),
)
);
@ -363,7 +364,7 @@ class WC_Tests_API_Reports_Import extends WC_REST_Unit_Test_Case {
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( true, $report['is_importing'] );
$this->assertEquals( 0, $report['customers_count'] );
$this->assertEquals( 3, $report['customers_total'] );
$this->assertEquals( 1, $report['customers_total'] );
$this->assertEquals( 0, $report['orders_count'] );
$this->assertEquals( 4, $report['orders_total'] );
@ -380,7 +381,7 @@ class WC_Tests_API_Reports_Import extends WC_REST_Unit_Test_Case {
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( false, $report['is_importing'] );
$this->assertEquals( 1, $report['customers_count'] );
$this->assertEquals( 3, $report['customers_total'] );
$this->assertEquals( 1, $report['customers_total'] );
$this->assertEquals( 4, $report['orders_count'] );
$this->assertEquals( 4, $report['orders_total'] );
@ -390,8 +391,7 @@ class WC_Tests_API_Reports_Import extends WC_REST_Unit_Test_Case {
$response = $this->server->dispatch( $request );
$report = $response->get_data();
// @todo The following line should be uncommented when https://github.com/woocommerce/woocommerce-admin/issues/2195 is resolved.
// $this->assertEquals( 0, $report['customers'] );
$this->assertEquals( 0, $report['customers'] );
$this->assertEquals( 0, $report['orders'] );
}
}