|
|
@@ -39,6 +39,7 @@ class OutputPresenter:
|
|
|
GOODS_INFO_TOOLS = frozenset(('query_goods_info',))
|
|
|
GOODS_TAX_TOOLS = frozenset(('trial_goods_tax',))
|
|
|
CONTAINER_TIMELINESS_TOOLS = frozenset(('query_container_timeliness_list',))
|
|
|
+ INBOUND_RECEIPT_TOOLS = frozenset(('list_inbound_receipt_templates',))
|
|
|
FREIGHTOWER_TRACK_TOOLS = frozenset(('query_freightower_track',))
|
|
|
DETAIL_TOOLS = frozenset(('query_outbound_detail',))
|
|
|
ORDER_DETAIL_TOOLS = frozenset(('query_order_detail',))
|
|
|
@@ -57,6 +58,7 @@ class OutputPresenter:
|
|
|
'export_receivable_cost_list',
|
|
|
'export_pallet_data',
|
|
|
'export_container_timeliness_report',
|
|
|
+ 'export_inbound_receipt',
|
|
|
))
|
|
|
TASK_TOOLS = frozenset(('query_export_task',))
|
|
|
SAFE_TOOLS = (
|
|
|
@@ -70,6 +72,7 @@ class OutputPresenter:
|
|
|
| GOODS_INFO_TOOLS
|
|
|
| GOODS_TAX_TOOLS
|
|
|
| CONTAINER_TIMELINESS_TOOLS
|
|
|
+ | INBOUND_RECEIPT_TOOLS
|
|
|
| FREIGHTOWER_TRACK_TOOLS
|
|
|
| OPTION_TOOLS | EXPORT_TOOLS | TASK_TOOLS
|
|
|
)
|
|
|
@@ -953,6 +956,8 @@ class OutputPresenter:
|
|
|
return self._present_container_timeliness_list(
|
|
|
data, tool_result.get('meta'), meta
|
|
|
)
|
|
|
+ if tool_name in self.INBOUND_RECEIPT_TOOLS:
|
|
|
+ return self._present_inbound_receipt_templates(data, meta)
|
|
|
if tool_name in self.FREIGHTOWER_TRACK_TOOLS:
|
|
|
return self._present_freightower_track(data, meta)
|
|
|
if tool_name in self.TABLE_TOOLS:
|
|
|
@@ -2224,6 +2229,38 @@ class OutputPresenter:
|
|
|
content['pagination'] = pagination
|
|
|
return self._success_result(content, self._render_table(content), meta)
|
|
|
|
|
|
+ def _present_inbound_receipt_templates(self, data, meta):
|
|
|
+ if set(data) != {'receipt_kind', 'templates'}:
|
|
|
+ return self._format_error(meta)
|
|
|
+ kind = data.get('receipt_kind')
|
|
|
+ templates = data.get('templates')
|
|
|
+ if kind not in ('直送入仓单', '非直送入仓单') or not isinstance(templates, list):
|
|
|
+ return self._format_error(meta)
|
|
|
+ if not templates:
|
|
|
+ return self._format_error(meta)
|
|
|
+ rows = []
|
|
|
+ for item in templates:
|
|
|
+ if not isinstance(item, dict) or set(item) != {'name', 'template_code'}:
|
|
|
+ return self._format_error(meta)
|
|
|
+ name = item.get('name')
|
|
|
+ code = item.get('template_code')
|
|
|
+ if (
|
|
|
+ not isinstance(name, str) or not name.strip()
|
|
|
+ or not isinstance(code, str) or not code.strip()
|
|
|
+ ):
|
|
|
+ return self._format_error(meta)
|
|
|
+ rows.append([name.strip(), code.strip()])
|
|
|
+ content = {
|
|
|
+ 'receipt_kind': kind,
|
|
|
+ 'summary': kind,
|
|
|
+ 'headers': [
|
|
|
+ {'label': '模板名称'},
|
|
|
+ {'label': '模板编码'},
|
|
|
+ ],
|
|
|
+ 'rows': rows,
|
|
|
+ }
|
|
|
+ return self._success_result(content, self._render_table(content), meta)
|
|
|
+
|
|
|
def _present_export_submission(self, data, meta):
|
|
|
expected = {'task_ref', 'status', 'retry_after_seconds'}
|
|
|
if set(data) != expected:
|
|
|
@@ -2359,6 +2396,16 @@ class OutputPresenter:
|
|
|
if code == 'MCP_1401':
|
|
|
label = self._find_field_label(tool_name, raw_message)
|
|
|
message = self._parameter_message(label)
|
|
|
+ elif tool_name in self.INBOUND_RECEIPT_TOOLS | self.EXPORT_TOOLS and (
|
|
|
+ tool_name in (
|
|
|
+ 'list_inbound_receipt_templates',
|
|
|
+ 'export_inbound_receipt',
|
|
|
+ )
|
|
|
+ ):
|
|
|
+ allowed = self._inbound_receipt_message(message)
|
|
|
+ message = allowed or self.ERROR_MESSAGES.get(
|
|
|
+ code, self.ERROR_MESSAGES['MCP_9001']
|
|
|
+ )
|
|
|
elif tool_name in self.FREIGHTOWER_TRACK_TOOLS:
|
|
|
allowed = str(raw_message or '').strip()
|
|
|
if allowed not in (
|
|
|
@@ -2389,6 +2436,45 @@ class OutputPresenter:
|
|
|
def _parameter_message(label):
|
|
|
return '{0}参数不正确'.format(label) if label else '工具参数不正确,请检查后重试'
|
|
|
|
|
|
+ @classmethod
|
|
|
+ def _inbound_receipt_message(cls, message):
|
|
|
+ text = str(message or '').strip()
|
|
|
+ if text in (
|
|
|
+ '当前没有可用的入仓单模板',
|
|
|
+ '所选模板不属于这次柜号对应的入仓单',
|
|
|
+ ):
|
|
|
+ return text
|
|
|
+ missing_prefix = '这些柜号没有对应的排舱单:'
|
|
|
+ if text.startswith(missing_prefix) and cls._container_code_list(
|
|
|
+ text[len(missing_prefix):]
|
|
|
+ ):
|
|
|
+ return text
|
|
|
+ direct_prefix = '这些柜号是直送柜:'
|
|
|
+ indirect_mark = '。这些柜号是非直送柜:'
|
|
|
+ if text.startswith(direct_prefix) and text.endswith('。') and indirect_mark in text:
|
|
|
+ body = text[len(direct_prefix):-1]
|
|
|
+ direct, indirect = body.split(indirect_mark, 1)
|
|
|
+ if cls._container_code_list(direct) and cls._container_code_list(indirect):
|
|
|
+ return text
|
|
|
+ return ''
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def _container_code_list(text):
|
|
|
+ if not text or len(text) > 200 * 101:
|
|
|
+ return False
|
|
|
+ parts = text.split('、')
|
|
|
+ if not parts:
|
|
|
+ return False
|
|
|
+ for part in parts:
|
|
|
+ if (
|
|
|
+ not part
|
|
|
+ or part != part.strip()
|
|
|
+ or len(part) > 100
|
|
|
+ or any(ord(char) < 32 for char in part)
|
|
|
+ ):
|
|
|
+ return False
|
|
|
+ return True
|
|
|
+
|
|
|
@staticmethod
|
|
|
def _build_meta(raw_meta):
|
|
|
if not isinstance(raw_meta, dict):
|