@labdigital/commercetools-mock 2.45.1 → 2.47.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.
Files changed (80) hide show
  1. package/dist/index.cjs +614 -250
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +788 -59
  4. package/dist/index.d.ts +788 -59
  5. package/dist/index.js +602 -238
  6. package/dist/index.js.map +1 -1
  7. package/package.json +41 -48
  8. package/src/ctMock.ts +11 -13
  9. package/src/index.test.ts +5 -5
  10. package/src/lib/predicateParser.test.ts +91 -60
  11. package/src/lib/predicateParser.ts +38 -42
  12. package/src/lib/productSearchFilter.test.ts +18 -0
  13. package/src/lib/productSearchFilter.ts +7 -0
  14. package/src/lib/projectionSearchFilter.test.ts +17 -17
  15. package/src/lib/projectionSearchFilter.ts +2 -3
  16. package/src/oauth/server.test.ts +1 -1
  17. package/src/oauth/server.ts +11 -11
  18. package/src/priceSelector.ts +1 -1
  19. package/src/product-projection-search.ts +18 -19
  20. package/src/product-search.ts +48 -8
  21. package/src/repositories/business-unit.ts +17 -16
  22. package/src/repositories/cart/actions.ts +32 -32
  23. package/src/repositories/cart/helpers.ts +1 -1
  24. package/src/repositories/cart/index.ts +25 -8
  25. package/src/repositories/cart-discount/actions.ts +1 -4
  26. package/src/repositories/category/actions.ts +2 -6
  27. package/src/repositories/custom-object.ts +20 -21
  28. package/src/repositories/customer/actions.ts +4 -4
  29. package/src/repositories/errors.ts +1 -1
  30. package/src/repositories/extension.ts +2 -1
  31. package/src/repositories/helpers.ts +27 -27
  32. package/src/repositories/index.ts +17 -17
  33. package/src/repositories/my-customer.ts +1 -1
  34. package/src/repositories/my-order.ts +2 -2
  35. package/src/repositories/order/index.ts +1 -1
  36. package/src/repositories/product/actions.ts +1 -1
  37. package/src/repositories/quote/actions.ts +83 -0
  38. package/src/repositories/quote/index.ts +54 -0
  39. package/src/repositories/quote-request/actions.ts +84 -0
  40. package/src/repositories/quote-request/index.test.ts +167 -0
  41. package/src/repositories/quote-request/index.ts +67 -0
  42. package/src/repositories/quote-staged/actions.ts +84 -0
  43. package/src/repositories/quote-staged/index.ts +47 -0
  44. package/src/repositories/review.ts +4 -4
  45. package/src/repositories/shipping-method/actions.ts +17 -17
  46. package/src/repositories/shipping-method/index.ts +6 -6
  47. package/src/repositories/shopping-list/actions.ts +1 -1
  48. package/src/repositories/shopping-list/index.ts +9 -1
  49. package/src/repositories/subscription.ts +2 -4
  50. package/src/server.ts +3 -2
  51. package/src/services/abstract.ts +7 -7
  52. package/src/services/as-associate-order.test.ts +1 -1
  53. package/src/services/cart-discount.test.ts +1 -1
  54. package/src/services/cart.test.ts +40 -15
  55. package/src/services/category.test.ts +1 -1
  56. package/src/services/customer.test.ts +16 -55
  57. package/src/services/customer.ts +1 -1
  58. package/src/services/index.ts +20 -14
  59. package/src/services/inventory-entry.test.ts +5 -5
  60. package/src/services/my-cart.test.ts +2 -2
  61. package/src/services/my-customer.test.ts +2 -2
  62. package/src/services/order.test.ts +8 -8
  63. package/src/services/product-projection.test.ts +5 -5
  64. package/src/services/product-projection.ts +12 -14
  65. package/src/services/product.test.ts +155 -71
  66. package/src/services/quote-request.test.ts +59 -0
  67. package/src/services/quote-request.ts +16 -0
  68. package/src/services/quote-staged.ts +16 -0
  69. package/src/services/quote.ts +16 -0
  70. package/src/services/standalone-price.test.ts +4 -4
  71. package/src/services/state.test.ts +1 -1
  72. package/src/services/store.test.ts +2 -2
  73. package/src/services/tax-category.test.ts +1 -1
  74. package/src/shipping.ts +3 -3
  75. package/src/storage/in-memory.ts +55 -63
  76. package/src/testing/customer.ts +40 -0
  77. package/src/types.ts +51 -31
  78. package/src/repositories/quote-request.ts +0 -17
  79. package/src/repositories/quote.ts +0 -14
  80. package/src/repositories/staged-quote.ts +0 -17
