Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ func TestCreateAccount(t *testing.T) {
}
metaDataJSON, _ := json.Marshal(account.MetaData)

rows := sqlmock.NewRows([]string{"balance_id", "indicator", "currency", "ledger_id", "balance", "credit_balance", "debit_balance", "inflight_balance", "inflight_credit_balance", "inflight_debit_balance", "created_at", "version", "track_fund_lineage", "allocation_strategy", "identity_id"}).
AddRow(account.BalanceID, "", "NGN", account.LedgerID, 100, 50, 50, 0, 0, 0, time.Now(), 0, false, "FIFO", "")
rows := sqlmock.NewRows([]string{"balance_id", "indicator", "currency", "ledger_id", "balance", "credit_balance", "debit_balance", "inflight_balance", "inflight_credit_balance", "inflight_debit_balance", "created_at", "version", "track_fund_lineage", "allocation_strategy", "identity_id", "meta_data"}).
AddRow(account.BalanceID, "", "NGN", account.LedgerID, 100, 50, 50, 0, 0, 0, time.Now(), 0, false, "FIFO", "", nil)

mock.ExpectQuery("SELECT .* FROM blnk.balances WHERE balance_id =").
WithArgs(account.BalanceID).
Expand Down Expand Up @@ -104,8 +104,8 @@ func TestCreateAccountWithExternalGenerator(t *testing.T) {
}
metaDataJSON, _ := json.Marshal(account.MetaData)

rows := sqlmock.NewRows([]string{"balance_id", "indicator", "currency", "ledger_id", "balance", "credit_balance", "debit_balance", "inflight_balance", "inflight_credit_balance", "inflight_debit_balance", "created_at", "version", "track_fund_lineage", "allocation_strategy", "identity_id"}).
AddRow(account.BalanceID, "", "NGN", account.LedgerID, 100, 50, 50, 0, 0, 0, time.Now(), 0, false, "FIFO", "")
rows := sqlmock.NewRows([]string{"balance_id", "indicator", "currency", "ledger_id", "balance", "credit_balance", "debit_balance", "inflight_balance", "inflight_credit_balance", "inflight_debit_balance", "created_at", "version", "track_fund_lineage", "allocation_strategy", "identity_id", "meta_data"}).
AddRow(account.BalanceID, "", "NGN", account.LedgerID, 100, 50, 50, 0, 0, 0, time.Now(), 0, false, "FIFO", "", nil)

mock.ExpectQuery("SELECT .* FROM blnk.balances WHERE balance_id =").
WithArgs(account.BalanceID).
Expand Down
11 changes: 10 additions & 1 deletion database/balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,10 +340,11 @@ func (d Datasource) GetBalanceByIDLite(id string) (*model.Balance, error) {
var inflightBalanceValue, inflightCreditBalanceValue, inflightDebitBalanceValue string
var indicator sql.NullString
var allocationStrategy sql.NullString
var metaDataJSON []byte

// Execute the query
row := d.Conn.QueryRowContext(context.Background(), `
SELECT balance_id, indicator, currency, ledger_id, balance, credit_balance, debit_balance, inflight_balance, inflight_credit_balance, inflight_debit_balance, created_at, version, track_fund_lineage, COALESCE(allocation_strategy, 'FIFO') as allocation_strategy, COALESCE(identity_id, '') as identity_id
SELECT balance_id, indicator, currency, ledger_id, balance, credit_balance, debit_balance, inflight_balance, inflight_credit_balance, inflight_debit_balance, created_at, version, track_fund_lineage, COALESCE(allocation_strategy, 'FIFO') as allocation_strategy, COALESCE(identity_id, '') as identity_id, meta_data
FROM blnk.balances
WHERE balance_id = $1
`, id)
Expand All @@ -365,6 +366,7 @@ func (d Datasource) GetBalanceByIDLite(id string) (*model.Balance, error) {
&balance.TrackFundLineage,
&allocationStrategy,
&balance.IdentityID,
&metaDataJSON,
)

// Handle null indicator field
Expand Down Expand Up @@ -416,6 +418,13 @@ func (d Datasource) GetBalanceByIDLite(id string) (*model.Balance, error) {
return nil, fmt.Errorf("failed to parse inflight_debit_balance: %w", err)
}

// Parse the metadata JSON into the MetaData map field (may be NULL)
if len(metaDataJSON) > 0 {
if err := json.Unmarshal(metaDataJSON, &balance.MetaData); err != nil {
return nil, fmt.Errorf("failed to parse meta_data: %w", err)
}
}

return &balance, nil
}

