atualiza versão do PRD para 1.5 e detalha campos lógicos e regras de validação
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# PRD — Comparador de Notas
|
||||
|
||||
**Versão:** 1.3
|
||||
**Versão:** 1.5
|
||||
**Data:** 02/03/2026
|
||||
**Status:** Planejamento
|
||||
|
||||
@@ -100,10 +100,10 @@ O sistema trabalhará com os seguintes campos lógicos:
|
||||
|
||||
| Campo | Obrigatório | Descrição |
|
||||
| ------ | ----------- | ------------------------------------------------------------------------- |
|
||||
| Numero | Sim | Número incremental da nota. Junto com a Série forma o identificador único |
|
||||
| Serie | Sim | Série da nota (1–3 dígitos, ex: 001–999). Separa lotes de emissão |
|
||||
| Valor | Não | Valor monetário da nota |
|
||||
| Data | Não | Data de emissão da nota |
|
||||
| Numero | Sim | Número incremental da nota. Junto com a Série forma o identificador único. Armazenado internamente como `u64`. |
|
||||
| Serie | Sim | Série da nota. Deve conter de 1 a 3 dígitos numéricos (regex: `[0-9]{1,3}`, ex: `1`, `01`, `001`). Separa lotes de emissão. |
|
||||
| Valor | Não | Valor monetário da nota. Armazenado internamente como decimal fixo (`rust_decimal`). |
|
||||
| Data | Não | Data de emissão da nota. Quando mapeado, exibido como informação adicional no relatório PDF. Não participa de nenhuma regra de validação ou cálculo. |
|
||||
|
||||
Os campos serão mapeados pelo usuário conforme o tipo de arquivo: via **índice numérico** (base 0) para CSV, e via **notação LetraLinha** (ex: `B3`) para XLSX.
|
||||
|
||||
@@ -253,6 +253,18 @@ Registros com o campo Numero igual a `0` devem ser descartados e reportados ao u
|
||||
|
||||
Faltantes são detectados **por série**. Cada série possui sua própria sequência independente.
|
||||
|
||||
### Série com Apenas um Registro
|
||||
|
||||
Se uma série contiver apenas um registro, o intervalo de sequência é `numero..numero`. Não há faltantes nesse caso. A série é processada e exibida normalmente.
|
||||
|
||||
### Ordenação
|
||||
|
||||
A ordenação dos registros dentro de cada série é sempre **numérica crescente**, independentemente do formato original do campo Numero no arquivo de entrada.
|
||||
|
||||
### Exibição do Campo Numero
|
||||
|
||||
O campo Numero é armazenado e processado como inteiro. Na exibição (listas de faltantes, duplicatas e relatório PDF), o número é exibido **sem zeros à esquerda** (ex: `0001` é exibido como `1`). O formato de exibição não altera a lógica de detecção ou ordenação.
|
||||
|
||||
### Proteção contra Intervalos Anormalmente Grandes
|
||||
|
||||
Se o intervalo de faltantes de qualquer série exceder **10.000 registros**, o sistema deve:
|
||||
@@ -267,11 +279,15 @@ Esse comportamento protege contra mapeamentos incorretos de colunas que gerariam
|
||||
|
||||
### Tratamento de Série com Valor Inválido
|
||||
|
||||
Se o campo Série de um registro estiver vazio ou contiver valor não utilizável:
|
||||
A Série é válida se e somente se corresponder à regex `[0-9]{1,3}` após remoção de espaços.
|
||||
|
||||
Se o campo Série de um registro estiver vazio, não corresponder à regex ou contiver valor não utilizável:
|
||||
|
||||
1. O registro deve ser descartado
|
||||
2. O sistema deve reportar ao usuário quais linhas foram afetadas, sem interromper a importação
|
||||
|
||||
Exemplos de valores inválidos: `ABC`, `1A`, `1234` (4 dígitos), string vazia.
|
||||
|
||||
---
|
||||
|
||||
## RF05 — Detecção de Duplicidade
|
||||
@@ -299,20 +315,41 @@ O sistema deve calcular:
|
||||
|
||||
### Formato de Valor Aceito
|
||||
|
||||
O sistema deve aceitar valores numéricos com ponto **ou** vírgula como separador decimal, detectando o formato automaticamente por registro.
|
||||
O sistema deve aceitar valores numéricos em formato brasileiro ou americano, detectando o formato automaticamente por registro seguindo o algoritmo abaixo.
|
||||
|
||||
| Exemplo de entrada | Resultado parseado |
|
||||
| ------------------ | ------------------ |
|
||||
| `1000.00` | 1000,00 |
|
||||
| `1000,00` | 1000,00 |
|
||||
| `1.000,00` | 1000,00 |
|
||||
| `1,000.00` | 1000,00 |
|
||||
| `1.000` | 1000,00 (ponto interpretado como separador de milhar quando seguido de exatamente 3 dígitos sem parte decimal subsequente) |
|
||||
#### Algoritmo de Parsing Monetário
|
||||
|
||||
**Regra 1 — Contém ambos ponto e vírgula:**
|
||||
- O último separador encontrado é o decimal; o outro é o separador de milhar.
|
||||
- Exemplos: `1.000,00` → 1.000,00 | `1,000.00` → 1.000,00
|
||||
|
||||
**Regra 2 — Contém apenas um separador:**
|
||||
- Vírgula ou ponto com **exatamente 2 dígitos** após → separador decimal.
|
||||
- Exemplos: `1000,00` → 1.000,00 | `1000.00` → 1.000,00
|
||||
- Vírgula ou ponto com **exatamente 3 dígitos** após → separador de milhar.
|
||||
- Exemplos: `1,234` → 1.234,00 | `1.234` → 1.234,00
|
||||
- Demais casos → separador tratado como decimal.
|
||||
|
||||
**Regra 3 — Sem separador:**
|
||||
- Interpretar como número inteiro.
|
||||
- Exemplo: `1000` → 1.000,00
|
||||
|
||||
| Exemplo de entrada | Regra aplicada | Resultado parseado |
|
||||
| ------------------ | ---------------------------------- | ------------------ |
|
||||
| `1000.00` | Regra 2 (ponto + 2 dígitos) | 1.000,00 |
|
||||
| `1000,00` | Regra 2 (vírgula + 2 dígitos) | 1.000,00 |
|
||||
| `1.000,00` | Regra 1 (ambos separadores) | 1.000,00 |
|
||||
| `1,000.00` | Regra 1 (ambos separadores) | 1.000,00 |
|
||||
| `1.000` | Regra 2 (ponto + 3 dígitos) | 1.000,00 |
|
||||
| `1,234` | Regra 2 (vírgula + 3 dígitos) | 1.234,00 |
|
||||
| `1000` | Regra 3 (sem separador) | 1.000,00 |
|
||||
|
||||
Valores negativos (precedidos de `-`) devem ser rejeitados e reportados ao usuário como inválidos.
|
||||
|
||||
Valores que não puderem ser interpretados como número devem ser descartados e reportados ao usuário.
|
||||
|
||||
> **Nota de implementação:** O valor deve ser parseado e armazenado internamente como `rust_decimal::Decimal`, nunca como `f64`. Aritmética de ponto flutuante introduz erros de representação em valores monetários (ex: `0.1 + 0.2 ≠ 0.3` em IEEE 754). A soma total e as somas por série devem ser calculadas inteiramente em `Decimal`.
|
||||
|
||||
### Formato de Exibição de Valores
|
||||
|
||||
Todos os valores monetários são exibidos com **2 casas decimais fixas** no formato brasileiro (ex: `1.234,56`).
|
||||
@@ -387,6 +424,8 @@ O sistema deve suportar no mínimo:
|
||||
|
||||
100.000 registros por arquivo
|
||||
|
||||
> **Nota de implementação:** A detecção de faltantes deve ser implementada de forma **incremental** — ordenar a lista e percorrer comparando elementos consecutivos — evitando a geração de listas intermediárias completas antes da confirmação do usuário. Isso garante consumo de memória proporcional aos dados reais, não ao intervalo.
|
||||
|
||||
---
|
||||
|
||||
## RNF04 — Usabilidade
|
||||
@@ -405,6 +444,16 @@ O idioma da interface é **Português do Brasil (PT-BR)**.
|
||||
|
||||
Todas as mensagens de erro e aviso devem ser exibidas em **modal/popup bloqueante**. O usuário deve fechar o modal explicitamente para continuar.
|
||||
|
||||
### Consolidação de Mensagens
|
||||
|
||||
Quando múltiplos avisos forem gerados durante uma mesma operação (ex: múltiplas linhas malformadas, múltiplos registros descartados), esses avisos devem ser **consolidados em um único modal**, exibindo um resumo ao final da operação. Exemplo de conteúdo consolidado:
|
||||
|
||||
* "32 linhas descartadas por mal formação"
|
||||
* "12 valores de Numero inválidos convertidos ou descartados"
|
||||
* "5 registros com Série inválida descartados"
|
||||
|
||||
Cada categoria de problema deve ser exibida como um item separado dentro do mesmo modal. Nunca devem ser abertos múltiplos modais sequenciais para a mesma operação de importação.
|
||||
|
||||
---
|
||||
|
||||
# 8. Fluxo do Usuário
|
||||
@@ -443,6 +492,7 @@ Sem dependências externas obrigatórias.
|
||||
| SQLite | rusqlite | Definido |
|
||||
| Leitura de CSV | csv | Definido |
|
||||
| Leitura de XLSX | calamine | Definido |
|
||||
| Decimal fixo | rust_decimal | Definido |
|
||||
| Geração de PDF | genpdf | Definido |
|
||||
|
||||
---
|
||||
@@ -489,10 +539,11 @@ O diretório e o arquivo devem ser **criados automaticamente** pelo sistema na p
|
||||
Se o arquivo `config.db` estiver ilegível ou corrompido ao iniciar o programa, o sistema deve:
|
||||
|
||||
1. Exibir aviso ao usuário informando que o banco de dados está corrompido e será recriado
|
||||
2. Recriar o banco de dados vazio
|
||||
3. Continuar a execução normalmente
|
||||
2. Renomear o arquivo corrompido para `config.db.bak` (sobrescrevendo qualquer `.bak` anterior)
|
||||
3. Criar um novo banco de dados vazio
|
||||
4. Continuar a execução normalmente
|
||||
|
||||
Os layouts salvos anteriormente serão perdidos neste cenário.
|
||||
Os layouts salvos anteriormente serão perdidos neste cenário. O arquivo `config.db.bak` permanece no disco e permite recuperação manual por usuários avançados.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user