accounts creation
All checks were successful
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/discovery Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/gateway_mntx Pipeline was successful
ci/woodpecker/push/gateway_chain Pipeline was successful
ci/woodpecker/push/gateway_tgsettle Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful

This commit is contained in:
Stephan D
2026-01-23 00:13:43 +01:00
parent b677d37b99
commit 218c4e20b3
64 changed files with 1641 additions and 338 deletions

View File

@@ -2,8 +2,8 @@ package ledger
import (
"context"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
"go.mongodb.org/mongo-driver/bson/primitive"
@@ -23,6 +23,7 @@ type accountStoreStub struct {
existingErr error
defaultSettlement *model.Account
defaultErr error
createErrs []error
}
func (s *accountStoreStub) Create(_ context.Context, account *model.Account) error {
@@ -30,8 +31,16 @@ func (s *accountStoreStub) Create(_ context.Context, account *model.Account) err
if s.createErrSettlement != nil {
return s.createErrSettlement
}
} else if s.createErr != nil {
return s.createErr
} else {
if len(s.createErrs) > 0 {
err := s.createErrs[0]
s.createErrs = s.createErrs[1:]
if err != nil {
return err
}
} else if s.createErr != nil {
return s.createErr
}
}
if account.GetID() == nil || account.GetID().IsZero() {
account.SetID(primitive.NewObjectID())
@@ -94,7 +103,6 @@ func TestCreateAccountResponder_Success(t *testing.T) {
req := &ledgerv1.CreateAccountRequest{
OrganizationRef: orgRef.Hex(),
AccountCode: "asset:cash:main",
AccountType: ledgerv1.AccountType_ACCOUNT_TYPE_ASSET,
Currency: "usd",
AllowNegative: false,
@@ -107,7 +115,11 @@ func TestCreateAccountResponder_Success(t *testing.T) {
require.NotNil(t, resp)
require.NotNil(t, resp.Account)
require.Equal(t, "asset:cash:main", resp.Account.AccountCode)
parts := strings.Split(resp.Account.AccountCode, ":")
require.Len(t, parts, 3)
require.Equal(t, "asset", parts[0])
require.Equal(t, "usd", parts[1])
require.Len(t, parts[2], 24)
require.Equal(t, ledgerv1.AccountType_ACCOUNT_TYPE_ASSET, resp.Account.AccountType)
require.Equal(t, "USD", resp.Account.Currency)
require.True(t, resp.Account.IsSettlement)
@@ -129,7 +141,6 @@ func TestCreateAccountResponder_AutoCreatesSettlementAccount(t *testing.T) {
req := &ledgerv1.CreateAccountRequest{
OrganizationRef: orgRef.Hex(),
AccountCode: "liability:customer:1",
AccountType: ledgerv1.AccountType_ACCOUNT_TYPE_LIABILITY,
Currency: "usd",
}
@@ -146,40 +157,29 @@ func TestCreateAccountResponder_AutoCreatesSettlementAccount(t *testing.T) {
if acc.IsSettlement {
settlement = acc
}
if acc.AccountCode == "liability:customer:1" {
if !acc.IsSettlement {
created = acc
}
}
require.NotNil(t, settlement)
require.NotNil(t, created)
parts := strings.Split(created.AccountCode, ":")
require.Len(t, parts, 3)
require.Equal(t, "liability", parts[0])
require.Equal(t, "usd", parts[1])
require.Len(t, parts[2], 24)
require.Equal(t, defaultSettlementAccountCode("USD"), settlement.AccountCode)
require.Equal(t, model.AccountTypeAsset, settlement.AccountType)
require.Equal(t, "USD", settlement.Currency)
require.True(t, settlement.AllowNegative)
}
func TestCreateAccountResponder_DuplicateReturnsExisting(t *testing.T) {
func TestCreateAccountResponder_RetriesOnConflict(t *testing.T) {
t.Parallel()
orgRef := primitive.NewObjectID()
existing := &model.Account{
AccountCode: "asset:cash:main",
Currency: "USD",
AccountType: model.AccountTypeAsset,
Status: model.AccountStatusActive,
AllowNegative: false,
IsSettlement: true,
Metadata: map[string]string{"purpose": "existing"},
}
existing.OrganizationRef = orgRef
existing.SetID(primitive.NewObjectID())
existing.CreatedAt = time.Now().Add(-time.Hour).UTC()
existing.UpdatedAt = time.Now().UTC()
accountStore := &accountStoreStub{
createErr: merrors.DataConflict("duplicate"),
existing: existing,
existingErr: nil,
createErrs: []error{merrors.DataConflict("duplicate")},
}
svc := &Service{
@@ -189,7 +189,6 @@ func TestCreateAccountResponder_DuplicateReturnsExisting(t *testing.T) {
req := &ledgerv1.CreateAccountRequest{
OrganizationRef: orgRef.Hex(),
AccountCode: "asset:cash:main",
AccountType: ledgerv1.AccountType_ACCOUNT_TYPE_ASSET,
Currency: "usd",
}
@@ -199,8 +198,15 @@ func TestCreateAccountResponder_DuplicateReturnsExisting(t *testing.T) {
require.NotNil(t, resp)
require.NotNil(t, resp.Account)
require.Equal(t, existing.GetID().Hex(), resp.Account.LedgerAccountRef)
require.Equal(t, existing.Metadata["purpose"], resp.Account.Metadata["purpose"])
require.Len(t, accountStore.created, 2)
var created *model.Account
for _, acc := range accountStore.created {
if !acc.IsSettlement {
created = acc
}
}
require.NotNil(t, created)
require.Equal(t, created.AccountCode, resp.Account.AccountCode)
}
func TestCreateAccountResponder_InvalidAccountType(t *testing.T) {
@@ -213,7 +219,6 @@ func TestCreateAccountResponder_InvalidAccountType(t *testing.T) {
req := &ledgerv1.CreateAccountRequest{
OrganizationRef: primitive.NewObjectID().Hex(),
AccountCode: "asset:cash:main",
Currency: "USD",
}