# Instructions

- Following Playwright test failed.
- Explain why, be concise, respect Playwright best practices.
- Provide a snippet of code with the fix, if possible.

# Test info

- Name: transaction-full.spec.ts >> 订单管理 >> 查询订单列表 - 按日期筛选
- Location: tests/transaction-full.spec.ts:629:7

# Error details

```
TimeoutError: apiRequestContext.get: Timeout 15000ms exceeded.
Call log:
  - → GET http://192.168.3.151:5173/nail/pos/orders?page=1&page_size=20&date_from=2026-07-24&date_to=2026-07-24
    - user-agent: Playwright/1.61.1 (arm64; alpine 3.23.4) node/20.20
    - accept: */*
    - accept-encoding: gzip,deflate,br
    - Product: inail
    - Authorization: Bearer 01KY9GKYFC6WD17XYT310FT9NM
    - Content-Type: application/json

```

# Test source

```ts
  530 |         visit_card_splits: [{ holding_id: 'fake_id_should_fail', amount_cents: 8800 }],
  531 |       }),
  532 |     });
  533 |     // 假 ID 不能成功！这是安全漏洞
  534 |     expect(res.status()).toBeGreaterThanOrEqual(400);
  535 |   });
  536 | 
  537 |   test('次卡核销 - 空 splits 应报错', async ({ request }) => {
  538 |     const res = await request.post(`${BASE}/nail/pos/transactions`, {
  539 |       headers: headers(),
  540 |       data: makeTransaction({
  541 |         client_id: ADA_ID,
  542 |         items: [serviceItem(SVC_PURE, '纯色美甲', 8800)],
  543 |         method: 'visit_card',
  544 |         split_payments: [{ method: 'visit_card', amount_cents: 8800 }],
  545 |         visit_card_splits: [],
  546 |       }),
  547 |     });
  548 |     expect(res.status()).not.toBe(500);
  549 |   });
  550 | 
  551 |   test('次卡核销 - 无 client_id 应报错', async ({ request }) => {
  552 |     const res = await request.post(`${BASE}/nail/pos/transactions`, {
  553 |       headers: headers(),
  554 |       data: makeTransaction({
  555 |         items: [serviceItem(SVC_PURE, '纯色美甲', 8800)],
  556 |         method: 'visit_card',
  557 |         split_payments: [{ method: 'visit_card', amount_cents: 8800 }],
  558 |         visit_card_splits: [{ holding_id: 'test', amount_cents: 8800 }],
  559 |       }),
  560 |     });
  561 |     expect(res.status()).not.toBe(500);
  562 |   });
  563 | });
  564 | 
  565 | // ═══════════════════════════════════════════════════
  566 | // 六、代金券核销
  567 | // ═══════════════════════════════════════════════════
  568 | test.describe('代金券核销', () => {
  569 | 
  570 |   test('代金券核销 - 假 voucher_id 必须被拒绝', async ({ request }) => {
  571 |     const res = await request.post(`${BASE}/nail/pos/transactions`, {
  572 |       headers: headers(),
  573 |       data: makeTransaction({
  574 |         client_id: ADA_ID,
  575 |         items: [serviceItem(SVC_PURE, '纯色美甲', 8800)],
  576 |         method: 'voucher',
  577 |         split_payments: [{ method: 'voucher', amount_cents: 8800 }],
  578 |         voucher_splits: [{ voucher_id: 'fake_voucher_should_fail', amount_cents: 8800 }],
  579 |       }),
  580 |     });
  581 |     // 假 ID 不能成功！安全漏洞
  582 |     expect(res.status()).toBeGreaterThanOrEqual(400);
  583 |   });
  584 | 
  585 |   test('代金券核销 - 空 splits 应报错', async ({ request }) => {
  586 |     const res = await request.post(`${BASE}/nail/pos/transactions`, {
  587 |       headers: headers(),
  588 |       data: makeTransaction({
  589 |         client_id: ADA_ID,
  590 |         items: [serviceItem(SVC_PURE, '纯色美甲', 8800)],
  591 |         method: 'voucher',
  592 |         split_payments: [{ method: 'voucher', amount_cents: 8800 }],
  593 |         voucher_splits: [],
  594 |       }),
  595 |     });
  596 |     expect(res.status()).not.toBe(500);
  597 |   });
  598 | 
  599 |   test('代金券 - 金额超过券面值应报错', async ({ request }) => {
  600 |     const res = await request.post(`${BASE}/nail/pos/transactions`, {
  601 |       headers: headers(),
  602 |       data: makeTransaction({
  603 |         client_id: ADA_ID,
  604 |         items: [serviceItem(SVC_SHELL, '韩式贝壳片', 22800)],
  605 |         method: 'voucher',
  606 |         split_payments: [{ method: 'voucher', amount_cents: 22800 }],
  607 |         voucher_splits: [{ voucher_id: 'fake_voucher', amount_cents: 22800 }],
  608 |       }),
  609 |     });
  610 |     expect(res.status()).not.toBe(500);
  611 |   });
  612 | });
  613 | 
  614 | // ═══════════════════════════════════════════════════
  615 | // 七、订单管理
  616 | // ═══════════════════════════════════════════════════
  617 | test.describe('订单管理', () => {
  618 | 
  619 |   test('查询订单列表 - 全部', async ({ request }) => {
  620 |     const res = await request.get(`${BASE}/nail/pos/orders?page=1&page_size=20`, {
  621 |       headers: headers(),
  622 |     });
  623 |     expect(res.status()).toBe(200);
  624 |     const data = await res.json();
  625 |     expect(data).toHaveProperty('orders');
  626 |     expect(data).toHaveProperty('total');
  627 |   });
  628 | 
  629 |   test('查询订单列表 - 按日期筛选', async ({ request }) => {
> 630 |     const res = await request.get(`${BASE}/nail/pos/orders?page=1&page_size=20&date_from=${today()}&date_to=${today()}`, {
      |                               ^ TimeoutError: apiRequestContext.get: Timeout 15000ms exceeded.
  631 |       headers: headers(),
  632 |     });
  633 |     expect(res.status()).toBe(200);
  634 |   });
  635 | 
  636 |   test('查询订单列表 - 按员工筛选', async ({ request }) => {
  637 |     const res = await request.get(`${BASE}/nail/pos/orders?page=1&page_size=20&employee_id=${EMPLOYEE_ID}`, {
  638 |       headers: headers(),
  639 |     });
  640 |     expect(res.status()).toBe(200);
  641 |   });
  642 | 
  643 |   test('查询订单列表 - 按状态筛选（completed）', async ({ request }) => {
  644 |     const res = await request.get(`${BASE}/nail/pos/orders?page=1&page_size=20&status=completed`, {
  645 |       headers: headers(),
  646 |     });
  647 |     expect(res.status()).toBe(200);
  648 |   });
  649 | 
  650 |   test('查询订单列表 - 按状态筛选（pending）', async ({ request }) => {
  651 |     const res = await request.get(`${BASE}/nail/pos/orders?page=1&page_size=20&status=pending`, {
  652 |       headers: headers(),
  653 |     });
  654 |     expect(res.status()).toBe(200);
  655 |   });
  656 | 
  657 |   test('查询订单列表 - 按状态筛选（voided）', async ({ request }) => {
  658 |     const res = await request.get(`${BASE}/nail/pos/orders?page=1&page_size=20&status=voided`, {
  659 |       headers: headers(),
  660 |     });
  661 |     expect(res.status()).toBe(200);
  662 |   });
  663 | 
  664 |   test('今日统计 - summary', async ({ request }) => {
  665 |     const res = await request.get(`${BASE}/nail/pos/summary?period=day`, {
  666 |       headers: headers(),
  667 |     });
  668 |     expect(res.status()).toBe(200);
  669 |     const data = await res.json();
  670 |     expect(data).toHaveProperty('total_revenue_cents');
  671 |     expect(data).toHaveProperty('transaction_count');
  672 |   });
  673 | 
  674 |   test('挂单列表', async ({ request }) => {
  675 |     const res = await request.get(`${BASE}/nail/pos/holds`, {
  676 |       headers: headers(),
  677 |     });
  678 |     expect(res.status()).toBe(200);
  679 |   });
  680 | });
  681 | 
  682 | // ═══════════════════════════════════════════════════
  683 | // 八、预约流程
  684 | // ═══════════════════════════════════════════════════
  685 | test.describe('预约流程', () => {
  686 | 
  687 |   test('创建预约 - 完整字段', async ({ request }) => {
  688 |     const res = await request.post(`${BASE}/nail/appointments`, {
  689 |       headers: headers(),
  690 |       data: {
  691 |         client_id: ADA_ID,
  692 |         service_id: SVC_PURE,
  693 |         employee_id: EMPLOYEE_ID,
  694 |         start_time: '2026-07-27T10:00:00Z',
  695 |         source: 'sys_employee',
  696 |         items: [{ service_id: SVC_PURE, employee_id: EMPLOYEE_ID, start_time: '2026-07-27T10:00:00Z', price_cents: 8800 }],
  697 |         notes: 'E2E完整字段测试',
  698 |       },
  699 |     });
  700 |     expect(res.status()).toBe(201);
  701 |     const data = await res.json();
  702 |     expect(data.status).toBe('confirmed');
  703 |     expect(data.id).toBeTruthy();
  704 |   });
  705 | 
  706 |   test('创建预约 - 前端格式（缺顶层字段）不应 500', async ({ request }) => {
  707 |     const res = await request.post(`${BASE}/nail/appointments`, {
  708 |       headers: headers(),
  709 |       data: {
  710 |         items: [{ service_id: SVC_PURE, employee_id: null, start_time: '2026-07-27T14:00:00Z' }],
  711 |         notes: '',
  712 |         client_id: ADA_ID,
  713 |       },
  714 |     });
  715 |     expect(res.status()).not.toBe(500);
  716 |   });
  717 | 
  718 |   test('创建预约 - 多服务项', async ({ request }) => {
  719 |     const res = await request.post(`${BASE}/nail/appointments`, {
  720 |       headers: headers(),
  721 |       data: {
  722 |         client_id: ADA_ID,
  723 |         service_id: SVC_PURE,
  724 |         employee_id: EMPLOYEE_ID,
  725 |         start_time: '2026-07-27T16:00:00Z',
  726 |         source: 'sys_employee',
  727 |         items: [
  728 |           { service_id: SVC_PURE, employee_id: EMPLOYEE_ID, start_time: '2026-07-27T16:00:00Z', price_cents: 8800 },
  729 |           { service_id: SVC_GRADIENT, employee_id: EMPLOYEE_ID, start_time: '2026-07-27T17:00:00Z', price_cents: 13800 },
  730 |         ],
```