feat: #46 auto-categorização no import por histórico de descrições
- TransactionRepository.CategoryByDescription: busca a categoria mais recente para cada descrição normalizada no histórico do perfil - ImportService.Preview: pré-preenche category_id em linhas não-duplicatas cuja descrição já foi categorizada antes (case-insensitive) - Duplicatas não recebem sugestão - 2 novos testes: auto-categorize + duplicate-not-categorized Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
@@ -12,6 +12,10 @@ import (
|
||||
"financeiro-carvalho/internal/repository"
|
||||
)
|
||||
|
||||
func normalizeDesc(s string) string {
|
||||
return strings.ToLower(strings.Join(strings.Fields(s), " "))
|
||||
}
|
||||
|
||||
type ImportService struct {
|
||||
repo repository.TransactionRepository
|
||||
}
|
||||
@@ -20,19 +24,37 @@ func NewImportService(repo repository.TransactionRepository) *ImportService {
|
||||
return &ImportService{repo: repo}
|
||||
}
|
||||
|
||||
// Preview parses the file and marks duplicates without saving anything.
|
||||
// Preview parses the file, marks duplicates, and pre-fills category_id from history.
|
||||
func (s *ImportService) Preview(ctx context.Context, filename string, r io.Reader, csvMapping *model.CSVMapping) ([]model.ImportRow, []string, error) {
|
||||
rows, parseErrs, err := s.parse(filename, r, csvMapping)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Collect unique descriptions for history lookup
|
||||
descs := make([]string, 0, len(rows))
|
||||
seen := make(map[string]bool)
|
||||
for _, row := range rows {
|
||||
n := normalizeDesc(row.Description)
|
||||
if !seen[n] {
|
||||
descs = append(descs, n)
|
||||
seen[n] = true
|
||||
}
|
||||
}
|
||||
catByDesc, _ := s.repo.CategoryByDescription(ctx, descs)
|
||||
|
||||
for i := range rows {
|
||||
dup, err := s.isDuplicate(ctx, &rows[i])
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("dedup check: %w", err)
|
||||
}
|
||||
rows[i].IsDuplicate = dup
|
||||
// Pre-fill category from history for non-duplicate rows that have no category yet
|
||||
if !dup && rows[i].CategoryID == nil {
|
||||
if catID, ok := catByDesc[normalizeDesc(rows[i].Description)]; ok {
|
||||
rows[i].CategoryID = &catID
|
||||
}
|
||||
}
|
||||
}
|
||||
return rows, parseErrs, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user