fix(order): 抢单收紧为仅「待接单」可抢,抢单池同步过滤

- claimOrder 状态闸门改为严格只允许 待接单(含 CAS 条件 status='待接单'),杜绝抢已在履约/已服务/已核销的订单

- getOrdersPool 仅返回未认领的 待接单 订单

- 种子数据新增一笔待接单订单用于演示抢单

- 更新/新增回归护栏 claim-status-gate.spec.ts(78 套件/608 用例全绿)
这个提交包含在:
xcbyy
2026-10-19 08:54:28 +08:00
父节点 8edffbefa2
当前提交 c90b0bd44e
共有 5 个文件被更改,包括 49 次插入 和 9 次删除

查看文件

@@ -0,0 +1,35 @@
// 已读取AGENTS.md
import * as fs from 'fs';
import * as path from 'path';
/**
* 第六十二批回归闸门:抢单状态收紧为「仅待接单可抢」
*/
describe('第六十二批抢单状态闸门', () => {
const rootDir = path.resolve(__dirname, '../../');
const repoCode = fs.readFileSync(path.join(rootDir, 'server/src/db/repository.ts'), 'utf-8');
const mysqlCode = fs.readFileSync(path.join(rootDir, 'server/src/db/mysql.ts'), 'utf-8');
const claimBlock = () => {
const start = repoCode.indexOf('async claimOrder(');
expect(start).toBeGreaterThan(-1);
return repoCode.slice(start, start + 2600);
};
it('仅待接单可抢单(含 CAS 条件)', () => {
const b = claimBlock();
expect(b).toContain("String(cur.status) !== '待接单'");
expect(b).toContain("仅待接单可抢");
expect(b).toContain("AND status = '待接单'");
});
it('抢单池仅含待接单且未认领', () => {
const start = repoCode.indexOf('async getOrdersPool(');
const block = repoCode.slice(start, start + 900);
expect(block).toContain("WHERE status = '待接单'");
});
it('种子数据提供一笔待接单用于演示抢单', () => {
expect(mysqlCode).toContain("'待接单');");
});
});

查看文件

@@ -46,9 +46,13 @@ describe('订单与活动资金一致性护栏 (报名超卖 / 抢单 CAS / 评
expect(code).toContain('该订单已被其他大神抢先接单');
});
it('claimOrder 必须拦截不可接单状态', () => {
it('claimOrder 必须仅允许待接单抢单', () => {
const code = fs.readFileSync(serverRepoPath, 'utf-8');
expect(code).toContain("const blocked = ['待付款', '待支付', '已完成', '已取消', '已关闭', '已退款', '已全额退款', '争议仲裁中']");
const start = code.indexOf('async claimOrder(');
expect(start).toBeGreaterThan(-1);
const block = code.slice(start, start + 2400);
expect(block).toContain("String(cur.status) !== '待接单'");
expect(block).toContain("AND status = '待接单'");
});
it('数据库层必须为 orders 增加 claimed_by / claimed_at 认领标记列', () => {

查看文件

@@ -13,7 +13,7 @@ describe('第二十九批抢单池过滤闸门', () => {
const start = repoCode.indexOf('async getOrdersPool(');
expect(start).toBeGreaterThan(-1);
const block = repoCode.slice(start, start + 1400);
expect(block).toContain("WHERE status NOT IN ('已完成', '已取消'");
expect(block).toContain("WHERE status = '待接单'");
expect(block).toContain('claimed_by IS NULL');
expect(block).toContain('LIMIT 20');
});