ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

易飞ERP品号单位切换:换算率、历史单据与金额校验全解析

易飞ERP品号单位切换:换算率、历史单据与金额校验全解析

简介:易飞ERP品号单位切换工具,专为需要批量调整或修正品号计量单位的实施顾问、IT维护人员及ERP管理员设计。工具以轻量zip包提供,共包含2个文件:用于执行单位切换与数据修正的SQL脚本,以及梳理涉及单据和数据表关系的Excel说明表格,整个压缩包仅9KB,便于快速部署使用。SQL脚本可针对品号主档及相关交易记录进行单位批量修正;Excel说明则清楚列出切换所影响的单据类型、数据表字段与关联逻辑,帮助使用者在执行前评估影响范围,降低误操作风险。例如在采购、库存、销售等环节遇到品号单位需从一种转换为另一种时,可先借助Excel核对受影响数据,再通过SQL脚本完成实际切换,避免手工逐笔修改的疏漏。目前已有470人学习/下载,适合在易飞ERP日常维护、数据清理或项目切换阶段作为参考工具使用。

1. 易飞ERP品号单位切换:为什么同一个品号要让系统记两本账

易飞ERP品号单位切换,听起来是品号档案里那个单位下拉框一换就完事的小功能,实际上它对应着ERP维护里最典型的一个翻车点:某天你打开品号档案,把钢材这个品号从「公斤」切到「吨」,库存数量瞬间缩水一千倍,库存金额却纹丝不动,月底财务报表怎么对都对不上。品号单位切换真正要做的事,不是改一个下拉框,而是把数量、单价、金额三条数据链在同一套换算率下同步换算,同时保证历史单据口径一致、新开单据默认单位正确。这篇笔记按我做过的方案,从底层逻辑讲到操作流程、参数边界和避坑记录,适合实施顾问、企业内部IT和负责ERP长期维护的工程师参考。

2. 单位切换的底层逻辑:换算率、价格基准与历史单据的三角关系

2.1 基本单位与交易单位:为什么不能直接在品号档案里改单位

在易飞ERP里,每个品号有一个库存单位,也就是基本单位。系统里所有数量字段最终都要折算到基本单位上去记账,这个单位通常是采购、库存和财务共同认可的最小计量口径。而采购单、销售单、领料单上显示和录入的单位叫交易单位,是业务人员日常使用的口径。

这两者必须分开理解。品号档案里的单位字段一旦被直接修改,系统不会认为你是想「换个口径」,它会认为这个品号从此以后就按新单位入库。历史单据上还是老单位,新单据上已经是新单位,采购入库按新单位收,库存结存却按老单位算,两端直接对不上。更麻烦的是,单价基准也随单位漂移了——原来一公斤五块钱,改成吨以后单价如果不跟着换算,金额链就断了。

我一般不会去直接改动品号档案的库存单位,而是先查清楚这个品号的历史单据跨度。如果历史单据量很大,方案就变成「在单据层面做单位切换」:保留基本单位不动,给品号建立一套单位换算关系,让交易单位在单据上换成目标单位,同时把历史单据的数量、单价按换算率重算一遍。这套思路的出发点就是:基本单位是锚,不能动;交易单位是变量,可以切。

2.2 数量、单价与金额:切换时三条数据链各自要动什么

切换单位之所以容易翻车,是因为它同时牵动三条数据链,而且每条链的换算方向不一样。

数量链是最直观的。库存数量按基本单位存,单据数量按交易单位录。如果基本单位是公斤,交易单位从公斤切到吨,那么一张单据里录入1吨,系统要靠换算率1吨=1000公斤推出库存数量1000公斤。历史单据反过来处理:原本按公斤填的数量,刷新时要么把单位改成吨、数值除以1000,要么保持底层数量不变、只改显示单位。这两种做法选哪种,取决于业务上要保留哪一端的口径。

单价链和数量链方向相反。单价永远跟着交易单位走,一吨钢材3000元,切到公斤后应该是3元/公斤。这就是单位切换里最容易写反的一处:数量除以换算率,单价就要乘以换算率;数量乘以换算率,单价就要除以换算率。两处不一致,金额必然变化。

金额链是最终的校验标尺。金额等于数量乘以单价,一次设计正确的切换,应该让每笔单据的金额保持不变。只要数量单价换算方向有一处反了,或者换算率建反了方向,金额就会平白多出一千倍或者少掉一千倍。所以我在做切换前一定会先导出金额快照,切换后再逐笔核对,金额差异是判断切换是否正确的第一信号。

2.3 常见做法:三件套式切换的构成

