atualiza versão do PRD para 1.6 e detalha arquitetura e estrutura de pastas do projeto
This commit is contained in:
@@ -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 |
|
||||
| ---------------- | ------------------ | -------------- |
|
||||
|
||||
Reference in New Issue
Block a user