summaryrefslogtreecommitdiff
path: root/tests/FundLab.Web.Tests/BoundaryTests.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-22 04:59:12 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-22 04:59:12 +0800
commit545f2a507fd0138f7fd50ed7fb2631d0273db625 (patch)
treef9eedee8d82b632474408e774cb95e9e01a9750d /tests/FundLab.Web.Tests/BoundaryTests.fs
parent0183b86f18d9897ff9487e6d864898954397991d (diff)
downloadfund-lab-545f2a507fd0138f7fd50ed7fb2631d0273db625.tar.gz
Integrate bond and stock positions into fund valuation (3d-23)
Diffstat (limited to 'tests/FundLab.Web.Tests/BoundaryTests.fs')
-rw-r--r--tests/FundLab.Web.Tests/BoundaryTests.fs69
1 files changed, 69 insertions, 0 deletions
diff --git a/tests/FundLab.Web.Tests/BoundaryTests.fs b/tests/FundLab.Web.Tests/BoundaryTests.fs
index 3a9ec61..d8bb472 100644
--- a/tests/FundLab.Web.Tests/BoundaryTests.fs
+++ b/tests/FundLab.Web.Tests/BoundaryTests.fs
@@ -710,6 +710,75 @@ module ConfirmationBoundaryTests =
Assert.False(updated.bondPositionsInFlight)
[<Fact>]
+ let ``valuation completion stores totals and per-position marks`` () =
+ let fundId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
+
+ let model =
+ { init () with
+ createdFund = Some(FundBoundaryTests.sampleFund fundId)
+ valuationReadSeq = 1
+ valuationInFlight = true }
+
+ let raw : RawFundValuation =
+ {
+ fundId = fundId
+ currency = "CNY"
+ cash = "10000.00"
+ positionsMarketValue = "126320.68"
+ portfolioValue = "136320.68"
+ pricedPositions = 1
+ unavailablePositions = 1
+ positions =
+ [|
+ {
+ instrumentCode = "600519"
+ name = box "贵州茅台"
+ assetClass = "stock"
+ quantity = "100.00000000"
+ price = box "1252.57"
+ priceSource = box "live"
+ marketValue = box "125257.00"
+ status = "priced"
+ }
+ {
+ instrumentCode = "110075"
+ name = box "南航转债"
+ assetClass = "bond"
+ quantity = "10.00000000"
+ price = null
+ priceSource = null
+ marketValue = null
+ status = "unavailable"
+ }
+ |]
+ }
+
+ let updated, _ = update (ValuationReadCompleted(1, fundId, raw)) model
+
+ let valuation = updated.valuation.Value
+ Assert.Equal("136320.68", valuation.portfolioValue)
+ Assert.Equal(1, valuation.unavailablePositions)
+ Assert.Equal(2, valuation.positions.Length)
+ Assert.Equal("unavailable", valuation.positions[1].status)
+ Assert.False(updated.valuationInFlight)
+
+ [<Fact>]
+ let ``valuation failure clears totals and surfaces a message`` () =
+ let fundId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
+
+ let model =
+ { init () with
+ createdFund = Some(FundBoundaryTests.sampleFund fundId)
+ valuationReadSeq = 1
+ valuationInFlight = true }
+
+ let updated, _ = update (ValuationReadFailed(1, fundId, "collector exited with code 2")) model
+
+ Assert.Equal(None, updated.valuation)
+ Assert.Contains("组合估值不可用", updated.valuationMessage |> Option.defaultValue "")
+ Assert.False(updated.valuationInFlight)
+
+ [<Fact>]
let ``order decode keeps decimal strings and decodes option fields`` () =
let confirmed = Api.decodeOrder (sampleConfirmedRaw ())
let pending = Api.decodeOrder (samplePendingRaw ())