@labdigital/commercetools-mock 0.6.4 → 0.7.1

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 (118) hide show
  1. package/dist/index.d.ts +385 -3
  2. package/dist/index.global.js +49770 -0
  3. package/dist/index.global.js.map +1 -0
  4. package/dist/index.js +4622 -6
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.mjs +4590 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +30 -17
  9. package/src/ctMock.ts +5 -0
  10. package/src/helpers.ts +15 -0
  11. package/src/lib/projectionSearchFilter.test.ts +177 -0
  12. package/src/lib/projectionSearchFilter.ts +248 -0
  13. package/src/priceSelector.test.ts +96 -0
  14. package/src/priceSelector.ts +109 -0
  15. package/src/product-projection-search.ts +149 -0
  16. package/src/projectAPI.ts +19 -20
  17. package/src/repositories/category.ts +36 -0
  18. package/src/repositories/channel.ts +104 -0
  19. package/src/repositories/customer-group.ts +37 -0
  20. package/src/repositories/discount-code.ts +37 -0
  21. package/src/repositories/helpers.ts +46 -4
  22. package/src/repositories/product-discount.ts +181 -0
  23. package/src/repositories/product-projection.ts +29 -55
  24. package/src/repositories/product-type.ts +88 -6
  25. package/src/repositories/product.ts +49 -9
  26. package/src/repositories/shipping-method.ts +31 -0
  27. package/src/repositories/store.ts +43 -3
  28. package/src/repositories/type.ts +19 -0
  29. package/src/services/custom-object.test.ts +2 -2
  30. package/src/services/product-discount.ts +33 -0
  31. package/src/services/product-projection.test.ts +171 -116
  32. package/src/services/product.test.ts +12 -0
  33. package/src/storage.ts +116 -58
  34. package/src/types.ts +9 -2
  35. package/dist/commercetools-mock.cjs.development.js +0 -4380
  36. package/dist/commercetools-mock.cjs.development.js.map +0 -1
  37. package/dist/commercetools-mock.cjs.production.min.js +0 -2
  38. package/dist/commercetools-mock.cjs.production.min.js.map +0 -1
  39. package/dist/commercetools-mock.esm.js +0 -4372
  40. package/dist/commercetools-mock.esm.js.map +0 -1
  41. package/dist/constants.d.ts +0 -2
  42. package/dist/ctMock.d.ts +0 -32
  43. package/dist/exceptions.d.ts +0 -12
  44. package/dist/helpers.d.ts +0 -6
  45. package/dist/lib/expandParser.d.ts +0 -15
  46. package/dist/lib/filterParser.d.ts +0 -1
  47. package/dist/lib/haversine.d.ts +0 -8
  48. package/dist/lib/masking.d.ts +0 -1
  49. package/dist/lib/predicateParser.d.ts +0 -11
  50. package/dist/lib/proxy.d.ts +0 -1
  51. package/dist/oauth/errors.d.ts +0 -8
  52. package/dist/oauth/helpers.d.ts +0 -2
  53. package/dist/oauth/server.d.ts +0 -12
  54. package/dist/oauth/store.d.ts +0 -14
  55. package/dist/projectAPI.d.ts +0 -12
  56. package/dist/repositories/abstract.d.ts +0 -33
  57. package/dist/repositories/cart-discount.d.ts +0 -9
  58. package/dist/repositories/cart.d.ts +0 -21
  59. package/dist/repositories/category.d.ts +0 -18
  60. package/dist/repositories/channel.d.ts +0 -6
  61. package/dist/repositories/custom-object.d.ts +0 -8
  62. package/dist/repositories/customer-group.d.ts +0 -11
  63. package/dist/repositories/customer.d.ts +0 -11
  64. package/dist/repositories/discount-code.d.ts +0 -8
  65. package/dist/repositories/errors.d.ts +0 -2
  66. package/dist/repositories/extension.d.ts +0 -8
  67. package/dist/repositories/helpers.d.ts +0 -10
  68. package/dist/repositories/inventory-entry.d.ts +0 -14
  69. package/dist/repositories/my-order.d.ts +0 -6
  70. package/dist/repositories/order.d.ts +0 -26
  71. package/dist/repositories/payment.d.ts +0 -23
  72. package/dist/repositories/product-projection.d.ts +0 -10
  73. package/dist/repositories/product-type.d.ts +0 -10
  74. package/dist/repositories/product.d.ts +0 -11
  75. package/dist/repositories/project.d.ts +0 -8
  76. package/dist/repositories/shipping-method.d.ts +0 -10
  77. package/dist/repositories/shopping-list.d.ts +0 -6
  78. package/dist/repositories/state.d.ts +0 -8
  79. package/dist/repositories/store.d.ts +0 -10
  80. package/dist/repositories/subscription.d.ts +0 -6
  81. package/dist/repositories/tax-category.d.ts +0 -10
  82. package/dist/repositories/type.d.ts +0 -8
  83. package/dist/repositories/zone.d.ts +0 -8
  84. package/dist/server.d.ts +0 -1
  85. package/dist/services/abstract.d.ts +0 -20
  86. package/dist/services/cart-discount.d.ts +0 -9
  87. package/dist/services/cart.d.ts +0 -12
  88. package/dist/services/category.d.ts +0 -9
  89. package/dist/services/channel.d.ts +0 -9
  90. package/dist/services/custom-object.d.ts +0 -13
  91. package/dist/services/customer-group.d.ts +0 -9
  92. package/dist/services/customer.d.ts +0 -10
  93. package/dist/services/discount-code.d.ts +0 -9
  94. package/dist/services/extension.d.ts +0 -9
  95. package/dist/services/inventory-entry.d.ts +0 -9
  96. package/dist/services/my-cart.d.ts +0 -11
  97. package/dist/services/my-customer.d.ts +0 -13
  98. package/dist/services/my-order.d.ts +0 -10
  99. package/dist/services/my-payment.d.ts +0 -9
  100. package/dist/services/order.d.ts +0 -12
  101. package/dist/services/payment.d.ts +0 -9
  102. package/dist/services/product-projection.d.ts +0 -11
  103. package/dist/services/product-type.d.ts +0 -11
  104. package/dist/services/product.d.ts +0 -9
  105. package/dist/services/project.d.ts +0 -11
  106. package/dist/services/shipping-method.d.ts +0 -10
  107. package/dist/services/shopping-list.d.ts +0 -9
  108. package/dist/services/state.d.ts +0 -9
  109. package/dist/services/store.d.ts +0 -11
  110. package/dist/services/subscription.d.ts +0 -9
  111. package/dist/services/tax-category.d.ts +0 -11
  112. package/dist/services/type.d.ts +0 -9
  113. package/dist/services/zone.d.ts +0 -9
  114. package/dist/storage.d.ts +0 -56
  115. package/dist/types.d.ts +0 -89
  116. package/dist/validate.d.ts +0 -7482
  117. package/src/lib/filterParser.test.ts +0 -15
  118. package/src/lib/filterParser.ts +0 -17
