Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
H
hh_ccs
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
贺阳
hh_ccs
Commits
8af2ea18
提交
8af2ea18
authored
2月 09, 2026
作者:
伍姿英
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'release/3.9.0'
上级
11b54e37
c58892b0
显示空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
129 行增加
和
16 行删除
+129
-16
zh_CN.po
ccs_connect_tiktok/i18n/zh_CN.po
+15
-3
cc_bill_loading.py
ccs_connect_tiktok/models/cc_bill_loading.py
+109
-12
cc_node.py
ccs_connect_tiktok/models/cc_node.py
+1
-0
cc_node_view.xml
ccs_connect_tiktok/views/cc_node_view.xml
+4
-1
没有找到文件。
ccs_connect_tiktok/i18n/zh_CN.po
浏览文件 @
8af2ea18
...
...
@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 202
5-10-31 02:15
+0000\n"
"PO-Revision-Date: 202
5-10-31 10:16
+0800\n"
"POT-Creation-Date: 202
6-02-06 06:30
+0000\n"
"PO-Revision-Date: 202
6-02-06 14:32
+0800\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: zh_CN\n"
...
...
@@ -57,7 +57,7 @@ msgstr "附件"
#. module: ccs_connect_tiktok
#: model:ir.model,name:ccs_connect_tiktok.model_batch_get_pod_info_wizard
msgid "Batch Get POD Info Wizard"
msgstr "批量获取
尾程
POD向导"
msgstr "批量获取POD向导"
#. module: ccs_connect_tiktok
#: model:ir.actions.server,name:ccs_connect_tiktok.action_batch_sync_bl_status
...
...
@@ -287,6 +287,11 @@ msgstr ""
msgid "Is Bill Of Loading Sync"
msgstr "关务提单状态是否同步"
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_node__is_patrol_node
msgid "Is Patrol Node"
msgstr "是巡查节点"
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package__is_sync
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.form_cc_bl_view_inherit
...
...
@@ -867,6 +872,13 @@ msgstr ""
msgid "推出"
msgstr ""
#. module: ccs_connect_tiktok
#. odoo-python
#: code:addons/ccs_connect_tiktok/wizard/batch_get_pod_info_wizard.py:0
#, python-format
msgid "提单 %s 没有提取到时间信息,请检查提单是否正确"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__bl_issues
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_form
...
...
ccs_connect_tiktok/models/cc_bill_loading.py
浏览文件 @
8af2ea18
...
...
@@ -375,6 +375,7 @@ class CcBl(models.Model):
:param user_obj:
:return:
"""
logging
.
info
(
f
"package_state_obj: {package_state_obj}"
)
# 根据小包的状态找到对应的提单关务状态
state_obj
=
self
.
env
[
'cc.node'
]
.
search
([(
'package_state'
,
'='
,
package_state_obj
.
id
)],
limit
=
1
)
for
bl
in
self
:
...
...
@@ -390,25 +391,114 @@ class CcBl(models.Model):
is_ok
=
True
for
before_node
in
before_node_obj
:
if
not
bl
.
bl_sync_log_ids
.
filtered
(
lambda
r
:
r
.
process_code
==
before_node
.
tk_code
):
# 修改关务提单状态
bl
.
customs_clearance_status
=
before_node
.
id
# 操作时间根据设置的前序节点间距时间取值
before_minutes
=
before_node
.
calculate_total_interval
(
state_obj
)
bl
.
process_time
=
datetime
.
strptime
(
str
(
operate_time
),
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
)
-
timedelta
(
candidate_time
=
datetime
.
strptime
(
str
(
operate_time
),
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
)
-
timedelta
(
minutes
=
before_minutes
)
prev_nodes
=
before_node
.
get_before_node
(
node_type
=
'bl'
)
if
prev_nodes
:
prev_codes
=
prev_nodes
.
mapped
(
'tk_code'
)
prev_logs
=
bl
.
bl_sync_log_ids
.
filtered
(
lambda
r
:
r
.
process_code
in
prev_codes
and
r
.
operate_time
)
if
prev_logs
:
latest_prev_time
=
max
(
prev_logs
.
mapped
(
'operate_time'
))
logging
.
info
(
f
"latest_prev_time: {latest_prev_time}"
)
if
candidate_time
<
latest_prev_time
:
remark
=
(
f
"自动补写提单前序关务节点被拦截,节点:{before_node.desc or before_node.name},"
f
"候选时间:{candidate_time.strftime('
%
Y-
%
m-
%
d
%
H:
%
M:
%
S')},"
f
"前序节点最新时间:{latest_prev_time.strftime('
%
Y-
%
m-
%
d
%
H:
%
M:
%
S')}。"
f
"存在时间倒挂风险,请核查。"
)
bl
.
message_post
(
body
=
remark
)
# continue
is_ok
=
False
break
next_nodes
=
self
.
env
[
'cc.node'
]
.
sudo
()
.
search
([
(
'node_type'
,
'='
,
'bl'
),
(
'is_must'
,
'='
,
True
),
(
'seq'
,
'>'
,
before_node
.
seq
),
])
if
next_nodes
:
next_codes
=
next_nodes
.
mapped
(
'tk_code'
)
next_logs
=
bl
.
bl_sync_log_ids
.
filtered
(
lambda
r
:
r
.
process_code
in
next_codes
and
r
.
operate_time
)
if
next_logs
:
earliest_next_time
=
min
(
next_logs
.
mapped
(
'operate_time'
))
logging
.
info
(
f
"earliest_next_time: {earliest_next_time}, candidate_time: {candidate_time}"
)
if
candidate_time
>
earliest_next_time
:
remark
=
(
f
"自动补写提单前序关务节点被拦截,节点:{before_node.desc or before_node.name},"
f
"候选时间:{candidate_time.strftime('
%
Y-
%
m-
%
d
%
H:
%
M:
%
S')},"
f
"后续节点最早时间:{earliest_next_time.strftime('
%
Y-
%
m-
%
d
%
H:
%
M:
%
S')}。"
f
"存在时间倒挂风险,请核查。"
)
bl
.
message_post
(
body
=
remark
)
is_ok
=
False
break
if
not
is_ok
:
break
bl
.
customs_clearance_status
=
before_node
.
id
bl
.
process_time
=
candidate_time
bl
.
is_bl_sync
=
before_node
.
node_is_sync
()
self
.
_cr
.
commit
()
# 调用同步关务提单状态
is_ok
=
bl
.
callback_track_bl
(
user_obj
)
if
not
is_ok
:
break
if
is_ok
:
candidate_time
=
operate_time
prev_nodes
=
state_obj
.
get_before_node
(
node_type
=
'bl'
)
allow_push
=
True
block_reason
=
""
if
prev_nodes
:
prev_codes
=
prev_nodes
.
mapped
(
'tk_code'
)
prev_logs
=
bl
.
bl_sync_log_ids
.
filtered
(
lambda
r
:
r
.
process_code
in
prev_codes
and
r
.
operate_time
)
if
prev_logs
:
latest_prev_time
=
max
(
prev_logs
.
mapped
(
'operate_time'
))
if
candidate_time
<
latest_prev_time
:
allow_push
=
False
block_reason
=
(
f
"候选时间早于前序节点最新时间(候选时间:"
f
"{candidate_time.strftime('
%
Y-
%
m-
%
d
%
H:
%
M:
%
S')},前序最新时间:"
f
"{latest_prev_time.strftime('
%
Y-
%
m-
%
d
%
H:
%
M:
%
S')})"
)
if
allow_push
:
next_nodes
=
self
.
env
[
'cc.node'
]
.
sudo
()
.
search
([
(
'node_type'
,
'='
,
'bl'
),
(
'is_must'
,
'='
,
True
),
(
'seq'
,
'>'
,
state_obj
.
seq
),
])
logging
.
info
(
f
"next_nodes: {next_nodes}"
)
if
next_nodes
:
next_codes
=
next_nodes
.
mapped
(
'tk_code'
)
next_logs
=
bl
.
bl_sync_log_ids
.
filtered
(
lambda
r
:
r
.
process_code
in
next_codes
and
r
.
operate_time
)
logging
.
info
(
f
"next_logs: {next_logs}"
)
if
next_logs
:
earliest_next_time
=
min
(
next_logs
.
mapped
(
'operate_time'
))
if
candidate_time
>
earliest_next_time
:
allow_push
=
False
block_reason
=
(
f
"候选时间晚于后续节点最早时间(候选时间:"
f
"{candidate_time.strftime('
%
Y-
%
m-
%
d
%
H:
%
M:
%
S')},后续最早时间:"
f
"{earliest_next_time.strftime('
%
Y-
%
m-
%
d
%
H:
%
M:
%
S')})"
)
logging
.
info
(
f
"allow_push: {allow_push}"
)
if
allow_push
:
logging
.
info
(
f
"state_obj: {state_obj.tk_code}"
)
bl
.
customs_clearance_status
=
state_obj
.
id
bl
.
process_time
=
oper
ate_time
bl
.
process_time
=
candid
ate_time
bl
.
is_bl_sync
=
state_obj
.
node_is_sync
()
self
.
_cr
.
commit
()
# 调用同步提单状态
bl
.
callback_track_bl
(
user_obj
)
elif
block_reason
:
remark
=
(
f
"自动补写提单关务节点被拦截,节点:{state_obj.desc or state_obj.name},"
f
"{block_reason}。存在时间倒挂风险,请核查。"
)
bl
.
message_post
(
body
=
remark
)
# 如果提单有小包变成了清关开始,提单状态变为清关中;如果提单所有小包的清关节点变成"是完成节点",则该提单状态变成已完成
bl
.
change_state_by_ship_package
()
...
...
@@ -549,7 +639,7 @@ class CcBl(models.Model):
logs_by_process
[
log
.
process_code
]
=
log
# 方法1: 根据节点的seq进行排序(推荐)
sync_logs
=
[]
bl_nodes
=
self
.
env
[
'cc.node'
]
.
sudo
()
.
search
([(
'node_type'
,
'='
,
'package'
),
(
'is_
must
'
,
'='
,
True
)],
bl_nodes
=
self
.
env
[
'cc.node'
]
.
sudo
()
.
search
([(
'node_type'
,
'='
,
'package'
),
(
'is_
patrol_node
'
,
'='
,
True
)],
order
=
'seq'
)
if
bl_nodes
:
for
node
in
bl_nodes
:
...
...
@@ -646,7 +736,7 @@ class CcBl(models.Model):
"""
issues
=
[]
# 获取所有小包节点,按顺序排序
package_nodes
=
self
.
env
[
'cc.node'
]
.
sudo
()
.
search
([(
'node_type'
,
'='
,
'package'
),
(
'is_
must
'
,
'='
,
True
)],
package_nodes
=
self
.
env
[
'cc.node'
]
.
sudo
()
.
search
([(
'node_type'
,
'='
,
'package'
),
(
'is_
patrol_node
'
,
'='
,
True
)],
order
=
'seq'
)
if
not
package_nodes
:
return
issues
...
...
@@ -696,7 +786,7 @@ class CcBl(models.Model):
# 根据节点的seq进行排序
sync_logs
=
[]
# 获取所有提单节点,按业务顺序排序
bl_nodes
=
self
.
env
[
'cc.node'
]
.
sudo
()
.
search
([(
'node_type'
,
'='
,
'bl'
),
(
'is_
must
'
,
'='
,
True
)],
order
=
'seq'
)
bl_nodes
=
self
.
env
[
'cc.node'
]
.
sudo
()
.
search
([(
'node_type'
,
'='
,
'bl'
),
(
'is_
patrol_node
'
,
'='
,
True
)],
order
=
'seq'
)
if
bl_nodes
:
for
node
in
bl_nodes
:
if
node
.
tk_code
in
logs_by_bl_process
.
keys
():
...
...
@@ -753,7 +843,7 @@ class CcBl(models.Model):
"""
issues
=
[]
# 获取所有提单节点,按顺序排序
bl_nodes
=
self
.
env
[
'cc.node'
]
.
sudo
()
.
search
([(
'node_type'
,
'='
,
'bl'
),
(
'is_
must
'
,
'='
,
True
)],
order
=
'seq'
)
bl_nodes
=
self
.
env
[
'cc.node'
]
.
sudo
()
.
search
([(
'node_type'
,
'='
,
'bl'
),
(
'is_
patrol_node
'
,
'='
,
True
)],
order
=
'seq'
)
if
not
bl_nodes
:
return
issues
# 检查每个节点是否有对应的同步日志
...
...
@@ -1217,6 +1307,7 @@ class CcBl(models.Model):
if
self
.
ship_package_ids
:
# 检查所有小包状态是否一致
states
=
set
(
self
.
ship_package_ids
.
mapped
(
'state.id'
))
logging
.
info
(
f
"states: {states}"
)
if
len
(
states
)
==
1
:
self
.
change_customs_state_by_ship_package
(
self
.
ship_package_ids
[
0
]
.
state
,
user_obj
=
user_obj
)
else
:
...
...
@@ -1292,12 +1383,15 @@ class CcBl(models.Model):
# 合并前序节点和当前节点,去重
before_node_obj
=
before_node_obj
|
node_obj
[
0
]
# 理货或尾程交接之前没有生成的节点
for
before_node
in
before_node_obj
:
for
idx
,
before_node
in
enumerate
(
before_node_obj
)
:
before_minutes
=
before_node
.
calculate_total_interval
(
node_obj
[
0
])
# 准备批量更新数据
update_data
=
[]
for
package
in
all_ship_package_obj
:
package_id
=
package
.
id
# 后续节点只处理上一节点同步成功(is_sync=True)的小包
if
idx
>
0
and
not
package
.
is_sync
:
continue
if
package_id
not
in
sync_log_dict
or
before_node
.
tk_code
not
in
sync_log_dict
.
get
(
package_id
,
set
()):
tally_time
=
ship_packages_dict
.
get
(
package_id
)
...
...
@@ -1348,6 +1442,9 @@ class CcBl(models.Model):
for
index
,
node
in
enumerate
(
node_obj
):
update_data
=
[]
for
package
in
all_ship_package_obj
:
# 只有上一节点同步成功的小包才生成后续节点
if
not
package
.
is_sync
:
continue
if
package
.
state
.
name
in
state_node_dict
:
current_state_node
=
state_node_dict
[
package
.
state
.
name
]
if
current_state_node
.
seq
<
node
.
seq
:
...
...
ccs_connect_tiktok/models/cc_node.py
浏览文件 @
8af2ea18
...
...
@@ -11,6 +11,7 @@ class CCNode(models.Model):
tk_code
=
fields
.
Char
(
'TK Code'
,
help
=
'TK Code'
)
interval_minutes
=
fields
.
Integer
(
'Predecessor Node Interval (Minutes)'
,
default
=
20
,
help
=
'Default interval time between predecessor nodes in minutes.'
)
# 前序节点间隔时间,默认20分钟
is_patrol_node
=
fields
.
Boolean
(
'Is Patrol Node'
,
default
=
False
)
def
get_before_node
(
self
,
node_type
=
'package'
):
"""
...
...
ccs_connect_tiktok/views/cc_node_view.xml
浏览文件 @
8af2ea18
...
...
@@ -2,7 +2,7 @@
<odoo>
<data>
<!-- # 继承节点的tree视图,增加tt_code字段在列表中-->
<!-- # 继承节点的tree视图,增加tt_code字段在列表中-->
<record
model=
"ir.ui.view"
id=
"tree_cc_node_view_inherit"
>
<field
name=
"name"
>
tree.cc.node.view
</field>
<field
name=
"model"
>
cc.node
</field>
...
...
@@ -16,6 +16,9 @@
<field
name=
"interval_minutes"
/>
</field>
<field
name=
"is_must"
position=
"after"
>
<field
name=
"is_patrol_node"
/>
</field>
</field>
</record>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论