pyflutter-app 0.2.4__tar.gz → 0.2.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/PKG-INFO +5 -1
  2. pyflutter_app-0.2.6/cartas/__init__.py +17 -0
  3. pyflutter_app-0.2.6/cartas/_table_toi.py +249 -0
  4. pyflutter_app-0.2.6/cartas/common.py +67 -0
  5. pyflutter_app-0.2.6/cartas/find_toi.py +27 -0
  6. pyflutter_app-0.2.6/cartas/relatorio.py +453 -0
  7. pyflutter_app-0.2.6/cartas/util.py +43 -0
  8. pyflutter_app-0.2.6/converter/__init__.py +1 -0
  9. pyflutter_app-0.2.6/converter/__main__.py +9 -0
  10. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/converter/home_page/_page_edit.py +1 -1
  11. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/converter/home_page/view.py +6 -7
  12. pyflutter_app-0.2.6/converter/page_forms/Diagnorstico.txt +108 -0
  13. pyflutter_app-0.2.6/converter/page_forms/__init__.py +5 -0
  14. pyflutter_app-0.2.6/converter/page_forms/common.py +192 -0
  15. pyflutter_app-0.2.6/converter/page_forms/config.py +68 -0
  16. pyflutter_app-0.2.6/converter/page_forms/controller_forms.py +256 -0
  17. pyflutter_app-0.2.6/converter/page_forms/diagnose_forms.py +64 -0
  18. pyflutter_app-0.2.6/converter/page_forms/model_forms.py +215 -0
  19. pyflutter_app-0.2.6/converter/page_forms/service.py +347 -0
  20. pyflutter_app-0.2.6/converter/page_forms/view_forms.py +104 -0
  21. pyflutter_app-0.2.4/converter/run.py → pyflutter_app-0.2.6/converter/run_app_convert.py +4 -8
  22. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/converter/util.py +6 -3
  23. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/export_app.sh +14 -10
  24. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/main.py +5 -5
  25. pyflutter_app-0.2.6/mediator.py +264 -0
  26. pyflutter_app-0.2.6/mvc/controller.py +60 -0
  27. pyflutter_app-0.2.6/mvc/model.py +40 -0
  28. pyflutter_app-0.2.6/mvc/view.py +133 -0
  29. pyflutter_app-0.2.6/new-export_app.sh +60 -0
  30. pyflutter_app-0.2.6/ocrlib/__init__.py +53 -0
  31. pyflutter_app-0.2.6/ocrlib/_common.py +300 -0
  32. pyflutter_app-0.2.4/ocrlib/pdf_convert.py → pyflutter_app-0.2.6/ocrlib/_pdf_convert.py +388 -264
  33. pyflutter_app-0.2.6/ocrlib/_table_ocr.py +625 -0
  34. pyflutter_app-0.2.6/ocrlib/_tesseract.py +385 -0
  35. pyflutter_app-0.2.6/ocrlib/erros.py +10 -0
  36. pyflutter_app-0.2.6/ocrlib/relatorio_ocr.py +534 -0
  37. pyflutter_app-0.2.6/ocrlib/util.py +29 -0
  38. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/file_picker.py +8 -7
  39. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/ui/core.py +1 -1
  40. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyproject.toml +13 -3
  41. pyflutter_app-0.2.6/table_stream/__init__.py +91 -0
  42. pyflutter_app-0.2.6/table_stream/erros.py +156 -0
  43. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/hash_map.py +170 -57
  44. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/notifier.py +5 -5
  45. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/pattner/adapter.py +2 -3
  46. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/sysfiles.py +221 -180
  47. pyflutter_app-0.2.6/table_stream/table.py +835 -0
  48. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/thread.py +1 -0
  49. pyflutter_app-0.2.6/test.py +108 -0
  50. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/uv.lock +237 -1
  51. pyflutter_app-0.2.6/whatsapp_files/__init__.py +21 -0
  52. pyflutter_app-0.2.6/whatsapp_files/_table_whatsapp.py +461 -0
  53. pyflutter_app-0.2.6/whatsapp_files/common.py +141 -0
  54. pyflutter_app-0.2.6/whatsapp_files/erros.py +11 -0
  55. pyflutter_app-0.2.6/whatsapp_files/stream_files.py +477 -0
  56. pyflutter_app-0.2.6/whatsapp_files/util.py +36 -0
  57. pyflutter_app-0.2.4/converter/__init__.py +0 -1
  58. pyflutter_app-0.2.4/converter/__main__.py +0 -9
  59. pyflutter_app-0.2.4/converter/page_forms/__init__.py +0 -191
  60. pyflutter_app-0.2.4/converter/page_forms/common.py +0 -155
  61. pyflutter_app-0.2.4/converter/page_forms/config.py +0 -199
  62. pyflutter_app-0.2.4/converter/page_forms/controller_forms.py +0 -193
  63. pyflutter_app-0.2.4/converter/page_forms/model_forms.py +0 -68
  64. pyflutter_app-0.2.4/converter/page_forms/service.py +0 -207
  65. pyflutter_app-0.2.4/ocrlib/modules.py +0 -178
  66. pyflutter_app-0.2.4/ocrlib/recognize.py +0 -1034
  67. pyflutter_app-0.2.4/ocrlib/util.py +0 -6
  68. pyflutter_app-0.2.4/table_stream/__init__.py +0 -22
  69. pyflutter_app-0.2.4/table_stream/erros.py +0 -102
  70. pyflutter_app-0.2.4/test.py +0 -63
  71. pyflutter_app-0.2.4/whatsapp_files/file_names.py +0 -678
  72. pyflutter_app-0.2.4/whatsapp_files/stream_files.py +0 -417
  73. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/.gitignore +0 -0
  74. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/.idea/.gitignore +0 -0
  75. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/.idea/inspectionProfiles/Project_Default.xml +0 -0
  76. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
  77. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/.idea/misc.xml +0 -0
  78. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/.idea/modules.xml +0 -0
  79. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/.idea/pyflutter_app.iml +0 -0
  80. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/.idea/vcs.xml +0 -0
  81. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/README.md +0 -0
  82. pyflutter_app-0.2.4/converter/home_page/__init__.py → pyflutter_app-0.2.6/cartas/erros.py +0 -0
  83. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/converter/assets/forms_config.json +0 -0
  84. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/converter/config_app.py +0 -0
  85. {pyflutter_app-0.2.4/converter/whatsapp → pyflutter_app-0.2.6/converter/home_page}/__init__.py +0 -0
  86. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/converter/home_page/controller.py +0 -0
  87. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/converter/home_page/model.py +0 -0
  88. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/converter/lib_toi.py +0 -0
  89. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/converter/table_widget.py +0 -0
  90. {pyflutter_app-0.2.4/whatsapp_files → pyflutter_app-0.2.6/converter/whatsapp}/__init__.py +0 -0
  91. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/converter/whatsapp/model.py +0 -0
  92. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/local_build/linux.sh +0 -0
  93. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/local_build/send.sh +0 -0
  94. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/ocrlib/export_ocr.sh +0 -0
  95. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/__init__.py +0 -0
  96. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/app.py +0 -0
  97. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/navigator.py +0 -0
  98. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/scheduler.py +0 -0
  99. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/theme.py +0 -0
  100. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/ui/__init__.py +0 -0
  101. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/ui/buttons.py +0 -0
  102. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/ui/container.py +0 -0
  103. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/ui/list_builder.py +0 -0
  104. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/ui/progress.py +0 -0
  105. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/ui/tables.py +0 -0
  106. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/pyflutter_ui/ui/widgets.py +0 -0
  107. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/pattner/__init__.py +0 -0
  108. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/sheet/__init__.py +0 -0
  109. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/sheet/check_mod.py +0 -0
  110. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/sheet/load.py +0 -0
  111. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/sheet/options.py +0 -0
  112. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/sheet/parse.py +0 -0
  113. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/sheet/save.py +0 -0
  114. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/state.py +1 -1
  115. {pyflutter_app-0.2.4 → pyflutter_app-0.2.6}/table_stream/workbook.py +0 -0
