gs1-barcode-parser
Version:
The barcode parser is a library for handling the contents of GS1 barcodes.
1,059 lines (1,015 loc) • 61.2 kB
JavaScript
/**
* P. Brockfeld, 2014-02-05
*
* JavaScript for parsing GS1 barcodes, see
*
* https://github.com/hprange/BarcodeParser (active fork)
*
* https://github.com/PeterBrockfeld/BarcodeParser (original repo)
*
* for details.
*/
/**
*
* encapsulating the barcode parsing function in an anonymous, self-executing function
*/
var parseBarcode = (function () {
'use strict';
/**
* This is the main routine provided by the parseBarcode library. It takes a string,
* splices it from left to right into its elements and tries to parse it as an
* GS1 - element. If it succeeds, the result is returned as an object composed of
* an identifier and an array.It accepts
* @param {String} barcode is the contents of the barcode you'd like to get parsed
* @returns {Array} an array with elements which are objects of type "ParsedElement"
*/
function parseBarcode(barcode) {
var i = 0, // counter
fncChar = String.fromCharCode(29), // the ASCII "group separator"
barcodelength = barcode.length,
answer = {}, // the object to return
restOfBarcode = "", // the rest of the barcode, when first
// elements are spliced away
symbologyIdentifier = barcode.slice(0, 3),
firstElement = {};
//auxilliary functions
/**
* "ParsedElement" is the
*
* @constructor for ParsedElements, the components of the array returned by parseBarcode
* @param {String} elementAI the AI of the recognized element
* @param {String} elementDataTitle the title of the element, i.e. its short description
* @param {String} elementType a one-letter string describing the type of the element.
* allowed values are
* "S" for strings,
* "N" for numbers and
* "D" for dates
*/
function ParsedElement(elementAI, elementDataTitle, elementType) {
/* defines the object which represents a single element
*/
this.ai = elementAI; //application identifier
this.dataTitle = elementDataTitle; //title
switch (elementType) {
case "S":
this.data = ""; // the contents
break;
case "N":
this.data = 0;
break;
case "D":
this.data = new Date();
this.data.setHours(0, 0, 0, 0);
break;
default:
this.data = "";
break;
}
this.unit = ""; // some elements are accompaigned by an unit of
// measurement or currency
}
/**
*
* ================== BEGIN of identifyAI =======================
*
* does the main work:
* what AI is in the beginning of the restOfBarcode?
* If identified:
* which function to call with
* which parameters to parse the element?[Description]]
* @param {String} codestring a string; the function tries to
* identify an AI in the beginning of this string
* @returns {Object} if it succeeds in identifying an AI the
* ParsedElement is returned, together with the
* still unparsed rest of codestring.
*/
function identifyAI(codestring) {
// find first identifier. AIs have a minimum length of 2
// digits, some have 3, some even 4.
var firstNumber = codestring.slice(0, 1),
secondNumber = codestring.slice(1, 2),
thirdNumber = "",
fourthNumber = "",
codestringToReturn = "",
codestringLength = codestring.length,
elementToReturn = "";
/**
* ============ auxiliary functions for identifyAI =============
*/
/**
* some data items are followed by an FNC even in case of
* fixed length, so the codestringToReturn may have
* leading FNCs.
*
* This function eleminates these leading FNCs.
*
* @param {String} stringToClean string which has to be cleaned
* @returns {String} the cleaned string
*/
function cleanCodestring(stringToClean) {
//
var firstChar = stringToClean.slice(0, 1);
while (firstChar === fncChar) {
stringToClean = stringToClean.slice(1, stringToClean.length);
firstChar = stringToClean.slice(0, 1);
}
return stringToClean;
}
/**
* Used for calculating numbers which are given as string
* with a given number of fractional decimals.
*
* To avoid conversion errors binary <-> decimal I _don't_
* just divide by 10 numberOfFractionals times.
*/
function parseFloatingPoint(stringToParse, numberOfFractionals) {
var auxString = "",
offset = stringToParse.length - numberOfFractionals,
auxFloat = 0.0;
auxString = stringToParse.slice(0, offset) +
'.' +
stringToParse.slice(offset, stringToParse.length);
try {
auxFloat = parseFloat(auxString);
} catch (e36) {
throw "36";
}
return auxFloat;
}
/**
* ======== END of auxiliary function for identifyAI =======
*/
/**
*
* ======== BEGIN of parsing functions in identifyAI =======
*
* Some functions to parse the various GS1 formats. They
* create a new ParsedElement and set its properties.
*
* They all modify the variables "elementToReturn" and
* "codestringToReturn".
*/
/**
* dates in GS1-elements have the format "YYMMDD".
* This function generates a new ParsedElement and tries to fill a
* JS-date into the "data"-part.
* @param {String} ai the AI to use for the ParsedElement
* @param {String} title the title to use for the ParsedElement
*/
function parseDate(ai, title) {
elementToReturn = new ParsedElement(ai, title, "D");
var offSet = ai.length,
dateYYMMDD = codestring.slice(offSet, offSet + 6),
yearAsNumber = 0,
monthAsNumber = 0,
dayAsNumber = 0;
try {
yearAsNumber = parseInt(dateYYMMDD.slice(0, 2), 10);
} catch (e33) {
throw "33";
}
try {
monthAsNumber = parseInt(dateYYMMDD.slice(2, 4), 10);
} catch (e34) {
throw "34";
}
try {
dayAsNumber = parseInt(dateYYMMDD.slice(4, 6), 10);
} catch (e35) {
throw "35";
}
// we are in the 21st century, but section 7.12 of the specification
// states that years 51-99 should be considered to belong to the
// 20th century:
if (yearAsNumber > 50) {
yearAsNumber = yearAsNumber + 1900;
} else {
yearAsNumber = yearAsNumber + 2000;
}
if (dayAsNumber > 0) {
// Dates in Javascript are funny. Months start at 0. Days, on the other
// hand, start at 1. We need to decrement the month by 1. Otherwise,
// the date will be wrong by one month. E.g., month 11 and day 15
// become Dec 15th. If the day is equal to 0, however, we use a Javascript
// trick to turn the date into the last day of the previous month.
// So, e.g., month 11 and day 0 become Nov 30th.
monthAsNumber--;
}
elementToReturn.data.setFullYear(yearAsNumber, monthAsNumber, dayAsNumber);
codestringToReturn = codestring.slice(offSet + 6, codestringLength);
}
/**
* simple: the element has a fixed length AND is not followed by an FNC1.
* @param {String} ai the AI to use
* @param {String} title its title, i.e. its short description
* @param {Number} length the fixed length
*/
function parseFixedLength(ai, title, length) {
elementToReturn = new ParsedElement(ai, title, "S");
var offSet = ai.length;
elementToReturn.data = codestring.slice(offSet, length + offSet);
codestringToReturn = codestring.slice(length + offSet, codestringLength);
}
/**
* tries to parse an element of variable length
* some fixed length AIs are terminated by FNC1, so this function
* is used even for fixed length items
* @param {String} ai the AI to use
* @param {String} title its title, i.e. its short description
*/
function parseVariableLength(ai, title) {
//
elementToReturn = new ParsedElement(ai, title, "S");
var offSet = ai.length,
posOfFNC = codestring.indexOf(fncChar);
if (posOfFNC === -1) { //we've got the last element of the barcode
elementToReturn.data = codestring.slice(offSet, codestringLength);
codestringToReturn = "";
} else {
elementToReturn.data = codestring.slice(offSet, posOfFNC);
codestringToReturn = codestring.slice(posOfFNC + 1, codestringLength);
}
}
/**
* the place of the decimal fraction is given by the fourth number, that's
* the first after the identifier itself.
*
* All of theses elements have a length of 6 characters.
* @param {String} ai_stem the first digits of the AI, _not_ the fourth digit
* @param {Number} fourthNumber the 4th number indicating the count of valid fractionals
* @param {String} title the title of the AI
* @param {String} unit often these elements have an implicit unit of measurement
*/
function parseFixedLengthMeasure(ai_stem, fourthNumber, title, unit) {
//
elementToReturn = new ParsedElement(ai_stem + fourthNumber, title, "N");
var offSet = ai_stem.length + 1,
numberOfDecimals = parseInt(fourthNumber, 10),
numberPart = codestring.slice(offSet, offSet + 6);
elementToReturn.data = parseFloatingPoint(numberPart, numberOfDecimals);
elementToReturn.unit = unit;
codestringToReturn = codestring.slice(offSet + 6, codestringLength);
}
/**
* parses data elements of variable length, which additionally have
*
* - an indicator for the number of valid decimals
* - an implicit unit of measurement
*
* These data elements contain e.g. a weight or length.
*
*/
function parseVariableLengthMeasure(ai_stem, fourthNumber, title, unit) {
// the place of the decimal fraction is given by the fourth number, that's
// the first after the identifier itself.
elementToReturn = new ParsedElement(ai_stem + fourthNumber, title, "N");
var offSet = ai_stem.length + 1,
posOfFNC = codestring.indexOf(fncChar),
numberOfDecimals = parseInt(fourthNumber, 10),
numberPart = "";
if (posOfFNC === -1) {
numberPart = codestring.slice(offSet, codestringLength);
codestringToReturn = "";
} else {
numberPart = codestring.slice(offSet, posOfFNC);
codestringToReturn = codestring.slice(posOfFNC + 1, codestringLength);
}
// adjust decimals according to fourthNumber:
elementToReturn.data = parseFloatingPoint(numberPart, numberOfDecimals);
elementToReturn.unit = unit;
}
/**
* parses data elements of variable length, which additionally have
*
* - an indicator for the number of valid decimals
* - an explicit unit of measurement
*
* These data element contain amounts to pay or prices.
*
*/
function parseVariableLengthWithISONumbers(ai_stem, fourthNumber, title) {
// an element of variable length, representing a number, followed by
// some ISO-code.
elementToReturn = new ParsedElement(ai_stem + fourthNumber, title, "N");
var offSet = ai_stem.length + 1,
posOfFNC = codestring.indexOf(fncChar),
numberOfDecimals = parseInt(fourthNumber, 10),
isoPlusNumbers = "",
numberPart = "";
if (posOfFNC === -1) {
isoPlusNumbers = codestring.slice(offSet, codestringLength);
codestringToReturn = "";
} else {
isoPlusNumbers = codestring.slice(offSet, posOfFNC);
codestringToReturn = codestring.slice(posOfFNC + 1, codestringLength);
}
// cut off ISO-Code
numberPart = isoPlusNumbers.slice(3, isoPlusNumbers.length);
elementToReturn.data = parseFloatingPoint(numberPart, numberOfDecimals);
elementToReturn.unit = isoPlusNumbers.slice(0, 3);
}
/**
* parses data elements of variable length, which additionally have
*
* - an explicit unit of measurement or reference
*
* These data element contain countries, authorities within countries.
*
*/
function parseVariableLengthWithISOChars(ai_stem, title) {
// an element of variable length, representing a sequence of chars, followed by
// some ISO-code.
elementToReturn = new ParsedElement(ai_stem, title, "S");
var offSet = ai_stem.length,
posOfFNC = codestring.indexOf(fncChar),
isoPlusNumbers = "";
if (posOfFNC === -1) {
isoPlusNumbers = codestring.slice(offSet, codestringLength);
codestringToReturn = "";
} else {
isoPlusNumbers = codestring.slice(offSet, posOfFNC);
codestringToReturn = codestring.slice(posOfFNC + 1, codestringLength);
}
// cut off ISO-Code
elementToReturn.data = isoPlusNumbers.slice(3, isoPlusNumbers.length);
elementToReturn.unit = isoPlusNumbers.slice(0, 3);
}
/**
*
* ======== END of parsing functions in identifyAI =======
*
*/
/**
*
* ======= BEGIN of the big switch =======================
*
* and now a very big "switch", which tries to find a valid
* AI within the first digits of the codestring.
*
* See the documentation for an explanation why it is made
* this way (and not by some configuration file).
*/
switch (firstNumber) {
case "0":
switch (secondNumber) {
case "0":
// SSCC (Serial Shipping Container Code)
parseFixedLength("00", "SSCC", 18);
break;
case "1":
// Global Trade Item Number (GTIN)
parseFixedLength("01", "GTIN", 14);
break;
case "2":
// GTIN of Contained Trade Items
parseFixedLength("02", "CONTENT", 14);
break;
default:
throw "01";
}
break;
case "1":
switch (secondNumber) {
case "0":
// Batch or Lot Number
parseVariableLength("10", "BATCH/LOT");
break;
case "1":
// Production Date (YYMMDD)
parseDate("11", "PROD DATE");
break;
case "2":
// Due Date (YYMMDD)
parseDate("12", "DUE DATE");
break;
case "3":
// Packaging Date (YYMMDD)
parseDate("13", "PACK DATE");
break;
// AI "14" isn't defined
case "5":
// Best Before Date (YYMMDD)
parseDate("15", "BEST BEFORE or BEST BY");
break;
case "6":
// Sell By Date (YYMMDD)
parseDate("16", "SELL BY");
break;
case "7":
// Expiration Date (YYMMDD)
parseDate("17", "USE BY OR EXPIRY");
break;
default:
throw "02";
}
break;
case "2":
switch (secondNumber) {
case "0":
// Variant Number
parseFixedLength("20", "VARIANT", 2);
break;
case "1":
// Serial Number
parseVariableLength("21", "SERIAL");
break;
case "2":
// Consumer product variant
parseVariableLength("22", "CPV");
break;
// AI 23 is not defined
case "4":
// from now, the third number matters:
thirdNumber = codestring.slice(2, 3);
switch (thirdNumber) {
case "0":
// Additional Item Identification
parseVariableLength("240", "ADDITIONAL ID");
break;
case "1":
// Customer Part Number
parseVariableLength("241", "CUST. PART NO.");
break;
case "2":
// Made-to-Order Variation Number
parseVariableLength("242", "MTO VARIANT");
break;
case "3":
// Packaging Component Number
parseVariableLength("243", "PCN");
break;
default:
throw "03";
}
break;
case "5":
// from now, the third number matters:
thirdNumber = codestring.slice(2, 3);
switch (thirdNumber) {
case "0":
// Secondary Serial Number
parseVariableLength("250", "SECONDARY SERIAL");
break;
case "1":
// Reference to Source Entity
parseVariableLength("251", "REF. TO SOURCE");
break;
// AI "252" isn't defined
case "3":
// Global Document Type Identifier (GDTI)
parseVariableLength("253", "GDTI");
break;
case "4":
// GLN Extension Component
parseVariableLength("254", "GLN EXTENSION COMPONENT");
break;
case "5":
// Global Coupon Number (GCN)
parseVariableLength("255", "GCN");
break;
default:
throw "04";
}
break;
// AI "26" to "29" aren't defined
default:
throw "05";
}
break;
case "3":
switch (secondNumber) {
case "0":
// Count of Items (Variable Measure Trade Item)
parseVariableLength("30", "VAR. COUNT");
break;
case "1":
// third and fourth numbers matter:
thirdNumber = codestring.slice(2, 3);
fourthNumber = codestring.slice(3, 4);
switch (thirdNumber) {
case "0":
// Net weight, kilograms (Variable Measure Trade Item)
parseFixedLengthMeasure("310", fourthNumber, "NET WEIGHT (kg)", "KGM");
break;
case "1":
// Length or first dimension, metres (Variable Measure Trade Item)
parseFixedLengthMeasure("311", fourthNumber, "LENGTH (m)", "MTR");
break;
case "2":
// Width, diameter, or second dimension, metres (Variable Measure Trade Item)
parseFixedLengthMeasure("312", fourthNumber, "WIDTH (m)", "MTR");
break;
case "3":
// Depth, thickness, height, or third dimension, metres (Variable Measure Trade Item)
parseFixedLengthMeasure("313", fourthNumber, "HEIGHT (m)", "MTR");
break;
case "4":
// Area, square metres (Variable Measure Trade Item)
parseFixedLengthMeasure("314", fourthNumber, "AREA (m2)", "MTK");
break;
case "5":
// Net volume, litres (Variable Measure Trade Item)
parseFixedLengthMeasure("315", fourthNumber, "NET VOLUME (l)", "LTR");
break;
case "6":
// Net volume, cubic metres (Variable Measure Trade Item)
parseFixedLengthMeasure("316", fourthNumber, "NET VOLUME (m3)", "MTQ");
break;
default:
throw "06";
}
break;
case "2":
// third and fourth numbers matter:
thirdNumber = codestring.slice(2, 3);
fourthNumber = codestring.slice(3, 4);
switch (thirdNumber) {
case "0":
// Net weight, pounds (Variable Measure Trade Item)
parseFixedLengthMeasure("320", fourthNumber, "NET WEIGHT (lb)", "LBR");
break;
case "1":
// Length or first dimension, inches (Variable Measure Trade Item)
parseFixedLengthMeasure("321", fourthNumber, "LENGTH (i)", "INH");
break;
case "2":
// Length or first dimension, feet (Variable Measure Trade Item)
parseFixedLengthMeasure("322", fourthNumber, "LENGTH (f)", "FOT");
break;
case "3":
// Length or first dimension, yards (Variable Measure Trade Item)
parseFixedLengthMeasure("323", fourthNumber, "LENGTH (y)", "YRD");
break;
case "4":
// Width, diameter, or second dimension, inches (Variable Measure Trade Item)
parseFixedLengthMeasure("324", fourthNumber, "WIDTH (i)", "INH");
break;
case "5":
// Width, diameter, or second dimension, feet (Variable Measure Trade Item)
parseFixedLengthMeasure("325", fourthNumber, "WIDTH (f)", "FOT");
break;
case "6":
// Width, diameter, or second dimension, yards (Variable Measure Trade Item
parseFixedLengthMeasure("326", fourthNumber, "WIDTH (y)", "YRD");
break;
case "7":
// Depth, thickness, height, or third dimension, inches (Variable Measure Trade Item)
parseFixedLengthMeasure("327", fourthNumber, "HEIGHT (i)", "INH");
break;
case "8":
// Depth, thickness, height, or third dimension, feet (Variable Measure Trade Item)
parseFixedLengthMeasure("328", fourthNumber, "HEIGHT (f)", "FOT");
break;
case "9":
// Depth, thickness, height, or third dimension, yards (Variable Measure Trade Item)
parseFixedLengthMeasure("329", fourthNumber, "HEIGHT (y)", "YRD");
break;
default:
throw "07";
}
break;
case "3":
// third and fourth numbers matter:
thirdNumber = codestring.slice(2, 3);
fourthNumber = codestring.slice(3, 4);
switch (thirdNumber) {
case "0":
// Logistic weight, kilograms
parseFixedLengthMeasure("330", fourthNumber, "GROSS WEIGHT (kg)", "KGM");
break;
case "1":
// Length or first dimension, metres
parseFixedLengthMeasure("331", fourthNumber, "LENGTH (m), log", "MTR");
break;
case "2":
// Width, diameter, or second dimension, metres
parseFixedLengthMeasure("332", fourthNumber, "WIDTH (m), log", "MTR");
break;
case "3":
// Depth, thickness, height, or third dimension, metres
parseFixedLengthMeasure("333", fourthNumber, "HEIGHT (m), log", "MTR");
break;
case "4":
// Area, square metres
parseFixedLengthMeasure("334", fourthNumber, "AREA (m2), log", "MTK");
break;
case "5":
// Logistic volume, litres
parseFixedLengthMeasure("335", fourthNumber, "VOLUME (l), log", "LTR");
break;
case "6":
// Logistic volume, cubic metres
parseFixedLengthMeasure("336", fourthNumber, "VOLUME (m3), log", "MTQ");
break;
case "7":
// Kilograms per square metre, yes, the ISO code for this _is_ "28".
parseFixedLengthMeasure("337", fourthNumber, "KG PER m²", "28");
break;
default:
throw "08";
}
break;
case "4":
// third and fourth numbers matter:
thirdNumber = codestring.slice(2, 3);
fourthNumber = codestring.slice(3, 4);
switch (thirdNumber) {
case "0":
// Logistic weight, pounds
parseFixedLengthMeasure("340", fourthNumber, "GROSS WEIGHT (lb)", "LBR");
break;
case "1":
// Length or first dimension, inches
parseFixedLengthMeasure("341", fourthNumber, "LENGTH (i), log", "INH");
break;
case "2":
// Length or first dimension, feet
parseFixedLengthMeasure("342", fourthNumber, "LENGTH (f), log", "FOT");
break;
case "3":
// Length or first dimension, yards
parseFixedLengthMeasure("343", fourthNumber, "LENGTH (y), log", "YRD");
break;
case "4":
// Width, diameter, or second dimension, inches
parseFixedLengthMeasure("344", fourthNumber, "WIDTH (i), log", "INH");
break;
case "5":
// Width, diameter, or second dimension, feet
parseFixedLengthMeasure("345", fourthNumber, "WIDTH (f), log", "FOT");
break;
case "6":
// Width, diameter, or second dimension, yard
parseFixedLengthMeasure("346", fourthNumber, "WIDTH (y), log", "YRD");
break;
case "7":
// Depth, thickness, height, or third dimension, inches
parseFixedLengthMeasure("347", fourthNumber, "HEIGHT (i), log", "INH");
break;
case "8":
// Depth, thickness, height, or third dimension, feet
parseFixedLengthMeasure("348", fourthNumber, "HEIGHT (f), log", "FOT");
break;
case "9":
// Depth, thickness, height, or third dimension, yards
parseFixedLengthMeasure("349", fourthNumber, "HEIGHT (y), log", "YRD");
break;
default:
throw "09";
}
break;
case "5":
// third and fourth numbers matter:
thirdNumber = codestring.slice(2, 3);
fourthNumber = codestring.slice(3, 4);
switch (thirdNumber) {
case "0":
// Area, square inches (Variable Measure Trade Item)
parseFixedLengthMeasure("350", fourthNumber, "AREA (i2)", "INK");
break;
case "1":
// Area, square feet (Variable Measure Trade Item)
parseFixedLengthMeasure("351", fourthNumber, "AREA (f2)", "FTK");
break;
case "2":
// Area, square yards (Variable Measure Trade Item)
parseFixedLengthMeasure("352", fourthNumber, "AREA (y2)", "YDK");
break;
case "3":
// Area, square inches
parseFixedLengthMeasure("353", fourthNumber, "AREA (i2), log", "INK");
break;
case "4":
// Area, square feet
parseFixedLengthMeasure("354", fourthNumber, "AREA (f2), log", "FTK");
break;
case "5":
// Area, square yards
parseFixedLengthMeasure("355", fourthNumber, "AREA (y2), log", "YDK");
break;
case "6":
// Net weight, troy ounces (Variable Measure Trade Item)
parseFixedLengthMeasure("356", fourthNumber, "NET WEIGHT (t)", "APZ");
break;
case "7":
// Net weight (or volume), ounces (Variable Measure Trade Item)
parseFixedLengthMeasure("357", fourthNumber, "NET VOLUME (oz)", "ONZ");
break;
default:
throw "10";
}
break;
case "6":
// third and fourth numbers matter:
thirdNumber = codestring.slice(2, 3);
fourthNumber = codestring.slice(3, 4);
switch (thirdNumber) {
case "0":
// Net volume, quarts (Variable Measure Trade Item)
parseFixedLengthMeasure("360", fourthNumber, "NET VOLUME (q)", "QT");
break;
case "1":
// Net volume, gallons U.S. (Variable Measure Trade Item)
parseFixedLengthMeasure("361", fourthNumber, "NET VOLUME (g)", "GLL");
break;
case "2":
// Logistic volume, quarts
parseFixedLengthMeasure("362", fourthNumber, "VOLUME (q), log", "QT");
break;
case "3":
// Logistic volume, gallons U.S.
parseFixedLengthMeasure("363", fourthNumber, "VOLUME (g), log", "GLL");
break;
case "4":
// Net volume, cubic inches (Variable Measure Trade Item)
parseFixedLengthMeasure("364", fourthNumber, "VOLUME (i3)", "INQ");
break;
case "5":
// Net volume, cubic feet (Variable Measure Trade Item)
parseFixedLengthMeasure("365", fourthNumber, "VOLUME (f3)", "FTQ");
break;
case "6":
// Net volume, cubic yards (Variable Measure Trade Item)
parseFixedLengthMeasure("366", fourthNumber, "VOLUME (y3)", "YDQ");
break;
case "7":
// Logistic volume, cubic inches
parseFixedLengthMeasure("367", fourthNumber, "VOLUME (i3), log", "INQ");
break;
case "8":
// Logistic volume, cubic feet
parseFixedLengthMeasure("368", fourthNumber, "VOLUME (f3), log", "FTQ");
break;
case "9":
// Logistic volume, cubic yards
parseFixedLengthMeasure("369", fourthNumber, "VOLUME (y3), log", "YDQ");
break;
default:
throw "11";
}
break;
case "7":
// Count of Trade Items
parseVariableLength("37", "COUNT");
break;
// AI "38" isn't defined
case "9":
// third and fourth numbers matter:
thirdNumber = codestring.slice(2, 3);
fourthNumber = codestring.slice(3, 4);
switch (thirdNumber) {
case "0":
// Applicable Amount Payable, local currency
parseVariableLengthMeasure("390", fourthNumber, "AMOUNT", "");
break;
case "1":
// Applicable Amount Payable with ISO Currency Code
parseVariableLengthWithISONumbers("391", fourthNumber, "AMOUNT");
break;
case "2":
// Applicable Amount Payable, single monetary area (Variable Measure Trade Item)
parseVariableLengthMeasure("392", fourthNumber, "PRICE", "");
break;
case "3":
// Applicable Amount Payable with ISO Currency Code (Variable Measure Trade Item)
parseVariableLengthWithISONumbers("393", fourthNumber, "PRICE");
break;
default:
throw "12";
}
break;
default:
throw "13";
}
break;
case "4":
switch (secondNumber) {
case "0":
// third number matters:
thirdNumber = codestring.slice(2, 3);
switch (thirdNumber) {
case "0":
// Customer's Purchase Order Number
parseVariableLength("400", "ORDER NUMBER");
break;
case "1":
// Global Identification Number for Consignment (GINC)
parseVariableLength("401", "GINC");
break;
case "2":
// Global Shipment Identification Number (GSIN)
parseVariableLength("402", "GSIN"); // should be 17 digits long
break;
case "3":
// Routing Code
parseVariableLength("403", "ROUTE");
break;
default:
throw "14";
}
break;
case "1":
//third number matters:
thirdNumber = codestring.slice(2, 3);
switch (thirdNumber) {
case "0":
// Ship to - Deliver to Global Location Number
parseFixedLength("410", "SHIP TO LOC", 13);
break;
case "1":
// Bill to - Invoice to Global Location Number
parseFixedLength("411", "BILL TO", 13);
break;
case "2":
// Purchased from Global Location Number
parseFixedLength("412", "PURCHASE FROM", 13);
break;
case "3":
// Ship for - Deliver for - Forward to Global Location Number
parseFixedLength("413", "SHIP FOR LOC", 13);
break;
default:
throw "15";
}
break;
case "2":
//third number matters:
thirdNumber = codestring.slice(2, 3);
switch (thirdNumber) {
case "0":
// Ship to - Deliver to Postal Code Within a Single Postal Authority
parseVariableLength("420", "SHIP TO POST");
break;
case "1":
// Ship to - Deliver to Postal Code with ISO Country Code
parseVariableLengthWithISOChars("421", "SHIP TO POST");
break;
case "2":
// Country of Origin of a Trade Item
parseFixedLength("422", "ORIGIN", 3);
break;
case "3":
// Country of Initial Processing
// Up to 5 3-digit ISO-countrycodes
parseVariableLength("423", "COUNTRY - INITIAL PROCESS.");
break;
case "4":
// Country of Processing
parseFixedLength("424", "COUNTRY - PROCESS.", 3);
break;
case "5":
// Country of Disassembly
parseFixedLength("425", "COUNTRY - DISASSEMBLY", 3);
break;
case "6":
// Country Covering full Process Chain
parseFixedLength("426", "COUNTRY – FULL PROCESS", 3);
break;
case "7":
// Country Subdivision of Origin
parseVariableLength("427", "ORIGIN SUBDIVISION");
break;
default:
throw "16";
}
break;
default:
throw "17";
}
break;
// first digits 5 and 6 are not used
case "7":
switch (secondNumber) {
case "0":
//third and fourth number matter:
thirdNumber = codestring.slice(2, 3);
fourthNumber = codestring.slice(3, 4);
switch (thirdNumber) {
case "0":
switch (fourthNumber) {
case "1":
// NATO Stock Number (NSN)
parseVariableLength("7001", "NSN"); //should be 13 digits long
break;
case "2":
// UN/ECE Meat Carcasses and Cuts Classification
parseVariableLength("7002", "MEAT CUT");
break;
case "3":
// Expiration Date and Time
parseVariableLength("7003", "EXPIRY TIME"); //should be 10 digits long
break;
case "4":
// Active Potency
parseVariableLength("7004", "ACTIVE POTENCY");
break;
default:
throw "18";
}
break;
// 1 and 2 are not used
case "3":
// Approval Number of Processor with ISO Country Code
// Title and stem for parsing are build from 4th number:
parseVariableLengthWithISOChars("703" + fourthNumber, "PROCESSOR # " + fourthNumber);
break;
default:
throw "19";
}
break;
case "1":
thirdNumber = codestring.slice(2, 3);
switch (thirdNumber) {
case "0":
// National Healthcare Reimbursement Number (NHRN) – Germany PZN
parseVariableLength("710", "NHRN PZN");
break;
case "1":
// National Healthcare Reimbursement Number (NHRN) – France CIP
parseVariableLength("711", "NHRN CIP");
break;
case "2":
// National Healthcare Reimbursement Number (NHRN) – Spain CN
parseVariableLength("712", "NHRN CN");
break;
case "3":
// National Healthcare Reimbursement Number (NHRN) – Brasil DRN
parseVariableLength("713", "NHRN DRN");
break;
default:
throw "20";
}
break;
default:
throw "21";
}
break;
case "8":
switch (secondNumber) {
case "0":
thirdNumber = codestring.slice(2, 3);
fourthNumber = codestring.slice(3, 4);
switch (thirdNumber) {
case "0":
switch (fourthNumber) {
case "1":
// Roll Products (Width, Length, Core Diameter, Direction, Splices)
parseVariableLength("8001", "DIMENSIONS"); // should be 14 digits long
break;
case "2":
// Cellular Mobile Telephone Identifier
parseVariableLength("8002", "CMT No");
break;
case "3":
// Global Returnable Asset Identifier (GRAI)
parseVariableLength("8003", "GRAI"); // should contain at least 14 digits
break;
case "4":
// Global Individual Asset Identifier (GIAI)
parseVariableLength("8004", "GIAI");
break;
case "5":
// Price Per Unit of Measure
parseVariableLength("8005", "PRICE PER UNIT"); // should be 6 digits long
break;
case "6":
// Identification of the Components of a Trade Item
parseVariableLength("8006", "GCTIN"); // should be exactly 18 digits long
break;
case "7":
// International Bank Account Number (IBAN)
parseVariableLength("8007", "IBAN");
break;
case "8":
// Date and Time of Production
parseVariableLength("8008", "PROD TIME"); // should be exactly 12 digits long
break;
default:
throw "22";
}
break;
case "1":
switch (fourthNumber) {
case "0":
// Component / Part Identifier (CPID)
parseVariableLength("8010", "CPID");
break;
case "1":
// Component / Part Identifier Serial Number (CPID SERIAL)
parseVariableLength("8011", "CPID SERIAL");
break;
case "7":
// Global Service Relation Number to identify the relationship between an organisation offering services and the provider of services
parseVariableLength("8017", "GSRN - PROVIDER"); // should be 18 digits long
break;
case "8":
// Global Service Relation Number to identify the relationship between an organisation offering services and the recipient of services
parseVariableLength("8018", "GSRN - RECIPIENT"); // should be 18 digits long
break;
case "9":
// Service Relation Instance Number (SRIN)
parseVariableLength("8019", "SRIN");
break;
default:
throw "23";
}