Expand Down
57 changes: 50 additions & 7 deletions database/balance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -650,23 +650,26 @@ func TestGetBalanceByIDLite_Success(t *testing.T) {
ds := Datasource{Conn: db}

query := `
SELECT balance_id, indicator, currency, ledger_id, balance, credit_balance, debit_balance, inflight_balance, inflight_credit_balance, inflight_debit_balance, created_at, version, track_fund_lineage, COALESCE(allocation_strategy, 'FIFO') as allocation_strategy, COALESCE(identity_id, '') as identity_id
SELECT balance_id, indicator, currency, ledger_id, balance, credit_balance, debit_balance, inflight_balance, inflight_credit_balance, inflight_debit_balance, created_at, version, track_fund_lineage, COALESCE(allocation_strategy, 'FIFO') as allocation_strategy, COALESCE(identity_id, '') as identity_id, meta_data
FROM blnk.balances
WHERE balance_id = $1
`

metaDataJSON, err := json.Marshal(map[string]interface{}{"field": "test_value"})
assert.NoError(t, err)

mock.ExpectQuery(regexp.QuoteMeta(query)).
WithArgs("bln_123").
WillReturnRows(sqlmock.NewRows([]string{
"balance_id", "indicator", "currency", "ledger_id",
"balance", "credit_balance", "debit_balance",
"inflight_balance", "inflight_credit_balance", "inflight_debit_balance",
"created_at", "version", "track_fund_lineage", "allocation_strategy", "identity_id",
"created_at", "version", "track_fund_lineage", "allocation_strategy", "identity_id", "meta_data",
}).AddRow(
"bln_123", "ACC001", "USD", "ldg_001",
"100000", "60000", "40000",
"5000", "3000", "2000",
time.Now(), 1, false, "FIFO", "",
time.Now(), 1, false, "FIFO", "", metaDataJSON,
))

balance, err := ds.GetBalanceByIDLite("bln_123")
Expand All @@ -679,6 +682,46 @@ func TestGetBalanceByIDLite_Success(t *testing.T) {
assert.Equal(t, "60000", balance.CreditBalance.String())
assert.Equal(t, "40000", balance.DebitBalance.String())
assert.Equal(t, "5000", balance.InflightBalance.String())
// Regression test for #256: meta_data must be populated from the query,
// not silently dropped, since callers persist this struct back to the
// search index and would otherwise overwrite existing metadata with nil.
assert.Equal(t, "test_value", balance.MetaData["field"])

err = mock.ExpectationsWereMet()
assert.NoError(t, err)
}

func TestGetBalanceByIDLite_NilMetaData(t *testing.T) {
db, mock, err := sqlmock.New()
assert.NoError(t, err)
defer func() { _ = db.Close() }()

ds := Datasource{Conn: db}

query := `
SELECT balance_id, indicator, currency, ledger_id, balance, credit_balance, debit_balance, inflight_balance, inflight_credit_balance, inflight_debit_balance, created_at, version, track_fund_lineage, COALESCE(allocation_strategy, 'FIFO') as allocation_strategy, COALESCE(identity_id, '') as identity_id, meta_data
FROM blnk.balances
WHERE balance_id = $1
`

mock.ExpectQuery(regexp.QuoteMeta(query)).
WithArgs("bln_123").
WillReturnRows(sqlmock.NewRows([]string{
"balance_id", "indicator", "currency", "ledger_id",
"balance", "credit_balance", "debit_balance",
"inflight_balance", "inflight_credit_balance", "inflight_debit_balance",
"created_at", "version", "track_fund_lineage", "allocation_strategy", "identity_id", "meta_data",
}).AddRow(
"bln_123", "ACC001", "USD", "ldg_001",
"100000", "60000", "40000",
"5000", "3000", "2000",
time.Now(), 1, false, "FIFO", "", nil,
))

balance, err := ds.GetBalanceByIDLite("bln_123")
assert.NoError(t, err)
assert.NotNil(t, balance)
assert.Nil(t, balance.MetaData)

err = mock.ExpectationsWereMet()
assert.NoError(t, err)
Expand All @@ -692,7 +735,7 @@ func TestGetBalanceByIDLite_NotFound(t *testing.T) {
ds := Datasource{Conn: db}

query := `
SELECT balance_id, indicator, currency, ledger_id, balance, credit_balance, debit_balance, inflight_balance, inflight_credit_balance, inflight_debit_balance, created_at, version, track_fund_lineage, COALESCE(allocation_strategy, 'FIFO') as allocation_strategy, COALESCE(identity_id, '') as identity_id
SELECT balance_id, indicator, currency, ledger_id, balance, credit_balance, debit_balance, inflight_balance, inflight_credit_balance, inflight_debit_balance, created_at, version, track_fund_lineage, COALESCE(allocation_strategy, 'FIFO') as allocation_strategy, COALESCE(identity_id, '') as identity_id, meta_data
FROM blnk.balances
WHERE balance_id = $1
`
Expand Down Expand Up @@ -720,7 +763,7 @@ func TestGetBalanceByIDLite_NullIndicator(t *testing.T) {
ds := Datasource{Conn: db}

query := `
SELECT balance_id, indicator, currency, ledger_id, balance, credit_balance, debit_balance, inflight_balance, inflight_credit_balance, inflight_debit_balance, created_at, version, track_fund_lineage, COALESCE(allocation_strategy, 'FIFO') as allocation_strategy, COALESCE(identity_id, '') as identity_id
SELECT balance_id, indicator, currency, ledger_id, balance, credit_balance, debit_balance, inflight_balance, inflight_credit_balance, inflight_debit_balance, created_at, version, track_fund_lineage, COALESCE(allocation_strategy, 'FIFO') as allocation_strategy, COALESCE(identity_id, '') as identity_id, meta_data
FROM blnk.balances
WHERE balance_id = $1
`
Expand All @@ -731,12 +774,12 @@ func TestGetBalanceByIDLite_NullIndicator(t *testing.T) {
"balance_id", "indicator", "currency", "ledger_id",
"balance", "credit_balance", "debit_balance",
"inflight_balance", "inflight_credit_balance", "inflight_debit_balance",
"created_at", "version", "track_fund_lineage", "allocation_strategy", "identity_id",
"created_at", "version", "track_fund_lineage", "allocation_strategy", "identity_id", "meta_data",
}).AddRow(
"bln_123", nil, "USD", "ldg_001",
"100000", "60000", "40000",
"5000", "3000", "2000",
time.Now(), 1, false, "FIFO", "",
time.Now(), 1, false, "FIFO", "", nil,
))

balance, err := ds.GetBalanceByIDLite("bln_123")
Expand Down
Loading
Loading