diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-21 10:43:09 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-21 10:43:09 +0800 |
| commit | 3d9398234a54774544eb48a1caed6a1b2d5132eb (patch) | |
| tree | bf6773bfce7872da1d7aa40f5d1b8af8cdaacf76 /src/FundLab.Api/App.fs | |
| parent | a5ac465ab59197a55a222d30ebd2cf26ffe80f86 (diff) | |
| download | fund-lab-3d9398234a54774544eb48a1caed6a1b2d5132eb.tar.gz | |
Add confirmation status and holdings UI (3d-2c)
Wire the subscription confirmation and positions endpoints into the
frontend: order rows show per-order trade date and confirmed outcome
(NAV, units, NAV date, invested cash, residual) or pending_nav reason,
each confirmable order gets a confirm action posting to the existing
confirm endpoint with an idempotency key and request-sequence guard,
and a new holdings panel renders available/reserved cash plus per-code
positions (units, cost, latest valuation NAV with date, or an explicit
'估值待更新' when no valuation exists).
Orders list/create responses now return the full detail shape so
pending reasons and confirmation results survive refresh. The optional
text decoder accepts the current plain-value/null wire format alongside
the legacy case/fields envelope, restoring fund type and daily return
display. Browser QA gains a J-series covering the real confirm flow,
holdings rendering and cash accounting; Web tests cover decoders,
confirm guard, stale-response protection and token invalidation.
Diffstat (limited to 'src/FundLab.Api/App.fs')
| -rw-r--r-- | src/FundLab.Api/App.fs | 30 |
1 files changed, 2 insertions, 28 deletions
diff --git a/src/FundLab.Api/App.fs b/src/FundLab.Api/App.fs index 839a641..97787aa 100644 --- a/src/FundLab.Api/App.fs +++ b/src/FundLab.Api/App.fs @@ -57,19 +57,6 @@ type FundApiResponse = status: string } -type SubscriptionOrderApiResponse = - { - id: Guid - fundId: Guid - fundCode: string - amount: string - feeAmount: string - reservedTotal: string - status: string - submittedAt: string - isSynthetic: bool - } - type ConfirmedQuoteEvidenceResponse = { navDate: string @@ -198,20 +185,7 @@ module App = status = fund.Status } - let private orderResponse (order: SubscriptionOrderRecord) : SubscriptionOrderApiResponse = - { - id = order.Id - fundId = order.FundId - fundCode = order.FundCode - amount = cashText order.Amount - feeAmount = cashText order.FeeAmount - reservedTotal = cashText order.ReservedTotal - status = order.Status - submittedAt = timestampText order.SubmittedAt - isSynthetic = order.IsSynthetic - } - - let private confirmationResponse (order: SubscriptionOrderRecord) : SubscriptionOrderDetailResponse = + let private orderResponse (order: SubscriptionOrderRecord) : SubscriptionOrderDetailResponse = let quoteEvidence = order.ConfirmedQuote |> Option.map (fun quote -> @@ -461,7 +435,7 @@ module App = match repository.ConfirmSubscriptionOrder(idempotencyKey, fundId, orderId) with | OrderConfirmed order | ConfirmReplayed order - | ConfirmPendingNav order -> json (confirmationResponse order) next ctx + | ConfirmPendingNav order -> json (orderResponse order) next ctx | ConfirmIdempotencyConflict -> errorResponse 409 "IDEMPOTENCY_CONFLICT" "idempotency key was used with a different request" next ctx | ConfirmAlreadyConfirmed -> |
