Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1140,18 +1140,37 @@ def _patch_ocr_with_textlayer(page_md: str, pdf_path: str, page_num: int) -> str
|
|
| 1140 |
ocr_freq[key] = ocr_freq.get(key, 0) + 1
|
| 1141 |
ocr_rows_indexed.append((ri, key))
|
| 1142 |
|
| 1143 |
-
# Guard: overlap
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1144 |
overlap = set(ocr_freq.keys()) & set(tl_freq.keys())
|
| 1145 |
-
|
| 1146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1147 |
|
| 1148 |
# Determine missing rows.
|
| 1149 |
# Case A: row exists in OCR but count is too low (duplicate dropped)
|
| 1150 |
-
# Case B: row exists in text layer but
|
| 1151 |
-
|
| 1152 |
-
|
| 1153 |
-
to_inject = {} # key -> count of missing copies
|
| 1154 |
-
to_inject_new = {} # key -> row content for brand-new rows
|
| 1155 |
|
| 1156 |
for key in tl_freq:
|
| 1157 |
ocr_count = ocr_freq.get(key, 0)
|
|
@@ -1159,18 +1178,20 @@ def _patch_ocr_with_textlayer(page_md: str, pdf_path: str, page_num: int) -> str
|
|
| 1159 |
if tl_count > ocr_count:
|
| 1160 |
missing = tl_count - ocr_count
|
| 1161 |
if ocr_count > 0:
|
| 1162 |
-
# Case A: restore
|
| 1163 |
-
|
|
|
|
| 1164 |
else:
|
| 1165 |
-
# Case B:
|
| 1166 |
-
#
|
| 1167 |
-
|
| 1168 |
-
|
| 1169 |
-
|
| 1170 |
-
|
| 1171 |
-
|
| 1172 |
-
|
| 1173 |
-
|
|
|
|
| 1174 |
|
| 1175 |
if not to_inject and not to_inject_new:
|
| 1176 |
continue
|
|
|
|
| 1140 |
ocr_freq[key] = ocr_freq.get(key, 0) + 1
|
| 1141 |
ocr_rows_indexed.append((ri, key))
|
| 1142 |
|
| 1143 |
+
# Guard: overlap check for Case A (duplicate restore).
|
| 1144 |
+
# For Case A we require at least one row in both OCR and text layer
|
| 1145 |
+
# to confirm we are patching the right table.
|
| 1146 |
+
# For Case B (entirely missing rows) we use a lighter structural check:
|
| 1147 |
+
# if the OCR table has DATE+DESCRIPTION+AMOUNT columns (already verified)
|
| 1148 |
+
# and the text layer date format matches the OCR date format,
|
| 1149 |
+
# we can safely inject — even when zero rows overlap.
|
| 1150 |
overlap = set(ocr_freq.keys()) & set(tl_freq.keys())
|
| 1151 |
+
|
| 1152 |
+
# Detect date format used in OCR table (MM/DD vs MM-DD vs Mon DD)
|
| 1153 |
+
_ocr_dates = [
|
| 1154 |
+
_norm(str(row[date_col] or ""))
|
| 1155 |
+
for row in grid[1:]
|
| 1156 |
+
if len(row) > date_col and str(row[date_col] or "").strip()
|
| 1157 |
+
]
|
| 1158 |
+
_tl_dates = [_norm(r["date"]) for r in tl_rows]
|
| 1159 |
+
_slash_re = re.compile(r"^\d{1,2}/\d{2}")
|
| 1160 |
+
_hyphen_re = re.compile(r"^\d{1,2}-\d{2}")
|
| 1161 |
+
def _date_fmt(dates):
|
| 1162 |
+
if any(_slash_re.match(d) for d in dates): return "slash"
|
| 1163 |
+
if any(_hyphen_re.match(d) for d in dates): return "hyphen"
|
| 1164 |
+
return "other"
|
| 1165 |
+
ocr_fmt = _date_fmt(_ocr_dates)
|
| 1166 |
+
tl_fmt = _date_fmt(_tl_dates)
|
| 1167 |
+
date_fmt_match = (ocr_fmt == tl_fmt) or "other" in (ocr_fmt, tl_fmt)
|
| 1168 |
|
| 1169 |
# Determine missing rows.
|
| 1170 |
# Case A: row exists in OCR but count is too low (duplicate dropped)
|
| 1171 |
+
# Case B: row exists in text layer but completely absent from OCR
|
| 1172 |
+
to_inject = {}
|
| 1173 |
+
to_inject_new = {}
|
|
|
|
|
|
|
| 1174 |
|
| 1175 |
for key in tl_freq:
|
| 1176 |
ocr_count = ocr_freq.get(key, 0)
|
|
|
|
| 1178 |
if tl_count > ocr_count:
|
| 1179 |
missing = tl_count - ocr_count
|
| 1180 |
if ocr_count > 0:
|
| 1181 |
+
# Case A: restore duplicates — requires overlap confirmation
|
| 1182 |
+
if overlap:
|
| 1183 |
+
to_inject[key] = missing
|
| 1184 |
else:
|
| 1185 |
+
# Case B: entirely new row — requires date format match
|
| 1186 |
+
# (lighter guard: no overlap needed, just structural match)
|
| 1187 |
+
if date_fmt_match:
|
| 1188 |
+
tl_row_data = next(
|
| 1189 |
+
(r for r in tl_rows
|
| 1190 |
+
if (_norm(r["date"]), _norm(r["desc"]), _norm(r["amount"])) == key),
|
| 1191 |
+
None
|
| 1192 |
+
)
|
| 1193 |
+
if tl_row_data:
|
| 1194 |
+
to_inject_new[key] = (missing, tl_row_data)
|
| 1195 |
|
| 1196 |
if not to_inject and not to_inject_new:
|
| 1197 |
continue
|