0

0

Odoo 15 送货单地址显示错误问题深度解析与排查

碧海醫心

碧海醫心

发布时间:2025-09-25 11:13:00

|

991人浏览过

|

来源于php中文网

原创

Odoo 15 送货单地址显示错误问题深度解析与排查

本文深入探讨了Odoo 15送货单有时错误显示客户账单地址而非送货地址的疑难杂症。通过分析report_deliveryslip.xml报告模板和res.partner模型的commercial_partner_id字段逻辑,揭示了根本原因在于送货地址的res.partner记录被设置为“个人”类型且拥有父公司,导致报告误取父公司的商业伙伴地址。文章详细介绍了排查过程、关键代码分析及该问题对数据结构的影响,为理解和解决类似Odoo报告显示问题提供了专业指导。

Odoo 15 送货单地址显示错误问题排查与分析

在odoo 15企业版中,部分用户可能遇到一个棘手的问题:打印送货单时,生成的pdf有时会错误地显示客户的账单地址,而非实际的送货地址。这种现象看似随机发生,给物流和客户沟通带来了困扰。本文将详细解析这一问题的排查过程、根本原因以及其对odoo数据结构的影响。

1. 问题描述与初步排查

问题的核心在于,当为销售订单生成发货单(Delivery Slip)时,PDF报告本应展示正确的送货地址,却意外地显示了与销售订单关联的客户主地址(通常是账单地址)。

初步排查通常从以下几个方面入手:

  • 检查销售订单数据: 确认销售订单(sale.order)上的 partner_id(客户主地址)和 partner_shipping_id(送货地址)是否正确设置。
  • 检查发货单数据: 确认与销售订单关联的发货单(stock.picking)上的 partner_id 是否指向正确的送货地址。
  • Odoo Shell 验证: 利用Odoo Shell进行实时数据查询,验证相关记录的地址信息。

以下是一个Odoo Shell的验证示例,用于检查特定销售订单(S12345)及其相关发货单的地址数据:

# 假设self.env已在Odoo Shell中可用
# 查找销售订单
so = self.env['sale.order'].search([('name', '=', 'S12345')])           

# 销售订单的客户主地址
print(f"SO Partner ID: {so.partner_id}")                                   

# 销售订单的送货地址
print(f"SO Shipping Partner ID: {so.partner_shipping_id}")                 

# 查找与销售订单相关的发货单
pick = self.env['stock.picking'].search([('origin', '=', so.name)])     

# 发货单的关联伙伴ID(通常应是送货地址)
print(f"Picking Partner ID: {pick.partner_id}")                           

# 发货单移动行中的伙伴ID(通常应是送货地址)
print(f"Picking Move Line Partner ID: {pick.move_lines[0].partner_id}") 

# 打印发货单移动行伙伴的完整地址
print(f"Picking Move Line Partner Address:\n{pick.move_lines[0].partner_id._display_address()}")

# 检查是否应该打印送货地址(Odoo内部逻辑)
print(f"Should print delivery address: {pick.should_print_delivery_address()}")

在上述示例中,尽管 pick.partner_id 和 pick.move_lines[0].partner_id 都正确指向了送货地址(YYYYYY),且 pick.should_print_delivery_address() 返回 True,但生成的PDF报告仍可能显示错误的地址。这表明问题可能出在报告模板的渲染逻辑上。

2. 深入分析报告模板:report_deliveryslip.xml

Odoo的送货单报告模板位于 stock 模块的 report_deliveryslip.xml 文件中。仔细分析该文件是解决问题的关键。

2.1 误导性的“发货地址”区域

在 report_deliveryslip.xml 中,存在一个名为 div_outgoing_address 的 块,其代码片段如下:


    
Delivery Address:
Warehouse Address:

这个区域虽然包含了 Delivery Address 的字样,但其作用是定义发货方的地址,即仓库或公司自己的地址,而不是收货方的送货地址。这是最初排查时容易产生混淆的地方。

2.2 真正的客户地址渲染逻辑

真正用于渲染客户地址(包括送货地址和账单地址)的逻辑位于另一个名为 information_block 的 块中,具体在 div_incoming_address 部分:


    
Vendor Address:
Customer Address:

:

请注意其中的关键行:

Customer Address:

以及后续用于显示地址的:

这里的问题在于,当 o.picking_type_id.code=='outgoing'(即发货单)时,Odoo会检查 partner != partner.commercial_partner_id 这个条件。如果这个条件为 True,它就会显示 Customer Address,并且最重要的是,它会显示 partner.commercial_partner_id 的地址,而不是 partner 本身的地址。

3. 根本原因:res.partner 的 commercial_partner_id 字段

