@fabrix/spool-cart
Version:
Spool - eCommerce Spool for Fabrix
235 lines (234 loc) • 8.99 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const common_1 = require("@fabrix/fabrix/dist/common");
const csvParser = require("papaparse");
const _ = require("lodash");
const shortid = require("shortid");
const fs = require("fs");
const enums_1 = require("../../enums");
class VendorCsvService extends common_1.FabrixService {
publish(type, event, options = {}) {
if (this.app.services.EventsService) {
options.include = options.include || [{
model: this.app.models.EventItem.instance,
as: 'objects'
}];
return this.app.services.EventsService.publish(type, event, options);
}
this.app.log.debug('spool-events is not installed, please install it to use publish');
return Promise.resolve();
}
vendorCsv(file) {
console.time('csv');
const uploadID = shortid.generate();
const EventsService = this.app.services.EventsService;
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;
EventsService.count('VendorUpload', { where: { upload_id: uploadID } })
.then(count => {
results.vendors = count;
results.errors_count = errorsCount;
results.errors = errors;
EventsService.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');
csvParser.parse(fileString, options);
});
}
csvVendorRow(row, uploadID) {
const VendorUpload = this.app.models.VendorUpload;
const values = _.values(enums_1.VENDOR_UPLOAD);
const keys = _.keys(enums_1.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();
}
processVendorUpload(uploadId) {
const VendorUpload = this.app.models.VendorUpload;
let vendorsTotal = 0;
const errors = [];
return VendorUpload.batch({
where: {
upload_id: uploadId
}
}, vendors => {
const Sequelize = this.app.models.Product.sequelize;
return Sequelize.Promise.mapSeries(vendors, vendor => {
const create = {
customer: {
email: vendor.customer
},
email: vendor.customer,
status: vendor.status,
shipping_address: {},
billing_address: {}
};
vendor = vendor instanceof this.app.models['VendorUpload'].instance ? 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 {
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.EventsService.publish('vendor_process.complete', results);
return results;
});
}
transformFromRow(obj) {
let resCustomer, resProducts;
const resVendor = this.app.models['Vendor'].build();
const Customer = this.app.models['Customer'];
return Customer.resolve(obj.customer, { create: true })
.then(customer => {
resCustomer = customer;
return this.app.models['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) => {
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.publish(event.type, event, { save: true });
return vendor;
});
}
}
exports.VendorCsvService = VendorCsvService;