Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
H
hh_ccs
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
贺阳
hh_ccs
Commits
c92e3705
提交
c92e3705
authored
7月 21, 2026
作者:
伍姿英
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'release/3.15.0'
上级
6281d9d9
eea1901b
显示空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
128 行增加
和
3 行删除
+128
-3
cc_bill_loading.py
ccs_connect_tiktok/models/cc_bill_loading.py
+69
-0
tt_api.py
ccs_connect_tiktok/models/tt_api.py
+14
-0
cc_ship_package_view.xml
ccs_connect_tiktok/views/cc_ship_package_view.xml
+18
-0
attachment_preview.xml
..._attachment_preview/static/src/xml/attachment_preview.xml
+27
-3
没有找到文件。
ccs_connect_tiktok/models/cc_bill_loading.py
浏览文件 @
c92e3705
...
...
@@ -13,6 +13,7 @@ import pytz
from
odoo
import
models
,
fields
,
api
,
_
from
odoo.exceptions
import
ValidationError
,
UserError
_logger
=
logging
.
getLogger
(
__name__
)
def
get_rfc339_time
(
utc_time
=
None
):
if
not
utc_time
:
...
...
@@ -260,6 +261,74 @@ class CcShipPackage(models.Model):
'logistic_order_no'
:
self
.
logistic_order_no
,
# 物流订单号
}
def
get_package_invoice_query_data
(
self
):
push_data
=
{
"provider_order_id"
:
self
.
logistic_order_no
or
''
,
"declaretion_bill_id"
:
self
.
customer_ref
or
''
,
"reason"
:
"业务需要"
}
# logging.info('小包发票下载 push_data:%s' % push_data)
return
push_data
def
operate_package_invoice_query
(
self
):
data_arr
=
[]
error_msg_arr
=
[]
for
item
in
self
:
data
=
item
.
get_package_invoice_query_data
()
data_arr
.
append
((
data
,
item
))
tt_api_obj
=
self
.
env
[
"ao.tt.api"
]
.
sudo
()
async
def
perform_requests
():
async
with
aiohttp
.
ClientSession
()
as
session
:
tasks
=
[]
for
index
,
data
in
enumerate
(
data_arr
):
tasks
.
append
(
tt_api_obj
.
async_package_invoice_callback_track
(
session
,
data
[
0
],
data
[
1
]))
responses
=
await
asyncio
.
gather
(
*
tasks
)
return
responses
# 在 Odoo 中运行异步任务
responses
=
asyncio
.
run
(
perform_requests
())
for
index
,
response_result
in
enumerate
(
responses
):
package_obj
=
response_result
[
2
]
response_data
=
response_result
[
0
]
# big_obj.message_post(body="推送轨迹揽收", author_id=self.env.user.partner_id.id,
# email_from=self.env.user.partner_id.display_name)
# print(response_data)
# 使用 .get('code') 避免某些异常情况下缺少 'code' 键导致 KeyError
if
response_data
.
get
(
'code'
)
!=
0
:
error_msg_arr
.
append
(
f
"{package_obj.logistic_order_no}发票下载失败:{response_data.get('msg', '')}"
)
_logger
.
error
(
f
"{package_obj.logistic_order_no}发票下载失败:{response_data.get('msg', '')}"
)
else
:
# 获取发票列表
pdf_data_arr
=
response_data
.
get
(
'data'
,
{})
.
get
(
'package_invoice_list'
,
[])
attachment_commands
=
[]
for
pdf_index
,
pdf_data
in
enumerate
(
pdf_data_arr
):
file_code
=
pdf_data
.
get
(
'invoice_file_code'
)
if
file_code
:
# 动态生成附件名称,包含物流单号和索引
file_name
=
f
"{package_obj.logistic_order_no}_invoice_{pdf_index + 1}.pdf"
# 组装 One2many / Many2many 创建指令 (0, 0, values)
attachment_commands
.
append
((
0
,
0
,
{
'name'
:
file_name
,
'type'
:
'binary'
,
'datas'
:
file_code
,
# Base64 文件内容
'res_model'
:
package_obj
.
_name
,
# 绑定当前模型
'res_id'
:
package_obj
.
id
,
# 绑定当前记录 ID
'mimetype'
:
'application/pdf'
,
}))
# 批量写入并关联附件
if
attachment_commands
:
# 如果是覆盖之前的附件,可以把 attachment_commands 改为 [(5, 0, 0)] + attachment_commands
package_obj
.
invoice_attachment_ids
.
sudo
()
.
unlink
()
package_obj
.
write
({
'invoice_attachment_ids'
:
attachment_commands
})
# package_obj.message_post(body="发票下载操作成功", author_id=self.env.user.partner_id.id,
# email_from=self.env.user.partner_id.display_name)
return
error_msg_arr
# 继承提单对象t
class
CcBl
(
models
.
Model
):
...
...
ccs_connect_tiktok/models/tt_api.py
浏览文件 @
c92e3705
...
...
@@ -172,3 +172,17 @@ class TT(models.Model):
"""异步调用提单推送接口"""
# async with semaphore:
return
await
self
.
async_bl_callback_track_callback
(
session
,
data
,
bl_id
)
async
def
async_package_invoice_query
(
self
,
session
,
push_data
,
package_id
):
"""包裹发票下载"""
url
=
'/logistics/provider/customs/package_invoice_query?country=GB'
timestamp
=
int
(
time
.
time
())
sign
=
self
.
generate_sign
(
timestamp
,
push_data
)
response
=
await
self
.
async_get_response
(
session
,
url
,
sign
,
timestamp
,
push_data
)
# logging.info('async_package_invoice_query response:%s' % response)
return
response
,
push_data
,
package_id
async
def
async_package_invoice_callback_track
(
self
,
session
,
data
,
package_id
):
"""异步调用推送接口"""
# async with semaphore:
return
await
self
.
async_package_invoice_query
(
session
,
data
,
package_id
)
ccs_connect_tiktok/views/cc_ship_package_view.xml
浏览文件 @
c92e3705
...
...
@@ -49,6 +49,10 @@
<field
name=
"model"
>
cc.ship.package
</field>
<field
name=
"inherit_id"
ref=
"ccs_base.form_cc_ship_package_view"
/>
<field
name=
"arch"
type=
"xml"
>
<header
position=
"inside"
>
<button
name=
"operate_package_invoice_query"
string=
"获取发票"
type=
"object"
groups=
"ccs_base.group_clearance_of_customs_user"
/>
</header>
<notebook
position=
"inside"
>
<page
string=
"Sync Log"
>
<field
name=
"sync_log_ids"
widget=
"one2many_list"
/>
...
...
@@ -57,4 +61,17 @@
</field>
</record>
<record
id=
"operate_package_invoice_query_server"
model=
"ir.actions.server"
>
<field
name=
"name"
>
批量获取发票
</field>
<field
name=
"model_id"
ref=
"model_cc_ship_package"
/>
<field
name=
"binding_model_id"
ref=
"model_cc_ship_package"
/>
<field
name=
"state"
>
code
</field>
<field
name=
"binding_view_types"
>
list
</field>
<field
name=
"groups_id"
eval=
"[(4, ref('ccs_base.group_clearance_of_customs_user'))]"
/>
<field
name=
"code"
>
if records:
action = records.operate_package_invoice_query()
</field>
</record>
</odoo>
\ No newline at end of file
many2many_attachment_preview/static/src/xml/attachment_preview.xml
浏览文件 @
c92e3705
...
...
@@ -82,13 +82,28 @@
</a>
</div>
</t>
<!-- <t t-if="ext=='pdf'">-->
<!-- <div class="o_image_box float-start"-->
<!-- t-att-data-tooltip="'Download ' + file.name">-->
<!-- <a t-att-href="getUrl(file.id)"-->
<!-- aria-label="Download"-->
<!-- style="cursor: zoom-in;" data-fancybox=""-->
<!-- data-type="iframe">-->
<!-- <span class="o_image o_hover"-->
<!-- t-att-data-mimetype="file.mimetype"-->
<!-- t-att-data-ext="ext" role="img"-->
<!-- t-attf-data-src="/web/content/{{file.id}}"/>-->
<!-- </a>-->
<!-- </div>-->
<!-- </t>-->
<t
t-if=
"ext=='pdf'"
>
<div
class=
"o_image_box float-start"
t-att-data-tooltip=
"'Download ' + file.name"
>
<!-- 移除了 data-fancybox,添加了 target="_blank" -->
<a
t-att-href=
"getUrl(file.id)"
aria-label=
"Download"
style=
"cursor:
zoom-in;"
data-fancybox=
"
"
data-type=
"iframe
"
>
style=
"cursor:
pointer;
"
target=
"_blank
"
>
<span
class=
"o_image o_hover"
t-att-data-mimetype=
"file.mimetype"
t-att-data-ext=
"ext"
role=
"img"
...
...
@@ -112,10 +127,19 @@
</div>
</t>
<!-- <div class="caption">-->
<!-- <a class="ml4"-->
<!-- t-att-data-tooltip="'Download ' + file.name"-->
<!-- t-att-href="getUrl(file.id)">-->
<!-- <t t-esc='file.name'/>-->
<!-- </a>-->
<!-- </div>-->
<div
class=
"caption"
>
<!-- 添加了 target="_blank" -->
<a
class=
"ml4"
t-att-data-tooltip=
"'Download ' + file.name"
t-att-href=
"getUrl(file.id)"
>
t-att-href=
"getUrl(file.id)"
target=
"_blank"
>
<t
t-esc=
'file.name'
/>
</a>
</div>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论