- 下单页新增「指定大神 / 平台派单」模式:平台派单填品类、预算、地点/选点,expertId=0 - 服务端:平台派单单据支付后进入待接单池(余额支付即时入池,微信支付确认后入池),预算由买家出价但受 1~2000 元/小时约束 - 抢单由认领大神写入 expert_id 并转履约中;30 分钟无人接单沿用自动全额退款 - 修复订单 INSERT 占位符少一个导致下单报 Column count doesn't match 的问题,并新增列数/占位符一致性护栏 - 111 套件/737 用例全绿;线上 1 元实测:下单→待接单→池内 640m,测试数据已回滚
64 行
2.9 KiB
TypeScript
64 行
2.9 KiB
TypeScript
// 已读取AGENTS.md
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
|
|
/**
|
|
* 第九十五批:平台派单(发需求单)闭环闸门。
|
|
* 背景:抢单池只查 status='待接单',但下单流程全是「指定大神 → 支付 → 履约中」,
|
|
* 没有任何流程产出待接单订单,导致雷达/接单大厅永远是空池。
|
|
*/
|
|
describe('第九十五批平台派单闭环', () => {
|
|
const root = path.resolve(__dirname, '../../');
|
|
const read = (rel: string) => fs.readFileSync(path.join(root, rel), 'utf-8');
|
|
const repo = read('server/src/db/repository.ts');
|
|
const indexCode = read('server/src/index.ts');
|
|
const createPage = read('pwuniapp/pages/order/create.vue');
|
|
|
|
it('平台派单订单 expertId=0,余额支付后直接进入待接单池', () => {
|
|
expect(repo).toContain('const isMarketplace = !Number(data.expertId)');
|
|
expect(repo).toContain("const expertId = isMarketplace ? 0 : Number(data.expertId)");
|
|
expect(repo).toContain("isMarketplace ? '待接单' : '履约中'");
|
|
});
|
|
|
|
it('平台派单预算由买家出价但受服务端上下限约束', () => {
|
|
expect(repo).toContain('hourlyRate = Math.min(2000, Math.max(1, Number(data.hourlyRate) || 35))');
|
|
});
|
|
|
|
it('微信支付确认后:无大神订单转入待接单而不是履约中', () => {
|
|
expect(indexCode).toContain("const paidStatus = isMarketplace ? '待接单' : '履约中'");
|
|
expect(indexCode).toContain('已进入派单池,等待附近大神接单');
|
|
expect(indexCode).toContain('30 分钟内无人接单将自动全额退款');
|
|
});
|
|
|
|
it('抢单后由认领大神写入 expert_id 并进入履约中', () => {
|
|
expect(repo).toContain("SET status = '履约中', expert_id = ?, companion_name = ?");
|
|
expect(repo).toContain("AND status = '待接单'");
|
|
});
|
|
|
|
it('下单页提供「平台派单」模式并提交 expertId=0', () => {
|
|
expect(createPage).toContain("const orderMode = ref('EXPERT')");
|
|
expect(createPage).toContain('platformCategories');
|
|
expect(createPage).toContain('expertId: isPlatform ? 0 : expert.value.id');
|
|
expect(createPage).toContain('平台派单需求');
|
|
});
|
|
|
|
it('平台派单时不会沿用指定大神页的默认地点', () => {
|
|
expect(createPage).toContain('const switchMode = (mode) =>');
|
|
expect(createPage).toContain("meetVenue.value = '';");
|
|
});
|
|
|
|
it('订单 INSERT 的列数必须与占位符数量一致(含 paid_at/created_at 两个表达式值)', () => {
|
|
const start = repo.indexOf('INSERT INTO orders');
|
|
const end = repo.indexOf('`, [', start);
|
|
const seg = repo.slice(start, end);
|
|
const columns = seg
|
|
.slice(seg.indexOf('(') + 1, seg.indexOf(')'))
|
|
.split(',')
|
|
.filter((s) => s.trim()).length;
|
|
const values = seg.slice(seg.indexOf('VALUES'));
|
|
const placeholders = (values.replace(/\$\{[^}]*\}/g, '').match(/\?/g) || []).length;
|
|
expect(columns).toBe(24);
|
|
expect(placeholders + 2).toBe(columns);
|
|
});
|
|
});
|