Update activity panels order endpoint (https://github.com/woocommerce/woocommerce-admin/pull/1578)
* Only show customer name if available * Map customer data to extended_info in orders API response * Add gross total and refund total to orders API response * Hook up report orders endpoint to activity panel orders * Add on-hold orders to activity panel orders * Destructure extended_info in case of filtering * Add customer link to orders panel
This commit is contained in:
parent
0ef2dc27f4
commit
73ff2d37e8
|
@ -24,7 +24,7 @@ import {
|
||||||
Section,
|
Section,
|
||||||
} from '@woocommerce/components';
|
} from '@woocommerce/components';
|
||||||
import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
|
import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency';
|
||||||
import { getAdminLink } from '@woocommerce/navigation';
|
import { getAdminLink, getNewPath } from '@woocommerce/navigation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
|
@ -32,7 +32,6 @@ import { getAdminLink } from '@woocommerce/navigation';
|
||||||
import { ActivityCard, ActivityCardPlaceholder } from '../activity-card';
|
import { ActivityCard, ActivityCardPlaceholder } from '../activity-card';
|
||||||
import ActivityHeader from '../activity-header';
|
import ActivityHeader from '../activity-header';
|
||||||
import ActivityOutboundLink from '../activity-outbound-link';
|
import ActivityOutboundLink from '../activity-outbound-link';
|
||||||
import { getOrderRefundTotal } from 'lib/order-values';
|
|
||||||
import { QUERY_DEFAULTS } from 'wc-api/constants';
|
import { QUERY_DEFAULTS } from 'wc-api/constants';
|
||||||
import withSelect from 'wc-api/with-select';
|
import withSelect from 'wc-api/with-select';
|
||||||
|
|
||||||
|
@ -64,28 +63,56 @@ function OrdersPanel( { orders, isRequesting, isError } ) {
|
||||||
</EllipsisMenu>
|
</EllipsisMenu>
|
||||||
);
|
);
|
||||||
|
|
||||||
const orderCardTitle = ( order, address ) => {
|
const getCustomerString = order => {
|
||||||
const name = `${ address.first_name } ${ address.last_name }`;
|
const extended_info = order.extended_info || {};
|
||||||
|
const { first_name, last_name } = extended_info.customer || {};
|
||||||
|
|
||||||
|
if ( ! first_name && ! last_name ) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = [ first_name, last_name ].join( ' ' );
|
||||||
|
return sprintf(
|
||||||
|
__(
|
||||||
|
/* translators: describes who placed an order, e.g. Order #123 placed by John Doe */
|
||||||
|
'placed by {{customerLink}}%(customerName)s{{/customerLink}}',
|
||||||
|
'wc-admin'
|
||||||
|
),
|
||||||
|
{
|
||||||
|
customerName: name,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const orderCardTitle = order => {
|
||||||
|
const { extended_info, order_id } = order;
|
||||||
|
const { customer } = extended_info || {};
|
||||||
|
const customerUrl = customer.customer_id
|
||||||
|
? getNewPath( {}, '/analytics/customers', {
|
||||||
|
filter: 'single_customer',
|
||||||
|
customer_id: customer.customer_id,
|
||||||
|
} )
|
||||||
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{ interpolateComponents( {
|
{ interpolateComponents( {
|
||||||
mixedString: sprintf(
|
mixedString: sprintf(
|
||||||
__(
|
__(
|
||||||
/* eslint-disable-next-line max-len */
|
'Order {{orderLink}}#%(orderNumber)s{{/orderLink}} %(customerString)s {{destinationFlag/}}',
|
||||||
'Order {{orderLink}}#%(orderNumber)s{{/orderLink}} placed by {{customerLink}}%(customerName)s{{/customerLink}} {{destinationFlag/}}',
|
|
||||||
'wc-admin'
|
'wc-admin'
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
orderNumber: order.number,
|
orderNumber: order_id,
|
||||||
customerName: name,
|
customerString: getCustomerString( order ),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
components: {
|
components: {
|
||||||
orderLink: <Link href={ 'post.php?action=edit&post=' + order.id } type="wp-admin" />,
|
orderLink: <Link href={ 'post.php?action=edit&post=' + order_id } type="wp-admin" />,
|
||||||
// @todo Hook up customer name link
|
destinationFlag: customer.country ? (
|
||||||
customerLink: <Link href={ '#' } type="wp-admin" />,
|
<Flag code={ customer.country } round={ false } />
|
||||||
destinationFlag: <Flag order={ order } round={ false } />,
|
) : null,
|
||||||
|
customerLink: customerUrl ? <Link href={ customerUrl } type="wc-admin" /> : <span />,
|
||||||
},
|
},
|
||||||
} ) }
|
} ) }
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -93,20 +120,20 @@ function OrdersPanel( { orders, isRequesting, isError } ) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const cards = [];
|
const cards = [];
|
||||||
orders.forEach( ( order, id ) => {
|
orders.forEach( order => {
|
||||||
// We want the billing address, but shipping can be used as a fallback.
|
const extended_info = order.extended_info || {};
|
||||||
const address = { ...order.shipping, ...order.billing };
|
const productsCount =
|
||||||
const productsCount = order.line_items.reduce( ( total, line ) => total + line.quantity, 0 );
|
extended_info && extended_info.products ? extended_info.products.length : 0;
|
||||||
|
|
||||||
const total = order.total;
|
const total = order.gross_total;
|
||||||
const refundValue = getOrderRefundTotal( order );
|
const refundValue = order.refund_total;
|
||||||
const remainingTotal = getCurrencyFormatDecimal( order.total ) + refundValue;
|
const remainingTotal = getCurrencyFormatDecimal( total ) + refundValue;
|
||||||
|
|
||||||
cards.push(
|
cards.push(
|
||||||
<ActivityCard
|
<ActivityCard
|
||||||
key={ id }
|
key={ order.order_id }
|
||||||
className="woocommerce-order-activity-card"
|
className="woocommerce-order-activity-card"
|
||||||
title={ orderCardTitle( order, address ) }
|
title={ orderCardTitle( order ) }
|
||||||
date={ order.date_created }
|
date={ order.date_created }
|
||||||
subtitle={
|
subtitle={
|
||||||
<div>
|
<div>
|
||||||
|
@ -118,16 +145,15 @@ function OrdersPanel( { orders, isRequesting, isError } ) {
|
||||||
</span>
|
</span>
|
||||||
{ refundValue ? (
|
{ refundValue ? (
|
||||||
<span>
|
<span>
|
||||||
<s>{ formatCurrency( total, order.currency_symbol ) }</s>{' '}
|
<s>{ formatCurrency( total ) }</s> { formatCurrency( remainingTotal ) }
|
||||||
{ formatCurrency( remainingTotal, order.currency_symbol ) }
|
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span>{ formatCurrency( total, order.currency_symbol ) }</span>
|
<span>{ formatCurrency( total ) }</span>
|
||||||
) }
|
) }
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
actions={
|
actions={
|
||||||
<Button isDefault href={ getAdminLink( 'post.php?action=edit&post=' + order.id ) }>
|
<Button isDefault href={ getAdminLink( 'post.php?action=edit&post=' + order.order_id ) }>
|
||||||
{ __( 'Begin fulfillment' ) }
|
{ __( 'Begin fulfillment' ) }
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
|
@ -162,29 +188,30 @@ function OrdersPanel( { orders, isRequesting, isError } ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OrdersPanel.propTypes = {
|
OrdersPanel.propTypes = {
|
||||||
orders: PropTypes.instanceOf( Map ).isRequired,
|
orders: PropTypes.array.isRequired,
|
||||||
isError: PropTypes.bool,
|
isError: PropTypes.bool,
|
||||||
isRequesting: PropTypes.bool,
|
isRequesting: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
OrdersPanel.defaultProps = {
|
OrdersPanel.defaultProps = {
|
||||||
orders: new Map(),
|
orders: [],
|
||||||
isError: false,
|
isError: false,
|
||||||
isRequesting: false,
|
isRequesting: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withSelect( select => {
|
withSelect( select => {
|
||||||
const { getItems, getItemsError, isGetItemsRequesting } = select( 'wc-api' );
|
const { getReportItems, getReportItemsError, isReportItemsRequesting } = select( 'wc-api' );
|
||||||
const ordersQuery = {
|
const ordersQuery = {
|
||||||
page: 1,
|
page: 1,
|
||||||
per_page: QUERY_DEFAULTS.pageSize,
|
per_page: QUERY_DEFAULTS.pageSize,
|
||||||
status: 'processing',
|
status_is: [ 'processing', 'on-hold' ],
|
||||||
|
extended_info: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const orders = getItems( 'orders', ordersQuery );
|
const orders = getReportItems( 'orders', ordersQuery ).data;
|
||||||
const isError = Boolean( getItemsError( 'orders', ordersQuery ) );
|
const isError = Boolean( getReportItemsError( 'orders', ordersQuery ) );
|
||||||
const isRequesting = isGetItemsRequesting( 'orders', ordersQuery );
|
const isRequesting = isReportItemsRequesting( 'orders', ordersQuery );
|
||||||
|
|
||||||
return { orders, isError, isRequesting };
|
return { orders, isError, isRequesting };
|
||||||
} )
|
} )
|
||||||
|
|
|
@ -30,6 +30,8 @@ class WC_Admin_Reports_Orders_Data_Store extends WC_Admin_Reports_Data_Store imp
|
||||||
'status' => 'strval',
|
'status' => 'strval',
|
||||||
'customer_id' => 'intval',
|
'customer_id' => 'intval',
|
||||||
'net_total' => 'floatval',
|
'net_total' => 'floatval',
|
||||||
|
'gross_total' => 'floatval',
|
||||||
|
'refund_total' => 'floatval',
|
||||||
'num_items_sold' => 'intval',
|
'num_items_sold' => 'intval',
|
||||||
'customer_type' => 'strval',
|
'customer_type' => 'strval',
|
||||||
);
|
);
|
||||||
|
@ -45,6 +47,8 @@ class WC_Admin_Reports_Orders_Data_Store extends WC_Admin_Reports_Data_Store imp
|
||||||
'status' => 'REPLACE(status, "wc-", "") as status',
|
'status' => 'REPLACE(status, "wc-", "") as status',
|
||||||
'customer_id' => 'customer_id',
|
'customer_id' => 'customer_id',
|
||||||
'net_total' => 'net_total',
|
'net_total' => 'net_total',
|
||||||
|
'gross_total' => 'gross_total',
|
||||||
|
'refund_total' => 'refund_total',
|
||||||
'num_items_sold' => 'num_items_sold',
|
'num_items_sold' => 'num_items_sold',
|
||||||
'customer_type' => '(CASE WHEN returning_customer <> 0 THEN "returning" ELSE "new" END) as customer_type',
|
'customer_type' => '(CASE WHEN returning_customer <> 0 THEN "returning" ELSE "new" END) as customer_type',
|
||||||
);
|
);
|
||||||
|
@ -243,6 +247,8 @@ class WC_Admin_Reports_Orders_Data_Store extends WC_Admin_Reports_Data_Store imp
|
||||||
$mapped_products = $this->map_array_by_key( $products, 'product_id' );
|
$mapped_products = $this->map_array_by_key( $products, 'product_id' );
|
||||||
$coupons = $this->get_coupons_by_order_ids( array_keys( $mapped_orders ) );
|
$coupons = $this->get_coupons_by_order_ids( array_keys( $mapped_orders ) );
|
||||||
$product_categories = $this->get_product_categories_by_product_ids( array_keys( $mapped_products ) );
|
$product_categories = $this->get_product_categories_by_product_ids( array_keys( $mapped_products ) );
|
||||||
|
$customers = $this->get_customers_by_orders( $orders_data );
|
||||||
|
$mapped_customers = $this->map_array_by_key( $customers, 'customer_id' );
|
||||||
|
|
||||||
$mapped_data = array();
|
$mapped_data = array();
|
||||||
foreach ( $products as $product ) {
|
foreach ( $products as $product ) {
|
||||||
|
@ -280,8 +286,12 @@ class WC_Admin_Reports_Orders_Data_Store extends WC_Admin_Reports_Data_Store imp
|
||||||
'products' => array(),
|
'products' => array(),
|
||||||
'categories' => array(),
|
'categories' => array(),
|
||||||
'coupons' => array(),
|
'coupons' => array(),
|
||||||
|
'customer' => array(),
|
||||||
);
|
);
|
||||||
$orders_data[ $key ]['extended_info'] = isset( $mapped_data[ $order_data['order_id'] ] ) ? array_merge( $defaults, $mapped_data[ $order_data['order_id'] ] ) : $defaults;
|
$orders_data[ $key ]['extended_info'] = isset( $mapped_data[ $order_data['order_id'] ] ) ? array_merge( $defaults, $mapped_data[ $order_data['order_id'] ] ) : $defaults;
|
||||||
|
if ( $order_data['customer_id'] && isset( $mapped_customers[ $order_data['customer_id'] ] ) ) {
|
||||||
|
$orders_data[ $key ]['extended_info']['customer'] = $mapped_customers[ $order_data['customer_id'] ];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,6 +334,32 @@ class WC_Admin_Reports_Orders_Data_Store extends WC_Admin_Reports_Data_Store imp
|
||||||
return $products;
|
return $products;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get customer data from order IDs.
|
||||||
|
*
|
||||||
|
* @param array $orders Array of orders.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function get_customers_by_orders( $orders ) {
|
||||||
|
global $wpdb;
|
||||||
|
$customer_lookup_table = $wpdb->prefix . 'wc_customer_lookup';
|
||||||
|
|
||||||
|
$customer_ids = array();
|
||||||
|
foreach ( $orders as $order ) {
|
||||||
|
if ( $order['customer_id'] ) {
|
||||||
|
$customer_ids[] = $order['customer_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$customer_ids = implode( ',', $customer_ids );
|
||||||
|
|
||||||
|
$customers = $wpdb->get_results(
|
||||||
|
"SELECT * FROM {$customer_lookup_table} WHERE customer_id IN ({$customer_ids})",
|
||||||
|
ARRAY_A
|
||||||
|
); // WPCS: cache ok, DB call ok, unprepared SQL ok.
|
||||||
|
|
||||||
|
return $customers;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get coupon information from order IDs.
|
* Get coupon information from order IDs.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue