feat: adicionar validação de erros no TXT e exibição no comparador DMED
This commit is contained in:
Vendored
BIN
Binary file not shown.
+107
-2
@@ -27,9 +27,18 @@ struct ComparadorApp {
|
|||||||
divergencias: Vec<Divergencia>,
|
divergencias: Vec<Divergencia>,
|
||||||
cpfs_so_txt: Vec<CpfExclusivo>,
|
cpfs_so_txt: Vec<CpfExclusivo>,
|
||||||
cpfs_so_xls: Vec<CpfExclusivo>,
|
cpfs_so_xls: Vec<CpfExclusivo>,
|
||||||
|
erros_validacao: Vec<ErroValidacao>,
|
||||||
processando: bool,
|
processando: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct ErroValidacao {
|
||||||
|
cpf: String,
|
||||||
|
nome: String,
|
||||||
|
valor: f64,
|
||||||
|
tipo_erro: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct CpfExclusivo {
|
struct CpfExclusivo {
|
||||||
cpf: String,
|
cpf: String,
|
||||||
@@ -230,8 +239,42 @@ impl eframe::App for ComparadorApp {
|
|||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Erros de validação
|
||||||
|
if !self.erros_validacao.is_empty() {
|
||||||
|
ui.separator();
|
||||||
|
ui.add_space(5.0);
|
||||||
|
ui.heading(format!("❌ Erros de validação no TXT: {}", self.erros_validacao.len()));
|
||||||
|
ui.label("Estes registros possuem problemas que precisam ser corrigidos");
|
||||||
|
ui.add_space(5.0);
|
||||||
|
|
||||||
|
egui::ScrollArea::vertical()
|
||||||
|
.max_height(150.0)
|
||||||
|
.show(ui, |ui| {
|
||||||
|
egui::Grid::new("erros_validacao_grid")
|
||||||
|
.striped(true)
|
||||||
|
.min_col_width(100.0)
|
||||||
|
.show(ui, |ui| {
|
||||||
|
ui.strong("CPF");
|
||||||
|
ui.strong("Nome");
|
||||||
|
ui.strong("Valor (R$)");
|
||||||
|
ui.strong("Erro");
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
for erro in &self.erros_validacao {
|
||||||
|
ui.label(&erro.cpf);
|
||||||
|
ui.label(&erro.nome);
|
||||||
|
ui.label(Self::formatar_valor(erro.valor));
|
||||||
|
ui.colored_label(egui::Color32::RED, &erro.tipo_erro);
|
||||||
|
ui.end_row();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.add_space(10.0);
|
||||||
|
}
|
||||||
|
|
||||||
// Botão para exportar (mostra se tiver qualquer resultado)
|
// Botão para exportar (mostra se tiver qualquer resultado)
|
||||||
if !self.divergencias.is_empty() || !self.cpfs_so_txt.is_empty() || !self.cpfs_so_xls.is_empty() {
|
if !self.divergencias.is_empty() || !self.cpfs_so_txt.is_empty() || !self.cpfs_so_xls.is_empty() || !self.erros_validacao.is_empty() {
|
||||||
ui.separator();
|
ui.separator();
|
||||||
ui.add_space(5.0);
|
ui.add_space(5.0);
|
||||||
|
|
||||||
@@ -254,6 +297,10 @@ impl eframe::App for ComparadorApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ComparadorApp {
|
impl ComparadorApp {
|
||||||
|
fn nome_tem_numero(nome: &str) -> bool {
|
||||||
|
nome.chars().any(|c| c.is_ascii_digit())
|
||||||
|
}
|
||||||
|
|
||||||
fn formatar_valor(valor: f64) -> String {
|
fn formatar_valor(valor: f64) -> String {
|
||||||
let valor_abs = valor.abs();
|
let valor_abs = valor.abs();
|
||||||
let inteiro = valor_abs.trunc() as u64;
|
let inteiro = valor_abs.trunc() as u64;
|
||||||
@@ -285,6 +332,7 @@ impl ComparadorApp {
|
|||||||
self.divergencias.clear();
|
self.divergencias.clear();
|
||||||
self.cpfs_so_txt.clear();
|
self.cpfs_so_txt.clear();
|
||||||
self.cpfs_so_xls.clear();
|
self.cpfs_so_xls.clear();
|
||||||
|
self.erros_validacao.clear();
|
||||||
|
|
||||||
let txt_path = self.arquivo_txt.as_ref().unwrap().clone();
|
let txt_path = self.arquivo_txt.as_ref().unwrap().clone();
|
||||||
let xls_path = self.arquivo_xls.as_ref().unwrap().clone();
|
let xls_path = self.arquivo_xls.as_ref().unwrap().clone();
|
||||||
@@ -335,6 +383,34 @@ impl ComparadorApp {
|
|||||||
.filter(|cpf| !mapa_txt.contains_key(**cpf))
|
.filter(|cpf| !mapa_txt.contains_key(**cpf))
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
|
// Validações no TXT
|
||||||
|
for pessoa in &pessoas_txt {
|
||||||
|
let mut erros = Vec::new();
|
||||||
|
|
||||||
|
// Validação 1: Valor zerado
|
||||||
|
if pessoa.valor == 0.0 {
|
||||||
|
erros.push("Valor zerado");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validação 2: Nome com número
|
||||||
|
if Self::nome_tem_numero(&pessoa.nome) {
|
||||||
|
erros.push("Nome contém número");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Se houver erros, adiciona à lista
|
||||||
|
if !erros.is_empty() {
|
||||||
|
self.erros_validacao.push(ErroValidacao {
|
||||||
|
cpf: pessoa.cpf.clone(),
|
||||||
|
nome: pessoa.nome.clone(),
|
||||||
|
valor: pessoa.valor,
|
||||||
|
tipo_erro: erros.join(" | "),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ordena erros por CPF
|
||||||
|
self.erros_validacao.sort_by(|a, b| a.cpf.cmp(&b.cpf));
|
||||||
|
|
||||||
// Encontra divergências
|
// Encontra divergências
|
||||||
let margem_tolerancia = 0.01;
|
let margem_tolerancia = 0.01;
|
||||||
|
|
||||||
@@ -390,7 +466,8 @@ impl ComparadorApp {
|
|||||||
|
|
||||||
// Resultado
|
// Resultado
|
||||||
let diferenca_total = total_txt - total_xls;
|
let diferenca_total = total_txt - total_xls;
|
||||||
self.resultado = format!(
|
|
||||||
|
let resultado_base = format!(
|
||||||
"📊 Estatísticas:\n\
|
"📊 Estatísticas:\n\
|
||||||
• Total TXT: {} registros\n\
|
• Total TXT: {} registros\n\
|
||||||
• Total XLS: {} registros únicos\n\
|
• Total XLS: {} registros únicos\n\
|
||||||
@@ -414,6 +491,13 @@ impl ComparadorApp {
|
|||||||
Self::formatar_valor(diferenca_total)
|
Self::formatar_valor(diferenca_total)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.resultado = if !self.erros_validacao.is_empty() {
|
||||||
|
format!("{}\n\n❌ ATENÇÃO: {} erros de validação encontrados no TXT!",
|
||||||
|
resultado_base, self.erros_validacao.len())
|
||||||
|
} else {
|
||||||
|
resultado_base
|
||||||
|
};
|
||||||
|
|
||||||
self.processando = false;
|
self.processando = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,10 +515,31 @@ impl ComparadorApp {
|
|||||||
writeln!(arquivo, " • Total de divergências de valores: {}", self.divergencias.len())?;
|
writeln!(arquivo, " • Total de divergências de valores: {}", self.divergencias.len())?;
|
||||||
writeln!(arquivo, " • CPFs apenas no TXT: {}", self.cpfs_so_txt.len())?;
|
writeln!(arquivo, " • CPFs apenas no TXT: {}", self.cpfs_so_txt.len())?;
|
||||||
writeln!(arquivo, " • CPFs apenas no XLS: {}", self.cpfs_so_xls.len())?;
|
writeln!(arquivo, " • CPFs apenas no XLS: {}", self.cpfs_so_xls.len())?;
|
||||||
|
writeln!(arquivo, " • Erros de validação no TXT: {}", self.erros_validacao.len())?;
|
||||||
writeln!(arquivo)?;
|
writeln!(arquivo)?;
|
||||||
writeln!(arquivo, "{}", "=".repeat(120))?;
|
writeln!(arquivo, "{}", "=".repeat(120))?;
|
||||||
writeln!(arquivo)?;
|
writeln!(arquivo)?;
|
||||||
|
|
||||||
|
// Erros de validação
|
||||||
|
if !self.erros_validacao.is_empty() {
|
||||||
|
writeln!(arquivo, "❌ ERROS DE VALIDAÇÃO NO TXT ({} registros)", self.erros_validacao.len())?;
|
||||||
|
writeln!(arquivo, " Estes registros possuem problemas que DEVEM ser corrigidos")?;
|
||||||
|
writeln!(arquivo, "{}", "-".repeat(120))?;
|
||||||
|
writeln!(arquivo, "{:<15} {:<40} {:>15} {:<30}", "CPF", "Nome", "Valor (R$)", "Erro")?;
|
||||||
|
writeln!(arquivo, "{}", "-".repeat(120))?;
|
||||||
|
|
||||||
|
for erro in &self.erros_validacao {
|
||||||
|
writeln!(arquivo, "{:<15} {:<40} {:>15} {:<30}",
|
||||||
|
erro.cpf,
|
||||||
|
erro.nome,
|
||||||
|
Self::formatar_valor(erro.valor),
|
||||||
|
erro.tipo_erro)?;
|
||||||
|
}
|
||||||
|
writeln!(arquivo)?;
|
||||||
|
writeln!(arquivo, "{}", "=".repeat(120))?;
|
||||||
|
writeln!(arquivo)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Divergências de valores
|
// Divergências de valores
|
||||||
if !self.divergencias.is_empty() {
|
if !self.divergencias.is_empty() {
|
||||||
writeln!(arquivo, "🔍 DIVERGÊNCIAS DE VALORES ({} registros)", self.divergencias.len())?;
|
writeln!(arquivo, "🔍 DIVERGÊNCIAS DE VALORES ({} registros)", self.divergencias.len())?;
|
||||||
|
|||||||
Reference in New Issue
Block a user