Add product categories wc-api and breadcrumbs (https://github.com/woocommerce/woocommerce-admin/pull/1131)
* Add support for product cats in wp rest api * Add categories to WC API * Add category breadcrumbs component * Increase per_page limit size for product cat API * Use wc/v3 API to pull product categories * Return category IDs in API * Add categories to product reports * Add category IDs test for REST API * Switch to getResource instead of require for total count selector
This commit is contained in:
parent
47b674ace2
commit
f83b0e0615
|
@ -0,0 +1,67 @@
|
||||||
|
/** @format */
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { Component } from '@wordpress/element';
|
||||||
|
import { first, last } from 'lodash';
|
||||||
|
import { Spinner } from '@wordpress/components';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WooCommerce dependencies
|
||||||
|
*/
|
||||||
|
import { Link } from '@woocommerce/components';
|
||||||
|
|
||||||
|
export default class CategoryBreadcrumbs extends Component {
|
||||||
|
getCategoryAncestorIds( category, categories ) {
|
||||||
|
const ancestors = [];
|
||||||
|
let parent = category.parent;
|
||||||
|
while ( parent ) {
|
||||||
|
ancestors.unshift( parent );
|
||||||
|
parent = categories[ parent ].parent;
|
||||||
|
}
|
||||||
|
return ancestors;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCategoryAncestors( category, categories ) {
|
||||||
|
const ancestorIds = this.getCategoryAncestorIds( category, categories );
|
||||||
|
|
||||||
|
if ( ! ancestorIds.length ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( ancestorIds.length === 1 ) {
|
||||||
|
return categories[ first( ancestorIds ) ].name + ' › ';
|
||||||
|
}
|
||||||
|
if ( ancestorIds.length === 2 ) {
|
||||||
|
return (
|
||||||
|
categories[ first( ancestorIds ) ].name +
|
||||||
|
' › ' +
|
||||||
|
categories[ last( ancestorIds ) ].name +
|
||||||
|
' › '
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
categories[ first( ancestorIds ) ].name +
|
||||||
|
' … ' +
|
||||||
|
categories[ last( ancestorIds ) ].name +
|
||||||
|
' › '
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { categories, category } = this.props;
|
||||||
|
|
||||||
|
return category ? (
|
||||||
|
<div className="woocommerce-table__breadcrumbs">
|
||||||
|
{ this.getCategoryAncestors( category, categories ) }
|
||||||
|
<Link
|
||||||
|
href={ 'term.php?taxonomy=product_cat&post_type=product&tag_ID=' + category.id }
|
||||||
|
type="wp-admin"
|
||||||
|
>
|
||||||
|
{ category.name }
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Spinner />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,21 +4,23 @@
|
||||||
*/
|
*/
|
||||||
import { __, _n } from '@wordpress/i18n';
|
import { __, _n } from '@wordpress/i18n';
|
||||||
import { Component } from '@wordpress/element';
|
import { Component } from '@wordpress/element';
|
||||||
|
import { compose } from '@wordpress/compose';
|
||||||
import { map } from 'lodash';
|
import { map } from 'lodash';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WooCommerce dependencies
|
* WooCommerce dependencies
|
||||||
*/
|
*/
|
||||||
import { Link } from '@woocommerce/components';
|
|
||||||
import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
|
import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import ReportTable from 'analytics/components/report-table';
|
import CategoryBreacrumbs from './breadcrumbs';
|
||||||
import { numberFormat } from 'lib/number';
|
import { numberFormat } from 'lib/number';
|
||||||
|
import ReportTable from 'analytics/components/report-table';
|
||||||
|
import withSelect from 'wc-api/with-select';
|
||||||
|
|
||||||
export default class CategoriesReportTable extends Component {
|
class CategoriesReportTable extends Component {
|
||||||
constructor( props ) {
|
constructor( props ) {
|
||||||
super( props );
|
super( props );
|
||||||
|
|
||||||
|
@ -64,29 +66,16 @@ export default class CategoriesReportTable extends Component {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
getRowsContent( categories ) {
|
getRowsContent( categoryStats ) {
|
||||||
return map( categories, category => {
|
return map( categoryStats, categoryStat => {
|
||||||
const {
|
const { category_id, items_sold, net_revenue, products_count, orders_count } = categoryStat;
|
||||||
category_id,
|
const categories = this.props.categories;
|
||||||
items_sold,
|
const category = categories[ category_id ];
|
||||||
net_revenue,
|
|
||||||
products_count,
|
|
||||||
orders_count,
|
|
||||||
extended_info,
|
|
||||||
} = category;
|
|
||||||
const { name } = extended_info;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
display: (
|
display: <CategoryBreacrumbs category={ category } categories={ categories } />,
|
||||||
<Link
|
value: category && category.name,
|
||||||
href={ 'term.php?taxonomy=product_cat&post_type=product&tag_ID=' + category_id }
|
|
||||||
type="wp-admin"
|
|
||||||
>
|
|
||||||
{ name }
|
|
||||||
</Link>
|
|
||||||
),
|
|
||||||
value: name,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
display: numberFormat( items_sold ),
|
display: numberFormat( items_sold ),
|
||||||
|
@ -156,3 +145,15 @@ export default class CategoriesReportTable extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withSelect( select => {
|
||||||
|
const { getCategories, getCategoriesError, isGetCategoriesRequesting } = select( 'wc-api' );
|
||||||
|
|
||||||
|
const categories = getCategories();
|
||||||
|
const isError = Boolean( getCategoriesError() );
|
||||||
|
const isRequesting = isGetCategoriesRequesting();
|
||||||
|
|
||||||
|
return { categories, isError, isRequesting };
|
||||||
|
} )
|
||||||
|
)( CategoriesReportTable );
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
/** @format */
|
||||||
|
|
||||||
|
.woocommerce-table__product-categories {
|
||||||
|
> .woocommerce-table__breadcrumbs {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: $gap-small;
|
||||||
|
}
|
||||||
|
.components-popover__content {
|
||||||
|
padding: 0 $gap;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.components-popover__content .woocommerce-table__breadcrumbs {
|
||||||
|
margin-top: $gap-small;
|
||||||
|
margin-bottom: $gap-small;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,25 +2,29 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { __, _n, _x } from '@wordpress/i18n';
|
import { __, _n, _x, sprintf } from '@wordpress/i18n';
|
||||||
import { Component } from '@wordpress/element';
|
import { Component } from '@wordpress/element';
|
||||||
|
import { compose } from '@wordpress/compose';
|
||||||
import { map } from 'lodash';
|
import { map } from 'lodash';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WooCommerce dependencies
|
* WooCommerce dependencies
|
||||||
*/
|
*/
|
||||||
import { Link } from '@woocommerce/components';
|
|
||||||
import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
|
import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
|
||||||
import { getNewPath, getPersistedQuery } from '@woocommerce/navigation';
|
import { getNewPath, getPersistedQuery } from '@woocommerce/navigation';
|
||||||
|
import { Link, Tag } from '@woocommerce/components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import ReportTable from 'analytics/components/report-table';
|
import CategoryBreacrumbs from '../categories/breadcrumbs';
|
||||||
import { numberFormat } from 'lib/number';
|
|
||||||
import { isLowStock } from './utils';
|
import { isLowStock } from './utils';
|
||||||
|
import { numberFormat } from 'lib/number';
|
||||||
|
import ReportTable from 'analytics/components/report-table';
|
||||||
|
import withSelect from 'wc-api/with-select';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
export default class ProductsReportTable extends Component {
|
class ProductsReportTable extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
@ -96,10 +100,9 @@ export default class ProductsReportTable extends Component {
|
||||||
items_sold,
|
items_sold,
|
||||||
net_revenue,
|
net_revenue,
|
||||||
orders_count,
|
orders_count,
|
||||||
categories = [], // @TODO
|
|
||||||
variations = [], // @TODO
|
variations = [], // @TODO
|
||||||
} = row;
|
} = row;
|
||||||
const { name, stock_status, stock_quantity, low_stock_amount } = extended_info;
|
const { category_ids, low_stock_amount, name, stock_status, stock_quantity } = extended_info;
|
||||||
const ordersLink = getNewPath( persistedQuery, 'orders', {
|
const ordersLink = getNewPath( persistedQuery, 'orders', {
|
||||||
filter: 'advanced',
|
filter: 'advanced',
|
||||||
product_includes: product_id,
|
product_includes: product_id,
|
||||||
|
@ -108,6 +111,8 @@ export default class ProductsReportTable extends Component {
|
||||||
filter: 'single_product',
|
filter: 'single_product',
|
||||||
products: product_id,
|
products: product_id,
|
||||||
} );
|
} );
|
||||||
|
const categories = this.props.categories;
|
||||||
|
const productCategories = category_ids.map( category_id => categories[ category_id ] );
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
@ -139,10 +144,29 @@ export default class ProductsReportTable extends Component {
|
||||||
value: orders_count,
|
value: orders_count,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
display: Array.isArray( categories )
|
display: (
|
||||||
? categories.map( cat => cat.name ).join( ', ' )
|
<div className="woocommerce-table__product-categories">
|
||||||
: '',
|
{ productCategories[ 0 ] && (
|
||||||
value: Array.isArray( categories ) ? categories.map( cat => cat.name ).join( ', ' ) : '',
|
<CategoryBreacrumbs category={ productCategories[ 0 ] } categories={ categories } />
|
||||||
|
) }
|
||||||
|
{ productCategories.length > 1 && (
|
||||||
|
<Tag
|
||||||
|
label={ sprintf(
|
||||||
|
_x( '+%d more', 'categories', 'wc-admin' ),
|
||||||
|
productCategories.length - 1
|
||||||
|
) }
|
||||||
|
popoverContents={ productCategories.map( category => (
|
||||||
|
<CategoryBreacrumbs
|
||||||
|
category={ category }
|
||||||
|
categories={ categories }
|
||||||
|
key={ category.id }
|
||||||
|
/>
|
||||||
|
) ) }
|
||||||
|
/>
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
value: productCategories.map( category => category.name ).join( ', ' ),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
display: numberFormat( variations.length ),
|
display: numberFormat( variations.length ),
|
||||||
|
@ -219,3 +243,15 @@ export default class ProductsReportTable extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withSelect( select => {
|
||||||
|
const { getCategories, getCategoriesError, isGetCategoriesRequesting } = select( 'wc-api' );
|
||||||
|
|
||||||
|
const categories = getCategories();
|
||||||
|
const isError = Boolean( getCategoriesError() );
|
||||||
|
const isRequesting = isGetCategoriesRequesting();
|
||||||
|
|
||||||
|
return { categories, isError, isRequesting };
|
||||||
|
} )
|
||||||
|
)( ProductsReportTable );
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
/** @format */
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import operations from './operations';
|
||||||
|
import selectors from './selectors';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
operations,
|
||||||
|
selectors,
|
||||||
|
};
|
|
@ -0,0 +1,54 @@
|
||||||
|
/** @format */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import apiFetch from '@wordpress/api-fetch';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WooCommerce dependencies
|
||||||
|
*/
|
||||||
|
import { stringifyQuery } from '@woocommerce/navigation';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { isResourcePrefix, getResourceIdentifier, getResourceName } from '../utils';
|
||||||
|
|
||||||
|
function read( resourceNames, fetch = apiFetch ) {
|
||||||
|
const filteredNames = resourceNames.filter( name => isResourcePrefix( name, 'category-query' ) );
|
||||||
|
|
||||||
|
return filteredNames.map( async resourceName => {
|
||||||
|
const query = getResourceIdentifier( resourceName );
|
||||||
|
const url = `/wc/v3/products/categories${ stringifyQuery( query ) }`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch( {
|
||||||
|
parse: false,
|
||||||
|
path: url,
|
||||||
|
} );
|
||||||
|
|
||||||
|
const categories = await response.json();
|
||||||
|
const totalCount = parseInt( response.headers.get( 'x-wp-total' ) );
|
||||||
|
const ids = categories.map( category => category.id );
|
||||||
|
const categoryResources = categories.reduce( ( resources, category ) => {
|
||||||
|
resources[ getResourceName( 'category', category.id ) ] = { data: category };
|
||||||
|
return resources;
|
||||||
|
}, {} );
|
||||||
|
|
||||||
|
return {
|
||||||
|
[ resourceName ]: {
|
||||||
|
data: ids,
|
||||||
|
totalCount,
|
||||||
|
},
|
||||||
|
...categoryResources,
|
||||||
|
};
|
||||||
|
} catch ( error ) {
|
||||||
|
return { [ resourceName ]: { error } };
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
read,
|
||||||
|
};
|
|
@ -0,0 +1,56 @@
|
||||||
|
/** @format */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { isNil } from 'lodash';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { getResourceName } from '../utils';
|
||||||
|
import { DEFAULT_REQUIREMENT } from '../constants';
|
||||||
|
|
||||||
|
const getCategories = ( getResource, requireResource ) => (
|
||||||
|
query = {},
|
||||||
|
requirement = DEFAULT_REQUIREMENT
|
||||||
|
) => {
|
||||||
|
const resourceName = getResourceName( 'category-query', query );
|
||||||
|
const ids = requireResource( requirement, resourceName ).data || [];
|
||||||
|
const categories = ids.reduce(
|
||||||
|
( acc, id ) => ( {
|
||||||
|
...acc,
|
||||||
|
[ id ]: getResource( getResourceName( 'category', id ) ).data || {},
|
||||||
|
} ),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
return categories;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCategoriesTotalCount = getResource => ( query = {} ) => {
|
||||||
|
const resourceName = getResourceName( 'category-query', query );
|
||||||
|
return getResource( resourceName ).totalCount || 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCategoriesError = getResource => ( query = {} ) => {
|
||||||
|
const resourceName = getResourceName( 'category-query', query );
|
||||||
|
return getResource( resourceName ).error;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isGetCategoriesRequesting = getResource => ( query = {} ) => {
|
||||||
|
const resourceName = getResourceName( 'category-query', query );
|
||||||
|
const { lastRequested, lastReceived } = getResource( resourceName );
|
||||||
|
|
||||||
|
if ( isNil( lastRequested ) || isNil( lastReceived ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lastRequested > lastReceived;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getCategories,
|
||||||
|
getCategoriesError,
|
||||||
|
getCategoriesTotalCount,
|
||||||
|
isGetCategoriesRequesting,
|
||||||
|
};
|
|
@ -3,6 +3,7 @@
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
|
import categories from './categories';
|
||||||
import customers from './customers';
|
import customers from './customers';
|
||||||
import notes from './notes';
|
import notes from './notes';
|
||||||
import orders from './orders';
|
import orders from './orders';
|
||||||
|
@ -17,6 +18,7 @@ function createWcApiSpec() {
|
||||||
...user.mutations,
|
...user.mutations,
|
||||||
},
|
},
|
||||||
selectors: {
|
selectors: {
|
||||||
|
...categories.selectors,
|
||||||
...customers.selectors,
|
...customers.selectors,
|
||||||
...notes.selectors,
|
...notes.selectors,
|
||||||
...orders.selectors,
|
...orders.selectors,
|
||||||
|
@ -28,6 +30,7 @@ function createWcApiSpec() {
|
||||||
operations: {
|
operations: {
|
||||||
read( resourceNames ) {
|
read( resourceNames ) {
|
||||||
return [
|
return [
|
||||||
|
...categories.operations.read( resourceNames ),
|
||||||
...customers.operations.read( resourceNames ),
|
...customers.operations.read( resourceNames ),
|
||||||
...notes.operations.read( resourceNames ),
|
...notes.operations.read( resourceNames ),
|
||||||
...orders.operations.read( resourceNames ),
|
...orders.operations.read( resourceNames ),
|
||||||
|
|
|
@ -29,6 +29,10 @@ class WC_Admin_Api_Init {
|
||||||
|
|
||||||
// Initialize Orders data store class's static vars.
|
// Initialize Orders data store class's static vars.
|
||||||
add_action( 'woocommerce_after_register_post_type', array( 'WC_Admin_Api_Init', 'orders_data_store_init' ), 20 );
|
add_action( 'woocommerce_after_register_post_type', array( 'WC_Admin_Api_Init', 'orders_data_store_init' ), 20 );
|
||||||
|
// Add taxonomy support for product categories.
|
||||||
|
add_filter( 'woocommerce_taxonomy_args_product_cat', array( 'WC_Admin_Api_Init', 'show_product_categories_in_rest' ) );
|
||||||
|
// Increase per_page limit in REST response.
|
||||||
|
add_filter( 'woocommerce_rest_product_cat_query', array( 'WC_Admin_Api_Init', 'increase_per_page_limit' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -470,6 +474,28 @@ class WC_Admin_Api_Init {
|
||||||
add_action( 'woocommerce_after_register_post_type', array( 'WC_Admin_Api_Init', 'order_product_lookup_store_init' ), 20 );
|
add_action( 'woocommerce_after_register_post_type', array( 'WC_Admin_Api_Init', 'order_product_lookup_store_init' ), 20 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables the WP REST API for product categories
|
||||||
|
*
|
||||||
|
* @param array $args Default arguments for product_cat taxonomy.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function show_product_categories_in_rest( $args ) {
|
||||||
|
$args['show_in_rest'] = true;
|
||||||
|
return $args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increase per page limit for product categories
|
||||||
|
*
|
||||||
|
* @param array $prepared_args Prepared arguments for query.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function increase_per_page_limit( $prepared_args ) {
|
||||||
|
$prepared_args['number'] = PHP_INT_MAX;
|
||||||
|
return $prepared_args;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new WC_Admin_Api_Init();
|
new WC_Admin_Api_Init();
|
||||||
|
|
|
@ -25,17 +25,21 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $column_types = array(
|
protected $column_types = array(
|
||||||
'date_start' => 'strval',
|
'date_start' => 'strval',
|
||||||
'date_end' => 'strval',
|
'date_end' => 'strval',
|
||||||
'product_id' => 'intval',
|
'product_id' => 'intval',
|
||||||
'items_sold' => 'intval',
|
'items_sold' => 'intval',
|
||||||
'net_revenue' => 'floatval',
|
'net_revenue' => 'floatval',
|
||||||
'orders_count' => 'intval',
|
'orders_count' => 'intval',
|
||||||
// Extended attributes.
|
// Extended attributes.
|
||||||
'name' => 'strval',
|
'name' => 'strval',
|
||||||
'price' => 'floatval',
|
'price' => 'floatval',
|
||||||
'image' => 'strval',
|
'image' => 'strval',
|
||||||
'permalink' => 'strval',
|
'permalink' => 'strval',
|
||||||
|
'stock_status' => 'strval',
|
||||||
|
'stock_quantity' => 'intval',
|
||||||
|
'low_stock_amount' => 'intval',
|
||||||
|
'category_ids' => 'array_values',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,6 +67,7 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
|
||||||
'stock_status',
|
'stock_status',
|
||||||
'stock_quantity',
|
'stock_quantity',
|
||||||
'low_stock_amount',
|
'low_stock_amount',
|
||||||
|
'category_ids',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -199,6 +199,9 @@ class WC_Tests_Reports_Products extends WC_Unit_Test_Case {
|
||||||
$product->set_low_stock_amount( 5 );
|
$product->set_low_stock_amount( 5 );
|
||||||
$product->save();
|
$product->save();
|
||||||
|
|
||||||
|
$term = wp_insert_term( 'Test Category', 'product_cat' );
|
||||||
|
wp_set_object_terms( $product->get_id(), $term['term_id'], 'product_cat' );
|
||||||
|
|
||||||
$order = WC_Helper_Order::create_order( 1, $product );
|
$order = WC_Helper_Order::create_order( 1, $product );
|
||||||
$order->set_status( 'completed' );
|
$order->set_status( 'completed' );
|
||||||
$order->set_shipping_total( 10 );
|
$order->set_shipping_total( 10 );
|
||||||
|
@ -217,7 +220,9 @@ class WC_Tests_Reports_Products extends WC_Unit_Test_Case {
|
||||||
'extended_info' => 1,
|
'extended_info' => 1,
|
||||||
);
|
);
|
||||||
// Test retrieving the stats through the data store.
|
// Test retrieving the stats through the data store.
|
||||||
$data = $data_store->get_data( $args );
|
$data = $data_store->get_data( $args );
|
||||||
|
// Get updated product data.
|
||||||
|
$product = wc_get_product( $product->get_id() );
|
||||||
$expected_data = (object) array(
|
$expected_data = (object) array(
|
||||||
'total' => 1,
|
'total' => 1,
|
||||||
'pages' => 1,
|
'pages' => 1,
|
||||||
|
@ -234,8 +239,9 @@ class WC_Tests_Reports_Products extends WC_Unit_Test_Case {
|
||||||
'permalink' => $product->get_permalink(),
|
'permalink' => $product->get_permalink(),
|
||||||
'price' => (float) $product->get_price(),
|
'price' => (float) $product->get_price(),
|
||||||
'stock_status' => $product->get_stock_status(),
|
'stock_status' => $product->get_stock_status(),
|
||||||
'stock_quantity' => $product->get_stock_quantity() - 4, // subtract the ones purchased.
|
'stock_quantity' => $product->get_stock_quantity(),
|
||||||
'low_stock_amount' => $product->get_low_stock_amount(),
|
'low_stock_amount' => $product->get_low_stock_amount(),
|
||||||
|
'category_ids' => array_values( $product->get_category_ids() ),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in New Issue