diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-22 13:23:34 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-22 13:23:34 +0800 |
| commit | 9bdc062e99b8de10700036a13a6e07a1d45411bd (patch) | |
| tree | dd6857e299c58507fc21f0a9f99709b214aafe9d /tests | |
| parent | 2dedc30358d1724f60ab646b7a24e93f3672dff1 (diff) | |
| download | fund-lab-9bdc062e99b8de10700036a13a6e07a1d45411bd.tar.gz | |
Prove manual stock sells credit cash with a single ledger event (3d-35)
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/FundLab.Api.Tests/CashReconciliationTests.fs | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/tests/FundLab.Api.Tests/CashReconciliationTests.fs b/tests/FundLab.Api.Tests/CashReconciliationTests.fs index 6fb761e..e969472 100644 --- a/tests/FundLab.Api.Tests/CashReconciliationTests.fs +++ b/tests/FundLab.Api.Tests/CashReconciliationTests.fs @@ -248,6 +248,13 @@ type CashReconciliationTests(fixture: PostgresFixture) = command.Parameters.AddWithValue("fund_id", fundId) |> ignore command.ExecuteScalar() :?> int64 + let tableCount (table: string) fundId = + use connection = new NpgsqlConnection(fixture.ConnectionString) + connection.Open() + use command = new NpgsqlCommand(sprintf "SELECT count(*) FROM %s WHERE fund_id = @fund_id" table, connection) + command.Parameters.AddWithValue("fund_id", fundId) |> ignore + command.ExecuteScalar() :?> int64 + [<Fact>] member _.``cash reconciliation balances across every source category``() = let fundId = createFund 10000.00m @@ -427,3 +434,40 @@ type CashReconciliationTests(fixture: PostgresFixture) = Assert.Contains("\"closingCash\":\"1000.00\"", body) Assert.Contains("\"difference\":\"0.00\"", body) Assert.Equal(0, eventCount body "bond_buy") + + // the rolled-back transaction must not leave trades, positions or dirty ledger rows behind + Assert.Equal(0L, tableCount "bond_trades" fundId) + Assert.Equal(0L, tableCount "bond_positions" fundId) + Assert.Equal(0L, ledgerEventCount fundId) + + [<Fact>] + member _.``manual stock sell credits available cash and records a stock_sell event``() = + let fundId = createFund 10000.00m + buyStock fundId "600519" 100m 10.00m (fixture.Key "cash-sell-buy") + sellStock fundId "600519" 40m 12.00m (fixture.Key "cash-sell-partial") + + let status, body = reconciliation fundId + Assert.Equal(200, status) + Assert.Contains("\"openingCash\":\"10000.00\"", body) + Assert.Contains("\"closingCash\":\"9480.00\"", body) + Assert.Contains("\"ledgerBalance\":\"9480.00\"", body) + Assert.Contains("\"difference\":\"0.00\"", body) + Assert.Equal("-1000.00", (sourceEntry body "stock_buy").GetProperty("netAmount").GetString()) + Assert.Equal("480.00", (sourceEntry body "stock_sell").GetProperty("netAmount").GetString()) + Assert.Equal(1, eventCount body "stock_sell") + + [<Fact>] + member _.``replaying a stock sell credits cash and the ledger only once``() = + let fundId = createFund 10000.00m + let sellKey = fixture.Key "cash-sell-replay" + buyStock fundId "600519" 100m 10.00m (fixture.Key "cash-sell-replay-buy") + + sellStock fundId "600519" 40m 12.00m sellKey + sellStock fundId "600519" 40m 12.00m sellKey + + let status, body = reconciliation fundId + Assert.Equal(200, status) + Assert.Contains("\"closingCash\":\"9480.00\"", body) + Assert.Contains("\"difference\":\"0.00\"", body) + Assert.Equal(1, eventCount body "stock_sell") + Assert.Equal(1L, tableCount "stock_sells" fundId) |