一套完整的品号单位切换方案,常见做法是拆成三个模块,缺一个都会出问题。

第一个模块是换算率维护。给品号建立「基本单位到交易单位」的换算关系,同时定义换算精度和舍入方式。这个模块看起来简单,却是后面所有步骤的地基。换算率一旦建错方向,后续所有单据刷新都会跟着错。

第二个模块是历史单据刷新程序。把旧单上的单位、数量、单价统一刷成新口径。核心逻辑就是上一节说的三条链:数量按正向或反向换算,单价按相反方向换算,金额保持不变。这个模块最需要谨慎,因为历史单据跨年度、跨期间,刷错了要回滚成本极高。

第三个模块是新开单据默认单位设置。把各类单据里的品号默认单位参数改成目标单位。这一步经常被忽略,结果就是历史单据变成了新单位,新开的采购单却还是旧单位,系统里同一品号两套口径并存。

三个模块按顺序跑,每一步都可以独立验证和回滚。这就是整个方案的基本盘,接下来我按这个框架讲具体操作。

3. 实操流程:从拿到zip包到完成一次干净的单位切换

3.1 切换前检查清单:先确认哪些品号能切、哪些不能切

拿到一个品号单位切换的开发包或方案包,不要急着跑刷新程序,先把前置检查做完。我每次都会先跑一遍下面的清单,确认品号是否具备切换条件。

需要检查的项目至少有这几项:品号是否有未结案的采购订单、销售订单、领料单和委外单;品号是否启用了批次或保质期管理;品号是否被BOM作为子件引用;品号历史单据的跨期间范围;品号已建立的换算关系是否符合业务实际。

其中未结案的订单是最主要的阻断项。一张未结案的采购订单,如果切换前是公斤,切换后变成了吨,后续入库数量按吨收,但采购单上的数量还是旧的公斤值,对账就会非常痛苦。

下面是检查未结订单的示意SQL,具体表名以实际环境为准。

SELECT IM.品号, COUNT(DISTINCT SO.单号) AS 未结销售单数, COUNT(DISTINCT PO.单号) AS 未结采购单数 FROM 品号档案 IM LEFT JOIN 销售订单明细 SO ON IM.品号 = SO.品号 AND SO.结案标记 = 'N' LEFT JOIN 采购订单明细 PO ON IM.品号 = PO.品号 AND PO.结案标记 = 'N' GROUP BY IM.品号 HAVING COUNT(DISTINCT SO.单号) > 0 OR COUNT(DISTINCT PO.单号) > 0

这段SQL的逻辑是:以品号档案为主表,分别关联销售订单和采购订单的明细,用结案标记过滤出未结案的记录,最后按品号分组计数。结案标记 = 'N'这个条件用来判断单据是否还在进行中。如果查询结果里某个品号有记录,说明这个品号存在未结案单据,不建议批量自动切换,需要人工确认处理方式。

所有前置检查的结果,应该整理成一张品号清单,标注每个品号是「可自动切换」「需人工处理」还是「不建议切换」。这张清单是后续操作的边界依据。

3.2 分步操作:维护换算率、刷新历史单据、验证新单据默认单位

前置检查做完,确认目标品号可以切换,就进入正式操作。整个操作分三步走,每一步都要有验证动作。

第一步是维护换算率。在单位换算关系维护界面,把基本单位、目标交易单位、换算率和舍入位数录入进去。比如某品号基本单位是公斤,目标交易单位是吨,换算率填1000,含义是1吨等于1000公斤。这里要特别注意换算方向的定义方式,确定「数值方向」是什么。如果系统约定的方向是「1交易单位 = 换算率 × 基本单位」,那数量从公斤切到吨就是除以1000;如果方向反了,算法就完全反过来了。我一般会在保存后先用一个测试品号验证一下方向。

第二步是刷新历史单据。这一步优先使用系统自带的重整程序或转换程序,因为自带的程序会同时处理关联子表,比如单据明细、库存异动、成本记录。如果没有现成程序,只能写SQL更新,那么一定先做备份表。

-- 切换前备份,备份表必须和原表在同一事务边界内 SELECT * INTO 销售订单明细_公斤切吨备份 FROM 销售订单明细 WHERE 品号 = :品号; -- 刷新历史单据:数量从公斤切到吨除以1000,单价从每公斤切到每吨乘以1000 BEGIN TRANSACTION; UPDATE 销售订单明细 SET 单位代码 = '吨', 数量 = ROUND(数量 / 1000.0000, 3), 单价 = ROUND(单价 * 1000.0000, 6) WHERE 品号 = :品号; -- 校验金额是否保持不变 SELECT COUNT(*) AS 金额不平笔数 FROM 销售订单明细 WHERE 品号 = :品号 AND ABS(ROUND(数量 * 单价, 2) - ROUND(:原金额, 2)) > 0.01; COMMIT;

