Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
H
hh_ccs
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
贺阳
hh_ccs
Commits
8a7e31ff
提交
8a7e31ff
authored
10月 29, 2025
作者:
贺阳
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
获取pod,如果是自动的,失败的直接跳过。如果是手动批量,失败的需要进行提示,成功的需要继续执行
上级
151bf0e8
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
30 行增加
和
77 行删除
+30
-77
cc_bill_loading.py
ccs_base/models/cc_bill_loading.py
+1
-1
batch_get_pod_info_wizard.py
ccs_base/wizard/batch_get_pod_info_wizard.py
+26
-76
batch_get_pod_info_wizard_views.xml
ccs_base/wizard/batch_get_pod_info_wizard_views.xml
+3
-0
没有找到文件。
ccs_base/models/cc_bill_loading.py
浏览文件 @
8a7e31ff
...
...
@@ -719,7 +719,7 @@ class CcBL(models.Model):
bl_objs
=
self
.
env
[
'cc.bl'
]
.
search
([(
'state'
,
'='
,
'ccing'
),
(
'cc_attachment_ids.file_name'
,
'='
,
'尾程交接POD(待大包数量和箱号)'
),
(
'cc_attachment_ids.file'
,
'='
,
False
)])
logging
.
info
(
'cron_get_pod bl_objs:
%
s'
%
len
(
bl_objs
))
if
len
(
bl_objs
)
>
0
:
wizard_obj
=
self
.
env
[
'batch.get.pod.info.wizard'
]
.
sudo
()
.
with_context
(
active_id
=
bl_objs
.
ids
)
.
create
({
wizard_obj
=
self
.
env
[
'batch.get.pod.info.wizard'
]
.
sudo
()
.
with_context
(
active_id
=
bl_objs
.
ids
,
is_skip_raise_error
=
True
)
.
create
({
'sync_last_mile_pod'
:
True
,
'remove_specified_text'
:
True
,
'sync_match_node'
:
True
...
...
ccs_base/wizard/batch_get_pod_info_wizard.py
浏览文件 @
8a7e31ff
...
...
@@ -51,6 +51,10 @@ class BatchGetPodInfoWizard(models.TransientModel):
# default=False,
# help='Show red markers for deleted text positions' # 显示删除文字位置的红色标记
# )
show_error_message
=
fields
.
Text
(
string
=
'Show Error Message'
,
help
=
'Show error message'
)
def
confirm
(
self
):
"""
...
...
@@ -58,6 +62,7 @@ class BatchGetPodInfoWizard(models.TransientModel):
"""
# 计算整个过程的耗时
start_time
=
time
.
time
()
self
.
show_error_message
=
False
bl_objs
=
self
.
get_order
()
_logger
.
info
(
f
"
%
s提单开始执行批量获取POD信息操作"
%
len
(
bl_objs
))
# 调用接口获取提单pdf文件
...
...
@@ -71,10 +76,13 @@ class BatchGetPodInfoWizard(models.TransientModel):
if
bl
.
id
not
in
matched_bl_ids
:
error_bl
.
append
(
bl
)
if
error_bl
:
logging
.
info
(
'
%
s个提单无法找到release note文件'
%
len
(
error_bl
))
# 英文提示
raise
ValidationError
(
_
(
'
%
s bill of loading cannot find release note file'
)
%
(
', '
.
join
([
bl
.
bl_no
for
bl
in
error_bl
])))
# xx提单无法找到release note文件
if
not
self
.
_context
.
get
(
'is_skip_raise_error'
):
self
.
show_error_message
=
_
(
'
%
s bill of loading cannot find release note file'
)
%
(
', '
.
join
([
bl
.
bl_no
for
bl
in
error_bl
]))
# raise ValidationError(_('%s bill of loading cannot find release note file') % (
# ', '.join([bl.bl_no for bl in error_bl]))) # xx提单无法找到release note文件
if
self
.
remove_specified_text
:
# 临时启用调试模式,查看删除位置
processed_files
=
self
.
_remove_specified_text
(
processed_files
,
debug_mode
=
False
)
...
...
@@ -95,6 +103,15 @@ class BatchGetPodInfoWizard(models.TransientModel):
self
.
get_date_sync_match_node
(
processed_files
)
end_time
=
time
.
time
()
_logger
.
info
(
f
"批量获取POD信息操作完成,耗时: {end_time - start_time}秒"
)
if
self
.
show_error_message
and
not
self
.
_context
.
get
(
'is_skip_raise_error'
):
return
{
'type'
:
'ir.actions.act_window'
,
'res_model'
:
'batch.get.pod.info.wizard'
,
'view_mode'
:
'form'
,
'res_id'
:
self
.
id
,
'target'
:
'new'
,
'context'
:
{
'default_show_error_message'
:
self
.
show_error_message
,
'active_id'
:
bl_objs
.
ids
}
}
# 写一个方法调接口获取提单pdf文件
def
_get_pdf_file_arr
(
self
):
...
...
@@ -183,6 +200,8 @@ class BatchGetPodInfoWizard(models.TransientModel):
bl
=
file_info
[
'bl'
]
file_name
=
file_info
[
'file_name'
]
file_data
=
file_info
[
'file_data'
]
if
not
file_data
:
continue
# 如果有文件为空的就回写,否则就创建新的清关文件记录
fix_name
=
'尾程交接POD(待大包数量和箱号)'
clearance_file
=
self
.
env
[
'cc.clearance.file'
]
.
search
(
...
...
@@ -747,77 +766,6 @@ class BatchGetPodInfoWizard(models.TransientModel):
return
previous_row
[
-
1
]
def
_save_and_return_download_link
(
self
,
file_info
):
"""
用于测试的 Save processed PDF as attachment and return download action # 保存处理后的PDF作为附件并返回下载动作
:param file_info: 处理后的文件信息
:return: Odoo action to download the file
"""
try
:
# 获取处理后的PDF数据
file_data
=
file_info
.
get
(
'file_data'
,
''
)
file_name
=
file_info
.
get
(
'file_name'
,
'processed.pdf'
)
if
not
file_data
:
raise
ValidationError
(
_
(
'No processed file data available'
))
# 提示:没有处理后的文件数据
# 解码base64数据
if
isinstance
(
file_data
,
str
):
pdf_binary
=
base64
.
b64decode
(
file_data
)
else
:
pdf_binary
=
file_data
# 确保PDF数据有效
if
not
pdf_binary
.
startswith
(
b
'
%
PDF-'
):
# 尝试修复:如果是base64字符串被错误处理
if
isinstance
(
file_data
,
str
)
and
len
(
file_data
)
>
100
:
_logger
.
info
(
"尝试重新解码base64数据..."
)
try
:
# 重新尝试base64解码
pdf_binary_fixed
=
base64
.
b64decode
(
file_data
)
if
pdf_binary_fixed
.
startswith
(
b
'
%
PDF-'
):
_logger
.
info
(
"✅ 重新解码成功,PDF数据有效"
)
pdf_binary
=
pdf_binary_fixed
else
:
_logger
.
error
(
"❌ 重新解码后仍然不是有效的PDF"
)
raise
ValidationError
(
_
(
'Invalid PDF data for saving: not a valid PDF format'
))
except
Exception
as
e
:
_logger
.
error
(
f
"重新解码失败: {str(e)}"
)
raise
ValidationError
(
_
(
'Invalid PDF data for saving: not a valid PDF format'
))
else
:
raise
ValidationError
(
_
(
'Invalid PDF data for saving: not a valid PDF format'
))
# 验证PDF可以打开
try
:
import
fitz
test_doc
=
fitz
.
open
(
stream
=
pdf_binary
,
filetype
=
"pdf"
)
_logger
.
info
(
f
"PDF验证成功,页数: {len(test_doc)}"
)
test_doc
.
close
()
except
Exception
as
e
:
_logger
.
error
(
f
"PDF验证失败: {str(e)}"
)
raise
ValidationError
(
_
(
'Invalid PDF data for saving: cannot open PDF -
%
s'
)
%
str
(
e
))
# 创建附件记录
attachment
=
self
.
env
[
'ir.attachment'
]
.
create
({
'name'
:
f
'processed_{file_name}'
,
'type'
:
'binary'
,
'datas'
:
base64
.
b64encode
(
pdf_binary
),
'mimetype'
:
'application/pdf'
,
'res_model'
:
'batch.get.pod.info.wizard'
,
'res_id'
:
self
.
id
,
})
# 返回下载动作
return
{
'type'
:
'ir.actions.act_url'
,
'url'
:
f
'/web/content/{attachment.id}?download=true'
,
'target'
:
'new'
,
}
except
Exception
as
e
:
_logger
.
error
(
f
"保存PDF附件失败: {str(e)}"
)
raise
ValidationError
(
_
(
'Failed to save PDF attachment:
%
s'
)
%
str
(
e
))
def
get_date_sync_match_node
(
self
,
processed_files
):
"""
Sync matched node based on POD file, extract time from red boxes # 根据POD文件同步匹配节点
...
...
@@ -849,7 +797,7 @@ class BatchGetPodInfoWizard(models.TransientModel):
# 从PDF文件提取红色框的时间
file_data
=
file_info
.
get
(
'file_data'
)
if
not
file_data
:
_logger
.
warning
(
f
"提单 {bl.bl_no} 没有文件数据"
)
logging
.
info
(
f
"提单 {bl.bl_no} 没有文件数据"
)
continue
try
:
# 如果已识别过OCR文本,则复用
...
...
@@ -873,7 +821,9 @@ class BatchGetPodInfoWizard(models.TransientModel):
error_bl
.
append
(
bl
)
if
error_bl
:
_logger
.
warning
(
f
"提单 {', '.join([bl.bl_no for bl in error_bl])} 没有提取到时间信息"
)
raise
ValidationError
(
if
not
self
.
_context
.
get
(
'is_skip_raise_error'
):
raise
ValidationError
(
_
(
'
%
s bill of loading cannot get node operation time,please manually upload push tk'
)
%
(
', '
.
join
([
bl
.
bl_no
for
bl
in
error_bl
])))
# xx提单号没有获取到节点操作时间,请手动上传推送提单到TK
return
ship_packages
,
pod_node
.
id
...
...
ccs_base/wizard/batch_get_pod_info_wizard_views.xml
浏览文件 @
8a7e31ff
...
...
@@ -29,6 +29,9 @@
<li><strong>
Sync Push Match Node:
</strong>
Synchronize and push matched node information based on POD file, extract time from red boxes as node operation time
</li>
<!-- 同步推送匹配节点:根据POD文件获取对应的清关节点,提取红色框时间作为节点操作时间 -->
</ul>
</div>
<div
class=
"alert alert-danger"
role=
"alert"
attrs=
"{'invisible': [('show_error_message', '=', False)]}"
>
<field
name=
"show_error_message"
/>
</div>
<footer>
<button
string=
"Confirm"
type=
"object"
name=
"confirm"
class=
"btn-primary"
/>
<button
string=
"Close"
special=
"cancel"
/>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论