feat(order): complete 7.1 order full lifecycle state transitions, 15m/30m/48h auto-timeouts, expert reject/apply-complete, and partial refund arbitration

这个提交包含在:
xcbyy
2026-10-14 15:52:56 +08:00
父节点 a14f27d641
当前提交 3bf38db8b6
共有 10 个文件被更改,包括 551 次插入 和 34 次删除

查看文件

@@ -248,4 +248,89 @@ describe('CompanionOrderService (TDD 测试套件: 线上游戏与同城陪玩·
}).toThrow('无权核销该订单');
});
});
describe('3. 7.1 陪玩服务全生命周期超时自动流转与部分退款仲裁闭环', () => {
it('待付款订单超过 15 分钟未支付自动流转为已取消 (CANCELLED)', () => {
const order = orderService.createOrder({
buyerId: 1001,
expertId: 2001,
track: CompanionTrack.ONLINE_GAME,
serviceTitle: '王者双排',
hours: 1,
totalAmountCents: 3500,
});
const future16Min = new Date(order.createdAt.getTime() + 16 * 60 * 1000);
const res = orderService.processOrderTimeouts(future16Min);
expect(res.cancelledIds).toContain(order.id);
expect(order.status).toBe(OrderStatus.CANCELLED);
});
it('待接单订单超过 30 分钟大神未接单自动流转为已退款 (REFUNDED)', () => {
const order = orderService.createOrder({
buyerId: 1001,
expertId: 2001,
track: CompanionTrack.ONLINE_GAME,
serviceTitle: '王者双排',
hours: 1,
totalAmountCents: 3500,
});
orderService.payOrder(order.id, 1001);
expect(order.status).toBe(OrderStatus.PENDING_ACCEPT);
const future31Min = new Date((order.paidAt || order.createdAt).getTime() + 31 * 60 * 1000);
const res = orderService.processOrderTimeouts(future31Min);
expect(res.refundedIds).toContain(order.id);
expect(order.status).toBe(OrderStatus.REFUNDED);
expect(order.refundAmountCents).toBe(3500);
});
it('待确认订单超过 48 小时买家未确认自动流转为已完成 (COMPLETED)', () => {
const order = orderService.createOrder({
buyerId: 1001,
expertId: 2001,
track: CompanionTrack.ONLINE_GAME,
serviceTitle: '王者双排',
hours: 2,
totalAmountCents: 7000,
});
orderService.payOrder(order.id, 1001);
orderService.expertAccept(order.id, 2001);
orderService.expertApplyFinish(order.id, 2001);
expect(order.status).toBe(OrderStatus.PENDING_CONFIRM);
const future49Hours = new Date((order.finishAppliedAt || order.createdAt).getTime() + 49 * 60 * 60 * 1000);
const res = orderService.processOrderTimeouts(future49Hours);
expect(res.autoCompletedIds).toContain(order.id);
expect(order.status).toBe(OrderStatus.COMPLETED);
});
it('争议仲裁支持客服判定部分退款 (PARTIAL_REFUND) 并流转为已退款', () => {
const order = orderService.createOrder({
buyerId: 1001,
expertId: 2001,
track: CompanionTrack.ONLINE_GAME,
serviceTitle: '王者三排',
hours: 2,
totalAmountCents: 10000,
});
orderService.payOrder(order.id, 1001);
orderService.expertAccept(order.id, 2001);
orderService.expertApplyFinish(order.id, 2001);
orderService.buyerDispute(order.id, 1001, '只打了一半时长申请部分退款');
const arbOrder = orderService.arbitrate({
orderId: order.id,
operatorAdminId: 9001,
decision: 'PARTIAL_REFUND',
refundAmountCents: 5000,
reason: '核实已完成1小时对局,判定退还买家一半费用',
});
expect(arbOrder.status).toBe(OrderStatus.REFUNDED);
expect(arbOrder.arbitrationDecision).toBe('PARTIAL_REFUND');
expect(arbOrder.refundAmountCents).toBe(5000);
});
});
});