提交 4777943a authored 作者: 伍姿英's avatar 伍姿英

Merge branch 'release/3.5.0'

......@@ -25,6 +25,7 @@
'wizard/add_exception_info_wizard_views.xml',
'wizard/email_template.xml',
'wizard/bl_done_wizard_views.xml',
'wizard/batch_get_pod_info_wizard_views.xml',
'data/data.xml',
'data/timer.xml',
'data/sequence.xml',
......
......@@ -40,5 +40,14 @@
<field name="value">mjgUUgbxXK8UHcRi5MTlPrb4BWM8NrOu</field>
</record>
<record id="last_mile_pod_api_url" model="ir.config_parameter">
<field name="key">last_mile_pod_api_url</field>
<field name="value">http://172.104.52.150:7002</field>
</record>
<record id="time_warning_hours" model="ir.config_parameter">
<field name="key">time_warning_hours</field>
<field name="value">24</field>
</record>
</data>
</odoo>
\ No newline at end of file
差异被折叠。
......@@ -16,3 +16,5 @@ from . import cc_history_package_good
from . import cc_history_ship_package
from . import cc_history_package_sync_log
from . import history_tt_api_log
......@@ -58,7 +58,7 @@ class CcBigPackage(models.Model):
# 提货相关字段
pickup_user_id = fields.Many2one('res.users', 'Pickup User', index=True) # 提货人
pickup_time = fields.Datetime('Pickup Time') # 提货时间
tally_state = fields.Selection([
('unprocessed_goods', 'Unprocessed goods'),
('picked_up', 'Picked Up'),
......@@ -554,6 +554,9 @@ class CcClearanceFile(models.Model):
def action_sync(self):
pass
def search_clearance_file(self, bl_id, file_name):
"""搜索清关文件"""
return self.env['cc.clearance.file'].search([('bl_id','=',bl_id),('file_name','=',file_name)],limit=1)
# 创建一个业务对象,继承自models.Model, 用于管理业务数据.业务数据包括提单号、提单日期、提单总件数、提单总金额、所属客户、提单明细、清关进度明细、状态[待确认、清关中、已完成]
class CcBL(models.Model):
......@@ -647,7 +650,8 @@ class CcBL(models.Model):
big_package_qty = fields.Integer(string='Big Package Qty')
# 已提货大包数量
picked_up_big_package_qty = fields.Integer(string='Picked Up Big Package Qty', compute='cal_picked_up_big_package_qty',
picked_up_big_package_qty = fields.Integer(string='Picked Up Big Package Qty',
compute='cal_picked_up_big_package_qty',
store=True)
# 理货大包数量
tally_big_package_qty = fields.Integer(string='Tally Big Package Qty', compute='cal_tally_big_package_qty',
......@@ -779,6 +783,58 @@ class CcBL(models.Model):
# 定义清关国家,关联到国家字段
cc_country_id = fields.Many2one('res.country', string='CC Country')
# 新增尾程快递,many2many,cc.last.mile.provider
last_mile_provider_ids = fields.Many2many('cc.last.mile.provider', 'cc_bill_loading_last_mile_provider_rel',
'bl_id', 'last_mile_provider_id', string='Last Mile Providers',
compute='_compute_last_mile_provider_ids', store=True)
@api.depends('big_package_ids', 'big_package_ids.next_provider_name')
def _compute_last_mile_provider_ids(self):
"""
提单关联的大包对应下一个尾程快递匹配到到尾程快递
"""
# 一次性获取所有尾程快递,避免重复查询
all_providers = self.env['cc.last.mile.provider'].sudo().search([])
# 预构建匹配值映射,提高查找效率
provider_matching_map = {}
for provider in all_providers:
if provider.matching_value:
# 预处理匹配值,避免重复split和lower操作
matching_values = [value.lower().strip() for value in provider.matching_value.split('\n') if
value.strip()]
for value in matching_values:
if value not in provider_matching_map:
provider_matching_map[value] = []
provider_matching_map[value].append(provider.id)
for bl in self:
# 先清空现有记录
bl.last_mile_provider_ids = [(6, 0, [])]
if not bl.big_package_ids:
continue
# 获取所有大包的下一个快递名称(去重)
provider_names = bl.big_package_ids.filtered('next_provider_name').mapped('next_provider_name')
if not provider_names:
continue
# 去重provider名称
provider_names = list(set(provider_names))
# 使用集合存储匹配的provider ID,避免重复
matched_provider_ids = set()
# 使用预构建的映射进行快速查找
for provider_name in provider_names:
provider_name_lower = provider_name.lower().strip()
if provider_name_lower in provider_matching_map:
matched_provider_ids.update(provider_matching_map[provider_name_lower])
# 更新字段值
if matched_provider_ids:
bl.last_mile_provider_ids = [(6, 0, list(matched_provider_ids))]
def push_clear_customs_start(self, utc_time):
# 创建向导
push_node_obj = self.env['cc.node'].sudo().search(
......@@ -870,17 +926,17 @@ class CcBL(models.Model):
}
}
def check_is_done(self, is_email=False,**kwargs):
def check_is_done(self, is_email=False, **kwargs):
# 如果提单所有小包的清关节点变成"是完成节点",则该提单状态变成已完成.tk模块有继承
if all(line.state.is_done for line in
self.ship_package_ids) and self.customs_clearance_status.is_done and self.is_bl_sync:
self.done_func(is_email,**kwargs)
self.done_func(is_email, **kwargs)
else:
if not is_email:
raise ValidationError(
_('The small package node or bill of lading node is not in the completed node, and the bill of lading cannot be changed to completed!')) # 小包节点或提单节点不在已完成节点,提单不能变为已完成!
def done_func(self, is_email=False,**kwargs):
def done_func(self, is_email=False, **kwargs):
"""
变为已完成
"""
......@@ -890,7 +946,7 @@ class CcBL(models.Model):
# 如果选择了忽略节点异常,则记录异常原因
if kwargs.get('exception_reason'):
exception_reason = kwargs['exception_reason']
#输出当前用户是什么语言
# 输出当前用户是什么语言
if self.env.user.lang == 'zh_CN':
message = '提单已完成,但存在节点异常,原因是:%s!' % exception_reason
else:
......@@ -1089,6 +1145,17 @@ class CcBL(models.Model):
'default_current_status': customs_clearance_status_list[0]}
}
def action_batch_get_pod_info(self):
"""批量获取尾程POD信息"""
return {
'name': _('Batch Get POD Info'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'batch.get.pod.info.wizard',
'context': {'active_id': self.ids},
'target': 'new',
}
# 增加一个清关进度的业务对象,继承自models.Model, 用于管理业务数据.业务数据包括提单号、清关节点(业务对象)、进度日期、进度描述、更新人
class CcProgress(models.Model):
......
......@@ -6,8 +6,7 @@ add_exception_info_wizard_group_user,add_exception_info_wizard_group_user,ccs_ba
update_bl_status_wizard_group_user,update_bl_status_wizard_group_user,ccs_base.model_update_bl_status_wizard,base.group_user,1,1,1,1
batch_update_transfer_bl_no_wizard_group_user,batch_update_transfer_bl_no_wizard_group_user,ccs_base.model_batch_update_transfer_bl_no_wizard,base.group_user,1,1,1,1
bl_done_wizard_group_user,bl_done_wizard_group_user,ccs_base.model_bl_done_wizard,base.group_user,1,1,1,1
batch_get_pod_info_wizard_group_user,batch_get_pod_info_wizard_group_user,ccs_base.model_batch_get_pod_info_wizard,base.group_user,1,1,1,1
access_group_user_common_common,access_group_user_common_common,model_common_common,base.group_user,1,1,1,1
......
......@@ -13,6 +13,7 @@
<field optional="show" name="customs_clearance_status" string="Customs Clearance Status"/>
<field optional="show" name="bl_no" string="Bill of Loading No."/>
<field optional="show" name="bl_date" string="B/L Date"/>
<field optional="show" name="last_mile_provider_ids" string="Last Mile Providers" widget="many2many_tags"/>
<field optional="hide" name="transfer_bl_no" string="Transfer Bill of Loading No."/>
<field optional="show" name="customer_id" string="Customer"/>
<field optional="show" name="customs_bl_no" string="Customs Bill of Loading No."/>
......@@ -140,6 +141,7 @@
<group>
<group>
<field name="bl_date" string="B/L Date"/>
<field name="last_mile_provider_ids" string="Last Mile Providers" widget="many2many_tags"/>
<field name="transfer_bl_no"/>
<field name="customer_id" string="Customer"/>
<field name="customs_bl_no" string="Customs Bill of Loading No."/>
......@@ -308,6 +310,8 @@
domain="[('cc_deadline', '&lt;', time.strftime('%Y-%m-%d'))]"/>
<separator/>
<group expand="0" string="Group By">
<!-- <filter domain="[]" name="groupby_last_mile_provider_ids" string="Last Mile Providers"
context="{'group_by': 'last_mile_provider_ids'}"/> -->
<filter domain="[]" name="groupby_customer_id" string="Customer"
context="{'group_by': 'customer_id'}"/>
<filter domain="[]" name="groupby_cc_company_id" string="CC Company"
......@@ -465,4 +469,18 @@
</field>
</record>
<!-- 获取尾程POD -->
<record id="bl_get_pod_info_server_action" model="ir.actions.server">
<field name="name">Batch Get POD Info</field>
<field name="model_id" ref="model_cc_bl"/>
<field name="binding_model_id" ref="model_cc_bl"/>
<field name="state">code</field>
<field name="binding_view_types">list,form</field>
<field name="groups_id" eval="[(4, ref('ccs_base.group_clearance_of_customs_user'))]"/>
<field name="code">
if records:
action = records.action_batch_get_pod_info()
</field>
</record>
</odoo>
\ No newline at end of file
......@@ -7,4 +7,5 @@ from . import add_exception_info_wizard
from . import update_bl_status_wizard
from . import batch_update_transfer_bl_no_wizard
from . import bl_done_wizard
from . import batch_get_pod_info_wizard
差异被折叠。
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Batch Get POD Info Wizard Form View 批量获取POD信息向导表单视图 -->
<record id="view_batch_get_pod_info_wizard_form" model="ir.ui.view">
<field name="name">batch.get.pod.info.wizard.form</field>
<field name="model">batch.get.pod.info.wizard</field>
<field name="arch" type="xml">
<form string="Batch Get POD Info"> <!-- 批量获取POD信息 -->
<sheet>
<group>
<group>
<field name="sync_last_mile_pod" widget="boolean_toggle"/>
</group>
<group>
<field name="remove_specified_text" widget="boolean_toggle"/>
</group>
</group>
<div class="alert alert-info" role="alert">
<strong>Description:</strong> <!-- 说明: -->
<ul>
<li><strong>Sync Last Mile POD:</strong> Synchronize POD (Proof of Delivery) attachment information with TK system, including big package quantities and container numbers</li> <!-- 同步尾程POD:向TK同步尾程交接POD(待大包数量和箱号)的附件信息 -->
<li><strong>Remove Specified Text:</strong> Remove specified text (AGN, UCLINK LOGISITICS LTD) from PDF files</li> <!-- 涂抹指定文字:对PDF文件中的指定文字进行涂抹处理 -->
</ul>
</div>
<footer>
<button string="Confirm" type="object" name="confirm" class="btn-primary"/>
<button string="Close" special="cancel"/>
</footer>
</sheet>
</form>
</field>
</record>
<!-- Batch Get POD Info Wizard Action 批量获取POD信息向导动作 -->
<record id="action_batch_get_pod_info_wizard" model="ir.actions.act_window">
<field name="name">Batch Get POD Info</field> <!-- 批量获取POD信息 -->
<field name="res_model">batch.get.pod.info.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context">{}</field>
</record>
</data>
</odoo>
\ No newline at end of file
......@@ -2,7 +2,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
from datetime import datetime
from odoo import models, api, fields, _
from odoo.exceptions import ValidationError
......@@ -83,6 +83,23 @@ class BatchInputShipPackageStatusWizard(models.TransientModel):
state_explain = fields.Text('State Explain', help='State Explain')
node_exception_reason_id = fields.Many2one('cc.node.exception.reason', 'Exception Reason',
domain="[('code_id', '=', update_status)]")
# 添加时间对比提示字段
time_warning = fields.Text('Time Warning', compute='_compute_time_warning', store=False)
@api.depends('process_time')
def _compute_time_warning(self):
"""计算时间警告提示"""
for record in self:
record.time_warning = ""
if record.process_time:
now = datetime.now()
time_diff = now - record.process_time
hours_diff = time_diff.total_seconds() / 3600
time_warning_hours = self.env['ir.config_parameter'].sudo().get_param('time_warning_hours',24)
if hours_diff > int(time_warning_hours):
record.time_warning = _("The selected operation time exceeds %s hours, please confirm the operation time again") % time_warning_hours#提示:所选操作时间超过24小时,请再次确认操作时间
# 批量更新小包状态
def submit(self):
......
......@@ -40,10 +40,16 @@
<!-- domain="[('id','in',next_code_ids),('node_type','=','package')]"-->
<field name="update_status" required="1" options="{'no_create':True,'no_open':True,}"/>
<field name="process_time" required="1" string="Process Time"/>
<field name="node_exception_reason_id" options="{'no_create':True}"/>
<field name="state_explain"/>
<field name="is_batch" invisible="1"/>
</group>
<!-- <group> -->
<div attrs="{'invisible': [('time_warning', '=', False),('time_warning', '=', '')]}" style="color: red; font-weight: bold;">
<field name="time_warning"/>
</div>
<!-- </group> -->
<group>
<field name="is_ok"/>
</group>
......
......@@ -407,6 +407,7 @@ class TTApi(http.Controller):
big_package_vals)
else:
big_package.write(big_package_vals)
# 生成cc.ship.package
package_list = big_bag.get(
'package_list') # 大包下的小包
......@@ -431,6 +432,8 @@ class TTApi(http.Controller):
'big_bag_no')
else:
res['msg'] = 'Big bag list is empty.'
#调用计算尾程服务商的方法
bl.compute_last_mile_provider_ids()
except Exception as e:
res['code'] = 5000
res['msg'] = 'system error: %s' % str(e)
......
pygtrans
PyMuPDF
opencv-python; sys_platform == "win32"
opencv-python-headless; sys_platform != "win32"
numpy
Pillow
tesseract
pytesseract
# 系统依赖安装说明:
# Windows系统:
# 1. 安装Tesseract OCR: 下载并安装 https://github.com/UB-Mannheim/tesseract/wiki
# 2. 安装OpenCV: pip install opencv-python
# Linux系统:
# 1. 更新包列表: sudo apt update
# 2. 安装Tesseract OCR: sudo apt install tesseract-ocr
# 3. 安装英语语言包: sudo apt install tesseract-ocr-eng
# 4. 安装OpenCV系统依赖: sudo apt install libopencv-dev python3-opencv
# 5. 安装OpenCV Python包: pip install opencv-python-headless
# macOS系统:
# 1. 安装Tesseract: brew install tesseract
# 2. 安装OpenCV: pip install opencv-python-headless
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论