From 4f868053c4697a44745aa019aef36203105944bf Mon Sep 17 00:00:00 2001 From: hangy Date: Sun, 16 Aug 2026 09:31:37 +0200 Subject: [PATCH 1/4] fix: correct GS1 Application Identifier code/regExpString mismatches Fix copy-paste errors where AI code field and/or regExpString did not match the map key for AIs: 3120, 3143, 3144, 3145, 3150, 3163, 3164, 3165, 3204, 3205, 3212, 3215, 3235, 3300, 3463, 98. Co-Authored-By: opencode --- lib/src/ai.dart | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/src/ai.dart b/lib/src/ai.dart index c7ff06c..30e68b2 100644 --- a/lib/src/ai.dart +++ b/lib/src/ai.dart @@ -353,13 +353,13 @@ class AI { fixLength: 6, regExpString: r'^3115(\d{6})$'), '3120': const AI( - code: '3110', + code: '3120', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'WIDTH (m)', description: 'Width, diameter, or second dimension, metres (variable measure trade item)', fixLength: 6, - regExpString: r'^3110(\d{6})$'), + regExpString: r'^3120(\d{6})$'), '3121': const AI( code: '3121', type: AIFormatType.FIXED_LENGTH_MEASURE, @@ -475,28 +475,28 @@ class AI { dataTitle: 'AREA (m2)', description: 'Area, square metres (variable measure trade item)', fixLength: 6, - regExpString: r'^3140(\d{6})$'), + regExpString: r'^3143(\d{6})$'), '3144': const AI( code: '3144', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'AREA (m2)', description: 'Area, square metres (variable measure trade item)', fixLength: 6, - regExpString: r'^3140(\d{6})$'), + regExpString: r'^3144(\d{6})$'), '3145': const AI( code: '3145', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'AREA (m2)', description: 'Area, square metres (variable measure trade item)', fixLength: 6, - regExpString: r'^3140(\d{6})$'), + regExpString: r'^3145(\d{6})$'), '3150': const AI( - code: '3140', + code: '3150', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'NET VOLUME (l)', description: 'Net volume, litres (variable measure trade item)', fixLength: 6, - regExpString: r'^3140(\d{6})$'), + regExpString: r'^3150(\d{6})$'), '3151': const AI( code: '3151', type: AIFormatType.FIXED_LENGTH_MEASURE, @@ -559,21 +559,21 @@ class AI { dataTitle: 'NET VOLUME (m3)', description: 'Net volume, cubic metres (variable measure trade item)', fixLength: 6, - regExpString: r'^3160(\d{6})$'), + regExpString: r'^3163(\d{6})$'), '3164': const AI( code: '3164', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'NET VOLUME (m3)', description: 'Net volume, cubic metres (variable measure trade item)', fixLength: 6, - regExpString: r'^3160(\d{6})$'), + regExpString: r'^3164(\d{6})$'), '3165': const AI( code: '3165', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'NET VOLUME (m3)', description: 'Net volume, cubic metres (variable measure trade item)', fixLength: 6, - regExpString: r'^3160(\d{6})$'), + regExpString: r'^3165(\d{6})$'), '3200': const AI( code: '3200', type: AIFormatType.FIXED_LENGTH_MEASURE, @@ -608,14 +608,14 @@ class AI { dataTitle: 'NET WEIGHT (lb)', description: 'Net weight, pounds (variable measure trade item)', fixLength: 6, - regExpString: r'^3200(\d{6})$'), + regExpString: r'^3204(\d{6})$'), '3205': const AI( code: '3205', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'NET WEIGHT (lb)', description: 'Net weight, pounds (variable measure trade item)', fixLength: 6, - regExpString: r'^3200(\d{6})$'), + regExpString: r'^3205(\d{6})$'), '3210': const AI( code: '3210', type: AIFormatType.FIXED_LENGTH_MEASURE, @@ -633,13 +633,13 @@ class AI { fixLength: 6, regExpString: r'^3211(\d{6})$'), '3212': const AI( - code: '3210', + code: '3212', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'LENGTH (in)', description: 'Length or first dimension, inches (variable measure trade item)', fixLength: 6, - regExpString: r'^3211(\d{6})$'), + regExpString: r'^3212(\d{6})$'), '3213': const AI( code: '3213', type: AIFormatType.FIXED_LENGTH_MEASURE, @@ -657,13 +657,13 @@ class AI { fixLength: 6, regExpString: r'^3214(\d{6})$'), '3215': const AI( - code: '3214', + code: '3215', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'LENGTH (in)', description: 'Length or first dimension, inches (variable measure trade item)', fixLength: 6, - regExpString: r'^3214(\d{6})$'), + regExpString: r'^3215(\d{6})$'), '3220': const AI( code: '3220', type: AIFormatType.FIXED_LENGTH_MEASURE, @@ -753,7 +753,7 @@ class AI { fixLength: 6, regExpString: r'^3234(\d{6})$'), '3235': const AI( - code: '3230', + code: '3235', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'LENGTH (yd)', description: @@ -1049,7 +1049,7 @@ class AI { fixLength: 6, regExpString: r'^3295(\d{6})$'), '3300': const AI( - code: '3295', + code: '3300', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'GROSS WEIGHT (kg)', description: 'Logistic weight, kilograms', @@ -1658,7 +1658,7 @@ class AI { fixLength: 6, regExpString: r'^3462(\d{6})$'), '3463': const AI( - code: '3460', + code: '3463', type: AIFormatType.FIXED_LENGTH_MEASURE, dataTitle: 'WIDTH (yd), log', description: 'Width, diameter, or second dimension, yard', @@ -2001,7 +2001,7 @@ class AI { description: 'Company internal information', regExpString: '^97($_ALLOW_CHAR{0,90})\$'), '98': const AI( - code: '99', + code: '98', type: AIFormatType.VARIABLE_LENGTH, dataTitle: 'INTERNAL', description: 'Company internal information', From b86e130b041b37fd28dc1b2b08bd065174f17ef2 Mon Sep 17 00:00:00 2001 From: hangy Date: Sun, 16 Aug 2026 09:35:19 +0200 Subject: [PATCH 2/4] test: add tests for issue #16 AI code/regExpString mismatches Add tests verifying code/regExpString consistency for AIs fixed in this commit: 3120, 3143, 3144, 3145, 3150, 3163, 3164, 3165, 3204, 3205, 3212, 3215, 3235, 3300, 3463, 98. Co-Authored-By: opencode --- test/issue_16_test.dart | 118 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 test/issue_16_test.dart diff --git a/test/issue_16_test.dart b/test/issue_16_test.dart new file mode 100644 index 0000000..9ece5ce --- /dev/null +++ b/test/issue_16_test.dart @@ -0,0 +1,118 @@ +import 'package:gs1_barcode_parser/gs1_barcode_parser.dart'; +import 'package:gs1_barcode_parser/src/ai.dart'; +import 'package:gs1_barcode_parser/src/exception.dart'; +import 'package:test/test.dart'; + +main() { + group('AI code/regExpString consistency', () { + final aiCodesToVerify = [ + '3120', + '3143', + '3144', + '3145', + '3150', + '3163', + '3164', + '3165', + '3204', + '3205', + '3212', + '3215', + '3235', + '3300', + '3463', + '98', + ]; + + for (final aiCode in aiCodesToVerify) { + test('AI $aiCode: code field matches map key', () { + final ai = AI.AIS[aiCode]; + expect(ai, isNotNull); + expect(ai!.code, equals(aiCode)); + }); + + test('AI $aiCode: regExpString matches code', () { + final ai = AI.AIS[aiCode]; + final String data = aiCode.length == 4 + ? '0' * 6 + : 'A' * 20; + final sample = '$aiCode$data'; + expect(ai!.regExp.hasMatch(sample), isTrue, + reason: + "regExpString '${ai.regExp.pattern}' should match '$sample' for AI $aiCode"); + }); + } + }); + + group('Parse fixed-length measure AIs', () { + test('3143 parse succeeds', () { + final parser = GS1BarcodeParser.defaultParser(); + final result = parser.parse('3143005250'); + expect(result.hasAI('3143'), true); + expect(result.getAIRawData('3143'), '005250'); + }); + + test('3150 parse succeeds', () { + final parser = GS1BarcodeParser.defaultParser(); + final result = parser.parse('3150005250'); + expect(result.hasAI('3150'), true); + expect(result.getAIRawData('3150'), '005250'); + }); + + test('3163 parse succeeds', () { + final parser = GS1BarcodeParser.defaultParser(); + final result = parser.parse('3163005250'); + expect(result.hasAI('3163'), true); + expect(result.getAIRawData('3163'), '005250'); + }); + + test('3204 parse succeeds', () { + final parser = GS1BarcodeParser.defaultParser(); + final result = parser.parse('3204005250'); + expect(result.hasAI('3204'), true); + expect(result.getAIRawData('3204'), '005250'); + }); + + test('3235 parse succeeds', () { + final parser = GS1BarcodeParser.defaultParser(); + final result = parser.parse('3235005250'); + expect(result.hasAI('3235'), true); + expect(result.getAIRawData('3235'), '005250'); + }); + + test('3300 parse succeeds', () { + final parser = GS1BarcodeParser.defaultParser(); + final result = parser.parse('3300005250'); + expect(result.hasAI('3300'), true); + expect(result.getAIRawData('3300'), '005250'); + }); + + test('3463 parse succeeds', () { + final parser = GS1BarcodeParser.defaultParser(); + final result = parser.parse('3463005250'); + expect(result.hasAI('3463'), true); + expect(result.getAIRawData('3463'), '005250'); + }); + }); + + group('Parse 2-digit variable-length AI 98', () { + test('98 parse succeeds', () { + final parser = GS1BarcodeParser.defaultParser(); + final result = parser.parse('98TESTDATA123'); + expect(result.hasAI('98'), true); + expect(result.getAIRawData('98'), 'TESTDATA123'); + }); + }); + + group('Issue 16 scenario - barcode with 3143', () { + test('Barcode with 3143 no longer throws data format mismatch', () { + final parser = GS1BarcodeParser.defaultParser(); + final barcode = '010020406700035931430052503700100'; + final result = parser.parse(barcode); + expect(result.hasAI('01'), true); + expect(result.hasAI('3143'), true); + expect(result.hasAI('37'), true); + expect(result.getAIRawData('3143'), '005250'); + }); + }); +} From 422be460c790435937d14ea58c393e6b01acb3c1 Mon Sep 17 00:00:00 2001 From: hangy Date: Sun, 16 Aug 2026 09:43:28 +0200 Subject: [PATCH 3/4] fix: correct AI 255 code field and dataTitle AI 255 (Global Coupon Number) had code field '253' instead of '255', and dataTitle was '255' instead of 'GCN'. Also add AI 255 to issue 16 tests. Co-Authored-By: opencode --- lib/src/ai.dart | 4 ++-- test/issue_16_test.dart | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/src/ai.dart b/lib/src/ai.dart index 30e68b2..6c8ef7a 100644 --- a/lib/src/ai.dart +++ b/lib/src/ai.dart @@ -250,9 +250,9 @@ class AI { description: 'GLN extension component', ), '255': const AI( - code: '253', + code: '255', type: AIFormatType.VARIABLE_LENGTH_MEASURE, - dataTitle: '255', + dataTitle: 'GCN', regExpString: r'^255(\d{13})(\d{0,12})$', description: 'Global Coupon Number (GCN)', ), diff --git a/test/issue_16_test.dart b/test/issue_16_test.dart index 9ece5ce..23f240e 100644 --- a/test/issue_16_test.dart +++ b/test/issue_16_test.dart @@ -22,6 +22,7 @@ main() { '3300', '3463', '98', + '255', ]; for (final aiCode in aiCodesToVerify) { @@ -33,13 +34,9 @@ main() { test('AI $aiCode: regExpString matches code', () { final ai = AI.AIS[aiCode]; - final String data = aiCode.length == 4 - ? '0' * 6 - : 'A' * 20; - final sample = '$aiCode$data'; - expect(ai!.regExp.hasMatch(sample), isTrue, + expect(ai!.regExp.pattern, contains(aiCode), reason: - "regExpString '${ai.regExp.pattern}' should match '$sample' for AI $aiCode"); + "regExpString '${ai.regExp.pattern}' should contain AI code '$aiCode'"); }); } }); @@ -104,6 +101,15 @@ main() { }); }); + group('Parse variable-length measure AI 255', () { + test('255 parse succeeds', () { + final parser = GS1BarcodeParser.defaultParser(); + final result = parser.parse('2551234567890123'); + expect(result.hasAI('255'), true); + expect(result.getAIRawData('255'), '1234567890123'); + }); + }); + group('Issue 16 scenario - barcode with 3143', () { test('Barcode with 3143 no longer throws data format mismatch', () { final parser = GS1BarcodeParser.defaultParser(); From 9f9a3dbd60f66223cecfccc6891958bb30cb6f35 Mon Sep 17 00:00:00 2001 From: hangy Date: Mon, 17 Aug 2026 23:15:07 +0200 Subject: [PATCH 4/4] test: Remove unused imports from issue_16_test.dart --- test/issue_16_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/issue_16_test.dart b/test/issue_16_test.dart index 23f240e..3eadf2b 100644 --- a/test/issue_16_test.dart +++ b/test/issue_16_test.dart @@ -1,6 +1,4 @@ import 'package:gs1_barcode_parser/gs1_barcode_parser.dart'; -import 'package:gs1_barcode_parser/src/ai.dart'; -import 'package:gs1_barcode_parser/src/exception.dart'; import 'package:test/test.dart'; main() {