@@ -0,0 +1,109 @@
1
+ import {
2
+ InvalidInputError,
3
+ Price,
4
+ Product,
5
+ ProductVariant,
6
+ } from '@commercetools/platform-sdk'
7
+ import { CommercetoolsError } from './exceptions'
8
+ import { Writable } from './types'
9
+
10
+ export type PriceSelector = {
11
+ currency?: string
12
+ country?: string
13
+ customerGroup?: string
14
+ channel?: string
15
+ }
16
+
17
+ /**
18
+ * Apply the price selector on all the variants. The price selector is applied
19
+ * on all the prices per variant and the first match per variant is stored in
20
+ * the scopedPrice attribute
21
+ */
22
+ export const applyPriceSelector = (
23
+ products: Product[],
24
+ selector: PriceSelector
25
+ ) => {
26
+ validatePriceSelector(selector)
27
+
28
+ for (const product of products) {
29
+ const variants: Writable<ProductVariant>[] = [
30
+ product.masterData.staged?.masterVariant,
31
+ ...(product.masterData.staged?.variants || []),
32
+
33
+ product.masterData.current?.masterVariant,
34
+ ...(product.masterData.current?.variants || []),
35
+ ].filter(x => x != undefined)
36
+
37
+ for (const variant of variants) {
38
+ const scopedPrices =
39
+ variant.prices?.filter(p => priceSelectorFilter(p, selector)) ?? []
40
+
41
+ if (scopedPrices.length > 0) {
42
+ const price = scopedPrices[0]
43
+
44
+ variant.scopedPriceDiscounted = false
45
+ variant.scopedPrice = {
46
+ ...price,
47
+ currentValue: price.value,
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+
54
+ const validatePriceSelector = (selector: PriceSelector) => {
55
+ if (
56
+ (selector.country || selector.channel || selector.customerGroup) &&
57
+ !selector.currency
58
+ ) {
59
+ throw new CommercetoolsError<InvalidInputError>(
60
+ {
61
+ code: 'InvalidInput',
62
+ message:
63
+ 'The price selecting parameters country, channel and customerGroup ' +
64
+ 'cannot be used without the currency.',
65
+ },
66
+ 400
67
+ )
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Return a boolean to indicate if the price matches the selector. Price
73
+ * selection requires that if the selector or the price has a specific value
74
+ * then it should match.
75
+ */
76
+ export const priceSelectorFilter = (
77
+ price: Price,
78
+ selector: PriceSelector
79
+ ): boolean => {
80
+ if (
81
+ (selector.country || price.country) &&
82
+ selector.country !== price.country
83
+ ) {
84
+ return false
85
+ }
86
+
87
+ if (
88
+ (selector.currency || price.value.currencyCode) &&
89
+ selector.currency !== price.value.currencyCode
90
+ ) {
91
+ return false
92
+ }
93
+
94
+ if (
95
+ (selector.channel || price.channel?.id) &&
96
+ selector.channel !== price.channel?.id
97
+ ) {
98
+ return false
99
+ }
100
+
101
+ if (
102
+ (selector.customerGroup || price.customerGroup?.id) &&
103
+ selector.customerGroup !== price.customerGroup?.id
104
+ ) {
105
+ return false
106
+ }
107
+
108
+ return true
109
+ }
@@ -0,0 +1,149 @@
1
+ import {
2
+ InvalidInputError,
3
+ ProductProjectionPagedSearchResponse,
4
+ Product,
5
+ ProductProjection,
6
+ QueryParam,
7
+ } from '@commercetools/platform-sdk'
8
+ import { CommercetoolsError } from './exceptions'
9
+ import { parseFilterExpression } from './lib/projectionSearchFilter'
10
+ import { applyPriceSelector } from './priceSelector'
11
+ import { AbstractStorage } from './storage'
12
+
13
+ export type ProductProjectionSearchParams = {
14
+ fuzzy?: boolean
15
+ fuzzyLevel?: number
16
+ markMatchingVariants?: boolean
17
+ staged?: boolean
18
+ filter?: string[]
19
+ 'filter.facets'?: string[]
20
+ 'filter.query'?: string[]
21
+ facet?: string | string[]
22
+ sort?: string | string[]
23
+ limit?: number
24
+ offset?: number
25
+ withTotal?: boolean
26
+ priceCurrency?: string
27
+ priceCountry?: string
28
+ priceCustomerGroup?: string
29
+ priceChannel?: string
30
+ localeProjection?: string
31
+ storeProjection?: string
32
+ expand?: string | string[]
33
+ [key: string]: QueryParam
34
+ }
35
+
36
+ export class ProductProjectionSearch {
37
+ protected _storage: AbstractStorage
38
+
39
+ constructor(storage: AbstractStorage) {
40
+ this._storage = storage
41
+ }
42
+
43
+ search(
44
+ projectKey: string,
45
+ params: ProductProjectionSearchParams
46
+ ): ProductProjectionPagedSearchResponse {
47
+ // Get a copy of all the products in the storage engine. We need a copy
48
+ // since we will be modifying the data.
49
+ let resources = this._storage
50
+ .all(projectKey, 'product')
51
+ .map(r => JSON.parse(JSON.stringify(r)))
52
+
53
+ let markMatchingVariant = params.markMatchingVariants ?? false
54
+
55
+ // Apply the priceSelector
56
+ applyPriceSelector(resources, {
57
+ country: params.priceCountry,
58
+ channel: params.priceChannel,
59
+ customerGroup: params.priceCustomerGroup,
60
+ currency: params.priceCurrency,
61
+ })
62
+
63
+ // Apply filters pre facetting
64
+ if (params.filter) {
65
+ try {
66
+ const filters = params.filter.map(f =>
67
+ parseFilterExpression(f, params.staged ?? false)
68
+ )
69
+
70
+ // Filters can modify the output. So clone the resources first.
71
+ resources = resources
72
+ .filter(resource =>
73
+ filters.every(f => f(resource, markMatchingVariant))
74
+ )
75
+ } catch (err) {
76
+ throw new CommercetoolsError<InvalidInputError>(
77
+ {
78
+ code: 'InvalidInput',
79
+ message: (err as any).message,
80
+ },
81
+ 400
82
+ )
83
+ }
84
+ }
85
+
86
+ // TODO: Calculate facets
87
+
88
+ // Apply filters post facetting
89
+ if (params['filter.query']) {
90
+ try {
91
+ const filters = params['filter.query'].map(f =>
92
+ parseFilterExpression(f, params.staged ?? false)
93
+ )
94
+ resources = resources
95
+ .filter(resource =>
96
+ filters.every(f => f(resource, markMatchingVariant))
97
+ )
98
+ } catch (err) {
99
+ throw new CommercetoolsError<InvalidInputError>(
100
+ {
101
+ code: 'InvalidInput',
102
+ message: (err as any).message,
103
+ },
104
+ 400
105
+ )
106
+ }
107
+ }
108
+
109
+ // Get the total before slicing the array
110
+ const totalResources = resources.length
111
+
112
+ // Apply offset, limit
113
+ const offset = params.offset || 0
114
+ const limit = params.limit || 20
115
+ resources = resources.slice(offset, offset + limit)
116
+
117
+ // Expand the resources
118
+ if (params.expand !== undefined) {
119
+ resources = resources.map(resource => {
120
+ return this._storage.expand(projectKey, resource, params.expand)
121
+ })
122
+ }
123
+
124
+ return {
125
+ count: totalResources,
126
+ total: resources.length,
127
+ offset: offset,
128
+ limit: limit,
129
+ results: resources.map(this.transform),
130
+ facets: {},
131
+ }
132
+ }
133
+
134
+ transform(product: Product): ProductProjection {
135
+ const obj = product.masterData.current
136
+ return {
137
+ id: product.id,
138
+ createdAt: product.createdAt,
139
+ lastModifiedAt: product.lastModifiedAt,
140
+ version: product.version,
141
+ name: obj.name,
142
+ slug: obj.slug,
143
+ categories: obj.categories,
144
+ masterVariant: obj.masterVariant,
145
+ variants: obj.variants,
146
+ productType: product.productType,
147
+ }
148
+ }
149
+ }
package/src/projectAPI.ts CHANGED
@@ -1,7 +1,14 @@
1
+ import { ReferenceTypeId } from '@commercetools/platform-sdk'
1
2
  import { GetParams } from 'repositories/abstract'
2
3
  import { getBaseResourceProperties } from './helpers'
3
4
  import { AbstractStorage } from './storage'
4
- import { RepositoryMap, ResourceMap, Services } from './types'
5
+ import {
6
+ RepositoryMap,
7
+ RepositoryTypes,
8
+ ResourceMap,
9
+ Services,
10
+ ServiceTypes,
11
+ } from './types'
5
12
 
6
13
  export class ProjectAPI {
7
14
  private projectKey: string
@@ -18,18 +25,10 @@ export class ProjectAPI {
18
25
  this._services = services
19
26
  }
20
27
 
21
- add<ReferenceTypeId extends keyof ResourceMap>(
22
- typeId: ReferenceTypeId | 'custom-object',
23
- resource: ResourceMap[ReferenceTypeId]
24
- ) {
25
- //@ts-ignore
26
- if (typeId === 'custom-object') typeId = 'key-value-document'
27
-
28
- const parsedTypeId = typeId as ReferenceTypeId
29
-
30
- const service = this._services[parsedTypeId]
28
+ add(typeId: ReferenceTypeId, resource: ResourceMap[ReferenceTypeId]) {
29
+ const service = this._services[typeId]
31
30
  if (service) {
32
- this._storage.add(this.projectKey, parsedTypeId, {
31
+ this._storage.add(this.projectKey, typeId as ReferenceTypeId, {
33
32
  ...getBaseResourceProperties(),
34
33
  ...resource,
35
34
  })
@@ -38,26 +37,26 @@ export class ProjectAPI {
38
37
  }
39
38
  }
40
39
 
41
- get<ReferenceTypeId extends keyof ResourceMap>(
42
- typeId: ReferenceTypeId,
40
+ get<RT extends RepositoryTypes>(
41
+ typeId: RT,
43
42
  id: string,
44
43
  params?: GetParams
45
- ): ResourceMap[ReferenceTypeId] {
44
+ ): ResourceMap[RT] {
46
45
  return this._storage.get(
47
46
  this.projectKey,
48
47
  typeId,
49
48
  id,
50
49
  params
51
- ) as ResourceMap[ReferenceTypeId]
50
+ ) as ResourceMap[RT]
52
51
  }
53
52
 
54
53
  // TODO: Not sure if we want to expose this...
55
- getRepository<ReferenceTypeId extends keyof RepositoryMap>(
56
- typeId: ReferenceTypeId
57
- ): RepositoryMap[ReferenceTypeId] {
54
+ getRepository<RT extends keyof RepositoryMap>(
55
+ typeId: ServiceTypes
56
+ ): RepositoryMap[RT] {
58
57
  const service = this._services[typeId]
59
58
  if (service !== undefined) {
60
- return service.repository as RepositoryMap[ReferenceTypeId]
59
+ return service.repository as RepositoryMap[RT]
61
60
  }
62
61
  throw new Error('No such repository')
63
62
  }
@@ -6,6 +6,8 @@ import {
6
6
  CategoryDraft,
7
7
  CategorySetAssetDescriptionAction,
8
8
  CategorySetAssetSourcesAction,
9
+ CategorySetCustomFieldAction,
10
+ CategorySetCustomTypeAction,
9
11
  CategorySetDescriptionAction,
10
12
  CategorySetKeyAction,
11
13
  CategorySetMetaDescriptionAction,
@@ -51,6 +53,11 @@ export class CategoryRepository extends AbstractResourceRepository {
51
53
  ),
52
54
  }
53
55
  }) || [],
56
+ custom: createCustomFields(
57
+ draft.custom,
58
+ context.projectKey,
59
+ this._storage
60
+ ),
54
61
  }
55
62
  this.save(context, resource)
56
63
  return resource
@@ -141,5 +148,34 @@ export class CategoryRepository extends AbstractResourceRepository {
141
148
  ) => {
142
149
  resource.metaTitle = metaTitle
143
150
  },
151
+ setCustomType: (
152
+ context: RepositoryContext,
153
+ resource: Writable<Category>,
154
+ { type, fields }: CategorySetCustomTypeAction
155
+ ) => {
156
+ if (type) {
157
+ resource.custom = createCustomFields(
158
+ { type, fields },
159
+ context.projectKey,
160
+ this._storage
161
+ )
162
+ } else {
163
+ resource.custom = undefined
164
+ }
165
+ },
166
+ setCustomField: (
167
+ context: RepositoryContext,
168
+ resource: Writable<Category>,
169
+ { name, value }: CategorySetCustomFieldAction
170
+ ) => {
171
+ if (!resource.custom) {
172
+ return
173
+ }
174
+ if (value === null) {
175
+ delete resource.custom.fields[name]
176
+ } else {
177
+ resource.custom.fields[name] = value
178
+ }
179
+ },
144
180
  }
145
181
  }
@@ -1,10 +1,20 @@
1
1
  import {
2
2
  Channel,
3
+ ChannelChangeDescriptionAction,
4
+ ChannelChangeKeyAction,
5
+ ChannelChangeNameAction,
3
6
  ChannelDraft,
7
+ ChannelSetAddressAction,
8
+ ChannelSetCustomFieldAction,
9
+ ChannelSetCustomTypeAction,
10
+ ChannelSetGeoLocationAction,
11
+ ChannelUpdateAction,
4
12
  ReferenceTypeId,
5
13
  } from '@commercetools/platform-sdk'
14
+ import { Writable } from 'types'
6
15
  import { getBaseResourceProperties } from '../helpers'
7
16
  import { AbstractResourceRepository, RepositoryContext } from './abstract'
17
+ import { createAddress, createCustomFields } from './helpers'
8
18
 
9
19
  export class ChannelRepository extends AbstractResourceRepository {
10
20
  getTypeId(): ReferenceTypeId {
@@ -15,9 +25,103 @@ export class ChannelRepository extends AbstractResourceRepository {
15
25
  const resource: Channel = {
16
26
  ...getBaseResourceProperties(),
17
27
  key: draft.key,
28
+ name: draft.name,
29
+ description: draft.description,
18
30
  roles: draft.roles || [],
31
+ geoLocation: draft.geoLocation,
32
+ address: createAddress(draft.address, context.projectKey, this._storage),
33
+ custom: createCustomFields(
34
+ draft.custom,
35
+ context.projectKey,
36
+ this._storage
37
+ ),
19
38
  }
20
39
  this.save(context, resource)
21
40
  return resource
22
41
  }
42
+
43
+ actions: Partial<
44
+ Record<
45
+ ChannelUpdateAction['action'],
46
+ (
47
+ context: RepositoryContext,
48
+ resource: Writable<Channel>,
49
+ action: any
50
+ ) => void
51
+ >
52
+ > = {
53
+ changeKey: (
54
+ context: RepositoryContext,
55
+ resource: Writable<Channel>,
56
+ { key }: ChannelChangeKeyAction
57
+ ) => {
58
+ resource.key = key
59
+ },
60
+
61
+ changeName: (
62
+ context: RepositoryContext,
63
+ resource: Writable<Channel>,
64
+ { name }: ChannelChangeNameAction
65
+ ) => {
66
+ resource.name = name
67
+ },
68
+
69
+ changeDescription: (
70
+ context: RepositoryContext,
71
+ resource: Writable<Channel>,
72
+ { description }: ChannelChangeDescriptionAction
73
+ ) => {
74
+ resource.description = description
75
+ },
76
+
77
+ setAddress: (
78
+ context: RepositoryContext,
79
+ resource: Writable<Channel>,
80
+ { address }: ChannelSetAddressAction
81
+ ) => {
82
+ resource.address = createAddress(
83
+ address,
84
+ context.projectKey,
85
+ this._storage
86
+ )
87
+ },
88
+
89
+ setGeoLocation: (
90
+ context: RepositoryContext,
91
+ resource: Writable<Channel>,
92
+ { geoLocation }: ChannelSetGeoLocationAction
93
+ ) => {
94
+ resource.geoLocation = geoLocation
95
+ },
96
+
97
+ setCustomType: (
98
+ context: RepositoryContext,
99
+ resource: Writable<Channel>,
100
+ { type, fields }: ChannelSetCustomTypeAction
101
+ ) => {
102
+ if (type) {
103
+ resource.custom = createCustomFields(
104
+ { type, fields },
105
+ context.projectKey,
106
+ this._storage
107
+ )
108
+ } else {
109
+ resource.custom = undefined
110
+ }
111
+ },
112
+ setCustomField: (
113
+ context: RepositoryContext,
114
+ resource: Writable<Channel>,
115
+ { name, value }: ChannelSetCustomFieldAction
116
+ ) => {
117
+ if (!resource.custom) {
118
+ return
119
+ }
120
+ if (value === null) {
121
+ delete resource.custom.fields[name]
122
+ } else {
123
+ resource.custom.fields[name] = value
124
+ }
125
+ },
126
+ }
23
127
  }
@@ -2,12 +2,15 @@ import {
2
2
  CustomerGroup,
3
3
  CustomerGroupChangeNameAction,
4
4
  CustomerGroupDraft,
5
+ CustomerGroupSetCustomFieldAction,
6
+ CustomerGroupSetCustomTypeAction,
5
7
  CustomerGroupSetKeyAction,
6
8
  ReferenceTypeId,
7
9
  } from '@commercetools/platform-sdk'
8
10
  import { Writable } from 'types'
9
11
  import { getBaseResourceProperties } from '../helpers'
10
12
  import { AbstractResourceRepository, RepositoryContext } from './abstract'
13
+ import { createCustomFields } from './helpers'
11
14
 
12
15
  export class CustomerGroupRepository extends AbstractResourceRepository {
13
16
  getTypeId(): ReferenceTypeId {
@@ -18,6 +21,11 @@ export class CustomerGroupRepository extends AbstractResourceRepository {
18
21
  ...getBaseResourceProperties(),
19
22
  key: draft.key,
20
23
  name: draft.groupName,
24
+ custom: createCustomFields(
25
+ draft.custom,
26
+ context.projectKey,
27
+ this._storage
28
+ ),
21
29
  }
22
30
  this.save(context, resource)
23
31
  return resource
@@ -38,5 +46,34 @@ export class CustomerGroupRepository extends AbstractResourceRepository {
38
46
  ) => {
39
47
  resource.name = name
40
48
  },
49
+ setCustomType: (
50
+ context: RepositoryContext,
51
+ resource: Writable<CustomerGroup>,
52
+ { type, fields }: CustomerGroupSetCustomTypeAction
53
+ ) => {
54
+ if (type) {
55
+ resource.custom = createCustomFields(
56
+ { type, fields },
57
+ context.projectKey,
58
+ this._storage
59
+ )
60
+ } else {
61
+ resource.custom = undefined
62
+ }
63
+ },
64
+ setCustomField: (
65
+ context: RepositoryContext,
66
+ resource: Writable<CustomerGroup>,
67
+ { name, value }: CustomerGroupSetCustomFieldAction
68
+ ) => {
69
+ if (!resource.custom) {
70
+ return
71
+ }
72
+ if (value === null) {
73
+ delete resource.custom.fields[name]
74
+ } else {
75
+ resource.custom.fields[name] = value
76
+ }
77
+ },
41
78
  }
42
79
  }
@@ -5,6 +5,8 @@ import {
5
5
  DiscountCodeChangeIsActiveAction,
6
6
  DiscountCodeDraft,
7
7
  DiscountCodeSetCartPredicateAction,
8
+ DiscountCodeSetCustomFieldAction,
9
+ DiscountCodeSetCustomTypeAction,
8
10
  DiscountCodeSetDescriptionAction,
9
11
  DiscountCodeSetMaxApplicationsAction,
10
12
  DiscountCodeSetMaxApplicationsPerCustomerAction,
@@ -18,6 +20,7 @@ import {
18
20
  import { Writable } from 'types'
19
21
  import { getBaseResourceProperties } from '../helpers'
20
22
  import { AbstractResourceRepository, RepositoryContext } from './abstract'
23
+ import { createCustomFields } from './helpers'
21
24
 
22
25
  export class DiscountCodeRepository extends AbstractResourceRepository {
23
26
  getTypeId(): ReferenceTypeId {
@@ -45,6 +48,11 @@ export class DiscountCodeRepository extends AbstractResourceRepository {
45
48
  validUntil: draft.validUntil,
46
49
  maxApplications: draft.maxApplications,
47
50
  maxApplicationsPerCustomer: draft.maxApplicationsPerCustomer,
51
+ custom: createCustomFields(
52
+ draft.custom,
53
+ context.projectKey,
54
+ this._storage
55
+ ),
48
56
  }
49
57
  this.save(context, resource)
50
58
  return resource
@@ -138,5 +146,34 @@ export class DiscountCodeRepository extends AbstractResourceRepository {
138
146
  resource.validFrom = validFrom
139
147
  resource.validUntil = validUntil
140
148
  },
149
+ setCustomType: (
150
+ context: RepositoryContext,
151
+ resource: Writable<DiscountCode>,
152
+ { type, fields }: DiscountCodeSetCustomTypeAction
153
+ ) => {
154
+ if (type) {
155
+ resource.custom = createCustomFields(
156
+ { type, fields },
157
+ context.projectKey,
158
+ this._storage
159
+ )
160
+ } else {
161
+ resource.custom = undefined
162
+ }
163
+ },
164
+ setCustomField: (
165
+ context: RepositoryContext,
166
+ resource: Writable<DiscountCode>,
167
+ { name, value }: DiscountCodeSetCustomFieldAction
168
+ ) => {
169
+ if (!resource.custom) {
170
+ return
171
+ }
172
+ if (value === null) {
173
+ delete resource.custom.fields[name]
174
+ } else {
175
+ resource.custom.fields[name] = value
176
+ }
177
+ },
141
178
  }
142
179
  }