parse static method
Parses raw text extracted from bank cheque OCR scan into BankChequeInfo.
Implementation
static BankChequeInfo parse(String rawText) {
final cleanedText = rawText.replaceAll('\r', '').trim();
final lines = cleanedText.split('\n');
String rawMicrLine = '';
for (final line in lines) {
if (line.contains('c') || line.contains('a') || line.contains('⑈') || line.contains('⑆') || RegExp(r'[0-9]{6}.*[0-9]{9}').hasMatch(line)) {
rawMicrLine = line;
break;
}
}
if (rawMicrLine.isEmpty && lines.isNotEmpty) {
rawMicrLine = lines.last;
}
// 1. Extract Cheque Number (6 digits)
String chequeNumber = '000000';
final chequeMatch = _chequeNumRegex.firstMatch(cleanedText);
if (chequeMatch != null) {
chequeNumber = chequeMatch.group(1)!;
}
// 2. Extract MICR Routing Number (9 digits)
String routingNumber = '000000000';
final routingMatch = _routingRegex.firstMatch(cleanedText);
if (routingMatch != null) {
routingNumber = routingMatch.group(1)!;
} else {
final plain9 = RegExp(r'\b([0-9]{9})\b').firstMatch(cleanedText);
if (plain9 != null) routingNumber = plain9.group(1)!;
}
// 6. Extract optional IFSC Code & Bank Name
String? ifscCode;
final ifscMatch = _ifscRegex.firstMatch(cleanedText);
if (ifscMatch != null) {
ifscCode = ifscMatch.group(1);
}
// 3. Extract Account Number
String accountNumber = '000000';
final accountMatches = _accountRegex.allMatches(cleanedText).toList();
for (final match in accountMatches) {
final val = match.group(1)!;
if (val != chequeNumber && val != routingNumber && (ifscCode == null || !ifscCode.contains(val))) {
accountNumber = val;
break;
}
}
// 4. Extract Transaction Code
String transactionCode = '10';
final transMatches = _transCodeRegex.allMatches(cleanedText).toList();
for (final match in transMatches) {
final val = match.group(1)!;
if (val != chequeNumber && !routingNumber.contains(val) && val != accountNumber) {
transactionCode = val;
break;
}
}
// 5. Check sum validation on ABA 9-digit Transit Routing Number (3-7-1 weighting)
final isValidMicr = validateRoutingChecksum(routingNumber) || (chequeNumber != '000000' && routingNumber.length == 9);
String? bankName = _inferBankName(cleanedText, routingNumber, ifscCode);
// 7. Extract Date & Amount
String? chequeDate;
final dateMatch = _dateRegex.firstMatch(cleanedText);
if (dateMatch != null) {
chequeDate = dateMatch.group(1);
}
double? amount;
final explicitAmt = RegExp(r'(?:AMOUNT|TOTAL|PAY)\s*[:\$₹]?\s*([0-9,]+(?:\.[0-9]{2})?)', caseSensitive: false).firstMatch(cleanedText);
if (explicitAmt != null) {
amount = double.tryParse(explicitAmt.group(1)!.replaceAll(',', ''));
} else {
final currencyMatch = RegExp(r'[\$₹]\s*([0-9,]+(?:\.[0-9]{2})?)').firstMatch(cleanedText);
if (currencyMatch != null) {
amount = double.tryParse(currencyMatch.group(1)!.replaceAll(',', ''));
}
}
return BankChequeInfo(
rawMicrLine: rawMicrLine,
chequeNumber: chequeNumber,
routingNumber: routingNumber,
accountNumber: accountNumber,
transactionCode: transactionCode,
bankName: bankName,
ifscCode: ifscCode,
chequeDate: chequeDate,
amount: amount,
isValidMicr: isValidMicr,
extraDetails: {
'MICR Codeline': rawMicrLine,
'Format Standard': 'ISO 1004 / E-13B MICR',
},
);
}