"""Recognize explicit, whitelisted order summary and list filters.""" import re from .order_tracking import NODE_LABELS NODE_PHRASES = ( ('DOMESTIC_RECEIVED',r'已入国内仓|已入仓'), ('LOADING_COMPLETED',r'已完成装柜|已装柜'), ('DEPARTED_WAREHOUSE',r'已离开国内仓库|已离仓|已出库'), ('AT_ORIGIN_PORT',r'重箱已进入起运港或码头|已到起运港|已进起运港'), ('LOADED_ON_VESSEL',r'已装船'), ('DEPARTED_ORIGIN_PORT',r'船舶已离开起运港|已开船|开船'), ('IN_TRANSIT',r'海运途中|运输中|在途|海上'), ('ARRIVED_DESTINATION_PORT',r'船舶已到目的港|已到目的港|已到港|到港'), ('DISCHARGED_FROM_VESSEL',r'已卸船、未清关|卸船未清关|已卸船|卸船'), ('PICKUP_READY',r'已清关、可提柜|已清关|清关完成|可提柜'), ('PICKED_UP',r'已提柜|提柜'), ('EMPTY_RETURNED',r'已还柜|还柜'), ('NO_ACTUAL',r'没有实际轨迹|暂无实际节点|没有轨迹|无轨迹'), ('MIXED',r'多柜进度不一致|多柜进度不同'), ) STAGE_LABELS = {code:labels[1] for code,labels in NODE_LABELS.items()} STAGE_LABELS.update(NO_ACTUAL='暂无实际节点',MIXED='多柜进度不同') STATUSES = (('头程订单已完成','COMPLETED'),('已完成','COMPLETED'),('履约中','PROCESSING'), ('处理中','PROCESSING'),('已取消','CANCELLED'),('审核通过','APPROVED'), ('审核驳回','REJECTED'),('已接单','ACCEPTED'),('已提交','SUBMITTED'),('草稿','DRAFT'), ('processing','PROCESSING')) NOUN = r'订单|运单|入仓码|入仓号|\borders?\b|\bshipments?\b' COUNT = r'多少|几(?:个|票|条|张|笔)|总数|数量|总量|统计|数一下|(?:订单|运单)数(?!量)|\bhow\s+many\b|\bcount\b|\bnumber\b|\btotal\b' def parse_query(message,listing=False): if not re.search(NOUN,message,re.I):return None if not listing and not (re.search(COUNT,message,re.I) or re.search(r'分布|(?:都|分别).*到哪',message)):return None if re.search(r'公斤|千克|\bkg\b|重量|毛重|体积|件数|箱数|运费|费用|价格|多少钱',message,re.I):return None remaining=message statuses=[];nodes=[] # Unknown/negated logistics conditions must never silently become a total. unsupported=bool(re.search(r'未到港|没到港|还没|未开船|未发货|未签收|已签收|已送达|曾经|曾到|到过|正常订单|无异常',remaining)) for code,pattern in NODE_PHRASES: if re.search(pattern,remaining): nodes.append(code);remaining=re.sub(pattern,'',remaining) for phrase,status in STATUSES: if re.search(re.escape(phrase),remaining,re.I): statuses.append(status);remaining=re.sub(re.escape(phrase),'',remaining,flags=re.I) exception=bool(re.search(r'异常|\b(?:exception|abnormal)\b',remaining,re.I)) remaining=re.sub(r'物流异常|异常|\b(?:exception|abnormal)\b','',remaining,flags=re.I) grouped=not nodes and bool(re.search(r'轨迹|节点|阶段|到哪|\btracking (?:stages?|nodes?)\b',remaining,re.I)) remaining=re.sub(r'物流轨迹|物流节点|当前节点|轨迹|节点|阶段|到哪里|到哪|各自|各个|每个|分别|分布|各|都|了|\btracking (?:stages?|nodes?)\b', '',remaining,flags=re.I) remaining=re.sub(COUNT+'|'+NOUN,'',remaining,flags=re.I) remaining=re.sub(r'当前账号|当前账户|账号下|账户下|名下|可查询|能查到|可以查到|目前|现在|当前|一共|总共|合计|总计|' r'请问|麻烦|帮我|想知道|想查|想看|请|查询|查一下|查下|查查|看一下|看看|看下|一下|下|列出|列表|显示|全部|所有|共有|我的|我|能|有|的|个|票|条|张|笔|呢|吗|呀|啊|共|' r'\b(?:list|what|is|of|do|i|have|are|there|my|in|all|the|currently|at|each)\b|[\s,,。.!!??、::]','',remaining,flags=re.I) return {'status':statuses[0] if statuses else None,'stage':nodes[0] if nodes else None, 'exception':exception,'grouped':grouped, 'unsupported':bool(unsupported or remaining or len(set(statuses))>1 or len(set(nodes))>1)} def filters(intent): return {key:intent.get(key) for key in ('status','stage','exception')}