Passed
Push — 6.4 ( a2ab34...70d76f )
by Christian
13:23 queued 14s
created

src/Administration/Resources/app/administration/src/module/sw-order/component/sw-order-create-initial-modal/index.ts   B

Complexity

Total Complexity 48
Complexity/F 2.18

Size

Lines of Code 252
Function Count 22

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 197
dl 0
loc 252
rs 8.5599
c 0
b 0
f 0
wmc 48
mnd 26
bc 26
fnc 22
bpm 1.1818
cpm 2.1818
noi 0

21 Functions

Rating   Name   Duplication   Size   Complexity  
A index.ts ➔ currency 0 3 1
A index.ts ➔ updateOrderContext 0 7 1
A index.ts ➔ updateAutoPromotionToggle 0 3 1
A index.ts ➔ updatePromotion 0 3 1
A index.ts ➔ salesChannelId 0 2 4
C index.ts ➔ salesChannelContext 0 3 9
A index.ts ➔ onRemoveItems 0 12 2
A index.ts ➔ cartDelivery 0 3 2
A index.ts ➔ isCustomerActive 0 4 1
A index.ts ➔ modifyShippingCost 0 15 4
A index.ts ➔ disableAutoAppliedPromotions 0 7 1
A index.ts ➔ onSaveItem 0 12 2
A index.ts ➔ cancelCart 0 7 1
A index.ts ➔ addPromotionCodes 0 7 2
A index.ts ➔ onCloseModal 0 8 2
A index.ts ➔ updateShippingCost 0 3 1
A index.ts ➔ customer 0 4 1
A index.ts ➔ data 0 24 1
B index.ts ➔ onPreviewOrder 0 29 8
A index.ts ➔ cart 0 3 1
A index.ts ➔ promotionCodeItems 0 6 1

How to fix   Complexity   

Complexity

