Comparing version 1.0.2 to 1.0.3
@@ -0,1 +1,2 @@ | ||
module.exports.EntryAddenda = require('./lib/entry-addenda') | ||
module.exports.Entry = require('./lib/entry'); | ||
@@ -6,2 +7,1 @@ module.exports.Batch = require('./lib/batch'); | ||
module.exports.Validate = require('./lib/validate'); | ||
module.exports.EntryAddenda = require('./lib/entry-addenda') |
@@ -40,3 +40,3 @@ module.exports = { | ||
entryDetailSequenceNumber: { | ||
name: 'Entry Detail Sequnce Number', | ||
name: 'Entry Detail Sequence Number', | ||
width: 7, | ||
@@ -43,0 +43,0 @@ position: 5, |
@@ -7,3 +7,3 @@ // Entry | ||
let highLevelOverrides = ['addendaTypeCode', 'paymentRelatedInformation', 'addendaSequenceNumber', 'entryDetailSequnceNumber']; | ||
let highLevelOverrides = ['addendaTypeCode', 'paymentRelatedInformation', 'addendaSequenceNumber', 'entryDetailSequenceNumber']; | ||
@@ -27,4 +27,4 @@ function EntryAddenda(options) { | ||
if (options.entryDetailSequnceNumber) { | ||
this.fields.entryDetailSequnceNumber.value = options.entryDetailSequnceNumber.slice(0 - this.fields.entryDetailSequnceNumber.width); // last n digits. pass | ||
if (options.entryDetailSequenceNumber) { | ||
this.fields.entryDetailSequenceNumber.value = options.entryDetailSequenceNumber.slice(0 - this.fields.entryDetailSequenceNumber.width); // last n digits. pass | ||
} | ||
@@ -31,0 +31,0 @@ |
// Entry | ||
var _ = require('lodash'); | ||
var async = require('async'); | ||
var utils = require('./../utils'); | ||
var validate = require('./../validate'); | ||
const _ = require('lodash'); | ||
const async = require('async'); | ||
const utils = require('./../utils'); | ||
const validate = require('./../validate'); | ||
var highLevelOverrides = ['transactionCode','receivingDFI','checkDigit','DFIAccount','amount','idNumber','individualName','discretionaryData','addendaId','traceNumber']; | ||
const highLevelOverrides = ['transactionCode','receivingDFI','checkDigit','DFIAccount','amount','idNumber','individualName','discretionaryData','addendaId','traceNumber']; | ||
@@ -69,3 +69,3 @@ function Entry(options) { | ||
Entry.prototype.generateString = function(cb) { | ||
var self = this; | ||
let self = this; | ||
async.map(self._addendas, function(entryAddenda, done) { | ||
@@ -77,3 +77,3 @@ utils.generateString(entryAddenda.fields, function(string) { | ||
utils.generateString(self.fields, function(string) { | ||
cb([string].concat(addendaStrings).join('\n')); | ||
cb([string].concat(addendaStrings).join(utils.newLineChar())); | ||
}); | ||
@@ -80,0 +80,0 @@ }); |
'use strict'; | ||
// Create a new object, that prototypally inherits from the Error constructor. | ||
var nACHError = function(errorObj) { | ||
// Create a new object, that prototypal inherits from the Error constructor. | ||
let nACHError = function(errorObj) { | ||
this.name = 'nACHError['+errorObj.name+']' || 'nACHError'; | ||
@@ -5,0 +5,0 @@ this.message = errorObj.message || 'Uncaught nACHError'; |
@@ -1,2 +0,2 @@ | ||
var utils = require('../utils'); | ||
const utils = require('../utils'); | ||
@@ -3,0 +3,0 @@ // The date/time defaults are dynamic, so always create a new object |
@@ -7,181 +7,186 @@ // File | ||
let validate = require('../validate'); | ||
let highLevelOverrides = ['immediateDestination','immediateOrigin','fileCreationDate','fileCreationTime','fileIdModifier','immediateDestinationName','immediateOriginName','referenceCode']; | ||
let highLevelOverrides = ['immediateDestination', 'immediateOrigin', 'fileCreationDate', 'fileCreationTime', 'fileIdModifier', 'immediateDestinationName', 'immediateOriginName', 'referenceCode']; | ||
function File(options) { | ||
this._batches = []; | ||
this._batches = []; | ||
// Allow the batch header/control defaults to be overriden if provided | ||
this.header = options.header ? _.merge(options.header, require('./header')(), _.defaults) : require('./header')(); | ||
this.control = options.control ? _.merge(options.header, require('./control'), _.defaults) : _.cloneDeep(require('./control')); | ||
// Allow the batch header/control defaults to be overriden if provided | ||
this.header = options.header ? _.merge(options.header, require('./header')(), _.defaults) : require('./header')(); | ||
this.control = options.control ? _.merge(options.header, require('./control'), _.defaults) : _.cloneDeep(require('./control')); | ||
// Configure high-level overrides (these override the low-level settings if provided) | ||
utils.overrideLowLevel(highLevelOverrides, options, this); | ||
// Configure high-level overrides (these override the low-level settings if provided) | ||
utils.overrideLowLevel(highLevelOverrides, options, this); | ||
// This is done to make sure we have a 9-digit routing number | ||
if(options.immediateDestination) { | ||
if (options.immediateDestination) { | ||
this.header.immediateDestination.value = utils.computeCheckDigit(options.immediateDestination); | ||
} | ||
this._batchSequenceNumber = Number(options.batchSequenceNumber) || 0 | ||
this._batchSequenceNumber = Number(options.batchSequenceNumber) || 0 | ||
// Validate all values | ||
this._validate(); | ||
return this; | ||
// Validate all values | ||
this._validate(); | ||
return this; | ||
} | ||
File.prototype.get = function(field) { | ||
// If the header has the field, return the value | ||
if(this.header[field]) { | ||
return this.header[field]['value']; | ||
} | ||
File.prototype.get = function (field) { | ||
// If the control has the field, return the value | ||
if(this.control[field]) { | ||
return this.control[field]['value']; | ||
} | ||
// If the header has the field, return the value | ||
if (this.header[field]) { | ||
return this.header[field]['value']; | ||
} | ||
// If the control has the field, return the value | ||
if (this.control[field]) { | ||
return this.control[field]['value']; | ||
} | ||
} | ||
File.prototype.set = function(field, value) { | ||
File.prototype.set = function (field, value) { | ||
// If the header has the field, set the value | ||
if(this.header[field]) { | ||
this.header[field]['value'] = value; | ||
} | ||
// If the header has the field, set the value | ||
if (this.header[field]) { | ||
this.header[field]['value'] = value; | ||
} | ||
// If the control has the field, set the value | ||
if(this.control[field]) { | ||
this.control[field]['value'] = value; | ||
} | ||
// If the control has the field, set the value | ||
if (this.control[field]) { | ||
this.control[field]['value'] = value; | ||
} | ||
}; | ||
File.prototype._validate = function() { | ||
// Validate header field lengths | ||
validate.validateLengths(this.header); | ||
File.prototype._validate = function () { | ||
// Validate header data types | ||
validate.validateDataTypes(this.header); | ||
// Validate header field lengths | ||
validate.validateLengths(this.header); | ||
// Validate control field lengths | ||
validate.validateLengths(this.control); | ||
// Validate header data types | ||
validate.validateDataTypes(this.header); | ||
// Validate header data types | ||
validate.validateDataTypes(this.control); | ||
// Validate control field lengths | ||
validate.validateLengths(this.control); | ||
// Validate header data types | ||
validate.validateDataTypes(this.control); | ||
}; | ||
File.prototype.addBatch = function(batch) { | ||
// Set the batch number on the header and control records | ||
batch.header.batchNumber.value = this._batchSequenceNumber | ||
batch.control.batchNumber.value = this._batchSequenceNumber | ||
File.prototype.addBatch = function (batch) { | ||
// Increment the batchSequenceNumber | ||
++this._batchSequenceNumber | ||
// Set the batch number on the header and control records | ||
batch.header.batchNumber.value = this._batchSequenceNumber | ||
batch.control.batchNumber.value = this._batchSequenceNumber | ||
this._batches.push(batch); | ||
// Increment the batchSequenceNumber | ||
++this._batchSequenceNumber | ||
this._batches.push(batch); | ||
}; | ||
File.prototype.generatePaddedRows = function(rows, cb) { | ||
let paddedRows = ''; | ||
for(let i = 0; i < rows; i++) { | ||
paddedRows += utils.newLineChar() + utils.pad('', 94, '9'); | ||
} | ||
// Return control flow back by calling the callback function | ||
cb(paddedRows); | ||
File.prototype.generatePaddedRows = function (rows, cb) { | ||
let paddedRows = ''; | ||
for (let i = 0; i < rows; i++) { | ||
paddedRows += utils.newLineChar() + utils.pad('', 94, '9'); | ||
} | ||
// Return control flow back by calling the callback function | ||
cb(paddedRows); | ||
} | ||
File.prototype.generateBatches = function(done1) { | ||
File.prototype.generateBatches = function (done1) { | ||
let self = this; | ||
let result = ''; | ||
let result = ''; | ||
let rows = 2; | ||
let entryHash = 0; | ||
let addendaCount = 0; | ||
let totalDebit = 0; | ||
let totalCredit = 0; | ||
async.each(this._batches, function(batch, done2) { | ||
totalDebit += batch.control.totalDebit.value; | ||
totalCredit += batch.control.totalCredit.value; | ||
async.each(batch._entries, function(entry, done3) { | ||
entry.fields.traceNumber.value = ( entry.fields.traceNumber.value) ? entry.fields.traceNumber.value : self.header.immediateOrigin.value.slice(0,8) + utils.pad(addendaCount, 7, false, '0'); | ||
entryHash += Number(entry.fields.receivingDFI.value); | ||
let entryHash = 0; | ||
let addendaCount = 0; | ||
let totalDebit = 0; | ||
let totalCredit = 0; | ||
async.each(this._batches, function (batch, done2) { | ||
totalDebit += batch.control.totalDebit.value; | ||
totalCredit += batch.control.totalCredit.value; | ||
async.each(batch._entries, function (entry, done3) { | ||
entry.fields.traceNumber.value = (entry.fields.traceNumber.value ? entry.fields.traceNumber.value : self.header.immediateOrigin.value.slice(0, 8)) + utils.pad(addendaCount, 7, false, '0'); | ||
async.each(entry._addendas, function (addenda, done4) { | ||
addenda.fields.entryDetailSequenceNumber.value = entry.fields.traceNumber.value.slice(0 - addenda.fields.entryDetailSequenceNumber.width); | ||
done4() | ||
}) | ||
entryHash += Number(entry.fields.receivingDFI.value); | ||
// Increment the addenda and block count | ||
addendaCount++; | ||
addendaCount++; | ||
rows++; | ||
done3(); | ||
}, function(){ | ||
done3(); | ||
}, function () { | ||
// Only iterate and generate the batch if there is at least one entry in the batch | ||
if(batch._entries.length > 0) { | ||
if (batch._entries.length > 0) { | ||
// Increment the addendaCount of the batch | ||
self.control.batchCount.value++; | ||
// Increment the addendaCount of the batch | ||
self.control.batchCount.value++; | ||
// Bump the number of rows only for batches with at least one entry | ||
rows = rows + 2; | ||
// Generate the batch after we've added the trace numbers | ||
batch.generateString(function(batchString){ | ||
result += batchString + utils.newLineChar(); | ||
done2(); | ||
}); | ||
// Generate the batch after we've added the trace numbers | ||
batch.generateString(function (batchString) { | ||
result += batchString + utils.newLineChar(); | ||
done2(); | ||
}); | ||
} else { | ||
done2(); | ||
} | ||
}); | ||
}, function(){ | ||
self.control.totalDebit.value = totalDebit; | ||
self.control.totalCredit.value = totalCredit; | ||
}); | ||
}, function () { | ||
self.control.totalDebit.value = totalDebit; | ||
self.control.totalCredit.value = totalCredit; | ||
self.control.addendaCount.value = addendaCount; | ||
self.control.addendaCount.value = addendaCount; | ||
self.control.blockCount.value = utils.getNextMultiple(rows, 10) / 10; | ||
// Slice the 10 rightmost digits. | ||
self.control.entryHash.value = entryHash.toString().slice(-10); | ||
// Slice the 10 rightmost digits. | ||
self.control.entryHash.value = entryHash.toString().slice(-10); | ||
// Pass the result string as well as the number of rows back | ||
done1(result, rows); | ||
}); | ||
}); | ||
}; | ||
File.prototype.generateHeader = function(cb) { | ||
utils.generateString(this.header, function(string) { | ||
cb(string); | ||
}); | ||
File.prototype.generateHeader = function (cb) { | ||
utils.generateString(this.header, function (string) { | ||
cb(string); | ||
}); | ||
}; | ||
File.prototype.generateControl = function(cb) { | ||
utils.generateString(this.control, function(string) { | ||
cb(string); | ||
}); | ||
File.prototype.generateControl = function (cb) { | ||
utils.generateString(this.control, function (string) { | ||
cb(string); | ||
}); | ||
}; | ||
File.prototype.generateFile = function(cb) { | ||
let self = this; | ||
File.prototype.generateFile = function (cb) { | ||
let self = this; | ||
self.generateHeader(function(headerString) { | ||
self.generateBatches(function(batchString, rows) { | ||
self.generateControl(function(controlString) { | ||
self.generateHeader(function (headerString) { | ||
self.generateBatches(function (batchString, rows) { | ||
self.generateControl(function (controlString) { | ||
// These must be within this callback otherwise rows won't be calculated yet | ||
let paddedRows = utils.getNextMultipleDiff(rows, 10); | ||
let paddedRows = utils.getNextMultipleDiff(rows, 10); | ||
self.generatePaddedRows(paddedRows, function(paddedString) { | ||
cb(headerString + utils.newLineChar() + batchString + controlString + paddedString); | ||
}); | ||
}); | ||
}) | ||
}); | ||
self.generatePaddedRows(paddedRows, function (paddedString) { | ||
cb(headerString + utils.newLineChar() + batchString + controlString + paddedString); | ||
}); | ||
}); | ||
}) | ||
}); | ||
}; | ||
module.exports = File; |
@@ -1,2 +0,2 @@ | ||
var _ = require('lodash') | ||
let _ = require('lodash') | ||
, utils = require('./utils') | ||
@@ -16,3 +16,3 @@ , nACHError = require('./error') | ||
_.forEach(object, function(field) { | ||
// This check ensures a required field's value is not NaN, null, undefined or empty. Zero is valid, but the data type check will make sure any fields with 0 are numeric. | ||
// This check ensures a required field's value is not NaN, null, undefined or empty. Zero is valid, but the data type check will make sure any fields with zero are numeric. | ||
if(field.required === true && (_.isNaN(field.value) || _.isNull(field.value) || _.isUndefined(field.value) || field.value.toString().length === 0)) { | ||
@@ -111,3 +111,3 @@ throw new nACHError({ | ||
// Split the routing number into an array of numbers. `array` will look like this: `[2,8,1,0,8,1,4,7,9]`. | ||
// Split the routing number into an array of numbers. `Array` will look like this: `[2,8,1,0,8,1,4,7,9]`. | ||
array = routing.split('').map(Number); | ||
@@ -121,3 +121,3 @@ | ||
// Throw an error if the the result of `sum` modulo 10 is not zero. The value of `sum` must be a multiple of 10 to be a valid routing number. | ||
// Throw an error if the result of `sum` modulo 10 is not zero. The value of `sum` must be a multiple of 10 to be a valid routing number. | ||
if(sum % 10 !== 0) { | ||
@@ -124,0 +124,0 @@ throw new nACHError({ |
{ | ||
"name": "sp-nacha", | ||
"description": "NACHA file format is a set of instructions that, when uploaded into a bank portal, successfully initiates a batch of ACH payments. NACHA file format is the protocol for structuring those instructions in a way that successfully initiates the payments. NACHA is a highly customizable Node.js module exposing a high & low-level API for generating ACH files for use within the ACH network.", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"keywords": [ | ||
@@ -28,8 +28,8 @@ "Seerportal Nacha", | ||
"scripts": { | ||
"test": "SET NODE_ENV=test&& mocha --reporter spec --recursive" | ||
"test": "mocha --reporter spec --recursive" | ||
}, | ||
"dependencies": { | ||
"async": "^2.0.1", | ||
"lodash": "^4.14.1", | ||
"moment": "^2.14.1" | ||
"async": "^3.2.4", | ||
"lodash": "^4.17.21", | ||
"moment": "^2.29.4" | ||
}, | ||
@@ -36,0 +36,0 @@ "devDependencies": { |
# SP-NACH | ||
[![Node.js](https://github.com/pradeepvish1213/sp-nacha/actions/workflows/node.js.yml/badge.svg)](https://github.com/pradeepvish1213/sp-nacha/actions/workflows/node.js.yml) | ||
@@ -59,3 +60,3 @@ NACHA file format is a set of instructions that, when uploaded into a bank portal, successfully initiates a batch of ACH | ||
ACH specification requires you to fill in the remainder of the file with rows of 9s until the number of rows is a | ||
multiple of 10. Of course, nACH will handle all of this for you, but it's aways good to know why it's doing it. | ||
multiple of 10. Of course, nACH will handle all of this for you, but it's always good to know why it's doing it. | ||
@@ -153,3 +154,3 @@ ## File Anatomy | ||
Finally to generate the file & write it to a text file | ||
Finally, to generate the file & write it to a text file | ||
@@ -156,0 +157,0 @@ ```js |
@@ -64,2 +64,3 @@ let chai = require('chai') | ||
}).catch(error => { | ||
console.log('===========',error) | ||
expect(true).to.be.false; | ||
@@ -66,0 +67,0 @@ expect(error.message).to.equal('Successfully writing file.'); |
@@ -7,10 +7,10 @@ const Moment = require('moment') | ||
let data = [{ | ||
"id": 32, | ||
"id": 1, | ||
"immediateDestination": "325272306", | ||
"immediateOrigin": "041215663", | ||
"immediateDestinationName": "TONGASS FCU", | ||
"immediateDestinationName": "TONGA'S FCU", | ||
"immediateOriginName": "SUTTON BANK", | ||
"referenceCode": " ", | ||
"batchChildren": [{ | ||
"id": 32, | ||
"id": 1, | ||
"companyName": "SSA TREAS 310", | ||
@@ -26,3 +26,3 @@ "companyIdentification": "9101036669", | ||
"entryChildren": [{ | ||
"id": 32, | ||
"id": 1, | ||
"receivingDFI": "325272306", | ||
@@ -36,3 +36,3 @@ "DFIAccount": "1347569324910", | ||
"transactionType": "Credit", | ||
"paymentRelatedInformation": "N1GDTEYUNNA L SPEARS N1BETEYUNNA L SPEARS 34501116885" | ||
"paymentRelatedInformation": "N1YUNNAN L SPEARS N1YUNNAN L SPEARS 34501116885" | ||
}] | ||
@@ -42,7 +42,60 @@ }] | ||
let dataAddenda = [{ | ||
"id": 1, | ||
"immediateDestination": "011002725", | ||
"immediateOrigin": "011001726", | ||
"immediateDestinationName": "BERKSHIRE BANK", | ||
"immediateOriginName": "BROOKLINE BANK", | ||
"referenceCode": " ", | ||
"batchChildren": [{ | ||
"id": 1, | ||
"companyName": "FF4 US", | ||
"companyIdentification": "0", | ||
"serviceClassCode": "220", | ||
"standardEntryClassCode": "IAT", | ||
"companyDiscretionaryData": "FF4 US", | ||
"companyEntryDescription": "NA", | ||
"companyDescriptiveDate": Moment(NachaAimPoint.Utils.computeBusinessDay(8)).format('MMM D'), | ||
"effectiveEntryDate": Moment('2023-08-30 05:30:00').toDate(), | ||
"settlementDate": "2023-09-15 05:30:00", | ||
"originatingDFI": "011001726", | ||
"entryChildren": [{ | ||
"id": 1, | ||
"receivingDFI": "011002725", | ||
"DFIAccount": "2234532", | ||
"amount": "1000", | ||
"idNumber": "", | ||
"individualName": "Sandeep", | ||
"discretionaryData": " ", | ||
"transactionCode": "22", | ||
"transactionType": "Credit", | ||
"addendaRecords": [{ | ||
"payment_related_information": "ANN000000000000100000928383-23939 XYZ Enterprises" | ||
}, { | ||
"payment_related_information": "XYZ Solutions 15 East Place Street" | ||
}, { | ||
"payment_related_information": "SmithTown*PA\\ US*19306\\" | ||
}, { | ||
"payment_related_information": "Citibank 01231380104 US" | ||
}, { | ||
"payment_related_information": "Standard Bank 01121042882 CA" | ||
}, { | ||
"payment_related_information": "9874654932139872122 Front Street" | ||
}, { | ||
"payment_related_information": "BetterTown*AB\\ CA*80015\\" | ||
}, { | ||
"payment_related_information": "Another international payment" | ||
}, { | ||
"payment_related_information": "Bank of Canada 01456456456987988 CA" | ||
}] | ||
}] | ||
}], | ||
"recordCount": 1 | ||
}] | ||
async function GenerateAchFile(queuedTransaction = [], fileFullPath = './') { | ||
return new Promise((resolve, reject) => { | ||
let totalRunsFile = []; | ||
queuedTransaction = queuedTransaction.length > 0 ? queuedTransaction : data; | ||
queuedTransaction = queuedTransaction.length > 0 ? queuedTransaction : dataAddenda; | ||
queuedTransaction.forEach(({batchChildren, id, ...restField}) => { | ||
@@ -58,3 +111,3 @@ try { | ||
let batch = new NachaAimPoint.Batch(restField); | ||
entryChildren.forEach(({transactionType, paymentRelatedInformation, id, ...entry}) => { | ||
entryChildren.forEach(({transactionType, addendaRecords, id, ...entry}) => { | ||
if (transactionType === 'Credit') { | ||
@@ -68,7 +121,9 @@ totalCreditAmount = totalCreditAmount + parseInt(entry.amount) | ||
let entryRecord = new NachaAimPoint.Entry(entry); | ||
if (paymentRelatedInformation) { | ||
let addenda = new NachaAimPoint.EntryAddenda({ | ||
paymentRelatedInformation | ||
}); | ||
entryRecord.addAddenda(addenda); | ||
if (addendaRecords && addendaRecords.length > 0) { | ||
addendaRecords.forEach(addenda => { | ||
let addendaEntry = new NachaAimPoint.EntryAddenda({ | ||
paymentRelatedInformation: addenda.payment_related_information | ||
}); | ||
entryRecord.addAddenda(addendaEntry); | ||
}) | ||
} | ||
@@ -93,4 +148,3 @@ batch.addEntry(entryRecord); | ||
totalRunsFile.push({ | ||
message: error.message ? error.message : error.stack, | ||
error: true | ||
message: error.message ? error.message : error.stack, error: true | ||
}) | ||
@@ -130,5 +184,3 @@ return reject(totalRunsFile) | ||
return reject({ | ||
row_id: id, | ||
message: error.message ? error.message : error.stack, | ||
error: true | ||
row_id: id, message: error.message ? error.message : error.stack, error: true | ||
}) | ||
@@ -135,0 +187,0 @@ } |
@@ -15,3 +15,3 @@ let chai = require('chai'), | ||
}); | ||
describe('GenerateString', function(){ | ||
@@ -30,3 +30,3 @@ it("Test to see if object can be passed", function(){ | ||
}; | ||
expect( function() { utils.generateString(testObj) }).not.to.throw('Not passing object correctly.'); | ||
@@ -42,6 +42,6 @@ }); | ||
if(dateNum === date) { expect(function() { utils.formatDate }).not.to.throw('Dates match'); } | ||
if(dateNum === date) { expect(function() { utils.formatDate }).not.to.throw('Dates match'); } | ||
// The formatDate() function never throws an error -- this test isn't accurate | ||
//else { expect(function() { utils.formatDate }).to.throw('Dates don\'t match');} | ||
//else { expect(function() { utils.formatDate }).to.throw('Dates don\'t match');} | ||
@@ -62,3 +62,3 @@ }); | ||
if(utilsTime === time) { expect(function() { utils.formatTime }).not.to.throw('Times match'); } | ||
// The formatTime() function never throws an error -- this test isn't accurate | ||
@@ -65,0 +65,0 @@ //else { expect(function() { utils.formatTime }).to.throw('Times don\'t match.') } |
@@ -44,3 +44,3 @@ let chai = require('chai') | ||
// The expect should not throw an error since the field is not required so an empty string is okay. | ||
// To expect should not throw an error since the field is not required so an empty string is okay. | ||
expect(function () { validate.validateRequiredFields(testObjectOne) }).not.to.throw('fieldOne is a required field but its value is: '); | ||
@@ -162,3 +162,3 @@ }); | ||
}); | ||
describe('Service Class Codes', function(){ | ||
@@ -165,0 +165,0 @@ it('must be valid ACH codes', function(){ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
75693
28
1645
199
+ Addedasync@3.2.6(transitive)
- Removedasync@2.6.4(transitive)
Updatedasync@^3.2.4
Updatedlodash@^4.17.21
Updatedmoment@^2.29.4