Browse Source

fix(core): Correctly return order quantities from list query

Fixes #603
Michael Bromley 5 years ago
parent
commit
a2e34ec8ca

+ 41 - 0
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -5845,6 +5845,20 @@ export type GetOrderWithPaymentsQuery = {
     >;
 };
 
+export type GetOrderListWithQtyQueryVariables = Exact<{
+    options?: Maybe<OrderListOptions>;
+}>;
+
+export type GetOrderListWithQtyQuery = {
+    orders: {
+        items: Array<
+            Pick<Order, 'id' | 'code' | 'totalQuantity'> & {
+                lines: Array<Pick<OrderLine, 'id' | 'quantity'> & { items: Array<Pick<OrderItem, 'id'>> }>;
+            }
+        >;
+    };
+};
+
 export type UpdateProductOptionGroupMutationVariables = Exact<{
     input: UpdateProductOptionGroupInput;
 }>;
@@ -7835,6 +7849,33 @@ export namespace GetOrderWithPayments {
     >;
 }
 
+export namespace GetOrderListWithQty {
+    export type Variables = GetOrderListWithQtyQueryVariables;
+    export type Query = GetOrderListWithQtyQuery;
+    export type Orders = NonNullable<GetOrderListWithQtyQuery['orders']>;
+    export type Items = NonNullable<
+        NonNullable<NonNullable<GetOrderListWithQtyQuery['orders']>['items']>[number]
+    >;
+    export type Lines = NonNullable<
+        NonNullable<
+            NonNullable<
+                NonNullable<NonNullable<GetOrderListWithQtyQuery['orders']>['items']>[number]
+            >['lines']
+        >[number]
+    >;
+    export type _Items = NonNullable<
+        NonNullable<
+            NonNullable<
+                NonNullable<
+                    NonNullable<
+                        NonNullable<NonNullable<GetOrderListWithQtyQuery['orders']>['items']>[number]
+                    >['lines']
+                >[number]
+            >['items']
+        >[number]
+    >;
+}
+
 export namespace UpdateProductOptionGroup {
     export type Variables = UpdateProductOptionGroupMutationVariables;
     export type Mutation = UpdateProductOptionGroupMutation;

+ 65 - 18
packages/core/e2e/order.e2e-spec.ts

@@ -35,6 +35,7 @@ import {
     GetOrderHistory,
     GetOrderList,
     GetOrderListFulfillments,
+    GetOrderListWithQty,
     GetOrderWithPayments,
     GetProductWithVariants,
     GetStockMovement,
@@ -60,6 +61,7 @@ import {
     GetOrderByCodeWithPayments,
     TestOrderFragmentFragment,
     UpdatedOrder,
+    UpdatedOrderFragment,
 } from './graphql/generated-e2e-shop-types';
 import {
     CANCEL_ORDER,
@@ -99,7 +101,7 @@ describe('Orders resolver', () => {
     const password = 'test';
 
     const orderGuard: ErrorResultGuard<
-        TestOrderFragmentFragment | CanceledOrderFragment
+        TestOrderFragmentFragment | CanceledOrderFragment | UpdatedOrderFragment
     > = createErrorResultGuard(input => !!input.lines);
     const paymentGuard: ErrorResultGuard<PaymentFragment> = createErrorResultGuard(input => !!input.state);
     const fulfillmentGuard: ErrorResultGuard<FulfillmentFragment> = createErrorResultGuard(
@@ -342,23 +344,6 @@ describe('Orders resolver', () => {
         let f2Id: string;
         let f3Id: string;
 
-        // https://github.com/vendure-ecommerce/vendure/issues/639
-        it('returns fulfillments for Order with no lines', async () => {
-            // Apply a coupon code just to create an active order with no OrderLines
-            await shopClient.query<ApplyCouponCode.Mutation, ApplyCouponCode.Variables>(APPLY_COUPON_CODE, {
-                couponCode: 'TEST',
-            });
-            const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
-            const { order } = await adminClient.query<
-                GetOrderFulfillments.Query,
-                GetOrderFulfillments.Variables
-            >(GET_ORDER_FULFILLMENTS, {
-                id: activeOrder!.id,
-            });
-
-            expect(order?.fulfillments).toEqual([]);
-        });
-
         it('return error result if lines is empty', async () => {
             const { order } = await adminClient.query<GetOrder.Query, GetOrder.Variables>(GET_ORDER, {
                 id: orderId,
@@ -1628,6 +1613,52 @@ describe('Orders resolver', () => {
             expect(after?.history.totalItems).toBe(2);
         });
     });
+
+    describe('issues', () => {
+        // https://github.com/vendure-ecommerce/vendure/issues/639
+        it('returns fulfillments for Order with no lines', async () => {
+            // Apply a coupon code just to create an active order with no OrderLines
+            await shopClient.query<ApplyCouponCode.Mutation, ApplyCouponCode.Variables>(APPLY_COUPON_CODE, {
+                couponCode: 'TEST',
+            });
+            const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
+            const { order } = await adminClient.query<
+                GetOrderFulfillments.Query,
+                GetOrderFulfillments.Variables
+            >(GET_ORDER_FULFILLMENTS, {
+                id: activeOrder!.id,
+            });
+
+            expect(order?.fulfillments).toEqual([]);
+        });
+
+        // https://github.com/vendure-ecommerce/vendure/issues/603
+        it('orders correctly resolves quantities and OrderItems', async () => {
+            await shopClient.asAnonymousUser();
+            const { addItemToOrder } = await shopClient.query<
+                AddItemToOrder.Mutation,
+                AddItemToOrder.Variables
+            >(ADD_ITEM_TO_ORDER, {
+                productVariantId: 'T_1',
+                quantity: 2,
+            });
+            orderGuard.assertSuccess(addItemToOrder);
+
+            const { orders } = await adminClient.query<
+                GetOrderListWithQty.Query,
+                GetOrderListWithQty.Variables
+            >(GET_ORDERS_LIST_WITH_QUANTITIES, {
+                options: {
+                    filter: {
+                        code: { eq: addItemToOrder.code },
+                    },
+                },
+            });
+
+            expect(orders.items[0].totalQuantity).toBe(2);
+            expect(orders.items[0].lines[0].quantity).toBe(2);
+        });
+    });
 });
 
 async function createTestOrder(
@@ -1802,3 +1833,19 @@ const GET_ORDER_WITH_PAYMENTS = gql`
         }
     }
 `;
+
+const GET_ORDERS_LIST_WITH_QUANTITIES = gql`
+    query GetOrderListWithQty($options: OrderListOptions) {
+        orders(options: $options) {
+            items {
+                id
+                code
+                totalQuantity
+                lines {
+                    id
+                    quantity
+                }
+            }
+        }
+    }
+`;

+ 8 - 1
packages/core/src/service/services/order.service.ts

@@ -152,7 +152,14 @@ export class OrderService {
     findAll(ctx: RequestContext, options?: ListQueryOptions<Order>): Promise<PaginatedList<Order>> {
         return this.listQueryBuilder
             .build(Order, options, {
-                relations: ['lines', 'customer', 'lines.productVariant', 'channels', 'shippingLines'],
+                relations: [
+                    'lines',
+                    'customer',
+                    'lines.productVariant',
+                    'lines.items',
+                    'channels',
+                    'shippingLines',
+                ],
                 channelId: ctx.channelId,
                 ctx,
             })