Fix modern ICICI template parsing and parser fallback
This commit is contained in:
@@ -77,8 +77,15 @@ def _upper(value) -> str:
|
||||
return norm(value).upper().replace("\n", " ")
|
||||
|
||||
|
||||
def _is_date(value) -> bool:
|
||||
def _normalise_date_cell(value) -> str:
|
||||
"""Normalise PDF table line-wrap artefacts without changing the date value."""
|
||||
text = norm(value)
|
||||
text = re.sub(r"\s*([/-])\s*", r"\1", text)
|
||||
return text
|
||||
|
||||
|
||||
def _is_date(value) -> bool:
|
||||
text = _normalise_date_cell(value)
|
||||
return bool(_DATE_CELL_RE.fullmatch(text)) and not pd.isna(parse_flexible_date(text))
|
||||
|
||||
|
||||
@@ -102,7 +109,7 @@ def _find_header_mapping(row: list) -> dict[str, int]:
|
||||
|
||||
|
||||
def _looks_like_data_row(row: list) -> bool:
|
||||
return bool(row) and (_is_date(row[0]) or (len(row) > 1 and _is_date(row[1])))
|
||||
return bool(row) and any(_is_date(row[index]) for index in range(min(4, len(row))))
|
||||
|
||||
|
||||
def _infer_structural_template(table: list[list]) -> LayoutTemplate | None:
|
||||
@@ -110,6 +117,23 @@ def _infer_structural_template(table: list[list]) -> LayoutTemplate | None:
|
||||
if sample is None:
|
||||
return None
|
||||
width = len(sample)
|
||||
# Modern ICICI and similar indexed statements:
|
||||
# serial no, transaction id, transaction date, cheque no, description,
|
||||
# withdrawal, deposit, available balance.
|
||||
if width >= 8 and _is_date(sample[2]):
|
||||
return LayoutTemplate(
|
||||
"indexed_transaction_id_debit_credit_balance",
|
||||
{
|
||||
"transaction_date": 2,
|
||||
"value_date": 2,
|
||||
"reference_no": 1,
|
||||
"narration": 4,
|
||||
"debit": 5,
|
||||
"credit": 6,
|
||||
"balance": 7,
|
||||
},
|
||||
0.92,
|
||||
)
|
||||
# SBI Account Summary / SBI YONO family:
|
||||
# value date, post date, details, reference, debit, credit, balance.
|
||||
if width >= 7 and _is_date(sample[0]) and _is_date(sample[1]):
|
||||
@@ -354,11 +378,11 @@ class TemplateBasedStatementParser(BaseParser):
|
||||
max_index = max(mapping.values())
|
||||
if len(cells) <= max_index:
|
||||
cells += [None] * (max_index + 1 - len(cells))
|
||||
txn_text = norm(cells[mapping["transaction_date"]])
|
||||
txn_text = _normalise_date_cell(cells[mapping["transaction_date"]])
|
||||
if not _is_date(txn_text):
|
||||
continue
|
||||
value_index = mapping.get("value_date", mapping["transaction_date"])
|
||||
value_text = norm(cells[value_index]) or txn_text
|
||||
value_text = _normalise_date_cell(cells[value_index]) or txn_text
|
||||
narration = norm(cells[mapping["narration"]])
|
||||
reference = norm(cells[mapping["reference_no"]]) if "reference_no" in mapping else ""
|
||||
debit = amount(cells[mapping["debit"]])
|
||||
|
||||
Reference in New Issue
Block a user