DaoSales 培训手册

财务经理

面向财务经理:审批、报表、预算、现金流

今天要做什么

财务经理是管理层,不做凭证录入、不跑网银付款:每天两次过审批队列(报销单、付款申请),每周复盘预算差异,每月月结后出三大报表并正式关账。凭证录入 / 过账 / 月结执行都归会计(accountant),网银打款归出纳(cashier)。

每日

  1. 上午 9:30 过一遍报销审批队列:处理昨晚到队的「待财务审批」单(status='pending_finance'),逐单看金额 / 附件 / 事由,放行或驳回。
  2. 下午 17:00 再扫一遍队列,防止单据压过夜影响员工报销时效。
  3. 扫付款进度看板:看「已批待付」/「处理中」金额,提醒出纳排期;经理只看不点付款
  4. 现金流量表(CF)仪表盘粗扫:「经营活动净额」异常立刻找会计核查。
日常入口:/dashboard/expenses/approvals/dashboard/expenses/payments/dashboard/reports

每周

  • 周一翻预算执行:进预算详情页看「预算 vs 实际」差异表,标红的超支科目(预算字段 isOverBudget=true)联系部门经理问原因。
  • 周四批量审批日:对小额 < ¥5000 的单子批量放行,减少逐单切换。
  • 周五扫自定义报表,出周报给老板。

每月

  • 月初 1–3 日:等会计发出「月结完成」信号后,先做试算平衡核平,再出利润表 / 资产负债表 / 现金流量表(IS / BS / CF)三表交老板。
  • 月初 5–10 日:上月会计期间正式「关账」(会计期间状态从「开启 open」→「已关账 closed」);关账前必须确认会计已把所有草稿凭证过完账。
  • 月末 25–30 日:启动下月 / 下季 / 下年预算——审批起草人提交的 budget、复核 12 列月度表后放行。
finance-manager/nav-overview.jpg

权限红线(先看这 5 条)

  • 不能直接执行付款——网银 / 银企互联归出纳。经理的动作止于「审批通过」(状态变「已审批 approved」),后续「标为已付 paid」由出纳点。
  • 不能关有未过账凭证的期间——「草稿态」/「待过账」凭证不进利润表 / 资产负债表,硬关会让报表失真;关账前先让会计批量过账。
  • 不能在 UI 绕过审批直接改数据库状态——审批链一断,合规性丢失且无留痕,审计出问题无法追溯。
  • 审批阈值 5000 / 50000 / 200000 当前版本写死在代码里——超 5 万走总监、超 20 万走总经理,经理一个人无法最终拍板;后台改不了,要改需发版(代码里标注了 TODO: Move to organization_settings)。阈值按基础币种(人民币)比较,外币报销需先按当日汇率折算。
  • 不能开采购单 / 录凭证 / 过账 / 批量付款——采购 / 会计 / 出纳的事,经理是只读或不可见;需要协作时找对应角色。

Quickstart — 日常核心任务

2.1 审批报销(单笔)

员工已提交报销单且金额介于 ¥5000–50000 之间,状态为「待财务审批 pending_finance」,队列里出现该单。

  1. 点左侧导航「费用 → 审批队列」进入 /dashboard/expenses/approvals。(见图 ①)
  2. 逐行看列表字段:金额、币种、申请人、部门、事由、附件数。附件数为 0 直接驳回。
  3. 要看细节点单号进详情:看费用项明细、审批历史时间线、是否已过部门经理节点(状态 pending_manager 已走完)。
  4. 放行:回队列点该行「通过」按钮(绿色对勾)。(见图 ① 圈 ①)
  5. 驳回:点红色叉按钮,弹窗里填「驳回原因」——必填,留给员工改单参考。(见图 ②)
  6. 放行后若金额 > ¥50000:状态推进到「待总监审批 pending_director」而非「已审批 approved」——经理这里到此为止,总监接力。
finance-manager/approvals-queue.jpg
finance-manager/approvals-reject-dialog.jpg
何时不该做:单据来源是「企微来源」(source='wecom')时队列里根本不会出现——企微提交的报销走企微内审批,经理在 DaoSales 看不到,需要打开企微审批后台处理;误以为"没单积压"会让员工报销被压一周以上。金额超 ¥50000 放行时不要以为"一通了之"——界面上看似成功但实际会推总监节点,总监不在场会卡住;超额的先线下和申请人对工作量,再决定放行时机。
观测信号:
  1. 列表行从队列消失,转到「已处理」Tab。
  2. 单据详情「审批历史」时间线新增一行(操作人 = 你,动作 = 「通过 approved」或「驳回 rejected」)。
  3. 申请人企微收到「审批通过 / 驳回」卡片;驳回卡片含你填的原因。
