rehan953 commited on
Commit
2b7d582
·
verified ·
1 Parent(s): f67813a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -2
app.py CHANGED
@@ -2643,6 +2643,58 @@ def _split_fused_date_transaction_header(grid):
2643
  new_grid.append(split_row)
2644
  return new_grid
2645
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2646
  def _normalize_fused_date_posted_amount_table(grid):
2647
  """
2648
  Normalize 2-column OCR tables with fused header like:
@@ -2799,8 +2851,12 @@ def normalize_html_tables(text: str) -> str:
2799
 
2800
  # Fix 3: fused key-value rows in summary sections (no-space guard — safe on all PDFs)
2801
  grid = _fix_fused_keyvalue_rows(grid)
2802
-
2803
- out.append(_grid_to_html(grid) if grid else table_html)
 
 
 
 
2804
  except Exception:
2805
  out.append(table_html)
2806
  last = m.end()
 
2643
  new_grid.append(split_row)
2644
  return new_grid
2645
 
2646
+ def _split_combined_summary_daily_balance_grid(grid):
2647
+ """
2648
+ Some OCR outputs fuse an account summary table and a Daily Balance block
2649
+ into one HTML table. Split them into two tables when structure is clear.
2650
+ Generic guards:
2651
+ - A row containing "Daily Balance" exists
2652
+ - There are rows after it with date-like + amount-like tokens
2653
+ """
2654
+ if not grid or len(grid) < 4:
2655
+ return None
2656
+
2657
+ def _norm(s):
2658
+ return re.sub(r"\s+", " ", str(s or "").strip().lower())
2659
+
2660
+ daily_idx = None
2661
+ for i, row in enumerate(grid):
2662
+ row_text = " ".join(_norm(c) for c in row if str(c or "").strip())
2663
+ if "daily balance" in row_text:
2664
+ daily_idx = i
2665
+ break
2666
+ if daily_idx is None or daily_idx <= 1 or daily_idx >= len(grid) - 2:
2667
+ return None
2668
+
2669
+ date_re = re.compile(r"^\d{1,2}/\d{2}(?:/\d{2,4})?$")
2670
+ money_re = re.compile(r"^-?\$?\d{1,3}(?:,\d{3})*(?:\.\d{2})-?$")
2671
+
2672
+ daily_rows = []
2673
+ for row in grid[daily_idx + 1:]:
2674
+ tokens = []
2675
+ for cell in row:
2676
+ ct = str(cell or "").strip()
2677
+ if not ct:
2678
+ continue
2679
+ tokens.extend(re.split(r"\s+", ct))
2680
+ dates = [t for t in tokens if date_re.match(t)]
2681
+ amts = [t for t in tokens if money_re.match(t)]
2682
+ if not dates or not amts:
2683
+ continue
2684
+ for d, a in zip(dates, amts):
2685
+ daily_rows.append([d, a])
2686
+
2687
+ # Need meaningful daily table to split safely.
2688
+ if len(daily_rows) < 2:
2689
+ return None
2690
+
2691
+ summary = [r for r in grid[:daily_idx] if any(str(c or "").strip() for c in r)]
2692
+ if len(summary) < 2:
2693
+ return None
2694
+
2695
+ daily = [["Date", "Ledger Balance"]] + daily_rows
2696
+ return [summary, daily]
2697
+
2698
  def _normalize_fused_date_posted_amount_table(grid):
2699
  """
2700
  Normalize 2-column OCR tables with fused header like:
 
2851
 
2852
  # Fix 3: fused key-value rows in summary sections (no-space guard — safe on all PDFs)
2853
  grid = _fix_fused_keyvalue_rows(grid)
2854
+ # Fix 12: split fused summary+daily-balance combined table, if detected.
2855
+ split_tables = _split_combined_summary_daily_balance_grid(grid)
2856
+ if split_tables:
2857
+ out.append("\n\n".join(_grid_to_html(g) for g in split_tables if g))
2858
+ else:
2859
+ out.append(_grid_to_html(grid) if grid else table_html)
2860
  except Exception:
2861
  out.append(table_html)
2862
  last = m.end()