@zoxllc/shopify-checkout-extensions 0.0.2 → 0.0.4

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.
Files changed (43) hide show
  1. package/migrate.ts +64 -0
  2. package/package.json +2 -1
  3. package/src/common/AndSelector.ts +17 -10
  4. package/src/common/Campaign.ts +27 -12
  5. package/src/common/CampaignFactory.ts +103 -51
  6. package/src/common/CartHasItemQualifier.ts +38 -22
  7. package/src/common/CartQuantityQualifier.ts +41 -20
  8. package/src/common/CountryCodeQualifier.ts +49 -0
  9. package/src/common/CustomerEmailQualifier.ts +14 -7
  10. package/src/common/CustomerTagQualifier.ts +29 -16
  11. package/src/common/DiscountCart.ts +78 -54
  12. package/src/common/DiscountInterface.ts +15 -3
  13. package/src/common/OrSelector.ts +13 -8
  14. package/src/common/ProductHandleSelector.ts +5 -3
  15. package/src/common/ProductIdSelector.ts +10 -4
  16. package/src/common/ProductTagSelector.ts +19 -10
  17. package/src/common/ProductTypeSelector.ts +10 -4
  18. package/src/common/SaleItemSelector.ts +2 -1
  19. package/src/common/Selector.ts +26 -13
  20. package/src/common/SubscriptionItemSelector.ts +5 -3
  21. package/src/index.ts +1 -1
  22. package/src/{common → lineItem}/BuyXGetY.ts +42 -20
  23. package/src/lineItem/ConditionalDiscount.ts +1 -1
  24. package/src/lineItem/FixedItemDiscount.ts +2 -4
  25. package/src/lineItem/PercentageDiscount.ts +2 -4
  26. package/src/shipping/FixedDiscount.ts +37 -0
  27. package/src/shipping/RateNameSelector.ts +54 -0
  28. package/src/shipping/ShippingDiscount.ts +75 -0
  29. package/src/shipping/api.ts +2097 -0
  30. package/tests/AndSelector.test.ts +1 -1
  31. package/tests/CartQuantityQualifier.test.ts +1 -1
  32. package/tests/CountryCodeQualifier.test.ts +56 -0
  33. package/tests/CustomerSubscriberQualifier.test.ts +1 -1
  34. package/tests/CustomerTagQualifier.test.ts +71 -0
  35. package/tests/DiscountCart.test.ts +1 -1
  36. package/tests/OrSelector.test.ts +1 -1
  37. package/tests/ProductIdSelector.test.ts +83 -0
  38. package/tests/ProductTagSelector.test.ts +1 -1
  39. package/tests/Qualifier.test.ts +1 -1
  40. package/tests/RateNameSelector.test.ts +107 -0
  41. package/tests/SaleItemSelector.test.ts +1 -1
  42. package/tests/Selector.test.ts +1 -1
  43. /package/src/{generated → lineItem}/api.ts +0 -0
package/migrate.ts ADDED
@@ -0,0 +1,64 @@
1
+ ShippingDiscount.new(
2
+ :all,
3
+ CustomerTagQualifier.new(
4
+ :does,
5
+ :match,
6
+ ["new customer 35", "tier: Active Subscriber", "active_subscriber", "tier: Subscribers", "Active Subscriber"]
7
+ ),
8
+ AndSelector.new(
9
+ CartAmountQualifier.new(
10
+ :cart,
11
+ :greater_than,
12
+ 50
13
+ ),
14
+ ReducedCartAmountQualifier.new(
15
+ :greater_than,
16
+ 50
17
+ ),
18
+ nil
19
+ ),
20
+ :any,
21
+ nil,
22
+ RateNameSelector.new(
23
+ :does,
24
+ :include,
25
+ ["FedEx"]
26
+ ),
27
+ FixedDiscount.new(
28
+ 10,
29
+ "ZOXPASS Discount"
30
+ )
31
+ ),
32
+ ShippingDiscount.new(
33
+ :all,
34
+ nil,
35
+ CountryCodeQualifier.new(
36
+ :is_one,
37
+ ["US"]
38
+ ),
39
+ :any,
40
+ SubscriptionItemSelector.new(
41
+ :is
42
+ ),
43
+ nil,
44
+ FixedDiscount.new(
45
+ 4,
46
+ ""
47
+ )
48
+ ),
49
+ ShippingDiscount.new(
50
+ :all,
51
+ nil,
52
+ nil,
53
+ :any,
54
+ nil,
55
+ RateNameSelector.new(
56
+ :does,
57
+ :include,
58
+ ["Standard - Untracked"]
59
+ ),
60
+ FixedDiscount.new(
61
+ 3,
62
+ ""
63
+ )
64
+ )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zoxllc/shopify-checkout-extensions",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "ZOX helper lib for shopify checkout extensions",
5
5
  "main": "src/index.ts",
