@labdigital/commercetools-mock 2.34.3 → 2.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,147 @@
1
+ import {
2
+ Cart,
3
+ CartValueTier,
4
+ InvalidOperationError,
5
+ ShippingRate,
6
+ ShippingRatePriceTier,
7
+ } from "@commercetools/platform-sdk";
8
+ import { CommercetoolsError } from "./exceptions";
9
+ import { GetParams, RepositoryContext } from "./repositories/abstract";
10
+ import { AbstractStorage } from "./storage/abstract";
11
+
12
+ export const markMatchingShippingRate = (
13
+ cart: Cart,
14
+ shippingRate: ShippingRate,
15
+ ): ShippingRate => {
16
+ const isMatching =
17
+ shippingRate.price.currencyCode === cart.totalPrice.currencyCode;
18
+ return {
19
+ ...shippingRate,
20
+ tiers: markMatchingShippingRatePriceTiers(cart, shippingRate.tiers),
21
+ isMatching: isMatching,
22
+ };
23
+ };
24
+
25
+ export const markMatchingShippingRatePriceTiers = (
26
+ cart: Cart,
27
+ tiers: ShippingRatePriceTier[],
28
+ ): ShippingRatePriceTier[] => {
29
+ if (tiers.length === 0) {
30
+ return [];
31
+ }
32
+
33
+ if (new Set(tiers.map((tier) => tier.type)).size > 1) {
34
+ throw new Error("Can't handle multiple types of tiers");
35
+ }
36
+
37
+ const tierType = tiers[0].type;
38
+ switch (tierType) {
39
+ case "CartValue":
40
+ return markMatchingCartValueTiers(cart, tiers as CartValueTier[]);
41
+ // case 'CartClassification':
42
+ // return markMatchingCartClassificationTiers(cart, tiers)
43
+ // case 'CartScore':
44
+ // return markMatchingCartScoreTiers(cart, tiers)
45
+ default:
46
+ throw new Error(`Unsupported tier type: ${tierType}`);
47
+ }
48
+ };
49
+
50
+ const markMatchingCartValueTiers = (
51
+ cart: Cart,
52
+ tiers: readonly CartValueTier[],
53
+ ): ShippingRatePriceTier[] => {
54
+ // Sort tiers from high to low since we only want to match the highest tier
55
+ const sortedTiers = [...tiers].sort(
56
+ (a, b) => b.minimumCentAmount - a.minimumCentAmount,
57
+ );
58
+
59
+ // Find the first tier that matches the cart and set the flag. We push
60
+ // the results into a map so that we can output the tiers in the same order as
61
+ // we received them.
62
+ const result: Record<number, ShippingRatePriceTier> = {};
63
+ let hasMatchingTier = false;
64
+ for (const tier of sortedTiers) {
65
+ const isMatching =
66
+ !hasMatchingTier &&
67
+ cart.totalPrice.currencyCode === tier.price.currencyCode &&
68
+ cart.totalPrice.centAmount >= tier.minimumCentAmount;
69
+
70
+ if (isMatching) hasMatchingTier = true;
71
+ result[tier.minimumCentAmount] = {
72
+ ...tier,
73
+ isMatching: isMatching,
74
+ };
75
+ }
76
+
77
+ return tiers.map((tier) => result[tier.minimumCentAmount]);
78
+ };
79
+
80
+ /*
81
+ * Retrieves all the ShippingMethods that can ship to the shipping address of
82
+ * the given Cart. Each ShippingMethod contains exactly one ShippingRate with
83
+ * the flag isMatching set to true. This ShippingRate is used when the
84
+ * ShippingMethod is added to the Cart.
85
+ */
86
+ export const getShippingMethodsMatchingCart = (
87
+ context: RepositoryContext,
88
+ storage: AbstractStorage,
89
+ cart: Cart,
90
+ params: GetParams = {},
91
+ ) => {
92
+ if (!cart.shippingAddress?.country) {
93
+ throw new CommercetoolsError<InvalidOperationError>({
94
+ code: "InvalidOperation",
95
+ message: `The cart with ID '${cart.id}' does not have a shipping address set.`,
96
+ });
97
+ }
98
+
99
+ // Get all shipping methods that have a zone that matches the shipping address
100
+ const zones = storage.query<"zone">(context.projectKey, "zone", {
101
+ where: [`locations(country="${cart.shippingAddress.country}"))`],
102
+ limit: 100,
103
+ });
104
+ const zoneIds = zones.results.map((zone) => zone.id);
105
+ const shippingMethods = storage.query<"shipping-method">(
106
+ context.projectKey,
107
+ "shipping-method",
108
+ {
109
+ "where": [
110
+ `zoneRates(zone(id in (:zoneIds)))`,
111
+ `zoneRates(shippingRates(price(currencyCode="${cart.totalPrice.currencyCode}")))`,
112
+ ],
113
+ "var.zoneIds": zoneIds,
114
+ "expand": params.expand,
115
+ },
116
+ );
117
+
118
+ // Make sure that each shipping method has exactly one shipping rate and
119
+ // that the shipping rate is marked as matching
120
+ const results = shippingMethods.results
121
+ .map((shippingMethod) => {
122
+ // Iterate through the zoneRates, process the shipping rates and filter
123
+ // out all zoneRates which have no matching shipping rates left
124
+ const rates = shippingMethod.zoneRates
125
+ .map((zoneRate) => ({
126
+ zone: zoneRate.zone,
127
+
128
+ // Iterate through the shippingRates and mark the matching ones
129
+ // then we filter out the non-matching ones
130
+ shippingRates: zoneRate.shippingRates
131
+ .map((rate) => markMatchingShippingRate(cart, rate))
132
+ .filter((rate) => rate.isMatching),
133
+ }))
134
+ .filter((zoneRate) => zoneRate.shippingRates.length > 0);
135
+
136
+ return {
137
+ ...shippingMethod,
138
+ zoneRates: rates,
139
+ };
140
+ })
141
+ .filter((shippingMethod) => shippingMethod.zoneRates.length > 0);
142
+
143
+ return {
144
+ ...shippingMethods,
145
+ results: results,
146
+ };
147
+ };
package/src/types.ts CHANGED
@@ -14,7 +14,8 @@ export type ServiceTypes =
14
14
  | "my-cart"