技术追溯:expense_claims.statusapproved(≤¥50000)或 pending_director(>¥50000);approved_by_finance / approved_by_finance_at 回填;expense_approvals 新增 approver_role='finance' 行。
系统动作:approveClaimActionrejectClaimActiongetPendingApprovalsForUser(查队列)

2.2 批量审批(小额单子)

队列里积压 20+ 笔小额 < ¥5000 的出差 / 样品快递报销;逐单点效率太低,一次性放行。

  1. /dashboard/expenses/approvals,用金额筛选器过滤 < ¥5000。(见图 ①)
  2. 勾选表头全选,或按 Shift 多选相邻行。
  3. 顶部动作条点「批量通过」或「批量驳回」;批量驳回会弹窗让填统一原因。
  4. 等提示 toast:「已处理 N 笔」;失败的单子会在错误列表提示单号和原因——单独再处理。
finance-manager/approvals-queue.jpg
何时不该做:别对金额分布不均的队列批量放行——把 > ¥50000 的混进去会都被推「待总监审批 pending_director」,总监一次性收到一堆会退回重来。月底 25 号之后别批量处理——临近月结的票据要逐单核对日期,避免跨期(会影响当月利润表)。
观测信号:
  1. 队列一次性少掉 N 行,「已处理」Tab 增 N 行。
  2. 付款看板「已批待付」金额合计上升 ΣN。
技术追溯:批量事务 batchApproveClaimsAction(claimIds[]) 返回 { success, errors[] };每笔独立走 expense_claims.status 状态转换。
系统动作:batchApproveClaimsActionbatchRejectClaimsAction

2.3 查预算执行(预算 vs 实际)

月中 / 月末想知道哪个部门 / 哪个科目超支,哪个科目还有闲置额度可重分配。

  1. /dashboard/accounting/budgets 看预算列表,按状态筛「已审批 approved」的当期预算。(见图 ①)
  2. 右上角「新建预算」按钮走创建流程:填名称、预算类型(年 / 季 / 月 / 项目)、财年、币种,保存后在 12 列月度表里录数字。(见图 ②)
  3. 点某行「查看」进详情页——上半部 12 列月度录入表,下半部「预算 vs 实际」差异表。
  4. 看差异表:每行一个「科目 + 成本中心」组合。重点看「差异 variance」列(负数 = 超支)和红色「超支 isOverBudget」标记。
  5. 超支科目点展开看明细:按已过账凭证(会计已走 postJournalEntry)按月聚合。
  6. 超支严重的科目联系部门经理了解原因;若预算整体失效(行情剧变),让起草人撤回或驳回后走新版。
finance-manager/budgets-list.jpg
finance-manager/budget-create-dialog.jpg
已知 gap:预算明细表(budget_items)的数据库迁移(迁移文件 20251223_budgets.sql / 20260226_budget_items_private.sql)在当前 SaaS 或私有环境可能尚未应用——打开详情页会看到 404 或查询报错;遇到此情况先联系 IT 应用迁移(部署备忘录有说明),不要自己改前端降级。另外,「实际 actual」数据只统计已过账凭证,草稿 / 待过账凭证看不到,月中看会显著偏小——问会计「还有多少凭证未过账」后再下结论。
观测信号:
  1. 差异表每行显示「预算金额 budgetAmount」/「实际金额 actualAmount」/「差异 variance」/「差异率 variancePercent」。
  2. 实际 > 预算的行整行染红。
  3. 底部合计 = Σ各行 variance。
技术追溯:getBudgetVsActualData(budgetId) 返回 { rows[], totals };每行按 account_id + cost_center_id 聚合 journal_entries + journal_entry_lines
系统动作:getBudgetsDatagetBudgetDetailDatagetBudgetVsActualData

2.4 审批 / 驳回预算

部门预算员起草完下年度 / 下季度预算并点「提交审批」,状态从「草稿 draft」变「待审批 pending_approval」,经理收到待审。

  1. /dashboard/accounting/budgets,按状态筛「待审批」。
  2. 点「查看」进详情,复核 12 列月度表:科目 / 成本中心 / 每月金额是否合理。(见图 ①)
  3. 和历史期间「实际」对比(用 2.3 差异表反推)——偏差超 ±20% 要求起草人说明。
  4. 合理:点顶部「通过」按钮(状态变「已审批 approved」)。
  5. 不合理:点「驳回」,状态变「已驳回 rejected」,起草人需新建 v2 版本(「已审批」的不可直接改)。
