Power BI + Odoo 集成完整指南

将 Power BI 连接到 Odoo ERP 以进行高级分析。 PostgreSQL 直接查询、关键表、销售/库存/HR 仪表板和增量刷新设置。

E
ECOSIRE Research and Development Team
|2026年3月17日11 分钟阅读2.4k 字数|

属于我们的Data Analytics & BI系列

阅读完整指南

Power BI + Odoo 集成完整指南

Odoo 是世界上最强大的开源 ERP 平台之一,拥有超过 1200 万用户和 43 个官方模块,涵盖从销售和库存到制造和人力资源的各个方面。 Power BI 是业界领先的商业智能平台,每月活跃用户超过 3 亿。然而令人惊讶的是,很少有组织将这两个系统连接起来,从而留下了巨大的分析价值。

原因很简单:Odoo 有自己的内置报告,大多数 Power BI 咨询公司都专注于 Microsoft Dynamics、SAP 或 Salesforce 集成。很少有公司在这两个平台上拥有深厚的专业知识。在 ECOSIRE,我们构建并部署了超过 43 个 Odoo 模块,并保持深厚的 Power BI 专业知识,使 Odoo + Power BI 组合成为我们的核心专业之一。本指南总结了我们从数十个现实世界集成中学到的所有知识。


要点

  • Odoo 的 PostgreSQL 数据库可以使用本机 PostgreSQL 连接器直接连接到 Power BI Desktop,让您可以完全访问每个表和字段
  • 用于分析的五个最有价值的 Odoo 表是 sale_order、account_move、stock_picking、hr_employee 和 mrp_product --- 它们总共满足了 80% 的执行报告需求
  • Power BI 中的增量刷新仅获取自上次刷新以来更改的记录,可以将 Odoo 数据加载时间从几小时缩短至几分钟
  • 当直接数据库访问不可用时,OData 端点和 Odoo 的外部 API 提供云友好的替代方案
  • Power BI 中的行级安全性可以反映 Odoo 的多公司访问控制,确保用户只能看到来自其指定公司的数据
  • 针对 Odoo 的 PostgreSQL 数据库的自定义 SQL 查询的性能比通用表导入高 5-10 倍,因为您可以在数据库级别进行过滤、联接和聚合
  • 精心设计的 Odoo + Power BI 部署用单个受管理的分析平台取代了数十个电子表格报告

为什么 Odoo + Power BI 是一个强大的组合

Odoo 内置报告的局限性

Odoo 附带了多种报告工具:透视视图、图形视图和内置仪表板。对于日常操作来说,这些已经足够了。但它们在几个关键方面无法满足企业分析的要求。

首先,Odoo 的数据透视视图无法将来自多个模块的数据组合到单个可视化中。您无法在一张图表中将销售收入与库存周转率和制造吞吐量叠加起来。每个模块的报告都是孤立的。

其次,Odoo 缺乏时间智能功能。同比比较、滚动平均值、累计总计和迄今为止的计算需要定制开发或手动电子表格导出。

第三,Odoo 没有受控数据模型的概念。对于“收入”或“客户生命周期价值”等指标没有共同的定义。每个用户都会创建自己的解释,从而导致管理会议中出现数字冲突。

第四,Odoo的可视化功能仅限于基本的条形图、折线图和饼图。热图、散点图、瀑布图、分解树和 KPI 卡不可用。

Power BI 添加了什么

Power BI 解决了所有这些限制。它连接到 Odoo 的 PostgreSQL 数据库(或 API)并跨所有模块创建统一的语义模型。 DAX 公式提供时间智能、统计函数和复杂的业务逻辑。可视化库包含 300 多种图表类型。 Power BI 的治理功能(工作区、行级安全性、认可、敏感度标签)提供企业级数据管理。

这一组合为您提供了 Odoo 日常工作的卓越运营能力和 Power BI 战略决策的深度分析能力。运营团队继续在 Odoo 工作;管理人员和分析师可以获得自动更新的 Power BI 仪表板。


连接方法:直接数据库与 API

将 Power BI 连接到 Odoo 的主要方法有三种。根据您的托管模型和安全要求,每种方案都需要权衡。

方法1:直接连接PostgreSQL

这是本地或自托管 Odoo 部署的首选方法。 Odoo 将所有数据存储在 PostgreSQL 中,而 Power BI 具有本机 PostgreSQL 连接器。

优点:

  • 最快的查询性能(无 API 开销)
  • 完全访问每个表和字段,包括自定义模块
  • 支持复杂的 SQL 查询,在数据库级别进行连接和聚合
  • 启用增量刷新(需要日期时间列)
  • 无 Odoo 许可证或 API 速率限制

设置步骤:

  1. 打开 Power BI Desktop 并选择获取数据,然后选择 PostgreSQL 数据库
  2. 输入您的 Odoo 服务器主机名和数据库名称(通常是 Odoo 实例名称) 3.使用只读数据库用户(绝不是Odoo管理员帐户)
  3. 大部分场景选择Import模式,或者实时需求选择DirectQuery
  4. 导航表列表或使用自定义 SQL 查询

