@labdigital/commercetools-mock 2.17.0 → 2.18.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.
- package/dist/index.cjs +4219 -3989
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +268 -415
- package/dist/index.d.ts +268 -415
- package/dist/index.js +4219 -3989
- package/dist/index.js.map +1 -1
- package/package.json +44 -46
- package/src/constants.ts +2 -2
- package/src/ctMock.test.ts +11 -11
- package/src/ctMock.ts +141 -127
- package/src/deprecation.ts +8 -0
- package/src/exceptions.ts +17 -15
- package/src/helpers.ts +32 -32
- package/src/index.test.ts +128 -128
- package/src/index.ts +3 -3
- package/src/lib/expandParser.ts +13 -13
- package/src/lib/haversine.test.ts +9 -9
- package/src/lib/haversine.ts +11 -11
- package/src/lib/masking.ts +11 -11
- package/src/lib/parser.ts +2 -2
- package/src/lib/password.ts +23 -3
- package/src/lib/predicateParser.test.ts +185 -183
- package/src/lib/predicateParser.ts +234 -234
- package/src/lib/projectionSearchFilter.test.ts +103 -101
- package/src/lib/projectionSearchFilter.ts +152 -150
- package/src/lib/proxy.ts +5 -5
- package/src/oauth/errors.ts +4 -4
- package/src/oauth/helpers.ts +6 -6
- package/src/oauth/server.test.ts +110 -67
- package/src/oauth/server.ts +161 -141
- package/src/oauth/store.ts +49 -44
- package/src/priceSelector.test.ts +35 -35
- package/src/priceSelector.ts +30 -30
- package/src/product-projection-search.ts +136 -134
- package/src/projectAPI.test.ts +7 -7
- package/src/projectAPI.ts +24 -22
- package/src/repositories/abstract.ts +168 -116
- package/src/repositories/associate-role.ts +90 -77
- package/src/repositories/attribute-group.ts +51 -40
- package/src/repositories/business-unit.ts +168 -148
- package/src/repositories/cart/actions.ts +489 -0
- package/src/repositories/cart/helpers.ts +30 -0
- package/src/repositories/cart/index.ts +180 -0
- package/src/repositories/cart-discount/actions.ts +148 -0
- package/src/repositories/cart-discount/index.ts +86 -0
- package/src/repositories/category/actions.ts +231 -0
- package/src/repositories/category/index.ts +52 -0
- package/src/repositories/channel.ts +88 -90
- package/src/repositories/custom-object.ts +46 -45
- package/src/repositories/customer/actions.ts +165 -0
- package/src/repositories/customer/index.ts +79 -0
- package/src/repositories/customer-group.ts +66 -55
- package/src/repositories/discount-code/actions.ts +149 -0
- package/src/repositories/discount-code/index.ts +50 -0
- package/src/repositories/errors.ts +10 -10
- package/src/repositories/extension.ts +64 -62
- package/src/repositories/helpers.ts +117 -118
- package/src/repositories/index.ts +80 -79
- package/src/repositories/inventory-entry/actions.ts +84 -0
- package/src/repositories/inventory-entry/index.ts +44 -0
- package/src/repositories/my-customer.ts +114 -0
- package/src/repositories/my-order.ts +8 -8
- package/src/repositories/order/actions.ts +281 -0
- package/src/repositories/{order.test.ts → order/index.test.ts} +77 -77
- package/src/repositories/order/index.ts +260 -0
- package/src/repositories/order-edit.ts +10 -23
- package/src/repositories/payment/actions.ts +305 -0
- package/src/repositories/payment/helpers.ts +17 -0
- package/src/repositories/payment/index.ts +56 -0
- package/src/repositories/product/actions.ts +943 -0
- package/src/repositories/product/helpers.ts +98 -0
- package/src/repositories/product/index.ts +130 -0
- package/src/repositories/product-discount.ts +127 -117
- package/src/repositories/product-projection.ts +56 -62
- package/src/repositories/product-selection.ts +31 -28
- package/src/repositories/product-type.ts +136 -134
- package/src/repositories/project.ts +133 -118
- package/src/repositories/quote-request.ts +7 -19
- package/src/repositories/quote.ts +7 -22
- package/src/repositories/review.ts +13 -26
- package/src/repositories/shipping-method/actions.ts +198 -0
- package/src/repositories/shipping-method/helpers.ts +10 -0
- package/src/repositories/shipping-method/index.ts +138 -0
- package/src/repositories/shopping-list/actions.ts +295 -0
- package/src/repositories/shopping-list/index.ts +122 -0
- package/src/repositories/staged-quote.ts +7 -20
- package/src/repositories/standalone-price.ts +57 -44
- package/src/repositories/state.ts +113 -68
- package/src/repositories/store.ts +106 -94
- package/src/repositories/subscription.ts +46 -22
- package/src/repositories/tax-category/actions.ts +94 -0
- package/src/repositories/tax-category/helpers.ts +8 -0
- package/src/repositories/tax-category/index.ts +25 -0
- package/src/repositories/type/actions.ts +162 -0
- package/src/repositories/type/index.ts +24 -0
- package/src/repositories/zone.ts +62 -58
- package/src/server.ts +9 -9
- package/src/services/abstract.ts +75 -72
- package/src/services/associate-roles.test.ts +27 -27
- package/src/services/associate-roles.ts +7 -7
- package/src/services/attribute-group.ts +7 -7
- package/src/services/business-units.test.ts +28 -28
- package/src/services/business-units.ts +7 -7
- package/src/services/cart-discount.test.ts +199 -199
- package/src/services/cart-discount.ts +7 -7
- package/src/services/cart.test.ts +261 -261
- package/src/services/cart.ts +22 -21
- package/src/services/category.test.ts +121 -121
- package/src/services/category.ts +7 -7
- package/src/services/channel.ts +7 -7
- package/src/services/custom-object.test.ts +130 -130
- package/src/services/custom-object.ts +34 -31
- package/src/services/customer-group.ts +7 -7
- package/src/services/customer.test.ts +205 -205
- package/src/services/customer.ts +31 -29
- package/src/services/discount-code.ts +7 -7
- package/src/services/extension.ts +7 -7
- package/src/services/index.ts +85 -81
- package/src/services/inventory-entry.test.ts +106 -106
- package/src/services/inventory-entry.ts +7 -7
- package/src/services/my-cart.test.ts +56 -56
- package/src/services/my-cart.ts +20 -20
- package/src/services/my-customer.test.ts +155 -104
- package/src/services/my-customer.ts +61 -75
- package/src/services/my-order.ts +16 -16
- package/src/services/my-payment.test.ts +40 -40
- package/src/services/my-payment.ts +7 -7
- package/src/services/my-shopping-list.ts +7 -7
- package/src/services/order.test.ts +243 -243
- package/src/services/order.ts +23 -18
- package/src/services/payment.test.ts +40 -40
- package/src/services/payment.ts +7 -7
- package/src/services/product-discount.ts +7 -7
- package/src/services/product-projection.test.ts +190 -190
- package/src/services/product-projection.ts +34 -32
- package/src/services/product-selection.test.ts +19 -19
- package/src/services/product-selection.ts +7 -7
- package/src/services/product-type.test.ts +38 -38
- package/src/services/product-type.ts +7 -7
- package/src/services/product.test.ts +658 -656
- package/src/services/product.ts +7 -7
- package/src/services/project.test.ts +24 -24
- package/src/services/project.ts +17 -17
- package/src/services/reviews.ts +7 -7
- package/src/services/shipping-method.test.ts +78 -78
- package/src/services/shipping-method.ts +16 -16
- package/src/services/shopping-list.test.ts +170 -170
- package/src/services/shopping-list.ts +7 -7
- package/src/services/standalone-price.test.ts +112 -112
- package/src/services/standalone-price.ts +7 -7
- package/src/services/state.test.ts +30 -30
- package/src/services/state.ts +7 -7
- package/src/services/store.test.ts +40 -40
- package/src/services/store.ts +7 -7
- package/src/services/subscription.ts +7 -7
- package/src/services/tax-category.test.ts +43 -43
- package/src/services/tax-category.ts +7 -7
- package/src/services/type.ts +7 -7
- package/src/services/zone.ts +7 -7
- package/src/shippingCalculator.test.ts +43 -43
- package/src/shippingCalculator.ts +23 -23
- package/src/storage/abstract.ts +36 -34
- package/src/storage/in-memory.ts +237 -233
- package/src/storage/index.ts +2 -2
- package/src/types.ts +91 -91
- package/src/repositories/cart-discount.ts +0 -219
- package/src/repositories/cart.ts +0 -659
- package/src/repositories/category.ts +0 -256
- package/src/repositories/customer.ts +0 -228
- package/src/repositories/discount-code.ts +0 -181
- package/src/repositories/inventory-entry.ts +0 -109
- package/src/repositories/order.ts +0 -514
- package/src/repositories/payment.ts +0 -342
- package/src/repositories/product.ts +0 -1106
- package/src/repositories/shipping-method.ts +0 -312
- package/src/repositories/shopping-list.ts +0 -392
- package/src/repositories/tax-category.ts +0 -111
- package/src/repositories/type.ts +0 -172
|
@@ -1,1106 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
Price,
|
|
3
|
-
PriceDraft,
|
|
4
|
-
Product,
|
|
5
|
-
ProductData,
|
|
6
|
-
ProductDraft,
|
|
7
|
-
ProductPublishAction,
|
|
8
|
-
ProductSetAttributeAction,
|
|
9
|
-
ProductSetAttributeInAllVariantsAction,
|
|
10
|
-
ProductSetDescriptionAction,
|
|
11
|
-
ProductAddExternalImageAction,
|
|
12
|
-
ProductRemoveImageAction,
|
|
13
|
-
ProductSetKeyAction,
|
|
14
|
-
ProductTypeReference,
|
|
15
|
-
ProductUpdateAction,
|
|
16
|
-
ProductVariant,
|
|
17
|
-
ProductVariantDraft,
|
|
18
|
-
ProductMoveImageToPositionAction,
|
|
19
|
-
ProductChangePriceAction,
|
|
20
|
-
ProductAddPriceAction,
|
|
21
|
-
ProductRemovePriceAction,
|
|
22
|
-
CategoryReference,
|
|
23
|
-
InvalidJsonInputError,
|
|
24
|
-
InvalidOperationError,
|
|
25
|
-
TaxCategoryReference,
|
|
26
|
-
StateReference,
|
|
27
|
-
ProductChangeNameAction,
|
|
28
|
-
ProductChangeSlugAction,
|
|
29
|
-
ProductSetMetaTitleAction,
|
|
30
|
-
ProductSetMetaDescriptionAction,
|
|
31
|
-
ProductSetMetaKeywordsAction,
|
|
32
|
-
ProductAddVariantAction,
|
|
33
|
-
ProductRemoveVariantAction,
|
|
34
|
-
ProductChangeMasterVariantAction,
|
|
35
|
-
ProductSetTaxCategoryAction,
|
|
36
|
-
ProductAddToCategoryAction,
|
|
37
|
-
ProductRemoveFromCategoryAction,
|
|
38
|
-
ProductTransitionStateAction,
|
|
39
|
-
ChannelReference,
|
|
40
|
-
} from '@commercetools/platform-sdk'
|
|
41
|
-
import { v4 as uuidv4 } from 'uuid'
|
|
42
|
-
import type { Writable } from '../types.js'
|
|
43
|
-
import { getBaseResourceProperties } from '../helpers.js'
|
|
44
|
-
import { AbstractResourceRepository, RepositoryContext } from './abstract.js'
|
|
45
|
-
import {
|
|
46
|
-
createTypedMoney,
|
|
47
|
-
getReferenceFromResourceIdentifier,
|
|
48
|
-
} from './helpers.js'
|
|
49
|
-
import deepEqual from 'deep-equal'
|
|
50
|
-
import { CommercetoolsError } from '../exceptions.js'
|
|
51
|
-
|
|
52
|
-
export class ProductRepository extends AbstractResourceRepository<'product'> {
|
|
53
|
-
getTypeId() {
|
|
54
|
-
return 'product' as const
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
create(context: RepositoryContext, draft: ProductDraft): Product {
|
|
58
|
-
if (!draft.masterVariant) {
|
|
59
|
-
throw new Error('Missing master variant')
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
let productType: ProductTypeReference | undefined = undefined
|
|
63
|
-
try {
|
|
64
|
-
productType = getReferenceFromResourceIdentifier<ProductTypeReference>(
|
|
65
|
-
draft.productType,
|
|
66
|
-
context.projectKey,
|
|
67
|
-
this._storage
|
|
68
|
-
)
|
|
69
|
-
} catch (err) {
|
|
70
|
-
// For now accept missing product types (but warn)
|
|
71
|
-
console.warn(
|
|
72
|
-
`Error resolving product-type '${draft.productType.id}'. This will be throw an error in later releases.`
|
|
73
|
-
)
|
|
74
|
-
productType = {
|
|
75
|
-
typeId: 'product-type',
|
|
76
|
-
id: draft.productType.id || '',
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Resolve Product categories
|
|
81
|
-
const categoryReferences: CategoryReference[] = []
|
|
82
|
-
draft.categories?.forEach((category) => {
|
|
83
|
-
if (category) {
|
|
84
|
-
categoryReferences.push(
|
|
85
|
-
getReferenceFromResourceIdentifier<CategoryReference>(
|
|
86
|
-
category,
|
|
87
|
-
context.projectKey,
|
|
88
|
-
this._storage
|
|
89
|
-
)
|
|
90
|
-
)
|
|
91
|
-
} else {
|
|
92
|
-
throw new CommercetoolsError<InvalidJsonInputError>(
|
|
93
|
-
{
|
|
94
|
-
code: 'InvalidJsonInput',
|
|
95
|
-
message: 'Request body does not contain valid JSON.',
|
|
96
|
-
detailedErrorMessage: 'categories: JSON object expected.',
|
|
97
|
-
},
|
|
98
|
-
400
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
// Resolve Tax category
|
|
104
|
-
let taxCategoryReference: TaxCategoryReference | undefined = undefined
|
|
105
|
-
if (draft.taxCategory) {
|
|
106
|
-
taxCategoryReference =
|
|
107
|
-
getReferenceFromResourceIdentifier<TaxCategoryReference>(
|
|
108
|
-
draft.taxCategory,
|
|
109
|
-
context.projectKey,
|
|
110
|
-
this._storage
|
|
111
|
-
)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Resolve Product State
|
|
115
|
-
let productStateReference: StateReference | undefined = undefined
|
|
116
|
-
if (draft.state) {
|
|
117
|
-
productStateReference =
|
|
118
|
-
getReferenceFromResourceIdentifier<StateReference>(
|
|
119
|
-
draft.state,
|
|
120
|
-
context.projectKey,
|
|
121
|
-
this._storage
|
|
122
|
-
)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const productData: ProductData = {
|
|
126
|
-
name: draft.name,
|
|
127
|
-
slug: draft.slug,
|
|
128
|
-
description: draft.description,
|
|
129
|
-
categories: categoryReferences,
|
|
130
|
-
masterVariant: this.variantFromDraft(context, 1, draft.masterVariant),
|
|
131
|
-
variants:
|
|
132
|
-
draft.variants?.map((variant, index) =>
|
|
133
|
-
this.variantFromDraft(context, index + 2, variant)
|
|
134
|
-
) ?? [],
|
|
135
|
-
metaTitle: draft.metaTitle,
|
|
136
|
-
metaDescription: draft.metaDescription,
|
|
137
|
-
metaKeywords: draft.metaKeywords,
|
|
138
|
-
searchKeywords: draft.searchKeywords ?? {},
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const resource: Product = {
|
|
142
|
-
...getBaseResourceProperties(),
|
|
143
|
-
key: draft.key,
|
|
144
|
-
productType: productType,
|
|
145
|
-
taxCategory: taxCategoryReference,
|
|
146
|
-
state: productStateReference,
|
|
147
|
-
masterData: {
|
|
148
|
-
current: productData,
|
|
149
|
-
staged: productData,
|
|
150
|
-
hasStagedChanges: false,
|
|
151
|
-
published: draft.publish ?? false,
|
|
152
|
-
},
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
this.saveNew(context, resource)
|
|
156
|
-
|
|
157
|
-
return resource
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
private variantFromDraft(
|
|
161
|
-
context: RepositoryContext,
|
|
162
|
-
variantId: number,
|
|
163
|
-
variant: ProductVariantDraft
|
|
164
|
-
): ProductVariant {
|
|
165
|
-
return {
|
|
166
|
-
id: variantId,
|
|
167
|
-
sku: variant?.sku,
|
|
168
|
-
key: variant?.key,
|
|
169
|
-
attributes: variant?.attributes ?? [],
|
|
170
|
-
prices: variant?.prices?.map((p) => this.priceFromDraft(context, p)),
|
|
171
|
-
assets: [],
|
|
172
|
-
images: [],
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
private priceFromDraft(context: RepositoryContext, draft: PriceDraft): Price {
|
|
177
|
-
return {
|
|
178
|
-
id: uuidv4(),
|
|
179
|
-
key: draft.key,
|
|
180
|
-
country: draft.country,
|
|
181
|
-
value: createTypedMoney(draft.value),
|
|
182
|
-
channel: draft.channel
|
|
183
|
-
? getReferenceFromResourceIdentifier<ChannelReference>(
|
|
184
|
-
draft.channel,
|
|
185
|
-
context.projectKey,
|
|
186
|
-
this._storage
|
|
187
|
-
)
|
|
188
|
-
: undefined,
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
actions: Partial<
|
|
193
|
-
Record<
|
|
194
|
-
ProductUpdateAction['action'],
|
|
195
|
-
(
|
|
196
|
-
context: RepositoryContext,
|
|
197
|
-
resource: Writable<Product>,
|
|
198
|
-
action: any
|
|
199
|
-
) => void
|
|
200
|
-
>
|
|
201
|
-
> = {
|
|
202
|
-
publish: (
|
|
203
|
-
context: RepositoryContext,
|
|
204
|
-
resource: Writable<Product>,
|
|
205
|
-
{ scope }: ProductPublishAction
|
|
206
|
-
) => {
|
|
207
|
-
resource.masterData.current = resource.masterData.staged
|
|
208
|
-
resource.masterData.published = true
|
|
209
|
-
checkForStagedChanges(resource)
|
|
210
|
-
},
|
|
211
|
-
unpublish: (
|
|
212
|
-
context: RepositoryContext,
|
|
213
|
-
resource: Writable<Product>
|
|
214
|
-
// { action }: ProductUnpublishAction
|
|
215
|
-
) => {
|
|
216
|
-
resource.masterData.published = false
|
|
217
|
-
checkForStagedChanges(resource)
|
|
218
|
-
},
|
|
219
|
-
setAttribute: (
|
|
220
|
-
context: RepositoryContext,
|
|
221
|
-
resource: Writable<Product>,
|
|
222
|
-
{ variantId, sku, name, value, staged }: ProductSetAttributeAction
|
|
223
|
-
) => {
|
|
224
|
-
const setAttr = (data: Writable<ProductData>) => {
|
|
225
|
-
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
226
|
-
data,
|
|
227
|
-
variantId,
|
|
228
|
-
sku
|
|
229
|
-
)
|
|
230
|
-
if (!variant) {
|
|
231
|
-
throw new Error(
|
|
232
|
-
`Variant with id ${variantId} or sku ${sku} not found on product ${resource.id}`
|
|
233
|
-
)
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if (!variant.attributes) {
|
|
237
|
-
variant.attributes = []
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
const existingAttr = variant.attributes.find(
|
|
241
|
-
(attr) => attr.name === name
|
|
242
|
-
)
|
|
243
|
-
if (existingAttr) {
|
|
244
|
-
existingAttr.value = value
|
|
245
|
-
} else {
|
|
246
|
-
variant.attributes.push({
|
|
247
|
-
name,
|
|
248
|
-
value,
|
|
249
|
-
})
|
|
250
|
-
}
|
|
251
|
-
if (isMasterVariant) {
|
|
252
|
-
data.masterVariant = variant
|
|
253
|
-
} else {
|
|
254
|
-
data.variants[variantIndex] = variant
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// If true, only the staged Attribute is set. If false, both current and
|
|
259
|
-
// staged Attribute is set. Default is true
|
|
260
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
261
|
-
|
|
262
|
-
// Write the attribute to the staged data
|
|
263
|
-
setAttr(resource.masterData.staged)
|
|
264
|
-
|
|
265
|
-
// Also write to published data is isStaged = false
|
|
266
|
-
// if isStaged is false we set the attribute on both the staged and
|
|
267
|
-
// published data.
|
|
268
|
-
if (!onlyStaged) {
|
|
269
|
-
setAttr(resource.masterData.current)
|
|
270
|
-
}
|
|
271
|
-
checkForStagedChanges(resource)
|
|
272
|
-
|
|
273
|
-
return resource
|
|
274
|
-
},
|
|
275
|
-
setAttributeInAllVariants: (
|
|
276
|
-
context: RepositoryContext,
|
|
277
|
-
resource: Writable<Product>,
|
|
278
|
-
{ name, value, staged }: ProductSetAttributeInAllVariantsAction
|
|
279
|
-
) => {
|
|
280
|
-
const setAttrInAllVariants = (data: Writable<ProductData>) => {
|
|
281
|
-
if (!data.masterVariant.attributes) {
|
|
282
|
-
data.masterVariant.attributes = []
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const existingAttr = data.masterVariant.attributes?.find(
|
|
286
|
-
(attr) => attr.name === name
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
if (existingAttr) {
|
|
290
|
-
existingAttr.value = value
|
|
291
|
-
} else {
|
|
292
|
-
data.masterVariant.attributes.push({
|
|
293
|
-
name,
|
|
294
|
-
value,
|
|
295
|
-
})
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
data.variants.forEach((variant) => {
|
|
299
|
-
if (!variant.attributes) {
|
|
300
|
-
variant.attributes = []
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
const existingAttr = variant.attributes.find(
|
|
304
|
-
(attr) => attr.name === name
|
|
305
|
-
)
|
|
306
|
-
if (existingAttr) {
|
|
307
|
-
existingAttr.value = value
|
|
308
|
-
} else {
|
|
309
|
-
variant.attributes.push({
|
|
310
|
-
name,
|
|
311
|
-
value,
|
|
312
|
-
})
|
|
313
|
-
}
|
|
314
|
-
})
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// If true, only the staged Attribute is set. If false, both current and
|
|
318
|
-
// staged Attribute is set. Default is true
|
|
319
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
320
|
-
|
|
321
|
-
// Write the attribute to the staged data
|
|
322
|
-
setAttrInAllVariants(resource.masterData.staged)
|
|
323
|
-
|
|
324
|
-
// Also write to published data is isStaged = false
|
|
325
|
-
// if isStaged is false we set the attribute on both the staged and
|
|
326
|
-
// published data.
|
|
327
|
-
if (!onlyStaged) {
|
|
328
|
-
setAttrInAllVariants(resource.masterData.current)
|
|
329
|
-
}
|
|
330
|
-
checkForStagedChanges(resource)
|
|
331
|
-
|
|
332
|
-
return resource
|
|
333
|
-
},
|
|
334
|
-
setDescription: (
|
|
335
|
-
context: RepositoryContext,
|
|
336
|
-
resource: Writable<Product>,
|
|
337
|
-
{ description, staged }: ProductSetDescriptionAction
|
|
338
|
-
) => {
|
|
339
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
340
|
-
|
|
341
|
-
resource.masterData.staged.description = description
|
|
342
|
-
if (!onlyStaged) {
|
|
343
|
-
resource.masterData.current.description = description
|
|
344
|
-
}
|
|
345
|
-
checkForStagedChanges(resource)
|
|
346
|
-
return resource
|
|
347
|
-
},
|
|
348
|
-
setKey: (
|
|
349
|
-
context: RepositoryContext,
|
|
350
|
-
resource: Writable<Product>,
|
|
351
|
-
{ key }: ProductSetKeyAction
|
|
352
|
-
) => {
|
|
353
|
-
resource.key = key
|
|
354
|
-
return resource
|
|
355
|
-
},
|
|
356
|
-
addExternalImage: (
|
|
357
|
-
context: RepositoryContext,
|
|
358
|
-
resource: Writable<Product>,
|
|
359
|
-
{ variantId, sku, image, staged }: ProductAddExternalImageAction
|
|
360
|
-
) => {
|
|
361
|
-
const addImg = (data: Writable<ProductData>) => {
|
|
362
|
-
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
363
|
-
data,
|
|
364
|
-
variantId,
|
|
365
|
-
sku
|
|
366
|
-
)
|
|
367
|
-
if (!variant) {
|
|
368
|
-
throw new Error(
|
|
369
|
-
`Variant with id ${variantId} or sku ${sku} not found on product ${resource.id}`
|
|
370
|
-
)
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
if (!variant.images) {
|
|
374
|
-
variant.images = []
|
|
375
|
-
} else {
|
|
376
|
-
const existingImage = variant.images.find((x) => x.url === image.url)
|
|
377
|
-
if (existingImage) {
|
|
378
|
-
throw new Error(
|
|
379
|
-
`Cannot add image '${image.url}' because product '${resource.id}' already has that image.`
|
|
380
|
-
)
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// Add image
|
|
385
|
-
variant.images.push(image)
|
|
386
|
-
|
|
387
|
-
if (isMasterVariant) {
|
|
388
|
-
data.masterVariant = variant
|
|
389
|
-
} else {
|
|
390
|
-
data.variants[variantIndex] = variant
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// If true, only the staged Attribute is set. If false, both current and
|
|
395
|
-
// staged Attribute is set. Default is true
|
|
396
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
397
|
-
|
|
398
|
-
// Write the attribute to the staged data
|
|
399
|
-
addImg(resource.masterData.staged)
|
|
400
|
-
|
|
401
|
-
// Also write to published data is isStaged = false
|
|
402
|
-
// if isStaged is false we set the attribute on both the staged and
|
|
403
|
-
// published data.
|
|
404
|
-
if (!onlyStaged) {
|
|
405
|
-
addImg(resource.masterData.current)
|
|
406
|
-
}
|
|
407
|
-
checkForStagedChanges(resource)
|
|
408
|
-
|
|
409
|
-
return resource
|
|
410
|
-
},
|
|
411
|
-
removeImage: (
|
|
412
|
-
context: RepositoryContext,
|
|
413
|
-
resource: Writable<Product>,
|
|
414
|
-
{ variantId, sku, imageUrl, staged }: ProductRemoveImageAction
|
|
415
|
-
) => {
|
|
416
|
-
const removeImg = (data: Writable<ProductData>) => {
|
|
417
|
-
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
418
|
-
data,
|
|
419
|
-
variantId,
|
|
420
|
-
sku
|
|
421
|
-
)
|
|
422
|
-
if (!variant) {
|
|
423
|
-
throw new Error(
|
|
424
|
-
`Variant with id ${variantId} or sku ${sku} not found on product ${resource.id}`
|
|
425
|
-
)
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
const variantImages = variant.images ?? []
|
|
429
|
-
const existingImage = variantImages.find((x) => x.url === imageUrl)
|
|
430
|
-
if (!existingImage) {
|
|
431
|
-
throw new Error(
|
|
432
|
-
`Cannot remove image '${imageUrl}' because product '${resource.id}' does not have that image.`
|
|
433
|
-
)
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// Remove image
|
|
437
|
-
variant.images = variantImages.filter((image) => image.url !== imageUrl)
|
|
438
|
-
|
|
439
|
-
if (isMasterVariant) {
|
|
440
|
-
data.masterVariant = variant
|
|
441
|
-
} else {
|
|
442
|
-
data.variants[variantIndex] = variant
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// If true, only the staged Attribute is set. If false, both current and
|
|
447
|
-
// staged Attribute is set. Default is true
|
|
448
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
449
|
-
|
|
450
|
-
// Write the attribute to the staged data
|
|
451
|
-
removeImg(resource.masterData.staged)
|
|
452
|
-
|
|
453
|
-
// Also write to published data is isStaged = false
|
|
454
|
-
// if isStaged is false we set the attribute on both the staged and
|
|
455
|
-
// published data.
|
|
456
|
-
if (!onlyStaged) {
|
|
457
|
-
removeImg(resource.masterData.current)
|
|
458
|
-
}
|
|
459
|
-
checkForStagedChanges(resource)
|
|
460
|
-
|
|
461
|
-
return resource
|
|
462
|
-
},
|
|
463
|
-
moveImageToPosition: (
|
|
464
|
-
context: RepositoryContext,
|
|
465
|
-
resource: Writable<Product>,
|
|
466
|
-
{
|
|
467
|
-
variantId,
|
|
468
|
-
sku,
|
|
469
|
-
imageUrl,
|
|
470
|
-
position,
|
|
471
|
-
staged,
|
|
472
|
-
}: ProductMoveImageToPositionAction
|
|
473
|
-
) => {
|
|
474
|
-
const moveImg = (data: Writable<ProductData>) => {
|
|
475
|
-
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
476
|
-
data,
|
|
477
|
-
variantId,
|
|
478
|
-
sku
|
|
479
|
-
)
|
|
480
|
-
if (!variant) {
|
|
481
|
-
throw new Error(
|
|
482
|
-
`Variant with id ${variantId} or sku ${sku} not found on product ${resource.id}`
|
|
483
|
-
)
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
const variantImages = variant.images ?? []
|
|
487
|
-
const existingImage = variantImages.find((x) => x.url === imageUrl)
|
|
488
|
-
if (!existingImage) {
|
|
489
|
-
throw new Error(
|
|
490
|
-
`Cannot move image '${imageUrl}' because product '${resource.id}' does not have that image.`
|
|
491
|
-
)
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
if (position >= variantImages.length) {
|
|
495
|
-
throw new Error(
|
|
496
|
-
`Invalid position given. Position in images where the image should be moved. Must be between 0 and the total number of images minus 1.`
|
|
497
|
-
)
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
// Remove image
|
|
501
|
-
variant.images = variantImages.filter((image) => image.url !== imageUrl)
|
|
502
|
-
|
|
503
|
-
// Re-add image to the correct position
|
|
504
|
-
variant.images.splice(position, 0, existingImage)
|
|
505
|
-
|
|
506
|
-
if (isMasterVariant) {
|
|
507
|
-
data.masterVariant = variant
|
|
508
|
-
} else {
|
|
509
|
-
data.variants[variantIndex] = variant
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// If true, only the staged Attribute is set. If false, both current and
|
|
514
|
-
// staged Attribute is set. Default is true
|
|
515
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
516
|
-
|
|
517
|
-
// Write the attribute to the staged data
|
|
518
|
-
moveImg(resource.masterData.staged)
|
|
519
|
-
|
|
520
|
-
// Also write to published data is isStaged = false
|
|
521
|
-
// if isStaged is false we set the attribute on both the staged and
|
|
522
|
-
// published data.
|
|
523
|
-
if (!onlyStaged) {
|
|
524
|
-
moveImg(resource.masterData.current)
|
|
525
|
-
}
|
|
526
|
-
checkForStagedChanges(resource)
|
|
527
|
-
|
|
528
|
-
return resource
|
|
529
|
-
},
|
|
530
|
-
addPrice: (
|
|
531
|
-
context: RepositoryContext,
|
|
532
|
-
resource: Writable<Product>,
|
|
533
|
-
{ variantId, sku, price, staged }: ProductAddPriceAction
|
|
534
|
-
) => {
|
|
535
|
-
const addVariantPrice = (
|
|
536
|
-
data: Writable<ProductData>,
|
|
537
|
-
priceToAdd: Price
|
|
538
|
-
) => {
|
|
539
|
-
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
540
|
-
data,
|
|
541
|
-
variantId,
|
|
542
|
-
sku
|
|
543
|
-
)
|
|
544
|
-
if (!variant) {
|
|
545
|
-
throw new Error(
|
|
546
|
-
`Variant with id ${variantId} or sku ${sku} not found on product ${resource.id}`
|
|
547
|
-
)
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
if (variant.prices === undefined) {
|
|
551
|
-
variant.prices = [priceToAdd]
|
|
552
|
-
} else {
|
|
553
|
-
variant.prices.push(priceToAdd)
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
if (isMasterVariant) {
|
|
557
|
-
data.masterVariant = variant
|
|
558
|
-
} else {
|
|
559
|
-
data.variants[variantIndex] = variant
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
// Pre-creating the price object ensures consistency between staged and current versions
|
|
564
|
-
const priceToAdd = this.priceFromDraft(context, price)
|
|
565
|
-
|
|
566
|
-
// If true, only the staged Attribute is set. If false, both current and
|
|
567
|
-
// staged Attribute is set. Default is true
|
|
568
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
569
|
-
|
|
570
|
-
// Write the attribute to the staged data
|
|
571
|
-
addVariantPrice(resource.masterData.staged, priceToAdd)
|
|
572
|
-
|
|
573
|
-
// Also write to published data is isStaged = false
|
|
574
|
-
// if isStaged is false we set the attribute on both the staged and
|
|
575
|
-
// published data.
|
|
576
|
-
if (!onlyStaged) {
|
|
577
|
-
addVariantPrice(resource.masterData.current, priceToAdd)
|
|
578
|
-
}
|
|
579
|
-
checkForStagedChanges(resource)
|
|
580
|
-
|
|
581
|
-
return resource
|
|
582
|
-
},
|
|
583
|
-
changePrice: (
|
|
584
|
-
context: RepositoryContext,
|
|
585
|
-
resource: Writable<Product>,
|
|
586
|
-
{ priceId, price, staged }: ProductChangePriceAction
|
|
587
|
-
) => {
|
|
588
|
-
const changeVariantPrice = (data: Writable<ProductData>) => {
|
|
589
|
-
const allVariants = [data.masterVariant, ...(data.variants ?? [])]
|
|
590
|
-
const priceVariant = allVariants.find((variant) =>
|
|
591
|
-
variant.prices?.some((x) => x.id === priceId)
|
|
592
|
-
)
|
|
593
|
-
if (!priceVariant) {
|
|
594
|
-
throw new Error(
|
|
595
|
-
`Price with id ${priceId} not found on product ${resource.id}`
|
|
596
|
-
)
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
600
|
-
data,
|
|
601
|
-
priceVariant.id,
|
|
602
|
-
priceVariant.sku
|
|
603
|
-
)
|
|
604
|
-
if (!variant) {
|
|
605
|
-
throw new Error(
|
|
606
|
-
`Variant with id ${priceVariant.id} or sku ${priceVariant.sku} not found on product ${resource.id}`
|
|
607
|
-
)
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
variant.prices = variant.prices?.map((x) => {
|
|
611
|
-
if (x.id === priceId) {
|
|
612
|
-
return { ...x, ...price } as Price
|
|
613
|
-
}
|
|
614
|
-
return x
|
|
615
|
-
})
|
|
616
|
-
|
|
617
|
-
if (isMasterVariant) {
|
|
618
|
-
data.masterVariant = variant
|
|
619
|
-
} else {
|
|
620
|
-
data.variants[variantIndex] = variant
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// If true, only the staged Attribute is set. If false, both current and
|
|
625
|
-
// staged Attribute is set. Default is true
|
|
626
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
627
|
-
|
|
628
|
-
// Write the attribute to the staged data
|
|
629
|
-
changeVariantPrice(resource.masterData.staged)
|
|
630
|
-
|
|
631
|
-
// Also write to published data is isStaged = false
|
|
632
|
-
// if isStaged is false we set the attribute on both the staged and
|
|
633
|
-
// published data.
|
|
634
|
-
if (!onlyStaged) {
|
|
635
|
-
changeVariantPrice(resource.masterData.current)
|
|
636
|
-
}
|
|
637
|
-
checkForStagedChanges(resource)
|
|
638
|
-
|
|
639
|
-
return resource
|
|
640
|
-
},
|
|
641
|
-
removePrice: (
|
|
642
|
-
context: RepositoryContext,
|
|
643
|
-
resource: Writable<Product>,
|
|
644
|
-
{ priceId, staged }: ProductRemovePriceAction
|
|
645
|
-
) => {
|
|
646
|
-
const removeVariantPrice = (data: Writable<ProductData>) => {
|
|
647
|
-
const allVariants = [data.masterVariant, ...(data.variants ?? [])]
|
|
648
|
-
const priceVariant = allVariants.find((variant) =>
|
|
649
|
-
variant.prices?.some((x) => x.id === priceId)
|
|
650
|
-
)
|
|
651
|
-
if (!priceVariant) {
|
|
652
|
-
throw new Error(
|
|
653
|
-
`Price with id ${priceId} not found on product ${resource.id}`
|
|
654
|
-
)
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
658
|
-
data,
|
|
659
|
-
priceVariant.id,
|
|
660
|
-
priceVariant.sku
|
|
661
|
-
)
|
|
662
|
-
if (!variant) {
|
|
663
|
-
throw new Error(
|
|
664
|
-
`Variant with id ${priceVariant.id} or sku ${priceVariant.sku} not found on product ${resource.id}`
|
|
665
|
-
)
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
variant.prices = variant.prices?.filter((x) => x.id !== priceId)
|
|
669
|
-
|
|
670
|
-
if (isMasterVariant) {
|
|
671
|
-
data.masterVariant = variant
|
|
672
|
-
} else {
|
|
673
|
-
data.variants[variantIndex] = variant
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
// If true, only the staged Attribute is set. If false, both current and
|
|
678
|
-
// staged Attribute is set. Default is true
|
|
679
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
680
|
-
|
|
681
|
-
// Write the attribute to the staged data
|
|
682
|
-
removeVariantPrice(resource.masterData.staged)
|
|
683
|
-
|
|
684
|
-
// Also write to published data is isStaged = false
|
|
685
|
-
// if isStaged is false we set the attribute on both the staged and
|
|
686
|
-
// published data.
|
|
687
|
-
if (!onlyStaged) {
|
|
688
|
-
removeVariantPrice(resource.masterData.current)
|
|
689
|
-
}
|
|
690
|
-
checkForStagedChanges(resource)
|
|
691
|
-
|
|
692
|
-
return resource
|
|
693
|
-
},
|
|
694
|
-
changeName: (
|
|
695
|
-
context: RepositoryContext,
|
|
696
|
-
resource: Writable<Product>,
|
|
697
|
-
{ name, staged }: ProductChangeNameAction
|
|
698
|
-
) => {
|
|
699
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
700
|
-
resource.masterData.staged.name = name
|
|
701
|
-
if (!onlyStaged) {
|
|
702
|
-
resource.masterData.current.name = name
|
|
703
|
-
}
|
|
704
|
-
checkForStagedChanges(resource)
|
|
705
|
-
return resource
|
|
706
|
-
},
|
|
707
|
-
changeSlug: (
|
|
708
|
-
context: RepositoryContext,
|
|
709
|
-
resource: Writable<Product>,
|
|
710
|
-
{ slug, staged }: ProductChangeSlugAction
|
|
711
|
-
) => {
|
|
712
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
713
|
-
resource.masterData.staged.slug = slug
|
|
714
|
-
if (!onlyStaged) {
|
|
715
|
-
resource.masterData.current.slug = slug
|
|
716
|
-
}
|
|
717
|
-
checkForStagedChanges(resource)
|
|
718
|
-
return resource
|
|
719
|
-
},
|
|
720
|
-
setMetaTitle: (
|
|
721
|
-
context: RepositoryContext,
|
|
722
|
-
resource: Writable<Product>,
|
|
723
|
-
{ metaTitle, staged }: ProductSetMetaTitleAction
|
|
724
|
-
) => {
|
|
725
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
726
|
-
resource.masterData.staged.metaTitle = metaTitle
|
|
727
|
-
if (!onlyStaged) {
|
|
728
|
-
resource.masterData.current.metaTitle = metaTitle
|
|
729
|
-
}
|
|
730
|
-
checkForStagedChanges(resource)
|
|
731
|
-
return resource
|
|
732
|
-
},
|
|
733
|
-
setMetaDescription: (
|
|
734
|
-
context: RepositoryContext,
|
|
735
|
-
resource: Writable<Product>,
|
|
736
|
-
{ metaDescription, staged }: ProductSetMetaDescriptionAction
|
|
737
|
-
) => {
|
|
738
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
739
|
-
resource.masterData.staged.metaDescription = metaDescription
|
|
740
|
-
if (!onlyStaged) {
|
|
741
|
-
resource.masterData.current.metaDescription = metaDescription
|
|
742
|
-
}
|
|
743
|
-
checkForStagedChanges(resource)
|
|
744
|
-
return resource
|
|
745
|
-
},
|
|
746
|
-
setMetaKeywords: (
|
|
747
|
-
context: RepositoryContext,
|
|
748
|
-
resource: Writable<Product>,
|
|
749
|
-
{ metaKeywords, staged }: ProductSetMetaKeywordsAction
|
|
750
|
-
) => {
|
|
751
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
752
|
-
resource.masterData.staged.metaKeywords = metaKeywords
|
|
753
|
-
if (!onlyStaged) {
|
|
754
|
-
resource.masterData.current.metaKeywords = metaKeywords
|
|
755
|
-
}
|
|
756
|
-
checkForStagedChanges(resource)
|
|
757
|
-
return resource
|
|
758
|
-
},
|
|
759
|
-
addVariant: (
|
|
760
|
-
context: RepositoryContext,
|
|
761
|
-
resource: Writable<Product>,
|
|
762
|
-
{
|
|
763
|
-
sku,
|
|
764
|
-
key,
|
|
765
|
-
prices,
|
|
766
|
-
images,
|
|
767
|
-
attributes,
|
|
768
|
-
staged,
|
|
769
|
-
assets,
|
|
770
|
-
}: ProductAddVariantAction
|
|
771
|
-
) => {
|
|
772
|
-
const variantDraft: ProductVariantDraft = {
|
|
773
|
-
sku: sku,
|
|
774
|
-
key: key,
|
|
775
|
-
prices: prices,
|
|
776
|
-
images: images,
|
|
777
|
-
attributes: attributes,
|
|
778
|
-
assets: assets,
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
const dataStaged = resource.masterData.staged
|
|
782
|
-
const allVariants = [
|
|
783
|
-
dataStaged.masterVariant,
|
|
784
|
-
...(dataStaged.variants ?? []),
|
|
785
|
-
]
|
|
786
|
-
const maxId = allVariants.reduce(
|
|
787
|
-
(max, element) => (element.id > max ? element.id : max),
|
|
788
|
-
0
|
|
789
|
-
)
|
|
790
|
-
const variant = this.variantFromDraft(context, maxId + 1, variantDraft)
|
|
791
|
-
dataStaged.variants.push(variant)
|
|
792
|
-
|
|
793
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
794
|
-
|
|
795
|
-
if (!onlyStaged) {
|
|
796
|
-
resource.masterData.current.variants.push(variant)
|
|
797
|
-
}
|
|
798
|
-
checkForStagedChanges(resource)
|
|
799
|
-
|
|
800
|
-
return resource
|
|
801
|
-
},
|
|
802
|
-
removeVariant: (
|
|
803
|
-
context: RepositoryContext,
|
|
804
|
-
resource: Writable<Product>,
|
|
805
|
-
{ id, sku, staged }: ProductRemoveVariantAction
|
|
806
|
-
) => {
|
|
807
|
-
const removeVariant = (data: Writable<ProductData>) => {
|
|
808
|
-
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
809
|
-
data,
|
|
810
|
-
id,
|
|
811
|
-
sku
|
|
812
|
-
)
|
|
813
|
-
if (!variant) {
|
|
814
|
-
throw new Error(
|
|
815
|
-
`Variant with id ${id} or sku ${sku} not found on product ${resource.id}`
|
|
816
|
-
)
|
|
817
|
-
}
|
|
818
|
-
if (isMasterVariant) {
|
|
819
|
-
throw new Error(
|
|
820
|
-
`Can not remove the variant [ID:${id}] for [Product:${resource.id}] since it's the master variant`
|
|
821
|
-
)
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
data.variants.splice(variantIndex, 1)
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
828
|
-
|
|
829
|
-
removeVariant(resource.masterData.staged)
|
|
830
|
-
|
|
831
|
-
if (!onlyStaged) {
|
|
832
|
-
removeVariant(resource.masterData.current)
|
|
833
|
-
}
|
|
834
|
-
checkForStagedChanges(resource)
|
|
835
|
-
|
|
836
|
-
return resource
|
|
837
|
-
},
|
|
838
|
-
changeMasterVariant: (
|
|
839
|
-
context: RepositoryContext,
|
|
840
|
-
resource: Writable<Product>,
|
|
841
|
-
{ variantId, sku, staged }: ProductChangeMasterVariantAction
|
|
842
|
-
) => {
|
|
843
|
-
const setMaster = (data: Writable<ProductData>) => {
|
|
844
|
-
const { variant, isMasterVariant, variantIndex } = getVariant(
|
|
845
|
-
data,
|
|
846
|
-
variantId,
|
|
847
|
-
sku
|
|
848
|
-
)
|
|
849
|
-
if (!variant) {
|
|
850
|
-
throw new Error(
|
|
851
|
-
`Variant with id ${variantId} or sku ${sku} not found on product ${resource.id}`
|
|
852
|
-
)
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
if (!isMasterVariant) {
|
|
856
|
-
// Save previous master variant
|
|
857
|
-
const masterVariantPrev = data.masterVariant
|
|
858
|
-
data.masterVariant = variant
|
|
859
|
-
// Remove new master from variants
|
|
860
|
-
data.variants.splice(variantIndex, 1)
|
|
861
|
-
// Add previous master to variants
|
|
862
|
-
data.variants.push(masterVariantPrev)
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
867
|
-
|
|
868
|
-
setMaster(resource.masterData.staged)
|
|
869
|
-
|
|
870
|
-
if (!onlyStaged) {
|
|
871
|
-
setMaster(resource.masterData.current)
|
|
872
|
-
}
|
|
873
|
-
checkForStagedChanges(resource)
|
|
874
|
-
|
|
875
|
-
return resource
|
|
876
|
-
},
|
|
877
|
-
setTaxCategory: (
|
|
878
|
-
context: RepositoryContext,
|
|
879
|
-
resource: Writable<Product>,
|
|
880
|
-
{ taxCategory }: ProductSetTaxCategoryAction
|
|
881
|
-
) => {
|
|
882
|
-
let taxCategoryReference: TaxCategoryReference | undefined = undefined
|
|
883
|
-
if (taxCategory) {
|
|
884
|
-
taxCategoryReference =
|
|
885
|
-
getReferenceFromResourceIdentifier<TaxCategoryReference>(
|
|
886
|
-
taxCategory,
|
|
887
|
-
context.projectKey,
|
|
888
|
-
this._storage
|
|
889
|
-
)
|
|
890
|
-
} else {
|
|
891
|
-
throw new CommercetoolsError<InvalidJsonInputError>(
|
|
892
|
-
{
|
|
893
|
-
code: 'InvalidJsonInput',
|
|
894
|
-
message: 'Request body does not contain valid JSON.',
|
|
895
|
-
detailedErrorMessage:
|
|
896
|
-
'actions -> taxCategory: Missing required value',
|
|
897
|
-
},
|
|
898
|
-
400
|
|
899
|
-
)
|
|
900
|
-
}
|
|
901
|
-
resource.taxCategory = taxCategoryReference
|
|
902
|
-
return resource
|
|
903
|
-
},
|
|
904
|
-
addToCategory: (
|
|
905
|
-
context: RepositoryContext,
|
|
906
|
-
resource: Writable<Product>,
|
|
907
|
-
{ category, staged, orderHint }: ProductAddToCategoryAction
|
|
908
|
-
) => {
|
|
909
|
-
const addCategory = (data: Writable<ProductData>) => {
|
|
910
|
-
if (category) {
|
|
911
|
-
data.categories.push(
|
|
912
|
-
getReferenceFromResourceIdentifier<CategoryReference>(
|
|
913
|
-
category,
|
|
914
|
-
context.projectKey,
|
|
915
|
-
this._storage
|
|
916
|
-
)
|
|
917
|
-
)
|
|
918
|
-
} else {
|
|
919
|
-
throw new CommercetoolsError<InvalidJsonInputError>(
|
|
920
|
-
{
|
|
921
|
-
code: 'InvalidJsonInput',
|
|
922
|
-
message: 'Request body does not contain valid JSON.',
|
|
923
|
-
detailedErrorMessage:
|
|
924
|
-
'actions -> category: Missing required value',
|
|
925
|
-
},
|
|
926
|
-
400
|
|
927
|
-
)
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
932
|
-
|
|
933
|
-
addCategory(resource.masterData.staged)
|
|
934
|
-
|
|
935
|
-
if (!onlyStaged) {
|
|
936
|
-
addCategory(resource.masterData.current)
|
|
937
|
-
}
|
|
938
|
-
checkForStagedChanges(resource)
|
|
939
|
-
|
|
940
|
-
return resource
|
|
941
|
-
},
|
|
942
|
-
removeFromCategory: (
|
|
943
|
-
context: RepositoryContext,
|
|
944
|
-
resource: Writable<Product>,
|
|
945
|
-
{ category, staged }: ProductRemoveFromCategoryAction
|
|
946
|
-
) => {
|
|
947
|
-
const removeCategory = (data: Writable<ProductData>) => {
|
|
948
|
-
if (category) {
|
|
949
|
-
const resolvedCategory =
|
|
950
|
-
getReferenceFromResourceIdentifier<CategoryReference>(
|
|
951
|
-
category,
|
|
952
|
-
context.projectKey,
|
|
953
|
-
this._storage
|
|
954
|
-
)
|
|
955
|
-
|
|
956
|
-
const foundCategory = data.categories.find(
|
|
957
|
-
(productCategory: CategoryReference) => {
|
|
958
|
-
if (productCategory.id == resolvedCategory.id) {
|
|
959
|
-
return productCategory
|
|
960
|
-
}
|
|
961
|
-
return false
|
|
962
|
-
}
|
|
963
|
-
)
|
|
964
|
-
|
|
965
|
-
if (!foundCategory) {
|
|
966
|
-
throw new CommercetoolsError<InvalidOperationError>(
|
|
967
|
-
{
|
|
968
|
-
code: 'InvalidOperation',
|
|
969
|
-
message:
|
|
970
|
-
`Cannot remove from category '${resolvedCategory.id}' because product ` +
|
|
971
|
-
`'${resource.masterData.current.name}' is not in that category.`,
|
|
972
|
-
},
|
|
973
|
-
400
|
|
974
|
-
)
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
data.categories = data.categories.filter(
|
|
978
|
-
(productCategory: CategoryReference) => {
|
|
979
|
-
if (productCategory.id == resolvedCategory.id) {
|
|
980
|
-
return false
|
|
981
|
-
}
|
|
982
|
-
return true
|
|
983
|
-
}
|
|
984
|
-
)
|
|
985
|
-
} else {
|
|
986
|
-
throw new CommercetoolsError<InvalidJsonInputError>(
|
|
987
|
-
{
|
|
988
|
-
code: 'InvalidJsonInput',
|
|
989
|
-
message: 'Request body does not contain valid JSON.',
|
|
990
|
-
detailedErrorMessage:
|
|
991
|
-
'actions -> category: Missing required value',
|
|
992
|
-
},
|
|
993
|
-
400
|
|
994
|
-
)
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
const onlyStaged = staged !== undefined ? staged : true
|
|
999
|
-
removeCategory(resource.masterData.staged)
|
|
1000
|
-
|
|
1001
|
-
if (!onlyStaged) {
|
|
1002
|
-
removeCategory(resource.masterData.current)
|
|
1003
|
-
}
|
|
1004
|
-
checkForStagedChanges(resource)
|
|
1005
|
-
|
|
1006
|
-
return resource
|
|
1007
|
-
},
|
|
1008
|
-
transitionState: (
|
|
1009
|
-
context: RepositoryContext,
|
|
1010
|
-
resource: Writable<Product>,
|
|
1011
|
-
{ state, force }: ProductTransitionStateAction
|
|
1012
|
-
) => {
|
|
1013
|
-
let productStateReference: StateReference | undefined = undefined
|
|
1014
|
-
if (state) {
|
|
1015
|
-
productStateReference =
|
|
1016
|
-
getReferenceFromResourceIdentifier<StateReference>(
|
|
1017
|
-
state,
|
|
1018
|
-
context.projectKey,
|
|
1019
|
-
this._storage
|
|
1020
|
-
)
|
|
1021
|
-
resource.state = productStateReference
|
|
1022
|
-
} else {
|
|
1023
|
-
throw new CommercetoolsError<InvalidJsonInputError>(
|
|
1024
|
-
{
|
|
1025
|
-
code: 'InvalidJsonInput',
|
|
1026
|
-
message: 'Request body does not contain valid JSON.',
|
|
1027
|
-
detailedErrorMessage: 'actions -> state: Missing required value',
|
|
1028
|
-
},
|
|
1029
|
-
400
|
|
1030
|
-
)
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
return resource
|
|
1034
|
-
},
|
|
1035
|
-
|
|
1036
|
-
// 'setPrices': () => {},
|
|
1037
|
-
// 'setProductPriceCustomType': () => {},
|
|
1038
|
-
// 'setProductPriceCustomField': () => {},
|
|
1039
|
-
// 'setDiscountedPrice': () => {},
|
|
1040
|
-
// 'setAttributeInAllVariants': () => {},
|
|
1041
|
-
// 'setCategoryOrderHint': () => {},
|
|
1042
|
-
// 'setSku': () => {},
|
|
1043
|
-
// 'setProductVariantKey': () => {},
|
|
1044
|
-
// 'setImageLabel': () => {},
|
|
1045
|
-
// 'addAsset': () => {},
|
|
1046
|
-
// 'removeAsset': () => {},
|
|
1047
|
-
// 'setAssetKey': () => {},
|
|
1048
|
-
// 'changeAssetOrder': () => {},
|
|
1049
|
-
// 'changeAssetName': () => {},
|
|
1050
|
-
// 'setAssetDescription': () => {},
|
|
1051
|
-
// 'setAssetTags': () => {},
|
|
1052
|
-
// 'setAssetSources': () => {},
|
|
1053
|
-
// 'setAssetCustomType': () => {},
|
|
1054
|
-
// 'setAssetCustomField': () => {},
|
|
1055
|
-
// 'setSearchKeywords': () => {},
|
|
1056
|
-
// 'revertStagedChanges': () => {},
|
|
1057
|
-
// 'revertStagedVariantChanges': () => {},
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
// Check if the product still has staged data that is different from the
|
|
1062
|
-
// current data.
|
|
1063
|
-
const checkForStagedChanges = (product: Writable<Product>) => {
|
|
1064
|
-
if (!product.masterData.staged) {
|
|
1065
|
-
product.masterData.staged = product.masterData.current
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
if (deepEqual(product.masterData.current, product.masterData.staged)) {
|
|
1069
|
-
product.masterData.hasStagedChanges = false
|
|
1070
|
-
} else {
|
|
1071
|
-
product.masterData.hasStagedChanges = true
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
interface VariantResult {
|
|
1076
|
-
variant: Writable<ProductVariant> | undefined
|
|
1077
|
-
isMasterVariant: boolean
|
|
1078
|
-
variantIndex: number
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
const getVariant = (
|
|
1082
|
-
productData: ProductData,
|
|
1083
|
-
variantId?: number,
|
|
1084
|
-
sku?: string
|
|
1085
|
-
): VariantResult => {
|
|
1086
|
-
const variants = [productData.masterVariant, ...productData.variants]
|
|
1087
|
-
const foundVariant = variants.find((variant: ProductVariant) => {
|
|
1088
|
-
if (variantId) {
|
|
1089
|
-
return variant.id === variantId
|
|
1090
|
-
}
|
|
1091
|
-
if (sku) {
|
|
1092
|
-
return variant.sku === sku
|
|
1093
|
-
}
|
|
1094
|
-
return false
|
|
1095
|
-
})
|
|
1096
|
-
|
|
1097
|
-
const isMasterVariant = foundVariant === productData.masterVariant
|
|
1098
|
-
return {
|
|
1099
|
-
variant: foundVariant,
|
|
1100
|
-
isMasterVariant,
|
|
1101
|
-
variantIndex:
|
|
1102
|
-
!isMasterVariant && foundVariant
|
|
1103
|
-
? productData.variants.indexOf(foundVariant)
|
|
1104
|
-
: -1,
|
|
1105
|
-
}
|
|
1106
|
-
}
|