Files
sendico/api/ledger/internal/service/ledger/system_accounts_test.go
2026-02-03 00:40:46 +01:00

112 lines
4.0 KiB
Go

package ledger
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/tech/sendico/ledger/storage"
"github.com/tech/sendico/pkg/merrors"
pmodel "github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/model/account_role"
"go.mongodb.org/mongo-driver/v2/bson"
"go.uber.org/zap"
)
type systemAccountsStoreStub struct {
created []*pmodel.LedgerAccount
existing map[string]*pmodel.LedgerAccount
}
func (s *systemAccountsStoreStub) Create(_ context.Context, account *pmodel.LedgerAccount) error {
if account.GetID() == nil || account.GetID().IsZero() {
account.SetID(bson.NewObjectID())
}
s.created = append(s.created, account)
if s.existing == nil {
s.existing = make(map[string]*pmodel.LedgerAccount)
}
if account.SystemPurpose != nil {
key := string(*account.SystemPurpose) + "|" + account.Currency
s.existing[key] = account
}
return nil
}
func (s *systemAccountsStoreStub) Get(context.Context, bson.ObjectID) (*pmodel.LedgerAccount, error) {
return nil, storage.ErrAccountNotFound
}
func (s *systemAccountsStoreStub) GetByAccountCode(context.Context, bson.ObjectID, string, string) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get by code")
}
func (s *systemAccountsStoreStub) GetByRole(context.Context, bson.ObjectID, string, account_role.AccountRole) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get by role")
}
func (s *systemAccountsStoreStub) GetSystemAccount(_ context.Context, purpose pmodel.SystemAccountPurpose, currency string) (*pmodel.LedgerAccount, error) {
if s.existing == nil {
return nil, storage.ErrAccountNotFound
}
key := string(purpose) + "|" + currency
if acc, ok := s.existing[key]; ok {
return acc, nil
}
return nil, storage.ErrAccountNotFound
}
func (s *systemAccountsStoreStub) GetDefaultSettlement(context.Context, bson.ObjectID, string) (*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("get default settlement")
}
func (s *systemAccountsStoreStub) ListByOrganization(context.Context, bson.ObjectID, *storage.AccountsFilter, int, int) ([]*pmodel.LedgerAccount, error) {
return nil, merrors.NotImplemented("list")
}
func (s *systemAccountsStoreStub) UpdateStatus(context.Context, bson.ObjectID, pmodel.LedgerAccountStatus) error {
return merrors.NotImplemented("update status")
}
type systemAccountsRepoStub struct {
accounts storage.AccountsStore
}
func (r *systemAccountsRepoStub) Ping(context.Context) error { return nil }
func (r *systemAccountsRepoStub) Accounts() storage.AccountsStore { return r.accounts }
func (r *systemAccountsRepoStub) JournalEntries() storage.JournalEntriesStore { return nil }
func (r *systemAccountsRepoStub) PostingLines() storage.PostingLinesStore { return nil }
func (r *systemAccountsRepoStub) Balances() storage.BalancesStore { return nil }
func (r *systemAccountsRepoStub) Outbox() storage.OutboxStore { return nil }
func TestEnsureSystemAccounts_CreatesAndCaches(t *testing.T) {
originalCurrencies := pmodel.SupportedCurrencies
pmodel.SupportedCurrencies = []pmodel.Currency{pmodel.CurrencyUSD, pmodel.CurrencyEUR}
t.Cleanup(func() {
pmodel.SupportedCurrencies = originalCurrencies
})
accounts := &systemAccountsStoreStub{}
svc := &Service{
logger: zap.NewNop(),
storage: &systemAccountsRepoStub{accounts: accounts},
}
require.NoError(t, svc.ensureSystemAccounts(context.Background()))
require.Len(t, accounts.created, 4)
for _, acc := range accounts.created {
require.Equal(t, pmodel.LedgerAccountScopeSystem, acc.Scope)
require.True(t, acc.AllowNegative)
require.Nil(t, acc.OrganizationRef)
require.Equal(t, account_role.AccountRole(""), acc.Role)
require.NotNil(t, acc.SystemPurpose)
require.Equal(t, pmodel.LedgerAccountTypeAsset, acc.AccountType)
require.Equal(t, pmodel.LedgerAccountStatusActive, acc.Status)
}
// Idempotent: second call should not create new accounts.
require.NoError(t, svc.ensureSystemAccounts(context.Background()))
require.Len(t, accounts.created, 4)
}