连接字符串参数:

参数典型值
服务器your-odoo-server.com:5432
数据库odoo_生产
用户名powerbi_readonly
密码(存储在凭证中)
SSL 模式需要(用于生产)
命令超时600(秒,对于大型查询)

在 PostgreSQL 中创建只读用户:

CREATE ROLE powerbi_readonly WITH LOGIN PASSWORD 'secure_password';
GRANT CONNECT ON DATABASE odoo_production TO powerbi_readonly;
GRANT USAGE ON SCHEMA public TO powerbi_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO powerbi_readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO powerbi_readonly;

此方法可确保 Power BI 可以读取所有当前和未来的表,而无需对生产数据库进行任何写入访问。

方法 2:Odoo 外部 API (XML-RPC / JSON-RPC)

Odoo 公开了用于读取和写入数据的完整 API。 Power BI 可以通过自定义连接器或 Python 脚本使用它。

优点:

  • 可与 Odoo.sh 和 Odoo Online 配合使用(无需直接访问数据库)
  • 尊重Odoo的访问控制规则和记录规则
  • 无需对外暴露数据库端口

缺点:

  • 比直接数据库查询慢得多(大型数据集慢10-100倍)
  • API 速率限制可能会限制大容量提取
  • 需要自定义 Power Query 函数或中间 ETL 步骤
  • 分页增加了复杂性

对于 Odoo 的 JSON-RPC 端点,典型的 Power Query M 函数将调用 https://your-odoo.com/jsonrpc 进行身份验证,然后对结果进行分页。这可行,但对于包含超过 50,000 条记录的表来说变得不切实际。

方法 3:通过 Odoo 连接器模块的 OData 端点

多个 Odoo 社区模块公开了 Power BI 可以本机使用的 OData 源。 Power BI 中的 OData 连接器支持开箱即用的身份验证和分页。

何时使用此方法:

  • 数据库访问受到限制的 Odoo Online / Odoo.sh 部署
  • 数据中需要 Odoo 业务逻辑(计算字段、访问规则)的场景
  • 较小的数据集(每个实体少于 100,000 条记录)

对于大多数企业部署,强烈建议使用方法 1(直接 PostgreSQL)。性能差异很大,而且 SQL 查询的灵活性允许您在源头调整数据。


Power BI 的基本 Odoo 表

Odoo 的 PostgreSQL 数据库包含数百个表。了解核心表及其关系对于构建有效的 Power BI 模型至关重要。下面是为 80% 的执行仪表板提供支持的表格。

销售模块表

目的关键领域
销售订单销售订单(标题)id、名称、partner_id、date_order、amount_total、state、company_id、user_id
销售订单行销售订单行项目order_id、product_id、product_uom_qty、price_unit、price_subtotal、折扣
资源合作伙伴客户和供应商id、姓名、电子邮件、country_id、category_id、customer_rank、supplier_rank
产品_产品产品型号id、default_code、list_price、standard_price、categ_id、活动
产品模板产品模板id、名称、类型、sale_ok、purchase_ok

关键关系: sale_order.partner_id 链接到 res_partner.id。 sale_order_line.product_id 链接到product_product.id。 Product_product.product_tmpl_id 链接到product_template.id。

典型的销售分析查询连接这些表以生成非规范化事实表:

SELECT
  so.id AS order_id,
  so.name AS order_number,
  so.date_order,
  so.state,
  rp.name AS customer_name,
  rp.country_id,
  rc.name AS country_name,
  sol.product_id,
  pt.name AS product_name,
  pc.name AS product_category,
  sol.product_uom_qty AS quantity,
  sol.price_unit,
  sol.discount,
  sol.price_subtotal AS line_total,
  so.amount_total AS order_total,
  ru.login AS salesperson
FROM sale_order so
JOIN sale_order_line sol ON sol.order_id = so.id
JOIN res_partner rp ON so.partner_id = rp.id
LEFT JOIN res_country rc ON rp.country_id = rc.id
JOIN product_product pp ON sol.product_id = pp.id
JOIN product_template pt ON pp.product_tmpl_id = pt.id
LEFT JOIN product_category pc ON pt.categ_id = pc.id
LEFT JOIN res_users ru ON so.user_id = ru.id
WHERE so.state IN ('sale', 'done')
ORDER BY so.date_order DESC;

会计模块表

目的关键领域
帐户移动发票、账单、日记账分录id、名称、move_type、partner_id、invoice_date、amount_total、state、 payment_state
账户移动行日记条目行move_id、account_id、借方、贷方、余额、日期、partner_id
帐户_帐户会计科目表ID、代码、姓名、帐户类型
账户付款付款id、partner_id、金额、日期、状态、付款类型
账户日记期刊(银行、销售等)ID、名称、类型、代码

关键区别: 在 Odoo 中,account_move 存储发票 (move_type = 'out_invoice')、供应商账单 ('in_invoice')、贷方票据 ('out_refund'、'in_refund') 和日记帐分录 ('entry')。始终在 Power BI 查询中按 move_type 进行筛选。

