diff --git a/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js b/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js index 31d4bacb774..0651bfdf1ab 100644 --- a/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js +++ b/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js @@ -24,7 +24,7 @@ import { Section, } from '@woocommerce/components'; import { formatCurrency, getCurrencyFormatDecimal } from '@woocommerce/currency'; -import { getAdminLink } from '@woocommerce/navigation'; +import { getAdminLink, getNewPath } from '@woocommerce/navigation'; /** * Internal dependencies @@ -32,7 +32,6 @@ import { getAdminLink } from '@woocommerce/navigation'; import { ActivityCard, ActivityCardPlaceholder } from '../activity-card'; import ActivityHeader from '../activity-header'; import ActivityOutboundLink from '../activity-outbound-link'; -import { getOrderRefundTotal } from 'lib/order-values'; import { QUERY_DEFAULTS } from 'wc-api/constants'; import withSelect from 'wc-api/with-select'; @@ -64,28 +63,56 @@ function OrdersPanel( { orders, isRequesting, isError } ) { ); - const orderCardTitle = ( order, address ) => { - const name = `${ address.first_name } ${ address.last_name }`; + const getCustomerString = order => { + 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 ( { interpolateComponents( { mixedString: sprintf( __( - /* eslint-disable-next-line max-len */ - 'Order {{orderLink}}#%(orderNumber)s{{/orderLink}} placed by {{customerLink}}%(customerName)s{{/customerLink}} {{destinationFlag/}}', + 'Order {{orderLink}}#%(orderNumber)s{{/orderLink}} %(customerString)s {{destinationFlag/}}', 'wc-admin' ), { - orderNumber: order.number, - customerName: name, + orderNumber: order_id, + customerString: getCustomerString( order ), } ), components: { - orderLink: , - // @todo Hook up customer name link - customerLink: , - destinationFlag: , + orderLink: , + destinationFlag: customer.country ? ( + + ) : null, + customerLink: customerUrl ? : , }, } ) } @@ -93,20 +120,20 @@ function OrdersPanel( { orders, isRequesting, isError } ) { }; const cards = []; - orders.forEach( ( order, id ) => { - // We want the billing address, but shipping can be used as a fallback. - const address = { ...order.shipping, ...order.billing }; - const productsCount = order.line_items.reduce( ( total, line ) => total + line.quantity, 0 ); + orders.forEach( order => { + const extended_info = order.extended_info || {}; + const productsCount = + extended_info && extended_info.products ? extended_info.products.length : 0; - const total = order.total; - const refundValue = getOrderRefundTotal( order ); - const remainingTotal = getCurrencyFormatDecimal( order.total ) + refundValue; + const total = order.gross_total; + const refundValue = order.refund_total; + const remainingTotal = getCurrencyFormatDecimal( total ) + refundValue; cards.push( @@ -118,16 +145,15 @@ function OrdersPanel( { orders, isRequesting, isError } ) { { refundValue ? ( - { formatCurrency( total, order.currency_symbol ) }{' '} - { formatCurrency( remainingTotal, order.currency_symbol ) } + { formatCurrency( total ) } { formatCurrency( remainingTotal ) } ) : ( - { formatCurrency( total, order.currency_symbol ) } + { formatCurrency( total ) } ) } } actions={ - } @@ -162,29 +188,30 @@ function OrdersPanel( { orders, isRequesting, isError } ) { } OrdersPanel.propTypes = { - orders: PropTypes.instanceOf( Map ).isRequired, + orders: PropTypes.array.isRequired, isError: PropTypes.bool, isRequesting: PropTypes.bool, }; OrdersPanel.defaultProps = { - orders: new Map(), + orders: [], isError: false, isRequesting: false, }; export default compose( withSelect( select => { - const { getItems, getItemsError, isGetItemsRequesting } = select( 'wc-api' ); + const { getReportItems, getReportItemsError, isReportItemsRequesting } = select( 'wc-api' ); const ordersQuery = { page: 1, per_page: QUERY_DEFAULTS.pageSize, - status: 'processing', + status_is: [ 'processing', 'on-hold' ], + extended_info: true, }; - const orders = getItems( 'orders', ordersQuery ); - const isError = Boolean( getItemsError( 'orders', ordersQuery ) ); - const isRequesting = isGetItemsRequesting( 'orders', ordersQuery ); + const orders = getReportItems( 'orders', ordersQuery ).data; + const isError = Boolean( getReportItemsError( 'orders', ordersQuery ) ); + const isRequesting = isReportItemsRequesting( 'orders', ordersQuery ); return { orders, isError, isRequesting }; } ) diff --git a/plugins/woocommerce-admin/includes/data-stores/class-wc-admin-reports-orders-data-store.php b/plugins/woocommerce-admin/includes/data-stores/class-wc-admin-reports-orders-data-store.php index 726eb387149..f4ba4d362a9 100644 --- a/plugins/woocommerce-admin/includes/data-stores/class-wc-admin-reports-orders-data-store.php +++ b/plugins/woocommerce-admin/includes/data-stores/class-wc-admin-reports-orders-data-store.php @@ -30,6 +30,8 @@ class WC_Admin_Reports_Orders_Data_Store extends WC_Admin_Reports_Data_Store imp 'status' => 'strval', 'customer_id' => 'intval', 'net_total' => 'floatval', + 'gross_total' => 'floatval', + 'refund_total' => 'floatval', 'num_items_sold' => 'intval', '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', 'customer_id' => 'customer_id', 'net_total' => 'net_total', + 'gross_total' => 'gross_total', + 'refund_total' => 'refund_total', 'num_items_sold' => 'num_items_sold', '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' ); $coupons = $this->get_coupons_by_order_ids( array_keys( $mapped_orders ) ); $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(); foreach ( $products as $product ) { @@ -280,8 +286,12 @@ class WC_Admin_Reports_Orders_Data_Store extends WC_Admin_Reports_Data_Store imp 'products' => array(), 'categories' => 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; + 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; } + /** + * 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. *