跳转到内容

分析 NetSuite 财务数据:从连接到损益表

约 45 分钟 · 一个可用的 NetSuite 连接、一张已加载的总账、一张月度损益表、一份应收账款账龄,以及一个计划刷新

这是财务总监或 FP&A 分析师的入门路径:完成后,您将直接从 NetSuite 提取总账,将其转换为可像报表一样阅读的月度损益表,构建应收账款账龄,把两者放到仪表板上,并让整个流程自动刷新。无需导出电子表格,也无需手动重新录入,数据来自 NetSuite 并保持最新。

您只需连接一次、提取一次,然后做真正重要的部分:将原始总账行整理成业务人员周一早上要看的汇总。

NetSuiteSuiteQL 提取总账表分组并求和损益表
建立连接,提取一次总账,再将其整理成可阅读的报表,整个流程都可按计划重新运行。
  • 一个 PlaidCloud 工作区和一个用于操作的项目(如果需要,请开始试用)。
  • 一个可用的 NetSuite 连接。请先按照连接到 NetSuite 操作:需要在 NetSuite 中启用 OAuth 2.0 和 REST Web 服务,并准备好集成的客户端 ID、证书 ID、账户 ID 和私钥 PEM。开始之前,请确认发送测试请求显示为绿色。
  • 整理数据无需 SQL,使用标准转换步骤即可完成。唯一的查询文本是从 NetSuite 提取数据的部分,所有提取查询都已提供。请在另一个标签页中打开 NetSuite SuiteQL 查询示例,本教程的内容取自该页面。

工作流是提取并整理数据的管道。

  1. 打开项目,切换到工作流选项卡。
  2. 单击新建工作流,将其命名为例如 NetSuite Financials,然后打开。

一条 SuiteQL 查询即可得到一整年的过账活动(每个科目、每个月),足以构建损益表,以及之后的其他报表。

  1. 添加一个 REST 请求步骤。在请求选项卡上,将连接设为您的 NetSuite 连接,将方法设为 POST,将端点设为 /services/rest/query/v1/suiteql。

  2. 在正文中,放入以下 SuiteQL,并包装为 {"q": "…"}:

    SELECT
    TO_CHAR(t.trandate, 'YYYY-MM') AS period,
    a.accttype AS account_type,
    a.acctnumber AS account_number,
    BUILTIN.DF(a.id) AS account_name,
    tal.amount AS amount
    FROM transactionaccountingline tal
    JOIN transaction t ON t.id = tal.transaction
    JOIN account a ON a.id = tal.account
    WHERE tal.posting = 'T'
    AND tal.accountingbook = 1
    AND t.trandate BETWEEN TO_DATE('2026-01-01', 'YYYY-MM-DD')
    AND TO_DATE('2026-12-31', 'YYYY-MM-DD')
    ORDER BY period, a.acctnumber
  3. 在响应选项卡上,将目标设为表,命名为 netsuite_gl,并设置列类型:amount → 货币,其余 → 文本。(SuiteQL 将数字和日期作为文本返回;设置类型后 amount 才能求和。)

  4. 单击发送测试请求确认可以运行,然后运行该步骤。现在您有了一张 netsuite_gl 表:每个科目每个月一行,带有带符号的过账金额。

接下来是分析,只需一次点选式转换,无需 SQL。损益表其实就是汇总后的总账:收入和费用科目归入几个项目,并翻转符号,使收入显示为正数。Table Extract 步骤可以在其表数据选择和数据筛选器选项卡上完成全部操作。

  1. 添加一个 Table Extract 步骤。将其源设为 netsuite_gl,目标设为新表 netsuite_pnl。

  2. 在数据筛选器选项卡上,仅保留收入和费用科目(排除资产负债表科目):添加一个筛选器,条件为 account_type 属于其中之一 Income、OthIncome、COGS、Expense、OthExpense。

  3. 在表数据选择选项卡上,单击汇总以启用聚合,然后设置三个目标列:

    • period:直接从源映射。汇总方式为分组依据。
    • pnl_line:一个表达式(见下文),将每种科目类型转换为一个报表项目。汇总方式为分组依据。
    • amount:表达式为 netsuite_gl.amount * -1(翻转符号)。汇总方式为求和。

    对于 pnl_line,双击其表达式单元格并输入以下内容(编辑器允许您点选各列,以及条件分组中的 case 函数):

    case(
    (netsuite_gl.account_type.in_(['Income', 'OthIncome']), '1 - Revenue'),
    (netsuite_gl.account_type == 'COGS', '2 - Cost of Goods Sold'),
    (netsuite_gl.account_type.in_(['Expense', 'OthExpense']), '3 - Operating Expenses'),
    )
  4. 运行该步骤。