finance-manager/budget-create-dialog.jpg
何时不该做:「已审批 approved」状态后系统会拒绝修改(返回错误 CANNOT_MODIFY_APPROVED)——审批前务必核对,审批后只能走驳回 + 新建版本,不能直接改金额。同一「年度预算」+ 同一财年通常只保留一份生效——重复放行会让差异表口径混乱。
观测信号:
  1. 预算列表行状态徽标从「待审批」变「已审批」(绿徽标)。
  2. 详情页顶部动作条按钮消失(「已审批」状态不再显示通过 / 驳回按钮)。
  3. 其他角色建凭证时系统可按该预算查余额(checkBudgetAvailability)。
技术追溯:budgets.statusapprovedrejectedbudgets.approved_by / approved_at 回填;乐观锁 version+1
系统动作:approveBudgetActionrejectBudgetActionsubmitForApprovalAction(起草人用)

2.5 出三大报表(资产负债表 / 利润表 / 现金流量表)+ 试算平衡

月初 1–3 日会计完成月结后立刻出一套报表交老板;老板要求看昨日 / 本周瞬态数据时随时可出。

  1. /dashboard/reports,看顶部 4 个 Tab:试算平衡 / 利润表(IS)/ 资产负债表(BS)/ 现金流量表(CF)。(见图 ①)
  2. 先试算平衡:切「试算平衡」Tab,选截止日 asOfDate(默认今天),点「生成」——Σ借方必须 = Σ贷方,差额非零说明分录不平衡,把差额截图发给会计排查(经理不手动改分录)。(见图 ②)
  3. 利润表:切「利润表」Tab,选期间起止(当月 1 号 → 今天),点「生成」——看营收、成本、毛利、净利润。(见图 ③)
  4. 资产负债表:切「资产负债表」Tab,选截止日,点「生成」——三段式(资产 / 负债 / 所有者权益),「资产合计」= 「负债 + 权益合计」。(见图 ④)
  5. 现金流量表:切「现金流量表」Tab,选期间起止,点「生成」——三段(经营 / 投资 / 筹资)净流。(见图 ⑤)
  6. 四张表相互勾稽:利润表的净利润 → 资产负债表的未分配利润变动;现金流量表的期末现金 → 资产负债表的货币资金。
  7. 右上角「导出 PDF / Excel」给老板。
finance-manager/nav-overview.jpg
finance-manager/trial-balance.jpg
finance-manager/income-statement.jpg
finance-manager/balance-sheet.jpg
finance-manager/cash-flow.jpg
何时不该做:当前版本三大报表只按「租户 organizationId」取数、不接收「账套 bookId」参数——多账套场景下需和会计先确认口径(否则跨账套金额会被一起算进去)。关账日期晚于截止日时利润表 / 现金流量表数据可能不稳(当期正在结账)——尽量在会计确认「月结完成」后再出报表。
观测信号:
  1. 报表表头显示所选期间 + 基础币种(来自账套配置 accounting_books.base_currency)。
  2. 试算平衡底部 Σ 差额 = 0;有差额会高亮红色。
  3. 利润表底部「净利润」= 营收 − 成本 − 费用;资产负债表「资产合计」= 「负债 + 所有者权益合计」。
技术追溯:fetchTrialBalance({ asOfDate, includeZeroBalances })fetchIncomeStatement({ periodStart, periodEnd })fetchBalanceSheet({ asOfDate })fetchCashFlowStatement({ periodStart, periodEnd });数据源限定 journal_entries.status='posted'
系统动作:fetchTrialBalancefetchIncomeStatementfetchBalanceSheetfetchCashFlowStatement

2.6 关会计期间 / 重开期间

上月 1–3 日会计执行完月结结转后,经理正式把该期间置「已关账 closed」,锁定历史数据不让再改。

  1. /dashboard/accounting/fiscal-periods,找到要关的年度卡片展开 12 个期间。(见图 ①)
  2. 确认待关期间状态是「开启 open」,且未来期(序号更大)没有「开启」期——系统规则要求按顺序关账。
  3. 点该期行尾「关期」按钮——系统按乐观锁校验后把期间置「已关账 closed」。(见图 ②)
  4. toast 提示「已关闭」;徽标变灰色「已关账」。
  5. 发现错关要重开:同一行点「重开」按钮(仅「已关账」期显示),让会计补录凭证;重开后必须再关一次。
  6. 并发冲突提示「CONFLICT 数据已被其他用户修改」:刷新页面重试,不要多 tab 切换。
