Guilherme Silberfarb Costa commited on
Commit
3bda4f3
·
1 Parent(s): d4612a2

Review venal values per SIAT exercise

Browse files
extractors/pdf_extractor.py CHANGED
@@ -22,18 +22,18 @@ def anos_venais_ausentes(anos):
22
 
23
 
24
  def anos_venais_para_revisao(registros):
25
- """Identifica anos repetidos ou com quantidade inesperada de valores monetários."""
26
  contagem_por_ano = {}
27
- anos_com_linhas_incorretas = set()
28
- for ano, quantidade_valores, _ in registros:
29
  contagem_por_ano[ano] = contagem_por_ano.get(ano, 0) + 1
30
- if quantidade_valores != 3:
31
- anos_com_linhas_incorretas.add(ano)
32
 
33
  return [
34
  int(ano)
35
  for ano in contagem_por_ano
36
- if contagem_por_ano[ano] > 1 or ano in anos_com_linhas_incorretas
37
  ]
38
 
39
 
@@ -175,7 +175,11 @@ def extrair_dados_pdf(pdf_file) -> Optional[Dict]:
175
  try:
176
  ano = re.search(r'(\d{4})', m).group(1)
177
  valores = re.findall(r'(\d{1,3}(?:\.\d{3})*,\d{2})', m)
178
- registros_venais.append((ano, len(valores), valores[2] if len(valores) >= 3 else None))
 
 
 
 
179
  except (AttributeError, IndexError):
180
  continue
181
 
 
22
 
23
 
24
  def anos_venais_para_revisao(registros):
25
+ """Identifica anos repetidos ou com mais de uma linha de lançamento venal."""
26
  contagem_por_ano = {}
27
+ anos_com_linhas_adicionais = set()
28
+ for ano, quantidade_linhas, _ in registros:
29
  contagem_por_ano[ano] = contagem_por_ano.get(ano, 0) + 1
30
+ if quantidade_linhas > 1:
31
+ anos_com_linhas_adicionais.add(ano)
32
 
33
  return [
34
  int(ano)
35
  for ano in contagem_por_ano
36
+ if contagem_por_ano[ano] > 1 or ano in anos_com_linhas_adicionais
37
  ]
38
 
39
 
 
175
  try:
176
  ano = re.search(r'(\d{4})', m).group(1)
177
  valores = re.findall(r'(\d{1,3}(?:\.\d{3})*,\d{2})', m)
178
+ # Cada lançamento traz seis valores monetários: construção, terreno,
179
+ # total, alíquota, IPTU e TCL/multa. Mais de seis indica outra linha
180
+ # de lançamento para o mesmo exercício e exige conferência manual.
181
+ linhas_venais = len(valores) // 6
182
+ registros_venais.append((ano, linhas_venais, valores[2] if len(valores) >= 3 else None))
183
  except (AttributeError, IndexError):
184
  continue
185
 
frontend/src/App.jsx CHANGED
@@ -182,7 +182,7 @@ function App() {
182
  const [databaseColumns, setDatabaseColumns] = useState([]);
183
 
184
  const [error, setError] = useState("");
185
- const [pdfWarning, setPdfWarning] = useState("");
186
  const [result, setResult] = useState(null);
187
 
188
  useEffect(() => {
@@ -406,7 +406,7 @@ function App() {
406
 
407
  setLoadingPdf(true);
408
  setError("");
409
- setPdfWarning("");
410
 
411
  try {
412
  const formData = new FormData();
@@ -439,12 +439,12 @@ function App() {
439
  avisos.push(
440
  `${anosRevisao.length === 1 ? "O ano" : "Os anos"} ${anosRevisao.join(", ")} ${
441
  anosRevisao.length === 1 ? "aparece" : "aparecem"
442
- } mais de uma vez ou possui${anosRevisao.length === 1 ? "" : "em"} uma quantidade inesperada de valores venais. ` +
443
  "Foi inserido como XXX.XXX,XX para revisão.",
444
  );
445
  }
446
  if (avisos.length) {
447
- setPdfWarning(`${avisos.join(" ")} Complete manualmente o campo “Valores Venais”.`);
448
  }
449
  } catch (err) {
450
  setError(String(err));
@@ -478,7 +478,7 @@ function App() {
478
  setForm(buildEmptyForm(options));
479
  setDatabaseColumns([]);
480
  setError("");
481
- setPdfWarning("");
482
  setResult(null);
483
  };
484
 
@@ -787,7 +787,11 @@ function App() {
787
  </button>
788
  </div>
789
 
790
- {pdfWarning && <div className="warning-box">{pdfWarning}</div>}
 
 
 
 
791
 
792
  <label>
793
  Inscrição
 
182
  const [databaseColumns, setDatabaseColumns] = useState([]);
183
 
184
  const [error, setError] = useState("");
185
+ const [pdfWarnings, setPdfWarnings] = useState([]);
186
  const [result, setResult] = useState(null);
187
 
188
  useEffect(() => {
 
406
 
407
  setLoadingPdf(true);
408
  setError("");
409
+ setPdfWarnings([]);
410
 
411
  try {
412
  const formData = new FormData();
 
439
  avisos.push(
440
  `${anosRevisao.length === 1 ? "O ano" : "Os anos"} ${anosRevisao.join(", ")} ${
441
  anosRevisao.length === 1 ? "aparece" : "aparecem"
442
+ } mais de uma vez ou ${anosRevisao.length === 1 ? "possui" : "possuem"} mais de uma linha de valor venal. ` +
443
  "Foi inserido como XXX.XXX,XX para revisão.",
444
  );
445
  }
446
  if (avisos.length) {
447
+ setPdfWarnings(avisos.map((aviso) => `${aviso} Complete manualmente o campo “Valores Venais”.`));
448
  }
449
  } catch (err) {
450
  setError(String(err));
 
478
  setForm(buildEmptyForm(options));
479
  setDatabaseColumns([]);
480
  setError("");
481
+ setPdfWarnings([]);
482
  setResult(null);
483
  };
484
 
 
787
  </button>
788
  </div>
789
 
790
+ {pdfWarnings.map((warning) => (
791
+ <div className="warning-box" key={warning}>
792
+ {warning}
793
+ </div>
794
+ ))}
795
 
796
  <label>
797
  Inscrição
tests/test_pdf_extractor.py CHANGED
@@ -44,11 +44,15 @@ Documento de Origem
44
  def test_marca_anos_repetidos_ou_com_linhas_extras_para_revisao(self):
45
  registros = [
46
  ("2023", 3, "300.000,00"),
47
- ("2024", 4, "320.000,00"),
48
  ("2023", 3, "300.000,00"),
49
  ]
50
  self.assertEqual(anos_venais_para_revisao(registros), [2023, 2024])
51
 
 
 
 
 
52
 
53
  if __name__ == "__main__":
54
  unittest.main()
 
44
  def test_marca_anos_repetidos_ou_com_linhas_extras_para_revisao(self):
45
  registros = [
46
  ("2023", 3, "300.000,00"),
47
+ ("2024", 2, "320.000,00"),
48
  ("2023", 3, "300.000,00"),
49
  ]
50
  self.assertEqual(anos_venais_para_revisao(registros), [2023, 2024])
51
 
52
+ def test_uma_linha_venal_por_ano_nao_exige_revisao(self):
53
+ registros = [("2021", 1, "293.882,68"), ("2022", 1, "325.240,88")]
54
+ self.assertEqual(anos_venais_para_revisao(registros), [])
55
+
56
 
57
  if __name__ == "__main__":
58
  unittest.main()