@gameroom/cli
Version:
A command line tool for Gameroom
122 lines (120 loc) • 5.69 kB
JavaScript
const cosmetic = require('cosmetic'),
{ models: { Price, Product } } = require('@gameroom/kit'),
{ grGreen } = require('../../../helpers'),
{ ShopifyV2 } = require('../../../models'),
{ config, spinner } = require('../../../refs'),
LIMIT = 500
module.exports = async ({ verbose }) => {
// Gameroom prices >> Shopify variants
// date filter
let filter
if (config.shopify_price_sync) {
const date = new Date(config.shopify_price_sync)
spinner.info(`last price sync ${date.toLocaleString()}`)
// just in case...
// date.setTime(date.getTime() - 1)
filter = { key: 'updated_at', comparison: '>', value: date }
} else {
spinner.info(`first price sync`)
}
// Get updated prices and add or update or remove them on shopify
let offset = 0, done = false, processed = {}, products = {}
// update shopify
let added = 0, removed = 0, skipped = 0, updated = 0, current = 0, total = 0
spinner.text = `0 / 0 processed, 0 ${cosmetic.green('added')}, 0 ${cosmetic.red('removed')}, 0 ${cosmetic.yellow('updated')}, 0 skipped, 0 not offered`
while (!done) {
if (config.should_exit) break
// get batch of prices
const prices = await Price.get({ filter, limit: LIMIT, offset, sort: [{ updated_at: 1 }] })
done = prices.length === 0
offset += prices.length
total += prices.length
if (verbose) spinner.info(`got ${prices.length} ${grGreen('prices')}`)
// iterate through batch
for (let [i, price] of prices.entries()) {
try {
spinner.text = `${current} / ${total} processed, ${added} ${cosmetic.green('added')}, ${removed} ${cosmetic.red('removed')}, ${updated} ${cosmetic.yellow('updated')}, ${skipped} skipped`
current++
if (config.should_exit) break
if (verbose) spinner.info(`syncing gameroom ${grGreen('price')} ${price.id}`)
// snapshot price properties
const { properties: { shopify_id, shopify_inventory_id }, updated_at } = price
// check updated_at
if (updated_at.equals(processed[price.id])) {
delete processed[price.id]
config.shopify_price_sync = new Date(updated_at * 1000)
if (verbose) spinner.succeed(`already processed ${grGreen('price')}`)
skipped++
continue
}
// get shopify variant
let shopify_variant = shopify_id ? await ShopifyV2.Variant.getWithId(shopify_id) : null
// conditions
const shopifyable = price.amount > 0
const add = !shopify_variant && shopifyable
const remove = shopify_variant && !shopifyable
const update = shopify_variant && shopifyable
if (add) {
// get gameroom product
// create inventory levels too on add
const product = products[price.product_id] || await Product.find(price.product_id)
products[product.id] = product
if (!product) throw new Error('product not found')
if (!product.offered) {
// will be removed at the product level
config.shopify_price_sync = new Date(updated_at * 1000)
if (verbose) spinner.warn(`skipping ${grGreen('price')}`)
skipped++
continue
}
// create shopify product
shopify_variant = await ShopifyV2.Variant.fromProductAndPrice(product, price)
shopify_variant = await shopify_variant.save()
if (verbose) spinner.info(`created shopify ${cosmetic.green('variant')}`)
added++
} else if (remove) {
// delete shopify product
await ShopifyV2.Variant.delete(shopify_id)
shopify_variant = null
if (verbose) spinner.info(`removed shopify ${cosmetic.green('variant')}`)
removed++
} else if (update) {
// update shopify variant
shopify_variant = await shopify_variant.updateFromPrice(price)
if (verbose) spinner.info(`updated shopify ${cosmetic.green('variant')}`)
updated++
} else {
// not offered and not shopified, no action necessary
config.shopify_price_sync = new Date(updated_at * 1000)
if (verbose) spinner.warn(`skipping ${grGreen('price')}`)
skipped++
continue
}
// update shopify id
if (shopify_variant) {
price.properties.shopify_id = shopify_variant.id
price.properties.shopify_inventory_id = shopify_variant.inventory_item_id
} else {
delete price.properties.shopify_id
delete price.properties.shopify_inventory_id
}
if (price.properties.shopify_id != shopify_id || price.properties.shopify_inventory_id != shopify_inventory_id) {
// update price if need be
price = await Price.update({ id: price.id, properties: price.properties })
if (verbose) spinner.info(`updated gameroom ${grGreen('price')}`)
// updated prices go to the end of the pagination line and mess up the offset...
processed[price.id] = price.updated_at
offset--
}
config.shopify_price_sync = new Date(updated_at * 1000)
if (verbose) spinner.succeed(`synced ${grGreen('price')}`)
} catch (err) {
// if verbose, the id has already been printed
spinner.fail(`failed ${grGreen('price')}${verbose ? '' : ` ${price.id}`} ${err}`)
skipped++
}
}
}
spinner.succeed(`${total} processed, ${added} ${cosmetic.green('added')}, ${removed} ${cosmetic.red('removed')}, ${updated} ${cosmetic.yellow('updated')}, ${skipped} skipped`)
spinner.succeed(`completed price sync to ${cosmetic.green('shopify')} @ ${new Date().toLocaleString()}`)
}