多公司进销存系统设计:从账套隔离到权限控制的关键实践

多公司进销存系统设计:从账套隔离到权限控制的关键实践 在集团型企业和多分支商贸公司里多公司进销存并不是把几家公司放到同一个菜单里简单管理而是要让每一家公司拥有独立账套、独立库存、独立财务核算同时总部又能按需跨公司合并查询。很多团队第一次设计这类系统时容易在数据隔离方式、账套归属、权限边界三个地方反复返工。本文围绕“多公司进销存、多账套财务、分公司独立核算”这条主线先从概念讲清账套与公司的关系再对比数据隔离方案然后给出可落地的表结构、关键流程、权限控制和验证方式最后补充常见问题排查与上线建议。无论你是准备选型这类软件的商贸公司负责人还是要自研这套系统的技术人员都能从中找到直接可用的判断依据和设计参考。1. 先理解多公司场景中的“账套”到底是什么在正式设计表结构和写代码之前必须先统一业务口径。很多项目返工并不是因为代码写错而是把“公司”“账套”“仓库”“核算主体”几个概念混在一起。1.1 账套的含义一整套独立核算的数据边界通俗地说账套就是一套独立的数据集合。一个账套通常包含会计科目表、期初余额、业务单据、库存记录、凭证、固定资产卡片、期末报表。选中某个账套时用户看到的应当是完整且封闭的一套业务数据不能夹带其他公司的数据。用更技术化的话说账套是一个逻辑隔离域。账套内单据编号可以独立从 1 开始账套内期初库存、期初应收应付、期初科目余额各自成立账套内月末结账、年度结转互不影响。常见的映射关系有两种一家公司一个账套。这是最常见的情况分公司经营独立税务独立财务也需要单独出报表。一家公司多个账套。例如一家公司同时维护“对外税务账”和“内部管理账”两套数据规则不同但底层业务来源相同。设计中不要强行规定“公司就是账套”。数据库里应把公司组织和账套核算域拆成两个维度默认一对一但保留一对多的扩展能力。1.2 一套软件管理多家公司核心要解决三件事从业务角度看集团总部关心的是汇总分公司关心的是独立。一套系统要在同一套代码里同时满足这两类诉求必须解决三个问题第一数据隔离。任何一张业务表都要能回答“这条数据属于哪个公司、哪个账套”否则查询报表时会出现串数。串数是多公司系统里最严重的数据事故。第二流程隔离。分公司 A 的采购入库审批流不能触发分公司 B 的库存变化分公司 A 的销售单不能把成本结到分公司 B 的账上。第三合并视图。总部需要一个跨账套的查询层能按公司汇总采购金额、销售金额、库存总量和应收应付余额。合并视图只做读取不直接修改各分公司数据。这三件事决定了后续所有模块的设计。下面的章节就是围绕这三件事逐步展开。2. 数据隔离方案选型决定后续所有开发量的关键决策多公司系统的第一步不是写业务而是选数据隔离方案。方案选错后面接客开单、报表合并、权限控制都会很痛苦。2.1 三种常见隔离方案对比业界做多租户或多组织系统数据隔离通常有三种做法。这里用表格直观对比再给出推荐组合。方案隔离粒度开发复杂度部署与运维成本适合场景独立数据库一个公司一个数据库中需要动态数据源高备份、升级、迁移都要逐库处理大客户、强隔离要求共享数据库、独立 Schema一个公司一个 Schema中高需要动态 Schema 切换中数据库实例少但结构数量多中大型客户或定制项目共享数据库、共享 Schema、租户字段所有公司在同一套表中用公司字段区分低一套表一把梭低备份升级都简单中小型集团、商贸公司、SaaS 产品对多数商贸型集团和分公司模式来说第三种方案性价比最高。原因有三分公司数量通常在几个到几十个单表数据量可控。业务需要跨公司合并查询共享表结构做 UNION 或维度汇总最方便。上线和升级只需要维护一套数据库结构运维成本低。2.2 共享表结构下如何避免“大杂烩”共享表结构不等于不隔离。隔离靠两个东西表结构上的公司字段 查询层的强制过滤条件。每张业务表必须包含两个关键字段company_id所属公司用于组织维度隔离。account_book_id所属账套用于核算维度隔离。为什么两个字段都要因为一家公司可能开多个账套而总部合并统计又经常要跨公司。只有公司字段没有账套字段管理账和税务账会混在一起只有账套字段没有公司字段跨公司合并报表时就缺少组织维度。基础资料表要区分层级。商品、供应商、客户这类数据有些是集团共享的有些是公司私有的。推荐在基础资料表上也加一个data_scope字段取值为GROUP或COMPANY并配合company_id一起使用。集团共享资料可以被所有分公司引用公司私有资料只能被本公司单据引用。2.3 独立数据库方案在什么情况下才值得选择虽然共享表结构适合大部分场景但以下情况应该考虑独立数据库或独立 Schema分公司数量少但单体数据量极大例如每家公司每年产生上千万条流水。客户对数据隔离有合规要求要求不同法人主体物理分库。某些分公司需要独立部署、独立升级不能和集团共用一套发布流程。采用独立数据库时业务逻辑层要有统一的“数据源路由”抽象。常见做法是将公司编号与数据源 Key 做成映射表在请求进入服务层的拦截器里切换到对应数据源。这个方案的开发量明显高于共享表结构选型时要做好成本评估。3. 组织架构与账套模型设计先搭骨架再写业务确定隔离方案后下一步是设计组织与账套骨架。这部分是后续所有模块的地基建议先建表、先跑通基础数据维护再进入采购销售库存开发。3.1 一个可落地的组织模型设计上把组织分成三层集团最高层可以查看所有公司的汇总数据。公司承担经营责任和核算责任的法人主体。部门/仓库公司内部的业务单元业务单据上的归属单位。对应到数据库至少需要公司表和账套表两张核心表。下面给出 MySQL 风格的建表示例字段可根据实际项目调整。-- 公司表 CREATE TABLE t_sys_company ( id BIGINT PRIMARY KEY AUTO_INCREMENT, company_code VARCHAR(32) NOT NULL COMMENT 公司编码全局唯一, company_name VARCHAR(128) NOT NULL COMMENT 公司名称, parent_id BIGINT DEFAULT 0 COMMENT 上级公司ID集团为0, sort_no INT DEFAULT 0, status TINYINT DEFAULT 1 COMMENT 1启用 0停用, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_company_code (company_code) ) COMMENT 公司/组织表; -- 账套表 CREATE TABLE t_sys_account_book ( id BIGINT PRIMARY KEY AUTO_INCREMENT, company_id BIGINT NOT NULL COMMENT 所属公司, book_code VARCHAR(32) NOT NULL, book_name VARCHAR(128) NOT NULL COMMENT 账套名称如对外税务账、管理账, start_date DATE NULL COMMENT 启用日期, fiscal_year INT NULL COMMENT 当前会计年度, currency_code VARCHAR(16) DEFAULT CNY COMMENT 本位币, status TINYINT DEFAULT 1, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_book_code (book_code), KEY idx_company (company_id) ) COMMENT 账套表;这里要解释三个设计意图。第一公司编码必须全局唯一。在实际项目中公司编码会出现在单据编号前缀、数据源路由 Key、对接外部系统的主数据编码里一旦重复会造成串单。第二账套表用company_id指向公司而不是把公司信息冗余到账套表。这样可以支持“一个公司多个账套”的扩展。第三会计年度字段放在账套表而不是公司表因为年度结转是按账套执行的。每个账套可能有不同的启用日期和当前期间。3.2 基础资料如何按层级共享基础资料是另一个容易踩坑的地方。以商品档案为例集团希望同一个商品编码全集团统一但分公司又希望维护自己专属的商品例如包装规格不同的内部料号。推荐这样设计CREATE TABLE t_biz_product ( id BIGINT PRIMARY KEY AUTO_INCREMENT, product_code VARCHAR(64) NOT NULL, product_name VARCHAR(128) NOT NULL, spec VARCHAR(64) DEFAULT , unit VARCHAR(16) DEFAULT 件, data_scope TINYINT NOT NULL DEFAULT 1 COMMENT 1集团共享 2公司私有, company_id BIGINT DEFAULT 0 COMMENT data_scope2时必填, status TINYINT DEFAULT 1, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) COMMENT 商品档案;查询商品列表时逻辑是data_scope 1的商品全部可见data_scope 2且company_id 当前公司的商品可见。这个逻辑要封装成公共查询服务避免每个菜单都各写一遍。供应商、客户、仓库、部门等基础资料同理。基础资料的共享层级设计直接决定后续销售订单一来选择客户时能不能正确过滤出本公司客户。3.3 账套初始化应该包含什么一个账套启用时要完成以下初始化动作缺一不可创建会计科目表。可以从行业模板复制科目也可以通过 Excel 导入期初科目。设置账套参数。包括本位币、启用期间、数量小数位、单价小数位、库存成本核算方式。录入期初余额。包括库存期初、应收期初、应付期初、银行期初、科目期初。配置单据编号规则。通常按“账套 单据类型 年月 流水号”生成。初始化最好做成一个独立的功能菜单而不是在数据库里手工 INSERT。因为在初始化过程中系统要生成账套参数记录、科目记录、期初余额台账并且要做数据校验例如期初库存数量和单价不能为负期初科目借贷必须平衡。注意对学习环境来说手工建表和初始化数据可以加快跑通进度但生产环境必须通过程序完成账套初始化并保留初始化日志否则上线后很难追踪“这个账套当时启用了哪些参数”。4. 进销存核心流程在多账套下的实现要点进销存是多公司系统的核心业务域包含采购、销售、库存、盘点、调拨等流程。多账套环境下每个流程都要回答两个问题单据属于哪个账套单据操作会影响哪个账套的库存和往来4.1 采购入库从订单到入库单的隔离采购业务通常分成两步采购订单和采购入库单。订单是业务意向入库单才真正影响库存。关键设计是采购订单表、采购入库单表、入库明细表都要携带company_id和account_book_id。下拉选供应商时只显示当前公司的供应商系统在页面查询接口就按当前登录公司过滤。CREATE TABLE t_purchase_inbound ( id BIGINT PRIMARY KEY AUTO_INCREMENT, inbound_no VARCHAR(40) NOT NULL, company_id BIGINT NOT NULL, account_book_id BIGINT NOT NULL, supplier_id BIGINT NOT NULL, warehouse_id BIGINT NOT NULL, inbound_date DATE NOT NULL, total_amount DECIMAL(20, 6) DEFAULT 0 COMMENT 含税金额, status TINYINT DEFAULT 0 COMMENT 0草稿 1已审核 2已红冲, create_by BIGINT, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_inbound_no (inbound_no), KEY idx_company_book (company_id, account_book_id) ) COMMENT 采购入库单;采购入库审核时系统要同时做两件事增加对应仓库的库存库存明细记录来源单据号、供应商、单价、批次。生成应付暂估或直接生成采购凭证。如果采用暂估入库财务凭证是“借存货 贷应付暂估”。这里最容易犯的错是只更新了库存数量没有更新库存成本导致后续销售出库时成本计算错误。库存成本更新必须和入库单审核放在同一个数据库事务里。4.2 销售出库成本结转与往来确认销售出库的流程类似。销售订单审核后生成出库单出库单审核时做两件事扣减对应仓库库存记录出库数量、出库单价、出库成本。生成应收账款确认销售收入同时结转销售成本到主营业务成本。成本计算方式需要提前定好。商贸类企业常用移动加权平均法即每次入库后重新计算库存平均单价。-- 库存余额台账 CREATE TABLE t_stock_balance ( id BIGINT PRIMARY KEY AUTO_INCREMENT, company_id BIGINT NOT NULL, account_book_id BIGINT NOT NULL, warehouse_id BIGINT NOT NULL, product_id BIGINT NOT NULL, batch_no VARCHAR(64) DEFAULT , quantity DECIMAL(20, 4) DEFAULT 0 COMMENT 数量, cost_price DECIMAL(20, 6) DEFAULT 0 COMMENT 移动加权平均成本, amount DECIMAL(20, 6) DEFAULT 0, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_stock (company_id, account_book_id, warehouse_id, product_id, batch_no) ) COMMENT 库存余额台账;移动加权平均的逻辑是新平均单价 (原库存金额 本次入库金额) / (原库存数量 本次入库数量)。出库时按当前平均单价结转成本。这个公式要在代码里实现成独立服务并加上并发控制。统一使用SELECT ... FOR UPDATE锁定库存行避免两个单据同时审核时超卖或成本异常。4.3 盘点与调拨多仓库、多账套的分界盘点单处理的是“账面库存与实际库存的差异”。盘点流程中盘点表按仓库生成盘点完成后生成盘盈盘亏单盘盈盘亏单审核后影响库存余额。调拨分两种同账套内调拨只是仓库 A 到仓库 B不改变公司库存总量。跨账套调拨发生在集团下属两家公司之间本质上是一家公司销售、另一家公司采购。跨账套调拨不能只写一张调拨单。推荐设计为“调拨申请单”加“调出方的其他出库单”加“调入方的其他入库单”三者通过source_bill_no关联。调出方按出库价减少库存调入方按调入价增加库存双方分别在自己的账套内生成往来和凭证。这样财务核算才是清晰的。4.4 库存账要能追本溯源库存模块必须维护流水账。每次入库、出库、盘点、调拨都写一条库存流水流水表记录变化前数量、变化后数量、单据号、操作人、操作时间。CREATE TABLE t_stock_flow ( id BIGINT PRIMARY KEY AUTO_INCREMENT, company_id BIGINT NOT NULL, account_book_id BIGINT NOT NULL, warehouse_id BIGINT NOT NULL, product_id BIGINT NOT NULL, flow_type TINYINT NOT NULL COMMENT 1入库 2出库 3盘盈 4盘亏 5调出 6调入, bill_no VARCHAR(40) NOT NULL COMMENT 来源单据号, before_qty DECIMAL(20, 4) DEFAULT 0, change_qty DECIMAL(20, 4) DEFAULT 0, after_qty DECIMAL(20, 4) DEFAULT 0, cost_price DECIMAL(20, 6) DEFAULT 0, create_by BIGINT, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_product_warehouse (company_id, account_book_id, product_id, warehouse_id) ) COMMENT 库存流水;有了库存流水才能回答用户最常问的问题“这个批次这个商品为什么库存多了两百件”没有流水账的进销存系统库存对不上时基本无法排查。5. 财务模块与业务模块如何共用同一套账套多公司软件最容易出现业务和财务“两张皮”的问题。业务单据在进销存里查得到但财务凭证没有自动生成导致月底财务还要手工录入一遍。5.1 进销存单据与财务凭证的衔接规则推荐的做法是业务单据审核时按照预置的凭证模板自动生成一张草稿凭证进入会计的“待审核凭证”池。会计核对无误后审核过账。凭证模板可以按单据类型和业务方向配置例如业务单据借方科目贷方科目触发条件采购入库单存货应付暂估/应付账款审核通过销售出库单收入应收账款主营业务收入审核通过销售出库单成本主营业务成本存货审核通过采购付款单应付账款银行存款审核通过销售收款单银行存款应收账款审核通过生成凭证时科目可以从商品档案或供应商档案的“默认科目”字段带出。如果带不出科目就把凭证标记为“待完善”不允许审核。这样设计可以避免月底出现大量借贷不平的凭证。5.2 独立做账与合并报表如何并存总部财务要的合并报表不应该直接查分公司账套的数据表。推荐增加一个“跨账套报表查询”层专门做汇总按公司汇总销售收入、采购成本、库存余额。按集团汇总应收应付、资金余额。合并时先做内部往来抵消例如集团内部调拨产生的应收应付要抵消。实现上可以有两种方式一种是在应用层分别查询每个账套再汇总适合公司数量少的情况另一种是把各账套数据按统一口径抽取到报表库适合公司数量多、报表频繁查询的情况。第二种方式要注意抽取任务失败时的补偿机制保证报表数据不丢不重。5.3 凭证、科目、期末结账的隔离财务模块的每张凭证都要带account_book_id。凭证号在一个账套内连续禁止跨账套连续。会计科目表也属于账套级基础资料每个账套可以有自己的科目体系。不过实际项目中集团通常会统一下发科目模板保证各公司报表格式一致。实现方式是建账套时从“集团科目模板”复制科目复制后允许分公司在权限范围内局部调整但集团科目模板变更时要提供“对比和增量同步”功能。期末结账是另一个容易出问题的节点。每个账套自行执行“存货成本结转 - 计提费用 - 结转损益 - 月末结账”。A 公司结账不影响 B 公司未结账状态。系统要提供集团视角的“各公司结账状态表”方便总部财务跟踪。注意跨账套结账时不能使用全局锁把整个系统锁住。否则一个分公司结账慢会拖累所有分公司正常操作。应该只锁定当前账套的相关表或者使用乐观锁记录账套版本号。6. 权限与数据范围控制防止账号能串到别的公司数据多公司系统的权限不是简单的“菜单权限 按钮权限”还必须包含“数据权限”也就是登录一个分公司账号时后端查询必须自动带上该公司的过滤条件。6.1 用户、角色、数据权限三层模型建议使用三张表用户表保存登录账号、密码、所属公司、状态。角色表定义系统角色例如集团管理员、分公司经理、会计、仓管。用户角色关系表一个用户可以有多个角色。除业务角色外还需要一个数据权限范围字段用来标识用户能看到哪些账套的数据。常见取值数据范围说明使用对象全部账套查询时不过滤账套可跨公司汇总集团管理员指定公司及其下级按组织树过滤集团下属区域负责人指定账套只看本公司一个账套分公司财务、仓管仅本人数据只看自己创建的单据普通业务员6.2 数据权限拦截的实现思路数据权限必须是后端行为不能只靠前端隐藏菜单来保证。常见实现是使用 ORM 拦截器在查询时自动拼接company_id和account_book_id条件。下面是 MyBatis 拦截器的示意逻辑用于说明思路实际项目要结合自己的框架版本调整Intercepts({ Signature(type StatementHandler.class, method prepare, args {Connection.class, Integer.class}) }) public class DataScopeInterceptor implements Interceptor { Override public Object intercept(Invocation invocation) throws Throwable { // 1. 从当前线程上下文获取登录账套 UserContext ctx UserContextHolder.get(); // 2. 改写 SQL追加 company_id 和 account_book_id 条件 // 如果是关联查询还要在处理主表别名后生成正确条件 // 3. 白名单表不追加例如系统配置表 return invocation.proceed(); } }实现拦截器要注意三个细节拦截规则必须支持表白名单。公司表、账套表、用户表本身不能加公司条件否则连登录后的基本信息都查不出来。关联查询要处理表别名。如果 SQL 是SELECT p.* FROM t_biz_product p LEFT JOIN ...拼接条件时应该写成AND p.company_id ?不能漏掉别名。禁止通过在 Mapper XML 里每个查询手写company_id条件来替代拦截器。手写容易漏新来的开发加一个查询忘记加条件就会造成串账而且很难被发现。另一种更稳妥的方式是手写透明的查询层所有业务查询都经过统一的DataScopeService组装条件。虽然初期开发量大但可控性更高。6.3 集团管理员与分公司管理员的分工权限设计要区分两类管理员集团管理员可以创建公司、创建账套、维护集团共享商品和供应商、查看汇总报表但不应直接编辑分公司具体单据。分公司管理员在自己所属公司范围内创建用户、维护本公司基础资料、审核本公司单据、执行本公司结账。一个常见的错误是把所有权限都给了集团管理员导致集团管理员不小心改了分公司单据月底对账时责任无法界定。建议集团管理员默认只有“只读 导出”权限涉及数据修改必须走审计流程操作日志留痕。7. 运行验证与常见问题排查多公司系统上线前验证不能只验证“功能能跑”要专项验证“隔离是否生效”。这部分给出可操作的验证清单和排查路径。7.1 上线前功能验证清单验证项操作方式预期结果账套初始化新建一家分公司并启用账套生成独立科目、单据编号从 1 开始跨账套串数检查A 账套录入客户B 账套查询该客户B 账套看不到 A 的私有客户库存隔离A 公司采购入库查 B 公司库存B 公司库存不变财务凭证生成审核采购入库单自动生成暂估凭证科目与单据一致报表合并两家公司分别出库查集团汇总汇总数量等于两家之和权限过滤分公司会计登录直接调用其它公司查询接口返回结果为空或被拦截结账互不影响A 公司结账同时操作 B 公司单据B 公司操作正常A 公司锁定期内不可改每一项验证都要记录测试数据和结果截图最好做成自动化测试的一部分。特别是“串数检查”建议每次迭代都跑一遍回归脚本。7.2 常见问题现象、原因与处理问题现象常见原因检查方式处理建议B 公司能看到 A 公司的客户查询条件未过滤 company_id或基础资料 data_scope 判断错误查看 SQL 日志确认是否带 company_id 条件补过滤条件检查数据权限拦截器是否覆盖该 Mapper库存数量正确但金额不对成本计算没有按账套隔离或并发时重复计算平均价对比库存流水和成本明细入库和出库放在同一事务库存行加行锁单据编号重复编号生成只用了公司维度没有用账套维度查询单据表唯一索引编号规则调整为账套 类型 年月 流水号月底结账时系统卡死结账事务锁范围过大锁到了其他账套表查看数据库锁等待与事务 SQL缩小锁粒度按账套分表或按数据行加锁报表汇总金额翻倍合并报表时内部调拨没有抵消检查调拨单是否同时生成调出和调入两笔在合并层增加内部往来抵消规则用户离开公司后仍能访问用户与公司关系未同步停用检查用户状态和会话缓存停用用户时踢出会话并使缓存失效7.3 从现象倒推的排查链路遇到“某个功能数据不对”时按以下顺序排查确认当前登录用户所属公司与账套。先看登录上下文排除看错账套的可能。确认页面传入的查询参数。是否带掉了 company_id、account_book_id 参数。查看应用输出的 SQL。确认 SQL 中是否自动拼上了账套条件条件值是否正确。查看单据和流水。业务单据是否生成库存流水是否写入流水数量变化是否连续。查看凭证和科目。业务单据审核后是否生成凭证科目是否为空借贷是否平衡。查看数据库锁和慢查询日志。如果数据正确但操作慢需要考虑索引和锁。这条链路几乎能覆盖 80% 的多账套数据问题。无论什么模块出错先确认“数据到底落在哪个账套”再确认“查询时是否按这个账套过滤”往往很快能定位根因。8. 最佳实践与扩展方向8.1 开发落地时的检查清单每张业务表都包含company_id和account_book_id并建联合索引。单据编号规则按账套独立生成使用数据库唯一索引兜底。基础资料按集团共享、公司私有分层查询公共服务统一处理。库存余额更新和成本计算放在同一事务中库存行使用SELECT ... FOR UPDATE。数据权限过滤放在后端拦截器或公共查询层禁止依赖前端隐藏。凭证生成使用模板驱动生成后进入待审核池禁止业务单据直接写入已过账凭证。所有关键操作审核、反审核、结账、红冲写操作日志。表结构变更通过迁移脚本执行不手工改生产库。8.2 生产环境额外要注意的事情学习环境可以只在一台机器上跑通功能但生产环境必须补齐以下能力数据库备份和恢复演练。多账套数据都集中在一套库时备份粒度要大恢复验证要定期做。日志与监控。按公司、账套、用户维度记录关键操作日志同时监控慢 SQL 和库存异常。性能设计。库存余额表、流水表要按 company_id 账套 商品建联合索引单据列表查询必须分页避免全表扫描。异常补偿。业务单据审核和凭证生成如果跨服务调用需要设计重试或对账机制避免一处成功、一处失败。数据导入导出。上线初期通常要导入历史库存和往来余额导入工具必须有模板校验、错误行提示、幂等机制。8.3 扩展方向从进销存走向集团一体化多公司进销存是集团信息化的入口。系统跑稳后可以逐步扩展这些方向集团采购中心分公司共享供应商资源和采购价格集中采购后再按需调拨给各公司。合并报表先做进销存层面的汇总再扩展财务合并报表处理内部交易抵消。多组织核算从单一账套扩展到利润中心、成本中心维度让一个分公司内部也能按业务线独立核算。库存预留与齐套检查在销售订单下达时检查可用库存支持按仓库、按批次、按预留类型分配。移动端作业仓管用移动端扫码收货、发货、盘点减少手工录入错误。对团队来说最重要的建议是先在一个最小账套范围内把采购、销售、库存、财务凭证跑通再扩展多公司套用。多公司系统不是把单公司代码复制十份而是从一开始就按“数据隔离字段 统一查询层”去设计。设计上守住隔离边界业务上保留合并视图这套系统才能真正服务好集团企业的管理需求。