1. 项目背景与需求分析
在传统ERP系统中,库存管理通常依赖于基础的商品编码、批号等单一维度。但随着企业业务复杂度提升,越来越多的客户需要从多个维度对库存进行精细化管理。以某食品加工企业为例,他们不仅需要跟踪原料的批次信息,还需要记录供应商来源、质检状态等额外属性。
天通ERP的标准批号字段原本只支持单一字符序列,但通过本文介绍的组合拆分技术,我们可以将多个管理维度压缩存储在一个字段中。这种方案特别适合以下场景:
- 需要新增管理维度但系统字段数量有限
- 现有报表结构不允许新增列
- 希望保持原有业务流程不变的情况下扩展功能
提示:这种方案本质上是利用系统现有字段实现"字段复用",在数据录入阶段合并信息,在报表展示阶段拆分还原。选择@作为分隔符是因为该符号在业务数据中极少出现,能有效避免字符冲突。
2. 技术方案设计思路
2.1 字段组合原理
核心思路是通过JavaScript公式将多个字段值拼接为复合批号。在本案例中:
- 往来单位(billdiyfullname_ud28):标识原料供应商
- 批次(系统标准批号字段):记录生产批次号
- 分隔符(@):用于后续拆分的定位标记
组合后的批号格式为:供应商A@20240501-001
2.2 技术选型考量
选择JavaScript实现公式计算主要基于:
- 天通ERP内置V8引擎支持ES6语法
- 相比SQL公式更灵活处理字符串
- 可直接操作行对象(thatRow)实现即时计算
- 调试信息可通过console.log输出
注意:如果所有字段都是文本类型,建议优先使用系统自带的字段拼接功能("文本A"+"文本B"),只有在涉及特殊字段类型时才需要采用JS方案。
3. 详细实现步骤
3.1 采购入库单配置
3.1.1 自定义字段设置
- 进入【系统管理】-【单据自定义】
- 选择采购入库单表体
- 添加两个自定义字段:
- 文本字段:用于手工输入质检状态等附加信息
- 往来单位字段:关联供应商主数据
配置参数示例:
| 字段类型 | 字段名称 | 字段编码 | 是否必填 |
|---|---|---|---|
| 文本 | 质检状态 | quality_check | 否 |
| 往来单位 | 供应商 | supplier | 是 |
3.1.2 JS公式配置
在表体设置中找到【备注】字段,启用公式计算并输入:
javascript复制var thatjs = true;
if(thatRow) {
thatRow.goodsnumber = thatRow.billdiyfullname_ud28 + '@' + thatRow.batchcode;
// 调试时可取消下方注释
// console.log('组合批号:', thatRow.goodsnumber);
}
关键参数说明:
thatRow:当前行对象billdiyfullname_ud28:往来单位字段的系统编码batchcode:系统标准批号字段编码goodsnumber:最终输出的批号字段
3.2 报表字段拆分实现
3.2.1 往来单位提取公式
在报表设计器中新建计算字段:
javascript复制var sifValueName = function(){
let cstr = [批号];
let match = String(cstr).split('@');
if (match && match.length > 1) {
return match[0];
}
return '未知供应商';
}
return sifValueName();
3.2.2 批次提取公式
javascript复制var sifValueName = function(){
let cstr = [批号];
let match = String(cstr).split('@');
if (match && match.length > 1) {
return match[1];
}
return cstr; // 兼容未组合的旧数据
}
return sifValueName();
4. 实战经验与优化建议
4.1 性能优化方案
当处理大量数据时,建议:
- 在报表SQL中直接使用SUBSTRING_INDEX函数拆分:
sql复制SELECT SUBSTRING_INDEX(batch_no, '@', 1) AS supplier, SUBSTRING_INDEX(batch_no, '@', -1) AS batch_code FROM stock_detail - 建立函数索引加速查询:
sql复制CREATE INDEX idx_batch_supplier ON stock_detail ((SUBSTRING_INDEX(batch_no, '@', 1)));
4.2 异常数据处理
实际应用中需考虑以下边界情况:
- 历史数据中可能不存在@分隔符
- 用户可能误输入包含@的非法字符
- 字段组合顺序可能调整
改进后的健壮性代码示例:
javascript复制// 组合公式增强版
var thatjs = true;
if(thatRow) {
let supplier = (thatRow.billdiyfullname_ud28 || '').replace(/@/g, '');
let batch = (thatRow.batchcode || '').replace(/@/g, '');
thatRow.goodsnumber = supplier + '@' + batch;
}
5. 扩展应用场景
5.1 多维度组合
可以扩展为三级组合:
javascript复制thatRow.goodsnumber = [
thatRow.supplier,
thatRow.quality_check,
thatRow.batchcode
].join('@');
5.2 动态分隔符方案
在系统参数表中配置分隔符:
javascript复制let separator = getSystemParam('batch_separator') || '@';
thatRow.goodsnumber = thatRow.supplier + separator + thatRow.batchcode;
5.3 条码打印集成
在打印模板中直接拆分批号:
javascript复制var barcodeText = function(){
let parts = [批号].split('@');
return `供应商:${parts[0]}\n批次:${parts[1]}`;
}
6. 常见问题排查
6.1 公式不生效检查清单
- 确认公式开关已启用
- 检查字段编码是否正确
- 查看浏览器控制台是否有JS错误
- 验证用户是否有公式编辑权限
6.2 数据不一致处理
当发现组合与拆分结果不符时:
- 检查是否有空格等不可见字符
- 验证分隔符是否统一
- 确认各环节公式版本一致
6.3 性能问题处理
若报表加载变慢:
- 避免在循环中使用复杂JS拆分
- 考虑在数据库层面预处理
- 对大数据量报表增加分页处理
我在多个客户现场实施这套方案时,发现最常出现的问题是历史数据迁移。建议在新功能上线前,先用以下SQL检查数据质量:
sql复制-- 查找可能造成问题的现有批号
SELECT batch_no FROM stock_detail
WHERE batch_no LIKE '%@%'
OR batch_no LIKE '% %'
OR LENGTH(batch_no) > 50;
对于需要频繁查询的维度字段,可以考虑在数据库中建立物化视图,定期将拆解后的维度同步到专用字段,这样既能保持方案的灵活性,又能获得更好的查询性能。