这段SQL的逻辑:第一步把品号的销售订单明细备份到独立备份表,保证数据可回滚。第二步开启事务,把单位改成吨,数量除以1000,单价乘以1000。ROUND函数分别控制数量和单价的小数位,数量保留3位、单价保留6位是制造业的常见配置。第三步用金额校验来检查更新结果——切换后每行计算出的金额和切换前相比,差异不能超过0.01。如果金额不平笔数大于0,说明换算方向错了,需要回滚排查。

注意备份表必须放在切换逻辑之前,而且整个刷新过程要包在事务里。事务里任何一步失败,可以整体回滚,不会留下半切状态的数据。

第三步是验证新开单据默认单位。到各类单据的默认值设置里,把该品号的默认交易单位改成目标单位。这一步不只是改品号档案,要把采购订单、销售订单、领料单、委外单等各类单据的默认值都查一遍,改到位。改完之后实际新建一张测试单据,确认单据打开时默认单位就是吨,数量录入1时库存结存增加1000公斤。

3.3 关键SQL脚本与用途解析

除了刷新脚本,切换过程中最常用的还有两类查询脚本:一类是查单位换算关系是否已经在品号上生效,另一类是验证历史单据刷新后的金额一致性。

-- 查询品号的单位换算关系,确认换算率已生效 SELECT 品号, 基本单位, 交易单位, 换算率, 舍入方式 FROM 单位换算关系表 WHERE 品号 = :品号 AND 生效日期 <= CONVERT(DATE, GETDATE()); -- 验证刷新后单据金额与切换前一致 SELECT 单号, 品号, 单位代码, 数量, 单价, 数量 * 单价 AS 现金额, :原金额 AS 原金额, 数量 * 单价 - :原金额 AS 金额差异 FROM 销售订单明细 WHERE 品号 = :品号 AND ABS(数量 * 单价 - :原金额) > 0.01;

第一个查询的逻辑是:从单位换算关系表里查出该品号已经生效的换算记录,生效日期必须早于当前时间,避免拿到还没生效的配置。如果这里查不到记录,后面所有步骤都不用跑,回去先建换算关系。第二个查询是刷新后的验证明细,把现金额和原金额做差,差异超过0.01的行就是问题行,需要优先排查。

这两类脚本的作用,本质上就是把「切换前确认配置」和「切换后验证结果」这两个检查点固化成可重复执行的SQL。每次做切换,我都是先跑第一个,再跑刷新,最后跑第二个,顺序固定,少一步都不敢继续。

4. 参数与边界:换算率精度、舍入规则与单据转换的取舍

4.1 换算率怎么定:基本单位、交易单位与舍入基准

换算率不是一个简单的数字,它有三个维度需要同时定义。

第一个维度是方向。换算率定义成「1交易单位等于多少基本单位」,还是「1基本单位等于多少交易单位」,会直接改变所有后续计算公式。我建议在系统里统一采用「1目标交易单位 = 换算率 × 基本单位」的定义方式,换句话说,换算率填的是目标单位相对基本单位的倍数。1吨等于1000公斤,换算率就是1000。这个约定一旦定下来,全项目都要遵守,不要中途切换方向。

第二个维度是精度。数量保留几位小数、单价保留几位小数、金额保留几位小数,这三个参数直接决定换算后的尾差能不能被消化。制造业里,数量保留3位是常见配置,单价保留6位会更稳妥,因为单位切换后单价数值变化很大,精度不够就容易出现每张单据几分钱的尾差。系统参数里的数量小数位和单价小数位,切换前就要调到位。

第三个维度是舍入方式。四舍五入、向上取整、向下取整,三种方式在单据明细层和汇总层会产生不同结果。最常见的做法是明细行按四舍五入处理,但最后金额校验时按「总额优先」来调整,保证整张单据的金额是平的。如果每一行都独立四舍五入,行与行之间的尾差累积起来,到单据底部会莫名其妙多出几分钱。

换算率还有一个特殊要求:一旦历史单据刷新完成,换算率就不能再改了。改了也不会报错,但历史单据上的数量单价已经按旧换算率刷完,再改换算率不会反向更新历史数据,系统里就永久留下一个口径不一致的角落。所以切换前一定要冻结换算率,经过业务确认后再执行刷新。

4.2 单价换算的两种算法与选型依据

