UNPKG

@fye/aec-parser

Version:

Parsing of AEC files

178 lines (170 loc) 4.31 kB
const etl = require('etl'); const debug = require('debug')('parser:aec'); const { basename } = require('path'); const { headerFields, shippingFields, billingFields, itemFields, trailerFields, messageFields, } = require('./line-maps'); /** * assign value based on field and line element position * @param {Array} fields * @param {Array} lineTextList * @return {Object} */ const assignValues = (fields, lineTextList) => { const values = {}; fields.forEach((field, idx) => { if (field) { debug('field', field.name); const value = lineTextList[idx] || undefined; values[field.name] = field.type(value); } }); debug(values); return values; }; const layoutMap = { H: headerFields, B: billingFields, S: shippingFields, L: itemFields, T: trailerFields, M: messageFields, }; /** * Parses line using layout map * @param {String} line * @return {Object} */ const lineParser = line => { const lineTextList = line.text.replace(/"/g, '').split(','); debug(lineTextList); if (!layoutMap[lineTextList[0]]) { return undefined; } const fields = layoutMap[lineTextList[0]]; return assignValues(fields, lineTextList); }; /** * set order detail values by line type * line type is designated as first element in line array * @param {Object} opts * @param {String} opts.line unparsed line * @param {Object} opts.data data assigned by line mapping * @param {Object} opts.order an existing order * @param {String} opts.file file data origingated from * @return {Object} */ const setOrderDetail = ({ line, data, order, file }) => { const lineText = line.replace(/"/g, '').split(','); let completedOrder = null; /* eslint-disable no-param-reassign */ switch (lineText[0]) { case 'F': break; case 'H': // header order = data; order.totalShipped = 0; order.totalBackordered = 0; order.totalCancelled = 0; debug('i have a header'); break; case 'B': // billing order.billing = data; break; case 'S': // shipping order.shipping = data; break; case 'M': // message order.message = data; break; case 'L': // line if (order.items === undefined) { order.items = []; } // eslint-disable-next-line no-case-declarations const item = data; order.items.push(item); order.totalShipped += item.qtyShipped; order.totalBackordered += item.qtyBackordered; order.totalCancelled += item.qtyCancelled; break; case 'T': // trailer order.file = basename(file); if (order.totalShipped) { order.shipViaCode = data.shipViaCode; order.trackingNumber = data.trackingNum; order.shipDate = data.shipDate; order.shippingCost = data.retailerOrderTotal; } completedOrder = order; break; case 'E': break; case '': break; default: console.log(`No case for ${lineText[0]}`); console.log(lineText); break; } debug('here is the order', order); /* eslint-enable no-param-reassign */ return { order, completedOrder }; }; /** * parse file * @param {String} filename * @return {GenericTransformStream} */ function parseFile(filename) { debug('parsing file', filename); let currentOrder = null; let currentOrderLines = []; return etl .file(filename) .pipe(etl.split()) .pipe( etl.map(line => { const mappedLine = lineParser(line); if (line.text.indexOf('"F"') === 0 || line.text.indexOf('"E"') === 0) { return { orderLines: [line.text], }; } const set = setOrderDetail({ line: line.text, data: mappedLine, order: currentOrder, file: filename, }); currentOrder = set.order; currentOrderLines.push(line.text); if (set.completedOrder) { currentOrder = null; const orderObject = { order: set.completedOrder, orderLines: currentOrderLines, }; currentOrderLines = []; return orderObject; } return undefined; }), ); } module.exports = { lineParser, setOrderDetail, parseFile, };