@@ -7,36 +7,36 @@ import type {
7
7
  MissingTaxRateForCountryError,
8
8
  ShippingMethodDoesNotMatchCartError,
9
9
  } from "@commercetools/platform-sdk";
10
- import {
11
- type Address,
12
- type AddressDraft,
13
- type Cart,
14
- type CartAddItemShippingAddressAction,
15
- type CartAddLineItemAction,
16
- type CartChangeLineItemQuantityAction,
17
- type CartChangeTaxRoundingModeAction,
18
- type CartRemoveDiscountCodeAction,
19
- type CartRemoveLineItemAction,
20
- type CartSetBillingAddressAction,
21
- type CartSetBillingAddressCustomTypeAction,
22
- type CartSetCountryAction,
23
- type CartSetCustomFieldAction,
24
- type CartSetCustomShippingMethodAction,
25
- type CartSetCustomTypeAction,
26
- type CartSetCustomerEmailAction,
27
- type CartSetDirectDiscountsAction,
28
- type CartSetLineItemShippingDetailsAction,
29
- type CartSetLocaleAction,
30
- type CartSetShippingAddressAction,
31
- type CartSetShippingAddressCustomTypeAction,
32
- type CartSetShippingMethodAction,
33
- type CustomFields,
34
- type GeneralError,
35
- type ItemShippingDetails,
36
- type LineItem,
37
- type Product,
38
- type ProductPagedQueryResponse,
39
- type ProductVariant,
10
+ import type {
11
+ Address,
12
+ AddressDraft,
13
+ Cart,
14
+ CartAddItemShippingAddressAction,
15
+ CartAddLineItemAction,
16
+ CartChangeLineItemQuantityAction,
17
+ CartChangeTaxRoundingModeAction,
18
+ CartRemoveDiscountCodeAction,
19
+ CartRemoveLineItemAction,
20
+ CartSetBillingAddressAction,
21
+ CartSetBillingAddressCustomTypeAction,
22
+ CartSetCountryAction,
23
+ CartSetCustomFieldAction,
24
+ CartSetCustomShippingMethodAction,
25
+ CartSetCustomTypeAction,
26
+ CartSetCustomerEmailAction,
27
+ CartSetDirectDiscountsAction,
28
+ CartSetLineItemShippingDetailsAction,
29
+ CartSetLocaleAction,
30
+ CartSetShippingAddressAction,
31
+ CartSetShippingAddressCustomTypeAction,
32
+ CartSetShippingMethodAction,
33
+ CustomFields,
34
+ GeneralError,
35
+ ItemShippingDetails,
36
+ LineItem,
37
+ Product,
38
+ ProductPagedQueryResponse,
39
+ ProductVariant,
40
40
  } from "@commercetools/platform-sdk";
41
41
  import type {
42
42
  DirectDiscount,
@@ -232,7 +232,7 @@ export class CartUpdateHandler
232
232
  } else {
233
233
  throw new CommercetoolsError<GeneralError>({
234
234
  code: "General",
235
- message: `Either lineItemid or lineItemKey needs to be provided.`,
235
+ message: "Either lineItemid or lineItemKey needs to be provided.",
236
236
  });
237
237
  }
238
238
 
@@ -656,7 +656,7 @@ export class CartUpdateHandler
656
656
  // Locations cannot be assigned to more than one zone.
657
657
  // See https://docs.commercetools.com/api/projects/zones#location
658
658
  const zoneRate = method.zoneRates.find((rate) =>
659
- rate.zone.obj!.locations.some((loc) => loc.country === country),
659
+ rate.zone.obj?.locations.some((loc) => loc.country === country),
660
660
  );
661
661
 
662
662
  if (!zoneRate) {
@@ -24,7 +24,7 @@ export const selectPrice = ({
24
24
  };
25
25
 
26
26
  export const calculateLineItemTotalPrice = (lineItem: LineItem): number =>
27
- lineItem.price!.value.centAmount * lineItem.quantity;
27
+ lineItem.price?.value.centAmount * lineItem.quantity;
28
28
 
29
29
  export const calculateCartTotalPrice = (cart: Cart): number =>
30
30
  cart.lineItems.reduce((cur, item) => cur + item.totalPrice.centAmount, 0);
@@ -1,11 +1,12 @@
1
- import {
2
- type Cart,
3
- type CartDraft,
4
- type GeneralError,
5
- type LineItem,
6
- type LineItemDraft,
7
- type Product,
8
- type ProductPagedQueryResponse,
1
+ import type { InvalidOperationError } from "@commercetools/platform-sdk";
2
+ import type {
3
+ Cart,
4
+ CartDraft,
5
+ GeneralError,
6
+ LineItem,
7
+ LineItemDraft,
8
+ Product,
9
+ ProductPagedQueryResponse,
9
10
  } from "@commercetools/platform-sdk";
10
11
  import { v4 as uuidv4 } from "uuid";
11
12
  import type { Config } from "~src/config";
@@ -27,6 +28,21 @@ export class CartRepository extends AbstractResourceRepository<"cart"> {
27
28
  }
28
29
 
29
30
  create(context: RepositoryContext, draft: CartDraft): Cart {
31
+ if (draft.anonymousId && draft.customerId) {
32
+ throw new CommercetoolsError<InvalidOperationError>({
33
+ code: "InvalidOperation",
34
+ message: "Can set only one of customer OR anonymousId",
35
+ });
36
+ }
37
+
38
+ // Validate that the customer exists
39
+ if (draft.customerId) {
40
+ this._storage.getByResourceIdentifier(context.projectKey, {
41
+ typeId: "customer",
42
+ id: draft.customerId,
43
+ });
44
+ }
45
+
30
46
  const lineItems =
31
47
  draft.lineItems?.map((draftLineItem) =>
32
48
  this.draftLineItemtoLineItem(
@@ -45,6 +61,7 @@ export class CartRepository extends AbstractResourceRepository<"cart"> {
45
61
  : undefined,
46
62
  cartState: "Active",
47
63
  country: draft.country,
64
+ customerId: draft.customerId,
48
65
  customerEmail: draft.customerEmail,
49
66
  customLineItems: [],
50
67
  directDiscounts: [],
@@ -65,10 +65,7 @@ export class CartDiscountUpdateHandler
65
65
  throw new CommercetoolsError<InvalidOperationError>(
66
66
  {
67
67
  code: "InvalidOperation",
68
- message:
69
- "Cannot remove custom field " +
70
- name +
71
- " because it does not exist.",
68
+ message: `Cannot remove custom field ${name} because it does not exist.`,
72
69
  },
73
70
  400,
74
71
  );
@@ -100,17 +100,13 @@ export class CategoryUpdateHandler
100
100
  }
101
101
 
102
102
  if (assetId) {
103
- resource.assets = resource.assets.filter(function (obj) {
104
- return obj.id !== assetId;
105
- });
103
+ resource.assets = resource.assets.filter((obj) => obj.id !== assetId);
106
104
 
107
105
  return;
108
106
  }
109
107
 
110
108
  if (assetKey) {
111
- resource.assets = resource.assets.filter(function (obj) {
112
- return obj.key !== assetKey;
113
- });
109
+ resource.assets = resource.assets.filter((obj) => obj.key !== assetKey);
114
110
 
115
111
  return;
116
112
  }
@@ -42,28 +42,27 @@ export class CustomObjectRepository extends AbstractResourceRepository<"key-valu
42
42
  return updated;
43
43
  }
44
44
  return current;
45
- } else {
46
- // If the resource is new the only valid version is 0
47
- if (draft.version) {
48
- throw new CommercetoolsError<InvalidOperationError>(
49
- {
50
- code: "InvalidOperation",
51
- message: "version on create must be 0",
52
- },
53
- 400,
54
- );
55
- }
56
- const baseProperties = getBaseResourceProperties();
57
- const resource: CustomObject = {
58
- ...baseProperties,
59
- container: draft.container,
60
- key: draft.key,
61
- value: draft.value,
62
- };
63
-
64
- this.saveNew(context, resource);
65
- return resource;
66
45
  }
46
+ // If the resource is new the only valid version is 0
47
+ if (draft.version) {
48
+ throw new CommercetoolsError<InvalidOperationError>(
49
+ {
50
+ code: "InvalidOperation",
51
+ message: "version on create must be 0",
52
+ },
53
+ 400,
54
+ );
55
+ }
56
+ const baseProperties = getBaseResourceProperties();
57
+ const resource: CustomObject = {
58
+ ...baseProperties,
59
+ container: draft.container,
60
+ key: draft.key,
61
+ value: draft.value,
62
+ };
63
+
64
+ this.saveNew(context, resource);
65
+ return resource;
67
66
  }
68
67
 
69
68
  getWithContainerAndKey(
@@ -1,3 +1,4 @@
1
+ import assert from "node:assert";
1
2
  import type {
2
3
  Address,
3
4
  BaseAddress,
@@ -38,7 +39,6 @@ import type {
38
39
  InvalidJsonInputError,
39
40
  InvalidOperationError,
40
41
  } from "@commercetools/platform-sdk";
41
- import assert from "node:assert";
42
42
  import { CommercetoolsError } from "~src/exceptions";
43
43
  import { generateRandomString } from "~src/helpers";
44
44
  import { hashPassword } from "~src/lib/password";
@@ -49,7 +49,7 @@ import { createAddress, createCustomFields } from "../helpers";
49
49
 
50
50
  export class CustomerUpdateHandler
51
51
  extends AbstractUpdateHandler
52
- implements UpdateHandlerInterface<Customer, CustomerUpdateAction>
52
+ implements Partial<UpdateHandlerInterface<Customer, CustomerUpdateAction>>
53
53
  {
54
54
  addAddress(
55
55
  _context: RepositoryContext,
@@ -234,7 +234,7 @@ export class CustomerUpdateHandler
234
234
  }
235
235
  resource.authenticationMode = authMode;
236
236
  if (authMode === "ExternalAuth") {
237
- delete resource.password;
237
+ resource.password = undefined;
238
238
  return;
239
239
  }
240
240
  if (authMode === "Password") {
@@ -461,7 +461,7 @@ export class CustomerUpdateHandler
461
461
  resource: Writable<Customer>,
462
462
  addressId: string | undefined,
463
463
  addressKey: string | undefined,
464
- required: boolean = false,
464
+ required = false,
465
465
  ): Address | undefined {
466
466
  if (addressKey) {
467
467
  const address = resource.addresses.find((a) => a.key === addressKey);
@@ -1,4 +1,4 @@
1
- import { type ConcurrentModificationError } from "@commercetools/platform-sdk";
1
+ import type { ConcurrentModificationError } from "@commercetools/platform-sdk";
2
2
  import { CommercetoolsError } from "~src/exceptions";
3
3
 
4
4
  export const checkConcurrentModification = (
@@ -49,7 +49,8 @@ export class ExtensionRepository extends AbstractResourceRepository<"extension">
49
49
  extension,
50
50
  "destination.authentication.headerValue",
51
51
  );
52
- } else if (extension.destination.type === "AWSLambda") {
52
+ }
53
+ if (extension.destination.type === "AWSLambda") {
53
54
  return maskSecretValue(resource, "destination.accessSecret");
54
55
  }
55
56
  }
@@ -5,39 +5,39 @@ import type {
5
5
  BusinessUnitResourceIdentifier,
6
6
  RoundingMode,
7
7
  } from "@commercetools/platform-sdk";
8
- import {
9
- type Address,
10
- type Associate,
11
- type AssociateDraft,
12
- type AssociateRoleAssignment,
13
- type AssociateRoleAssignmentDraft,
14
- type AssociateRoleKeyReference,
15
- type AssociateRoleResourceIdentifier,
16
- type BaseAddress,
17
- type CentPrecisionMoney,
18
- type CustomFields,
19
- type CustomFieldsDraft,
20
- type HighPrecisionMoney,
21
- type HighPrecisionMoneyDraft,
22
- type InvalidJsonInputError,
23
- type Price,
24
- type PriceDraft,
25
- type Reference,
26
- type ReferencedResourceNotFoundError,
27
- type ResourceIdentifier,
28
- type Store,
29
- type StoreKeyReference,
30
- type StoreReference,
31
- type StoreResourceIdentifier,
32
- type Type,
33
- type _Money,
8
+ import type {
9
+ Address,
10
+ Associate,
11
+ AssociateDraft,
12
+ AssociateRoleAssignment,
13
+ AssociateRoleAssignmentDraft,
14
+ AssociateRoleKeyReference,
15
+ AssociateRoleResourceIdentifier,
16
+ BaseAddress,
17
+ CentPrecisionMoney,
18
+ CustomFields,
19
+ CustomFieldsDraft,
20
+ HighPrecisionMoney,
21
+ HighPrecisionMoneyDraft,
22
+ InvalidJsonInputError,
23
+ Price,
24
+ PriceDraft,
25
+ Reference,
26
+ ReferencedResourceNotFoundError,
27
+ ResourceIdentifier,
28
+ Store,
29
+ StoreKeyReference,
30
+ StoreReference,
31
+ StoreResourceIdentifier,
32
+ Type,
33
+ _Money,
34
34
  } from "@commercetools/platform-sdk";
35
35
  import { Decimal } from "decimal.js/decimal";
36
36
  import type { Request } from "express";
37
37
  import { v4 as uuidv4 } from "uuid";
38
38
  import { CommercetoolsError } from "~src/exceptions";
39
39
  import type { AbstractStorage } from "../storage";
40
- import { type RepositoryContext } from "./abstract";
40
+ import type { RepositoryContext } from "./abstract";
41
41
 
42
42
  export const createAddress = (
43
43
  base: BaseAddress | undefined,
@@ -30,10 +30,10 @@ import { ProductTypeRepository } from "./product-type";
30
30
  import { ProjectRepository } from "./project";
31
31
  import { QuoteRepository } from "./quote";
32
32
  import { QuoteRequestRepository } from "./quote-request";
33
+ import { StagedQuoteRepository } from "./quote-staged";
33
34
  import { ReviewRepository } from "./review";
34
35
  import { ShippingMethodRepository } from "./shipping-method";
35
36
  import { ShoppingListRepository } from "./shopping-list";
36
- import { StagedQuoteRepository } from "./staged-quote";
37
37
  import { StandAlonePriceRepository } from "./standalone-price";
38
38
  import { StateRepository } from "./state";
39
39
  import { StoreRepository } from "./store";
@@ -52,42 +52,42 @@ export const createRepositories = (config: Config) => ({
52
52
  "associate-role": new AssociateRoleRepository(config),
53
53
  "attribute-group": new AttributeGroupRepository(config),
54
54
  "business-unit": new BusinessUnitRepository(config),
55
- "category": new CategoryRepository(config),
56
- "cart": new CartRepository(config),
55
+ category: new CategoryRepository(config),
56
+ cart: new CartRepository(config),
57
57
  "cart-discount": new CartDiscountRepository(config),
58
- "customer": new CustomerRepository(config),
59
- "channel": new ChannelRepository(config),
58
+ customer: new CustomerRepository(config),
59
+ channel: new ChannelRepository(config),
60
60
  "customer-group": new CustomerGroupRepository(config),
61
61
  "discount-code": new DiscountCodeRepository(config),
62
- "extension": new ExtensionRepository(config),
62
+ extension: new ExtensionRepository(config),
63
63
  "inventory-entry": new InventoryEntryRepository(config),
64
64
  "key-value-document": new CustomObjectRepository(config),
65
- "order": new OrderRepository(config),
65
+ order: new OrderRepository(config),
66
66
  "order-edit": new OrderEditRepository(config),
67
- "payment": new PaymentRepository(config),
67
+ payment: new PaymentRepository(config),
68
68
  "my-cart": new CartRepository(config),
69
69
  "my-order": new MyOrderRepository(config),
70
70
  "my-customer": new MyCustomerRepository(config),
71
71
  "my-payment": new PaymentRepository(config),
72
72
  "my-shopping-list": new ShoppingListRepository(config),
73
- "product": new ProductRepository(config),
73
+ product: new ProductRepository(config),
74
74
  "product-type": new ProductTypeRepository(config),
75
75
  "product-discount": new ProductDiscountRepository(config),
76
76
  "product-projection": new ProductProjectionRepository(config),
77
77
  "product-selection": new ProductSelectionRepository(config),
78
78
  "product-tailoring": new ProductTailoringRepository(config),
79
- "project": new ProjectRepository(config),
80
- "review": new ReviewRepository(config),
81
- "quote": new QuoteRepository(config),
79
+ project: new ProjectRepository(config),
80
+ review: new ReviewRepository(config),
81
+ quote: new QuoteRepository(config),
82
82
  "quote-request": new QuoteRequestRepository(config),
83
83
  "shipping-method": new ShippingMethodRepository(config),
84
84
  "shopping-list": new ShoppingListRepository(config),
85
85
  "staged-quote": new StagedQuoteRepository(config),
86
86
  "standalone-price": new StandAlonePriceRepository(config),
87
- "state": new StateRepository(config),
88
- "store": new StoreRepository(config),
89
- "subscription": new SubscriptionRepository(config),
87
+ state: new StateRepository(config),
88
+ store: new StoreRepository(config),
89
+ subscription: new SubscriptionRepository(config),
90
90
  "tax-category": new TaxCategoryRepository(config),
91
- "type": new TypeRepository(config),
92
- "zone": new ZoneRepository(config),
91
+ type: new TypeRepository(config),
92
+ zone: new ZoneRepository(config),
93
93
  });
@@ -8,7 +8,7 @@ import type {
8
8
  import { CommercetoolsError } from "~src/exceptions";
9
9
  import { hashPassword, validateEmailVerifyToken } from "../lib/password";
10
10
  import type { Writable } from "../types";
11
- import { type RepositoryContext } from "./abstract";
11
+ import type { RepositoryContext } from "./abstract";
12
12
  import { CustomerRepository } from "./customer";
13
13
 
14
14
  export class MyCustomerRepository extends CustomerRepository {
@@ -1,10 +1,10 @@
1
+ import assert from "node:assert";
1
2
  import type {
2
3
  CartReference,
3
4
  MyOrderFromCartDraft,
4
5
  Order,
5
6
  } from "@commercetools/platform-sdk";
6
- import assert from "assert";
7
- import { type RepositoryContext } from "./abstract";
7
+ import type { RepositoryContext } from "./abstract";
8
8
  import { OrderRepository } from "./order";
9
9
 
10
10
  export class MyOrderRepository extends OrderRepository {
@@ -1,3 +1,4 @@
1
+ import assert from "node:assert";
1
2
  import type {
2
3
  Cart,
3
4
  CartReference,
@@ -13,7 +14,6 @@ import type {
13
14
  ProductPagedQueryResponse,
14
15
  ProductVariant,
15
16
  } from "@commercetools/platform-sdk";
16
- import assert from "assert";
17
17
  import type { Config } from "~src/config";
18
18
  import { CommercetoolsError } from "~src/exceptions";
19
19
  import { generateRandomString, getBaseResourceProperties } from "~src/helpers";
@@ -420,7 +420,7 @@ export class ProductUpdateHandler
420
420
 
421
421
  if (position >= variantImages.length) {
422
422
  throw new Error(
423
- `Invalid position given. Position in images where the image should be moved. Must be between 0 and the total number of images minus 1.`,
423
+ "Invalid position given. Position in images where the image should be moved. Must be between 0 and the total number of images minus 1.",
424
424
  );
425
425
  }
426
426
 
@@ -0,0 +1,83 @@
1
+ import type {
2
+ InvalidJsonInputError,
3
+ Quote,
4
+ QuoteSetCustomFieldAction,
5
+ QuoteSetCustomTypeAction,
6
+ QuoteTransitionStateAction,
7
+ QuoteUpdateAction,
8
+ StateReference,
9
+ } from "@commercetools/platform-sdk";
10
+ import { CommercetoolsError } from "~src/exceptions";
11
+ import type { Writable } from "~src/types";
12
+ import type { RepositoryContext, UpdateHandlerInterface } from "../abstract";
13
+ import { AbstractUpdateHandler } from "../abstract";
14
+ import { getReferenceFromResourceIdentifier } from "../helpers";
15
+
16
+ export class QuoteUpdateHandler
17
+ extends AbstractUpdateHandler
18
+ implements Partial<UpdateHandlerInterface<Quote, QuoteUpdateAction>>
19
+ {
20
+ setCustomField(
21
+ context: RepositoryContext,
22
+ resource: Quote,
23
+ { name, value }: QuoteSetCustomFieldAction,
24
+ ) {
25
+ if (!resource.custom) {
26
+ throw new Error("Resource has no custom field");
27
+ }
28
+ resource.custom.fields[name] = value;
29
+ }
30
+
31
+ setCustomType(
32
+ context: RepositoryContext,
33
+ resource: Writable<Quote>,
34
+ { type, fields }: QuoteSetCustomTypeAction,
35
+ ) {
36
+ if (!type) {
37
+ resource.custom = undefined;
38
+ } else {
39
+ const resolvedType = this._storage.getByResourceIdentifier(
40
+ context.projectKey,
41
+ type,
42
+ );
43
+ if (!resolvedType) {
44
+ throw new Error(`Type ${type} not found`);
45
+ }
46
+
47
+ resource.custom = {
48
+ type: {
49
+ typeId: "type",
50
+ id: resolvedType.id,
51
+ },
52
+ fields: fields || {},
53
+ };
54
+ }
55
+ }
56
+
57
+ transitionState(
58
+ context: RepositoryContext,
59
+ resource: Writable<Quote>,
60
+ { state, force }: QuoteTransitionStateAction,
61
+ ) {
62
+ let stateReference: StateReference | undefined = undefined;
63
+ if (state) {
64
+ stateReference = getReferenceFromResourceIdentifier<StateReference>(
65
+ state,
66
+ context.projectKey,
67
+ this._storage,
68
+ );
69
+ resource.state = stateReference;
70
+ } else {
71
+ throw new CommercetoolsError<InvalidJsonInputError>(
72
+ {
73
+ code: "InvalidJsonInput",
74
+ message: "Request body does not contain valid JSON.",
75
+ detailedErrorMessage: "actions -> state: Missing required value",
76
+ },
77
+ 400,
78
+ );
79
+ }
80
+
81
+ return resource;
82
+ }
83
+ }
@@ -0,0 +1,54 @@
1
+ import type { Quote, QuoteDraft } from "@commercetools/platform-sdk";
2
+ import type { Config } from "~src/config";
3
+ import { getBaseResourceProperties } from "~src/helpers";
4
+ import type { RepositoryContext } from "../abstract";
5
+ import { AbstractResourceRepository } from "../abstract";
6
+ import { QuoteUpdateHandler } from "./actions";
7
+
8
+ export class QuoteRepository extends AbstractResourceRepository<"quote"> {
9
+ constructor(config: Config) {
10
+ super("quote", config);
11
+ this.actions = new QuoteUpdateHandler(config.storage);
12
+ }
13
+
14
+ create(context: RepositoryContext, draft: QuoteDraft): Quote {
15
+ const staged = this._storage.getByResourceIdentifier<"staged-quote">(
16
+ context.projectKey,
17
+ draft.stagedQuote,
18
+ );
19
+
20
+ const cart = this._storage.getByResourceIdentifier<"cart">(
21
+ context.projectKey,
22
+ staged.quotationCart,
23
+ );
24
+
25
+ if (!cart.customerId) {
26
+ throw new Error("Cart does not have a customer");
27
+ }
28
+
29
+ const resource: Quote = {
30
+ ...getBaseResourceProperties(),
31
+ quoteState: "Accepted",
32
+ quoteRequest: staged.quoteRequest,
33
+ lineItems: cart.lineItems,
34
+ customLineItems: cart.customLineItems,
35
+ customer: {
36
+ typeId: "customer",
37
+ id: cart.customerId,
38
+ },
39
+ stagedQuote: {
40
+ typeId: "staged-quote",
41
+ id: staged.id,
42
+ },
43
+ totalPrice: cart.totalPrice,
44
+ taxedPrice: cart.taxedPrice,
45
+ taxMode: cart.taxMode,
46
+ taxRoundingMode: cart.taxRoundingMode,
47
+ taxCalculationMode: cart.taxCalculationMode,
48
+ billingAddress: cart.billingAddress,
49
+ shippingAddress: cart.shippingAddress,
50
+ };
51
+
52
+ return resource;
53
+ }
54
+ }