☰
REA模型实战:用资源-事件-代理重构业务语义与对账逻辑
2026/10/21 4:57:04 网站建设 项目流程

先说一个我印象特别深的场景:去年帮朋友复盘一个进销存系统,对账对了两天,最后的根因特别尴尬——销售出库单和收款单在数据库里各自为政,靠状态位互相拉扯。查“到底谁欠钱”的时候,得写一堆 join 加条件判断,任何一个人改错了状态位,整个账面就对不上。这种问题我见过太多次,它往往不是某个字段设计得不合理,而是整个团队从一开始就没有把业务语义主线立起来。后来我重新研究 REA(Resources-Events-Agents,资源-事件-代理)模型,发现它正好解决的就是这件事。

REA 最早是被提出用于会计信息系统设计的业务建模方法,圈子并不大,但确实有用。它逼着你在建表和写接口之前把所有业务动作拆成“谁、在什么时候、对公司什么资源做了什么”,再把这些动作串成因果链。对做订单、库存、账务、风控这类系统的人来说,理解 REA 以后再看业务,眼光会完全不一样。这篇就用一个采购闭环的完整案例讲透它,顺带复盘我落地过程中踩过的坑。

1. REA到底解决什么问题:业务建模里“看不见的语义”

1.1 从一次对账事故说起

那个进销存系统的设计其实非常有代表性:销售表、出库表、收款表、退款表各有一套,表之间用订单号弱关联,然后用一堆“状态”字段表达进度。表面上看 ER 是完整的,客户、订单、流水都有,但真要回答“哪些销售还没有收齐钱”,就得把所有表 join 一遍,再用状态位做排除法。更麻烦的是,出库和收款往往不是同一套流程,中间还隔着一道“应收款”的概念,而这个概念在表结构里根本不存在,只存在于开发人员的注释里。

这就暴露了传统 ER 建模的一个盲区:ER 能描述“有哪些对象、对象之间是什么关系”,但它不负责告诉你“哪些事件必须成对出现、资源从哪一方流动到哪一方”。而业务真正的规则恰恰藏在这里——一次销售必然伴随着资源的流出,一次收款必然伴随着补偿性的资源流入,这两个事实之间有一个不可分割的经济互换关系。

我用 REA 之后最大的变化是:建模的第一步不再是画表,而是问自己,这个业务里有哪些“经济事实”?每个事实是谁发起的、涉及什么资源、在什么时间点发生、跟哪个事实是配对的?把这些排清楚了,表结构反而是水到渠成的事。

1.2 REA三要素:资源、事件、代理分别指什么

REA 把所有业务浓缩成三类东西。

资源(Resources):公司拥有或控制、具有经济价值的东西。不只是库存商品和现金,也包括应收账款、预付款、设备产能、在制品。判断依据很简单——它能不能被交换、能不能被损耗、能不能形成债权债务。

事件(Events):改变资源状态的经济活动。典型的有采购收货、销售出库、收付款、生产领料、完工入库。注意这里的事件不是随便一条系统日志,必须是有经济语义的原子动作。

代理(Agents):参与事件的个人或组织。内部代理是员工、部门,外部代理是客户、供应商、物流商。强调一点:REA 通常要求一个完整的经济事件同时关联至少一个内部代理和至少一个外部代理,因为它要回答“谁对谁做了什么”。

三个要素组合起来,就能描述任何业务动作。再加上三条核心规则:每个事件至少关联一个资源和一个代理;每个减量事件必然与一个或多个增量事件配对(形成经济互换或转化);承诺/契约与实际执行要沿着责任链对齐。这套规则就是后面所有推导的基础。

1.3 它回答的四个关键问题

把 REA 用到实际业务里,它主要帮你回答四个问题:

谁是交易对手,各自承担什么角色;资源的控制权在哪个时点发生了转移;哪些业务事实之间存在成对关系,允许哪些组合;业务承诺到这个承诺被真正执行中间,有没有断点。

这四个问题,传统 ER 画图时没人逼你想。这也是为什么很多系统上线时功能正常,一运行到对账、审计、纠纷仲裁就到处漏风。

2. 把一个采购闭环拆成REA三要素:一单到底的资源-事件-代理

2.1 场景设定:从下单到付款的完整循环

光讲概念太空,我们走一遍具体业务:某制造公司要向一家供应商采购 500 套传感器,单价 30 元,整个流程大概长这样:

采购员在系统里提交采购申请,部门审批通过后转成正式采购订单。供应商确认采购订单。仓库到货后做收货入库,形成入库单。财务根据入库单和发票确认应付账款。出纳在账期内向供应商付款。车间领用 500 套传感器进入生产。生产完工后传感器变成产成品入库。

这套流程在很多企业的 ERP 里跑了好多年,大部分人习以为常。但用 REA 的镜头看,它有一个隐藏的主线——资源的控制权在不同代理之间一次次换手。你只需要找出每次换手的事实,就能完整重建整个采购业务,不需要任何“状态字段”的辅助。

