Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1255,6 +1255,64 @@ def _patch_ocr_with_textlayer(page_md: str, pdf_path: str, page_num: int) -> str
|
|
| 1255 |
insert_pos = result.find(new_table_html) + len(new_table_html)
|
| 1256 |
result = result[:insert_pos] + extra_html + result[insert_pos:]
|
| 1257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1258 |
return result
|
| 1259 |
|
| 1260 |
except Exception as e:
|
|
|
|
| 1255 |
insert_pos = result.find(new_table_html) + len(new_table_html)
|
| 1256 |
result = result[:insert_pos] + extra_html + result[insert_pos:]
|
| 1257 |
|
| 1258 |
+
# Case C: NO transaction table exists on this page at all, but text
|
| 1259 |
+
# layer has valid rows. Build a brand-new table and prepend it to
|
| 1260 |
+
# the page content. This handles pages where OCR dropped the entire
|
| 1261 |
+
# transaction section (e.g. East West Bank page 7 with only 2 rows).
|
| 1262 |
+
#
|
| 1263 |
+
# Guard: only fire if no table on this page already has DATE+DESCRIPTION
|
| 1264 |
+
# columns (avoids duplicating non-transaction tables like DAILY BALANCES).
|
| 1265 |
+
table_pattern2 = re.compile(r"<table[^>]*>.*?</table>", re.DOTALL | re.IGNORECASE)
|
| 1266 |
+
has_txn_table = False
|
| 1267 |
+
for tbl in table_pattern2.finditer(result):
|
| 1268 |
+
p2 = TableGridParser()
|
| 1269 |
+
p2.feed(tbl.group(0))
|
| 1270 |
+
g2 = _build_grid(p2.rows)
|
| 1271 |
+
if len(g2) < 2:
|
| 1272 |
+
continue
|
| 1273 |
+
hdr2 = [str(c or "").strip().upper() for c in g2[0]]
|
| 1274 |
+
has_date = any(re.search(r"DATE", h) for h in hdr2)
|
| 1275 |
+
has_desc = any(re.search(r"(DESCRIPTION|DETAILS?|NARRATION|PARTICULARS?)", h) for h in hdr2)
|
| 1276 |
+
if has_date and has_desc:
|
| 1277 |
+
has_txn_table = True
|
| 1278 |
+
break
|
| 1279 |
+
|
| 1280 |
+
if not has_txn_table and tl_rows:
|
| 1281 |
+
# Infer date format from text layer to pick column header label
|
| 1282 |
+
_hy = re.compile(r"^\d{1,2}-\d{2}")
|
| 1283 |
+
_sl = re.compile(r"^\d{1,2}/\d{2}")
|
| 1284 |
+
_sample_dates = [_norm(r["date"]) for r in tl_rows[:3]]
|
| 1285 |
+
if any(_hy.match(d) for d in _sample_dates):
|
| 1286 |
+
date_label = "Date"
|
| 1287 |
+
elif any(_sl.match(d) for d in _sample_dates):
|
| 1288 |
+
date_label = "Date"
|
| 1289 |
+
else:
|
| 1290 |
+
date_label = "Trans Date"
|
| 1291 |
+
|
| 1292 |
+
has_post = any(r.get("post_date") for r in tl_rows)
|
| 1293 |
+
if has_post:
|
| 1294 |
+
header_row = [date_label, "Post Date", "Transaction Description", "Amount"]
|
| 1295 |
+
else:
|
| 1296 |
+
header_row = [date_label, "Transaction Description", "Amount"]
|
| 1297 |
+
|
| 1298 |
+
date_ci = 0
|
| 1299 |
+
desc_ci = 2 if has_post else 1
|
| 1300 |
+
amt_ci = 3 if has_post else 2
|
| 1301 |
+
|
| 1302 |
+
new_rows = []
|
| 1303 |
+
for r in tl_rows:
|
| 1304 |
+
row = [""] * len(header_row)
|
| 1305 |
+
row[date_ci] = r["date"]
|
| 1306 |
+
row[desc_ci] = r["desc"]
|
| 1307 |
+
row[amt_ci] = r["amount"]
|
| 1308 |
+
if has_post:
|
| 1309 |
+
row[1] = r.get("post_date", "")
|
| 1310 |
+
new_rows.append(row)
|
| 1311 |
+
|
| 1312 |
+
new_table_html = _grid_to_html([header_row] + new_rows)
|
| 1313 |
+
result = new_table_html + "\n\n" + result
|
| 1314 |
+
log.info("page %d: created new table from text layer (%d rows)", page_num, len(new_rows))
|
| 1315 |
+
|
| 1316 |
return result
|
| 1317 |
|
| 1318 |
except Exception as e:
|