account_move 上的 payment_state 字段告诉您发票是否为“未付款”、“付款中”、“已付款”、“部分”或“已冲销”。这对于应收账款账龄仪表板至关重要。

库存模块表

目的关键领域
选股交货单、收据、内部转账id、姓名、partner_id、scheduled_date、date_done、state、picking_type_id
库存移动个别产品动向Picking_id、product_id、product_uom_qty、数量、状态、日期
股票量化目前现有库存产品 ID、位置 ID、数量、保留数量
库存位置仓库、区域、垃圾箱id、名称、用途、location_id(父级)
库存仓库仓库定义ID、姓名、代码、partner_id

实时库存: stock_quant 始终反映库存的当前状态。对于历史库存分析,您需要使用日期过滤器查询 stock_move 并计算运行余额。

制造模块表

目的关键领域
mrp_生产制造订单id、名称、product_id、product_qty、date_start、date_finished、状态
mrp_bom物料清单id、product_tmpl_id、product_qty、类型
mrp_bom_lineBOM 组件bom_id、产品_id、产品_数量
mrp_workorder工单操作生产_id、工作中心_id、持续时间、状态
mrp_工作中心工作中心/机器id、名称、容量、时间效率

OEE 计算: 通过将计划工期与实际工期进行比较、分析停机原因并跟踪质量指标,可以从 mrp_workorder 记录中导出总体设备效率。

人力资源表

目的关键领域
人力资源员工员工记录id、姓名、部门 ID、工作 ID、工作电子邮件、活动
人力资源部门部门id、姓名、parent_id、manager_id
人力资源合同雇佣合同员工 ID、工资、开始日期、结束日期、州
人力资源休假休假请求员工 ID、假期状态 ID、起始日期、截止日期、州
人力资源出勤打卡上下班记录员工 ID、签到、签出、工作时间

构建 Power BI 数据模型

星型架构设计

Odoo 分析最有效的数据模型遵循星型模式模式。事实表(销售订单、发票、库存移动、生产订单)位于中心。维度表(产品、客户、日期、员工、位置)围绕着它们。

推荐的事实表:

  1. Fact_Sales — 来自 sale_order + sale_order_line (粒度:每个订单行一行)
  2. Fact_Invoices — 来自 account_move + account_move_line (粒度:每个日记帐行一行)
  3. Fact_Inventory — 来自 stock_move(颗粒:每次库存变动一行)
  4. Fact_Production — 来自 mrp_product + mrp_workorder (粒度:每个工单一行)
  5. Fact_Attendance — 来自 hr_attendance(粒度:每个时钟输入/输出对一行)

共享维度表:

  1. Dim_Date — Power BI 中生成的日历表(对于时间智能至关重要)
  2. Dim_Customer — 来自 res_partner(过滤至 customer_rank > 0)
  3. Dim_Product — 来自产品产品 + 产品模板 + 产品类别
  4. Dim_Employee — 来自 hr_employee + hr_department + hr_job
  5. Dim_Location — 来自 stock_location + stock_warehouse
  6. Dim_Company — 来自 res_company(用于多公司 Odoo 部署)

创建日期维度

Odoo 没有专用的日期维度表。您必须使用 DAX 在 Power BI 中创建一个:

Dim_Date =
ADDCOLUMNS(
    CALENDAR(DATE(2020, 1, 1), DATE(2030, 12, 31)),
    "Year", YEAR([Date]),
    "Quarter", "Q" & QUARTER([Date]),
    "Month", FORMAT([Date], "MMMM"),
    "MonthNumber", MONTH([Date]),
    "WeekNumber", WEEKNUM([Date]),
    "DayOfWeek", FORMAT([Date], "dddd"),
    "FiscalYear", IF(MONTH([Date]) >= 4, YEAR([Date]), YEAR([Date]) - 1),
    "FiscalQuarter", "FQ" & SWITCH(TRUE(),
        MONTH([Date]) >= 10, 3,
        MONTH([Date]) >= 7, 2,
        MONTH([Date]) >= 4, 1,
        4
    ),
    "IsWeekend", IF(WEEKDAY([Date], 2) > 5, TRUE(), FALSE()),
    "YearMonth", FORMAT([Date], "YYYY-MM")
)

将此表标记为 Power BI 中的日期表,并创建从每个事实表的日期列到 Dim_Date[Date] 的关系。调整会计年度开始月份以匹配您的组织。

处理 Odoo 的多公司结构

Odoo 支持多公司配置,其中单个数据库为多个法人实体提供服务。每个事务表都包含一个 company_id 外键。在 Power BI 中,从 res_company 创建 Dim_Company 表并建立与每个事实表的关系。

对于行级安全性,请使用 Power BI 的 RLS 功能根据登录用户的公司分配筛选 Dim_Company。这反映了 Odoo 在 BI 层的多公司访问控制。


仪表板秘诀:销售分析

执行销售仪表板

