use thiserror::Error; #[derive(Debug, Error, Clone)] pub enum ErroSerie { #[error("Série inválida: '{0}' (deve conter de 1 a 3 dígitos numéricos)")] Invalida(String), #[error("Série vazia")] Vazia, } #[derive(Debug, Error, Clone)] pub enum ErroValor { #[error("Valor negativo não é permitido: '{0}'")] Negativo(String), #[error("Valor não numérico: '{0}'")] NaoNumerico(String), } #[derive(Debug, Error, Clone)] pub enum ErroLayout { #[error("Campo obrigatório ausente: '{0}'")] CampoObrigatorioAusente(String), #[error("JSON malformado: {0}")] JsonMalformado(String), #[error("Conflito de nome: layout '{0}' já existe")] NomeConflitante(String), } #[derive(Debug, Error, Clone)] pub enum ErroArquivo { #[error("Arquivo muito grande ({0} bytes). Limite: 50 MB")] TamanhoExcedido(u64), #[error("Arquivo corrompido ou ilegível: {0}")] Corrompido(String), #[error("Erro de leitura: {0}")] ErroLeitura(String), } /// Resumo consolidado de avisos para exibição em um único modal. #[derive(Debug, Default, Clone)] pub struct ResumoAvisos { pub linhas_malformadas: usize, pub numeros_invalidos: usize, pub series_invalidas: usize, pub valores_invalidos: usize, pub detalhes: Vec, } impl ResumoAvisos { pub fn tem_avisos(&self) -> bool { self.linhas_malformadas > 0 || self.numeros_invalidos > 0 || self.series_invalidas > 0 || self.valores_invalidos > 0 } pub fn linhas_para_exibir(&self) -> Vec { let mut linhas = Vec::new(); if self.linhas_malformadas > 0 { linhas.push(format!( "{} linhas descartadas por malformação", self.linhas_malformadas )); } if self.numeros_invalidos > 0 { linhas.push(format!( "{} valores de Numero inválidos convertidos ou descartados", self.numeros_invalidos )); } if self.series_invalidas > 0 { linhas.push(format!( "{} registros com Série inválida descartados", self.series_invalidas )); } if self.valores_invalidos > 0 { linhas.push(format!( "{} valores monetários inválidos descartados", self.valores_invalidos )); } linhas.extend(self.detalhes.clone()); linhas } }