Skip to content

Commit 961de7c

Browse files
peter-gerhardPeter Gerhardmarkus-azer
authored
PDM-236 Add support for product level attributes (#1969)
* feat(product-attributes): extract function '_buildAttributeValue' * feat(product-attributes): add function '_buildSetProductAttributeAction' * feat(product-attributes): refactor _buildNewSetAttributeAction * feat(product-attributes): add function '_buildNewSetProductAttributeAction' * feat(product-attributes): add function '_buildProductAttributesActions' * feat(product-attributes): rename function 'actionsMapAttributes' -> 'actionsMapVariantAttributes' * feat(product-attributes): add function 'actionsMapProductAttributes' * feat(product-attributes): rename action group 'attributes' -> 'variantAttributes' * feat(product-attributes): add 'setProductAttributes' to baseActionsList * feat(product-attributes): add action group 'productAttributes' * feat(product-attributes): add test for product attribute actions * feat(product-attributes): remove setProductAttribute from base actions * feat(product-attributes): version bump for package * feat(product attributes): revert productAttributes to attributes * chore(product attribute): re-order code for easy review * test(product attributes): add more coverage --------- Co-authored-by: Peter Gerhard <peter.gerhard@.commercetools.com> Co-authored-by: Markus Azer <markusgihady@gmail.com>
1 parent e91cb18 commit 961de7c

File tree

5 files changed

+613
-45
lines changed

5 files changed

+613
-45
lines changed

.changeset/warm-webs-dream.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@commercetools/sync-actions': minor
3+
---
4+
5+
Add support for product level attributes

packages/sync-actions/src/product-actions.js

Lines changed: 172 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,74 @@ function _buildKeyActions(variantDiff, oldVariant) {
9191
return null
9292
}
9393

94-
function _buildNewSetAttributeAction(id, el, sameForAllAttributeNames) {
95-
const attributeName = el && el.name
94+
function _buildAttributeValue(
95+
diffedValue,
96+
oldAttributeValue,
97+
newAttributeValue
98+
) {
99+
let value
100+
101+
if (Array.isArray(diffedValue))
102+
value = diffpatcher.getDeltaValue(diffedValue, oldAttributeValue)
103+
else if (typeof diffedValue === 'string')
104+
// LText: value: {en: "", de: ""}
105+
// Enum: value: {key: "foo", label: "Foo"}
106+
// LEnum: value: {key: "foo", label: {en: "Foo", de: "Foo"}}
107+
// Money: value: {centAmount: 123, currencyCode: ""}
108+
// *: value: ""
109+
110+
// normal
111+
value = diffpatcher.getDeltaValue(diffedValue, oldAttributeValue)
112+
else if (diffedValue.centAmount || diffedValue.currencyCode)
113+
// Money
114+
value = {
115+
centAmount: diffedValue.centAmount
116+
? diffpatcher.getDeltaValue(diffedValue.centAmount)
117+
: newAttributeValue.centAmount,
118+
currencyCode: diffedValue.currencyCode
119+
? diffpatcher.getDeltaValue(diffedValue.currencyCode)
120+
: newAttributeValue.currencyCode,
121+
}
122+
else if (diffedValue.key)
123+
// Enum / LEnum (use only the key)
124+
value = diffpatcher.getDeltaValue(diffedValue.key)
125+
else if (typeof diffedValue === 'object')
126+
if ({}.hasOwnProperty.call(diffedValue, '_t') && diffedValue._t === 'a') {
127+
// set-typed attribute
128+
value = newAttributeValue
129+
} else {
130+
// LText
131+
132+
const updatedValue = Object.keys(diffedValue).reduce(
133+
(acc, lang) => {
134+
const patchedValue = diffpatcher.getDeltaValue(
135+
diffedValue[lang],
136+
acc[lang]
137+
)
138+
return Object.assign(acc, { [lang]: patchedValue })
139+
},
140+
{ ...oldAttributeValue }
141+
)
142+
143+
value = updatedValue
144+
}
145+
146+
return value
147+
}
148+
149+
function _buildNewSetAttributeAction(
150+
variantId,
151+
attr,
152+
sameForAllAttributeNames
153+
) {
154+
const attributeName = attr && attr.name
96155
if (!attributeName) return undefined
97156

98157
let action = {
99158
action: 'setAttribute',
100-
variantId: id,
159+
variantId,
101160
name: attributeName,
102-
value: el.value,
161+
value: attr.value,
103162
}
104163

105164
if (sameForAllAttributeNames.indexOf(attributeName) !== -1) {
@@ -133,50 +192,49 @@ function _buildSetAttributeAction(
133192
delete action.variantId
134193
}
135194

136-
if (Array.isArray(diffedValue))
137-
action.value = diffpatcher.getDeltaValue(diffedValue, oldAttribute.value)
138-
else if (typeof diffedValue === 'string')
139-
// LText: value: {en: "", de: ""}
140-
// Enum: value: {key: "foo", label: "Foo"}
141-
// LEnum: value: {key: "foo", label: {en: "Foo", de: "Foo"}}
142-
// Money: value: {centAmount: 123, currencyCode: ""}
143-
// *: value: ""
195+
action.value = _buildAttributeValue(
196+
diffedValue,
197+
oldAttribute.value,
198+
attribute.value
199+
)
144200

145-
// normal
146-
action.value = diffpatcher.getDeltaValue(diffedValue, oldAttribute.value)
147-
else if (diffedValue.centAmount || diffedValue.currencyCode)
148-
// Money
149-
action.value = {
150-
centAmount: diffedValue.centAmount
151-
? diffpatcher.getDeltaValue(diffedValue.centAmount)
152-
: attribute.value.centAmount,
153-
currencyCode: diffedValue.currencyCode
154-
? diffpatcher.getDeltaValue(diffedValue.currencyCode)
155-
: attribute.value.currencyCode,
156-
}
157-
else if (diffedValue.key)
158-
// Enum / LEnum (use only the key)
159-
action.value = diffpatcher.getDeltaValue(diffedValue.key)
160-
else if (typeof diffedValue === 'object')
161-
if ({}.hasOwnProperty.call(diffedValue, '_t') && diffedValue._t === 'a') {
162-
// set-typed attribute
163-
action = { ...action, value: attribute.value }
164-
} else {
165-
// LText
201+
return action
202+
}
166203

167-
const updatedValue = Object.keys(diffedValue).reduce(
168-
(acc, lang) => {
169-
const patchedValue = diffpatcher.getDeltaValue(
170-
diffedValue[lang],
171-
acc[lang]
172-
)
173-
return Object.assign(acc, { [lang]: patchedValue })
174-
},
175-
{ ...oldAttribute.value }
176-
)
204+
function _buildNewSetProductAttributeAction(attr) {
205+
const attributeName = attr && attr.name
206+
if (!attributeName) return undefined
177207

178-
action.value = updatedValue
179-
}
208+
const action = {
209+
action: 'setProductAttribute',
210+
name: attributeName,
211+
value: attr.value,
212+
}
213+
214+
return action
215+
}
216+
217+
function _buildSetProductAttributeAction(
218+
diffedValue,
219+
oldProductData,
220+
newAttribute
221+
) {
222+
if (!newAttribute) return undefined
223+
224+
const action = {
225+
action: 'setProductAttribute',
226+
name: newAttribute.name,
227+
}
228+
229+
// Used as original object for patching long diff text
230+
const oldAttribute =
231+
oldProductData.attributes.find((a) => a.name === newAttribute.name) || {}
232+
233+
action.value = _buildAttributeValue(
234+
diffedValue,
235+
oldAttribute.value,
236+
newAttribute.value
237+
)
180238

181239
return action
182240
}
@@ -325,6 +383,63 @@ function _buildVariantPricesAction(
325383
return [addPriceActions, changePriceActions, removePriceActions]
326384
}
327385

386+
function _buildProductAttributesActions(
387+
diffedAttributes,
388+
oldProductData,
389+
newProductData
390+
) {
391+
const actions = []
392+
393+
if (!diffedAttributes) return actions
394+
395+
forEach(diffedAttributes, (value, key) => {
396+
if (REGEX_NUMBER.test(key)) {
397+
if (Array.isArray(value)) {
398+
const setAction = _buildNewSetProductAttributeAction(
399+
diffpatcher.getDeltaValue(value)
400+
)
401+
if (setAction) actions.push(setAction)
402+
} else if (newProductData.attributes) {
403+
const setAction = _buildSetProductAttributeAction(
404+
value.value,
405+
oldProductData,
406+
newProductData.attributes[key]
407+
)
408+
if (setAction) actions.push(setAction)
409+
}
410+
} else if (REGEX_UNDERSCORE_NUMBER.test(key)) {
411+
if (Array.isArray(value)) {
412+
// Ignore pure array moves!
413+
if (value.length === 3 && value[2] === 3) return
414+
415+
let deltaValue = diffpatcher.getDeltaValue(value)
416+
417+
if (!deltaValue)
418+
if (value[0] && value[0].name)
419+
// unset attribute if
420+
deltaValue = { name: value[0].name }
421+
else deltaValue = undefined
422+
423+
const setAction = _buildNewSetProductAttributeAction(deltaValue)
424+
425+
if (setAction) actions.push(setAction)
426+
} else {
427+
const index = key.substring(1)
428+
if (newProductData.attributes) {
429+
const setAction = _buildSetProductAttributeAction(
430+
value.value,
431+
oldProductData,
432+
newProductData.attributes[index]
433+
)
434+
if (setAction) actions.push(setAction)
435+
}
436+
}
437+
}
438+
})
439+
440+
return actions
441+
}
442+
328443
function _buildVariantAttributesActions(
329444
attributes,
330445
oldVariant,
@@ -654,6 +769,18 @@ export function actionsMapAssets(diff, oldObj, newObj, variantHashMap) {
654769
return allAssetsActions
655770
}
656771

772+
export function actionsMapProductAttributes(
773+
diffedProductData,
774+
oldProductData,
775+
newProductData
776+
) {
777+
return _buildProductAttributesActions(
778+
diffedProductData.attributes,
779+
oldProductData,
780+
newProductData
781+
)
782+
}
783+
657784
export function actionsMapAttributes(
658785
diff,
659786
oldObj,

packages/sync-actions/src/products.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const actionGroups = [
1919
'references',
2020
'prices',
2121
'pricesCustom',
22+
'productAttributes',
2223
'attributes',
2324
'images',
2425
'variants',
@@ -51,6 +52,12 @@ function createProductMapActions(
5152
newObj.variants
5253
)
5354

55+
allActions.push(
56+
mapActionGroup('productAttributes', (): Array<UpdateAction> =>
57+
productActions.actionsMapProductAttributes(diff, oldObj, newObj)
58+
)
59+
)
60+
5461
allActions.push(
5562
mapActionGroup('attributes', (): Array<UpdateAction> =>
5663
productActions.actionsMapAttributes(

0 commit comments

Comments
 (0)