
在企业管理软件领域,进销存与财务模块长期存在割裂现象。进销存负责记录业务流——采购、销售、库存调拨;财务负责资金流与会计账务。两者分离会导致数据重复录入、对账困难、业务与财务延迟。从0到1开发一套一体化软件,核心不是写代码,而是设计一个让业务单据自动生成会计凭证、库存变动实时影响成本账的数据模型。本文从架构视角,梳理关键设计决策。
采购管理:采购订单、入库单、采购退货、暂估入库
销售管理:销售订单、出库单、销售退货
库存管理:仓库、货位、批次、序列号、盘点、调拨
存货核算:成本计算方法(移动加权平均、先进先出、个别计价)、成本调整单
总账:科目表、凭证、期末结转、损益结转
应收应付:发票、收款单、付款单、核销、账龄分析
固定资产(可选):资产卡片、折旧、处置
报表:资产负债表、利润表、现金流量表
核心桥接点包括:
采购入库 → 借记“库存商品”,贷记“应付账款-暂估”或“材料采购”
采购发票与暂估差异 → 调整成本及应付
销售出库 → 借记“主营业务成本”,贷记“库存商品”
销售发票 → 借记“应收账款”,贷记“主营业务收入”、“应交税费”
收款/付款 → 核销应收/应付
这些桥接规则必须可配置,不能硬编码。
建议采用分层架构,自下而上:
基础设施层:数据库、消息队列、缓存、对象存储
数据访问层:仓储模式、工作单元、多租户隔离
领域模型层:聚合根(采购单、销售单、凭证)、值对象、领域事件
应用服务层:编排领域对象完成用例(如“审核销售出库单”)
API/接口层:RESTful API、消息端点、Webhook
前端层:桌面Web、移动端适配
领域模型层不依赖外部框架,纯业务逻辑
应用服务层协调事务和事件发布
财务记账逻辑不应散落在进销存各模块,应通过事件订阅或明确的记账服务完成
建议按业务能力划分模块,而非按技术分层划分模块:
库存模块
采购模块
销售模块
应收模块
应付模块
总账模块
报表模块
模块间通过明确的API或领域事件通信。例如:采购模块发布“采购入库已确认”事件,库存模块订阅并增加库存,存货核算模块订阅并记录入库成本,应付模块订阅并生成应付暂估单。
单据主表统一字段:
单据类型(区分采购入库、销售出库、收款、付款等)
单据编号(业务唯一键,有规则可配置)
业务日期、审核日期、记账日期
审核状态、记账状态(是否已生成凭证)
来源单据ID(例如退货单引用原销售单)
分录行设计:
每个单据有明细行(数量、单价、金额)
库存单据行含仓库、货位、批次
财务单据行含科目、借方金额、贷方金额、辅助核算(部门、项目、客户、供应商)
科目表:科目编码、名称、类别(资产、负债、权益、收入、费用)、余额方向、是否辅助核算、是否停用
凭证表:凭证字、号、日期、附件数、制单人、审核人、记账状态
凭证分录表:科目、摘要、借方、贷方、辅助核算JSON或关联表
往来核销表:业务单据(发票/收款单)之间的核销关系、核销金额
库存成本不能只依赖商品平均成本字段,因为每批入库成本可能不同。应设计成本明细账:
入库流水(参考成本、实际成本)
出库流水(按某种成本计算方法确定出库成本)
期末结存
当采用移动加权平均时,每次入库需重新计算新的平均成本,并回写出库单成本(如果未审核出库)。这涉及大量性能与并发问题,建议采用数据库行锁或乐观锁。
典型流程:
采购订单 → 收货 → 采购入库单(审核)
触发:借:库存商品(暂估) 贷:应付账款-暂估
收到供应商发票 → 采购发票录入
根据发票金额与暂估差异生成红蓝字调整单或成本调整单
生成正式应付凭证:借:应付账款-暂估 借/贷:材料成本差异 贷:应付账款-供应商
付款 → 付款单
借:应付账款-供应商 贷:银行存款
销售出库(审核)→ 确认成本
借:主营业务成本 贷:库存商品
开具销售发票 → 确认收入与应收
借:应收账款 贷:主营业务收入 贷:应交税费-销项税
跨期业务:已入库未收到发票,月底暂估,下月初红冲,再按发票入账。
退货:销售退货需反向冲减成本,同时红冲收入(或开具红字发票),不允许直接删除原单。
采购退货:冲减库存和应付暂估。
成本重算:历史月份因补录单据导致成本变化,提供成本调整单,不修改历史出库单,而是生成调整凭证入当期损益或存货。
单个业务操作(如审核销售出库单)可能同时修改库存、生成凭证、更新订单状态。如果放在一个数据库事务中,会导致事务过长,且财务记账可能因科目配置错误而回滚整个业务。不推荐。
建议采用工作单元模式将库存扣减作为主事务,记财务账通过领域事件异步处理,最终一致。但财务要求严格一致?中小企业可容忍短暂不一致,大型企业需提供对账与补偿机制。
折中方案:
同一数据库内,通过柔性事务(SAGA)或本地消息表保证最终一致性。
关键操作(如付款核销)必须同步记账,可拆分为更小的事务。
库存关账:截止某个时间点后不允许修改库存单据,保证成本计算闭合。
财务期末结转:结转损益至本年利润,计算所得税,结账后一般不允许修改业务单据;如需修改需反结账,这是设计复杂点。
应提供“取消审核→修改→重新审核→重新生成凭证”的完整流程,并标记旧凭证作废(红冲),非物理删除。
支持多企业(如不同分公司或客户)时,采用共享表+租户ID或每个租户独立数据库。前者降低运维复杂度,但需严格防范跨租户数据泄露,所有查询自动加上租户过滤器。
用户不应手工选择每个存货对应的收入、成本、应付暂估科目。应设计科目映射规则表,规则例如:
商品类别为“电子产品” → 收入科目“主营业务收入-电子”
供应商类别“增值税一般纳税人” → 应付暂估科目等
灵活性很重要:支持按仓库、部门、商品属性组合判断。
移动加权平均每次都需从成本明细账中查询最近结存。对于每日数万条出入库,查询会变慢。优化方式:
使用汇总表存储每个商品每日的期初数量和成本
或改用月末一次加权平均(性能好但实时性弱)
或引入列式数据库或时序数据库存储成本流水,关系库只存最终结果
财务数据和库存数据严禁物理删除。所有删除操作实质是标记“已删除”或插入红冲记录。审核后的单据不允许直接修改,必须通过“反审核→修改→重新审核”流程,且原版本需存档。
为了减少代码改动适应不同行业(商贸、服务、生产加工),软件应支持:
单据类型可扩展:用户可增加自定义单据(如“委托代销出库”),并配置其财务影响规则
凭证模板引擎:类似于“来源单据字段→科目取值”的公式:科目 = IF(单据类型=‘采购入库’ AND 计价类别=‘暂估’, ‘应付账款-暂估’, ‘应付账款’)
审批流程可配置:简单单据无需审批,大额采购单需两级审批
辅助核算项可自定义:部门、项目、客户、员工等
出库数量不能大于可用库存(考虑批次锁定)
已核销的应收单不能直接修改,应提示“请先反核销”
已结账期间的凭证不允许红冲,必须先反结账
当自动生成凭证失败时(如科目未映射),不要只记录后台错误,应在前端审核单据时给出明确提示:“请检查商品[XX]的收入科目映射”。
提供业务台账与财务科目的对账报表:
库存余额汇总与总账存货科目余额比对
应收模块汇总与总账应收账款科目比对
差异追踪工具
一体化软件对数据完整性要求高,推荐数据库采用高可用主从或集群,定期自动备份。对于初次使用者,应提供演示数据和默认会计科目表、凭证模板,降低入门门槛。
监控重点:
未处理的领域事件数量(如事件消费失败导致库存与账务不同步)
成本计算任务的执行时长
月末关账卡点(如未审核单据、未生成凭证的记录数量)
从0到1开发进销存+财务一体化软件,技术实现是次要的,核心是业务语义的准确建模和业务与财务的可靠桥接。设计决策点包括:
选择单据驱动记账,还是独立记账模块?
事务强一致还是最终一致?
成本计算方法是实时还是月末?
科目映射是硬编码还是规则引擎?
没有任何架构是完美的,但一套清晰的分层、事件驱动的模块通信、灵活的凭证模板,可以为后续功能扩展和性能优化打下基础。实际开发中,建议优先完成采购入库→生成暂估凭证、销售出库→结转成本、收款核销这三个主流程,再逐步增加退货、跨期、成本调整等复杂场景。先把核心路径跑通,再优化细节。
架构的目的是控制复杂度,不是追求最先进的技术。对于进销存+财务这类关键业务系统,稳定、可审计、可追溯远比高并发重要。