70 lines
4.2 KiB
Python
70 lines
4.2 KiB
Python
"""Bounded conversational pagination over the server-validated customer scope."""
|
||
|
||
import re
|
||
import sqlite3
|
||
|
||
from .db import connect
|
||
|
||
|
||
def page_command(message):
|
||
text=re.sub(r'[\s,,。.!!??]','',message)
|
||
match=re.fullmatch(r'(?:请)?(?:订单)?第(\d{1,5})页',text)
|
||
if match:return int(match.group(1))
|
||
if re.fullmatch(r'(?:请|继续)?(?:下一页|下页|继续显示|接着显示(?:剩下的)?订单)',text):return 'next'
|
||
if re.fullmatch(r'(?:请)?(?:上一页|上页)',text):return 'previous'
|
||
return None
|
||
|
||
|
||
def answer_list(message,tenants,conv_id=None):
|
||
from .order_data import is_lookup_help,parse_count_query,tenant_filter,STATUS_LABELS
|
||
from .customer_service import order_login_response
|
||
|
||
command=page_command(message)
|
||
initial=(not is_lookup_help(message) and re.search(r'订单|运单|\borders?\b|\bshipments?\b',message,re.I)
|
||
and re.search(r'列出|列表|全部|所有|\blist\b',message,re.I))
|
||
if command is None and not initial:return None
|
||
if not tenants:return order_login_response()
|
||
page=1;status=None
|
||
if command is None:
|
||
intent=parse_count_query(re.sub(r'列出|列表|全部|所有|\blist\b','多少',message,flags=re.I))
|
||
if intent is None or intent['unsupported']:
|
||
return {'t':'暂不支持按这个条件列出订单。可查看全部订单或按履约中、已完成等业务状态查询。'}
|
||
status=intent['status']
|
||
scope=tenant_filter(tenant_ids=tenants)
|
||
if scope is None:return order_login_response()
|
||
connection=None
|
||
try:
|
||
connection=connect()
|
||
if command is not None:
|
||
if not conv_id:return {'t':'请先在当前对话中发送“列出我的订单”,再翻页查看。'}
|
||
prior=connection.execute("SELECT content FROM messages WHERE conv_id=? AND role='assistant' ORDER BY id DESC LIMIT 1",(conv_id,)).fetchone()
|
||
header=prior[0].split('\n',1)[0] if prior else ''
|
||
match=re.fullmatch(r'您当前的订单列表(.*第(\d+)页;业务状态:([^)]+)):',header)
|
||
if not match:return {'t':'请先在当前对话中发送“列出我的订单”,再翻页查看。'}
|
||
labels={label:code for code,label in STATUS_LABELS.items()}
|
||
status=labels.get(match[2])
|
||
if match[2]!='全部' and status is None:return {'t':'请重新指定需要查看的订单状态。'}
|
||
page=int(command) if isinstance(command,int) else max(1,int(match[1])+(1 if command=='next' else -1))
|
||
if not 1<=page<=10000:return {'t':'请提供1至10000之间的有效页码。'}
|
||
where=' WHERE 1=1'+scope[0];values=scope[1]
|
||
if status:where+=' AND status=?';values=values+[status]
|
||
# Both reads see one current snapshot and apply exactly the same scope/filter.
|
||
connection.execute('BEGIN')
|
||
total=connection.execute('SELECT COUNT(*) FROM order_test_data'+where,values).fetchone()[0]
|
||
page=min(page,max(1,(total+19)//20))
|
||
rows=connection.execute('SELECT order_no,inbound_code,status,warehouse_code FROM order_test_data'+where+
|
||
' ORDER BY id DESC LIMIT 20 OFFSET ?',values+[(page-1)*20]).fetchall()
|
||
if not rows:return {'t':'当前账号下没有符合条件的订单。','_customer_data':True}
|
||
label=STATUS_LABELS[status] if status else '全部'
|
||
first='先列出20票;' if page==1 and total>20 else ''
|
||
lines=[f'您当前的订单列表({first}第{page}页;业务状态:{label}):',f'共{total}票,当前显示第{(page-1)*20+1}至{(page-1)*20+len(rows)}票。']
|
||
for number,inbound,business_status,warehouse in rows:
|
||
lines.append(f'- 入仓码:{inbound or "未登记"};订单号:{number};业务状态:{STATUS_LABELS.get(business_status,business_status)};目的仓:{warehouse or "未登记"}')
|
||
lines.append('回复“下一页”查看后续订单。' if page*20<total else '当前已是最后一页。')
|
||
lines.append('发送入仓码可查询该票订单和物流轨迹。')
|
||
return {'t':'\n'.join(lines),'_customer_data':True}
|
||
except sqlite3.Error:
|
||
return {'t':'订单信息暂时无法读取,请稍后重试。'}
|
||
finally:
|
||
if connection is not None:connection.close()
|