thebassey01 commited on
Commit
733d8e3
·
verified ·
1 Parent(s): 6427e42

Update app/spec_builder.py

Browse files
Files changed (1) hide show
  1. app/spec_builder.py +43 -97
app/spec_builder.py CHANGED
@@ -1,79 +1,71 @@
1
  import re
2
- from typing import List
3
  from .schemas import ParserSpec, ColumnRole
4
 
5
 
6
  def infer_parser_spec(text: str) -> ParserSpec:
7
  lower = text.lower()
8
 
9
- # layout detection
10
- if re.search(r"^\d{4}-\d{2}-\d{2}t\d{2}:", text, re.MULTILINE):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  return ParserSpec(
12
  document_type="bank_statement",
13
  layout_type="event_block",
14
  row_start_pattern="line_starts_with_datetime",
15
- row_continuation_rule="append_until_next_row_start",
16
  amount_style="debit_credit_balance",
17
  direction_signal="keywords",
18
- date_format="yyyy-mm-dd",
19
- currency_markers=find_currency_markers(text),
20
- columns=[
21
- ColumnRole(role="transaction_date", evidence="datetime row start"),
22
- ColumnRole(role="description", evidence="middle lines"),
23
- ColumnRole(role="debit", evidence="amount triplet"),
24
- ColumnRole(role="credit", evidence="amount triplet"),
25
- ColumnRole(role="balance", evidence="last amount in block"),
26
- ],
27
- summary_fields=infer_summary_fields(text),
28
- confidence=0.88,
29
- notes=["Detected event-block statement structure"],
30
  )
31
 
32
- if re.search(r"^\d{2}/\d{2}/\d{2}\s+", text, re.MULTILINE):
 
 
 
33
  return ParserSpec(
34
  document_type="bank_statement",
35
  layout_type="table",
36
- row_start_pattern="line_starts_with_slash_date",
37
  row_continuation_rule="append_until_next_row_start",
38
- amount_style="amount_balance",
39
- direction_signal="keywords",
40
- date_format="dd/mm/yy",
41
- currency_markers=find_currency_markers(text),
42
- columns=[
43
- ColumnRole(role="transaction_date", evidence="dd/mm/yy row start"),
44
- ColumnRole(role="direction", evidence="keywords like inward/outward/web/local"),
45
- ColumnRole(role="amount", evidence="currency amount inline"),
46
- ColumnRole(role="description", evidence="middle text"),
47
- ColumnRole(role="balance", evidence="ending currency amount"),
48
- ],
49
- summary_fields=infer_summary_fields(text),
50
- confidence=0.84,
51
- notes=["Detected slash-date multiline table structure"],
52
  )
53
 
54
- if re.search(r"^\d{2}-[A-Za-z]{3}-\d{4}\s+\d{2}-[A-Za-z]{3}-\d{4}", text, re.MULTILINE):
55
  return ParserSpec(
56
  document_type="bank_statement",
57
  layout_type="table",
58
- row_start_pattern="line_starts_with_two_dates",
59
  row_continuation_rule="append_until_next_row_start",
60
- amount_style="debit_credit_balance",
61
- direction_signal="separate_columns",
62
- date_format="dd-MMM-yyyy",
63
- currency_markers=find_currency_markers(text),
64
- columns=[
65
- ColumnRole(role="transaction_date", evidence="first date"),
66
- ColumnRole(role="value_date", evidence="second date"),
67
- ColumnRole(role="description", evidence="wrapped narration"),
68
- ColumnRole(role="debit", evidence="numeric amount column"),
69
- ColumnRole(role="credit", evidence="numeric amount column"),
70
- ColumnRole(role="balance", evidence="last numeric column"),
71
- ],
72
- summary_fields=infer_summary_fields(text),
73
- confidence=0.90,
74
- notes=["Detected classic bank statement table"],
75
  )
