Skip to content

Commit

Permalink
[FIX] Type detection for UPC (UPC_E = EAN_8)
Browse files Browse the repository at this point in the history
  • Loading branch information
thalassa-web committed Jan 18, 2019
1 parent 0ab94d0 commit 3ef0d8b
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 30 deletions.
14 changes: 5 additions & 9 deletions src/__tests__/barcode-type-detector.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { BarcodeTypeDetector } from '../barcode-type-detector';
import {BarcodeTypeDetector} from '../barcode-type-detector';
import { BarcodeType } from '../enums';

test('EAN_13', () => {
test('EAN_13 Validation', () => {
expect(BarcodeTypeDetector.detect('3614950268099')).toBe(BarcodeType.EAN_13);
});

test('EAN_8', () => {
test('EAN_8 Validation', () => {
expect(BarcodeTypeDetector.detect('78635708')).toBe(BarcodeType.EAN_8);
});

test('UPC_A', () => {
expect(BarcodeTypeDetector.detect('012345678905')).toBe(BarcodeType.UPC_A);
});

test('UPC_E', () => {
expect(BarcodeTypeDetector.detect('8635709')).toBe(BarcodeType.UPC_E);
test('UPC_A Validation', () => {
expect(BarcodeTypeDetector.detect('123456789104')).toBe(BarcodeType.UPC_A);
});
39 changes: 18 additions & 21 deletions src/barcode-type-detector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,28 @@ const onlyDigitsRegexp = (length: number): RegExp => new RegExp(`^\\d{${length}}
*/
const isOnlyDigits = (value: string, length: number): boolean => onlyDigitsRegexp(length).test(value);
/**
* EAN control key system based on the Luhn formula
* Control key calculation
* @param value
*/
const eanKeyController = (value: string): boolean => {
const lastIndex = value.length - 1;
const getEanControlKey = (value: string): number => {
const sumCtrl = value
.slice(0, lastIndex)
.split('')
// Chars are only digits
.map(digit => parseInt(digit, 10))
// Each even char column index is multiply by 3
// And we make the sum
.reduce((acc, digit, index) => acc + (index % 2 ? digit : digit * 3), 0);
// The calculated control key has to be the same as the last char in value
return parseInt(value.slice(lastIndex), 10) === 10 - (sumCtrl % 10);
.slice(0, value.length - 1)
.split('')
// Chars are only digits
.map(digit => parseInt(digit, 10))
// Each even char column index is multiply by 3
// And we make the sum
.reduce((acc, digit, index) => acc + ((index % 2) ? digit : (digit * 3)), 0);
return 10 - (sumCtrl % 10);
};
/**
* UPC uses the same control key system as EAN but we have to add a 0 at the beginning of value
* EAN and UPC control key system based on the Luhn formula
* @param value
*/
const upcKeyController = (value: string): boolean => eanKeyController(`0${value}`);
const eanKeyController = (value: string): boolean => {
// The calculated control key has to be the same as the last char in value
return parseInt(value.slice(value.length - 1), 10) === getEanControlKey(value);
};
/**
* Is the value an EAN with specified length ?
* @param value
Expand All @@ -50,23 +51,19 @@ const isEan = (value: string, length: 8 | 13): boolean => isOnlyDigits(value, le
* @param value
* @param length
*/
const isUpc = (value: string, length: 7 | 12): boolean => isOnlyDigits(value, length) && upcKeyController(value);
const isUpc = (value: string): boolean => isOnlyDigits(value, 12) && eanKeyController(value);
/**
* EAN_13 = ONLY 13 digits + control key checking
*/
const ean13Definer: IBarcodeTypeDefiner = { method: value => isEan(value, 13), type: BarcodeType.EAN_13 };
/**
* UPC_A = ONLY 12 digits + control key checking
*/
const upcADefiner: IBarcodeTypeDefiner = { method: value => isUpc(value, 12), type: BarcodeType.UPC_A };
const upcADefiner: IBarcodeTypeDefiner = { method: value => isUpc(value), type: BarcodeType.UPC_A };
/**
* EAN_8 = ONLY 8 digits + control key checking
*/
const ean8Definer: IBarcodeTypeDefiner = { method: value => isEan(value, 8), type: BarcodeType.EAN_8 };
/**
* UPC_E = ONLY 7 digits + control key checking
*/
const upcEDefiner: IBarcodeTypeDefiner = { method: value => isUpc(value, 7), type: BarcodeType.UPC_E };
/**
* Detector of barcode type
*/
Expand All @@ -87,5 +84,5 @@ export class BarcodeTypeDetector {
/**
* List of definers
*/
private static readonly definers: IBarcodeTypeDefiner[] = [ean13Definer, upcADefiner, ean8Definer, upcEDefiner];
private static readonly definers: IBarcodeTypeDefiner[] = [ean13Definer, upcADefiner, ean8Definer];
}

0 comments on commit 3ef0d8b

Please sign in to comment.