Browse Source

fix(core): Correctly populate shipping/billing address for new customer

Michael Bromley 3 years ago
parent
commit
264b326e2f

+ 16 - 9
packages/core/e2e/shop-order.e2e-spec.ts

@@ -900,7 +900,7 @@ describe('Shop orders', () => {
             const address: CreateAddressInput = {
                 fullName: 'name',
                 company: 'company',
-                streetLine1: '12 the street',
+                streetLine1: '12 Shipping Street',
                 streetLine2: null,
                 city: 'foo',
                 province: 'bar',
@@ -918,7 +918,7 @@ describe('Shop orders', () => {
             expect(setOrderShippingAddress!.shippingAddress).toEqual({
                 fullName: 'name',
                 company: 'company',
-                streetLine1: '12 the street',
+                streetLine1: '12 Shipping Street',
                 streetLine2: null,
                 city: 'foo',
                 province: 'bar',
@@ -932,7 +932,7 @@ describe('Shop orders', () => {
             const address: CreateAddressInput = {
                 fullName: 'name',
                 company: 'company',
-                streetLine1: '12 the street',
+                streetLine1: '22 Billing Avenue',
                 streetLine2: null,
                 city: 'foo',
                 province: 'bar',
@@ -950,7 +950,7 @@ describe('Shop orders', () => {
             expect(setOrderBillingAddress!.billingAddress).toEqual({
                 fullName: 'name',
                 company: 'company',
-                streetLine1: '12 the street',
+                streetLine1: '22 Billing Avenue',
                 streetLine2: null,
                 city: 'foo',
                 province: 'bar',
@@ -1040,11 +1040,18 @@ describe('Shop orders', () => {
             });
 
             // tslint:disable-next-line:no-non-null-assertion
-            const address = result.customer!.addresses![0];
-            expect(address.streetLine1).toBe('12 the street');
-            expect(address.postalCode).toBe('123456');
-            expect(address.defaultBillingAddress).toBe(true);
-            expect(address.defaultShippingAddress).toBe(true);
+            const shippingAddress = result.customer!.addresses!.find(a => a.defaultShippingAddress)!;
+            expect(shippingAddress.streetLine1).toBe('12 Shipping Street');
+            expect(shippingAddress.postalCode).toBe('123456');
+            expect(shippingAddress.defaultBillingAddress).toBe(false);
+            expect(shippingAddress.defaultShippingAddress).toBe(true);
+
+            // tslint:disable-next-line:no-non-null-assertion
+            const billingAddress = result.customer!.addresses!.find(a => a.defaultBillingAddress)!;
+            expect(billingAddress.streetLine1).toBe('22 Billing Avenue');
+            expect(billingAddress.postalCode).toBe('123456');
+            expect(billingAddress.defaultBillingAddress).toBe(true);
+            expect(billingAddress.defaultShippingAddress).toBe(false);
         });
     });
 

+ 1 - 20
packages/core/src/api/resolvers/shop/shop-order.resolver.ts

@@ -341,26 +341,7 @@ export class ShopOrderResolver {
                     return order;
                 }
                 if (order.active === false) {
-                    if (order.customer) {
-                        const addresses = await this.customerService.findAddressesByCustomerId(
-                            ctx,
-                            order.customer.id,
-                        );
-                        // If the Customer has no addresses yet, use the shipping address data
-                        // to populate the initial default Address.
-                        if (addresses.length === 0 && order.shippingAddress?.country) {
-                            const address = order.shippingAddress;
-                            await this.customerService.createAddress(ctx, order.customer.id, {
-                                ...address,
-                                company: address.company || '',
-                                streetLine1: address.streetLine1 || '',
-                                streetLine2: address.streetLine2 || '',
-                                countryCode: address.countryCode || '',
-                                defaultBillingAddress: true,
-                                defaultShippingAddress: true,
-                            });
-                        }
-                    }
+                    await this.customerService.createAddressesForNewCustomer(ctx, order);
                 }
                 if (order.active === false && ctx.session?.activeOrderId === sessionOrder.id) {
                     await this.sessionService.unsetActiveOrder(ctx, ctx.session);

+ 53 - 0
packages/core/src/service/services/customer.service.ts

@@ -14,6 +14,7 @@ import {
     DeletionResponse,
     DeletionResult,
     HistoryEntryType,
+    OrderAddress,
     UpdateAddressInput,
     UpdateCustomerInput,
     UpdateCustomerNoteInput,
@@ -46,6 +47,7 @@ import { Channel } from '../../entity/channel/channel.entity';
 import { CustomerGroup } from '../../entity/customer-group/customer-group.entity';
 import { Customer } from '../../entity/customer/customer.entity';
 import { HistoryEntry } from '../../entity/history-entry/history-entry.entity';
+import { Order } from '../../entity/index';
 import { User } from '../../entity/user/user.entity';
 import { EventBus } from '../../event-bus/event-bus';
 import { AccountRegistrationEvent } from '../../event-bus/events/account-registration-event';
@@ -790,6 +792,57 @@ export class CustomerService {
         };
     }
 
+    /**
+     * @description
+     * If the Customer associated with the given Order does not yet have any Addresses,
+     * this method will create new Address(es) based on the Order's shipping & billing
+     * addresses.
+     */
+    async createAddressesForNewCustomer(ctx: RequestContext, order: Order) {
+        if (!order.customer) {
+            return;
+        }
+        const addresses = await this.findAddressesByCustomerId(ctx, order.customer.id);
+        // If the Customer has no addresses yet, use the shipping/billing address data
+        // to populate the initial default Address.
+        if (addresses.length === 0 && order.shippingAddress?.country) {
+            const shippingAddress = order.shippingAddress;
+            const billingAddress = order.billingAddress;
+            const hasSeparateBillingAddress =
+                billingAddress?.streetLine1 && !this.addressesAreEqual(shippingAddress, billingAddress);
+            if (shippingAddress.streetLine1) {
+                await this.createAddress(ctx, order.customer.id, {
+                    ...shippingAddress,
+                    company: shippingAddress.company || '',
+                    streetLine1: shippingAddress.streetLine1 || '',
+                    streetLine2: shippingAddress.streetLine2 || '',
+                    countryCode: shippingAddress.countryCode || '',
+                    defaultBillingAddress: !hasSeparateBillingAddress,
+                    defaultShippingAddress: true,
+                });
+            }
+            if (hasSeparateBillingAddress) {
+                await this.createAddress(ctx, order.customer.id, {
+                    ...billingAddress,
+                    company: billingAddress.company || '',
+                    streetLine1: billingAddress.streetLine1 || '',
+                    streetLine2: billingAddress.streetLine2 || '',
+                    countryCode: billingAddress.countryCode || '',
+                    defaultBillingAddress: true,
+                    defaultShippingAddress: false,
+                });
+            }
+        }
+    }
+
+    private addressesAreEqual(address1: OrderAddress, address2: OrderAddress): boolean {
+        return (
+            address1.streetLine1 === address2.streetLine1 &&
+            address1.streetLine2 === address2.streetLine2 &&
+            address1.postalCode === address2.postalCode
+        );
+    }
+
     async addNoteToCustomer(ctx: RequestContext, input: AddNoteToCustomerInput): Promise<Customer> {
         const customer = await this.connection.getEntityOrThrow(ctx, Customer, input.id, {
             channelId: ctx.channelId,