@@ -1,11 +1,15 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pyflutter_app
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Bibliotecas Python para conversão de documentos, interface e processamento de tabelas.
5
5
  Requires-Python: >=3.12
6
+ Requires-Dist: opencv-python>=5.0.0.93
6
7
  Requires-Dist: openpyxl>=3.1.5
7
8
  Requires-Dist: pandas-stubs~=3.0.3
8
9
  Requires-Dist: pandas>=3.0.0
10
+ Requires-Dist: playwright>=1.63.0
11
+ Requires-Dist: pymupdf>=1.28.2
12
+ Requires-Dist: pytesseract>=0.3.13
9
13
  Description-Content-Type: text/markdown
10
14
 
11
15
  # pyflutter
@@ -0,0 +1,17 @@
1
+ from ._table_toi import (
2
+ HeaderTOI,
3
+ HeaderFormsTOI,
4
+ TableTOI,
5
+ LocalEntregaCarta,
6
+ TipoCarta,
7
+ BuilderTablesTOI,
8
+ )
9
+
10
+ from .find_toi import extrair_uc_toi
11
+ from .common import BuilderConfigTOI, ConfigTOI
12
+
13
+ from .relatorio import (
14
+ ControllerTOI,
15
+ ReadWriteTableTOI,
16
+ load_files_toi,
17
+ )
@@ -0,0 +1,249 @@
1
+ from __future__ import annotations
2
+ from enum import StrEnum
3
+ from typing import Any, Callable, TypeVar
4
+
5
+ from pandas import DataFrame
6
+
7
+ from cartas.util import (
8
+ ArrayList,
9
+ HashMapDict,
10
+ Table,
11
+ TableData,
12
+ ColumnV,
13
+ RowH,
14
+ PathElement,
15
+ Directory,
16
+ File,
17
+ concat_tables,
18
+ ColumnNotFoundError,
19
+ )
20
+
21
+ from table_stream import (
22
+ HeaderMetaData,
23
+ HeadersSizeNotIqualError,
24
+ hashFile,
25
+ load_file_hash,
26
+ )
27
+
28
+ from cartas.common import ConfigTOI, BuilderConfigTOI
29
+ import pandas as pd
30
+
31
+
32
+ class HeaderTOI(StrEnum):
33
+ """
34
+ Enumerador que representa a relação entre um documento e os dados
35
+ de entrega, como UC, TOI DATA etc...
36
+ a relação/key de uma entrega e a hash do documento.
37
+ """
38
+
39
+ UC = "uc"
40
+ TOI = "toi"
41
+ DAY = "day"
42
+ MON = "mon"
43
+ YEAR = "year"
44
+ DATE = "data_entrega"
45
+ HASH_FILE = HeaderMetaData.HASH_FILE.value
46
+
47
+
48
+ class HeaderFormsTOI(StrEnum):
49
+ """
50
+ Dados completos de uma entrega TOI, incluindo os metadados e
51
+ caminho absoluto dos arquivos.
52
+ """
53
+
54
+ UC = HeaderTOI.UC
55
+ TOI = HeaderTOI.TOI
56
+ DAY = HeaderTOI.DAY
57
+ MON = HeaderTOI.MON
58
+ YEAR = HeaderTOI.YEAR
59
+ DATE = HeaderTOI.DATE
60
+ HASH_FILE = HeaderTOI.HASH_FILE
61
+
62
+ LOCAL_ENTREGA = "local_entrega"
63
+ TIPO_DOC = "tipo_carta"
64
+
65
+ IS_FILE = "arquivo?"
66
+ FULL_PATH = HeaderMetaData.FILE_PATH.value
67
+ SRC = HeaderMetaData.PARENT_DIR.value
68
+ FILE_EXTENSION = HeaderMetaData.FILE_EXTENSION.value
69
+ FILE_BASENAME = "basename"
70
+
71
+
72
+ class TipoCarta(StrEnum):
73
+
74
+ CARTA_CALCULO = "CARTA-CALCULO"
75
+
76
+
77
+ class LocalEntregaCarta(StrEnum):
78
+
79
+ OUTRO = "OUTRO"
80
+ MAOS = "MÃOS"
81
+ CORREIOS = "CORREIOS"
82
+ PORTAO = "PORTÃO"
83
+
84
+
85
+ class TableTOI(TableData[HeaderTOI]):
86
+ """
87
+ Tabela para representar dados de das entregas de uma carta TOI. Não inclui meta dados dos arquivos.
88
+ """
89
+
90
+ def __init__(self, data: DataFrame | None = None) -> None:
91
+ super().__init__(data)
92
+
93
+ def rows(self) -> ArrayList[RowH[HeaderTOI, Any]]:
94
+ return super().rows()
95
+
96
+ def select_columns(self, header: list[HeaderTOI]) -> TableTOI:
97
+ return TableTOI.create_from_data(super().select_columns(header).to_dataframe())
98
+
99
+ def search(self, h: HeaderTOI, value: Any) -> TableTOI:
100
+ return TableTOI.create_from_data(super().search(h, value).to_dataframe())
101
+
102
+ def drop_duplicates(self) -> TableTOI:
103
+ return TableTOI(super().drop_duplicates().to_dataframe())
104
+
105
+ @classmethod
106
+ def create_from_data(cls, data: DataFrame) -> TableTOI:
107
+ return TableTOI.builder().create_table_toi_from_df(data)
108
+
109
+ @staticmethod
110
+ def builder() -> BuilderTablesTOI:
111
+ return BuilderTablesTOI()
112
+
113
+
114
+ class BuilderTablesTOI(object):
115
+
116
+ def __init__(self) -> None:
117
+
118
+ self.default_cols_toi = ArrayList[HeaderTOI].from_list(
119
+ [
120
+ HeaderTOI.UC,
121
+ HeaderTOI.TOI,
122
+ HeaderTOI.DATE,
123
+ HeaderTOI.YEAR,
124
+ HeaderTOI.MON,
125
+ HeaderTOI.DAY,
126
+ HeaderTOI.HASH_FILE,
127
+ ]
128
+ )
129
+
130
+ self.default_cols_forms = ArrayList[HeaderFormsTOI].from_list(
131
+ [
132
+ HeaderFormsTOI.UC,
133
+ HeaderFormsTOI.TOI,
134
+ HeaderFormsTOI.DATE,
135
+ HeaderFormsTOI.YEAR,
136
+ HeaderFormsTOI.MON,
137
+ HeaderFormsTOI.DAY,
138
+ HeaderFormsTOI.LOCAL_ENTREGA,
139
+ HeaderFormsTOI.TIPO_DOC,
140
+ HeaderFormsTOI.HASH_FILE,
141
+ HeaderFormsTOI.IS_FILE,
142
+ HeaderFormsTOI.FILE_BASENAME,
143
+ HeaderFormsTOI.FILE_EXTENSION,
144
+ HeaderFormsTOI.FULL_PATH,
145
+ HeaderFormsTOI.SRC,
146
+ ]
147
+ )
148
+
149
+ def create_table_toi(self) -> TableTOI:
150
+ """
151
+ Cria uma tabela TOI vazia com todos os itens do cabeçalho HeaderTOI
152
+ """
153
+
154
+ tb = TableTOI()
155
+ self.default_cols_toi.for_each(lambda c: tb.add(ColumnV(c)))
156
+ return tb
157
+
158
+ def create_table_toi_from_df(self, df: pd.DataFrame) -> TableTOI:
159
+ df = df.astype(str)
160
+ df_cols = ArrayList(df.columns.tolist())
161
+ tb = TableTOI()
162
+
163
+ c: HeaderTOI
164
+ for c in self.default_cols_toi:
165
+ if df_cols.contains(c.value):
166
+ tb.add(
167
+ ColumnV.create_from_list(c, df[c.value].astype(str).values.tolist())
168
+ )
169
+
170
+ if tb.header().size() != self.default_cols_toi.size():
171
+ raise HeadersSizeNotIqualError(
172
+ f"DataFrame() de entrega toi com colunas diferente do padrão: \n{tb.header()}"
173
+ )
174
+ return tb
175
+
176
+ def create_table_forms(self) -> TableData[HeaderFormsTOI]:
177
+ """
178
+ Cria uma tabela com os cabeçalhos de HeaderForms.
179
+ """
180
+ tb = TableData()
181
+ self.default_cols_forms.for_each(lambda c: tb.add(ColumnV(c)))
182
+ return tb
183
+
184
+ def create_table_forms_from_df(self, df: pd.DataFrame) -> TableData[HeaderFormsTOI]:
185
+ df = df.astype(str)
186
+ df_cols = ArrayList(df.columns.tolist())
187
+ final_table = TableData()
188
+
189
+ c: HeaderFormsTOI
190
+ for c in self.default_cols_forms:
191
+
192
+ if df_cols.contains(c.value):
193
+ final_table.add(
194
+ ColumnV.create_from_list(c, df[c.value].astype(str).values.tolist())
195
+ )
196
+
197
+ if final_table.header().size() != self.default_cols_forms.size():
198
+ msg = "DataFrame() FORMS toi com colunas diferente do padrão:"
199
+ msg_header = f"Cabeçalho FORMS {final_table.header()}"
200
+ raise HeadersSizeNotIqualError(
201
+ f"{msg} \n\n{msg_header}\nCabeçalho externo {df.columns}"
202
+ )
203
+ return final_table
204
+
205
+ def create_table_toi_from_file(self, path: File) -> TableTOI | None:
206
+ if not path.exists():
207
+ return None
208
+
209
+ mp = self.create_map_from_filename(path.name())
210
+ if mp is None:
211
+ return None
212
+
213
+ mp.set_value(HeaderTOI.HASH_FILE, load_file_hash(path))
214
+ tb = TableTOI()
215
+ c: HeaderTOI
216
+
217
+ for c in self.default_cols_toi:
218
+ tb.add(ColumnV.create_from_list(c, [mp.get_value(c)]))
219
+ return tb
220
+
221
+ def create_map_from_filename(
222
+ self, filename: str
223
+ ) -> HashMapDict[HeaderTOI, str] | None:
224
+ """
225
+ Retorna um Map de chave/valor com as seguintes chaves:
226
+
227
+ HeaderDocTOI.UC, HeaderDocTOI.TOI, HeaderDocTOI.DAY,
228
+ HeaderDocTOI.MON, HeaderDocTOI.YEAR e HeaderDocTOI.DATE.
229
+ """
230
+
231
+ try:
232
+ values = filename.split(" ")
233
+ if len(values) < 5:
234
+ return None
235
+ except:
236
+ return None
237
+ else:
238
+ for x in values:
239
+ if not x.isnumeric():
240
+ return None
241
+
242
+ data = HashMapDict()
243
+ data[HeaderTOI.UC] = values[0] # UC
244
+ data[HeaderTOI.TOI] = values[1] # TOI
245
+ data[HeaderTOI.DAY] = values[2] # DIA
246
+ data[HeaderTOI.MON] = values[3] # MÊS
247
+ data[HeaderTOI.YEAR] = values[4] # ANO
248
+ data[HeaderTOI.DATE] = f"{values[2]}/{values[3]}/{values[4]}"
249
+ return data
@@ -0,0 +1,67 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+
4
+ from cartas.util import File, Directory, UserFileSystem, BuilderConfigOcr
5
+
6
+
7
+ @dataclass
8
+ class ConfigTOI:
9
+
10
+ file_relatorio_toi: File
11
+ file_table_toi: File
12
+ dir_base_toi: Directory
13
+ work_dir: Directory
14
+
15
+
16
+ class BuilderConfigTOI(object):
17
+
18
+ _instance = None # Atributo de classe para armazenar a instância singleton
19
+
20
+ def __new__(cls, *args, **kwargs):
21
+ if cls._instance is None:
22
+ cls._instance = super(BuilderConfigTOI, cls).__new__(cls)
23
+ return cls._instance
24
+
25
+ def __init__(self) -> None:
26
+
27
+ # Garante que __init__ não será executado mais de uma vez
28
+ if hasattr(self, "_initialized") and self._initialized:
29
+ return
30
+
31
+ super().__init__()
32
+ self._initialized: bool = True
33
+ self._builder_ocr = BuilderConfigOcr.get_instance()
34
+ self._config = self._create()
35
+
36
+ @property
37
+ def dir_base_work(self) -> Directory:
38
+ return self._builder_ocr.builder().dir_base_work
39
+
40
+ @property
41
+ def dir_retorno_de_campo(self) -> Directory:
42
+ return self.dir_base_work.concat("Cartas-TOI", True).concat(
43
+ "Retorno-de-campo", True
44
+ )
45
+
46
+ @property
47
+ def file_relatorio_toi(self) -> File:
48
+ d = self._builder_ocr.builder().dir_table
49
+ return d.join_file("Relatorio-tois.xlsx")
50
+
51
+ @property
52
+ def file_table_toi(self) -> File:
53
+ d = self._builder_ocr.builder().dir_table
54
+ return d.join_file("Tabela-tois.xlsx")
55
+
56
+ def _create(self) -> ConfigTOI:
57
+ return ConfigTOI(
58
+ work_dir=self.dir_base_work,
59
+ dir_base_toi=self.dir_retorno_de_campo,
60
+ file_relatorio_toi=self.file_relatorio_toi,
61
+ file_table_toi=self.file_table_toi,
62
+ )
63
+
64
+ def builder(self) -> ConfigTOI:
65
+ if self._config is None:
66
+ self._config = self._create()
67
+ return self._config
@@ -0,0 +1,27 @@
1
+ import re
2
+
3
+
4
+ # ============================================================#
5
+ # Extração de UC/TOI tolerante a falhas de OCR
6
+ # ============================================================#
7
+ #
8
+ # UC: 1305934 TOI: 193166923 ...
9
+ # UC: 1305934 TO! 193166923 ... (TOI virou TO!, ":" some)
10
+ # UC| 1305934 T0I: 193166923 ... (0 no lugar do O)
11
+ #
12
+
13
+ UC_TOI_PATTERN = re.compile(
14
+ r"U[C0]\s*[:;|!]?\s*(\d{4,10})" r".{0,60}?" r"T[O0][I1L!l]?\s*[:;|!]?\s*(\d{4,10})",
15
+ re.IGNORECASE | re.DOTALL,
16
+ )
17
+
18
+
19
+ def extrair_uc_toi(texto: str) -> tuple[str, str] | None:
20
+ """
21
+ Retorna (uc, toi) a partir do texto OCR completo de um arquivo,
22
+ ou None se o padrão não for encontrado.
23
+ """
24
+ m = UC_TOI_PATTERN.search(texto)
25
+ if not m:
26
+ return None
27
+ return m.group(1), m.group(2)