finance-manager/fiscal-periods-list.jpg
finance-manager/fiscal-period-actions.jpg
何时不该做:期间内仍有「草稿 / 待过账」凭证时不要关——关账后该期日期的新凭证会被拒绝写入(系统调用 isDateInOpenPeriod 校验),会计再补时会被拦;关账前让会计先把所有凭证过账完(经理不代劳过账)。跨年度关账要先确认新年度已生成(createFiscalYearAction)——否则新年度没有「开启」期间会阻塞业务。
观测信号:
  1. 期间行徽标从「开启 open」变「已关账 closed」灰色。
  2. 统计卡片「已关账期间数」+1、「开启中期间数」−1。
  3. 该期日期范围内不再允许新建凭证——会计过账会报「Period is closed」。
技术追溯:accounting_periods.status='closed'closed_by / closed_at 回填;乐观锁 version+1
系统动作:updatePeriodStatusActiongetClosingPreviewAction(预览结转数)

2.7 对比历史期间(利润表 / 现金流量表多期横向)

老板问「本月营收和上月 / 去年同期比如何」——生成两份不同期间的利润表对比。

  1. /dashboard/reports 切「利润表」Tab。
  2. 先生成本月:期间起 2026-04-012026-04-30,点「生成」并导出 PDF。
  3. 再生成上月:改为 2026-03-012026-03-31,导出 PDF。
  4. 去年同期:改为 2025-04-012025-04-30,导出。
  5. 用 Excel / 自定义报表把三份横向拼表交老板。
  6. 现金流量表同理,三段净流横向比。
finance-manager/income-statement.jpg
何时不该做:期间跨了「未关账」+ 「已关账」时数据会部分已过账、部分漏——尽量对齐到已关账区间比较,避免把未结转数据错认为对比基础。
观测信号:
  1. 切换期间参数后点「生成」,表头期间显示更新。
  2. 数字行随期间变动,「净利润」行数值不同。
技术追溯:重复调 fetchIncomeStatement({ periodStart, periodEnd });每次独立查询,无缓存叠加。
系统动作:fetchIncomeStatementfetchCashFlowStatement

2.8 自定义报表与导出(审计清单 / 月度看板)

审计人员要一份「本月所有 > ¥10000 报销明细」;老板要按部门看费用分布——标准三表不够用时走自定义报表。

  1. /dashboard/reports/custom 看已有报表列表;想复用别人的报表看「公开」标记(isPublic=true)的公开模板。(见图 ①)
  2. 点「新建报表」弹窗:填名称、选类型(销售 / 库存 / 客户 / 财务)、公开与否。
  3. 提交后进报表详情页——拖拽实体 / 列 / 筛选 / 分组 / 聚合 / 排序。(见图 ②)
  4. 筛选条件写法参考已有公开模板的 config——常用 { 字段, 运算符, 值 } 三元组。
  5. 点「生成」预览;满意点「导出 Excel」。
  6. 导出审计清单示例:报表类型「财务」、实体「报销单 expense_claims」、筛选「金额 > 10000」、列选「申请人 / 金额 / 日期 / 审批人」。
finance-manager/custom-reports-list.jpg
finance-manager/custom-report-detail.jpg
何时不该做:删除报表不可撤销——常用模板打「公开」标记让队友能复用;别随意删他人报表。聚合 / 筛选写错不会实时报错(前端宽松校验),等「生成」时才 500——每改一次先小范围试跑。
观测信号:
  1. 报表列表出现新行,名称 + 类型 + 创建人。
  2. 详情页「预览」按钮点后表格刷新数据。
  3. 导出 Excel 后浏览器下载区出现 .xlsx 文件。
技术追溯:reports.idreports.config JSON;生命周期 createReportupdateReportdeleteReport
系统动作:createReportupdateReportdeleteReport

上下游交接契约

经理处于「审批 + 复核」节点——上游出纳 / 员工 / 会计把动作推上来,下游老板 / 会计按结论继续。字段缺失会卡住整条链路。

员工 → 经理:报销申请

我做什么:看队列里「待财务审批」单据——逐单或批量放行 / 驳回;驳回必须写原因。

员工看到什么:企微收到「审批通过 / 驳回」卡片;驳回卡片含经理填的原因,员工可改单重新提交。

缺失会回来找我:驳回原因空——员工不知哪里错,反复提交;放行后员工看不到下一步进度——员工以为没动,来问经理。

技术字段(给 IT / 员工交叉核对)

触发动作:approveClaimAction(claimId, comments?) / rejectClaimAction(claimId, reason)

必传字段:claimIdreason(reject 必填);comments?(approve 可选)。