该仪表板回答了每位首席执行官都会问的五个问题:本月收入是多少?本季度我们进展顺利吗?哪些产品获胜?哪些销售人员表现出色?我们的客户在哪里?

创建措施:

Total Revenue = SUM(Fact_Sales[line_total])

Revenue MTD =
TOTALMTD([Total Revenue], Dim_Date[Date])

Revenue QTD =
TOTALQTD([Total Revenue], Dim_Date[Date])

Revenue YTD =
TOTALYTD([Total Revenue], Dim_Date[Date])

Revenue PY =
CALCULATE([Total Revenue], SAMEPERIODLASTYEAR(Dim_Date[Date]))

Revenue Growth % =
DIVIDE([Total Revenue] - [Revenue PY], [Revenue PY], 0)

Average Order Value =
DIVIDE([Total Revenue], DISTINCTCOUNT(Fact_Sales[order_id]))

Orders Count =
DISTINCTCOUNT(Fact_Sales[order_id])

视觉布局:

  • 第 1 行:四张 KPI 卡(MTD 收入、QTD 收入、YTD 收入、增长率)
  • 第 2 行:折线图(月收入、本年度与上一年相比)和条形图(按产品类别划分的收入)
  • 第 3 行:地图视觉效果(按客户国家/地区划分的收入)和表格(前 10 名销售人员的收入、订单数、平均交易规模)
  • 第 4 行:瀑布图(收入桥梁:新客户、现有客户、流失客户)和圆环图(按销售渠道划分的收入)

销售渠道分析

如果您将 Odoo CRM 与销售模块一起使用,请连接 crm_lead 表来构建管道仪表板:

目的关键领域
客户关系管理领导机会和线索id、名称、partner_id、expected_revenue、概率、stage_id、user_id、date_deadline
客户关系管理阶段管道阶段id、名称、序列

管道措施:

Pipeline Value =
SUMX(
    FILTER(Fact_Pipeline, Fact_Pipeline[active] = TRUE()),
    Fact_Pipeline[expected_revenue] * Fact_Pipeline[probability] / 100
)

Win Rate =
DIVIDE(
    CALCULATE(COUNTROWS(Fact_Pipeline), Fact_Pipeline[stage_name] = "Won"),
    CALCULATE(COUNTROWS(Fact_Pipeline),
        OR(Fact_Pipeline[stage_name] = "Won", Fact_Pipeline[stage_name] = "Lost")
    )
)

Average Sales Cycle Days =
AVERAGEX(
    FILTER(Fact_Pipeline, Fact_Pipeline[stage_name] = "Won"),
    DATEDIFF(Fact_Pipeline[create_date], Fact_Pipeline[date_closed], DAY)
)

仪表板秘诀:库存和供应链

库存健康仪表板

该仪表板监控库存水平、周转率和供应链绩效。

主要措施:

Inventory Value =
SUMX(Fact_Inventory_Current, Fact_Inventory_Current[quantity] * RELATED(Dim_Product[standard_price]))

Inventory Turnover =
DIVIDE(
    [COGS Trailing 12 Months],
    [Average Inventory Value]
)

Days of Inventory =
DIVIDE(365, [Inventory Turnover])

Stockout Rate =
DIVIDE(
    CALCULATE(COUNTROWS(Dim_Product), Dim_Product[on_hand_qty] <= 0, Dim_Product[active] = TRUE()),
    CALCULATE(COUNTROWS(Dim_Product), Dim_Product[active] = TRUE())
)

Reorder Point Items =
CALCULATE(
    COUNTROWS(Dim_Product),
    FILTER(Dim_Product, Dim_Product[on_hand_qty] <= Dim_Product[reorder_min])
)

视觉效果:

  • KPI卡:库存总额、周转率、缺货率、低于再订购点的商品
  • 散点图:按周转率(x 轴)与利润率(y 轴)绘制每种产品,按收入贡献确定大小 --- 这是 ABC-XYZ 分析视觉效果
  • 条形图:按库存价值排名前 20 名的产品(识别滞销库存中占用的资金)
  • 表:低于再订购点的商品以及当前库存、每日需求和预计缺货日期

交付绩效

stock_picking 开始,衡量按时交货:

On-Time Delivery Rate =
DIVIDE(
    CALCULATE(
        COUNTROWS(Fact_Deliveries),
        Fact_Deliveries[date_done] <= Fact_Deliveries[scheduled_date]
    ),
    COUNTROWS(Fact_Deliveries)
)

Average Lead Time Days =
AVERAGEX(
    Fact_Deliveries,
    DATEDIFF(Fact_Deliveries[create_date], Fact_Deliveries[date_done], DAY)
)

仪表板配方:制造

生产绩效仪表板

对于运行 Odoo Manufacturing 的制造商,mrp_product 和 mrp_workorder 表提供了丰富的运营数据。

OEE(整体设备效率)计算:

Availability =
DIVIDE(
    [Actual Production Time],
    [Planned Production Time]
)

Performance Rate =
DIVIDE(
    [Ideal Cycle Time] * [Total Units Produced],
    [Actual Production Time]
)

