|
| 1 | +const { getProductOptions, productChecksum } = require('./productChecksum'); |
| 2 | + |
| 3 | +// 'id' check |
| 4 | +const getServerItemId = (product) => |
| 5 | + product.server_item_id || product.item_id |
| 6 | +const isServerIdsEquals = (product1, product2) => { |
| 7 | + const product1ItemId = getServerItemId(product1) |
| 8 | + const product2ItemId = getServerItemId(product2) |
| 9 | + |
| 10 | + const areItemIdsDefined = product1ItemId !== undefined && product2ItemId !== undefined |
| 11 | + |
| 12 | + return areItemIdsDefined && product1ItemId === product2ItemId |
| 13 | +} |
| 14 | + |
| 15 | +// 'checksum' check |
| 16 | +const getChecksum = (product) => { |
| 17 | + if (product.checksum) { |
| 18 | + return product.checksum |
| 19 | + } |
| 20 | + return productChecksum(product) |
| 21 | +} |
| 22 | +const isChecksumEquals = (product1, product2) => |
| 23 | + getChecksum(product1) === getChecksum(product2) |
| 24 | + |
| 25 | +// 'sku' check |
| 26 | +const isSkuEqual = (product1, product2) => |
| 27 | + String(product1.sku) === String(product2.sku) |
| 28 | + |
| 29 | +/** |
| 30 | + * Returns product equality check function |
| 31 | + * @param checkName - determines what type of check we want to do |
| 32 | + */ |
| 33 | +const getCheckFn = (checkName) => { |
| 34 | + switch (checkName) { |
| 35 | + case 'id': { |
| 36 | + return isServerIdsEquals |
| 37 | + } |
| 38 | + case 'checksum': { |
| 39 | + return isChecksumEquals |
| 40 | + } |
| 41 | + case 'sku': { |
| 42 | + return isSkuEqual |
| 43 | + } |
| 44 | + default: { |
| 45 | + return isSkuEqual |
| 46 | + } |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +/** |
| 51 | + * It passes all types of checks and returns the first passed. The order of checks matters! |
| 52 | + */ |
| 53 | +const makeCheck = (product1, product2, checks) => { |
| 54 | + for (let checkName of checks) { |
| 55 | + const fn = getCheckFn(checkName) |
| 56 | + if (fn(product1, product2)) { |
| 57 | + return true |
| 58 | + } |
| 59 | + } |
| 60 | + return false |
| 61 | +} |
| 62 | + |
| 63 | +const productsEquals = (product1, product2) => { |
| 64 | + if (!product1 || !product2) { |
| 65 | + return false |
| 66 | + } |
| 67 | + |
| 68 | + const check = makeCheck.bind(null, product1, product2) |
| 69 | + |
| 70 | + if (getProductOptions(product1, 'bundle_options').length || getProductOptions(product2, 'bundle_options').length) { |
| 71 | + // bundle options skus are merged into one sku so we can't rely on 'sku' |
| 72 | + // by default we want to check server_item_id ('id'), we can also use 'checksum' |
| 73 | + return check(['id', 'checksum']) |
| 74 | + } |
| 75 | + |
| 76 | + if (getProductOptions(product1, 'custom_options').length || getProductOptions(product2, 'custom_options').length) { |
| 77 | + // in admin panel we can add different sku for specific custom option so we can't rely on 'sku' |
| 78 | + // by default we want to check server_item_id ('id'), we can also use 'checksum' |
| 79 | + return check(['id', 'checksum']) |
| 80 | + } |
| 81 | + |
| 82 | + if (getProductOptions(product1, 'configurable_item_options').length || getProductOptions(product2, 'configurable_item_options').length) { |
| 83 | + // 'sku' should be uniq for configurable products |
| 84 | + // we can't check 'id' because it is the same when user edit product in microcart, so it can give wrong result |
| 85 | + return check(['sku']) |
| 86 | + } |
| 87 | + |
| 88 | + // by default we want to check if server_item_id is equal and check sku as fallback |
| 89 | + // this is for 'simple' and 'group' products |
| 90 | + return check(['id', 'sku']) |
| 91 | +} |
| 92 | + |
| 93 | +module.exports = productsEquals |
0 commit comments