出纳 → 经理:付款执行完毕

出纳做什么:银行实际打款后点「标为已付」,报销单状态从「已审批 approved」变「已付 paid」。

经理看到什么:付款看板「已付金额」上升、「已批待付」下降;看板数字刷新。

缺失会回来找我:出纳忘标「已付」——看板上「已批待付」虚高,经理追着出纳问;误标「已付」——员工以为没到账来问,需走会计冲销付款凭证。

技术字段(给 IT / 出纳交叉核对)

触发动作:getPaymentPageData(经理只读);markClaimAsPaidAction(出纳执行)。

读取字段:PaymentStats.approvedPendingPaymenttotalApprovedprocessingAmountpaidAmount

会计 → 经理:月结完成

会计做什么:执行月结(executeClosingAction('monthly'))——把收入 / 费用科目余额结转到「本年利润」,月结状态变「已完成 completed」。

经理看到什么:收到会计 IM 或系统「月结完成」通知;经理接力出三大报表、正式关账。

缺失会回来找我:会计月结没跑完就关账——资产负债表的「未分配利润」算错,报表交老板后被发现,经理要回头走「冲销月结」。

技术字段(给 IT / 会计交叉核对)

触发动作(会计):executeClosingAction;(经理):updatePeriodStatusAction(id, 'closed', version)

依赖字段:period_closings.status='completed'journal_entry_idtotal_revenue / total_expense / net_profit

部门预算员 → 经理:预算审批

起草人做什么:建预算、录 12 列月度表、点「提交审批」——预算状态从「草稿 draft」变「待审批 pending_approval」。

经理看到什么:预算列表筛「待审批」出现新行;详情页露出「通过 / 驳回」按钮。

缺失会回来找我:起草人漏填科目 / 成本中心 → 差异表维度缺(经理驳回让补);「已审批」后起草人发现错——系统会拒绝修改,让起草人自行建 v2。

技术字段(给 IT / 起草人交叉核对)

触发动作:approveBudgetAction(budgetId) / rejectBudgetAction(budgetId)

必传字段:budgetId;读取 budgets.statusbudget_items[].janAmount..decAmount(预算明细 12 列月度)。

经理 → 老板:三大报表

我做什么:月初四张表(试算平衡 / 利润表 / 资产负债表 / 现金流量表)出齐,右上角导出 PDF / Excel;自定义报表链接发给老板看费用分布 / 账龄分析。

老板看到什么:PDF 含期间、基础币种、数据截止时间;自定义报表(带「公开」标记的)链接可直接访问。

缺失会回来找我:期间跨了未关账期 → 数据非终态,老板下结论时偏差;基础币种未说明 → 多账套场景容易误解口径。

技术字段(给 IT / 老板交叉核对)

触发动作:fetchTrialBalance / fetchIncomeStatement / fetchBalanceSheet / fetchCashFlowStatement

传参:asOfDate(BS / TB)或 { periodStart, periodEnd }(IS / CF);注意:未接受 bookId 参数,多账套场景需先和会计确认口径。

经理 → 会计:重开期间 / 冲销结转

我做什么:发现已关账期数据错——走「重开期间」(期间状态从 closed 回 open);月结错——「冲销月结」(给会计留个反向凭证)。

会计看到什么:期间状态回「开启 open」可补凭证;冲销后生成反向凭证(凭证号 = 原号-R,引用类型 reference_type='reversal'),月结状态变「已冲销 reversed」。

缺失会回来找我:重开未填原因 → 审计追溯缺上下文;冲销后经理忘了要会计「重跑月结 + 再关账」,导致后续期间数据错。

技术字段(给 IT / 会计交叉核对)

触发动作:updatePeriodStatusAction(periodId, 'open', version)reverseClosingAction(closingId, reason)

必传字段:periodId + version(乐观锁);closingId + reason(冲销必填)。

异常回滚

审批 / 关账类动作误操作不要直接改数据库。按下表选对应入口按业务规则回滚。