Quality Rate =
DIVIDE(
    [Good Units],
    [Total Units Produced]
)

OEE = [Availability] * [Performance Rate] * [Quality Rate]

视觉效果:

  • 仪表图表:OEE、可用性、性能、质量(每个图表都有目标阈值:绿色高于 85%,黄色为 60-85%,红色低于 60%)
  • 折线图:每周 OEE 趋势,带有控制限制
  • 簇状条形图:按工作中心划分的 OEE,揭示哪些机器表现不佳
  • 表:包含计划工期与实际工期、差异和报废数量的生产订单

工作中心利用率

Utilization Rate =
DIVIDE(
    SUM(Fact_WorkOrders[duration_minutes]),
    [Available Minutes Per Period]
)

Downtime Hours =
DIVIDE(
    [Available Minutes Per Period] - SUM(Fact_WorkOrders[duration_minutes]),
    60
)

该仪表板可帮助生产经理识别瓶颈工作中心并优化调度。与 Odoo 的规划模块数据相结合,您可以构建容量规划模型来预测何时达到最大利用率。


仪表板秘诀:人力资源和劳动力

劳动力分析仪表板

根据 Odoo 数据构建的 HR 仪表板提供了大多数 HRIS 系统收取高价的见解。

员工人数和营业额衡量标准:

Active Employees =
CALCULATE(
    COUNTROWS(Dim_Employee),
    Dim_Employee[active] = TRUE()
)

Attrition Rate =
DIVIDE(
    CALCULATE(
        COUNTROWS(Dim_Employee),
        Dim_Employee[departure_date] <> BLANK(),
        YEAR(Dim_Employee[departure_date]) = YEAR(TODAY())
    ),
    [Average Headcount],
    0
)

Average Tenure Years =
AVERAGEX(
    FILTER(Dim_Employee, Dim_Employee[active] = TRUE()),
    DATEDIFF(Dim_Employee[contract_start_date], TODAY(), DAY) / 365.25
)

Cost Per Employee =
DIVIDE(
    SUM(Fact_Payroll[total_cost]),
    [Active Employees]
)

来自 hr_leave 的缺勤分析:

Absence Rate =
DIVIDE(
    SUM(Fact_Leaves[number_of_days]),
    [Working Days In Period] * [Active Employees]
)

Bradford Factor =
SUMX(
    Dim_Employee,
    VAR AbsenceSpells = CALCULATE(COUNTROWS(Fact_Leaves), Fact_Leaves[state] = "validate")
    VAR TotalDays = CALCULATE(SUM(Fact_Leaves[number_of_days]), Fact_Leaves[state] = "validate")
    RETURN AbsenceSpells * AbsenceSpells * TotalDays
)

来自 hr_attendance 的出勤分析:

Average Daily Hours =
AVERAGEX(
    VALUES(Dim_Date[Date]),
    CALCULATE(SUM(Fact_Attendance[worked_hours]))
)

Overtime Hours =
SUMX(
    Fact_Attendance,
    IF(Fact_Attendance[worked_hours] > 8, Fact_Attendance[worked_hours] - 8, 0)
)

增量刷新配置

对于拥有数百万条记录的 Odoo 数据库,完整的数据刷新是不切实际的。 Power BI 的增量刷新功能仅加载新的和更改的记录,将刷新时间从几小时缩短到几分钟。

先决条件

  • Power BI Pro 或 Premium 许可证
  • 每个表必须有一个可靠的日期时间列(Odoo 中的 write_date 是理想的——每当修改记录时它就会更新)
  • 数据源必须支持查询折叠(PostgreSQL支持)

配置步骤

步骤 1:创建 RangeStart 和 RangeEnd 参数

在 Power Query 中,创建两个 DateTime 类型的参数:

  • RangeStart:默认值 = 1/1/2020 12:00:00 AM
  • RangeEnd:默认值 = 12/31/2030 12:00:00 AM

步骤 2:按参数过滤表

对于每个事实表,在 Power Query 中添加一个筛选步骤:

= Table.SelectRows(Source, each [write_date] >= RangeStart and [write_date] < RangeEnd)

此过滤器必须折叠到数据库(出现在生成的 SQL 中)。通过右键单击该步骤并选择“查看本机查询”进行验证。

步骤3:定义增量刷新策略

右键单击模型中的表,选择增量刷新,然后配置:

设置推荐值
将行存储在最后3 年
刷新最后的行7 天
检测数据变化write_date 列
仅刷新完整周期已启用

此配置存储三年的历史记录,但在每次计划刷新期间仅刷新最近 7 天。当记录上的任何字段发生更改时,Odoo 的 write_date 列会自动更新,使其成为可靠的更改检测列。

性能影响

场景全面刷新增量刷新
100 万销售订单行12 分钟45 秒
500 万条日记条目38 分钟2 分钟
1000 万股股票变动65 分钟4 分钟

性能提升非常显着,特别是对于生成大量事务数据的制造和库存数据集。


高级:多公司和多货币

处理多公司 Odoo 部署

