vue-storefront
Version:
A Vue.js, PWA eCommerce frontend
182 lines (162 loc) • 7.68 kB
JavaScript
import config from 'config'
import rootStore from '../../'
import EventBus from 'core/plugins/event-bus'
import { calculateProductTax } from 'core/lib/taxcalc'
import _ from 'lodash'
export function syncProductPrice (product, backProduct) { // TODO: we probably need to update the Net prices here as well
product.sgn = backProduct.sgn // copy the signature for the modified price
product.priceInclTax = backProduct.price_info.final_price
product.originalPriceInclTax = backProduct.price_info.regular_price
product.specialPriceInclTax = backProduct.price_info.special_price
product.special_price = backProduct.price_info.extension_attributes.tax_adjustments.special_price
product.price = backProduct.price_info.extension_attributes.tax_adjustments.final_price
product.originalPrice = backProduct.price_info.extension_attributes.tax_adjustments.regular_price
product.priceTax = product.priceInclTax - product.price
product.specialPriceTax = product.specialPriceInclTax - product.special_price
product.originalPriceTax = product.originalPriceInclTax - product.originalPrice
if (product.priceInclTax >= product.originalPriceInclTax) {
product.specialPriceInclTax = 0
product.special_price = 0
} else {
product.special_price = 0 // the same price as original; it's not a promotion
}
EventBus.$emit('product-after-priceupdate', product)
// console.log(product.sku, product, backProduct)
return product
}
/**
* Synchronize / override prices got from ElasticSearch with current one's from Magento2 or other platform backend
* @param {Array} products
*/
export function doPlatformPricesSync (products) {
return new Promise((resolve, reject) => {
if (config.products.alwaysSyncPlatformPricesOver) {
if (config.products.clearPricesBeforePlatformSync) {
for (let product of products) { // clear out the prices as we need to sync them with Magento
product.priceInclTax = null
product.originalPriceInclTax = null
product.specialPriceInclTax = null
product.special_price = null
product.price = null
product.originalPrice = null
product.priceTax = null
product.specialPriceTax = null
product.originalPriceTax = null
if (product.configurable_children) {
for (let sc of product.configurable_children) {
sc.priceInclTax = null
sc.originalPriceInclTax = null
sc.specialPriceInclTax = null
sc.special_price = null
sc.price = null
sc.originalPrice = null
sc.priceTax = null
sc.specialPriceTax = null
sc.originalPriceTax = null
}
}
}
}
let skus = products.map((p) => { return p.sku })
if (products.length === 1) { // single product - download child data
const childSkus = _.flattenDeep(products.map((p) => { return (p.configurable_children) ? p.configurable_children.map((cc) => { return cc.sku }) : null }))
skus = _.union(skus, childSkus)
}
console.log('Starting platform prices sync for', skus) // TODO: add option for syncro and non syncro return
rootStore.dispatch('product/syncPlatformPricesOver', { skus: skus }, { root: true }).then((syncResult) => {
if (syncResult) {
syncResult = syncResult.items
for (let product of products) {
const backProduct = syncResult.find((itm) => { return itm.id === product.id })
if (backProduct) {
product.price_is_current = true // in case we're syncing up the prices we should mark if we do have current or not
product.price_refreshed_at = new Date()
product = syncProductPrice(product, backProduct)
if (product.configurable_children) {
for (let configurableChild of product.configurable_children) {
const backProductChild = syncResult.find((itm) => { return itm.id === configurableChild.id })
if (backProductChild) {
configurableChild = syncProductPrice(configurableChild, backProductChild)
}
}
}
// TODO: shall we update local storage here for the main product?
}
}
}
resolve(products)
})
if (!config.products.waitForPlatformSync && !global.isSSR) {
console.log('Returning products, the prices yet to come from backend!')
for (let product of products) {
product.price_is_current = false // in case we're syncing up the prices we should mark if we do have current or not
product.price_refreshed_at = null
}
resolve(products)
}
} else {
resolve(products)
}
})
}
/**
* Calculate taxes for specific product collection
*/
export function calculateTaxes (products, store) {
return new Promise((resolve, reject) => {
if (config.tax.calculateServerSide) {
console.log('Taxes calculated server side, skipping')
doPlatformPricesSync(products).then((products) => {
resolve(products)
})
} else {
store.dispatch('tax/list', { query: '' }, { root: true }).then((tcs) => { // TODO: move it to the server side for one requests OR cache in indexedDb
for (let product of products) {
product = calculateProductTax(product, tcs.items, global.__TAX_COUNTRY__, global.__TAX_REGION__)
}
doPlatformPricesSync(products).then((products) => {
resolve(products)
})
}) // TODO: run Magento2 prices request here if configured so in the config
}
})
}
export function configureProductAsync (context, { product, configuration, selectDefaultVariant = true }) {
// use current product if product wasn't passed
if (product === null) product = context.getters.productCurrent
const hasConfigurableChildren = (product.configurable_children && product.configurable_children.length > 0)
if (hasConfigurableChildren) {
// handle custom_attributes for easier comparing in the future
product.configurable_children.forEach((child) => {
let customAttributesAsObject = {}
child.custom_attributes.forEach((attr) => {
customAttributesAsObject[attr.attribute_code] = attr.value
})
// add values from custom_attributes in a different form
Object.assign(child, customAttributesAsObject)
})
// find selected variant
let selectedVariant = product.configurable_children.find((configurableChild) => {
if (configuration.sku) {
return configurableChild.sku === configuration.sku // by sku or first one
} else {
return Object.keys(configuration).every((configProperty) => {
return parseInt(configurableChild[configProperty]) === parseInt(configuration[configProperty].id)
})
}
}) || product.configurable_children[0]
if (typeof navigator !== 'undefined') {
if (selectedVariant && !navigator.onLine) { // this is fix for not preloaded images for offline
selectedVariant.image = product.image
}
}
// use chosen variant
if (selectDefaultVariant) {
context.dispatch('setCurrent', selectedVariant)
}
EventBus.$emit('product-after-configure', { product: product, configuration: configuration, selectedVariant: selectedVariant })
return selectedVariant
} else {
return product
}
}