2.2 资源清单:不只是“库存商品”

在这个闭环里,出现的资源至少有这么几类:

原材料(传感器):进来的时候是供应商给公司,领用的时候是公司内部转移。现金存款:付款时从公司流出到供应商。应付账款:严格来说它不是实物资源,但它代表公司未来需要向供应商兑付资源的经济义务,在 REA 里作为资源建模,目的是让“欠钱”这件事本身可以被记录和追踪。在制品和产成品:生产转化流程中出现的中间资源。

说到这我想特别强调一个容易混淆的地方:现金流水不是资源,银行账户里的存款才是资源。应收款余额也不是资源,它是由“交付了但未来会收到钱”的一系列事件推导出来的状态。“流水”和“余额”都是资源变动留下的痕迹,是派生数据,不是业务事实本身。

2.3 事件与代理识别表:五个核心经济事件

把上面的采购闭环拆下来,核心经济事件和对应代理如下:

事件资源方向内部代理外部代理
供应商发货/公司收货传感器流入仓库管理员供应商
确认应付账款应付账款增加财务核算员供应商
支付货款现金流出、应付减少出纳供应商
车间领料传感器流出领料员(内部转化)
完工入库在制品流出、产成品流入车间主管(内部转化)

顺着这个表再看业务,你会发现以前很容易忽略的一点:采购订单、审批记录、库存状态这些统统不是经济事件。它们要么是“承诺层”的东西,要么是管理状态,真正改写资源的是上面这几个动作。

2.4 成对规则的魅力:为什么 REA 不需要“借贷方向”

会计里记明细账讲究借贷,借表示资源流入,贷表示资源流出。REA 更彻底,它只记录“哪个事件让资源进来、哪个事件让资源出去”,并且强制它们成对出现。

比如确认应付账款这个事件,让“应付账款”这个资源增加(对公司来说这是一个索取权的反转方向),之后付款事件让“现金”减少,同时让“应付账款”减少。在系统里,你不需要约定这笔业务是借还是贷,只需要把事件和资源的方向记录下来,余额自然就能算出来。这对于开发人员更友好:不用去理解复式记账的规则,只需要保证每个减量事件都有对应的原因事件,账就不会平不了。

3. 事件是事实,余额是推导:这套模型如何帮你重构账务逻辑

3.1 从事件集合推导余额:一种可审计的对账思路

REA 一个反直觉的点是:正式模型里根本不保存余额。库存数量是多少?不是查库存表,而是把“所有入库类事件”加总减去“所有出库类事件”加总。应付余额是多少?也是从“确认应付事件”和“付款事件”的差得到。

用 SQL 表示就是:

-- 物料库存 = 所有收货事件总量 - 所有领用事件总量 SELECT resource_id, SUM(CASE WHEN event_type IN ('RECEIVE') THEN quantity ELSE 0 END) - SUM(CASE WHEN event_type IN ('ISSUE', 'CONSUME') THEN quantity ELSE 0 END) AS stock_balance FROM economic_events WHERE resource_id = :sensor_resource_id GROUP BY resource_id;

这套逻辑最大的好处是可审计——任何余额都能追溯到一组已知事件,而不是某个“被人手一改就再也讲不清”的数字。对财务、风控、法务来说,这不只是实现细节,而是真实性问题。

3.2 用配对规则自动发现业务异常

成对规则还能直接用来做完整性校验。如果销售系统里存在“已经发完货,但既没有生成应收、也没有后续收款”的事件,那基本就是业务异常。放到采购侧也一样:有收货却没有对应付款义务,说明应付流程断了。

实际应用时,我会在事件表里维护“配对关系字段”或者建立配对事件关联表,然后定期跑类似下面这段的未配对检查:

-- 找出所有已收货但尚未形成应付记录的事件 SELECT e.event_id, e.event_time, e.resource_id, e.quantity FROM economic_events e LEFT JOIN economic_events_pairing p ON e.event_id = p.decrement_event_id WHERE e.event_type = 'RECEIVE' AND p.increment_event_id IS NULL;

这类查询逻辑上非常直白,因为模型里天然要维护“每一笔源的流入都有对应源头流出关系”。以前要在十几个表的状态字段里绕来绕去才勉强查清的“差异”,在 REA 数据模型里只是一条简单的 join。

3.3 REA与事件溯源:语义约束和存储架构可以各司其职

很多做分布式系统的朋友会联想到事件溯源(Event Sourcing),它们的理念确实有亲缘关系:都是把“事实”作为核心,把“当前状态”当成投影。但二者有本质不同。

事件溯源是一种架构实现策略,关心“怎么追加存储、怎么重放事件流、怎么保证幂等”;REA 是一种领域建模方法,关心“这些事件是否有经济语义、哪些事件必须成对出现、资源和代理怎么关联”。两者可以配合使用,而不是竞争关系:用 REA 定义业务域里的经济事件和配对规则,用事件溯源作为存储和集成的实现底座。这样既能获得可追溯、可回放的架构优势,也不会把“用户改了个昵称”这种没有经济语义的事件混进账户体系。