单价换算是单位切换里最容易翻车的地方。它的本质是:单价跟着交易单位走,交易单位换了,单价必须按换算率重新计算,而且方向必须和数量相反。

算法A适用于从小单位切到大单位。比如基本单位是公斤,交易单位从公斤切到吨。历史单据的数量是1000公斤,刷新后应该是1吨,数量除以1000;单价是5元一公斤,刷新后应该是5000元一吨,单价乘以1000。

算法B适用于从大单位切到小单位。比如基本单位是箱,交易单位从箱切到件,1箱等于12件。历史单据的数量是5箱,刷新后应该是60件,数量乘以12;单价是60元一箱,刷新后应该是5元一件,单价除以12。

选型依据就一句话:先确认换算率的定义方向,再决定用乘法还是除法。如果换算率定义成「1目标单位 = 换算率 × 基本单位」,那么从基本单位切到目标单位时,数量除以换算率、单价乘以换算率;从目标单位切回基本单位时,数量乘以换算率、单价除以换算率。

这里我要特别提醒:同一套换算率,数量和单价的运算方向永远是相反的。我见过不止一次的情况是,数量和单价格式对了,但两边都取了同一个方向,导致金额翻倍或者砍半。最简单的自检方法是:切换前后各取一行单据,用手算一遍金额是否相等,相等再继续批量跑。

4.3 切换范围边界:哪些品号建议人工干预

并不是所有品号都适合批量自动切换。有几类情况,我建议单独拿出来做人工处理,不让自动化脚本碰。

第一类是启用了批次或保质期管理的品号。这类品号的库存异动记录里带批次号,批次的可追溯性靠连续的异动记录维持。如果批量刷新历史单据,批次对应的数量记录可能被重算,追溯链就断了。真出了问题,查不到某一批货是哪个供应商、哪一天入的库。这类品号我只在切换前确认总金额一致,单笔历史记录尽量不碰。

第二类是有在途采购单或未开票销售单的品号。在途采购单还没入库,切换后采购单上的单位口径变了,后续入库时按新单位收,但采购单上的旧数量对不上。未开票销售单同理,发票还没开,单位一变,开票时数量和单价都要重算。我一般会等这批单据全部结案后再切。

第三类是被BOM作为子件大量引用的品号。BOM里的子件耗用量通常按某个单位填写,如果母件品号切换单位,而BOM子件单位没同步,领料单上显示的耗用量就会放大或缩小。所以切换前必须把BOM引用清单导出来,逐条确认子件单位的处理方式。

这三类边界不是绝对的,但有一个原则是通用的:涉及追溯、涉及未完结业务、涉及配方结构的数据,优先人工确认,而不是交给脚本一把梭。

5. 易飞ERP单位切换常见问题排查:5个翻车现场与解决路径

5.1 现象:切换后库存金额不平

切换后打开库存金额账,发现某品号的库存金额和切换前对不上,有时差得离谱,数量缩小一千倍、金额也缩小一千倍,或者反方向放大。

原因是数量和单价只换了一边。刷新脚本里只改数量没改单价,或者单价换算方向写反了。根本上是没理解数量链和单价链方向相反这个基本面。

解决办法是回头检查刷新脚本里数量和单价两个字段的运算方向。切到吨时数量除以换算率、单价乘以换算率,两者必须同时出现在一条UPDATE语句里。切换前的金额快照和切换后的金额逐品号比对,差异超过0.01的全部拉出来,手算几行确认。

5.2 现象:历史单据单位变了单价没变

刷新后打开历史销售单,单位已经变成吨,数量也变成吨对应的数值,但单价还是每公斤的价,整张单据金额明显不对。

原因是刷新脚本只更新了单位字段和数量字段,漏了单价字段。很多开发包里的刷新程序逻辑只处理了库存数量的口径,价格链没有跟进。

解决办法是刷新后立刻跑一遍金额校验,把金额不平的行找出来。校验SQL就是第3章那段金额差异查询。如果发现问题,直接从备份表恢复,把单价换算补上后重新刷新,不要在已刷新的数据上原地打补丁,那样修不干净。

5.3 现象:同一个品号采购单用新单位,销售单还是旧单位

切换后采购部门开新采购单时默认单位是吨,销售部门开销售单时默认单位还是公斤,同一个品号两套单位并行。

原因是不同单别有独立的默认单位参数,切换时只改了其中一部分。品号档案的默认单位改了,但各单别的默认值还保留着旧设置。

解决办法是把采购订单、销售订单、领料单、委外单、退货单等各类单据的默认单位设置整理成一张清单,切换时逐项核对,确保所有单别的默认单位都同步更新。这张清单在切换前就要列好,不能切完再回头补。