许多 Odoo Enterprise 部署通过单个数据库为多个法律实体提供服务。每个事务记录都有一个 company_id 字段。在 Power BI 中:

  1. res_company 创建一个 Dim_Company
  2. 建立每个事实表的company_id到Dim_Company的关系 3.为每个仪表板页面添加公司切片器
  3. 实施行级安全性,以便每个用户只能看到其公司的数据

货币换算

Odoo 以公司的基础货币存储金额。对于多货币报告,请加入 res_currency_rate 表:

SELECT
  so.id,
  so.amount_total AS amount_local,
  so.amount_total / COALESCE(
    (SELECT rate FROM res_currency_rate
     WHERE currency_id = so.currency_id
     AND name <= so.date_order::date
     ORDER BY name DESC LIMIT 1),
    1
  ) AS amount_usd
FROM sale_order so;

或者,在 Power BI 中维护包含每日汇率的 Dim_Currency_Rate 表,并在报告时使用 DAX 进行转换。这种方法对于假设场景更加灵活(例如,“按去年的汇率计算收入会是什么样?”)。


Odoo Online 的 OData 和 REST API 集成

对于使用 Odoo Online 或 Odoo.sh 且无法直接访问 PostgreSQL 的组织,还有其他连接方法。

使用 Odoo 的 JSON-RPC API

Odoo 在 /jsonrpc 处公开 JSON-RPC 端点(或在 /xmlrpc/2 处较旧的 XML-RPC)。您可以调用 search_read 方法来获取数据:

{
  "jsonrpc": "2.0",
  "method": "call",
  "params": {
    "service": "object",
    "method": "execute_kw",
    "args": [
      "your_database",
      2,
      "your_api_key",
      "sale.order",
      "search_read",
      [[["state", "in", ["sale", "done"]]]],
      {"fields": ["name", "partner_id", "date_order", "amount_total", "state"],
       "limit": 1000, "offset": 0}
    ]
  }
}

在 Power BI 中,您可以使用 Web.Contents 和分页逻辑将其实现为自定义 Power Query 函数。挑战在于性能:每个 API 调用最多返回几千条记录,并且对于大型数据集,您需要多次往返。

社区 OData 模块

多个 Odoo 社区模块添加了 OData 端点:

  • Odoo 的 BI 连接器 — 公开可配置的 OData 源
  • Odoo-Power BI 连接器 — 常见模块的预构建数据模型

这些模块简化了集成,但添加了对 Odoo 实例的依赖项。评估社区模块的便利性是否超过维护负担。

混合方法:计划数据导出

务实的中间立场是安排每晚将数据从 Odoo 导出到临时数据库或 Azure SQL。 Odoo 计划操作运行一个 Python 脚本,将关键表导出到 CSV 或通过 API 将数据推送到 Azure SQL 数据库。然后,Power BI 连接到具有完整查询折叠支持的临时数据库。

这种方法非常适合那些希望获得近乎每日的数据新鲜度而又无需将 Odoo 的生产数据库暴露给 Power BI 查询的组织。


真实的 KPI 示例

以下是 ECOSIRE 客户在将 Odoo 连接到 Power BI 后经常构建的 20 个 KPI(按部门整理)。

财务 KPI

  1. 应收账款天数 (DSO) — 从 account_move 开始收取付款的平均天数(发票日期与付款日期)
  2. 毛利率% — 收入减去销货成本除以收入,来自 sale_order_line(价格小计与产品标准价格)
  3. 现金转换周期 — DSO + 库存未清天数 - 应付账款周转天数
  4. 预算与实际差异 — 需要预算表(Odoo 中的 account_budget 或手动上传)
  5. 每位员工的收入 — 总收入除以活跃员工人数

销售关键绩效指标

  1. 客户获取成本 — 营销支出除以获取的新客户(需要手动输入营销成本)
  2. 客户终身价值 — 每个客户的平均收入乘以平均关系长度
  3. 销售周期长度 — 从创造机会到赢得机会的天数 (crm_lead)
  4. 报价到订单转化率 — 已确认订单除以总报价
  5. 平均折扣 % — 来自 sale_order_line 折扣字段

运营 KPI

  1. 完美订单率 — 订单按时、全额交付,并附有正确的文件
  2. 库存准确性 — 实际数量与系统数量(来自 stock_quant 调整)
  3. 供应商交货期可靠性 — 实际收货日期与采购订单的预期日期
  4. 仓库空间利用率 — 占用位置除以总位置
  5. 退货率 — 贷项票据/退款占总销售额的百分比

制造 KPI

  1. 首次合格率 — 通过质量检验而无需返工的单位数除以总单位数
  2. 遵守计划 — 生产订单在计划日期完成
  3. 材料浪费% — 消耗的原材料超出 BOM 要求
  4. 工作中心利用率 — 实际生产时间与可用时间
  5. 平均故障间隔时间 (MTBF) — 设备故障之间的平均运行时间

其中每个 KPI 都需要特定的表连接和 DAX 逻辑。 ECOSIRE 的 Power BI 实施服务 包括一个标准 KPI 库,其中包含针对所有 20 个指标的预构建度量。