76
 
 
 
 
77
  return ParserSpec(
78
  document_type="unknown",
79
  layout_type="unknown",
@@ -81,52 +73,6 @@ def infer_parser_spec(text: str) -> ParserSpec:
81
  row_continuation_rule="unknown",
82
  amount_style="unknown",
83
  direction_signal="unknown",
84
- date_format=None,
85
- currency_markers=find_currency_markers(text),
86
- columns=[],
87
- summary_fields=infer_summary_fields(text),
88
- confidence=0.20,
89
- notes=["Could not confidently infer parser grammar"],
90
- )
91
-
92
-
93
- def find_currency_markers(text: str) -> List[str]:
94
- markers = []
95
- if "₦" in text:
96
- markers.append("₦")
97
- if "ngn" in text.lower():
98
- markers.append("NGN")
99
- if "$" in text:
100
- markers.append("$")
101
- return markers
102
-
103
-
104
- def infer_summary_fields(text: str) -> dict:
105
- lower = text.lower()
106
- result = {}
107
-
108
- if "opening balance" in lower:
109
- result["opening_balance"] = "Opening Balance"
110
- if "closing balance" in lower:
111
- result["closing_balance"] = "Closing Balance"
112
- if "total debit" in lower or "money out" in lower:
113
- result["total_debit"] = "Total Debit/Money out"
114
- if "total credit" in lower or "money in" in lower:
115
- result["total_credit"] = "Total Credit/Money in"
116
- if "account number" in lower or "account no" in lower:
117
- result["account_number"] = "Account Number/Account No"
118
-
119
- return result
120
-
121
-
122
- if profile.layout_type == "event_stream":
123
- return ParserSpec(
124
- document_type="bank_statement",
125
- layout_type="event_stream",
126
- row_start_pattern="line_contains_datetime",
127
- row_continuation_rule="merge_until_next_datetime",
128
- amount_style="signed_amount",
129
- direction_signal="sign",
130
- confidence=0.7,
131
- notes=["Detected PalmPay-style stream"]
132
  )
 
1
  import re
 
2
  from .schemas import ParserSpec, ColumnRole
3
 
4
 
5
  def infer_parser_spec(text: str) -> ParserSpec:
6
  lower = text.lower()
7
 
8
+ # =========================
9
+ # EVENT STREAM (PalmPay)
10
+ # =========================
11
+ if re.search(r"\d{2}/\d{2}/\d{4}", text) and re.search(r"[+-]\d+\.\d{2}", text):
12
+ return ParserSpec(
13
+ document_type="bank_statement",
14
+ layout_type="event_stream",
15
+ row_start_pattern="line_contains_datetime",
16
+ row_continuation_rule="merge_until_next_datetime",
17
+ amount_style="signed_amount",
18
+ direction_signal="sign",
19
+ date_format="dd/mm/yyyy",
20
+ confidence=0.7,
21
+ notes=["Detected mobile wallet / PalmPay style"]
22
+ )
23
+
24
+ # =========================
25
+ # EVENT BLOCK (Moniepoint)
26
+ # =========================
27
+ if re.search(r"\d{4}-\d{2}-\d{2}T\d{2}:", text):
28
  return ParserSpec(
29
  document_type="bank_statement",
30
  layout_type="event_block",
31
  row_start_pattern="line_starts_with_datetime",
32
+ row_continuation_rule="merge_until_amount_line",
33
  amount_style="debit_credit_balance",
34
  direction_signal="keywords",
35
+ confidence=0.8,
36
+ notes=["Detected Moniepoint-style event block"]
 
 
 
 
 
 
 
 
 
 
37
  )
38
 
39
+ # =========================
40
+ # TABLE (GT / UBA / Kuda)
41
+ # =========================
42
+ if re.search(r"\d{2}-[A-Za-z]{3}-\d{4}", text):
43
  return ParserSpec(
44
  document_type="bank_statement",
45
  layout_type="table",
46
+ row_start_pattern="line_starts_with_two_dates",
47
  row_continuation_rule="append_until_next_row_start",
48
+ amount_style="debit_credit_balance",
49
+ direction_signal="separate_columns",
50
+ confidence=0.8,
51
+ notes=["Detected table-style statement"]
 
 
 
 
 
 
 
 
 
 
52
  )
53
 
54
+ if re.search(r"\d{2}/\d{2}/\d{2}", text):
55
  return ParserSpec(
56
  document_type="bank_statement",
57
  layout_type="table",
58
+ row_start_pattern="line_starts_with_slash_date",
59
  row_continuation_rule="append_until_next_row_start",
60
+ amount_style="amount_balance",
61
+ direction_signal="keywords",
62
+ confidence=0.6,
63
+ notes=["Detected short date format table"]
 
 
 
 
 
 
 
 
 
 
 
64
  )
65
 
66
+ # =========================
67
+ # FALLBACK
68
+ # =========================
69
  return ParserSpec(
70
  document_type="unknown",
71
  layout_type="unknown",
 
73
  row_continuation_rule="unknown",
74
  amount_style="unknown",
75
  direction_signal="unknown",
76
+ confidence=0.0,
77
+ notes=["Could not infer structure"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  )