From 64a4ca5c0a523ffc51c861eac1291671b90a2f3a Mon Sep 17 00:00:00 2001 From: "Somhairle H. Marisol" Date: Mon, 21 Sep 2026 06:38:58 +0800 Subject: fix(api,web): 下单/读取请求身份隔离与零手续费支持(3d-1 评审修正) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Web: orderSeq 拆分为 orderCreateSeq/orderReadSeq,并发刷新不再丢弃在途下单结果;换基金/换 token 双序列失效并携带 fundId 双重守卫 - 零手续费:DB CHECK fee_amount >= 0(幂等迁移),校验改为拒绝负数,UI 提示与占位符同步 - 测试:API 增加零手续费回放与 DB 负手续费约束回归(43/43),浏览器新增 H 系列延迟 POST 并发刷新/失败恢复/换基金隔离(78/78) --- src/FundLab.Api/Persistence.fs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/FundLab.Api') diff --git a/src/FundLab.Api/Persistence.fs b/src/FundLab.Api/Persistence.fs index 88c0350..6c60bdd 100644 --- a/src/FundLab.Api/Persistence.fs +++ b/src/FundLab.Api/Persistence.fs @@ -131,13 +131,16 @@ type FundRepository(connectionString: string) = fund_id uuid NOT NULL REFERENCES funds(id), fund_code text NOT NULL, amount numeric(20, 2) NOT NULL CHECK (amount > 0), - fee_amount numeric(20, 2) NOT NULL CHECK (fee_amount > 0), + fee_amount numeric(20, 2) NOT NULL CHECK (fee_amount >= 0), reserved_total numeric(20, 2) NOT NULL CHECK (reserved_total > 0), status text NOT NULL, is_synthetic boolean NOT NULL, submitted_at timestamptz NOT NULL DEFAULT now() ); + ALTER TABLE subscription_orders DROP CONSTRAINT IF EXISTS subscription_orders_fee_amount_check; + ALTER TABLE subscription_orders ADD CONSTRAINT subscription_orders_fee_amount_check CHECK (fee_amount >= 0); + CREATE TABLE IF NOT EXISTS subscription_order_idempotencies ( idempotency_key text PRIMARY KEY, request_hash text NOT NULL, @@ -564,8 +567,8 @@ type FundRepository(connectionString: string) = Error "fund code cannot be empty" elif command.Amount <= 0m then Error "amount must be positive" - elif command.FeeAmount <= 0m then - Error "fee amount must be positive" + elif command.FeeAmount < 0m then + Error "fee amount cannot be negative" elif Decimal.Round(command.Amount, 2) <> command.Amount then Error "amount exceeds cash precision" elif Decimal.Round(command.FeeAmount, 2) <> command.FeeAmount then -- cgit v1.2.3