from __future__ import annotations import re import pandas as pd from pathlib import Path from .base import BaseParser, StatementMeta, extract_text, amount, norm, finalize, page_of_line from .common import DATE_TOKEN_PATTERN, find, date_iso class IDFCFirstParser(BaseParser): bank_name='IDFC FIRST Bank'; parser_name='IDFCFirstParser' @classmethod def detect(cls,text): u=text.upper(); return 0.99 if 'IDFC FIRST BANK' in u and 'STATEMENT PERIOD' in u else 0 def parse(self,path,text=None): text=text or extract_text(path) meta=StatementMeta(bank_name=self.bank_name,source_file=Path(path).name,parser_name=self.parser_name,confidence='High') meta.customer_name=find(r'CUSTOMER NAME\s*:\s*([^\n]+)',text) meta.account_number=find(r'ACCOUNT NO\s*:\s*([0-9X*]+)',text) meta.customer_id=find(r'CUSTOMER ID\s*:\s*([0-9X*]+)',text) meta.ifsc=find(r'IFSC\s*:\s*([A-Z0-9]+)',text) m=re.search(rf'STATEMENT PERIOD\s*:\s*({DATE_TOKEN_PATTERN})\s+TO\s+({DATE_TOKEN_PATTERN})', text, re.I) if m: meta.period_from=date_iso(m.group(1)); meta.period_to=date_iso(m.group(2)) m=re.search(r'Opening Balance\s+Total Debit\s+Total Credit\s+Closing Balance\s*\n\s*([\d,.]+)\s+([\d,.]+)\s+([\d,.]+)\s+([\d,.]+)',text,re.I) if m: meta.opening_balance,meta.total_debit,meta.total_credit,meta.closing_balance=map(amount,m.groups()) lines=text.splitlines(); rows=[]; current=None; pos=0 pat=re.compile(rf'^\s*({DATE_TOKEN_PATTERN})\s+({DATE_TOKEN_PATTERN})\s+(.*)$', re.I) for line in lines: mm=pat.match(line) if mm: if current: rows.append(current) current={'transaction_date':mm.group(1),'value_date':mm.group(2),'body':mm.group(3),'source_page':page_of_line(text,pos)} elif current and line.strip() and not re.match(r'^(STATEMENT|Opening Balance|REGISTERED OFFICE|Page \d+)',line.strip(),re.I): current['body']+=' '+line.strip() pos+=len(line)+1 if current: rows.append(current) out=[]; prev=meta.opening_balance for r in rows: body=norm(r['body']); nums=list(re.finditer(r'(?=prev else None; debit=txn if bal