@labdigital/commercetools-mock 2.62.1 → 2.64.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.
@@ -10,6 +10,8 @@ import type {
10
10
  Order,
11
11
  OrderFromCartDraft,
12
12
  OrderImportDraft,
13
+ OrderPagedSearchResponse,
14
+ OrderSearchRequest,
13
15
  Product,
14
16
  ProductPagedQueryResponse,
15
17
  ProductVariant,
@@ -27,6 +29,7 @@ import {
27
29
  calculateTaxedPriceFromRate,
28
30
  calculateTaxTotals,
29
31
  } from "#src/lib/tax.ts";
32
+ import { OrderSearch } from "#src/orderSearch.ts";
30
33
  import {
31
34
  createShippingInfoFromMethod,
32
35
  getShippingMethodsMatchingCart,
@@ -35,6 +38,7 @@ import type { Writable } from "#src/types.ts";
35
38
  import type { RepositoryContext } from "../abstract.ts";
36
39
  import { AbstractResourceRepository, type QueryParams } from "../abstract.ts";
37
40
  import {
41
+ calculateMoneyTotalCentAmount,
38
42
  createAddress,
39
43
  createCentPrecisionMoney,
40
44
  createCustomFields,
@@ -45,9 +49,12 @@ import {
45
49
  import { OrderUpdateHandler } from "./actions.ts";
46
50
 
47
51
  export class OrderRepository extends AbstractResourceRepository<"order"> {
52
+ protected _searchService: OrderSearch;
53
+
48
54
  constructor(config: Config) {
49
55
  super("order", config);
50
56
  this.actions = new OrderUpdateHandler(config.storage);
57
+ this._searchService = new OrderSearch(config);
51
58
  }
52
59
 
53
60
  create(context: RepositoryContext, draft: OrderFromCartDraft): Order {
@@ -260,11 +267,11 @@ export class OrderRepository extends AbstractResourceRepository<"order"> {
260
267
 
261
268
  const quantity = draft.quantity ?? 1;
262
269
  const totalPrice = createCentPrecisionMoney({
263
- ...draft.price.value,
264
- centAmount: (draft.price.value.centAmount ?? 0) * quantity,
270
+ currencyCode: draft.price.value.currencyCode,
271
+ centAmount: calculateMoneyTotalCentAmount(draft.price.value, quantity),
265
272
  });
266
273
 
267
- const lineItem: LineItem = {
274
+ return {
268
275
  ...getBaseResourceProperties(),
269
276
  custom: createCustomFields(
270
277
  draft.custom,
@@ -295,9 +302,7 @@ export class OrderRepository extends AbstractResourceRepository<"order"> {
295
302
  price: createPrice(draft.price),
296
303
  attributes: variant.attributes,
297
304
  },
298
- };
299
-
300
- return lineItem;
305
+ } satisfies LineItem;
301
306
  }
302
307
 
303
308
  private customLineItemFromImportDraft(
@@ -306,11 +311,11 @@ export class OrderRepository extends AbstractResourceRepository<"order"> {
306
311
  ): CustomLineItem {
307
312
  const quantity = draft.quantity ?? 1;
308
313
  const totalPrice = createCentPrecisionMoney({
309
- ...draft.money,
310
- centAmount: (draft.money.centAmount ?? 0) * quantity,
314
+ currencyCode: draft.money.currencyCode,
315
+ centAmount: calculateMoneyTotalCentAmount(draft.money, quantity),
311
316
  });
312
317
 
313
- const lineItem: CustomLineItem = {
318
+ return {
314
319
  ...getBaseResourceProperties(),
315
320
  custom: createCustomFields(
316
321
  draft.custom,
@@ -332,9 +337,7 @@ export class OrderRepository extends AbstractResourceRepository<"order"> {
332
337
  draft.taxRate,
333
338
  ),
334
339
  taxedPricePortions: [],
335
- };
336
-
337
- return lineItem;
340
+ } satisfies CustomLineItem;
338
341
  }
339
342
 
340
343
  getWithOrderNumber(
@@ -409,4 +412,11 @@ export class OrderRepository extends AbstractResourceRepository<"order"> {
409
412
  deliveries: [],
410
413
  };
411
414
  }
415
+
416
+ search(
417
+ context: RepositoryContext,
418
+ searchRequest: OrderSearchRequest,
419
+ ): OrderPagedSearchResponse {
420
+ return this._searchService.search(context.projectKey, searchRequest);
421
+ }
412
422
  }
@@ -2,12 +2,12 @@ import type {
2
2
  ShippingRate,
3
3
  ShippingRateDraft,
4
4
  } from "@commercetools/platform-sdk";
5
- import { createTypedMoney } from "../helpers.ts";
5
+ import { createCentPrecisionMoney } from "../helpers.ts";
6
6
 
7
7
  export const transformShippingRate = (
8
8
  rate: ShippingRateDraft,
9
9
  ): ShippingRate => ({
10
- price: createTypedMoney(rate.price),
11
- freeAbove: rate.freeAbove && createTypedMoney(rate.freeAbove),
10
+ price: createCentPrecisionMoney(rate.price),
11
+ freeAbove: rate.freeAbove && createCentPrecisionMoney(rate.freeAbove),
12
12
  tiers: rate.tiers || [],
13
13
  });
@@ -3,6 +3,7 @@ import type {
3
3
  Address,
4
4
  Cart,
5
5
  CentPrecisionMoney,
6
+ HighPrecisionMoneyDraft,
6
7
  ProductDraft,
7
8
  ShippingMethod,
8
9
  ShippingMethodDraft,
@@ -13,6 +14,7 @@ import type {
13
14
  } from "@commercetools/platform-sdk";
14
15
  import supertest from "supertest";
15
16
  import { afterEach, beforeEach, describe, expect, test } from "vitest";
17
+ import { calculateMoneyTotalCentAmount } from "#src/repositories/helpers.ts";
16
18
  import { customerDraftFactory } from "#src/testing/customer.ts";
17
19
  import { CommercetoolsMock } from "../index.ts";
18
20
 
@@ -786,6 +788,166 @@ describe("Cart Update Actions", () => {
786
788
  );
787
789
  });
788
790
 
791
+ test("setLineItemPrice supports high precision external price", async () => {
792
+ const product = await supertest(ctMock.app)
793
+ .post("/dummy/products")
794
+ .send(productDraft)
795
+ .then((x) => x.body);
796
+
797
+ assert(product, "product not created");
798
+
799
+ const baseCartResponse = await supertest(ctMock.app)
800
+ .post("/dummy/carts")
801
+ .send({ currency: "EUR" });
802
+ expect(baseCartResponse.status).toBe(201);
803
+ const baseCart = baseCartResponse.body as Cart;
804
+
805
+ const addLineItemResponse = await supertest(ctMock.app)
806
+ .post(`/dummy/carts/${baseCart.id}`)
807
+ .send({
808
+ version: baseCart.version,
809
+ actions: [
810
+ {
811
+ action: "addLineItem",
812
+ sku: product.masterData.current.masterVariant.sku,
813
+ quantity: 2,
814
+ },
815
+ ],
816
+ });
817
+ expect(addLineItemResponse.status).toBe(200);
818
+ const cartWithLineItem = addLineItemResponse.body as Cart;
819
+ const lineItem = cartWithLineItem.lineItems[0];
820
+ assert(lineItem, "lineItem not created");
821
+
822
+ const externalPrice: HighPrecisionMoneyDraft = {
823
+ type: "highPrecision",
824
+ currencyCode: "EUR",
825
+ fractionDigits: 3,
826
+ preciseAmount: 1015,
827
+ };
828
+ const expectedUnitCentAmount = calculateMoneyTotalCentAmount(
829
+ externalPrice,
830
+ 1,
831
+ );
832
+ const expectedTotalCentAmount = calculateMoneyTotalCentAmount(
833
+ externalPrice,
834
+ 2,
835
+ );
836
+
837
+ const response = await supertest(ctMock.app)
838
+ .post(`/dummy/carts/${cartWithLineItem.id}`)
839
+ .send({
840
+ version: cartWithLineItem.version,
841
+ actions: [
842
+ {
843
+ action: "setLineItemPrice",
844
+ lineItemId: lineItem.id,
845
+ externalPrice,
846
+ },
847
+ ],
848
+ });
849
+
850
+ expect(response.status).toBe(200);
851
+ expect(response.body.version).toBe(cartWithLineItem.version + 1);
852
+ expect(response.body.lineItems).toHaveLength(1);
853
+
854
+ const updatedLineItem = response.body.lineItems[0];
855
+ expect(updatedLineItem.priceMode).toBe("ExternalPrice");
856
+ expect(updatedLineItem.price.value.type).toBe("highPrecision");
857
+ expect(updatedLineItem.price.value.currencyCode).toBe(
858
+ externalPrice.currencyCode,
859
+ );
860
+ expect(updatedLineItem.price.value.fractionDigits).toBe(
861
+ externalPrice.fractionDigits,
862
+ );
863
+ expect(updatedLineItem.price.value.preciseAmount).toBe(
864
+ externalPrice.preciseAmount,
865
+ );
866
+ expect(updatedLineItem.price.value.centAmount).toBe(expectedUnitCentAmount);
867
+ expect(updatedLineItem.totalPrice.centAmount).toBe(expectedTotalCentAmount);
868
+ expect(response.body.totalPrice.centAmount).toBe(expectedTotalCentAmount);
869
+ });
870
+
871
+ test("setLineItemPrice supports high precision external price with fractionDigits 5", async () => {
872
+ const product = await supertest(ctMock.app)
873
+ .post("/dummy/products")
874
+ .send(productDraft)
875
+ .then((x) => x.body);
876
+
877
+ assert(product, "product not created");
878
+
879
+ const baseCartResponse = await supertest(ctMock.app)
880
+ .post("/dummy/carts")
881
+ .send({ currency: "EUR" });
882
+ expect(baseCartResponse.status).toBe(201);
883
+ const baseCart = baseCartResponse.body as Cart;
884
+
885
+ const addLineItemResponse = await supertest(ctMock.app)
886
+ .post(`/dummy/carts/${baseCart.id}`)
887
+ .send({
888
+ version: baseCart.version,
889
+ actions: [
890
+ {
891
+ action: "addLineItem",
892
+ sku: product.masterData.current.masterVariant.sku,
893
+ quantity: 2,
894
+ },
895
+ ],
896
+ });
897
+ expect(addLineItemResponse.status).toBe(200);
898
+ const cartWithLineItem = addLineItemResponse.body as Cart;
899
+ const lineItem = cartWithLineItem.lineItems[0];
900
+ assert(lineItem, "lineItem not created");
901
+
902
+ const externalPrice: HighPrecisionMoneyDraft = {
903
+ type: "highPrecision",
904
+ currencyCode: "EUR",
905
+ fractionDigits: 5,
906
+ preciseAmount: 101499,
907
+ };
908
+ const expectedUnitCentAmount = calculateMoneyTotalCentAmount(
909
+ externalPrice,
910
+ 1,
911
+ );
912
+ const expectedTotalCentAmount = calculateMoneyTotalCentAmount(
913
+ externalPrice,
914
+ 2,
915
+ );
916
+
917
+ const response = await supertest(ctMock.app)
918
+ .post(`/dummy/carts/${cartWithLineItem.id}`)
919
+ .send({
920
+ version: cartWithLineItem.version,
921
+ actions: [
922
+ {
923
+ action: "setLineItemPrice",
924
+ lineItemId: lineItem.id,
925
+ externalPrice,
926
+ },
927
+ ],
928
+ });
929
+
930
+ expect(response.status).toBe(200);
931
+ expect(response.body.version).toBe(cartWithLineItem.version + 1);
932
+ expect(response.body.lineItems).toHaveLength(1);
933
+
934
+ const updatedLineItem = response.body.lineItems[0];
935
+ expect(updatedLineItem.priceMode).toBe("ExternalPrice");
936
+ expect(updatedLineItem.price.value.type).toBe("highPrecision");
937
+ expect(updatedLineItem.price.value.currencyCode).toBe(
938
+ externalPrice.currencyCode,
939
+ );
940
+ expect(updatedLineItem.price.value.fractionDigits).toBe(
941
+ externalPrice.fractionDigits,
942
+ );
943
+ expect(updatedLineItem.price.value.preciseAmount).toBe(
944
+ externalPrice.preciseAmount,
945
+ );
946
+ expect(updatedLineItem.price.value.centAmount).toBe(expectedUnitCentAmount);
947
+ expect(updatedLineItem.totalPrice.centAmount).toBe(expectedTotalCentAmount);
948
+ expect(response.body.totalPrice.centAmount).toBe(expectedTotalCentAmount);
949
+ });
950
+
789
951
  test("setLineItemPrice fails when the money uses another currency", async () => {
790
952
  const product = await supertest(ctMock.app)
791
953
  .post("/dummy/products")
@@ -17,6 +17,7 @@ export class OrderService extends AbstractService {
17
17
 
18
18
  extraRoutes(router: Router) {
19
19
  router.post("/import", this.import.bind(this));
20
+ router.post("/search", this.search.bind(this));
20
21
  router.get(
21
22
  "/order-number=:orderNumber",
22
23
  this.getWithOrderNumber.bind(this),
@@ -56,4 +57,12 @@ export class OrderService extends AbstractService {
56
57
  ],
57
58
  });
58
59
  }
60
+
61
+ search(request: Request, response: Response) {
62
+ const resource = this.repository.search(
63
+ getRepositoryContext(request),
64
+ request.body,
65
+ );
66
+ response.status(200).send(resource);
67
+ }
59
68
  }