diff --git a/internal/storage/ledgerstore/accounts.go b/internal/storage/ledgerstore/accounts.go index 1f01d16cb..5fed1efee 100644 --- a/internal/storage/ledgerstore/accounts.go +++ b/internal/storage/ledgerstore/accounts.go @@ -107,21 +107,38 @@ func (store *Store) accountQueryContext(qb query.Builder, q GetAccountsQuery) (s case balanceRegex.Match([]byte(key)): match := balanceRegex.FindAllStringSubmatch(key, 2) + args := []any{match[0][1], store.name} + + dateFilter := `` + if q.Options.Options.PIT != nil && !q.Options.Options.PIT.IsZero() { + dateFilter = `and insertion_date < ?` + args = append(args, q.Options.Options.PIT) + } + args = append(args, value) + return fmt.Sprintf(`( select balance_from_volumes(post_commit_volumes) from moves - where asset = ? and account_address = accounts.address and ledger = ? + where asset = ? and account_address = accounts.address and ledger = ? `+dateFilter+` order by seq desc limit 1 - ) %s ?`, convertOperatorToSQL()), []any{match[0][1], store.name, value}, nil + ) %s ?`, convertOperatorToSQL()), args, nil case key == "balance": + args := []any{store.name} + dateFilter := `` + if q.Options.Options.PIT != nil && !q.Options.Options.PIT.IsZero() { + dateFilter = `and insertion_date < ?` + args = append(args, q.Options.Options.PIT) + } + args = append(args, value) + return fmt.Sprintf(`( select balance_from_volumes(post_commit_volumes) from moves - where account_address = accounts.address and ledger = ? + where account_address = accounts.address and ledger = ? `+dateFilter+` order by seq desc limit 1 - ) %s ?`, convertOperatorToSQL()), []any{store.name, value}, nil + ) %s ?`, convertOperatorToSQL()), args, nil case key == "metadata": if operator != "$exists" { diff --git a/internal/storage/ledgerstore/accounts_test.go b/internal/storage/ledgerstore/accounts_test.go index 8d249a459..7fca0bd52 100644 --- a/internal/storage/ledgerstore/accounts_test.go +++ b/internal/storage/ledgerstore/accounts_test.go @@ -7,6 +7,8 @@ import ( "math/big" "testing" + "github.com/formancehq/go-libs/pointer" + "github.com/formancehq/go-libs/time" "github.com/formancehq/go-libs/logging" @@ -155,6 +157,7 @@ func TestGetAccounts(t *testing.T) { require.NoError(t, err) require.Len(t, accounts.Data, 3) }) + t.Run("list using filter on multiple address", func(t *testing.T) { t.Parallel() accounts, err := store.GetAccountsWithVolumes(ctx, NewGetAccountsQuery(NewPaginatedQueryOptions(PITFilterWithVolumes{}). @@ -184,6 +187,18 @@ func TestGetAccounts(t *testing.T) { require.Equal(t, "account:1", accounts.Data[0].Account.Address) require.Equal(t, "bank", accounts.Data[1].Account.Address) }) + t.Run("list using filter on balances and pit", func(t *testing.T) { + t.Parallel() + accounts, err := store.GetAccountsWithVolumes(ctx, NewGetAccountsQuery(NewPaginatedQueryOptions(PITFilterWithVolumes{ + PITFilter: PITFilter{ + PIT: pointer.For(now.Add(100 * time.Millisecond)), + }, + }). + WithQueryBuilder(query.Lt("balance[USD]", 0)), + )) + require.NoError(t, err) + require.Len(t, accounts.Data, 1) // world + }) t.Run("list using filter on exists metadata", func(t *testing.T) { t.Parallel()