From df434c93e2cb15973d165236f024f98fe7127317 Mon Sep 17 00:00:00 2001 From: Nathan Youngman Date: Fri, 10 Aug 2018 12:02:31 -0600 Subject: [PATCH] parse Canadian licenses --- spec/fixtures/canada.js | 21 +++++++++++++++++++++ spec/fixtures/index.js | 3 ++- spec/parseUsdl.spec.js | 14 +++++++++++++- spec/sample/data_3.js | 26 ++++++++++++++++++++++++++ spec/sample/data_4.js | 23 +++++++++++++++++++++++ spec/sample/index.js | 2 ++ src/keys.js | 4 ++++ src/parseUsdl.js | 38 +++++++++++++++++++++++++++++++------- 8 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 spec/fixtures/canada.js create mode 100644 spec/sample/data_3.js create mode 100644 spec/sample/data_4.js diff --git a/spec/fixtures/canada.js b/spec/fixtures/canada.js new file mode 100644 index 0000000..ae7c42a --- /dev/null +++ b/spec/fixtures/canada.js @@ -0,0 +1,21 @@ +exports.canada = { + 'addressCity': "YOUR CITY", + 'addressPostalCode': "A1B 2C3", + 'addressState': "AB", + 'addressStreet': "2345 ANYWHERE STREET", + 'dateOfBirth': '2000/08/31', + 'dateOfExpiry': '2022/08/31', + 'documentNumber': "123456-123", + 'eyeColor': "green", + 'hairColor': "blond", + 'firstName': "M", + 'givenName': "M Motorist", + 'height': "175 cm", + 'weightLb': "73 kg", + 'weightRange': "4", + 'jurisdictionVehicleClass': "5", + 'jurisdictionRestrictionCodes': "A", + 'lastName': "MICHAEL", + 'middleName': "Motorist", + 'sex': "M", +}; diff --git a/spec/fixtures/index.js b/spec/fixtures/index.js index bc4ffda..0ec21f3 100644 --- a/spec/fixtures/index.js +++ b/spec/fixtures/index.js @@ -1 +1,2 @@ -exports.default = require('./default').default; \ No newline at end of file +exports.default = require('./default').default; +exports.canada = require('./canada').canada; diff --git a/spec/parseUsdl.spec.js b/spec/parseUsdl.spec.js index 60fd7fe..2c37e33 100644 --- a/spec/parseUsdl.spec.js +++ b/spec/parseUsdl.spec.js @@ -1,22 +1,34 @@ const UsdlData1 = require('./sample/index').UsdlData1; const UsdlData2 = require('./sample/index').UsdlData2; +const UsdlData3 = require('./sample/index').UsdlData3; +const UsdlData4 = require('./sample/index').UsdlData4; const UsdlData_error = require('./sample/index').UsdlData_error; const UsdlData_invalid_characters = require('./sample/index').UsdlData_invalid_characters; const UsdlData_invalid_characters_2 = require('./sample/index').UsdlData_invalid_characters_2; const default_fixture = require('./fixtures').default; +const canada_fixture = require('./fixtures').canada; const parse = require("../index").parse; describe("USDL Parser", () => { it("should parse correct values", () => { const parsedData = parse(UsdlData1); - expect(parsedData).toEqual(default_fixture) + expect(parsedData).toEqual(default_fixture); }); it("should correctly identify female", () => { const parsedData = parse(UsdlData2); expect(parsedData.sex).toBe("F"); + }); + it("should correctly identify unspecified gender", () => { + const parsedData = parse(UsdlData3); + expect(parsedData.sex).toBe("X"); + }); + + it("should parse correct values", () => { + const parsedData = parse(UsdlData4); + expect(parsedData).toEqual(canada_fixture); }); it("should not throw error if invalid code is passed and warming suppress is on", () => { diff --git a/spec/sample/data_3.js b/spec/sample/data_3.js new file mode 100644 index 0000000..a803986 --- /dev/null +++ b/spec/sample/data_3.js @@ -0,0 +1,26 @@ +exports.UsdlData3 = `@ + +ANSI 636001070002DL00410392ZN04330047DLDCANONE +DCBNONE +DCDNONE +DBA08312013 +DCSMichael +DACM +DADMotorist +DBD08312013 +DBB08312013 +DBC9 +DAYBRO +DAU064 in +DAG2345 ANYWHERE STREET +DAIYOUR CITY +DAJNY +DAK123450000 +DAQNONE +DCFNONE +DCGUSA +DDEN +DDFN +DDGN +ZNZNAMDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5 +`; diff --git a/spec/sample/data_4.js b/spec/sample/data_4.js new file mode 100644 index 0000000..7f32744 --- /dev/null +++ b/spec/sample/data_4.js @@ -0,0 +1,23 @@ +exports.UsdlData4 = `@ + +ANSI 990876030001DLÊDLDCSMICHAEL +DCTM Motorist +DABMICHAEL +DACM +DADMotorist +DAG2345 ANYWHERE STREET +DAQ123456-123 +DAKA1B 2C3 +DAIYOUR CITY +DAJAB +DBCM +DBB20000831 +DAR5 +DATA +DBA20220831 +DAU175 cm +DAW73 kg +DCE4 +DAZblond +DAYgreen +`; diff --git a/spec/sample/index.js b/spec/sample/index.js index 0efef2c..e3c4a92 100644 --- a/spec/sample/index.js +++ b/spec/sample/index.js @@ -1,5 +1,7 @@ exports.UsdlData1 = require('./data_1').UsdlData1; exports.UsdlData2 = require('./data_2').UsdlData2; +exports.UsdlData3 = require('./data_3').UsdlData3; +exports.UsdlData4 = require('./data_4').UsdlData4; exports.UsdlData_error = require('./data_error').UsdlData_error; exports.UsdlData_invalid_characters = require('./data_invalid_characters').UsdlData_invalid_characters; exports.UsdlData_invalid_characters_2 = require('./data_invalid_characters_2').UsdlData_invalid_characters_2; diff --git a/src/keys.js b/src/keys.js index 5d16483..dec43d5 100644 --- a/src/keys.js +++ b/src/keys.js @@ -5,8 +5,10 @@ exports.CodeToKey = { DCD: 'jurisdictionEndorsementCodes', DBA: 'dateOfExpiry', DCS: 'lastName', + DAB: 'lastName', DAC: 'firstName', DAD: 'middleName', + DAR: 'jurisdictionVehicleClass', // License Classification Code DBD: 'dateOfIssue', DBB: 'dateOfBirth', DBC: 'sex', @@ -17,8 +19,10 @@ exports.CodeToKey = { DAJ: 'addressState', DAK: 'addressPostalCode', DAQ: 'documentNumber', + DAT: 'jurisdictionRestrictionCodes', // License Endorsements Code DCF: 'documentDiscriminator', DCG: 'issuer', + DCT: 'givenName', DDE: 'lastNameTruncated', DDF: 'firstNameTruncated', DDG: 'middleNameTruncated', diff --git a/src/parseUsdl.js b/src/parseUsdl.js index 73a3367..d96f449 100644 --- a/src/parseUsdl.js +++ b/src/parseUsdl.js @@ -4,12 +4,12 @@ const lineSeparator = "\n"; const defaultOptions = {suppressErrors: false}; -exports.parse = function parseCode128(str, options = defaultOptions) { +exports.parse = function parseDL(str, options = defaultOptions) { const props = {}; const rawLines = str.trim().split(lineSeparator); const lines = rawLines.map(rawLine => sanitizeData(rawLine)); let started; - lines.slice(0, -1).forEach(line => { + lines.forEach(line => { if (!started) { if (line.indexOf("ANSI ") === 0) { started = true; @@ -21,7 +21,7 @@ exports.parse = function parseCode128(str, options = defaultOptions) { let value = getValue(line); let key = getKey(code); if (!key) { - if (options.suppressErrors) { + if (options.suppressErrors || code === "ZNZ") { return; } else { throw new Error("unknown code: " + code); @@ -29,10 +29,19 @@ exports.parse = function parseCode128(str, options = defaultOptions) { } if (isSexField(code)) value = getSex(code, value); - - props[key] = isDateField(key) ? getDateFormat(value) : value; + props[key] = value; }); + // date format depends on issuer + const issuer = props["issuer"] || "CAN"; + const getDateFormat = issuer === "USA" ? getDateFormatUSA : getDateFormatCAN; + + for (let key in props) { + if (isDateField(key)) { + props[key] = getDateFormat(props[key]); + } + } + return props; }; @@ -44,11 +53,26 @@ const getKey = code => CodeToKey[code]; const isSexField = code => code === "DBC"; -const getSex = (code, value) => (value === "1" ? "M" : "F"); +const getSex = (code, value) => { + if (value === "1" || value === "M") { + return "M"; + } else if (value === "2" || value === "F") { + return "F"; + } + return "X"; +}; const isDateField = key => key.indexOf("date") === 0; -const getDateFormat = value => { +const getDateFormatUSA = value => { const parts = [value.slice(0, 2), value.slice(2, 4), value.slice(4)]; return parts.join("/"); }; + +const getDateFormatCAN = value => { + const parts = [value.slice(0, 4), value.slice(4, 6), value.slice(6)]; + return parts.join("/"); +}; + + +