4. REA、ER模型和“三个最常踩的坑”

4.1 REA不是ER的替代品,而是语义层

REA 和 ER 经常被放在对立面,这是误解。我认为最准确的定位是:REA 关心这个业务“应该被怎么理解”,ER 关心“理解完之后用什么表来存储”。而且一张设计良好的 ER 图完全可以表达 REA 模型的结论——无非是资源表、事件流水表、代理角色表、承诺与执行链条表。

关键差别在于建模次序。传统做法是“先想表,再想业务”;REA 是“先想事件事实与配对,再落成表”。如果已经有一套 ER 模型,也可以拿 REA 三要素去评审现有表结构,这是成本最低的接触方式。

4.2 坑一:代理被压成单纯的外键字段

最常见的失误是把“代理”只建造成订单一侧的 customer_id 和 seller_id,所有人都当成普通外键看。麻烦很快会来:同一家客户,既可能是收货方,也可能是付款方,还可能是开票方;一旦三方不是同一主体,你只能继续加字段,或者用字符串拼状态,审计和风控全都别扭。

REA 的建议是让“人/组织”与“角色”分离。party(主体)是一张表,客户、供应商、内部部门这些“角色”是另一张关系或字典,事件只关联“在特定业务场景下承担特定角色的主体”。这样每个事件都能干净地回答“谁以什么身份做了什么”。

4.3 坑二:把流程活动当成经济事件

第二个高频坑是把“修改”“审核”“状态流转”也当事件往主事件表里灌。订单从草稿到已确认、审批人点了通过,这些确实发生了“变化”,但并没有任何资源控制权转移,它们不是 REA 意义上的经济事件。把它们混入事件流,会让所有聚合和配对检查全部失真。

我的判断标准很硬:只有导致资源进入、退出、消耗、转化或债权债务产生的行为,才能进入经济事件表。流程审批与状态机单独用流程表管,别跟经济事件混在一张表里。

4.4 坑三:资源语义漂移,把记录体当资源

还有一个坑藏在命名里:有人把“现金流水表”当成资源,有人把“应收余额字段”当成资源,还有人把“库存台账”这个记录当成了库存本身。这都犯了同一个毛病——把资源的“影像”和资源本身搞混。

资源是那笔钱本身,流水只是它的履历;资源是库房里那堆实物,台账只是它的纪录。建模时我会给资源主体表和流水表完全不同的命名前缀,比如 sensor_stock 代表资源本身,inventory_movement 代表它的事件轨迹,防止新人一上来就把两张表当成一回事。

5. 落地步骤与建模自检清单

5.1 三步走:先圈定互换闭环,再映射到表结构

想在一个新项目里落地 REA,我建议别一上来就想全公司建模。先选一个你最头疼的“钱货闭环”,比如“销售-收款”或者“采购-付款”,走这三步:

第一步,列出这个闭环里的全部资源,包括实物资源和债权债务类资源。第二步,列出全部经济事件,给每个事件标出内部代理、外部代理和资源方向。第三步,检查每个减量事件是否有对应的增量事件,画一张事件配对矩阵。

配对矩阵我一般就用表格手工画,例如销售-收款闭环:

减量事件对应增量事件配对语义
商品出库确认应收账款把货交给客户,同时取得了未来收款权
应收账款核销收款入账收到钱,应收义务终结
退款支出商品退回(如适用)交易退回,资源逆向流动

矩阵画完,表结构怎么落其实已经定了,照事件清单建流水表,照资源清单建资源表,照代理清单建主体和角色表即可。

5.2 一张自检问题清单

每次建模接近完成,我会拿下面几个问题当验收标准,全部能回答清楚才算过:

每个经济事件是否同时关联了至少一个内部代理和一个外部代理?资源变动是否都能落实到具体经济事件,而不是靠直接修改状态字段?所有减量事件是否都有关联的增量事件形成闭环?资源表是否明显区别于流水表,没有把记录体冒充成资源?承诺层与执行层之间是否有一条可追踪的链条?

我实际用下来,这几个问题能挡掉至少一半的返工。

5.3 推进策略:把它当评审工具,而不是文档仪式

最后说点推广层面的体会。REA 在团队里容易遇冷,因为它不像 ER 图那样接近设计师直觉,术语也有点“会计味”。我的建议是别强求所有人都会画正规的 REA 图,而是在评审表结构或定义接口事件时用 REA 三要素提问:这是资源、事件还是代理?这个事件配对了吗?这个资源有没有对应的流水主体?

只要评审会上大家习惯性问出这些问题,语义就自然而然变得清楚了。我自己踩过几次坑之后,现在反而更愿意把 REA 定位成“提问范式”,而不是必须填的文档模板。它能让你在讨论阶段就把那些以后会让财务、风控和开发集体头疼的问题提前暴露出来,远比画图本身值钱。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询