Complex classes like src/Administration/Resources/app/administration/src/module/sw-order/component/sw-order-create-initial-modal/index.ts often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import template from './sw-order-create-initial-modal.html.twig';
2
import './sw-order-create-initial-modal.scss';
3
4
import type {
5
    Customer,
6
    Cart,
7
    Currency,
8
    LineItem,
9
    SalesChannelContext,
10
    ContextSwitchParameters,
11
    CartDelivery,
12
} from '../../order.types';
13
14
import { LineItemType } from '../../order.types';
15
16
const { Component, State, Mixin, Service } = Shopware;
17
18
interface PromotionCodeItem {
19
    type: string,
20
    referencedId: string,
21
}
22
23
// eslint-disable-next-line sw-deprecation-rules/private-feature-declarations
24
Component.register('sw-order-create-initial-modal', {
25
    template,
26
27
    mixins: [
28
        Mixin.getByName('notification'),
29
        Mixin.getByName('cart-notification'),
30
    ],
31
32
    data(): {
33
        isLoading: boolean,
34
        isProductGridLoading: boolean,
35
        disabledAutoPromotion: boolean,
36
        promotionCodes: string[],
37
        productItems: LineItem[],
38
        context: ContextSwitchParameters,
39
        shippingCosts: number|null,
40
        } {
41
        return {
42
            productItems: [],
43
            promotionCodes: [],
44
            isLoading: false,
45
            isProductGridLoading: false,
46
            disabledAutoPromotion: false,
47
            shippingCosts: null,
48
            context: {
49
                currencyId: '',
50
                paymentMethodId: '',
51
                shippingMethodId: '',
52
                languageId: '',
53
                billingAddressId: '',
54
                shippingAddressId: '',
55
            },
56
        };
57
    },
58
59
    computed: {
60
        salesChannelId(): string {
61
            return this.customer?.salesChannelId ?? '';
62
        },
63
64
        salesChannelContext(): SalesChannelContext {
65
            return State.get('swOrder').context;
66
        },
67
68
        currency(): Currency {
69
            return this.salesChannelContext.currency;
70
        },
71
72
        cart(): Cart {
73
            return State.get('swOrder').cart;
74
        },
75
76
77
        customer(): Customer|null {
78
            return State.get('swOrder').customer;
79
        },
80
81
        isCustomerActive(): boolean {
82
            // eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-member-access
83
            return State.getters['swOrder/isCustomerActive'];
84
        },
85
86
        promotionCodeItems(): PromotionCodeItem[] {
87
            return this.promotionCodes.map(code => {
88
                return {
89
                    type: LineItemType.PROMOTION,
90
                    referencedId: code,
91
                };
92
            });
93
        },
94
95
        cartDelivery(): CartDelivery | null {
96
            return this.cart?.deliveries[0] as CartDelivery | null;
97
        },
98
    },
99
100
    watch: {
101
        salesChannelContext(value: SalesChannelContext): void {
102
            // Update context after switching customer successfully
103
            this.context = {
104
                ...this.context,
105
                currencyId: value.context.currencyId,
106
                languageId: value.context.languageIdChain[0],
107
                shippingMethodId: value.shippingMethod.id,
108
                paymentMethodId: value.paymentMethod.id,
109
                billingAddressId: value.customer?.activeBillingAddress?.id ?? '',
110
                shippingAddressId: value.customer?.activeShippingAddress?.id ?? '',
111
            };
112
        },
113
    },
114
115
    methods: {
116
        onCloseModal(): void {
117
            if (!this.customer || !this.cart.token) {
118
                this.$emit('modal-close');
119
                return;
120
            }
121
122
            void this.cancelCart().then(() => {
123
                this.$emit('modal-close');
124
            });
125
        },
126
127
        async onPreviewOrder(): Promise<void> {
128
            const promises = [];
129
130
            this.isLoading = true;
131
132
            promises.push(this.updateOrderContext());
133
134
            if (this.disabledAutoPromotion) {
135
                promises.push(this.disableAutoAppliedPromotions());
136
            }
137
138
            if (this.promotionCodes.length) {
139
                // eslint-disable-next-line @typescript-eslint/no-unsafe-call
140
                promises.push(this.addPromotionCodes());
141
            }
142
143
            if (this.shippingCosts !== null
144
                && this.shippingCosts !== this.cartDelivery?.shippingCosts?.totalPrice) {
145
                promises.push(this.modifyShippingCost(this.shippingCosts));
146
            }
147
148
            try {
149
                const responses = await Promise.all(promises);
150
                if (responses) {
151
                    this.$emit('order-preview');
152
                }
153
            } finally {
154
                this.isLoading = false;
155
            }
156
        },
157
158
        async onSaveItem(item: LineItem): Promise<void> {
159
            this.isProductGridLoading = true;
160
161
            try {
162
                await State.dispatch('swOrder/saveLineItem', {
163
                    salesChannelId: this.salesChannelId,
164
                    contextToken: this.cart.token,
165
                    item,
166
                });
167
            } finally {
168
                this.isProductGridLoading = false;
169
            }
170
        },
171
172
        addPromotionCodes(): Promise<void> {
173
            // eslint-disable-next-line @typescript-eslint/no-unsafe-return
174
            return State.dispatch('swOrder/saveMultipleLineItems', {
175
                salesChannelId: this.customer?.salesChannelId,
176
                contextToken: this.cart.token,
177
                items: this.promotionCodeItems,
178
            });
179
        },
180
181
        updatePromotion(promotions: string[]): void {
182
            this.promotionCodes = promotions;
183
        },
184
185
        async onRemoveItems(lineItemKeys: string[]): Promise<void> {
186
            this.isProductGridLoading = true;
187
188
            try {
189
                await State.dispatch('swOrder/removeLineItems', {
190
                    salesChannelId: this.salesChannelId,
191
                    contextToken: this.cart.token,
192
                    lineItemKeys: lineItemKeys,
193
                });
194
            } finally {
195
                this.isProductGridLoading = false;
196
            }
197
        },
198
199
        updateAutoPromotionToggle(value: boolean): void {
200
            this.disabledAutoPromotion = value;
201
        },
202
203
        updateShippingCost(value: number): void {
204
            this.shippingCosts = value;
205
        },
206
207
        updateOrderContext(): Promise<void> {
208
            // eslint-disable-next-line @typescript-eslint/no-unsafe-return
209
            return State.dispatch('swOrder/updateOrderContext', {
210
                context: this.context,
211
                salesChannelId: this.salesChannelId,
212
                contextToken: this.cart.token,
213
            });
214
        },
215
216
        disableAutoAppliedPromotions(): Promise<void> {
217
            const additionalParams = { salesChannelId: this.salesChannelId };
218
219
            return Service('cartStoreService').disableAutomaticPromotions(this.cart.token, additionalParams)
220
                .then(() => {
221
                    State.commit('swOrder/setDisabledAutoPromotion', true);
222
                });
223
        },
224
225
        modifyShippingCost(amount: number): Promise<void> {
226
            if (!this.cartDelivery) {
227
                return Promise.resolve();
228
            }
229
230
            const positiveAmount = Math.abs(amount);
231
            this.cartDelivery.shippingCosts.unitPrice = positiveAmount;
232
            this.cartDelivery.shippingCosts.totalPrice = positiveAmount;
233
234
            // eslint-disable-next-line @typescript-eslint/no-unsafe-return
235
            return State.dispatch('swOrder/modifyShippingCosts', {
236
                salesChannelId: this.customer?.salesChannelId,
237
                contextToken: this.cart.token,
238
                shippingCosts: this.cartDelivery?.shippingCosts,
239
            });
240
        },
241
242
        cancelCart(): Promise<void> {
243
            return State.dispatch('swOrder/cancelCart', {
244
                salesChannelId: this.salesChannelId,
245
                contextToken: this.cart.token,
246
            }).then(() => {
247
                this.$emit('modal-close');
248
            });
249
        },
250
    },
251
});
252