UNPKG

trailpack-proxy-cart

Version:

eCommerce - Trailpack for Proxy Engine

270 lines (251 loc) 7.46 kB
/* eslint no-console: [0] */ 'use strict' const Service = require('trails/service') const csvParser = require('papaparse') const _ = require('lodash') const shortid = require('shortid') const fs = require('fs') const VENDOR_UPLOAD = require('../../lib').Enums.VENDOR_UPLOAD /** * @module VendorCsvService * @description Vendor CSV Service */ module.exports = class VendorCsvService extends Service { /** * * @param file * @returns {Promise} */ vendorCsv(file) { // TODO validate csv console.time('csv') const uploadID = shortid.generate() const ProxyEngineService = this.app.services.ProxyEngineService const errors = [] let errorsCount = 0, lineNumber = 1 return new Promise((resolve, reject)=>{ const options = { header: true, dynamicTyping: true, encoding: 'utf-8', step: (results, parser) => { parser.pause() lineNumber++ return this.csvVendorRow(results.data[0], uploadID) .then(row => { parser.resume() }) .catch(err => { errorsCount++ errors.push(`Line ${lineNumber}: ${err.message}`) this.app.log.error('ROW ERROR',err) parser.resume() }) }, complete: (results, file) => { console.timeEnd('csv') results.upload_id = uploadID ProxyEngineService.count('VendorUpload', { where: { upload_id: uploadID }}) .then(count => { results.vendors = count results.errors_count = errorsCount results.errors = errors // Publish the event ProxyEngineService.publish('vendor_upload.complete', results) return resolve(results) }) .catch(err => { errorsCount++ errors.push(err.message) results.errors_count = errorsCount results.errors = errors return resolve(results) }) }, error: (err, file) => { return reject(err) } } const fileString = fs.readFileSync(file, 'utf8') // Parse the CSV/TSV csvParser.parse(fileString, options) }) } /** * * @param row * @param uploadID */ csvVendorRow(row, uploadID) { const VendorUpload = this.app.orm.VendorUpload const values = _.values(VENDOR_UPLOAD) const keys = _.keys(VENDOR_UPLOAD) const upload = { upload_id: uploadID, options: {}, products: [] } _.each(row, (data, key) => { if (typeof(data) === 'undefined' || data === '') { row[key] = null } }) row = _.omitBy(row, _.isNil) if (_.isEmpty(row)) { return Promise.resolve({}) } _.each(row, (data, key) => { if (typeof(data) !== 'undefined' && data !== null && data !== '') { const i = values.indexOf(key.replace(/^\s+|\s+$/g, '')) const k = keys[i] if (i > -1 && k) { if (k == 'handle') { upload[k] = this.app.services.ProxyCartService.splitHandle(data.toString()) } else if (k == 'name') { upload[k] = data.toString().trim() } else if (k == 'products') { upload[k] = data.toString().split(',').map(product => { return product.trim()}) } else { upload[k] = data } } } }) upload.products = upload.products.map((handle, index) => { return { handle: handle } }) const newVendor = VendorUpload.build(upload) return newVendor.save() } /** * * @param uploadId * @returns {Promise} */ processVendorUpload(uploadId) { const VendorUpload = this.app.orm.VendorUpload let vendorsTotal = 0 const errors = [] return VendorUpload.batch({ where: { upload_id: uploadId } }, vendors => { const Sequelize = this.app.orm.Product.sequelize return Sequelize.Promise.mapSeries(vendors, vendor => { const create = { customer: { email: vendor.customer }, email: vendor.customer, status: vendor.status, shipping_address: {}, billing_address: {} } // Convert to normal object vendor = vendor instanceof this.app.orm['VendorUpload'] ? vendor.get({plain: true}) : vendor _.each(vendor, (value, key) => { if (key.indexOf('shipping_') > -1) { const newKey = key.replace('shipping_', '') if (value && value != '') { create.shipping_address[newKey] = value } } if (key.indexOf('billing_') > -1) { const newKey = key.replace('billing_', '') if (value && value !== '') { create.billing_address[newKey] = value } } }) if (_.isEmpty(create.shipping_address)) { delete create.shipping_address } if (_.isEmpty(create.billing_address)) { delete create.billing_address } return this.transformFromRow(create) .catch(err => { errors.push(err.message) return err }) }) .then(vendor => { if (!vendor) { return } else { // Calculate Totals vendorsTotal++ return vendor } }) }) .then(results => { return VendorUpload.destroy({where: {upload_id: uploadId }}) .catch(err => { errors.push(err.message) return err }) }) .then(destroyed => { const results = { upload_id: uploadId, vendors: vendorsTotal, errors: errors } this.app.services.ProxyEngineService.publish('vendor_process.complete', results) return results }) } transformFromRow(obj) { let resCustomer, resProducts const resVendor = this.app.orm['Vendor'].build() const Customer = this.app.orm['Customer'] return Customer.resolve(obj.customer, {create: true}) .then(customer => { resCustomer = customer return this.app.orm['Product'].findAll({ where: { handle: obj.products.map(product => product.handle) } }) }) .then(products => { resProducts = products return Promise.all(resProducts.map(item => { return this.app.services.ProductService.resolveItem(item) })) }) .then(resolvedItems => { return Promise.all(resolvedItems.map((item) => { // item = _.omit(item.get({plain: true}), [ // 'requires_vendor', // 'vendor_unit', // 'vendor_interval' // ]) return resVendor.addLine(item, 1, []) })) }) .then(resolvedItems => { resVendor.customer_id = resCustomer.id return resVendor.save() }) .then(vendor => { const event = { object_id: vendor.customer_id, object: 'customer', type: 'customer.vendor.created', message: 'Imported Vendor Created', data: vendor } this.app.services.ProxyEngineService.publish(event.type, event, {save: true}) return vendor }) } }