6
6
  "directories": {
@@ -20,6 +20,7 @@
20
20
  },
21
21
  "homepage": "https://github.com/zoxllc/shopify-checkout-extensions#readme",
22
22
  "dependencies": {
23
+ "@shopify/app-bridge-types": "^0.0.7",
23
24
  "@shopify/shopify_function": "0.1.0",
24
25
  "@types/lodash": "^4.14.202",
25
26
  "javy": "0.1.1",
@@ -1,33 +1,40 @@
1
- import type { DiscountCart } from "./DiscountCart";
2
- import type { Qualifier } from "./Qualifier";
3
- import type { Selector } from "./Selector";
4
- import type { CartLine } from "extensions/zox-product-discount/generated/api";
1
+ import type { DiscountCart } from './DiscountCart';
2
+ import type { Qualifier } from './Qualifier';
3
+ import type { Selector } from './Selector';
4
+ import type { CartLine } from '../lineItem/api';
5
5
 
6
6
  export class AndSelector {
7
- is_a: "AndSelector";
7
+ is_a: 'AndSelector';
8
8
  conditions: (Qualifier | Selector)[];
9
9
 
10
10
  constructor(conditions: (Qualifier | Selector)[]) {
11
- this.is_a = "AndSelector";
11
+ this.is_a = 'AndSelector';
12
12
  this.conditions = conditions;
13
13
  }
14
14
 
15
- match(subject: CartLine | DiscountCart, selector?: Selector) {
15
+ match(
16
+ subject: CartLine | DiscountCart,
17
+ selector?: Selector
18
+ ) {
16
19
  try {
17
20
  const conditionsResult = this.conditions
18
21
  .map((condition) => {
19
22
  if (selector) {
20
23
  return (condition as Qualifier).match(
21
24
  subject as DiscountCart,
22
- selector,
25
+ selector
23
26
  );
24
27
  } else {
25
- return (condition as Selector).match(subject as CartLine);
28
+ return (condition as Selector).match(
29
+ subject as CartLine
30
+ );
26
31
  }
27
32
  })
28
33
  .filter((result) => result === true);
29
34
 
30
- return conditionsResult.length == this.conditions.length;
35
+ return (
36
+ conditionsResult.length == this.conditions.length
37
+ );
31
38
  } catch (e) {
32
39
  return false;
33
40
  }
@@ -1,8 +1,11 @@
1
- import type { AndSelector } from "./AndSelector";
2
- import type { DiscountCart } from "./DiscountCart";
3
- import type { OrSelector } from "./OrSelector";
4
- import type { Selector } from "./Selector";
5
- import { type Qualifier, QualifierBehavior } from "./Qualifier";
1
+ import type { AndSelector } from './AndSelector';
2
+ import type { DiscountCart } from './DiscountCart';
3
+ import type { OrSelector } from './OrSelector';
4
+ import type { Selector } from './Selector';
5
+ import {
6
+ type Qualifier,
7
+ QualifierBehavior,
8
+ } from './Qualifier';
6
9
 
7
10
  interface CampaignInterface {
8
11
  runWithHooks(cart: DiscountCart): DiscountCart;
@@ -13,28 +16,40 @@ interface CampaignInterface {
13
16
 
14
17
  export class Campaign implements CampaignInterface {
15
18
  behavior: QualifierBehavior;
16
- qualifiers: [AndSelector | OrSelector | Qualifier];
19
+ qualifiers?:
20
+ | (AndSelector | OrSelector | Qualifier)[]
21
+ | null;
17
22
  lineItemSelector?: Selector;
18
23
  message?: string;
19
24
 
20
25
  constructor(
21
26
  behavior: QualifierBehavior,
22
- qualifiers: [AndSelector | OrSelector | Qualifier]
27
+ qualifiers?:
28
+ | (AndSelector | OrSelector | Qualifier)[]
29
+ | null
23
30
  ) {
24
31
  this.behavior = behavior;
25
32
  this.qualifiers = qualifiers;
26
33
  }
27
34
 
28
35
  qualifies(discountCart: DiscountCart): boolean {
29
- // I have a feeling this needs to be revised... Check campaign.rb
30
- const qualifierResults = this.qualifiers.map((qualifier) =>
31
- qualifier.match(discountCart, this.lineItemSelector)
36
+ if (this.qualifiers == undefined) return true;
37
+
38
+ const qualifierResults = this.qualifiers.map(
39
+ (qualifier) =>
40
+ qualifier.match(discountCart, this.lineItemSelector)
32
41
  );
33
42
 
34
43
  if (this.behavior == QualifierBehavior.ALL) {
35
- return qualifierResults.filter((i) => i === false).length == 0;
44
+ return (
45
+ qualifierResults.filter((i) => i === false)
46
+ .length == 0
47
+ );
36
48
  } else if (this.behavior == QualifierBehavior.ANY) {
37
- return qualifierResults.filter((i) => i === true).length > 0;
49
+ return (
50
+ qualifierResults.filter((i) => i === true).length >
51
+ 0
52
+ );
38
53
  } else {
39
54
  return true;
40
55
  }
@@ -1,39 +1,43 @@
1
- import { OrSelector } from "./OrSelector";
2
- import type { Campaign } from "./Campaign";
3
- import type { DiscountInterface } from "./DiscountInterface";
1
+ import { OrSelector } from './OrSelector';
2
+ import type { Campaign } from './Campaign';
3
+ import type { DiscountInterface } from './DiscountInterface';
4
4
  import type {
5
5
  NumericalComparisonType,
6
6
  Qualifier,
7
7
  QualifierBehavior,
8
8
  QualifierMatchType,
9
9
  StringComparisonType,
10
- } from "./Qualifier";
11
- import type { MatchType, Selector } from "./Selector";
12
- import { ConditionalDiscount } from "../lineItem/ConditionalDiscount";
13
- import { FixedItemDiscount } from "../lineItem/FixedItemDiscount";
14
- import { PercentageDiscount } from "../lineItem/PercentageDiscount";
15
- import { AndSelector } from "./AndSelector";
16
- import { BuyXGetY } from "./BuyXGetY";
10
+ } from './Qualifier';
11
+ import type { MatchType, Selector } from './Selector';
12
+ import { ConditionalDiscount } from '../lineItem/ConditionalDiscount';
13
+ import { FixedItemDiscount } from '../lineItem/FixedItemDiscount';
14
+ import { PercentageDiscount } from '../lineItem/PercentageDiscount';
15
+ import { AndSelector } from './AndSelector';
16
+ import { BuyXGetY } from '../lineItem/BuyXGetY';
17
17
  import {
18
18
  type CartAmountBehavior,
19
19
  CartAmountQualifier,
20
- } from "./CartAmountQualifier";
20
+ } from './CartAmountQualifier';
21
21
  import {
22
22
  type CartQuantityBehavior,
23
23
  CartQuantityQualifier,
24
- } from "./CartQuantityQualifier";
25
- import { CustomerEmailQualifier } from "./CustomerEmailQualifier";
26
- import { CustomerSubscriberQualifier } from "./CustomerSubscriberQualifier";
27
- import { CustomerTagQualifier } from "./CustomerTagQualifier";
28
- import { PostCartAmountQualifier } from "./PostCartAmountQualifier";
29
- import { ProductIdSelector } from "./ProductIdSelector";
30
- import { ProductTagSelector } from "./ProductTagSelector";
31
- import { ProductTypeSelector } from "./ProductTypeSelector";
24
+ } from './CartQuantityQualifier';
25
+ import { CustomerEmailQualifier } from './CustomerEmailQualifier';
26
+ import { CustomerSubscriberQualifier } from './CustomerSubscriberQualifier';
27
+ import { CustomerTagQualifier } from './CustomerTagQualifier';
28
+ import { PostCartAmountQualifier } from './PostCartAmountQualifier';
29
+ import { ProductIdSelector } from './ProductIdSelector';
30
+ import { ProductTagSelector } from './ProductTagSelector';
31
+ import { ProductTypeSelector } from './ProductTypeSelector';
32
32
  import {
33
33
  SaleItemSelector,
34
34
  type SaleItemSelectorMatchType,
35
- } from "./SaleItemSelector";
36
- import { SubscriptionItemSelector } from "./SubscriptionItemSelector";
35
+ } from './SaleItemSelector';
36
+ import { SubscriptionItemSelector } from './SubscriptionItemSelector';
37
+ import { RateNameSelector } from '~/shipping/RateNameSelector';
38
+ import { FixedDiscount } from '~/shipping/FixedDiscount';
39
+ import { ShippingDiscount } from '~/shipping/ShippingDiscount';
40
+ import { CountryCodeQualifier } from './CountryCodeQualifier';
37
41
 
38
42
  export type InputConfig = {
39
43
  __type: string;
@@ -51,7 +55,9 @@ export type InputConfig = {
51
55
 
52
56
  export class CampaignFactory {
53
57
  static createFromConfig(config: InputConfig) {
54
- return CampaignFactory.createInputsObject(config) as Campaign;
58
+ return CampaignFactory.createInputsObject(
59
+ config
60
+ ) as Campaign;
55
61
  }
56
62
 
57
63
  private static parseInputConfig(
@@ -66,14 +72,16 @@ export class CampaignFactory {
66
72
  | InputConfig[]
67
73
  ) {
68
74
  if (
69
- typeof input == "string" ||
70
- typeof input == "number" ||
71
- typeof input == "boolean" ||
75
+ typeof input == 'string' ||
76
+ typeof input == 'number' ||
77
+ typeof input == 'boolean' ||
72
78
  input === null
73
79
  ) {
74
80
  return input;
75
81
  } else {
76
- return CampaignFactory.createInputsObject(input as InputConfig);
82
+ return CampaignFactory.createInputsObject(
83
+ input as InputConfig
84
+ );
77
85
  }
78
86
  }
79
87
 
@@ -89,14 +97,16 @@ export class CampaignFactory {
89
97
  | undefined {
90
98
  const args = config.inputs.map((input) => {
91
99
  if (Array.isArray(input)) {
92
- return input.map((i) => CampaignFactory.parseInputConfig(i));
100
+ return input.map((i) =>
101
+ CampaignFactory.parseInputConfig(i)
102
+ );
93
103
  } else {
94
104
  return CampaignFactory.parseInputConfig(input);
95
105
  }
96
106
  });
97
107
 
98
108
  switch (config.__type) {
99
- case "ConditionalDiscount":
109
+ case 'ConditionalDiscount':
100
110
  return new ConditionalDiscount(
101
111
  args[0] as QualifierBehavior,
102
112
  args[1] as [AndSelector | OrSelector | Qualifier],
@@ -104,7 +114,7 @@ export class CampaignFactory {
104
114
  args[3] as Selector,
105
115
  args[4] as number
106
116
  );
107
- case "BuyXGetY":
117
+ case 'BuyXGetY':
108
118
  return new BuyXGetY(
109
119
  args[0] as QualifierBehavior,
110
120
  args[1] as [AndSelector | OrSelector | Qualifier],
@@ -115,61 +125,103 @@ export class CampaignFactory {
115
125
  args[6] as number,
116
126
  args[7] as number
117
127
  );
118
- case "AndSelector":
119
- return new AndSelector([...args] as (Selector | Qualifier)[]);
120
- case "OrSelector":
121
- return new OrSelector([...args] as (Selector | Qualifier)[]);
122
- case "PostCartAmountQualifier":
128
+ case 'ShippingDiscount':
129
+ return new ShippingDiscount(
130
+ args[0] as QualifierBehavior,
131
+ args[1] as [AndSelector | OrSelector | Qualifier],
132
+ args[2] as DiscountInterface,
133
+ args[3] as Selector
134
+ );
135
+ case 'AndSelector':
136
+ return new AndSelector([...args] as (
137
+ | Selector
138
+ | Qualifier
139
+ )[]);
140
+ case 'OrSelector':
141
+ return new OrSelector([...args] as (
142
+ | Selector
143
+ | Qualifier
144
+ )[]);
145
+ case 'PostCartAmountQualifier':
123
146
  return new PostCartAmountQualifier(
124
147
  args[0] as NumericalComparisonType,
125
148
  args[1] as number
126
149
  );
127
- case "CartAmountQualifier":
150
+ case 'CartAmountQualifier':
128
151
  return new CartAmountQualifier(
129
152
  args[0] as CartAmountBehavior,
130
153
  args[1] as NumericalComparisonType,
131
154
  args[2] as number
132
155
  );
133
- case "CartQuantityQualifier":
156
+ case 'CartQuantityQualifier':
134
157
  return new CartQuantityQualifier(
135
158
  args[0] as CartQuantityBehavior,
136
159
  args[1] as NumericalComparisonType,
137
160
  args[2] as number
138
161
  );
139
- case "SaleItemSelector":
140
- return new SaleItemSelector(args[0] as SaleItemSelectorMatchType);
141
- case "ProductIdSelector":
142
- return new ProductIdSelector(args[0] as MatchType, args[1] as string[]);
143
- case "ProductTypeSelector":
162
+ case 'CountryCodeQualifier':
163
+ return new CountryCodeQualifier(
164
+ args[0] as QualifierMatchType,
165
+ args[1] as StringComparisonType,
166
+ args[2] as string[]
167
+ );
168
+ case 'SaleItemSelector':
169
+ return new SaleItemSelector(
170
+ args[0] as SaleItemSelectorMatchType
171
+ );
172
+ case 'ProductIdSelector':
173
+ return new ProductIdSelector(
174
+ args[0] as MatchType.IS_ONE | MatchType.NOT_ONE,
175
+ args[1] as string[]
176
+ );
177
+ case 'ProductTypeSelector':
144
178
  return new ProductTypeSelector(
145
179
  args[0] as MatchType,
146
180
  args[1] as string[]
147
181
  );
148
- case "ProductTagSelector":
182
+ case 'ProductTagSelector':
149
183
  return new ProductTagSelector(
150
184
  args[0] as QualifierMatchType,
151
185
  args[1] as StringComparisonType,
152
186
  args[2] as string[]
153
187
  );
154
- case "PercentageDiscount":
155
- return new PercentageDiscount(args[0] as number, args[1] as string);
156
- case "FixedItemDiscount":
188
+ case 'PercentageDiscount':
189
+ return new PercentageDiscount(
190
+ args[0] as number,
191
+ args[1] as string
192
+ );
193
+ case 'FixedItemDiscount':
157
194
  return new FixedItemDiscount(
158
195
  args[0] as number,
159
196
  args[1] as boolean,
160
197
  args[2] as string
161
198
  );
162
- case "SubscriptionItemSelector":
163
- return new SubscriptionItemSelector(args[0] as MatchType);
164
- case "CustomerSubscriberQualifier":
165
- return new CustomerSubscriberQualifier(args[0] as QualifierMatchType);
166
- case "CustomerEmailQualifier":
199
+ case 'FixedDiscount':
200
+ return new FixedDiscount(
201
+ args[0] as number,
202
+ args[1] as string
203
+ );
204
+ case 'SubscriptionItemSelector':
205
+ return new SubscriptionItemSelector(
206
+ args[0] as MatchType
207
+ );
208
+ case 'RateNameSelector':
209
+ return new RateNameSelector(
210
+ args[0] as MatchType.DOES | MatchType.DOES_NOT,
211
+ args[1] as StringComparisonType,
212
+ args[2] as string[]
213
+ );
214
+ case 'CustomerSubscriberQualifier':
215
+ return new CustomerSubscriberQualifier(
216
+ args[0] as QualifierMatchType
217
+ );
218
+ case 'CustomerEmailQualifier':
167
219
  return new CustomerEmailQualifier(
168
220
  args[0] as QualifierMatchType,
169
221
  args[1] as StringComparisonType,
170
222
  args[2] as string[]
171
223
  );
172
- case "CustomerTagQualifier":
224
+ case 'CustomerTagQualifier':
173
225
  return new CustomerTagQualifier(
174
226
  args[0] as QualifierMatchType,
175
227
  args[1] as StringComparisonType,
@@ -1,11 +1,14 @@
1
- import type { CartLine } from "extensions/zox-product-discount/generated/api";
2
- import type { DiscountCart } from "./DiscountCart";
3
- import { type NumericalComparisonType, Qualifier } from "./Qualifier";
4
- import { type Selector } from "./Selector";
1
+ import type { CartLine } from '../lineItem/api';
2
+ import type { DiscountCart } from './DiscountCart';
3
+ import {
4
+ type NumericalComparisonType,
5
+ Qualifier,
6
+ } from './Qualifier';
7
+ import { type Selector } from './Selector';
5
8
 
6
9
  export enum CartHasItemBehavior {
7
- QUANTITY = ":quantity",
8
- SUBTOTAL = ":subtotal",
10
+ QUANTITY = ':quantity',
11
+ SUBTOTAL = ':subtotal',
9
12
  }
10
13
 
11
14
  export class CartHasItemQualifier extends Qualifier {
@@ -24,7 +27,8 @@ export class CartHasItemQualifier extends Qualifier {
24
27
  this.quantityOrSubtotal = quantityOrSubtotal;
25
28
  this.comparisonType = comparisonType;
26
29
  this.amount =
27
- this.quantityOrSubtotal == CartHasItemBehavior.SUBTOTAL
30
+ this.quantityOrSubtotal ==
31
+ CartHasItemBehavior.SUBTOTAL
28
32
  ? amount
29
33
  : Math.floor(amount);
30
34
  this.itemSelector = itemSelector;
@@ -40,25 +44,37 @@ export class CartHasItemQualifier extends Qualifier {
40
44
 
41
45
  switch (this.quantityOrSubtotal) {
42
46
  case CartHasItemBehavior.QUANTITY:
43
- total = discountCart.cart.lines.reduce((quantity, line) => {
44
- return (
45
- quantity +
46
- (this.itemSelector.match(line as CartLine) ? line.quantity : 0)
47
- );
48
- }, 0);
47
+ total = discountCart.cart.lines.reduce(
48
+ (quantity, line) => {
49
+ return (
50
+ quantity +
51
+ (this.itemSelector.match(line as CartLine)
52
+ ? line.quantity
53
+ : 0)
54
+ );
55
+ },
56
+ 0
57
+ );
49
58
  break;
50
59
  case CartHasItemBehavior.SUBTOTAL:
51
- total = discountCart.cart.lines.reduce((amount, line) => {
52
- return (
53
- amount +
54
- (this.itemSelector.match(line as CartLine)
55
- ? line.cost.subtotalAmount.amount
56
- : 0)
57
- );
58
- }, 0);
60
+ total = discountCart.cart.lines.reduce(
61
+ (amount, line) => {
62
+ return (
63
+ amount +
64
+ (this.itemSelector.match(line as CartLine)
65
+ ? line.cost.subtotalAmount.amount
66
+ : 0)
67
+ );
68
+ },
69
+ 0
70
+ );
59
71
  break;
60
72
  }
61
73
 
62
- return this.compareAmounts(total, this.comparisonType, this.amount);
74
+ return this.compareAmounts(
75
+ total,
76
+ this.comparisonType,
77
+ this.amount
78
+ );
63
79
  }
64
80
  }
@@ -1,13 +1,16 @@
1
- import type { CartLine } from "extensions/zox-product-discount/generated/api";
2
- import type { DiscountCart } from "./DiscountCart";
3
- import { type NumericalComparisonType, Qualifier } from "./Qualifier";
4
- import { type Selector } from "./Selector";
1
+ import type { CartLine } from '../lineItem/api';
2
+ import type { DiscountCart } from './DiscountCart';
3
+ import {
4
+ type NumericalComparisonType,
5
+ Qualifier,
6
+ } from './Qualifier';
7
+ import { type Selector } from './Selector';
5
8
 
6
9
  export enum CartQuantityBehavior {
7
- CART = ":cart",
8
- ITEM = ":item",
9
- LINE_ANY = ":line_any",
10
- LINE_ALL = ":line_all",
10
+ CART = ':cart',
11
+ ITEM = ':item',
12
+ LINE_ANY = ':line_any',
13
+ LINE_ALL = ':line_all',
11
14
  }
12
15
 
13
16
  export class CartQuantityQualifier extends Qualifier {
@@ -36,17 +39,25 @@ export class CartQuantityQualifier extends Qualifier {
36
39
 
37
40
  switch (this.totalMethod) {
38
41
  case CartQuantityBehavior.ITEM:
39
- total = discountCart.cart.lines.reduce((totalQty, line) => {
40
- return (
41
- totalQty +
42
- ((selector ? selector.match(line as CartLine) : true)
43
- ? line.quantity
44
- : 0)
45
- );
46
- }, 0);
42
+ total = discountCart.cart.lines.reduce(
43
+ (totalQty, line) => {
44
+ return (
45
+ totalQty +
46
+ ((
47
+ selector
48
+ ? selector.match(line as CartLine)
49
+ : true
50
+ )
51
+ ? line.quantity
52
+ : 0)
53
+ );
54
+ },
55
+ 0
56
+ );
47
57
  break;
48
58
  case CartQuantityBehavior.CART:
49
- total = discountCart.totalLineItemQuantityExcludingGifts();
59
+ total =
60
+ discountCart.totalLineItemQuantityExcludingGifts();
50
61
  break;
51
62
  }
52
63
 
@@ -55,9 +66,15 @@ export class CartQuantityQualifier extends Qualifier {
55
66
  this.totalMethod == CartQuantityBehavior.LINE_ALL
56
67
  ) {
57
68
  const qualifiedItems = discountCart.cart.lines
58
- .filter((line) => (selector ? selector.match(line as CartLine) : true))
69
+ .filter((line) =>
70
+ selector ? selector.match(line as CartLine) : true
71
+ )
59
72
  .map((line) =>
60
- this.compareAmounts(line.quantity, this.comparisonType, this.quantity)
73
+ this.compareAmounts(
74
+ line.quantity,
75
+ this.comparisonType,
76
+ this.quantity
77
+ )
61
78
  );
62
79
 
63
80
  switch (this.totalMethod) {
@@ -67,7 +84,11 @@ export class CartQuantityQualifier extends Qualifier {
67
84
  return qualifiedItems.indexOf(false) == -1;
68
85
  }
69
86
  } else {
70
- return this.compareAmounts(total, this.comparisonType, this.quantity);
87
+ return this.compareAmounts(
88
+ total,
89
+ this.comparisonType,
90
+ this.quantity
91
+ );
71
92
  }
72
93
  }
73
94
  }
@@ -0,0 +1,49 @@
1
+ import type { DiscountCart } from './DiscountCart';
2
+ import {
3
+ StringComparisonType,
4
+ QualifierMatchType,
5
+ Qualifier,
6
+ } from './Qualifier';
7
+ import { type Selector } from './Selector';
8
+
9
+ export class CountryCodeQualifier extends Qualifier {
10
+ invert: boolean;
11
+ countryCodes: string[];
12
+
13
+ constructor(
14
+ matchType: QualifierMatchType,
15
+ countryCodes: string[]
16
+ ) {
17
+ super();
18
+ this.invert = matchType == QualifierMatchType.DOES_NOT;
19
+ this.countryCodes = countryCodes.map((e) =>
20
+ e.toLowerCase()
21
+ );
22
+ }
23
+
24
+ /**
25
+ * Determines if the customer has specified tags
26
+ * @param discountCart DiscountCart
27
+ * @param selector Selector
28
+ */
29
+ match(discountCart: DiscountCart, selector?: Selector) {
30
+ const matchResult =
31
+ (
32
+ discountCart.cart.deliveryGroups.filter(
33
+ (deliveryGroup) => {
34
+ const countryCode =
35
+ // @ts-ignore
36
+ deliveryGroup.deliveryAddress.countryCode.toLowerCase();
37
+
38
+ return this.countryCodes.includes(countryCode);
39
+ }
40
+ ) || []
41
+ ).length > 0;
42
+
43
+ if (this.invert) {
44
+ return !matchResult;
45
+ }
46
+
47
+ return matchResult;
48
+ }
49
+ }