atualiza versão do PRD para 1.6 e detalha arquitetura e estrutura de pastas do projeto

This commit is contained in:
2026-03-02 21:39:05 -03:00
parent 9d212747e7
commit 31cd94907a
2 changed files with 613 additions and 12 deletions
+184 -12
View File
@@ -1,6 +1,6 @@
# PRD — Comparador de Notas
**Versão:** 1.5
**Versão:** 1.6
**Data:** 02/03/2026
**Status:** Planejamento
@@ -468,22 +468,194 @@ Fluxo principal:
---
# 9. Arquitetura Inicial Sugerida
# 9. Arquitetura
Arquitetura desktop local.
Arquitetura desktop local com separação em quatro camadas: `domain`, `application`, `infrastructure` e `ui`.
Componentes:
* Interface gráfica
* Módulo de importação
* Módulo de processamento
* Módulo de configuração
Sem dependências externas obrigatórias.
Não é Clean Architecture radical. É apenas separação suficiente para manter fronteiras claras, domínio isolado e infraestrutura concreta sem vazar para a lógica de negócio.
---
## 9.1 Stack Tecnológica
## 9.1 Estrutura de Pastas
```
src/
├─ main.rs
├─ ui/
│ ├─ mod.rs
│ ├─ app.rs
│ ├─ screens/
│ │ ├─ import.rs
│ │ ├─ configuracao_colunas.rs
│ │ ├─ layouts.rs
│ │ ├─ resultado.rs
├─ application/
│ ├─ mod.rs
│ ├─ usecases/
│ │ ├─ importar_arquivo.rs
│ │ ├─ executar_analise.rs
│ │ ├─ exportar_pdf.rs
├─ domain/
│ ├─ mod.rs
│ ├─ errors.rs
│ ├─ entities/
│ │ ├─ nota.rs
│ │ ├─ serie.rs
│ │ ├─ layout.rs
│ │ ├─ resultado_analise.rs
│ │
│ ├─ services/
│ │ ├─ detector_sequencia.rs
│ │ ├─ detector_duplicidade.rs
│ │ ├─ parser_monetario.rs
├─ infrastructure/
│ ├─ mod.rs
│ ├─ csv_reader.rs
│ ├─ xlsx_reader.rs
│ ├─ pdf_generator.rs
│ ├─ sqlite/
│ │ ├─ mod.rs
│ │ ├─ connection.rs
│ │ ├─ migrations.rs
│ │ ├─ layout_repository.rs
```
---
## 9.2 Papel de Cada Camada
### Domain (núcleo puro)
Contém toda a lógica de negócio real.
**Não pode depender de:**
* egui
* rusqlite
* calamine
* csv
* genpdf
Apenas Rust puro + crates matemáticas (`rust_decimal`, `chrono`).
#### Entidades
**`Nota`**
| Campo | Tipo |
| ------ | ----------------- |
| numero | `u64` |
| serie | `String` |
| valor | `Option<Decimal>` |
| data | `Option<NaiveDate>` |
**`ResultadoAnalise`**
| Campo | Tipo |
| -------------------- | -------------------------------------- |
| faltantes_por_serie | `HashMap<String, Vec<u64>>` |
| duplicadas_por_serie | `HashMap<String, Vec<(u64, usize)>>` |
| soma_total | `Decimal` |
| soma_por_serie | `HashMap<String, Decimal>` |
> **Importante:** a geração dos faltantes não deve ser eager. O use case `executar_analise` deve primeiro calcular os intervalos por série e retornar um resultado intermediário (`ResultadoPreAnalise`) contendo o intervalo calculado. Somente após confirmação do usuário — quando algum intervalo exceder 10.000 registros (RF04) — o sistema expande e materializa a lista completa de faltantes. Isso evita alocar memória para intervalos gerados por mapeamento incorreto de colunas.
#### Services
`detector_sequencia` — recebe `Vec<Nota>` agrupadas por série, retorna faltantes.
`detector_duplicidade` — retorna mapa de contagem por `(numero, serie)`.
`parser_monetario` — implementa exatamente o algoritmo definido no RF06.
#### Erros
`domain/errors.rs` define os erros do domínio de forma tipada (ex: `ErroSerie::Invalida`, `ErroNumero::Zero`, `ErroValor::Negativo`). Nenhuma camada deve propagar `String` livre como erro de domínio.
---
### Application (orquestração)
Coordenam o fluxo entre domain e infrastructure.
Conhece o domain. O domain não conhece o application.
**`executar_analise.rs`**
1. Recebe dados crus
2. Chama `parser_monetario`
3. Chama `detector_sequencia`
4. Chama `detector_duplicidade`
5. Monta `ResultadoAnalise`
**`exportar_pdf.rs`**
Depende de uma trait abstrata (`PdfGenerator`) definida no próprio módulo application. A implementação concreta fica em `infrastructure/pdf_generator.rs`. Isso evita que o application dependa diretamente de `genpdf`.
---
### Infrastructure (implementações concretas)
Implementa leitores, persistência e geração de arquivos.
| Arquivo | Responsabilidade |
| -------------------------------- | ----------------------------------------- |
| `csv_reader.rs` | Leitura de arquivos CSV via `csv` |
| `xlsx_reader.rs` | Leitura de arquivos XLSX via `calamine` |
| `pdf_generator.rs` | Geração de PDF via `genpdf` |
| `sqlite/connection.rs` | Abertura e inicialização da conexão SQLite |
| `sqlite/migrations.rs` | Aplicação de migrations de schema |
| `sqlite/layout_repository.rs` | CRUD de layouts via `rusqlite` |
Nada de infrastructure sobe para domain.
#### Por que `layout_repository.rs` dentro de `sqlite/`
Manter o repositório dentro de `sqlite/` concentra todos os artefatos SQLite em um único módulo. Se futuramente o sistema armazenar histórico de análises ou configurações do usuário (RF14/10.8), novos repositórios são adicionados no mesmo lugar sem dispersão.
---
### UI (interface)
Apenas coleta input, chama use cases e renderiza resultado.
Nenhuma regra de sequência ou parsing monetário deve estar na camada de UI.
#### Screens
| Arquivo | Responsabilidade |
| ------------------------- | ----------------------------------------------------- |
| `import.rs` | Seleção de arquivo e configurações de importação |
| `configuracao_colunas.rs` | Mapeamento de colunas (RF02) |
| `layouts.rs` | Gerenciamento de layouts: salvar, carregar, excluir (RF08) |
| `resultado.rs` | Exibição de resultados com paginação (RF07) |
> `configuracao_colunas.rs` e `layouts.rs` são mantidos separados porque tratam de responsabilidades distintas do RF02 e RF08, evitando que uma única screen acumule lógica de mapeamento de colunas e gerenciamento de persistência.
---
## 9.3 Fluxo de Execução
```
UI → Application → Domain
Infrastructure entra apenas quando necessário.
```
Exemplo real:
1. UI chama `importar_arquivo`
2. Infrastructure lê CSV/XLSX
3. Application transforma registros em entidades `Nota`
4. Domain executa análise
5. Application retorna `ResultadoAnalise`
6. UI renderiza
---
## 9.4 Stack Tecnológica
| Camada | Tecnologia | Status |
| ---------------- | ------------------ | -------------- |