package service import ( "context" "errors" "financeiro-carvalho/internal/model" "financeiro-carvalho/internal/repository" ) var ( ErrAccountEmptyName = errors.New("account name cannot be empty") ErrAccountInvalidType = errors.New("account type must be checking, savings, investment, or credit") ) var validAccountTypes = map[string]bool{ "checking": true, "savings": true, "investment": true, "credit": true, } type AccountRepo interface { List(ctx context.Context) ([]model.Account, error) GetByID(ctx context.Context, id int) (*model.Account, error) Create(ctx context.Context, in model.AccountInput) (*model.Account, error) Update(ctx context.Context, id int, in model.AccountInput) (*model.Account, error) Delete(ctx context.Context, id int) error TotalPatrimony(ctx context.Context) (float64, error) } type AccountService struct { repo repository.AccountRepoWithYield cdiSvc *CDIYieldService } func NewAccountService(repo repository.AccountRepoWithYield, cdiSvc *CDIYieldService) *AccountService { return &AccountService{repo: repo, cdiSvc: cdiSvc} } func (s *AccountService) validate(in model.AccountInput) error { if in.Name == "" { return ErrAccountEmptyName } if !validAccountTypes[in.Type] { return ErrAccountInvalidType } return nil } // List returns accounts, applying CDI yield on-demand for cdi-type accounts. func (s *AccountService) List(ctx context.Context) ([]model.Account, error) { accounts, err := s.repo.List(ctx) if err != nil { return nil, err } for i := range accounts { if accounts[i].YieldType == "cdi" { // Apply CDI yield — errors are non-fatal (BCB API may be unavailable) _ = s.cdiSvc.ApplyYield(ctx, &accounts[i]) } } // Re-fetch after yield transactions may have been created to get updated balances return s.repo.List(ctx) } func (s *AccountService) Create(ctx context.Context, in model.AccountInput) (*model.Account, error) { if err := s.validate(in); err != nil { return nil, err } return s.repo.Create(ctx, in) } func (s *AccountService) Update(ctx context.Context, id int, in model.AccountInput) (*model.Account, error) { if err := s.validate(in); err != nil { return nil, err } return s.repo.Update(ctx, id, in) } func (s *AccountService) Delete(ctx context.Context, id int) error { return s.repo.Delete(ctx, id) } func (s *AccountService) TotalPatrimony(ctx context.Context) (float64, error) { return s.repo.TotalPatrimony(ctx) }