amount * -1 表达式是唯一的会计处理:将借方为正的金额取反,使收入为正、成本为负,因此每个月的三个项目相加即为净利润。随后以 period 和 pnl_line 为分组依据并求和,即可将所有科目汇总为每月三个项目。表达式使用 PlaidCloud 的点选式编辑器,参见高级数据映射器用法和表达式参考。

打开 netsuite_pnl 表。每个月有三个数字:

period pnl_line amount
2026-01 1 - Revenue 486,200.00
2026-01 2 - Cost of Goods Sold -190,540.00
2026-01 3 - Operating Expenses -212,880.00

可以直接从中读出:

  • 毛利润 = 收入 + 销货成本(销货成本已是负数)→ 486,200 − 190,540 = 295,660。
  • 净利润 = 三个项目之和 → 82,780。
  • 毛利率 = 毛利润 ÷ 收入 → 约 61%。

首先要做的是核对:针对同一个月运行 NetSuite 自带的损益表,确认收入和净利润一致。如果不一致,几乎总是范围不同:子公司或货币筛选器,或者过账期间与交易日期未对齐(参见关于期间的说明)。只有核对一致后,才能信任这条管道。

这是第二个入门成果,遵循同样的“连接、提取、整理”模式。从未结应收账款的查询开始,然后按每张发票的逾期时间分档。

  1. 再添加一个 REST 请求步骤(相同的连接,POST,suiteql 端点),正文如下:

    SELECT
    t.tranid AS invoice_number,
    BUILTIN.DF(t.entity) AS customer,
    TO_CHAR(t.trandate, 'YYYY-MM-DD') AS invoice_date,
    TO_CHAR(t.duedate, 'YYYY-MM-DD') AS due_date,
    t.foreigntotal AS invoice_total,
    t.foreignamountunpaid AS amount_unpaid
    FROM transaction t
    WHERE t.type = 'CustInvc'
    AND t.foreignamountunpaid <> 0
    ORDER BY t.tranid

    将其加载为 netsuite_open_ar,其中 invoice_total 和 amount_unpaid → 货币,invoice_date 和 due_date → 日期,其余 → 文本。

  2. 添加一个 Table Extract 步骤,读取 netsuite_open_ar 并写入新表 netsuite_ar_aging。在表数据选择选项卡上,单击汇总并设置三个目标列:

    • aging_bucket:一个表达式(见下文),根据每张发票的逾期时间为其打标签。汇总方式为分组依据。
    • invoices:任意列,例如 invoice_number。汇总方式为计数。
    • balance:从 amount_unpaid 映射。汇总方式为求和。

    对于 aging_bucket,输入以下表达式,它计算逾期天数(日期减日期得到天数)并标记所属区间:

    case(
    ((func.today() - netsuite_open_ar.due_date) <= 0, '0 - Current'),
    ((func.today() - netsuite_open_ar.due_date) <= 30, '1 - 1-30 days'),
    ((func.today() - netsuite_open_ar.due_date) <= 60, '2 - 31-60 days'),
    ((func.today() - netsuite_open_ar.due_date) <= 90, '3 - 61-90 days'),
    else_='4 - Over 90 days',
    )
  3. 运行。netsuite_ar_aging 现在用五行告诉您,有多少款项未到期,有多少款项逾期 30/60/90 天以上,这是业务人员首先查看的催收视图。(due_date 必须设为日期类型,日期相减才能生效,您已在上面 REST 请求步骤的响应选项卡上完成了设置。)

表中的数字尚可,但发给首席财务官的应当是图表。发布 netsuite_pnl 和 netsuite_ar_aging,然后按照构建仪表板添加:

  • 按 period 显示净利润(或收入)的条形图,以及
  • 按 aging_bucket 显示应收账款 balance 的饼图或条形图。

这就是一个实时的 NetSuite 财务仪表板,无需导出,每次运行工作流时都会刷新。

  1. 从头到尾运行整个工作流一次,确认每个步骤都显示为绿色。
  2. 为工作流设置计划:按结账节奏每月运行,或者如果希望每天早晨都有最新的应收账款账龄,则每晚运行。

由于每次提取都会完整替换整张表,每次运行都会重新提取其 WHERE 子句定义的数据范围,因此请将范围限制在所需的时间窗口内(当年、仅未结发票),而不是全部历史数据。

从一个空工作流开始,您提取了实时的 NetSuite 总账和应收账款,使用两个标准转换步骤(无需 SQL)将其整理为月度损益表和应收账款账龄,放到仪表板上,并设置为自动刷新。这是财务团队运行的核心报表循环,现在已经实现自动化。