|
@@ -17,6 +17,13 @@ class OutputPresenter:
|
|
|
'query_customs_declaration_files',
|
|
'query_customs_declaration_files',
|
|
|
'query_outbound_list',
|
|
'query_outbound_list',
|
|
|
'query_customer_list',
|
|
'query_customer_list',
|
|
|
|
|
+ 'query_remote_address_list',
|
|
|
|
|
+ 'query_fuel_rate_list',
|
|
|
|
|
+ 'save_fuel_rate',
|
|
|
|
|
+ 'enable_fuel_rate',
|
|
|
|
|
+ ))
|
|
|
|
|
+ FUEL_RATE_TOOLS = frozenset((
|
|
|
|
|
+ 'query_fuel_rate_list', 'save_fuel_rate', 'enable_fuel_rate',
|
|
|
))
|
|
))
|
|
|
PAYMENT_FOLLOWUP_TOOLS = frozenset(('query_customer_payment_followup',))
|
|
PAYMENT_FOLLOWUP_TOOLS = frozenset(('query_customer_payment_followup',))
|
|
|
PAYMENT_DETAIL_TOOLS = frozenset((
|
|
PAYMENT_DETAIL_TOOLS = frozenset((
|
|
@@ -41,6 +48,8 @@ class OutputPresenter:
|
|
|
GOODS_TAX_TOOLS = frozenset(('trial_goods_tax',))
|
|
GOODS_TAX_TOOLS = frozenset(('trial_goods_tax',))
|
|
|
CONTAINER_TIMELINESS_TOOLS = frozenset(('query_container_timeliness_list',))
|
|
CONTAINER_TIMELINESS_TOOLS = frozenset(('query_container_timeliness_list',))
|
|
|
HEADHAUL_DOCUMENT_TOOLS = frozenset(('query_headhaul_document_list',))
|
|
HEADHAUL_DOCUMENT_TOOLS = frozenset(('query_headhaul_document_list',))
|
|
|
|
|
+ REMOTE_ADDRESS_MAINTAIN_TOOLS = frozenset(('maintain_remote_address',))
|
|
|
|
|
+ REMOTE_ADDRESS_SAVE_TOOLS = frozenset(('save_remote_address',))
|
|
|
HEADHAUL_PREPARE_TOOLS = frozenset(('prepare_headhaul_document_upload',))
|
|
HEADHAUL_PREPARE_TOOLS = frozenset(('prepare_headhaul_document_upload',))
|
|
|
HEADHAUL_SAVE_TOOLS = frozenset(('save_headhaul_document',))
|
|
HEADHAUL_SAVE_TOOLS = frozenset(('save_headhaul_document',))
|
|
|
HEADHAUL_DELETE_TOOLS = frozenset(('delete_headhaul_document',))
|
|
HEADHAUL_DELETE_TOOLS = frozenset(('delete_headhaul_document',))
|
|
@@ -80,6 +89,8 @@ class OutputPresenter:
|
|
|
| GOODS_TAX_TOOLS
|
|
| GOODS_TAX_TOOLS
|
|
|
| CONTAINER_TIMELINESS_TOOLS
|
|
| CONTAINER_TIMELINESS_TOOLS
|
|
|
| HEADHAUL_DOCUMENT_TOOLS
|
|
| HEADHAUL_DOCUMENT_TOOLS
|
|
|
|
|
+ | REMOTE_ADDRESS_MAINTAIN_TOOLS
|
|
|
|
|
+ | REMOTE_ADDRESS_SAVE_TOOLS
|
|
|
| HEADHAUL_PREPARE_TOOLS
|
|
| HEADHAUL_PREPARE_TOOLS
|
|
|
| HEADHAUL_SAVE_TOOLS
|
|
| HEADHAUL_SAVE_TOOLS
|
|
|
| HEADHAUL_DELETE_TOOLS
|
|
| HEADHAUL_DELETE_TOOLS
|
|
@@ -389,6 +400,44 @@ class OutputPresenter:
|
|
|
'merchandiser_name': ('客户经理',),
|
|
'merchandiser_name': ('客户经理',),
|
|
|
'department_name': ('事业部',),
|
|
'department_name': ('事业部',),
|
|
|
},
|
|
},
|
|
|
|
|
+ 'query_remote_address_list': {
|
|
|
|
|
+ 'address_no': ('偏远地址库编号',),
|
|
|
|
|
+ 'remote_name': ('偏远地址库名称',),
|
|
|
|
|
+ 'status_text': ('状态',),
|
|
|
|
|
+ 'create_time': ('添加时间',),
|
|
|
|
|
+ 'create_user': ('添加人',),
|
|
|
|
|
+ },
|
|
|
|
|
+ 'query_fuel_rate_list': {
|
|
|
|
|
+ 'fuel_no': ('燃油代码',),
|
|
|
|
|
+ 'price_type_name': ('燃油类型',),
|
|
|
|
|
+ 'setting_type_text': ('配置方式',),
|
|
|
|
|
+ 'fuel_ratio': ('燃油系数',),
|
|
|
|
|
+ 'start_date': ('开始生效时间',),
|
|
|
|
|
+ 'end_date': ('截止生效时间',),
|
|
|
|
|
+ 'conditions_text': ('条件',),
|
|
|
|
|
+ 'product_type_name': ('产品分类',),
|
|
|
|
|
+ 'channel_type_name': ('渠道分类',),
|
|
|
|
|
+ 'product_name': ('产品',),
|
|
|
|
|
+ 'channel_name': ('渠道',),
|
|
|
|
|
+ 'status_name': ('状态',),
|
|
|
|
|
+ 'source': ('来源',),
|
|
|
|
|
+ 'user_name': ('创建人',),
|
|
|
|
|
+ 'create_date': ('创建时间',),
|
|
|
|
|
+ },
|
|
|
|
|
+ 'save_fuel_rate': {
|
|
|
|
|
+ 'fuel_no': ('燃油代码',),
|
|
|
|
|
+ 'price_type_name': ('燃油类型',),
|
|
|
|
|
+ 'fuel_ratio': ('燃油系数',),
|
|
|
|
|
+ 'status_text': ('状态',),
|
|
|
|
|
+ 'source': ('来源',),
|
|
|
|
|
+ 'start_date': ('开始生效时间',),
|
|
|
|
|
+ 'end_date': ('截止生效时间',),
|
|
|
|
|
+ 'conditions_text': ('条件',),
|
|
|
|
|
+ },
|
|
|
|
|
+ 'enable_fuel_rate': {
|
|
|
|
|
+ 'fuel_no': ('燃油代码',),
|
|
|
|
|
+ 'status_text': ('状态',),
|
|
|
|
|
+ },
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
PAYMENT_FOLLOWUP_COLUMNS = {
|
|
PAYMENT_FOLLOWUP_COLUMNS = {
|
|
@@ -624,6 +673,20 @@ class OutputPresenter:
|
|
|
('operator_name', '操作人'),
|
|
('operator_name', '操作人'),
|
|
|
('operate_time', '操作时间'),
|
|
('operate_time', '操作时间'),
|
|
|
)
|
|
)
|
|
|
|
|
+ REMOTE_ADDRESS_DETAIL_COLUMNS = (
|
|
|
|
|
+ ('shipper_country', '发件人国家'),
|
|
|
|
|
+ ('shipper_province', '发件人州/省'),
|
|
|
|
|
+ ('shipper_city', '发件人城市'),
|
|
|
|
|
+ ('shipper_start_postcode', '发件人开始邮编'),
|
|
|
|
|
+ ('shipper_end_postcode', '发件人结束邮编'),
|
|
|
|
|
+ ('country', '收件人国家'),
|
|
|
|
|
+ ('province', '收件人州/省'),
|
|
|
|
|
+ ('city', '收件人城市'),
|
|
|
|
|
+ ('start_postcode', '收件人开始邮编'),
|
|
|
|
|
+ ('end_postcode', '收件人结束邮编'),
|
|
|
|
|
+ ('create_time', '添加时间'),
|
|
|
|
|
+ ('create_user', '添加人'),
|
|
|
|
|
+ )
|
|
|
CONTAINER_TIMELINESS_COLUMNS = (
|
|
CONTAINER_TIMELINESS_COLUMNS = (
|
|
|
('ship_company', '船公司'), ('bl_number', '提单号'),
|
|
('ship_company', '船公司'), ('bl_number', '提单号'),
|
|
|
('container_code', '柜号'), ('container_type', '柜型'),
|
|
('container_code', '柜号'), ('container_type', '柜型'),
|
|
@@ -762,6 +825,55 @@ class OutputPresenter:
|
|
|
'page': '页码',
|
|
'page': '页码',
|
|
|
'limit': '每页数量',
|
|
'limit': '每页数量',
|
|
|
},
|
|
},
|
|
|
|
|
+ 'query_remote_address_list': {
|
|
|
|
|
+ 'address_no': '偏远地址库编号',
|
|
|
|
|
+ 'remote_name': '偏远地址库名称',
|
|
|
|
|
+ 'status': '状态',
|
|
|
|
|
+ 'country': '国家',
|
|
|
|
|
+ 'province': '州/省',
|
|
|
|
|
+ 'city': '城市',
|
|
|
|
|
+ 'postcode': '邮编',
|
|
|
|
|
+ 'page': '页码',
|
|
|
|
|
+ 'limit': '每页数量',
|
|
|
|
|
+ },
|
|
|
|
|
+ 'maintain_remote_address': {
|
|
|
|
|
+ 'address_no': '偏远地址库编号',
|
|
|
|
|
+ 'page': '页码',
|
|
|
|
|
+ 'limit': '每页数量',
|
|
|
|
|
+ },
|
|
|
|
|
+ 'save_remote_address': {
|
|
|
|
|
+ 'address_no': '偏远地址库编号',
|
|
|
|
|
+ 'remote_name': '偏远地址库名称',
|
|
|
|
|
+ 'status': '状态',
|
|
|
|
|
+ 'details': '地址明细',
|
|
|
|
|
+ },
|
|
|
|
|
+ 'query_fuel_rate_list': {
|
|
|
|
|
+ 'fuel_no': '燃油代码',
|
|
|
|
|
+ 'product': '产品',
|
|
|
|
|
+ 'channel': '渠道',
|
|
|
|
|
+ 'product_type': '产品分类',
|
|
|
|
|
+ 'channel_type': '渠道分类',
|
|
|
|
|
+ 'price_type': '燃油类型',
|
|
|
|
|
+ 'status': '状态',
|
|
|
|
|
+ 'start_date': '生效时间',
|
|
|
|
|
+ 'page': '页码',
|
|
|
|
|
+ 'limit': '每页数量',
|
|
|
|
|
+ },
|
|
|
|
|
+ 'save_fuel_rate': {
|
|
|
|
|
+ 'price_type': '燃油类型',
|
|
|
|
|
+ 'start_date': '开始生效时间',
|
|
|
|
|
+ 'end_date': '结束生效时间',
|
|
|
|
|
+ 'items': '燃油系数',
|
|
|
|
|
+ 'fuel_ratio': '燃油费率',
|
|
|
|
|
+ 'conditions': '计费条件',
|
|
|
|
|
+ 'condition': '计费条件',
|
|
|
|
|
+ 'condition_value': '条件值',
|
|
|
|
|
+ 'condition_relation': '条件关系',
|
|
|
|
|
+ 'group': '条件组',
|
|
|
|
|
+ },
|
|
|
|
|
+ 'enable_fuel_rate': {
|
|
|
|
|
+ 'fuel_no': '燃油代码',
|
|
|
|
|
+ },
|
|
|
'query_customer_payment_followup': {
|
|
'query_customer_payment_followup': {
|
|
|
'customer_id': '客户名称',
|
|
'customer_id': '客户名称',
|
|
|
'department_id': '事业部',
|
|
'department_id': '事业部',
|
|
@@ -1027,6 +1139,12 @@ class OutputPresenter:
|
|
|
return self._present_inbound_receipt_templates(data, meta)
|
|
return self._present_inbound_receipt_templates(data, meta)
|
|
|
if tool_name in self.FREIGHTOWER_TRACK_TOOLS:
|
|
if tool_name in self.FREIGHTOWER_TRACK_TOOLS:
|
|
|
return self._present_freightower_track(data, meta)
|
|
return self._present_freightower_track(data, meta)
|
|
|
|
|
+ if tool_name in self.REMOTE_ADDRESS_MAINTAIN_TOOLS:
|
|
|
|
|
+ return self._present_remote_address_maintain(
|
|
|
|
|
+ data, tool_result.get('meta'), meta
|
|
|
|
|
+ )
|
|
|
|
|
+ if tool_name in self.REMOTE_ADDRESS_SAVE_TOOLS:
|
|
|
|
|
+ return self._present_remote_address_save(data, meta)
|
|
|
if tool_name in self.TABLE_TOOLS:
|
|
if tool_name in self.TABLE_TOOLS:
|
|
|
return self._present_table(
|
|
return self._present_table(
|
|
|
tool_name,
|
|
tool_name,
|
|
@@ -1382,6 +1500,133 @@ class OutputPresenter:
|
|
|
meta,
|
|
meta,
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+ def _present_remote_address_maintain(self, data, raw_meta, meta):
|
|
|
|
|
+ required = {
|
|
|
|
|
+ 'summary', 'mode_text', 'address_no', 'remote_name',
|
|
|
|
|
+ 'status_text', 'temp_key', 'columns', 'records',
|
|
|
|
|
+ }
|
|
|
|
|
+ if not isinstance(data, dict) or not required.issubset(set(data)):
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ if set(data) - required - {'tips'}:
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ if data.get('mode_text') not in ('新增', '编辑'):
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ for key in ('summary', 'address_no', 'remote_name', 'status_text', 'temp_key'):
|
|
|
|
|
+ if not isinstance(data.get(key), str):
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ columns = data.get('columns')
|
|
|
|
|
+ records = data.get('records')
|
|
|
|
|
+ expected = list(self.REMOTE_ADDRESS_DETAIL_COLUMNS)
|
|
|
|
|
+ if not isinstance(columns, list) or len(columns) != len(expected):
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ if not isinstance(records, list):
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ for index, column in enumerate(columns):
|
|
|
|
|
+ key, label = expected[index]
|
|
|
|
|
+ if (
|
|
|
|
|
+ not isinstance(column, dict)
|
|
|
|
|
+ or column.get('key') != key
|
|
|
|
|
+ or column.get('name') != label
|
|
|
|
|
+ ):
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ keys = [item[0] for item in expected]
|
|
|
|
|
+ rows = []
|
|
|
|
|
+ for record in records:
|
|
|
|
|
+ if not isinstance(record, dict) or set(record) != set(keys):
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ rows.append(['' if record.get(key) is None else record.get(key) for key in keys])
|
|
|
|
|
+ headers = [{'label': label} for _, label in expected]
|
|
|
|
|
+ table = {
|
|
|
|
|
+ 'summary': self._safe_text(data.get('summary')),
|
|
|
|
|
+ 'headers': headers,
|
|
|
|
|
+ 'rows': rows,
|
|
|
|
|
+ }
|
|
|
|
|
+ tips = self._safe_tips(data.get('tips'))
|
|
|
|
|
+ if tips:
|
|
|
|
|
+ table['tips'] = tips
|
|
|
|
|
+ content = {
|
|
|
|
|
+ 'summary': table['summary'],
|
|
|
|
|
+ 'mode_text': data['mode_text'],
|
|
|
|
|
+ 'address_no': data['address_no'],
|
|
|
|
|
+ 'remote_name': data['remote_name'],
|
|
|
|
|
+ 'status_text': data['status_text'],
|
|
|
|
|
+ 'headers': headers,
|
|
|
|
|
+ 'rows': rows,
|
|
|
|
|
+ }
|
|
|
|
|
+ if tips:
|
|
|
|
|
+ content['tips'] = tips
|
|
|
|
|
+ pagination = self._build_pagination(raw_meta)
|
|
|
|
|
+ if pagination:
|
|
|
|
|
+ content['pagination'] = pagination
|
|
|
|
|
+ return self._success_result(content, self._render_table(table), meta)
|
|
|
|
|
+
|
|
|
|
|
+ def _present_remote_address_save(self, data, meta):
|
|
|
|
|
+ required = {'summary', 'mode_text', 'address_no', 'remote_name', 'status_text'}
|
|
|
|
|
+ if not isinstance(data, dict) or set(data) != required:
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ if data.get('mode_text') not in ('新增', '编辑'):
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ if data.get('status_text') not in ('启用', '禁用'):
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ address_no = data.get('address_no')
|
|
|
|
|
+ remote_name = data.get('remote_name')
|
|
|
|
|
+ summary = data.get('summary')
|
|
|
|
|
+ if (
|
|
|
|
|
+ not isinstance(address_no, str)
|
|
|
|
|
+ or not address_no.startswith('PY')
|
|
|
|
|
+ or not address_no[2:].isdigit()
|
|
|
|
|
+ or not isinstance(remote_name, str)
|
|
|
|
|
+ or not remote_name.strip()
|
|
|
|
|
+ or not isinstance(summary, str)
|
|
|
|
|
+ or not summary.strip()
|
|
|
|
|
+ ):
|
|
|
|
|
+ return self._format_error(meta)
|
|
|
|
|
+ content = {
|
|
|
|
|
+ '结果': summary.strip(),
|
|
|
|
|
+ '操作': data['mode_text'],
|
|
|
|
|
+ '偏远地址库编号': address_no,
|
|
|
|
|
+ '偏远地址库名称': remote_name.strip(),
|
|
|
|
|
+ '状态': data['status_text'],
|
|
|
|
|
+ }
|
|
|
|
|
+ return self._success_result(content, summary.strip(), meta)
|
|
|
|
|
+
|
|
|
|
|
+ @staticmethod
|
|
|
|
|
+ def _remote_address_save_message(message):
|
|
|
|
|
+ if message in (
|
|
|
|
|
+ '偏远地址库名称不能为空',
|
|
|
|
|
+ '偏远地址库名称过长',
|
|
|
|
|
+ '状态只能是启用或禁用',
|
|
|
|
|
+ '偏远地址库编号不正确',
|
|
|
|
|
+ '地址明细格式不正确',
|
|
|
|
|
+ '偏远地址库没有详情,请导入',
|
|
|
|
|
+ '编辑只修改名称和状态,不能同时提交地址明细',
|
|
|
|
|
+ ):
|
|
|
|
|
+ return True
|
|
|
|
|
+ if message.startswith('一次最多保存') and message.endswith('条地址明细'):
|
|
|
|
|
+ return True
|
|
|
|
|
+ if (
|
|
|
|
|
+ message.startswith('第')
|
|
|
|
|
+ and '条' in message
|
|
|
|
|
+ and len(message) <= 80
|
|
|
|
|
+ ):
|
|
|
|
|
+ return True
|
|
|
|
|
+ return False
|
|
|
|
|
+
|
|
|
|
|
+ @staticmethod
|
|
|
|
|
+ def _fuel_rate_message(message):
|
|
|
|
|
+ if not message or len(message) > 400:
|
|
|
|
|
+ return False
|
|
|
|
|
+ lowered = message.lower()
|
|
|
|
|
+ if 'sql' in lowered or 'exception' in lowered or '\\' in message:
|
|
|
|
|
+ return False
|
|
|
|
|
+ markers = (
|
|
|
|
|
+ '不正确', '不存在', '不能为空', '只能', '请添加', '请完善',
|
|
|
|
|
+ '对应多条', '不能大于', '不能同时', '重复', '过多', '未启用',
|
|
|
|
|
+ '草稿', '失败', '只适用于', '日期', '只新增', '最多新增', '不能修改', '不支持',
|
|
|
|
|
+ '已启用', '最多启用', '请选择',
|
|
|
|
|
+ )
|
|
|
|
|
+ return any(marker in message for marker in markers)
|
|
|
|
|
+
|
|
|
def _present_customer_payment_followup(self, data, raw_meta, meta):
|
|
def _present_customer_payment_followup(self, data, raw_meta, meta):
|
|
|
if set(data) != {'columns', 'records'}:
|
|
if set(data) != {'columns', 'records'}:
|
|
|
return self._format_error(meta)
|
|
return self._format_error(meta)
|
|
@@ -2588,6 +2833,14 @@ class OutputPresenter:
|
|
|
if not self._arrange_trailer_message(message):
|
|
if not self._arrange_trailer_message(message):
|
|
|
message = self._parameter_message('')
|
|
message = self._parameter_message('')
|
|
|
return self._error_result(code, message, False, meta)
|
|
return self._error_result(code, message, False, meta)
|
|
|
|
|
+ elif code == 'MCP_1401' and tool_name in self.REMOTE_ADDRESS_SAVE_TOOLS:
|
|
|
|
|
+ if not self._remote_address_save_message(message):
|
|
|
|
|
+ message = self._parameter_message('')
|
|
|
|
|
+ return self._error_result(code, message, False, meta)
|
|
|
|
|
+ elif code == 'MCP_1401' and tool_name in self.FUEL_RATE_TOOLS:
|
|
|
|
|
+ if not self._fuel_rate_message(message):
|
|
|
|
|
+ message = self._parameter_message('')
|
|
|
|
|
+ return self._error_result(code, message, False, meta)
|
|
|
elif code == 'MCP_1401':
|
|
elif code == 'MCP_1401':
|
|
|
label = self._find_field_label(tool_name, raw_message)
|
|
label = self._find_field_label(tool_name, raw_message)
|
|
|
message = self._parameter_message(label)
|
|
message = self._parameter_message(label)
|
|
@@ -2614,6 +2867,10 @@ class OutputPresenter:
|
|
|
message = self.ERROR_MESSAGES.get(code, self.ERROR_MESSAGES['MCP_9001'])
|
|
message = self.ERROR_MESSAGES.get(code, self.ERROR_MESSAGES['MCP_9001'])
|
|
|
else:
|
|
else:
|
|
|
message = allowed
|
|
message = allowed
|
|
|
|
|
+ elif tool_name in self.REMOTE_ADDRESS_MAINTAIN_TOOLS and message == '偏远地址库不存在':
|
|
|
|
|
+ message = '偏远地址库不存在'
|
|
|
|
|
+ elif tool_name in self.REMOTE_ADDRESS_SAVE_TOOLS and message == '偏远地址库不存在':
|
|
|
|
|
+ message = '偏远地址库不存在'
|
|
|
else:
|
|
else:
|
|
|
message = self.ERROR_MESSAGES[code]
|
|
message = self.ERROR_MESSAGES[code]
|
|
|
retryable = code not in self.NON_RETRYABLE_CODES
|
|
retryable = code not in self.NON_RETRYABLE_CODES
|