summaryrefslogtreecommitdiff
path: root/tests/FundLab.Domain.Tests/DomainTests.fs
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-21 12:38:56 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-21 12:38:56 +0800
commitd2a547b6a60ea769092894fff1f2b5105954f226 (patch)
tree5dfd493d926891509258ef133c0a54b0fac2363f /tests/FundLab.Domain.Tests/DomainTests.fs
parentf4ab0b08d7648914f6fd049fa1887c0422f69318 (diff)
downloadfund-lab-d2a547b6a60ea769092894fff1f2b5105954f226.tar.gz
Drive SIP plans through the shared order pipeline (3d-6)
Advance executes due periods as real subscription orders: each due trade date claims a sip_executions row (PRIMARY KEY plan_id+trade_date makes same-plan same-day runs atomic), places the order through CreateSubscriptionOrder with a deterministic idempotency key (sip:{plan}:{date}) and the period's trade date, then confirms through the shared ConfirmSubscriptionOrder pipeline with key sip-confirm:{plan}:{date} — identical freeze/fee/units math as manual orders, nothing bypasses confirmation. Outcomes: succeeded, pending_nav (cash stays frozen; later drives retry the confirmation once the NAV lands), insufficient_cash (no order placed, period fails visibly, reruns keep the marker), failed. Plans roll their next_trade_date past the processed window and repeats of the same endDate replay recorded executions instead of re-debiting. Domain adds SipPolicy.advancePlan (due-date enumeration; weekends-only trading-calendar approximation, noted in code). POST /funds/{id}/sip/advance {endDate?, limit?} drives execution on demand (no daemon). Plan responses/rows now carry last execution status/date; front-end shows 已执行/待净值/现金不足 per plan. Optional tradeDateOverride/anchorOverride keep manual flows untouched.
Diffstat (limited to 'tests/FundLab.Domain.Tests/DomainTests.fs')
-rw-r--r--tests/FundLab.Domain.Tests/DomainTests.fs22
1 files changed, 22 insertions, 0 deletions
diff --git a/tests/FundLab.Domain.Tests/DomainTests.fs b/tests/FundLab.Domain.Tests/DomainTests.fs
index 13be13f..42dd2a5 100644
--- a/tests/FundLab.Domain.Tests/DomainTests.fs
+++ b/tests/FundLab.Domain.Tests/DomainTests.fs
@@ -621,3 +621,25 @@ module SipPolicyTests =
Assert.Equal(Ok 200.00m, SipPolicy.executionNetAmount 200.00m)
Assert.Equal(Error "sip amount must be positive", SipPolicy.executionNetAmount 0m)
+
+ [<Fact>]
+ let ``advance plan enumerates due dates up to the end date`` () =
+ let anchor = d 2026 9 21
+
+ Assert.Equal<DateOnly list>(
+ [ d 2026 9 28; d 2026 10 5; d 2026 10 12 ],
+ SipPolicy.advancePlan Weekly anchor (d 2026 9 28) (d 2026 10 12)
+ )
+
+ Assert.Equal<DateOnly list>([ d 2026 9 28 ], SipPolicy.advancePlan Weekly anchor (d 2026 9 28) (d 2026 9 30))
+ Assert.Equal<DateOnly list>([], SipPolicy.advancePlan Weekly anchor (d 2026 10 5) (d 2026 9 30))
+
+ [<Fact>]
+ let ``advance plan never emits weekend dates`` () =
+ let anchor = d 2026 1 31
+
+ let dates = SipPolicy.advancePlan Monthly anchor (d 2026 2 2) (d 2026 5 31)
+
+ Assert.All(dates, fun (date: DateOnly) -> Assert.NotEqual(DayOfWeek.Saturday, date.DayOfWeek); Assert.NotEqual(DayOfWeek.Sunday, date.DayOfWeek))
+ Assert.Contains(d 2026 3 2, dates)
+ Assert.Equal(4, dates.Length)