134 lines
7.6 KiB
Python
134 lines
7.6 KiB
Python
"""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)
|