Files
carvalho-finances/apps/api/internal/service/transaction.go
T
Mlcavalho1andClaude Sonnet 4.6 88461a4aea feat: excluir transações de extrato + delete em lote por mês
Remove restrição que bloqueava delete de transações importadas.
Adiciona DELETE /transactions?month=YYYY-MM para exclusão em lote
e botão "EXCLUIR MÊS" na view de transações.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-27 16:41:26 -03:00

78 lines
2.0 KiB
Go

package service
import (
"context"
"errors"
"strings"
"financeiro-carvalho/internal/model"
"financeiro-carvalho/internal/repository"
)
var (
ErrInvalidTransactionType = errors.New("type must be 'income' or 'expense'")
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 errors.New("transaction not found")
}
return err
}
func (s *TransactionService) DeleteByMonth(ctx context.Context, month string) (int, error) {
return s.repo.DeleteByMonth(ctx, month)
}
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
}