feat(#19): registro manual de transações e recorrências fixas
Adiciona CRUD manual de transações (income/expense) com filtro mensal, CRUD de recorrências fixas com verificação mensal de cobertura (±10% por categoria), endpoint de ignore/unignore e telas Vue para Transações e Configurações. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"financeiro-carvalho/internal/model"
|
||||
"financeiro-carvalho/internal/repository"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidTransactionType = errors.New("type must be 'income' or 'expense'")
|
||||
ErrCannotEditImported = errors.New("imported transactions cannot be edited or deleted")
|
||||
ErrTransactionEmptyDesc = errors.New("description is required")
|
||||
ErrTransactionInvalidAmount = errors.New("amount must be greater than zero")
|
||||
)
|
||||
|
||||
type TransactionService struct {
|
||||
repo repository.ManualTransactionRepository
|
||||
}
|
||||
|
||||
func NewTransactionService(repo repository.ManualTransactionRepository) *TransactionService {
|
||||
return &TransactionService{repo: repo}
|
||||
}
|
||||
|
||||
func (s *TransactionService) List(ctx context.Context, month string) ([]model.Transaction, error) {
|
||||
txs, err := s.repo.List(ctx, month)
|
||||
if txs == nil {
|
||||
return []model.Transaction{}, err
|
||||
}
|
||||
return txs, err
|
||||
}
|
||||
|
||||
func (s *TransactionService) Create(ctx context.Context, t model.Transaction) (*model.Transaction, error) {
|
||||
if err := validateTransaction(t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.Description = strings.TrimSpace(t.Description)
|
||||
return s.repo.Create(ctx, t)
|
||||
}
|
||||
|
||||
func (s *TransactionService) Update(ctx context.Context, t model.Transaction) (*model.Transaction, error) {
|
||||
if err := validateTransaction(t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.Description = strings.TrimSpace(t.Description)
|
||||
out, err := s.repo.Update(ctx, t)
|
||||
if errors.Is(err, repository.ErrNotFound) {
|
||||
return nil, ErrCannotEditImported
|
||||
}
|
||||
return out, err
|
||||
}
|
||||
|
||||
func (s *TransactionService) Delete(ctx context.Context, id int) error {
|
||||
err := s.repo.Delete(ctx, id)
|
||||
if errors.Is(err, repository.ErrNotFound) {
|
||||
return ErrCannotEditImported
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func validateTransaction(t model.Transaction) error {
|
||||
if strings.TrimSpace(t.Description) == "" {
|
||||
return ErrTransactionEmptyDesc
|
||||
}
|
||||
if t.Amount <= 0 {
|
||||
return ErrTransactionInvalidAmount
|
||||
}
|
||||
if t.Type != "income" && t.Type != "expense" {
|
||||
return ErrInvalidTransactionType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user