症状 做什么 前置条件 / 后果
报销错放行但尚未付款 单据详情页「可用操作」下拉选「退回修改」(工作流 transition 到「草稿 draft」) 仅状态 =「已审批 approved」且付款日期为空;已付款需走会计冲销
报销错驳回 员工重新提交新单;原单不可恢复(「已驳回 rejected」是终态) 驳回是终态不可自愈,员工走「新建报销」再提交
批量通过误放行一批 「已审批 approved」不可回「已驳回 rejected」;让申请人走「作废」+ 重新提交 业务规则不支持直接撤回 approved,避免批量操作前先金额筛选
期间误关 同期间行点「重开」按钮 仅状态 =「已关账 closed」可重开;冲突提示「CONFLICT」要刷新取最新 version
月结执行错(收入 / 费用数据有误) 走「冲销月结」reverseClosingAction(closingId, reason) 月结状态变「已冲销 reversed」;生成「原号-R」反向凭证;期间回「开启」,会计重跑 executeClosingAction
预算通过后发现金额错 走「驳回预算」(状态变「已驳回 rejected」);起草人新建 v2 「已审批 approved」后修改接口被拒(返回 CANNOT_MODIFY_APPROVED
自定义报表误删 只能从公开模板复制重建 删除不可撤;平时把关键报表标「公开」做备份
关账前发现有草稿凭证 暂停关账;让会计批量过账后再关 草稿凭证 = 不进利润表 / 资产负债表;硬关会导致下月凭证写入被拒
对应系统动作(IT 追溯)
  • executeExpenseClaimTransitionAction — 走工作流回退 approved → draft(给申请人改单)
  • cancelClaimAction — 申请人作废自己的单;已 approved 的单只能走此路
  • updatePeriodStatusAction(periodId, 'open', version) — 重开已关账期,需最新 version
  • reverseClosingAction(closingId, reason) — 冲销月结,生成 reference_type='reversal' 凭证
  • rejectBudgetAction — 把 pending_approval / approved 预算置 rejected;保留历史
  • deleteReport — 删自定义报表;不可撤销

进阶功能

退回修改(比驳回更柔的审批回退)

员工单据基本合理只是附件不全 / 金额细节错——用「退回修改」让员工改后重交,避免「已驳回」的终态。在单据详情页走工作流 transition 回到「草稿 draft」。

系统动作:executeExpenseClaimTransitionActiongetExpenseClaimTransitionsgetExpenseClaimWorkflowState

新建下一年度(会计年度 Fiscal Year)

年末必须提前建下年度:按账套「财年起始月」生成 12 个会计期间。非历年财年(如 4 月 1 日 – 次年 3 月 31 日)靠「起始月」参数控制。

入口:/dashboard/accounting/fiscal-periods 右上「创建年度」按钮;系统动作 createFiscalYearAction(year, startMonth?)

finance-manager/fiscal-year-create.jpg
月结结转预览(关账前先试跑)

关账前会计先跑「结转预览」看本期「总收入 / 总费用 / 净利润」;经理也能看预览对比自己的利润表,差额异常时提前发现。在结账对话框里展开。

系统动作:getClosingPreviewActionexecuteClosingAction

finance-manager/closing-dialog.jpg
费用科目维护(启停开关)

老科目 / 停用科目:/dashboard/expenses/categories 用开关启停「有效」标记——停用后员工报销下拉不再出现,但历史单据不变。不要直接删,会影响历史报表。

系统动作:toggleCategoryStatusActioncreateExpenseCategoryActionupdateExpenseCategoryActiondeleteExpenseCategoryAction

finance-manager/expense-categories.jpg
费用分类分析 / 月度趋势

/dashboard/expenses/reports 按费用科目聚合本月 / 历史费用,带月度趋势折线。每周看一次趋势异常(某科目突增 50%)。

入口:/dashboard/expenses/reports;服务层 expense-claims 聚合查询。

finance-manager/expense-reports.jpg
付款进度监控(只读)

/dashboard/expenses/payments 看四个数字:「已批待付 / 已付 / 处理中 / 总批准」。经理只看不执行——出纳点「标为已付」完成闭环;若看板长期「已批待付」偏高,催出纳。

系统动作:getPaymentPageData(读);markClaimAsPaidAction / batchMarkClaimsAsPaidAction(出纳写)。

finance-manager/payments-dashboard.jpg

相关业务场景

  1. 标准成单流(询盘 → 报价 → 订单 → 发货 → 开票): 财务经理不参与销售侧执行;仅在利润表 / 现金流量表里看营收数据、AR 账龄由会计维护经理复核。 → 场景(了解即可)
  2. 定制家具项目流: 财务经理在「项目预算」审批时参与,核算项目成本对比预算;日常生产 / 交付不参与。 → 场景详解
  3. 回款流: 财务经理监控应收账龄(由会计在 /dashboard/accounting/ar-aging 产出),异常时找出纳追款;不直接录收款→ 场景详解
  4. 采购付款流: 财务经理审批大额「付款申请 payment_requests」 / 供应商付款(触动预算时走审批);出纳执行付款,会计入账。 → 场景详解
  5. 月结流: 财务经理的核心场景——会计月结后经理做试算平衡、出三表、正式关账;发现错走「冲销月结」。 → 场景详解
  6. 报销审批流: 财务经理是 finance 节点——> ¥5000 经部门经理后到经理,> ¥50000 经理过后推总监;批量放行 / 驳回是日常主要工作量。 → 场景详解

外部协作入口

权限与范围

看得到什么(RLS 边界)

  • 当前「租户 organization_id」下的所有报销单(expense_claims)/ 付款申请(payment_requests)/ 预算(budgets)/ 预算明细(budget_items)/ 会计期间(fiscal_periods / accounting_periods)/ 期末结转(period_closings)/ 自定义报表(reports)。
  • 三大报表(资产负债表 / 利润表 / 现金流量表)按「租户」查询——当前版本未接受「账套 bookId」参数,多账套场景需要和会计确认聚合口径。
  • 报销队列只显示「手工来源」(source='manual')——企微来源source='wecom')的报销走企微内审批,队列里看不到(已知 gap,培训要记住两套并行)。
  • 预算执行(budget_items):迁移未应用时查询会报错——先和 IT 确认迁移文件 20251223_budgets.sql / 20260226_budget_items_private.sql 已执行。

