提交 1af63629 authored 作者: 贺阳's avatar 贺阳

1、增加根据语言查询包裹异常原因的接口

2、查看提单的接口增加查看大包的服务商,服务商对应的胶带色值,以及大包的托盘号/托盘使用时间,托盘号去重,取最早的使用日期,小包信息 3、尾程服务商的尾程服务商匹配值,多个值以换行做区分,需做判重。【服务商匹配值,不能重复配置,需做判重】
上级 561a8a63
...@@ -6,8 +6,8 @@ msgid "" ...@@ -6,8 +6,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 16.0\n" "Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-06 06:23+0000\n" "POT-Creation-Date: 2025-02-07 07:52+0000\n"
"PO-Revision-Date: 2025-02-06 14:27+0800\n" "PO-Revision-Date: 2025-02-07 15:53+0800\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"Language: zh_CN\n" "Language: zh_CN\n"
...@@ -1545,11 +1545,6 @@ msgstr "最后更新人" ...@@ -1545,11 +1545,6 @@ msgstr "最后更新人"
msgid "Last Updated on" msgid "Last Updated on"
msgstr "最后更新时间" msgstr "最后更新时间"
#. module: ccs_base
#: model_terms:ir.ui.view,arch_db:ccs_base.search_cc_ship_package_view
msgid "Last month ship package"
msgstr "上月小包"
#. module: ccs_base #. module: ccs_base
#: model_terms:ir.ui.view,arch_db:ccs_base.search_cc_ship_package_view #: model_terms:ir.ui.view,arch_db:ccs_base.search_cc_ship_package_view
msgid "Last week ship package" msgid "Last week ship package"
...@@ -1608,6 +1603,13 @@ msgstr "主数据" ...@@ -1608,6 +1603,13 @@ msgstr "主数据"
msgid "Matching Value" msgid "Matching Value"
msgstr "尾程服务商匹配值" msgstr "尾程服务商匹配值"
#. module: ccs_base
#. odoo-python
#: code:addons/ccs_base/models/cc_last_mile_provider.py:0
#, python-format
msgid "Matching values must be unique!"
msgstr "尾程服务商匹配值必须是唯一的!"
#. module: ccs_base #. module: ccs_base
#: model:ir.model.fields,field_description:ccs_base.field_cc_big_package__message_has_error #: model:ir.model.fields,field_description:ccs_base.field_cc_big_package__message_has_error
#: model:ir.model.fields,field_description:ccs_base.field_cc_bl__message_has_error #: model:ir.model.fields,field_description:ccs_base.field_cc_bl__message_has_error
...@@ -1634,6 +1636,11 @@ msgstr "可输入多个,每行输入一个大包号" ...@@ -1634,6 +1636,11 @@ msgstr "可输入多个,每行输入一个大包号"
msgid "Multiple entries can be made, one email per line" msgid "Multiple entries can be made, one email per line"
msgstr "可输入多个,每行输入一个邮箱" msgstr "可输入多个,每行输入一个邮箱"
#. module: ccs_base
#: model_terms:ir.ui.view,arch_db:ccs_base.view_last_mile_provider_form
msgid "Multiple entries can be made, one matching value per line"
msgstr "可输入多个,每行输入一个匹配值"
#. module: ccs_base #. module: ccs_base
#: model:ir.model.fields,field_description:ccs_base.field_cc_big_package__my_activity_date_deadline #: model:ir.model.fields,field_description:ccs_base.field_cc_big_package__my_activity_date_deadline
#: model:ir.model.fields,field_description:ccs_base.field_cc_bl__my_activity_date_deadline #: model:ir.model.fields,field_description:ccs_base.field_cc_bl__my_activity_date_deadline
...@@ -2599,11 +2606,6 @@ msgstr "托盘号只能输入数字!" ...@@ -2599,11 +2606,6 @@ msgstr "托盘号只能输入数字!"
msgid "The usage date cannot be later than the current date!" msgid "The usage date cannot be later than the current date!"
msgstr "使用日期不能大于当前日期!" msgstr "使用日期不能大于当前日期!"
#. module: ccs_base
#: model_terms:ir.ui.view,arch_db:ccs_base.search_cc_ship_package_view
msgid "This month ship package"
msgstr "本月小包"
#. module: ccs_base #. module: ccs_base
#: model_terms:ir.ui.view,arch_db:ccs_base.search_cc_ship_package_view #: model_terms:ir.ui.view,arch_db:ccs_base.search_cc_ship_package_view
msgid "This week ship package" msgid "This week ship package"
......
...@@ -20,3 +20,15 @@ class CCExceptionInfo(models.Model): ...@@ -20,3 +20,15 @@ class CCExceptionInfo(models.Model):
# 异常编码增加唯一约束 # 异常编码增加唯一约束
_sql_constraints = [('exception_code_uniq', 'unique(exception_code)', 'The Exception Code must be unique.')] _sql_constraints = [('exception_code_uniq', 'unique(exception_code)', 'The Exception Code must be unique.')]
def search_exception_info(self, pda_lang=False):
"""
查询包裹异常原因
:return:
"""
return {
'exception_code': self.exception_code or '',
'reason': self.reason or '',
'responsible_email': self.responsible_email or '',
'id': self.id
}
from odoo import models, fields from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
class CCLastMileProvider(models.Model): class CCLastMileProvider(models.Model):
_name = 'cc.last.mile.provider' _name = 'cc.last.mile.provider'
_description = 'Last Mile Provider' _description = 'Last Mile Provider'
@api.constrains('matching_value')
def _check_matching_value(self):
for record in self:
if record.matching_value:
values = record.matching_value.split('\n')
existing_values = '\n'.join(self.search([('id', '!=', record.id)]).mapped('matching_value')).split('\n')
if len(values) != len(set(values)) or any(value in existing_values for value in values):
raise ValidationError(_("Matching values must be unique!"))
name = fields.Char(string='Courier Name', required=True) # 快递名称 name = fields.Char(string='Courier Name', required=True) # 快递名称
abbreviation = fields.Char(string='Abbreviation', required=True) # 简称 abbreviation = fields.Char(string='Abbreviation', required=True) # 简称
tape_color_value = fields.Char(string='Tape Color Value') # 胶带色值 tape_color_value = fields.Char(string='Tape Color Value') # 胶带色值
active = fields.Boolean('Active', default=True) # 有效☑️ active = fields.Boolean('Active', default=True) # 有效☑️
matching_value = fields.Float(string='Matching Value') # 尾程服务商匹配值 matching_value = fields.Text(string='Matching Value') # 尾程服务商匹配值
def match_provider(self, provider_name):
"""Check if the provider name exists in matching values and return the record."""
# 查询所有匹配的记录
matching_records = self.search([])
# 检查是否有记录的 matching_value 包含 provider_name
for record in matching_records:
if provider_name in record.matching_value.split('\n'):
return record # 返回找到的记录
return False # 如果没有找到,返回 None
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<field name="name"/> <!-- 快递名称 --> <field name="name"/> <!-- 快递名称 -->
<field name="abbreviation"/> <!-- 简称 --> <field name="abbreviation"/> <!-- 简称 -->
<field name="tape_color_value" required="1"/> <!-- 胶带色值 --> <field name="tape_color_value" required="1"/> <!-- 胶带色值 -->
<field name="matching_value"/> <!-- 尾程服务商匹配值 --> <field name="matching_value" placeholder="Multiple entries can be made, one matching value per line"/> <!-- 尾程服务商匹配值 -->
</group> </group>
<group> <group>
<field name="active"/> <!-- 有效☑️ --> <field name="active"/> <!-- 有效☑️ -->
......
...@@ -61,17 +61,25 @@ class AssociatePalletWizard(models.TransientModel): ...@@ -61,17 +61,25 @@ class AssociatePalletWizard(models.TransientModel):
for package in success_package: for package in success_package:
# 回写大包的托盘号和使用日期 # 回写大包的托盘号和使用日期
old_pallet_number = package.pallet_number old_pallet_number = package.pallet_number
new_pallet_number = record.pallet_number # 修改的托盘号
old_usage_date = package.pallet_usage_date old_usage_date = package.pallet_usage_date
package.update_pallet_info(record.pallet_number, record.usage_date) # 同一提单,同一托盘号,使用日期必须一致
related_packages = package.bl_id.big_package_ids.filtered(
lambda p: p.pallet_number == new_pallet_number) # 查找对应提单下相同托盘号的所有大包
for related_package in related_packages:
if related_package.pallet_usage_date != record.usage_date:
raise ValidationError(
_('The same bill of lading, same pallet number, and usage date must be consistent!')) # 同一提单,同一托盘号,使用日期必须一致
package.update_pallet_info(new_pallet_number, record.usage_date)
if old_pallet_number: if old_pallet_number:
# %s %s更改了托盘号,由%s变更为%s,托盘使用日期%s变更为%s # %s %s更改了托盘号,由%s变更为%s,托盘使用日期%s变更为%s
body = _( body = _(
'%s at %s changed the pallet number from %s to %s, and the pallet usage date from %s to %s') % ( '%s at %s changed the pallet number from %s to %s, and the pallet usage date from %s to %s') % (
self.env.user.name, fields.Datetime.now(), old_pallet_number, record.pallet_number, self.env.user.name, fields.Datetime.now(), old_pallet_number, new_pallet_number,
old_usage_date, old_usage_date,
record.usage_date) record.usage_date)
else: else:
# 某人某时关联了托盘xxx,托盘使用日期xxxx # 某人某时关联了托盘xxx,托盘使用日期xxxx
body = _('%s at %s associated tray %s, with a tray usage date of %s') % ( body = _('%s at %s associated tray %s, with a tray usage date of %s') % (
self.env.user.name, fields.Datetime.now(), record.pallet_number, record.usage_date) self.env.user.name, fields.Datetime.now(), new_pallet_number, record.usage_date)
package.message_post(body=body) package.message_post(body=body)
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import json
import logging
import math import math
import random
import re import re
from odoo import http, fields, exceptions, _ from odoo import http, fields, exceptions, _
from odoo.http import request from odoo.http import request
import logging
import json
import random
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
...@@ -82,6 +81,7 @@ class OrderController(http.Controller): ...@@ -82,6 +81,7 @@ class OrderController(http.Controller):
if kwargs.get('bl_no'): if kwargs.get('bl_no'):
bl_no = kwargs['bl_no'] bl_no = kwargs['bl_no']
bl_obj = request.env['cc.bl'].sudo().search([('bl_no', '=', bl_no)]) # 提单 bl_obj = request.env['cc.bl'].sudo().search([('bl_no', '=', bl_no)]) # 提单
bl_obj = request.env['cc.bl'].sudo().deal_bl_no(bl_no) # 提单号去掉杠和空格,并转换为小写
if bl_obj: if bl_obj:
res['bl_info'] = bl_obj.search_bl_info(pda_lang=pda_lang) res['bl_info'] = bl_obj.search_bl_info(pda_lang=pda_lang)
res['state'] = 200 res['state'] = 200
...@@ -118,6 +118,7 @@ class OrderController(http.Controller): ...@@ -118,6 +118,7 @@ class OrderController(http.Controller):
if kwargs.get('bl_no') and kwargs.get('big_package_arr'): if kwargs.get('bl_no') and kwargs.get('big_package_arr'):
bl_no = kwargs['bl_no'] bl_no = kwargs['bl_no']
bl_obj = request.env['cc.bl'].sudo().search([('bl_no', '=', bl_no)]) # 提单 bl_obj = request.env['cc.bl'].sudo().search([('bl_no', '=', bl_no)]) # 提单
bl_obj = request.env['cc.bl'].sudo().deal_bl_no(bl_no) # 提单号去掉杠和空格,并转换为小写
big_package_arr = kwargs['big_package_arr'] big_package_arr = kwargs['big_package_arr']
if bl_obj: if bl_obj:
# 该箱号的大包存在, 且状态为已扫, 则提示已扫; # 该箱号的大包存在, 且状态为已扫, 则提示已扫;
...@@ -174,3 +175,28 @@ class OrderController(http.Controller): ...@@ -174,3 +175,28 @@ class OrderController(http.Controller):
pda_lang] # _('System parsing error, the reason for the error is %s', e) # 系统解析错误,错误原因是 pda_lang] # _('System parsing error, the reason for the error is %s', e) # 系统解析错误,错误原因是
logging.info('res:%s' % res) logging.info('res:%s' % res)
return res return res
@http.route('/api/exceptions/info', type='json', auth='public', methods=['GET'], csrf=False)
def exceptions_info(self):
"""
返回所有的异常原因的信息
"""
kwargs = json.loads(request.httprequest.data)
pda_lang = kwargs.get('pda_lang') or 'zh'
res = {'state': 201, 'message': ''}
try:
logging.info('exceptions_info kwargs:%s' % kwargs)
lang = 'zh_CN' if pda_lang == 'zh' else 'en_US' # 语言
exception_obj = request.env['cc.exception.info'].sudo().with_context({'lang': lang}).search([]) # 包裹异常原因
res['exception_arr'] = [excep.search_exception_info(pda_lang=pda_lang) for excep in exception_obj]
res['state'] = 200
except Exception as e:
exceptions_msg_dic = {
'en': 'System parsing error, the reason for the error is %s' % e,
'zh': '系统解析错误,错误原因是%s' % e
}
logging.info('exceptions_info error:%s' % e)
res['message'] = exceptions_msg_dic[
pda_lang] # _('System parsing error, the reason for the error is %s', e) # 系统解析错误,错误原因是
logging.info('exceptions_info res:%s' % res)
return res
import aiohttp
import asyncio import asyncio
import base64 import base64
import certifi
import json import json
import logging import logging
import ssl
import aiohttp
import certifi
import pytz import pytz
import ssl
from datetime import datetime from datetime import datetime
from lxml import etree from lxml import etree
from odoo import models, fields, api, tools, _ from odoo import models, fields, api, tools, _
...@@ -231,6 +230,15 @@ class CcShipPackage(models.Model): ...@@ -231,6 +230,15 @@ class CcShipPackage(models.Model):
source='推出') source='推出')
return '' return ''
def search_ship_package_info(self, pda_lang=False):
"""
查询小包信息
:return:
"""
return {
'logistic_order_no': self.logistic_order_no, # 物流订单号
}
# 继承提单对象t # 继承提单对象t
class CcBl(models.Model): class CcBl(models.Model):
...@@ -257,9 +265,11 @@ class CcBl(models.Model): ...@@ -257,9 +265,11 @@ class CcBl(models.Model):
# for package in ship_packages: # for package in ship_packages:
# package.callback_track() # package.callback_track()
tt_api_obj = self.env["ao.tt.api"].sudo() tt_api_obj = self.env["ao.tt.api"].sudo()
async def perform_requests(): async def perform_requests():
ssl_context = ssl.create_default_context(cafile=certifi.where()) ssl_context = ssl.create_default_context(cafile=certifi.where())
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=ssl_context), timeout=aiohttp.ClientTimeout(total=60)) as session: async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=ssl_context),
timeout=aiohttp.ClientTimeout(total=60)) as session:
tasks = [] tasks = []
for index, package in enumerate(ship_packages): for index, package in enumerate(ship_packages):
if not package.is_sync and package.state and package.state.tk_code: if not package.is_sync and package.state and package.state.tk_code:
...@@ -333,9 +343,36 @@ class CcBl(models.Model): ...@@ -333,9 +343,36 @@ class CcBl(models.Model):
'big_package_arr': [big_package_item.search_big_package_info(pda_lang=pda_lang) for big_package_item in 'big_package_arr': [big_package_item.search_big_package_info(pda_lang=pda_lang) for big_package_item in
self.big_package_ids], self.big_package_ids],
# 大包信息 # 大包信息
'ship_package_arr': [ship_package_item.search_ship_package_info(pda_lang=pda_lang) for ship_package_item in
self.ship_package_ids], # 小包信息
'pallet_arr': self.get_unique_pallet_info(), # 托盘信息
} }
return vals return vals
def get_unique_pallet_info(self):
"""获取唯一托盘信息,返回托盘号和最早的使用时间"""
pallet_info = {}
for package in self.big_package_ids:
pallet_number = package.pallet_number
pallet_usage_time = package.pallet_usage_date
if pallet_number and (pallet_number not in pallet_info or pallet_info[pallet_number] > pallet_usage_time):
pallet_info[pallet_number] = pallet_usage_time
return [{'pallet_number': k, 'pallet_usage_time': v} for k, v in pallet_info.items()]
def deal_bl_no(self, bl_no):
"""
处理提单号:去掉杠和空格,并转换为小写
:param bl_no:
:return:
"""
processed_bl_no = bl_no.replace('-', '').replace(' ', '').lower()
# 查询所有提单并处理它们的 bl_no
all_bl_obj = self.env['cc.bl'].sudo().search([])
bl_obj = all_bl_obj.filtered(
lambda r: r.bl_no.replace('-', '').replace(' ', '').lower() == processed_bl_no) # 提单
return bl_obj
class CcBigPackage(models.Model): class CcBigPackage(models.Model):
# 模型名称 # 模型名称
...@@ -355,8 +392,15 @@ class CcBigPackage(models.Model): ...@@ -355,8 +392,15 @@ class CcBigPackage(models.Model):
'en': 'Checked goods', 'en': 'Checked goods',
'zh': '已理货' 'zh': '已理货'
} }
handover_completed_msg_dic = {
'en': 'Handover Completed',
'zh': '尾程交接'
}
state_arr = {'unprocessed_goods': unprocessed_goods_msg_dic[pda_lang], state_arr = {'unprocessed_goods': unprocessed_goods_msg_dic[pda_lang],
'checked_goods': checked_goods_msg_dic[pda_lang]} # 未理货/已理货 'checked_goods': checked_goods_msg_dic[pda_lang],
'handover_completed': handover_completed_msg_dic[pda_lang]} # 未理货/已理货/尾程交接
# 根据下一阶段服务商名称获取尾程服务商的记录
provider_obj = self.env['cc.last.mile.provider'].match_provider(self.next_provider_name)
vals = { vals = {
'tally_state_label': state_arr[self.tally_state] or '', # 理货状态显示名称 'tally_state_label': state_arr[self.tally_state] or '', # 理货状态显示名称
'tally_state': self.tally_state or '', # 理货状态系统KEY 'tally_state': self.tally_state or '', # 理货状态系统KEY
...@@ -365,7 +409,12 @@ class CcBigPackage(models.Model): ...@@ -365,7 +409,12 @@ class CcBigPackage(models.Model):
'tally_time': self.tally_time or '', 'tally_time': self.tally_time or '',
# self.env['common.common'].sudo().get_format_time(str(self.tally_time)) if self.tally_time else '', # self.env['common.common'].sudo().get_format_time(str(self.tally_time)) if self.tally_time else '',
# 理货时间 # 理货时间
'big_package_no': self.big_package_no or '' # 大包号 'big_package_no': self.big_package_no or '', # 大包号
'next_service_provider_name': self.next_provider_name or '', # 下一个服务商名称
'next_service_provider_tape_color': (provider_obj.tape_color_value or '') if provider_obj else '',
# 下一个服务商胶带对应色值
'pallet_number': self.pallet_number or '', # 托盘号
'pallet_usage_time': self.pallet_usage_date or '' # 托盘使用时间
} }
return vals return vals
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论