性能优化

查询折叠

查询折叠是 Odoo + Power BI 集成最重要的性能概念。当 Power Query“折叠”转换时,它会将步骤转换为 SQL 并在 PostgreSQL 服务器上而不是在 Power BI 引擎中执行。

折叠步骤:

  • Table.SelectRows(WHERE 子句)
  • Table.SelectColumns(选择特定列)
  • 表.排序(ORDER BY)
  • 表.组(GROUP BY)
  • 表.连接(JOIN)
  • 表.FirstN (LIMIT)

打破折叠的步骤:

  • Table.AddColumn 具有自定义 M 函数
  • 表.缓冲区
  • Table.Pivot / Table.Unpivot(大多数情况下)
  • 任何引用不可折叠的先前步骤的步骤

最佳实践: 编写自定义 SQL 查询,而不是依赖 Power Query 折叠。这使您可以完全控制发送到 PostgreSQL 的 SQL 并消除折叠的不确定性。

导入与 DirectQuery

因素导入模式直接查询
性能快速(数据缓存在本地)速度较慢(实时查询 Odoo DB)
数据新鲜度预定刷新(最少 30 分钟)实时
型号尺寸受内存限制(1 GB 免费,10-100 GB 高级)无尺寸限制
DAX 支持完整有限(部分功能不可用)
对 Odoo 的影响刷新后无每个报表交互都会查询数据库
推荐适用于大多数场景仅在必须实时时才使用

对于大多数 Odoo 部署,具有增量刷新的导入模式可提供性能和新鲜度的最佳平衡。 DirectQuery 应保留用于不可接受 30 分钟旧数据的操作仪表板(例如,现场生产车间显示)。

复合模型

Power BI Premium 支持组合导入和 DirectQuery 表的复合模型。这是 Odoo 集成的理想选择,其中:

  • 大型历史表(销售订单、日记帐分录)使用增量刷新的导入模式
  • 小型、快速变化的表(实时库存的 stock_quant)使用 DirectQuery
  • 日期维度和其他维度使用双存储模式

常见问题故障排除

连接错误

“无法连接到服务器” — 验证 PostgreSQL 正在侦听正确的端口(默认 5432),并且防火墙规则允许来自 Power BI 网关或桌面 IP 的入站连接。检查 postgresql.conf 中的 listen_addressespg_hba.conf 中的客户端身份验证规则。

“需要 SSL 连接” — 将 sslmode=require 添加到连接中。对于自签名证书,您可能需要导入 CA 证书或设置 sslmode=allow (不建议用于生产)。

“表的权限被拒绝” — Power BI 数据库用户缺乏 SELECT 权限。运行 GRANT SELECT ON ALL TABLES IN SCHEMA public TO powerbi_readonly; 并在 psql 中使用 \dp table_name 进行验证。

数据质量问题

关键字段中的 NULL 值 — Odoo 允许许多字段为空。在 SQL 查询中使用 COALESCE 或在 DAX 中处理 BLANK() 以避免计算错误。

重复记录 — Odoo 的 ORM 有时会在编辑过程中创建多个版本的记录。按 active = true 进行过滤,并确保您使用正确的州字段来排除草稿和已取消的记录。

时区不匹配 — Odoo 以 UTC 格式存储时间戳。默认情况下,Power BI 以本地时区显示。在 PostgreSQL 查询中使用 AT TIME ZONE 或在 Power Query 中使用 DateTimeZone.SwitchZone 进行规范化。

性能问题

刷新速度慢 — 启用增量刷新。使用自定义 SQL 查询而不是导入整个表。过滤掉分析窗口之外的非活动记录、草稿文档和历史数据。

报告加载时间超过 10 秒 — 检查在大型表(SUMX、具有多行的 FILTER)上迭代的复杂 DAX 度量。使用变量可以避免重复计算。考虑在 SQL 视图中预先聚合数据。

网关超时 — 增加网关数据源配置中的命令超时。默认为 120 秒;对于大型 Odoo 数据库设置为 600。


安全考虑

数据库安全

切勿使用 Odoo 管理员数据库用户将 Power BI 连接到 Odoo。创建一个专用的只读用户,如前所示。考虑这些额外措施:

  • 行级限制: 如果您不希望 Power BI 访问所有表(例如,不包括 hr_payslip),请使用 PostgreSQL CREATE POLICY 限制只读用户的访问权限
  • 列屏蔽: 创建排除敏感列(工资、SSN、银行详细信息)的视图,并授予 Power BI 访问视图而不是基表的权限
  • 连接加密: 始终使用 SSL 进行 PostgreSQL 连接,尤其是当 Power BI 网关和 Odoo 数据库位于不同网络时
  • 审核日志记录: 启用 PostgreSQL pgaudit 跟踪来自 Power BI 用户的所有查询

Power BI 安全

  • 在 Power BI 中实施行级安全性 (RLS),反映 Odoo 的多公司访问规则
  • 对包含财务或人力资源数据的数据集使用敏感度标签
  • 限制授权分析师和消费者访问工作空间
  • 禁用敏感报告上的数据导出以防止数据泄露

