Skip to content

Commit

Permalink
Merge befdf4c into ea8b004
Browse files Browse the repository at this point in the history
  • Loading branch information
junajan committed Dec 3, 2018
2 parents ea8b004 + befdf4c commit 604bcc4
Show file tree
Hide file tree
Showing 11 changed files with 1,766 additions and 1,497 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ test
config.js
.coveralls.yml
coverage
.idea
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ coverage
.coveralls.yml
create_config.sh
*.coffee
.idea
13 changes: 9 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"dependencies": {
"debug": "2.6.9",
"jsondiffpatch": "0.2.4",
"lodash.isnil": "^4.0.0",
"request": "^2.88.0",
"sphere-node-utils": "^1.0.0",
"underscore-mixins": "^0.1.4"
Expand Down
113 changes: 97 additions & 16 deletions src/coffee/sync/product-sync.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,104 @@ class ProductSync extends BaseSync
@sameForAllAttributeNames = sameForAllAttributeNames
super new_obj, old_obj

_doMapActions: (diff, new_obj, old_obj) ->
_ensureDefaultProperties: (variant) ->
variant.images = [] unless variant.images
variant.assets = [] unless variant.assets
variant.prices = [] unless variant.prices
variant.attributes = [] unless variant.attributes

_diffVariant: (newVariant, oldVariant) ->
# add default properties so we always compare arrays to arrays
@_ensureDefaultProperties(newVariant)
@_ensureDefaultProperties(oldVariant)

actions = []
diff = @_utils.diff(oldVariant, newVariant)

if diff
actions = []
.concat @_mapActionOrNot 'attributes', => @_utils.buildVariantBaseAction(diff, oldVariant)
.concat @_mapActionOrNot 'attributes', => @_utils.buildVariantAttributesActions(diff.attributes, oldVariant, newVariant, @sameForAllAttributeNames)
.concat @_mapActionOrNot 'prices', => @_utils.buildVariantPriceActions(diff.prices, oldVariant, newVariant)
.concat @_mapActionOrNot 'images', => @_utils.buildVariantImagesAction(diff.images, oldVariant, newVariant)
.filter(Boolean)
actions

_postProcessVariantUpdateActions: (actions) ->
# put addPrice actions to the end of the list (first remove price then add)
actions = _.sortBy(actions, (a) -> a.action is 'addPrice')

# filter out duplicate update actions - eg multiple sameForAll update actions
actions = _.unique(actions, (a) -> JSON.stringify a)
actions

_doMapVariantActions: (newObj, oldObj) ->
addVariantActions = []
variantUpdateActions = []

# group all variants to one list
newVariants = [newObj.masterVariant].concat(newObj.variants or []).filter Boolean
oldVariants = [oldObj.masterVariant].concat(oldObj.variants or []).filter Boolean

# generate changeMasterVariantAction
changeMasterVariantAction = @_utils.buildChangeMasterVariantAction(
newObj.masterVariant, oldObj.masterVariant
)

# generate remove variant actions
removeVariantActions = @_utils.buildRemoveVariantActions(newVariants, oldVariants)

# generate set attribute/image/assets actions for all changed variants
# if variant does not exist yet, create also addVariant action
newVariants.forEach (newVariant) =>
# find existing variant
oldVariant = @_utils.findVariantInList(newVariant, oldVariants)

# if variant does not exist, add it
if not oldVariant
addVariantActions.push(@_utils.buildAddVariantActions(newVariant))
else
variantUpdateActions.push.apply(variantUpdateActions, @_diffVariant(newVariant, oldVariant))

variantUpdateActions = @_postProcessVariantUpdateActions(variantUpdateActions.filter(Boolean))

return {
variantUpdateActions
addVariantActions
removeVariantActions
changeMasterVariantAction
}

_doMapActions: (diff, newObj, oldObj) ->
# Update actions needs to be sorted and executed in particular order.
variantActions = @_mapActionOrNot 'variants', => @_utils.actionsMapVariants(diff, old_obj, new_obj)

allActions = []
# First redundant variants need to be removed to prevent SKU conflicts, e.g. in case of chaging the master variant
allActions.push variantActions.filter (action) -> action.action is 'removeVariant'
# Before adding new variants, all attributes needs to be updated to the newest value to prevent adding a new variant with different
# sameForAll attribute value than the variants in the CTP product.
allActions.push @_mapActionOrNot 'attributes', => @_utils.actionsMapAttributes(diff, old_obj, new_obj, @sameForAllAttributeNames)
allActions.push variantActions.filter (action) -> action.action is 'addVariant'
allActions.push @_mapActionOrNot 'base', => @_utils.actionsMapBase(diff, old_obj)
allActions.push @_mapActionOrNot 'references', => @_utils.actionsMapReferences(diff, old_obj, new_obj)
allActions.push @_mapActionOrNot 'prices', => @_utils.actionsMapPrices(diff, old_obj, new_obj)
allActions.push @_mapActionOrNot 'images', => @_utils.actionsMapImages(diff, old_obj, new_obj)
allActions = []

# base product data update actions
allActions.push @_mapActionOrNot 'base', => @_utils.actionsMapBase(diff, oldObj)
allActions.push @_mapActionOrNot 'references', => @_utils.actionsMapReferences(diff, newObj, oldObj)
allActions.push @_mapActionOrNot 'categories', => @_utils.actionsMapCategories(diff)
allActions.push @_mapActionOrNot 'categoryOrderHints', => @_utils.actionsMapCategoryOrderHints(diff, old_obj)
_.flatten allActions
allActions.push @_mapActionOrNot 'categoryOrderHints', => @_utils.actionsMapCategoryOrderHints(diff, oldObj)

# generate variant related update actions
variantActionGroups = @_doMapVariantActions(newObj, oldObj)

# apply remove/add/changeMaster variant in the following order:
# - remove all variants except master variant
# - apply setAttribute/image .. update actions
# - add new variants
# - promote a new masterVariant
# - remove masterVariant

# divide removeVariant actions to two groups - one for masterVariant, second for normal variants
partitionedRemoveActionsByMasterVariant = _.partition variantActionGroups.removeVariantActions, (action) =>
oldObj.masterVariant and @_utils.matchesByIdOrKeyOrSku(action, oldObj.masterVariant)

allActions.push @_mapActionOrNot 'variants', => partitionedRemoveActionsByMasterVariant[1] # normal variants
allActions.push variantActionGroups.variantUpdateActions # already white/black listed from @_diffVariant
allActions.push @_mapActionOrNot 'variants', => variantActionGroups.addVariantActions
allActions.push @_mapActionOrNot 'variants', => variantActionGroups.changeMasterVariantAction
allActions.push @_mapActionOrNot 'variants', => partitionedRemoveActionsByMasterVariant[0] # masterVariant

_.flatten(allActions).filter(Boolean)

module.exports = ProductSync
Loading

0 comments on commit 604bcc4

Please sign in to comment.