为了理解 partner != partner.commercial_partner_id 为 True 的含义,我们需要检查 res.partner 模型中的 commercial_partner_id 字段定义及其计算方法。

3.1 commercial_partner_id 字段定义

commercial_partner_id 字段定义如下:

commercial_partner_id = fields.Many2one('res.partner', string='Commercial Entity',
                                        compute='_compute_commercial_partner', recursive=True,
                                        store=True, index=True)

这是一个计算字段,它递归地存储并索引了“商业实体”伙伴。

酷兔AI论文
酷兔AI论文

专业原创高质量、低查重,免费论文大纲,在线AI生成原创论文,AI辅助生成论文的神器!

下载

3.2 _compute_commercial_partner 计算方法

commercial_partner_id 的计算逻辑在 _compute_commercial_partner 方法中:

@api.depends('is_company', 'parent_id.commercial_partner_id')
def _compute_commercial_partner(self):
    for partner in self:
        if partner.is_company or not partner.parent_id:
            partner.commercial_partner_id = partner
        else:
            partner.commercial_partner_id = partner.parent_id.commercial_partner_id

这个方法的逻辑是:

  • 如果一个 res.partner 记录是公司(is_company 为 True)或者它没有父级(parent_id 为 False),那么它的 commercial_partner_id 就是它自己。
  • 否则(如果它不是公司且有父级),它的 commercial_partner_id 将是其父级伙伴的 commercial_partner_id。

3.3 问题症结

结合报告模板和 commercial_partner_id 的逻辑,问题的原因浮出水面:

当送货地址的 res.partner 记录被设置为“个人”类型(is_company 为 False),并且它有一个父公司(parent_id 已设置)时,根据 _compute_commercial_partner 方法,该送货地址记录的 commercial_partner_id 将会指向其父公司的 commercial_partner_id(通常是父公司本身)。

在这种情况下,对于送货地址 partner 而言,partner != partner.commercial_partner_id 条件将为 True。报告模板因此会渲染 partner.commercial_partner_id 的地址,这实际上是父公司的地址,而不是送货地址本身的地址。父公司的地址通常被用作账单地址,这就解释了为什么送货单上会错误地显示客户的账单地址。

4. 结论与潜在解决方案

根本原因: 送货地址的 res.partner 记录被配置为“个人”类型,并且拥有一个父公司,导致其 commercial_partner_id 字段指向了父公司(通常是账单地址)。Odoo发货单报告在特定条件下会优先显示 commercial_partner_id 的地址,从而引发了地址显示错误。

挑战: 尽管根本原因已查明,但如何优雅地解决这一问题仍需进一步探讨。直接将送货地址的 res.partner 记录类型修改为“公司”可能会破坏现有的联系人层级结构,或者在未来引发其他潜在问题。同时,修改父公司的地址也可能影响到其他业务流程。

潜在解决方案方向:

  1. 数据结构优化: 重新评估和调整 res.partner 记录的层级和类型设置,确保送货地址的 commercial_partner_id 始终指向自身或一个真正代表送货点的实体。这可能需要对现有客户数据进行清理和迁移。

  2. 报告定制: 如果无法修改底层数据结构,可以考虑定制 report_deliveryslip.xml 报告模板。修改 div_incoming_address 部分的逻辑,使其在发货单(outgoing)类型下,无论 partner.commercial_partner_id 是否与 partner 相同,都强制显示 partner(即 o.partner_id 或 o.move_lines[0].partner_id)的地址,而不是 partner.commercial_partner_id 的地址。

    例如,可以修改相关部分,直接引用发货单上的 partner_id:

    Delivery Address:

    或者更准确地使用 o.move_lines[0].partner_id,因为它通常代表了具体的送货伙伴。

在实施任何解决方案之前,务必在测试环境中进行充分的验证,以确保不会引入新的问题。理解Odoo的伙伴(res.partner)模型及其 commercial_partner_id 字段的复杂性,对于解决这类报告显示问题至关重要。

相关专题

更多
pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1893

2024.04.01

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

2087

2024.08.01

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

1028

2024.11.28

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

536

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

21

2026.01.06

Java编译相关教程合集
Java编译相关教程合集

本专题整合了Java编译相关教程,阅读专题下面的文章了解更多详细内容。

11

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

4

2026.01.21

无人机驾驶证报考 uom民用无人机综合管理平台官网
无人机驾驶证报考 uom民用无人机综合管理平台官网

无人机驾驶证(CAAC执照)报考需年满16周岁,初中以上学历,身体健康(矫正视力1.0以上,无严重疾病),且无犯罪记录。个人需通过民航局授权的训练机构报名,经理论(法规、原理)、模拟飞行、实操(GPS/姿态模式)及地面站训练后考试合格,通常15-25天拿证。

16

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 4万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号