核心概念

  • organization_id — 租户隔离键,所有财务表都带;RLS 按该键过滤。
  • book_id — 账套隔离键(会计 / 出纳的主键);经理的报表层当前不接该键,多账套需线下对齐。
  • 乐观锁 version — 期间 / 预算并发写入的保护机制;UI 保持最新 version,冲突返「CONFLICT 数据已被其他用户修改」,刷新后重试。
  • 工作流引擎(src/services/workflow-engine.ts)——报销、预算、期间等状态机由该引擎驱动;经理的审批动作都是其 transition 的一种。
  • 审批阈值 5000 / 50000 / 200000——硬编码在 src/services/expense-approvals.ts:125-131,文件头注释 TODO: Move to organization_settings当前版本后台改不了,要靠发版
  • 财务经理 vs 会计 职责边界:会计(accountant)是执行层——录凭证、过账、月结结转、账龄维护、银行对账;财务经理是管理层——审批(报销 / 预算 / 大额付款)、复核(试算平衡 + 三大报表)、关账、异常回滚。经理不录凭证、不过账、不跑月结执行,遇到这些动作找会计。

术语表

报销单 expense_claims
expense_claims { claim_number, total_amount, currency, status, source }
付款申请 payment_requests
payment_requests(供应商付款 / 大额资金动用,需审批)
会计期间 fiscal_periods
accounting_periods { period_number, period_name, start_date, end_date, status: open | closed, version }
会计年度 fiscal_year
fiscal_years + accounting_books.fiscal_year_start_month(支持非历年财年)
期末结转 period_closing
period_closings { closing_type: monthly | yearly, status: completed | reversed, net_profit }
资产负债表 BS
Balance Sheet — fetchBalanceSheet({ asOfDate })(瞬态,看某一天)
利润表 IS
Income Statement — fetchIncomeStatement({ periodStart, periodEnd })(区间)
现金流量表 CF
Cash Flow — fetchCashFlowStatement({ periodStart, periodEnd })(经营 / 投资 / 筹资三段)
试算平衡 Trial Balance
fetchTrialBalance({ asOfDate, includeZeroBalances })(Σ借方 = Σ贷方)
预算 budgets
budgets.idbudget_type ∈ annual | quarterly | monthly | project
预算明细 budget_items
budget_items.janAmount … decAmount(12 列月度)——迁移未应用时不存在
预算差异 variance
variance = budgetAmount - actualAmountisOverBudget: actualAmount > budgetAmount
滚动预测 rolling forecast
/dashboard/accounting/cash-flow-forecast(基于应收 / 应付预计日期)
报销阈值 approval_threshold
> ¥5000 → 「待财务审批 pending_finance」;> ¥50000 → 「待总监审批 pending_director」;> ¥200000 → 「待总经理审批 pending_ceo」(硬编码)
报销状态链
draft → pending_manager → pending_finance → pending_director → pending_ceo → approved → processing → paid + rejected | cancelled
报销状态中文
草稿 / 待部门经理审批 / 待财务审批 / 待总监审批 / 待总经理审批 / 已审批 / 处理中 / 已付 + 已驳回 / 已作废
报销来源 source
source='manual'(手工来源,DaoSales 队列可见) / source='wecom'(企微来源,企微内审,队列不可见)
期间状态
open(开启) / closed(已关账) / locked(已锁定)
审批阶段 approval_step
expense_approvals.approver_role ∈ manager | finance | director | ceo | cashierapproval_step 1..4
审批动作 action
approveClaimAction(通过) / rejectClaimAction(驳回) / executeExpenseClaimTransitionAction(退回修改)
乐观锁 version
accounting_periods.version / budgets.version(并发防护)
关账 close period
updatePeriodStatusAction(periodId, 'closed', version)
冲销月结 reverse closing
reverseClosingAction(closingId, reason) → 凭证号「原号-R」反向凭证
自定义报表 reports
reports { id, reportType, config: JSON, isPublic }reportType ∈ sales | inventory | customers | financial

