@reactionary/commercetools 0.10.36 → 0.10.37

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.
@@ -165,16 +165,46 @@ class CommercetoolsCheckoutCapability extends CheckoutCapability {
165
165
  }
166
166
  async getAvailableShippingMethods(payload) {
167
167
  const client = await this.getClient();
168
- const shippingMethodsResponse = await client.shippingMethods.matchingCart().get({
169
- queryArgs: {
170
- cartId: payload.checkout.key
171
- }
172
- }).execute();
168
+ const [shippingMethodsResponse, cartResponse] = await Promise.all([
169
+ client.shippingMethods.matchingCart().get({
170
+ queryArgs: {
171
+ cartId: payload.checkout.key
172
+ }
173
+ }).execute(),
174
+ client.carts.withId({ ID: payload.checkout.key }).get().execute()
175
+ ]);
173
176
  const result = shippingMethodsResponse.body.results.map(
174
- (shippingMethod) => this.factory.parseShippingMethod(this.context, shippingMethod)
177
+ (shippingMethod) => this.factory.parseShippingMethod(this.context, this.withFreeShipping(shippingMethod, cartResponse.body))
175
178
  );
176
179
  return success(result);
177
180
  }
181
+ /**
182
+ * Quotes the matching shipping rates as free where the cart reaches the
183
+ * rate's free-above threshold. commercetools' matching-cart query returns
184
+ * the rates at their configured price and only applies the threshold once
185
+ * the method is set on the cart.
186
+ */
187
+ withFreeShipping(shippingMethod, cart) {
188
+ return {
189
+ ...shippingMethod,
190
+ zoneRates: shippingMethod.zoneRates.map((zoneRate) => ({
191
+ ...zoneRate,
192
+ shippingRates: zoneRate.shippingRates.map((rate) => rate.isMatching && this.isFreeShipping(rate, cart) ? { ...rate, price: { ...rate.price, centAmount: 0 } } : rate)
193
+ }))
194
+ };
195
+ }
196
+ /**
197
+ * Whether commercetools charges nothing for the rate once the method is set:
198
+ * shipping is free if the sum of the (custom) line item prices, after line
199
+ * item discounts, reaches the rate's free-above threshold.
200
+ */
201
+ isFreeShipping(rate, cart) {
202
+ if (!rate.freeAbove || rate.freeAbove.currencyCode !== cart.totalPrice.currencyCode) {
203
+ return false;
204
+ }
205
+ const itemsTotal = [...cart.lineItems, ...cart.customLineItems].reduce((sum, item) => sum + item.totalPrice.centAmount, 0);
206
+ return itemsTotal >= rate.freeAbove.centAmount;
207
+ }
178
208
  async getAvailablePaymentMethods(payload) {
179
209
  const staticMethods = this.getStaticPaymentMethods(payload.checkout);
180
210
  const dynamicMethods = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactionary/commercetools",
3
- "version": "0.10.36",
3
+ "version": "0.10.37",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./src/index.d.ts",
@@ -9,7 +9,7 @@
9
9
  "url": "git+https://github.com/Solteq/reactionary.git"
10
10
  },
11
11
  "dependencies": {
12
- "@reactionary/core": "0.10.36",
12
+ "@reactionary/core": "0.10.37",
13
13
  "zod": "4.1.9",
14
14
  "@commercetools/ts-client": "^4.9.1",
15
15
  "@commercetools/platform-sdk": "^8.25.0",
@@ -1,4 +1,4 @@
1
- import type { MyCartUpdateAction } from '@commercetools/platform-sdk';
1
+ import type { Cart as CTCart, MyCartUpdateAction, ShippingMethod as CTShippingMethod, ShippingRate as CTShippingRate } from '@commercetools/platform-sdk';
2
2
  import type { Cache, CheckoutFactory, CheckoutFactoryCheckoutOutput, CheckoutFactoryPaymentMethodOutput, CheckoutFactoryShippingMethodOutput, CheckoutFactoryWithOutput, CheckoutIdentifier, CheckoutMutationAddPaymentInstruction, CheckoutMutationFinalizeCheckout, CheckoutMutationInitiateCheckout, CheckoutMutationRemovePaymentInstruction, CheckoutMutationSetShippingAddress, CheckoutMutationSetShippingInstruction, CheckoutQueryById, CheckoutQueryForAvailablePaymentMethods, CheckoutQueryForAvailableShippingMethods, NotFoundError, PaymentMethod, RequestContext, Result } from '@reactionary/core';
3
3
  import { CheckoutCapability } from '@reactionary/core';
4
4
  import type { CommercetoolsAPI } from '../core/client.js';
@@ -23,6 +23,19 @@ export declare class CommercetoolsCheckoutCapability<TFactory extends CheckoutFa
23
23
  getById(payload: CheckoutQueryById): Promise<Result<CheckoutFactoryCheckoutOutput<TFactory>, NotFoundError>>;
24
24
  setShippingAddress(payload: CheckoutMutationSetShippingAddress): Promise<Result<CheckoutFactoryCheckoutOutput<TFactory>>>;
25
25
  getAvailableShippingMethods(payload: CheckoutQueryForAvailableShippingMethods): Promise<Result<CheckoutFactoryShippingMethodOutput<TFactory>[]>>;
26
+ /**
27
+ * Quotes the matching shipping rates as free where the cart reaches the
28
+ * rate's free-above threshold. commercetools' matching-cart query returns
29
+ * the rates at their configured price and only applies the threshold once
30
+ * the method is set on the cart.
31
+ */
32
+ protected withFreeShipping(shippingMethod: CTShippingMethod, cart: CTCart): CTShippingMethod;
33
+ /**
34
+ * Whether commercetools charges nothing for the rate once the method is set:
35
+ * shipping is free if the sum of the (custom) line item prices, after line
36
+ * item discounts, reaches the rate's free-above threshold.
37
+ */
38
+ protected isFreeShipping(rate: CTShippingRate, cart: CTCart): boolean;
26
39
  getAvailablePaymentMethods(payload: CheckoutQueryForAvailablePaymentMethods): Promise<Result<CheckoutFactoryPaymentMethodOutput<TFactory>[]>>;
27
40
  addPaymentInstruction(payload: CheckoutMutationAddPaymentInstruction): Promise<Result<CheckoutFactoryCheckoutOutput<TFactory>>>;
28
41
  removePaymentInstruction(payload: CheckoutMutationRemovePaymentInstruction): Promise<Result<CheckoutFactoryCheckoutOutput<TFactory>>>;