15
15
  | "my-order"
16
16
  | "my-payment"
17
- | "my-customer";
17
+ | "my-customer"
18
+ | "my-business-unit";
18
19
 
19
20
  export type Services = Partial<{
20
21
  [index in ServiceTypes]: AbstractService;
@@ -1,74 +0,0 @@
1
- import {
2
- Cart,
3
- CartValueTier,
4
- ShippingRate,
5
- ShippingRatePriceTier,
6
- } from "@commercetools/platform-sdk";
7
-
8
- export const markMatchingShippingRate = (
9
- cart: Cart,
10
- shippingRate: ShippingRate,
11
- ): ShippingRate => {
12
- const isMatching =
13
- shippingRate.price.currencyCode === cart.totalPrice.currencyCode;
14
- return {
15
- ...shippingRate,
16
- tiers: markMatchingShippingRatePriceTiers(cart, shippingRate.tiers),
17
- isMatching: isMatching,
18
- };
19
- };
20
-
21
- export const markMatchingShippingRatePriceTiers = (
22
- cart: Cart,
23
- tiers: ShippingRatePriceTier[],
24
- ): ShippingRatePriceTier[] => {
25
- if (tiers.length === 0) {
26
- return [];
27
- }
28
-
29
- if (new Set(tiers.map((tier) => tier.type)).size > 1) {
30
- throw new Error("Can't handle multiple types of tiers");
31
- }
32
-
33
- const tierType = tiers[0].type;
34
- switch (tierType) {
35
- case "CartValue":
36
- return markMatchingCartValueTiers(cart, tiers as CartValueTier[]);
37
- // case 'CartClassification':
38
- // return markMatchingCartClassificationTiers(cart, tiers)
39
- // case 'CartScore':
40
- // return markMatchingCartScoreTiers(cart, tiers)
41
- default:
42
- throw new Error(`Unsupported tier type: ${tierType}`);
43
- }
44
- };
45
-
46
- const markMatchingCartValueTiers = (
47
- cart: Cart,
48
- tiers: readonly CartValueTier[],
49
- ): ShippingRatePriceTier[] => {
50
- // Sort tiers from high to low since we only want to match the highest tier
51
- const sortedTiers = [...tiers].sort(
52
- (a, b) => b.minimumCentAmount - a.minimumCentAmount,
53
- );
54
-
55
- // Find the first tier that matches the cart and set the flag. We push
56
- // the results into a map so that we can output the tiers in the same order as
57
- // we received them.
58
- const result: Record<number, ShippingRatePriceTier> = {};
59
- let hasMatchingTier = false;
60
- for (const tier of sortedTiers) {
61
- const isMatching =
62
- !hasMatchingTier &&
63
- cart.totalPrice.currencyCode === tier.price.currencyCode &&
64
- cart.totalPrice.centAmount >= tier.minimumCentAmount;
65
-
66
- if (isMatching) hasMatchingTier = true;
67
- result[tier.minimumCentAmount] = {
68
- ...tier,
69
- isMatching: isMatching,
70
- };
71
- }
72
-
73
- return tiers.map((tier) => result[tier.minimumCentAmount]);
74
- };