Files
baiyue-logistics-chat/tests/test_quote_business.py
T

134 lines
7.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Customer-language regressions use synthetic amounts, never private tariffs."""
from decimal import Decimal
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch
from logistics_chat import create_app, db
from logistics_chat.quote_data import import_snapshot
from logistics_chat.quote_engine import quantity, parse_intent
from test_quotes import fixture_snapshot, frames
class QuoteBusinessTests(unittest.TestCase):
def setUp(self):
folder=tempfile.TemporaryDirectory();self.addCleanup(folder.cleanup)
root=Path(folder.name)
self.app=create_app({'TESTING':True,'DATABASE':root/'test.db','UPLOAD_DIR':root/'uploads',
'BACKUP_DIR':root/'backups','LOG_DIR':root/'logs','DEEPSEEK_API_KEY':'','RATE_LIMIT_PER_MIN':1000})
self.client=self.app.test_client()
self.client.post('/api/visitor/session',json={'key':'1'*64})
book=fixture_snapshot()
documents=[
'铁铝制品另外加附加费¥5/KG',
'正常货物 A.0KG<单件重量<22KG B.0CM<最长单边长度<120CM C.0CM<第二边<75CM D.最长边<260CM',
'单件不能超22KG 超重收+70/件',
'普通超尺寸加收90RMB/件',
'大尺寸货物,任意2个条件,加收400RMB/件:22KG<单件重量<68KG;0<最长边<274CM;330CM<周长+单边长<419CM',
'超大件货物,加收USD900/件',
'保险费:保额的百分之0.25,min 13USD,投保金额是货值乘以1.2。',
'海外进口清关,超过5个品名,续页加收USD7元RMB/个',
'一般贸易出口报关费:RMB60/票',
'偏远地址加收4元/kg;超偏远地址加收6元/kg',
'禁止运输的货物:纯电池、液体、食品',
]
book['documents']=[{'sheet':'海派','cell':f'A{i+1}','text':text} for i,text in enumerate(documents)]
book['documents'].append({'sheet':'美森加班海卡','cell':'A1','text':'不可接一般贸易'})
with self.app.app_context():
c=db.connect();import_snapshot(c,book,activate=True);c.commit();c.close()
def ask(self,text,cid=None):
with patch('logistics_chat.ai_client.post_completion') as model:
events=frames(self.client.post('/stream_chat',json={'msg':text,'conv_id':cid}))
model.assert_not_called()
self.assertEqual(events[-1],{'d':1},events)
return events[0]['t']
def test_different_cartons_use_individual_minimums_and_dimensions(self):
text=self.ask('美国美西,1箱10KG,1箱20KG,义乌普船海派')
self.assertIn('32KG = 64元',text)
text=self.ask('美国美西,2箱,1箱10KG,60x50x40cm,1箱20KG,40x30x20cm,义乌普船海派')
self.assertIn('40KG = 80元',text)
text=self.ask('美国美西,2箱,1箱10KG,60x50x40cm,1箱20KG,义乌普船海派')
self.assertIn('40KG = 80元',text)
self.assertIn('箱数与分箱明细不一致',self.ask('美国3箱,1箱10KG,1箱20KG海派'))
def test_weight_units_chinese_followup_and_invalid_postal(self):
cid=self.client.post('/api/new_chat').json['id']
self.ask('美国美西30KG,义乌海派',cid)
for text in ('五十公斤呢','50000克呢','0.05吨呢'):
self.assertIn('美国 50KG',self.ask(text,cid))
self.assertIn('大于 0',self.ask('美国重量为-30KG海派'))
self.assertIn('邮编格式不正确',self.ask('美国30KG,邮编518000海派'))
self.assertIn('美国 30KG',self.ask('美国30000克海派'))
self.assertIn('未找到目的仓码',self.ask('美国30KG发ABC999海派'))
def test_commodity_survives_weight_followups_and_new_commodity_replaces_it(self):
cid=self.client.post('/api/new_chat').json['id']
text=self.ask('美国美西铁制品30KG,义乌普船海派',cid)
self.assertIn('铁铝附加费5元/KG',text)
self.assertIn('30KG = 210元',text)
self.assertIn('50KG = 350元',self.ask('50KG呢',cid))
self.assertNotIn('铁铝附加费',self.ask('换成普通货50KG呢',cid))
def test_limit_fees_take_maximum_per_carton_and_do_not_guess_bad_threshold(self):
text=self.ask('美国美西1箱30KG,130x50x20cm,义乌普船海派')
self.assertIn('最高项90元/件',text)
self.assertNotIn('160元',text)
text=self.ask('美国美西1箱30KG,180x50x30cm,义乌普船海派')
self.assertIn('最高项400元/件',text)
text=self.ask('美国美西1箱30KG,40x30x20cm,义乌普船海派')
self.assertIn('最高项70元/件',text)
self.assertNotIn('400元/件',text)
self.assertIn('人工确认是否接收',self.ask('美国美西1箱70KG,40x30x20cm,义乌普船海派'))
def test_cbm_uses_two_decimals_half_up_without_creating_free_shipments(self):
rate={'unit':'cbm','kind':'truck','service':'洛杉矶普船海卡'}
intent=parse_intent('美国1KG,1.005CBM',set())
self.assertEqual(quantity(intent,rate),Decimal('1.01'))
intent['cbm']='1.004';self.assertEqual(quantity(intent,rate),Decimal('1.00'))
intent['weight']='0.1';intent['cbm']='0.004'
self.assertIsNone(quantity(intent,rate))
def test_business_topics_use_current_documents_instead_of_generic_quotes(self):
insurance=self.ask('美国保价1万美元,保险费怎么算')
self.assertIn('0.25%',insurance);self.assertIn('=25USD',insurance)
self.assertNotIn('元/KG',insurance)
self.assertIn('大于0',self.ask('美国保价-10美元,保险费怎么算'))
text=self.ask('美国30KG,7个品名清关续页收费')
self.assertIn('7美元/个',text);self.assertIn('=14美元',text)
text=self.ask('美国30KG还需要什么费用')
self.assertIn('偏远地址加4元/KG',text);self.assertIn('超偏远地址加6元/KG',text)
self.assertNotIn('250',text)
self.assertIn('不可接一般贸易',self.ask('美国美森加班海卡一般贸易报关多少钱'))
self.assertIn('不接收',self.ask('美国30KG纯电池可以发吗'))
self.assertIn('不接收',self.ask('美国30KG食品,FDA申报费多少人民币'))
def test_destination_origin_comparison_time_and_english(self):
cid=self.client.post('/api/new_chat').json['id']
self.ask('美国30KG发ZZZ1,义乌海派',cid)
text=self.ask('深圳交仓呢',cid)
self.assertIn('美国 30KG',text);self.assertNotIn('· 义乌',text)
text=self.ask('海运和空运哪个好,美国30KG')
self.assertIn('没有美国空运费率',text)
text=self.ask('美国美西海派多久')
self.assertIn('按开船后到提取计算',text);self.assertNotIn('元/KG',text)
text=self.ask('Please quote 30kg to US by sea')
self.assertIn('CNY/kg',text)
self.assertFalse(__import__('re').search(r'[\u4e00-\u9fff]',text),text)
def test_human_and_photo_questions_never_use_old_regional_model_facts(self):
self.assertIn('联系人工',self.ask('帮我转人工客服'))
text=self.ask('我可以发张货物照片让你判断报价吗')
self.assertIn('不会自动识别',text);self.assertNotIn('21KG',text)
def test_short_fee_synonyms_keep_current_us_rules(self):
cid=self.client.post('/api/new_chat').json['id']
self.ask('美国美西30KG,义乌普船海派',cid)
for question in ('还加什么费','还有其他费用吗','这个还要加钱吗','有其他额外收费吗'):
text=self.ask(question,cid)
self.assertIn('偏远地址加4元/KG',text)
self.assertNotIn('250',text)