86 lines
4.5 KiB
Python
86 lines
4.5 KiB
Python
"""Discard explicitly rejected quote conditions before parsing their replacements."""
|
||
|
||
import re
|
||
|
||
|
||
SERVICE_TERMS = ('美森正班','美森加班','美森','EXX','合德','普船','海派','海卡','海铁')
|
||
CHANGE_VERBS = r'增加|追加|加上|加|减少|减掉|减去|减|去掉'
|
||
ADJUSTMENT_QUESTION = '请提供调整后的总重和箱数,或逐箱重量明细,我再继续核算。'
|
||
VOLUME_QUESTION = '请确认调整后的总体积,或提供更新后的逐箱尺寸,我再核算体积重。'
|
||
|
||
|
||
def condition_edits(text):
|
||
rejected = r'(?:不是|不要|并非|不从|不走|别走|不用|不选|别选)\s*(?:(?:发|寄|运|送)(?:到|往)?|去|到|走|选|用|按)?\s*'
|
||
service = r'(?:(?:洛杉矶|纽约|芝加哥|休斯顿|萨凡纳)?(?:美森正班|美森加班|美森|EXX|合德|普船)(?:海派|海卡|海铁|全卡)?|海派|海卡|海铁)'
|
||
value = (service+r'|不包税|包税|最快|最慢|最便宜|'
|
||
r'(?:[A-Za-z]{2,4}[0-9][A-Za-z0-9]{0,2})(?![A-Za-z0-9])|'
|
||
r'深圳|华南|东莞|义乌|华东|美西|美中|美东|美国|洛杉矶|纽约|铁制品|钢制品|铝制品|铁铝制品|金属制品')
|
||
excluded = []
|
||
taxes = set()
|
||
clear_choice = False
|
||
|
||
def discard(match):
|
||
nonlocal clear_choice
|
||
if re.match(r'\s*(?:的)?(?:吗|嘛|么|[??])', text[match.end():]):
|
||
return match[0]
|
||
condition = match['value']
|
||
term = next((name for name in SERVICE_TERMS if name.lower() in condition.lower()), None)
|
||
if term:
|
||
excluded.append(term)
|
||
if condition in ('包税','不包税'):
|
||
taxes.add(condition)
|
||
if condition in ('最快','最慢','最便宜'):
|
||
clear_choice = True
|
||
return ' '
|
||
|
||
cleaned = re.sub(rejected+'(?P<value>'+value+')', discard, text, flags=re.I)
|
||
tax = 'included' if taxes == {'不包税'} else 'excluded' if taxes == {'包税'} else None
|
||
return {'text':cleaned, 'excluded_services':list(dict.fromkeys(excluded)) or None,
|
||
'tax':tax, 'tax_pending':len(taxes)>1, 'clear_choice':clear_choice}
|
||
|
||
|
||
def clean_conditions(text):
|
||
return condition_edits(text)['text']
|
||
|
||
|
||
def quantity_adjustment(text):
|
||
"""Separate a relative increment from an explicitly supplied new total."""
|
||
from .quote_intent import WEIGHT,kg,normalize
|
||
|
||
text=normalize(text)
|
||
prefix = re.match(r'^(?:(?:那(?:么)?|我(?:们)?(?:想|要)?|这次|现在|请帮我|帮我|麻烦|请|总重|重量|箱数|总体积|体积)[,,\s]*)*'
|
||
r'(?:再)?('+CHANGE_VERBS+r')\s*', text)
|
||
if not prefix:
|
||
unmatched=re.search(r'(?:'+CHANGE_VERBS+r')\s*-?\d+(?:\.\d+)?\s*(KG|公斤|千克|吨|箱|件|CBM|立方米|立方|方)',text,re.I)
|
||
if unmatched:
|
||
kind='volume' if unmatched[1].lower() in ('cbm','立方米','立方','方') else 'unknown'
|
||
return {'kind':kind,'delta':None,'text':text,'uncertain':True}
|
||
return None
|
||
subtract = prefix[1] in ('减少','减掉','减去','减','去掉')
|
||
sign = -1 if subtract else 1
|
||
weight = WEIGHT.match(text, prefix.end())
|
||
boxes = re.match(r'(\d+)\s*(?:个)?(?:箱|件)', text[prefix.end():])
|
||
volume = re.match(r'(-?\d+(?:\.\d+)?)\s*(?:CBM|立方米|立方|方)',text[prefix.end():],re.I)
|
||
if weight:
|
||
remainder = text[weight.end():]
|
||
return {'kind':'weight', 'delta':str(sign*kg(*weight.groups())),
|
||
'text':remainder, 'uncertain':kg(*weight.groups())<=0 or bool(re.search(CHANGE_VERBS+r'\s*\d',remainder))}
|
||
if boxes:
|
||
total_weight=re.search(r'(?:新总重|总重量|总重|合计重量|一共重)\s*'+WEIGHT.pattern.replace(r'(?<![\d.])',''),text,re.I)
|
||
total_boxes=re.search(r'(?:一共|总共|合计|总计|共)\s*(\d+)\s*(?:箱|件)|总箱数\s*(?:是|为)?\s*(\d+)',text)
|
||
return {'kind':'boxes', 'delta':sign*int(boxes[1]), 'text':text, 'uncertain':int(boxes[1])<=0,
|
||
'declared_weight':str(kg(*total_weight.groups())) if total_weight else None,
|
||
'declared_boxes':int(total_boxes[1] or total_boxes[2]) if total_boxes else None}
|
||
if volume:
|
||
from decimal import Decimal
|
||
amount=Decimal(volume[1])
|
||
return {'kind':'volume','delta':str(sign*amount),'text':text[prefix.end()+volume.end():],
|
||
'uncertain':amount<=0}
|
||
if re.match(r'-?\d', text[prefix.end():]):
|
||
return {'kind':'unknown', 'delta':None, 'text':text, 'uncertain':True}
|
||
return None
|
||
|
||
|
||
def weight_comparison(text):
|
||
return bool(re.search(r'会不会按|是不是按|是否按|向上进位|小数公斤|计费.*(?:进位|取整)|公斤.*(?:进位|取整)',text))
|