常见问题

为什么我看不到企微里员工提交的报销?

DaoSales 的审批队列强制筛「手工来源」(source='manual')——企微来源(source='wecom')的报销走企微内审批链,不进这个队列。目前是两套并行:DaoSales 里看到的是公司内部手工单,企微审批的需要打开企微审批后台处理。长期方案是在设置里统一入口,但当前版本尚未实现。

预算详情页打开报错 / 查询 404 怎么办?

已知 gap:预算明细表(budget_items)对应的数据库迁移20251223_budgets.sql / 20260226_budget_items_private.sql)可能未在目标环境应用,导致运行时查询 404。先联系 IT 确认迁移状态——SaaS 用 supabase.execute_sqlinformation_schema.tables,私有用 supabase-private.execute_sql;未应用则申请 apply_migration。本地前端降级不解决问题,要从数据库层解决。

批量通过后发现漏看了一笔大额,还能撤回吗?

不能直接撤回。「已审批 approved」是审批链的终态之一,业务规则不支持「已审批 → 已驳回」。只能走「作废」(让申请人作废自己的单)+ 重新提交流程;若已付款,走会计冲销凭证。预防办法:批量操作前用金额筛选器过滤,别把 > ¥50000 的混进小额批次。

关账时系统提示 CONFLICT 怎么办?

「会计期间」的乐观锁(version 字段)冲突——说明别人(或你其他 tab)刚改过该期间。刷新页面取最新 version 后重试就行。多 tab 并发操作是常见诱因,建议关掉其他 tab 统一在一个 tab 里操作。

三大报表数据和会计看到的对不上?

两种可能:(a)期间未关完 / 有草稿凭证——经理看到的是「已过账」口径,会计可能引用了草稿数据;(b)多账套场景下三大报表当前不接受「账套 bookId」参数,按「租户 organizationId」聚合;会计看单账套视图,经理看全组织视图,数字自然不同。和会计确认期间状态 + 账套口径后再下结论。

想改审批阈值(5000 / 50000 / 200000)怎么办?

目前改不了。阈值硬编码在 src/services/expense-approvals.ts:125-131,文件头注释 TODO: Move escalation thresholds to organization_settings;要调整需要发版(改代码)。业务上若想柔性控制,可在事前沟通——员工提交前线下沟通金额切分(如把一次 ¥60000 拆两次 ¥30000 报销),避免总监节点等待。阈值按基础币种(人民币)比较,外币报销先按当日汇率折算为 RMB 再判断走哪一档。

财务经理 和 会计 的职责边界是什么?

会计(accountant)是执行层:录凭证(createJournalEntry)、过账(postJournalEntry)、月结结转(executeClosingAction)、应收 / 应付账龄维护、银行对账。财务经理(finance-manager)是管理层:审批(报销 / 预算 / 大额付款)、复核(试算平衡 + 三大报表)、关账(updatePeriodStatusAction)、异常回滚(reverseClosingAction)。经理不录凭证、不过账、不跑月结执行——都找会计。典型协作:会计月结完成 → 经理复核报表 → 经理关账 → 若发现错,经理发起「冲销月结」→ 会计重跑。

现金流预测和现金流量表有啥区别?

现金流量表(CF)= 历史报表,看过去一段时间三段净流(经营 / 投资 / 筹资),数据来源「已过账」凭证。现金流预测(rolling forecast)= 未来预估,看未来 30 / 60 / 90 天应收到账 / 应付到期的净现金预期,在 /dashboard/accounting/cash-flow-forecast,数据来源「应收未结余额 invoices.balance_due」+「付款申请到期日 payment_requests.due_date」。CF 是结果、预测是规划,搭配用。

试算平衡显示借贷不平怎么办?

经理不改分录——把差额截图 + 截止日发给会计排查。常见原因:(a)会计刚录的凭证还是「草稿」未过账(只有「已过账 posted」才进报表);(b)历史凭证被删除或修改过。让会计查「草稿 + 过账异常」凭证清单后统一补 / 过,再回来试算。