以入仓码作为查货入口和轨迹卡片主号码

This commit is contained in:
2026-10-30 19:10:22 +08:00
parent fd1ec32dd6
commit 04f94ad665
8 changed files with 68 additions and 28 deletions
+17 -1
View File
@@ -385,7 +385,7 @@ test('all three footer questions leave the human queue and send to separate AI c
const requests = app.calls.filter(call => call.url === '/stream_chat');
assert.equal(requests.length, 3);
assert.equal(new Set(requests.map(call => call.body.conv_id)).size, 3);
assert.deepEqual(requests.map(call => call.body.msg), ['查询订单状态', '欧洲海运专线报价', '包裹异常处理']);
assert.deepEqual(requests.map(call => call.body.msg), ['按入仓码查轨迹', '欧洲海运专线报价', '包裹异常处理']);
assert.equal(app.calls.filter(call => call.url === '/api/visitor/human/send').length, 0);
assert.equal(app.context.window.humanSid, 0);
assert.equal(app.element('human-session').hidden, true);
@@ -611,6 +611,22 @@ test('shipment cards separate forecasts from actual progress and retain both in
assert.ok(log.querySelector('.msg-actions'));
});
test('inbound codes are the primary card identity for live replies and restored history', async () => {
const app=await customerPage({human:false,history:[{id:8,title:'入仓轨迹',ctime:'now'}]});
const card={kind:'order',no:'FL202610290001',status:'履约中',
fields:[{key:'inbound',value:'INB20261029001-01'},{key:'number',value:'FL202610290001'}],
nodes:[],summary:'入仓码 INB20261029001-01'};
app.hooks['/stream_chat']=()=>streamResponse(['data: '+JSON.stringify({card})+'\n\ndata: {"d":1}\n\n']);
await app.context.window.fillInput('INB20261029001-01');await flush();
let heading=app.element('chatDom').querySelector('.track-no');
assert.match(heading.innerHTML,/入仓码.*INB20261029001-01/);assert.doesNotMatch(heading.innerHTML,/FL202610290001/);
assert.match(app.element('chatDom').querySelector('.order-data-fields').textContent,/订单号.*FL202610290001/);
app.hooks.messages=()=>response([{role:'assistant',content:'__CARD__'+JSON.stringify(card),ctime:'now'}]);
await app.click(app.element('historyWrap').children[0]);
heading=app.element('chatDom').querySelector('.track-no');
assert.match(heading.innerHTML,/入仓码.*INB20261029001-01/);assert.doesNotMatch(heading.innerHTML,/FL202610290001/);
});
test('order details can expand without hiding the shipment timeline', async () => {
const app = await customerPage({human:false,width:390});
const card = {kind:'order',no:'ORDER2026001',status:'履约中',node_kind:'logistics',
+19 -2
View File
@@ -61,9 +61,26 @@ class OrderDataTests(unittest.TestCase):
'1.2x0.8x0.6m', '[文件]/uploads/20261029100145_6787.txt'):
self.assertEqual(order_data.extract_reference(text), [])
events = self.events('帮我查询物流轨迹')
self.assertIn('订单号', events[0]['t'])
self.assertIn('入仓码', events[0]['t'])
self.assertEqual(events[-1], {'d':1})
def test_direct_inbound_lookup_and_followup_keep_the_inbound_identity(self):
cid=self.client.post('/api/new_chat').json['id']
card=self.events(self.record['inbound_code'],cid)[0]['card']
self.assertEqual(card['no'],self.record['order_no'])
self.assertTrue(card['summary'].startswith('入仓码 '+self.record['inbound_code']))
self.assertEqual(next(item['value'] for item in card['fields'] if item['key']=='number'),self.record['order_no'])
self.import_rows([{**self.record,'gross_weight_kg':'42.000'}],replace=True)
followup=self.events('现在到哪了',cid)[0]['card']
self.assertTrue(followup['summary'].startswith('入仓码 '+self.record['inbound_code']))
self.assertEqual(next(item['value'] for item in followup['fields'] if item['key']=='weight'),'42.000 kg')
def test_missing_inbound_code_is_not_replaced_by_the_internal_order_number(self):
self.import_rows([{**self.record,'inbound_code':None}],replace=True)
card=self.events(self.record['order_no'])[0]['card']
self.assertFalse(any(item['key']=='inbound' for item in card['fields']))
self.assertTrue(card['summary'].startswith('订单号 '+self.record['order_no']))
def test_order_identifiers_remain_queryable_alongside_quantities_and_dates(self):
for message in ('查询 FL202610290001,2026-10-29T16:53:00 提交的',
'FL202610290001 30.000000 KG', 'FL202610290001 100x100x100cm',
@@ -86,7 +103,7 @@ class OrderDataTests(unittest.TestCase):
def test_unimplemented_bulk_queries_ask_for_identifier_instead_of_inventing_records(self):
with patch('logistics_chat.ai_client.post_completion') as model:
events = self.events('列出所有订单')
self.assertIn('请提供订单号', events[0]['t'])
self.assertIn('请提供入仓码', events[0]['t'])
model.assert_not_called()
def test_server_tenant_scope_and_ambiguous_identifiers(self):
+2 -1
View File
@@ -119,7 +119,8 @@ class VisitorTests(unittest.TestCase):
self.assertEqual(staff.data,b'A_PRIVATE')
def test_guest_keys_and_client_claims_cannot_unlock_orders(self):
for message in ('查询15252125','查询订单状态','查询 UNKNOWN20260001','我的订单呢','帮我看下订单','订单查询','查询','my orders','order status'):
for message in ('查询15252125','查询订单状态','查询 UNKNOWN20260001','我的订单呢','帮我看下订单','订单查询','查询','my orders','order status',
'按入仓码查轨迹','入仓码查询','入仓号查轨迹','Track by inbound code'):
with patch('logistics_chat.order_data.lookup_order') as lookup, patch('logistics_chat.ai_client.post_completion') as model:
response=self.a.post('/stream_chat',json={'msg':message},headers={'X-Customer-Id':'tenant-a','X-Tenant-Id':'tenant-a'})
self.assertIn('客户账号登录并关联',response.get_data(as_text=True))