5.4 现象:切换过程中有并发的单据录入造成脏数据

切换当天白天跑刷新程序,业务人员还在正常开单。刷新脚本跑完的瞬间看数据是好的,第二天一查,发现有几张新单据的数量是旧单位,而库存异动已经按新单位折算,账实不符。

原因是刷新脚本没有考虑切换时间点的边界。脚本把所有单据都刷了一遍,包括在脚本运行期间新产生的单据,而新单据的默认单位可能是新单位也可能是旧单位,取决于用户的操作时机。

解决办法是把切换安排在业务静止时段,比如周末或月末结账后。刷新脚本里加上时间条件,只更新某个时间点之前建立的单据。同时切换期间对该品号做锁定,禁止新的出入库操作,等脚本跑完再解锁。

5.5 现象:小数位不够,每张单据都差几分钱

切换后逐笔核对,每张单据的金额差异都很小,几分钱到几毛钱不等。单看一张没什么感觉,月底汇总时发现差了几百块。

原因是换算后的数字超出了ERP当前配置的精度范围。比如换算率是1000,单价从5元变成5000元,单价小数位如果只保留2位,尾数会一直被截断或四舍五入掉。每张单据的尾差看起来小,单据多了就会累积成不可忽略的差异。

解决办法是切换前把数量小数位调到3-4位、单价小数位调到6位,切换后根据金额差异的情况再做调整。尾差处理上,优先保证单据整体的金额平,明细行舍入后产生的尾差在单据末尾统一修正,不要每行各自处理。

6. 切换后的验证脚本与长期维护习惯:怎么确认这次切换真的成功

6.1 用SQL对账:金额差异、单位字段、历史抽样三组检查

切换完成不等于事情结束,验证才是真正确认切换成功的环节。我每次都会跑三组检查:金额一致性、单位字段统一性、历史数据抽样复核。

金额一致性检查是把切换品号的所有单据明细按金额差异筛选出来,差异超过0.01的行逐笔确认原因。单位字段统一性检查是确认所有相关单据的单位代码都是目标单位,没有残留旧单位。历史抽样复核是从切换前三个月和切换后一个月各抽几笔单据,人工看一遍金额和数量逻辑。

-- 三组验证脚本合并执行 -- 组1:金额不平检查 SELECT '金额不平' AS 检查项, 单号, 品号, ABS(数量 * 单价 - :原金额) AS 差异 FROM 销售订单明细 WHERE 品号 = :品号 AND ABS(数量 * 单价 - :原金额) > 0.01 UNION ALL -- 组2:单位字段残留旧单位检查 SELECT '单位残留', 单号, 品号, 1 AS 差异 FROM 销售订单明细 WHERE 品号 = :品号 AND 单位代码 <> '吨' UNION ALL -- 组3:抽样单据数量一致性检查 SELECT '抽样数量差异' , 单号, 品号 , ABS(数量 - :原数量 * 1.0 / 1000) AS 差异 FROM 销售订单明细 WHERE 品号 = :品号 AND 单号 IN (:抽样单号1, :抽样单号2, :抽样单号3);

这段脚本把三组检查合并到一次执行里,每个检查项返回差异记录。组1查金额不平的行,组2查单位字段没切干净的行,组3查抽样单据的数量是否按换算率正确折算。三组都返回空结果,这次切换才算真正通过。

6.2 长期维护习惯:分层备份、切换记录表、季度抽查

验证通过以后,还要把维护习惯固定下来,不然下次切换还是得从头踩一遍坑。

层备份是第一步。切换前做一次数据库级备份,导出一份全部相关单据明细的文本备份,再建一个切换专用备份表。三层备份放在不同位置,万一后面发现问题,随时能回到切换前的状态。

切换记录表是第二步。每次切换结束,把时间戳、品号、旧单位、新单位、换算率、刷新范围、操作人、验证结果记录到一张维护表里。这张表平时看着没什么用,半年后出问题复盘时,它就是唯一的线索来源。

季度抽查是第三步。每个季度挑几个切换过的品号,把库存数量乘上换算率,对照基本单位下的原始记录,确认没有后续单据把口径带偏。这个习惯花不了多少时间,但能及时发现新开单据默认单位被谁改回去的情况。

说到这个,想起有一次切换漏了BOM子件单位,导致车间整整一个月的领料数量都偏大,查了三天才发现源头在配方关系上。那之后我把BOM引用检查写进了前置清单,再也没犯过同样的错。单位切换这种事,谨慎永远比聪明管用。希望这篇笔记能帮你少踩几个坑,一次就把切换做干净。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进