
本文深入探讨了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)
这是一个计算字段,它递归地存储并索引了“商业实体”伙伴。
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 记录类型修改为“公司”可能会破坏现有的联系人层级结构,或者在未来引发其他潜在问题。同时,修改父公司的地址也可能影响到其他业务流程。
潜在解决方案方向:
数据结构优化: 重新评估和调整 res.partner 记录的层级和类型设置,确保送货地址的 commercial_partner_id 始终指向自身或一个真正代表送货点的实体。这可能需要对现有客户数据进行清理和迁移。
报告定制: 如果无法修改底层数据结构,可以考虑定制 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 字段的复杂性,对于解决这类报告显示问题至关重要。
以上就是Odoo 15 送货单地址显示错误问题深度解析与排查的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1373603.html
微信扫一扫
支付宝扫一扫