-
+
@@ -59,7 +59,7 @@
-
+
diff --git a/tests/frontend/chat.test.cjs b/tests/frontend/chat.test.cjs
index efda82a..00145e8 100644
--- a/tests/frontend/chat.test.cjs
+++ b/tests/frontend/chat.test.cjs
@@ -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',
diff --git a/tests/test_order_data.py b/tests/test_order_data.py
index 321527a..6cffbe3 100644
--- a/tests/test_order_data.py
+++ b/tests/test_order_data.py
@@ -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):
diff --git a/tests/test_visitor.py b/tests/test_visitor.py
index 5b94955..a7b1a43 100644
--- a/tests/test_visitor.py
+++ b/tests/test_visitor.py
@@ -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))