From b383328aedd131481bf77fdc8145aac4a1197bb9 Mon Sep 17 00:00:00 2001 From: Misaka_Company Date: Wed, 12 Aug 2026 14:48:23 +0800 Subject: [PATCH] feat(android): add FJ- attachment code type to CodeParser Co-Authored-By: Claude --- .../parts/registration_scan_part.dart | 1 + lib/services/code_parser.dart | 8 ++++ test/services/code_parser_test.dart | 46 +++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/lib/pages/registration/parts/registration_scan_part.dart b/lib/pages/registration/parts/registration_scan_part.dart index a57863a..d6491a7 100644 --- a/lib/pages/registration/parts/registration_scan_part.dart +++ b/lib/pages/registration/parts/registration_scan_part.dart @@ -45,6 +45,7 @@ extension _RegistrationScanPart on _RegistrationPageState { final parsed = CodeParser.parse(result.barcode); switch (parsed.type) { case CodeType.zongpaiNo: + case CodeType.attachmentCode: _handleZongpaiScan(parsed.value); case CodeType.locationNormal: case CodeType.locationTransit: diff --git a/lib/services/code_parser.dart b/lib/services/code_parser.dart index 3f63a9a..f667dd9 100644 --- a/lib/services/code_parser.dart +++ b/lib/services/code_parser.dart @@ -3,6 +3,9 @@ class CodeParser { static final _zongpaiRegex = RegExp(r'^\d{2}(B|C|T)\d+$|^\d{2}(BW|CW)\d{4}$'); static final _locationRegex = RegExp(r'^[A-Z0-9]+-[A-Z0-9]+-[A-Z0-9]+$'); static final _transitRegex = RegExp(r'^TRANS-'); + static final _attachmentRegex = RegExp( + r'^FJ-(\d{2}(B|C|T)\d+|\d{2}(BW|CW)\d{4})$', + ); static ParseResult parse(String code) { final trimmed = code.trim(); @@ -10,6 +13,10 @@ class CodeParser { return ParseResult(type: CodeType.invalid, value: code); } final normalized = trimmed.toUpperCase(); + if (_attachmentRegex.hasMatch(normalized)) { + final zongpai = normalized.substring(3); // strip "FJ-" + return ParseResult(type: CodeType.attachmentCode, value: zongpai); + } if (_transitRegex.hasMatch(normalized)) { return ParseResult(type: CodeType.locationTransit, value: normalized); } @@ -36,6 +43,7 @@ class CodeParser { enum CodeType { zongpaiNo, + attachmentCode, locationNormal, locationTransit, locationTempStorage, diff --git a/test/services/code_parser_test.dart b/test/services/code_parser_test.dart index 12c698d..9b68bab 100644 --- a/test/services/code_parser_test.dart +++ b/test/services/code_parser_test.dart @@ -62,4 +62,50 @@ void main() { expect(CodeParser.isLocation(CodeType.invalid), false); }); }); + + group('CodeParser.parse attachmentCode (FJ-)', () { + test('identifies FJ- with zongpai B type', () { + final result = CodeParser.parse('FJ-26B1'); + expect(result.type, CodeType.attachmentCode); + expect(result.value, '26B1'); + }); + test('identifies FJ- with zongpai C type', () { + final result = CodeParser.parse('FJ-26C12'); + expect(result.type, CodeType.attachmentCode); + expect(result.value, '26C12'); + }); + test('identifies FJ- with zongpai T type', () { + final result = CodeParser.parse('FJ-26T3'); + expect(result.type, CodeType.attachmentCode); + expect(result.value, '26T3'); + }); + test('identifies FJ- with zongpai BW 4-digit', () { + final result = CodeParser.parse('FJ-26BW0001'); + expect(result.type, CodeType.attachmentCode); + expect(result.value, '26BW0001'); + }); + test('identifies FJ- with zongpai CW 4-digit', () { + final result = CodeParser.parse('FJ-26CW0015'); + expect(result.type, CodeType.attachmentCode); + expect(result.value, '26CW0015'); + }); + test('normalizes lowercase fj- to uppercase', () { + final result = CodeParser.parse('fj-26b1'); + expect(result.type, CodeType.attachmentCode); + expect(result.value, '26B1'); + }); + test('rejects FJ without hyphen', () { + expect(CodeParser.parse('FJ26B1').type, CodeType.invalid); + }); + test('rejects FJ- with invalid zongpai', () { + expect(CodeParser.parse('FJ-HELLO').type, CodeType.invalid); + }); + test('rejects FJ- with BW short serial', () { + expect(CodeParser.parse('FJ-26BW01').type, CodeType.invalid); + }); + test('attaches original raw code with FJ- prefix for display', () { + final result = CodeParser.parse('FJ-26B42360'); + expect(result.value, '26B42360'); + }); + }); }