今天要做什么
财务经理是管理层,不做凭证录入、不跑网银付款:每天两次过审批队列(报销单、付款申请),每周复盘预算差异,每月月结后出三大报表并正式关账。凭证录入 / 过账 / 月结执行都归会计(accountant),网银打款归出纳(cashier)。
每日
- 上午 9:30 过一遍报销审批队列:处理昨晚到队的「待财务审批」单(
status='pending_finance'),逐单看金额 / 附件 / 事由,放行或驳回。 - 下午 17:00 再扫一遍队列,防止单据压过夜影响员工报销时效。
- 扫付款进度看板:看「已批待付」/「处理中」金额,提醒出纳排期;经理只看不点付款。
- 现金流量表(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 列月度表后放行。
权限红线(先看这 5 条)
- 不能直接执行付款——网银 / 银企互联归出纳。经理的动作止于「审批通过」(状态变「已审批 approved」),后续「标为已付 paid」由出纳点。
- 不能关有未过账凭证的期间——「草稿态」/「待过账」凭证不进利润表 / 资产负债表,硬关会让报表失真;关账前先让会计批量过账。
- 不能在 UI 绕过审批直接改数据库状态——审批链一断,合规性丢失且无留痕,审计出问题无法追溯。
- 审批阈值 5000 / 50000 / 200000 当前版本写死在代码里——超 5 万走总监、超 20 万走总经理,经理一个人无法最终拍板;后台改不了,要改需发版(代码里标注了
TODO: Move to organization_settings)。阈值按基础币种(人民币)比较,外币报销需先按当日汇率折算。 - 不能开采购单 / 录凭证 / 过账 / 批量付款——采购 / 会计 / 出纳的事,经理是只读或不可见;需要协作时找对应角色。
Quickstart — 日常核心任务
2.1 审批报销(单笔)
员工已提交报销单且金额介于 ¥5000–50000 之间,状态为「待财务审批 pending_finance」,队列里出现该单。
- 点左侧导航「费用 → 审批队列」进入
/dashboard/expenses/approvals。(见图 ①) - 逐行看列表字段:金额、币种、申请人、部门、事由、附件数。附件数为 0 直接驳回。
- 要看细节点单号进详情:看费用项明细、审批历史时间线、是否已过部门经理节点(状态
pending_manager已走完)。 - 放行:回队列点该行「通过」按钮(绿色对勾)。(见图 ① 圈 ①)
- 驳回:点红色叉按钮,弹窗里填「驳回原因」——必填,留给员工改单参考。(见图 ②)
- 放行后若金额 > ¥50000:状态推进到「待总监审批 pending_director」而非「已审批 approved」——经理这里到此为止,总监接力。
source='wecom')时队列里根本不会出现——企微提交的报销走企微内审批,经理在 DaoSales 看不到,需要打开企微审批后台处理;误以为"没单积压"会让员工报销被压一周以上。金额超 ¥50000 放行时不要以为"一通了之"——界面上看似成功但实际会推总监节点,总监不在场会卡住;超额的先线下和申请人对工作量,再决定放行时机。
- 列表行从队列消失,转到「已处理」Tab。
- 单据详情「审批历史」时间线新增一行(操作人 = 你,动作 = 「通过 approved」或「驳回 rejected」)。
- 申请人企微收到「审批通过 / 驳回」卡片;驳回卡片含你填的原因。
expense_claims.status 变 approved(≤¥50000)或 pending_director(>¥50000);approved_by_finance / approved_by_finance_at 回填;expense_approvals 新增 approver_role='finance' 行。
approveClaimAction、rejectClaimAction、getPendingApprovalsForUser(查队列)
2.2 批量审批(小额单子)
队列里积压 20+ 笔小额 < ¥5000 的出差 / 样品快递报销;逐单点效率太低,一次性放行。
- 进
/dashboard/expenses/approvals,用金额筛选器过滤 < ¥5000。(见图 ①) - 勾选表头全选,或按 Shift 多选相邻行。
- 顶部动作条点「批量通过」或「批量驳回」;批量驳回会弹窗让填统一原因。
- 等提示 toast:「已处理 N 笔」;失败的单子会在错误列表提示单号和原因——单独再处理。
- 队列一次性少掉 N 行,「已处理」Tab 增 N 行。
- 付款看板「已批待付」金额合计上升 ΣN。
batchApproveClaimsAction(claimIds[]) 返回 { success, errors[] };每笔独立走 expense_claims.status 状态转换。
batchApproveClaimsAction、batchRejectClaimsAction
2.3 查预算执行(预算 vs 实际)
月中 / 月末想知道哪个部门 / 哪个科目超支,哪个科目还有闲置额度可重分配。
- 进
/dashboard/accounting/budgets看预算列表,按状态筛「已审批 approved」的当期预算。(见图 ①) - 右上角「新建预算」按钮走创建流程:填名称、预算类型(年 / 季 / 月 / 项目)、财年、币种,保存后在 12 列月度表里录数字。(见图 ②)
- 点某行「查看」进详情页——上半部 12 列月度录入表,下半部「预算 vs 实际」差异表。
- 看差异表:每行一个「科目 + 成本中心」组合。重点看「差异 variance」列(负数 = 超支)和红色「超支 isOverBudget」标记。
- 超支科目点展开看明细:按已过账凭证(会计已走
postJournalEntry)按月聚合。 - 超支严重的科目联系部门经理了解原因;若预算整体失效(行情剧变),让起草人撤回或驳回后走新版。
budget_items)的数据库迁移(迁移文件 20251223_budgets.sql / 20260226_budget_items_private.sql)在当前 SaaS 或私有环境可能尚未应用——打开详情页会看到 404 或查询报错;遇到此情况先联系 IT 应用迁移(部署备忘录有说明),不要自己改前端降级。另外,「实际 actual」数据只统计已过账凭证,草稿 / 待过账凭证看不到,月中看会显著偏小——问会计「还有多少凭证未过账」后再下结论。
- 差异表每行显示「预算金额 budgetAmount」/「实际金额 actualAmount」/「差异 variance」/「差异率 variancePercent」。
- 实际 > 预算的行整行染红。
- 底部合计 = Σ各行 variance。
getBudgetVsActualData(budgetId) 返回 { rows[], totals };每行按 account_id + cost_center_id 聚合 journal_entries + journal_entry_lines。
getBudgetsData、getBudgetDetailData、getBudgetVsActualData
2.4 审批 / 驳回预算
部门预算员起草完下年度 / 下季度预算并点「提交审批」,状态从「草稿 draft」变「待审批 pending_approval」,经理收到待审。
- 进
/dashboard/accounting/budgets,按状态筛「待审批」。 - 点「查看」进详情,复核 12 列月度表:科目 / 成本中心 / 每月金额是否合理。(见图 ①)
- 和历史期间「实际」对比(用 2.3 差异表反推)——偏差超 ±20% 要求起草人说明。
- 合理:点顶部「通过」按钮(状态变「已审批 approved」)。
- 不合理:点「驳回」,状态变「已驳回 rejected」,起草人需新建 v2 版本(「已审批」的不可直接改)。
CANNOT_MODIFY_APPROVED)——审批前务必核对,审批后只能走驳回 + 新建版本,不能直接改金额。同一「年度预算」+ 同一财年通常只保留一份生效——重复放行会让差异表口径混乱。
- 预算列表行状态徽标从「待审批」变「已审批」(绿徽标)。
- 详情页顶部动作条按钮消失(「已审批」状态不再显示通过 / 驳回按钮)。
- 其他角色建凭证时系统可按该预算查余额(
checkBudgetAvailability)。
budgets.status 变 approved 或 rejected;budgets.approved_by / approved_at 回填;乐观锁 version+1。
approveBudgetAction、rejectBudgetAction、submitForApprovalAction(起草人用)
2.5 出三大报表(资产负债表 / 利润表 / 现金流量表)+ 试算平衡
月初 1–3 日会计完成月结后立刻出一套报表交老板;老板要求看昨日 / 本周瞬态数据时随时可出。
- 进
/dashboard/reports,看顶部 4 个 Tab:试算平衡 / 利润表(IS)/ 资产负债表(BS)/ 现金流量表(CF)。(见图 ①) - 先试算平衡:切「试算平衡」Tab,选截止日
asOfDate(默认今天),点「生成」——Σ借方必须 = Σ贷方,差额非零说明分录不平衡,把差额截图发给会计排查(经理不手动改分录)。(见图 ②) - 利润表:切「利润表」Tab,选期间起止(当月 1 号 → 今天),点「生成」——看营收、成本、毛利、净利润。(见图 ③)
- 资产负债表:切「资产负债表」Tab,选截止日,点「生成」——三段式(资产 / 负债 / 所有者权益),「资产合计」= 「负债 + 权益合计」。(见图 ④)
- 现金流量表:切「现金流量表」Tab,选期间起止,点「生成」——三段(经营 / 投资 / 筹资)净流。(见图 ⑤)
- 四张表相互勾稽:利润表的净利润 → 资产负债表的未分配利润变动;现金流量表的期末现金 → 资产负债表的货币资金。
- 右上角「导出 PDF / Excel」给老板。
- 报表表头显示所选期间 + 基础币种(来自账套配置
accounting_books.base_currency)。 - 试算平衡底部 Σ 差额 = 0;有差额会高亮红色。
- 利润表底部「净利润」= 营收 − 成本 − 费用;资产负债表「资产合计」= 「负债 + 所有者权益合计」。
fetchTrialBalance({ asOfDate, includeZeroBalances })、fetchIncomeStatement({ periodStart, periodEnd })、fetchBalanceSheet({ asOfDate })、fetchCashFlowStatement({ periodStart, periodEnd });数据源限定 journal_entries.status='posted'。
fetchTrialBalance、fetchIncomeStatement、fetchBalanceSheet、fetchCashFlowStatement
2.6 关会计期间 / 重开期间
上月 1–3 日会计执行完月结结转后,经理正式把该期间置「已关账 closed」,锁定历史数据不让再改。
- 进
/dashboard/accounting/fiscal-periods,找到要关的年度卡片展开 12 个期间。(见图 ①) - 确认待关期间状态是「开启 open」,且未来期(序号更大)没有「开启」期——系统规则要求按顺序关账。
- 点该期行尾「关期」按钮——系统按乐观锁校验后把期间置「已关账 closed」。(见图 ②)
- toast 提示「已关闭」;徽标变灰色「已关账」。
- 发现错关要重开:同一行点「重开」按钮(仅「已关账」期显示),让会计补录凭证;重开后必须再关一次。
- 并发冲突提示「CONFLICT 数据已被其他用户修改」:刷新页面重试,不要多 tab 切换。
isDateInOpenPeriod 校验),会计再补时会被拦;关账前让会计先把所有凭证过账完(经理不代劳过账)。跨年度关账要先确认新年度已生成(createFiscalYearAction)——否则新年度没有「开启」期间会阻塞业务。
- 期间行徽标从「开启 open」变「已关账 closed」灰色。
- 统计卡片「已关账期间数」+1、「开启中期间数」−1。
- 该期日期范围内不再允许新建凭证——会计过账会报「Period is closed」。
accounting_periods.status='closed',closed_by / closed_at 回填;乐观锁 version+1。
updatePeriodStatusAction、getClosingPreviewAction(预览结转数)
2.7 对比历史期间(利润表 / 现金流量表多期横向)
老板问「本月营收和上月 / 去年同期比如何」——生成两份不同期间的利润表对比。
- 进
/dashboard/reports切「利润表」Tab。 - 先生成本月:期间起
2026-04-01止2026-04-30,点「生成」并导出 PDF。 - 再生成上月:改为
2026-03-01到2026-03-31,导出 PDF。 - 去年同期:改为
2025-04-01到2025-04-30,导出。 - 用 Excel / 自定义报表把三份横向拼表交老板。
- 现金流量表同理,三段净流横向比。
- 切换期间参数后点「生成」,表头期间显示更新。
- 数字行随期间变动,「净利润」行数值不同。
fetchIncomeStatement({ periodStart, periodEnd });每次独立查询,无缓存叠加。
fetchIncomeStatement、fetchCashFlowStatement
2.8 自定义报表与导出(审计清单 / 月度看板)
审计人员要一份「本月所有 > ¥10000 报销明细」;老板要按部门看费用分布——标准三表不够用时走自定义报表。
- 进
/dashboard/reports/custom看已有报表列表;想复用别人的报表看「公开」标记(isPublic=true)的公开模板。(见图 ①) - 点「新建报表」弹窗:填名称、选类型(销售 / 库存 / 客户 / 财务)、公开与否。
- 提交后进报表详情页——拖拽实体 / 列 / 筛选 / 分组 / 聚合 / 排序。(见图 ②)
- 筛选条件写法参考已有公开模板的 config——常用
{ 字段, 运算符, 值 }三元组。 - 点「生成」预览;满意点「导出 Excel」。
- 导出审计清单示例:报表类型「财务」、实体「报销单 expense_claims」、筛选「金额 > 10000」、列选「申请人 / 金额 / 日期 / 审批人」。
- 报表列表出现新行,名称 + 类型 + 创建人。
- 详情页「预览」按钮点后表格刷新数据。
- 导出 Excel 后浏览器下载区出现
.xlsx文件。
reports.id、reports.config JSON;生命周期 createReport → updateReport → deleteReport。
createReport、updateReport、deleteReport
上下游交接契约
经理处于「审批 + 复核」节点——上游出纳 / 员工 / 会计把动作推上来,下游老板 / 会计按结论继续。字段缺失会卡住整条链路。
员工 → 经理:报销申请
我做什么:看队列里「待财务审批」单据——逐单或批量放行 / 驳回;驳回必须写原因。
员工看到什么:企微收到「审批通过 / 驳回」卡片;驳回卡片含经理填的原因,员工可改单重新提交。
缺失会回来找我:驳回原因空——员工不知哪里错,反复提交;放行后员工看不到下一步进度——员工以为没动,来问经理。
技术字段(给 IT / 员工交叉核对)
触发动作:approveClaimAction(claimId, comments?) / rejectClaimAction(claimId, reason)。
必传字段:claimId;reason(reject 必填);comments?(approve 可选)。
出纳 → 经理:付款执行完毕
出纳做什么:银行实际打款后点「标为已付」,报销单状态从「已审批 approved」变「已付 paid」。
经理看到什么:付款看板「已付金额」上升、「已批待付」下降;看板数字刷新。
缺失会回来找我:出纳忘标「已付」——看板上「已批待付」虚高,经理追着出纳问;误标「已付」——员工以为没到账来问,需走会计冲销付款凭证。
技术字段(给 IT / 出纳交叉核对)
触发动作:getPaymentPageData(经理只读);markClaimAsPaidAction(出纳执行)。
读取字段:PaymentStats.approvedPendingPayment、totalApproved、processingAmount、paidAmount。
会计 → 经理:月结完成
会计做什么:执行月结(executeClosingAction('monthly'))——把收入 / 费用科目余额结转到「本年利润」,月结状态变「已完成 completed」。
经理看到什么:收到会计 IM 或系统「月结完成」通知;经理接力出三大报表、正式关账。
缺失会回来找我:会计月结没跑完就关账——资产负债表的「未分配利润」算错,报表交老板后被发现,经理要回头走「冲销月结」。
技术字段(给 IT / 会计交叉核对)
触发动作(会计):executeClosingAction;(经理):updatePeriodStatusAction(id, 'closed', version)。
依赖字段:period_closings.status='completed'、journal_entry_id、total_revenue / total_expense / net_profit。
部门预算员 → 经理:预算审批
起草人做什么:建预算、录 12 列月度表、点「提交审批」——预算状态从「草稿 draft」变「待审批 pending_approval」。
经理看到什么:预算列表筛「待审批」出现新行;详情页露出「通过 / 驳回」按钮。
缺失会回来找我:起草人漏填科目 / 成本中心 → 差异表维度缺(经理驳回让补);「已审批」后起草人发现错——系统会拒绝修改,让起草人自行建 v2。
技术字段(给 IT / 起草人交叉核对)
触发动作:approveBudgetAction(budgetId) / rejectBudgetAction(budgetId)。
必传字段:budgetId;读取 budgets.status、budget_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)— 重开已关账期,需最新 versionreverseClosingAction(closingId, reason)— 冲销月结,生成reference_type='reversal'凭证rejectBudgetAction— 把 pending_approval / approved 预算置 rejected;保留历史deleteReport— 删自定义报表;不可撤销
进阶功能
退回修改(比驳回更柔的审批回退)
员工单据基本合理只是附件不全 / 金额细节错——用「退回修改」让员工改后重交,避免「已驳回」的终态。在单据详情页走工作流 transition 回到「草稿 draft」。
系统动作:executeExpenseClaimTransitionAction、getExpenseClaimTransitions、getExpenseClaimWorkflowState。
新建下一年度(会计年度 Fiscal Year)
年末必须提前建下年度:按账套「财年起始月」生成 12 个会计期间。非历年财年(如 4 月 1 日 – 次年 3 月 31 日)靠「起始月」参数控制。
入口:/dashboard/accounting/fiscal-periods 右上「创建年度」按钮;系统动作 createFiscalYearAction(year, startMonth?)。
月结结转预览(关账前先试跑)
关账前会计先跑「结转预览」看本期「总收入 / 总费用 / 净利润」;经理也能看预览对比自己的利润表,差额异常时提前发现。在结账对话框里展开。
系统动作:getClosingPreviewAction、executeClosingAction。
费用科目维护(启停开关)
老科目 / 停用科目:/dashboard/expenses/categories 用开关启停「有效」标记——停用后员工报销下拉不再出现,但历史单据不变。不要直接删,会影响历史报表。
系统动作:toggleCategoryStatusAction、createExpenseCategoryAction、updateExpenseCategoryAction、deleteExpenseCategoryAction。
费用分类分析 / 月度趋势
/dashboard/expenses/reports 按费用科目聚合本月 / 历史费用,带月度趋势折线。每周看一次趋势异常(某科目突增 50%)。
入口:/dashboard/expenses/reports;服务层 expense-claims 聚合查询。
付款进度监控(只读)
/dashboard/expenses/payments 看四个数字:「已批待付 / 已付 / 处理中 / 总批准」。经理只看不执行——出纳点「标为已付」完成闭环;若看板长期「已批待付」偏高,催出纳。
系统动作:getPaymentPageData(读);markClaimAsPaidAction / batchMarkClaimsAsPaidAction(出纳写)。
相关业务场景
- 标准成单流(询盘 → 报价 → 订单 → 发货 → 开票): 财务经理不参与销售侧执行;仅在利润表 / 现金流量表里看营收数据、AR 账龄由会计维护经理复核。 → 场景(了解即可)
- 定制家具项目流: 财务经理在「项目预算」审批时参与,核算项目成本对比预算;日常生产 / 交付不参与。 → 场景详解
-
回款流:
财务经理监控应收账龄(由会计在
/dashboard/accounting/ar-aging产出),异常时找出纳追款;不直接录收款。 → 场景详解 - 采购付款流: 财务经理审批大额「付款申请 payment_requests」 / 供应商付款(触动预算时走审批);出纳执行付款,会计入账。 → 场景详解
- 月结流: 财务经理的核心场景——会计月结后经理做试算平衡、出三表、正式关账;发现错走「冲销月结」。 → 场景详解
- 报销审批流: 财务经理是 finance 节点——> ¥5000 经部门经理后到经理,> ¥50000 经理过后推总监;批量放行 / 驳回是日常主要工作量。 → 场景详解
外部协作入口
/dashboard/wecom— 企微推送 / 企微报销映射规则;企微来源报销走企微内审批,经理在 DaoSales 看不到(已知 gap)。/dashboard/accounting/ar-aging— 应收账龄看板(会计产出、经理复核)。/dashboard/accounting/ap-aging— 应付账龄看板。/dashboard/accounting/cash-flow-forecast— 未来 30 / 60 / 90 天现金流预测(滚动预测基础)。/dashboard/accounting/profit-analysis— 盈利分析(会计做,经理验收)。/dashboard/reports/custom— 自定义报表生态(公开模板共享)。/dashboard/settings/email— 邮件网关(报表 PDF 导出后发老板用)。
权限与范围
看得到什么(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.id、budget_type ∈ annual | quarterly | monthly | project- 预算明细 budget_items
budget_items.janAmount … decAmount(12 列月度)——迁移未应用时不存在- 预算差异 variance
variance = budgetAmount - actualAmount;isOverBudget: 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 | cashier、approval_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_sql 查 information_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)历史凭证被删除或修改过。让会计查「草稿 + 过账异常」凭证清单后统一补 / 过,再回来试算。