parse static method

ScanResult parse(
  1. String rawText
)

Parses raw text extracted from a receipt image.

Implementation

static ScanResult parse(String rawText) {
  if (rawText.trim().isEmpty) {
    return ScanResult.error(
      ScanMode.ocr,
      'Empty receipt payload. Ensure good illumination and clarity.',
    );
  }

  final lines = rawText
      .split('\n')
      .map((l) => l.trim())
      .where((l) => l.isNotEmpty)
      .toList();

  String merchantName = lines.isNotEmpty ? lines.first : 'Store / Merchant';
  String totalAmount = 'Not Found';
  String taxAmount = 'N/A';
  String dateStr = 'N/A';
  List<String> items = [];

  // Currency pattern matching ($ / € / £ / ₹ / USD / EUR / INR)
  final totalRegex = RegExp(
    r'(?:TOTAL|AMOUNT|BAL|NET|DUE)[^\d$€£₹\n\r]*([$€£₹]?\s*\d+[.,]\d{2})',
    caseSensitive: false,
  );
  final taxRegex = RegExp(
    r'(?:TAX|VAT|GST)[^\d$€£₹\n\r]*([$€£₹]?\s*\d+[.,]\d{2})',
    caseSensitive: false,
  );
  final dateRegex = RegExp(
    r'\b(\d{1,2}[/-]\d{1,2}[/-]\d{2,4}|\d{4}[/-]\d{1,2}[/-]\d{1,2}|\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]* \d{1,2},? \d{4})\b',
    caseSensitive: false,
  );

  for (final line in lines) {
    final totalMatch = totalRegex.firstMatch(line);
    if (totalMatch != null && totalAmount == 'Not Found') {
      totalAmount = totalMatch.group(1) ?? 'Not Found';
    }

    final taxMatch = taxRegex.firstMatch(line);
    if (taxMatch != null && taxAmount == 'N/A') {
      taxAmount = taxMatch.group(1) ?? 'N/A';
    }

    final dateMatch = dateRegex.firstMatch(line);
    if (dateMatch != null && dateStr == 'N/A') {
      dateStr = dateMatch.group(1) ?? 'N/A';
    }

    // Check if line looks like an item price
    if (RegExp(r'\d+[.,]\d{2}').hasMatch(line) &&
        !line.toUpperCase().contains('TOTAL') &&
        !line.toUpperCase().contains('TAX')) {
      items.add(line);
    }
  }

  final fields = <String, String>{
    'Document Type': 'RECEIPT OCR',
    'Merchant / Store': merchantName,
    'Total Amount': totalAmount,
    'Tax Amount': taxAmount,
    'Receipt Date': dateStr,
    'Line Items Count': '${items.length}',
    if (items.isNotEmpty) 'Item 1': items[0],
    if (items.length > 1) 'Item 2': items[1],
    if (items.length > 2) 'Item 3': items[2],
    'OCR Engine': 'ScannerPro Receipt Vision Engine',
    'Confidence Score': '97.5%',
  };

  return ScanResult(
    mode: ScanMode.receipt,
    rawValue: rawText,
    isValid: totalAmount != 'Not Found' || lines.length >= 2,
    confidence: 0.96,
    format: 'RECEIPT_OCR',
    fields: fields,
    metadata: {
      'documentType': 'receipt',
      'merchant': merchantName,
      'total': totalAmount,
      'tax': taxAmount,
      'date': dateStr,
      'itemsCount': items.length,
    },
  );
}