Fix SBI multiline table parsing and restore template-first bank analysis
This commit is contained in:
@@ -151,6 +151,10 @@ def detect_bank_identity(
|
||||
) -> BankIdentityMatch | None:
|
||||
raw_text = str(text or "")
|
||||
text_upper = _normalise(raw_text)
|
||||
# Identity headings and account metadata are normally in the first page.
|
||||
# Restrict strong name evidence to the beginning so counterparty bank names
|
||||
# inside hundreds of transaction narrations cannot relabel the statement.
|
||||
header_upper = _normalise(raw_text[:800])
|
||||
ifsc_upper = re.sub(r"[^A-Z0-9]", "", str(ifsc or "").upper())
|
||||
file_upper = _normalise(Path(source_file or "").stem)
|
||||
|
||||
@@ -159,25 +163,36 @@ def detect_bank_identity(
|
||||
score = 0.0
|
||||
evidence: list[str] = []
|
||||
|
||||
# Longest/special IFSC prefixes carry the strongest identity signal.
|
||||
matching_prefixes = [prefix for prefix in bank.ifsc_prefixes if ifsc_upper.startswith(prefix.upper())]
|
||||
matching_prefixes = [
|
||||
prefix for prefix in bank.ifsc_prefixes
|
||||
if ifsc_upper.startswith(prefix.upper())
|
||||
]
|
||||
if matching_prefixes:
|
||||
prefix = max(matching_prefixes, key=len)
|
||||
score += 0.72 if len(prefix) > 4 else 0.58
|
||||
# The account IFSC belongs to the issuing bank and therefore outranks
|
||||
# bank names appearing merely as transaction counterparties.
|
||||
score += 0.96 if len(prefix) > 4 else 0.90
|
||||
evidence.append(f"IFSC prefix {prefix}")
|
||||
|
||||
for domain in bank.domains:
|
||||
if domain.lower() in raw_text.lower():
|
||||
score += 0.72
|
||||
score += 0.92
|
||||
evidence.append(f"domain {domain}")
|
||||
break
|
||||
|
||||
alias_hits = [alias for alias in bank.aliases if _alias_present(text_upper, alias)]
|
||||
if alias_hits:
|
||||
longest = max(alias_hits, key=len)
|
||||
# Long formal headings are stronger than abbreviations such as SBI.
|
||||
score += 0.72 if len(_normalise(longest)) >= 12 else 0.36
|
||||
evidence.append(f"name {longest}")
|
||||
header_alias_hits = [alias for alias in bank.aliases if _alias_present(header_upper, alias)]
|
||||
if header_alias_hits:
|
||||
longest = max(header_alias_hits, key=len)
|
||||
score += 0.88 if len(_normalise(longest)) >= 12 else 0.55
|
||||
evidence.append(f"header name {longest}")
|
||||
else:
|
||||
# Full-document matches are weak because narrations commonly mention
|
||||
# beneficiary and remitter banks. They may support another signal but
|
||||
# cannot identify the issuer by themselves.
|
||||
body_hits = [alias for alias in bank.aliases if _alias_present(text_upper, alias)]
|
||||
if body_hits:
|
||||
score += 0.12
|
||||
evidence.append("body mention")
|
||||
|
||||
if any(_alias_present(file_upper, alias) for alias in bank.aliases):
|
||||
score += 0.10
|
||||
@@ -186,7 +201,9 @@ def detect_bank_identity(
|
||||
confidence = min(score, 0.99)
|
||||
if confidence < 0.50:
|
||||
continue
|
||||
candidate = BankIdentityMatch(bank.name, bank.category, confidence, tuple(dict.fromkeys(evidence)))
|
||||
candidate = BankIdentityMatch(
|
||||
bank.name, bank.category, confidence, tuple(dict.fromkeys(evidence))
|
||||
)
|
||||
if best is None or candidate.confidence > best.confidence:
|
||||
best = candidate
|
||||
|
||||
@@ -194,9 +211,21 @@ def detect_bank_identity(
|
||||
|
||||
|
||||
def apply_detected_bank_identity(meta, df, text: str):
|
||||
meta_ifsc = str(getattr(meta, "ifsc", "") or "")
|
||||
if not meta_ifsc:
|
||||
# Some PDFs place the IFSC value far from its label in text-reading
|
||||
# order. Recover the first header-area IFSC token directly; limiting
|
||||
# the search to the beginning avoids beneficiary-bank IFSC codes.
|
||||
header_match = re.search(r"\b[A-Z]{4}0[A-Z0-9]{6}\b", str(text or "")[:2500], re.I)
|
||||
if header_match:
|
||||
meta_ifsc = header_match.group(0).upper()
|
||||
try:
|
||||
meta.ifsc = meta_ifsc
|
||||
except Exception:
|
||||
pass
|
||||
match = detect_bank_identity(
|
||||
text,
|
||||
ifsc=str(getattr(meta, "ifsc", "") or ""),
|
||||
ifsc=meta_ifsc,
|
||||
source_file=str(getattr(meta, "source_file", "") or ""),
|
||||
)
|
||||
if match is None:
|
||||
|
||||
Reference in New Issue
Block a user