summaryrefslogtreecommitdiff
path: root/tests/FundLab.Api.Tests
Commit message (Collapse)AuthorAgeFilesLines
* Add stock sell vertical slice with cash recovery and snapshot pricing (3d-26)Somhairle H. Marisol13 days2-0/+238
|
* Add daily market refresh endpoint, snapshot-first valuation and UI refresh ↵Somhairle H. Marisol13 days1-0/+127
| | | | (3d-25)
* Add SIP plan pause/resume and rebalance plan archive lifecycle (3d-24)Somhairle H. Marisol13 days3-0/+328
|
* Integrate bond and stock positions into fund valuation (3d-23)Somhairle H. Marisol13 days2-0/+179
|
* Add bond buy to holdings minimal vertical slice (3d-22)Somhairle H. Marisol13 days2-0/+171
|
* Add stock buy to holdings minimal vertical slice (3d-21)Somhairle H. Marisol13 days2-0/+167
|
* Add multi-source bond quote probe fields and daily fallback (3d-20)Somhairle H. Marisol13 days1-9/+65
|
* Add real AKShare stock daily history probe slice (3d-19)Somhairle H. Marisol13 days6-7/+217
|
* Add real AKShare stock quote probe slice (3d-17)Somhairle H. Marisol13 days5-5/+205
|
* Fix bond quote probe to use live convertible-bond spot data (3d-15)Somhairle H. Marisol13 days1-0/+27
|
* Add real AKShare bond quote probe slice (3d-14)Somhairle H. Marisol13 days4-3/+212
|
* Add real NAV series multi-day returns (3d-13)Somhairle H. Marisol13 days3-1/+243
|
* Add real AKShare NAV-date probe slice (3d-12)Somhairle H. Marisol13 days2-0/+249
|
* Add rebalancing execution slice (3d-11)Somhairle H. Marisol13 days2-0/+279
|
* Add scheduled investment plans (3d-10)Somhairle H. Marisol13 days2-0/+323
|
* Add returns and charts slice (3d-9b)Somhairle H. Marisol13 days2-0/+234
|
* Add dividend history visibility (3d-9a)Somhairle H. Marisol13 days1-0/+52
| | | | Expose a deterministic source key on booked dividend records and surface a read-only dividend history panel with empty state, backed by API tests and browser QA assertions.
* Add dividend slice (3d-8)Somhairle H. Marisol13 days3-0/+253
| | | | Book cash dividends to available cash exactly once and reinvest dividends through the shared subscription pipeline, with deterministic scheme idempotency and cross-position isolation.
* Add rebalance first slice (3d-7)Somhairle H. Marisol13 days1-0/+179
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | First vertical slice for portfolio rebalancing. Domain gains RebalancePolicy: target-allocation validation (non-empty, per-code shares positive two-decimal, sum exactly 100); diff computation over the union of target and held codes (held without target = full exit) producing BUY amount diffs and SELL unit diffs priced at the current valuation NAV, clamped to available units, with no orders when a weight already balances; and the deterministic idempotency key set (rebalance:{plan}:{date}:{code} plus confirm/redeem counterparts). Rebalance plans persist as rebalance_plans + rebalance_targets with rebalance_idempotencies under the shared replay/conflict contract. ExecuteRebalancePlan snapshots cash plus holdings valued at each position's latest valuation NAV, then walks the diffs SELL-first through the same Create/Confirm pipeline used by manual orders, redemptions and SIP (nothing bypasses confirmation; a held code without a valuation is skipped with an explicit marker; insufficient cash/units fail the period visibly instead of silently trimming). API exposes POST/GET /funds/{id}/rebalance/plans and POST .../plans/{id}/execute. The frontend adds an 08/REBALANCE panel with target editing (two codes, sum must equal 100), a plan list with a manual execute button and post-run outcome rows; executing refreshes orders/positions so the new orders are immediately visible. Domain tests cover split validation, diff orders, exit/clamp logic, key determinism; API tests cover create/execute end-to-end; Web tests cover decoding and stale-execution protection.
* Drive SIP plans through the shared order pipeline (3d-6)Somhairle H. Marisol13 days2-0/+340
| | | | | | | | | | | | | | | | | | | | | | | 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.
* Add SIP plan first slice (3d-5)Somhairle H. Marisol14 days1-0/+132
| | | | | | | | | | | | | | | | | | | | | Introduce scheduled-investment plans as a schedule-only slice with no cash, position or NAV side effects. Domain gains SipPolicy: amount validation (positive, two-decimal, overflow-checked), frequency parsing/round-trip (weekly/biweekly/monthly), nextTradeDate generating the next due trade date off the plan anchor with month-end clamping and weekend roll-forward, plus the isDue/executionNetAmount contract the future executor will implement (execution itself stays unimplemented and is marked as such; nothing debits cash in this slice). Persistence stores plans in sip_plans with anchor/next trade dates and sip_plan_idempotencies under the shared replay/conflict contract; the API exposes POST/GET /funds/{id}/sip/plans behind the bearer token. The frontend adds a 07/SIP panel (code, amount, frequency select, plan list with next debit date) and Web tests cover decoding, validation, in-flight guards and stale completions. Choice note: first debit is scheduled strictly after the anchor date (creating a plan today never debits today).
* Add additional capital deposit flow (3d-4)Somhairle H. Marisol14 days1-0/+130
| | | | | | | | | | | | | | | | | | Deposits credit a fund's available cash directly: Domain gains CapitalPolicy (positive, two-decimal, overflow-checked amounts plus a settle function that never touches units, NAV or realized P&L). Persistence records deposits in fund_capital_deposits with a fund_capital_idempotencies table, crediting cash and the deposit row atomically under the same replay/conflict semantics as orders. The API exposes POST /funds/{id}/capital/deposit and GET /funds/{id}/capital/deposits behind the bearer token and idempotency keys. The frontend adds an '追加资金' entry on the fund cash card with in-place balance refresh, and repeats of the same amount reuse the idempotency key so double submits credit cash exactly once. Browser QA extends the J-series (J12-J18): invalid-amount rejection without POST, single credited deposit with a 32-hex key, instant balance refresh, unchanged units/cost proving no realized-income impact, and same-key replay crediting only once.
* Add redemption order minimal closed loop (3d-3)Somhairle H. Marisol14 days1-0/+333
| | | | | | | | | | | | | | | | | | | | | Redeem confirmed holdings end to end with exact decimal semantics: submission freezes position units (reserved_units) after an available-units check without touching cash, confirmation settles at the trade-date NAV with evidence and deferral rules identical to subscriptions, credits the fund with proceeds net of the stated fee, and writes off position cost pro rata (full redemption removes the position row). Cash conservation holds at every step: frozen shares and receivable cash never appear as available cash before settlement. Domain gains RedemptionPolicy (request validation plus proceeds/fee/ cost-release computation) with unit tests. Persistence adds redemption_orders, idempotency tables, reserved_units on positions and Create/Confirm repository members; the API exposes POST/GET /funds/{id}/redemptions and POST .../confirm. The frontend adds a 06/REDEEM panel (submit, confirm, pending reasons, confirmed proceeds/cost display), frozen-share display on the holdings panel, and refresh wiring. Browser QA gains a K-series covering freeze, settlement, cash accounting, replay and over-redemption rejection.
* Fix F# option JSON serialization in confirmation/positions API responsesSomhairle H. Marisol14 days2-1/+324
| | | | | | | | | | | Giraffe 6's default Newtonsoft serializer wrapped F# Some values as Value/IsSome/IsNone objects, breaking the confirmation and positions response contract (amounts must be exact decimal strings, absent fields null, quote object-or-null). Add OptionJsonConverter plus a shared serializer registration applied to both the Kestrel host and the in-process test fixture, and cover confirmation/positions over real HTTP including pending, conflict, cross-fund and Kestrel restart-replay regressions.
* Bind subscription confirmation to append-only nav observation evidenceSomhairle H. Marisol14 days1-5/+160
|
* Implement subscription order confirmation with locked trade dates and bound ↵Somhairle H. Marisol14 days1-0/+599
| | | | quote evidence
* fix(api,web): 下单/读取请求身份隔离与零手续费支持(3d-1 ↵Somhairle H. Marisol14 days1-5/+80
| | | | | | | | 评审修正) - Web: orderSeq 拆分为 orderCreateSeq/orderReadSeq,并发刷新不再丢弃在途下单结果;换基金/换 token 双序列失效并携带 fundId 双重守卫 - 零手续费:DB CHECK fee_amount >= 0(幂等迁移),校验改为拒绝负数,UI 提示与占位符同步 - 测试:API 增加零手续费回放与 DB 负手续费约束回归(43/43),浏览器新增 H 系列延迟 POST 并发刷新/失败恢复/换基金隔离(78/78)
* feat(api,web): 模拟认购订单创建/读取,幂等与预留现金(3d-1)Somhairle H. Marisol14 days2-0/+401
| | | | | | | | | | - API: POST/GET /api/funds/{fundId}/orders,advisory lock + 行级锁事务预留现金, 幂等键重放/冲突/校验/目录缺失错误码齐全,基金响应新增 reservedCash - Persistence: subscription_orders 与幂等表 + 保留现金列迁移 - Web: 认购表单与待确认订单列表(已提交·待确认),失败重试复用幂等键, token 轮换隔离延迟响应 - 测试: API 41(含并发不足/回滚/真实宿主重启回归)、Web 17、Domain 19; 浏览器 QA 58 项全过
* fix(api): EOF 阶段到期一律判定超时,恢复的载荷不得转为成功Somhairle H. Marisol14 days1-7/+60
| | | | | | | | - 退出阶段与 EOF 阶段统一用 expired 标志:EOF 等待按剩余总期限计时,未完成读取且非请求取消即视为期限已过,即便清理宽限期回收了载荷也只返回超时错误 - EOF 等待挂接 deadline+请求 联合取消令牌,请求取消即刻中断等待;清理宽限期(2s)仅用于回收日志,不再影响结果分类 - 预先取消的请求不启动采集器进程 - 回归:孤儿管道持有至总期限→超时+后代死亡;EOF 等待中取消→延迟<5s+后代死亡;预取消→无进程启动;保留成功/stderr 洪泛等原行为 - 验证:聚焦 ProcessCollector 11/11,全量 Domain 19 / Web 17 / API 32 通过(构建 0 警告);实机挂起采集器 HTTP 503 2.3s 且无进程残留
* fix(api): ↵Somhairle H. Marisol14 days3-2/+282
| | | | | | | | | | | 加固行情采集子进程超时、取消与进程组清理并脱敏错误 - MarketDataService: setsid 独立会话启动采集器,硬超时覆盖子进程退出与管道 EOF 两个阶段;超时、取消与异常路径按进程组杀灭(含持有管道的后台子进程),不遗留孤儿进程 - App.ts/Search/RefreshNav 传入 ctx.RequestAborted,客户端断开即取消采集 - 对外错误仅返回统一短消息(503 MARKET_DATA_UNAVAILABLE 等),不泄露路径、stderr 或密钥;stderr 仅记录服务端日志 - 新增 9 项子进程回归(成功/stderr 洪泛/超时杀灭/取消杀灭/孤儿管道恢复/畸形载荷/非零退出/启动失败/缺脚本)与 HTTP 脱敏回归;全文套件 66 通过(Domain 19 / Web 17 / API 30) - 实机验证:挂起采集器 503 2.4s 无进程残留;真实 akshare 1.18.96 搜索 000001 返回 200,净值刷新持久化 6010 条观测 - README 与 qa/README 补充环境变量、回归命令、G1 过滤断言口径与真实建档标签辨析
* feat(app): 接入 AKShare 行情采集、净值查询与前端净值曲线Somhairle H. Marisol14 days2-1/+209
| | | | | | | | | | | | | | | | | [变更性质] - 本提交完成 3b 行情闭环:真实 AKShare 搜索与净值采集、PostgreSQL 持久化、鉴权 API 与 Fable 前端净值曲线展示。 [新增功能] - API 新增 /api/instruments/search、/api/instruments/{code}/nav 与 nav/refresh 接口,经 Bearer 鉴权调用 AKShare Python 采集器并幂等落库。 - 前端提供基金搜索、精确代码选择、历史净值刷新/重读与 SVG 折线图,token 变更即清空私有结果并失效在途请求。 [实现方案] - MarketData 以 requiredProperty 校验采集器 payload,净值观测按 (code, nav_date) 幂等 upsert 并保留来源与哈希。 - 前端以 requestId 序列守卫 SearchCompleted/SearchFailed/NavCompleted/NavFailed,TokenChanged 同时递增 searchSeq/navSeq 拒绝过期响应;边界解码兼容 F# option 的 {"case":"Some"} 线格式。 [影响范围] - 新增 FundLab.Web.Tests(边界解码、序列失效、图表纯函数共 8 项),扩展 API 测试至 20 项;vite dev 代理 /api 至本地 API。 - 真实 AKShare 端到端依赖本机 akshare 环境,由负责人另行验收;本提交不包含 docs/overnight-progress.md 的现有修改。
* feat(api): 接入基金 PostgreSQL 持久化与幂等接口Somhairle H. Marisol2026-09-212-0/+776
| | | | | | | | | | | | | | | | | [变更性质] - 本提交新增基金创建与读取的 PostgreSQL 持久化能力,并完成 3a API 收口验证。 [新增功能] - 提供带事务和幂等键的基金创建、重放、冲突检测及基金读取接口。 - 覆盖认证、JSON 输入、数值边界、进程重启持久化和 SQL 故障回滚测试。 [实现方案] - 使用 Npgsql 建立 `funds` 与 `fund_idempotencies` 表,并以 advisory lock 串行化同一幂等键。 - 通过真实 Kestrel 子进程和临时 PostgreSQL 验证 HTTP 行为;同步更新环境、构建和交接文档。 [影响范围] - API 新增 PostgreSQL 配置要求 `FUND_LAB_DATABASE_URL`,前端构建入口和本地验证命令同步明确。 - 本提交不包含 `docs/overnight-progress.md` 的现有 Hermes 修改。
* feat(core): 建立 fund-lab 可运行基线Somhairle H. Marisol2026-09-203-0/+54
[变更性质] - 本提交冻结当前可构建、可测试的应用基线,不包含 PostgreSQL 持久化。 [新增功能] - 建立 F# Domain、API、Worker、Web 及测试项目。 - 增加 Bearer 认证、健康检查、账本领域模型和中文空状态页面。 [实现方案] - 使用环境变量模板注入认证配置,并排除数据、凭证和构建产物。 - 保留 19 个 Domain 测试和 5 个 API 测试作为后续变更基准。 [影响范围] - 为后续 3a PostgreSQL FOF 创建/读取切片提供可回滚基线。 - 当前仍不接入真实基金数据、真实交易或数据库。