要深入了解 Power BI 安全性,请参阅我们的行级安全性实现 指南。


综合起来:实施路线图

第 1 阶段:基础(第 1-2 周)

1.在Odoo数据库上创建只读PostgreSQL用户 2. 安装并配置本地数据网关(如果使用 Power BI 服务) 3.将Power BI Desktop连接到Odoo数据库 4.导入五个核心表组(销售、会计、库存、制造、HR) 5.构建日期维度并建立关系

第 2 阶段:核心仪表板(第 3-4 周)

  1. 构建高管销售仪表板(收入、增长、顶级产品、渠道)
  2. 构建财务仪表板(AR账龄、现金流、预算差异)
  3. 构建库存仪表板(库存水平、营业额、重新订购警报) 4.为所有事实表配置增量刷新
  4. 发布到 Power BI 服务并设置计划刷新

第 3 阶段:高级分析(第 5-6 周)

  1. 构建制造仪表板(OEE、利用率、生产调度)
  2. 构建人力资源仪表板(员工人数、人员流失、出勤、缺勤)
  3. 实现多公司数据隔离的行级安全
  4. 为关键仪表板创建移动优化布局
  5. 为关键 KPI(缺货、发票逾期、生产延迟)设置数据警报

第 4 阶段:治理和规模(第 7-8 周)

  1. 建立工作区命名约定和内容认证
  2. 对高级用户进行自助报告创建培训
  3. 记录数据模型和计算逻辑
  4. 设置使用情况监控来跟踪采用情况
  5. 规划其他数据源(营销平台、电子商务、物联网)

ECOSIRE 的 Power BI + Odoo 集成服务 遵循此路线图,通常会在两周内交付第一个执行仪表板。我们的团队在 Odoo 数据模型和 Power BI 分析引擎方面拥有双重专业知识,可确保您从第一天起就获得准确、高性能且受监管的分析。


常见问题解答

我可以将 Power BI 连接到 Odoo Online,还是仅连接自托管 Odoo?

您可以连接到两者,但方法不同。自托管 Odoo 为您提供直接 PostgreSQL 访问,速度更快、更灵活。 Odoo Online 和 Odoo.sh 不直接公开数据库,因此您需要使用 Odoo 的 JSON-RPC API、社区 OData 连接器模块或计划将数据导出到临时数据库。对于具有大型数据集的 Odoo Online,建议使用临时数据库方法,因为对于具有超过 50,000 条记录的表,基于 API 的提取速度较慢。

Power BI 多久可以从 Odoo 刷新一次数据?

使用 Power BI Pro,您每天最多可以安排 8 次刷新(每 3 小时一次)。使用 Power BI Premium,您每天最多可以安排 48 次刷新(每 30 分钟一次)。对于实时数据,请使用 DirectQuery 模式,但请注意,每个报表交互都将直接查询您的 Odoo 数据库。增量刷新减少了每次刷新所需的时间,使更频繁的刷新变得可行,而不会导致数据库过载。

Power BI 查询会减慢我们的 Odoo 系统吗?

如果您使用导入模式(推荐),Power BI 查询仅在计划刷新期间运行——通常是在非高峰时段。对 Odoo 性能的影响很小。如果您使用 DirectQuery,每个报告交互都会生成针对 Odoo 数据库的实时查询,这可能会影响工作时间的性能。缓解措施包括使用只读副本、配置查询超时以及设计使用索引的高效 SQL 查询。

我需要了解 SQL 才能设置集成吗?

基本的 SQL 知识很有帮助,但不是严格要求。 Power BI 的 Power Query 界面可让您选择表并直观地应用筛选器。但是,为了获得最佳性能和数据质量,强烈建议使用自定义 SQL 查询。它们允许您预先连接表、过滤不必要的记录并在数据库级别调整数据。如果您的团队缺乏 SQL 专业知识,请考虑聘请专家进行初始设置,然后使用 Power BI 的可视化工具维护报告。

ECOSIRE 的 Odoo + Power BI 服务与一般 Power BI 咨询有何不同?

大多数 Power BI 咨询公司都拥有 Power BI 方面的专业知识,但对 Odoo 数据模型的了解有限。他们花了数周时间对表关系进行逆向工程,了解 Odoo 特定的约定(例如双 Product_product / Product_template 结构),并找出哪些字段是有意义的。 ECOSIRE 已构建并部署了超过 43 个 Odoo 模块,并在这两个平台上保持着深厚的专业知识。我们提供预构建的数据模型、包含 50 多项指标的标准 KPI 库,以及 Odoo 特定的优化,例如 write_date 列上的增量刷新。与从头开始学习 Odoo 数据模型的团队相比,这种双重专业知识可将实施时间缩短 40-60%。

E

作者

ECOSIRE Research and Development Team

在 ECOSIRE 构建企业级数字产品。分享关于 Odoo 集成、电商自动化和 AI 驱动商业解决方案的洞见。

通过 WhatsApp 聊天