一,实现方式
由于需求的编码规则较为复杂,需要按照不同的物料类别设置不同的参数,且对应参数的值不同,需要按照选定的参数值对编码和名称进行处理,且成品和原材料的编码方式截然不同:
方式(一)
在物料档案当中添加上对应的参数字段,采用基础资料类型,在选值时可按照物料分组的编码设置BeforeSelectF7的过滤条件,不同物料分组选择不同的参数,最后改写插件可实现不同的分组 使用不同的编码规则,值得注意的是对应单据不能勾选默认规则,否则方法可能失效。该方法以失败告终,需要设计的字段和编码规则过于繁琐,不满足目前的需求。
public class BillCodeRulePlugIn : AbstractBillPlugIn { public override void BeforeSave(BeforeSaveEventArgs e) { base.BeforeSave(e); //获取物料分组是否是特定编码规则分组 var groupData = this.Model.DataObject["MaterialGroup"]; if (groupData != null && groupData is DynamicObject) { string specifiedGroupNum = "2.BCP"; //半成品分组编码 string specified = "2.CP"; //成品分组编码 var groupNum = ((DynamicObject)groupData)["Number"]; if (groupNum != null && (groupNum.ToString().Equals(specifiedGroupNum) || groupNum.ToString().Equals(specified))) { //满足特定分组使用自定义编码规则生成单据编号 GenerateBillNoById(); } } } private void GenerateBillNoById() { string sql = string.Format("/*dialect*/select FRULEID from T_BAS_BILLCODERULE_L t where t.fname ='产品物料编码规则'"); var result = DBServiceHelper.ExecuteDynamicObject(this.Context, sql); //查询对应编码规则的编码 BusinessDataService dataService = new BusinessDataService(); var businInfo = View.BillBusinessInfo; var dataObjs = new DynamicObject[] { this.Model.DataObject }; bool isUpdateMax = true; string specifiedRuleId = result[0]["FRULEID"].ToString(); var billNoList = dataService.GetBillNo(Context, businInfo, dataObjs, isUpdateMax, specifiedRuleId); this.Model.SetValue(businInfo.GetBillNoField().Key, billNoList[0].BillNo); }
方式(二)
参照https://vip.kingdee.com/questions/483924612934417664?productLineId=1 当中周老师的回答,目前实现的方式参照了周老师的想法。
新建了四张基础资料,设置了一个物料编码参数表,新增单据体和子单据体,分别绑定上不同的基础资料(对应在参数选择时才能在BeforeSelectF7当中添加过滤)。在物料单据 当中新增单据体和字段,配置对应的实体服务规则。
具体实现如下所示:
一,前期配置:
(1)基础资料
1.物料编码参数表(模板继承基础资料模板)
唯一标识 | QPUB_CodeProprexy | 物料编码参数表 |
单据体 | F_BL_CodeProprexyEntity | 编码类型 |
单据体表(FEntryID) | T_BL_CodeProprexyEntity | |
单据体字段 | 编码类型(文本) | F_BL_CODETYPE |
编码长度(整数)控制子单据体编码长度 | F_BL_CodeLength | |
启用(复选框) 配置值更新控制状态 | F_BL_Enable | |
数据状态(文本) -字段名(FDOCUMENTSTATUS) | F_BL_CodeStatu | |
子单据体 | F_BL_CodeProprexyDetail | 编码明细 |
子单据体表(FDetailID) | T_BL_CodeProprexyDetail | |
子单据体字段 | 编码(文本) | F_BL_CodeValue |
编码名称(文本) | F_BL_CodeName | |
启用(复选框) | F_BL_DetailEnable | |
数据状态(文本)-字段名(FDOCUMENTSTATUS) | F_BL_DetailStatus | |
2.物料大类编码(复制基础资料-BOS基对象模板) -----------单据头数据表(T_BL_CodeProprexy) -FID
单据标识-QPUB_MaterialTypeCode
3.物料大类编码属性(复制基础资料-BOS基对象模板)------------单据头数据表(T_BL_CodeProprexyEntity)-FEntryID
单据标识-QPUB_MaterialTypeCodeProperty
字段添加:序号(整数)-Fseq-FSEQ-seq
物料大类(基础资料)-F_BL_MaterialTypeCode-FID-F_BL_MaterialTypeCode --类型(物料大类编码)
4.物料编码参数表(复制基础资料-BOS基对象模板) --------单据头数据表(T_BL_CodeProprexyDetail)-FDetailID
单据标识- QPUB_CodePropertyEdit
字段添加: 物料大类编码属性(基础资料)-F_BL_MaterialTypeCodeProperty---类型(物料大类编码属性)
(2) 物料档案配置
新增一个面板 --F_BL_CodeProxy ---可通过实体服务规则控制面板的隐藏和显示
新增一个页签控件 --- 对应设置两个页签 - 产品信息 ,编码信息
编码信息中设置单据体编码属性(F_BL_CodeProxyEntity)--FEntryID---T_BL_MaterialCodeEntity
对应字段:
物料规格参数(基础资料)---F_BL_MtlSpctPara --类型(物料大类编码属性)
规格参数编码(基础资料)---F_BL_ParameterValue--类型(物料编码属性维护)
规格参数名(基础资料属性)---F_BL_ParaName---字段(编码属性·规格属性编码)
产品信息中设置对应产品信息字段
对应字段:
产品状态(F_BL_ProStatus)----单选辅助资料列表(产品状态)
产品层数(F_QPUB_LAYERNUMBER)--旧编码(层数)
装配方式(F_BL_ProAsmMhod)--- 单选辅助资料列表()
产品版型(F_BL_Propattern)--- 单选辅助资料列表()
产品序列(F_BL_ProSequence)--- 文本(禁止编辑)-------用于产品流水号
客户版本(F_BL_ProAsmMhod)--- 下拉列表(字母)
内部版本(F_BL_ProAsmMhod)--- 下拉列表(数字)
(3) 物料档案实体服务规则配置:
1.物料划分类别
2.隐藏面板
二,插件配置:
using System; using System.Linq; using System.Text; using System.ComponentModel; using System.Threading.Tasks; using System.Collections.Generic; using Kingdee.BOS.Util; using Kingdee.BOS.App.Core; using Kingdee.BOS.ServiceHelper; using Kingdee.BOS.Core.Bill.PlugIn; using Kingdee.BOS.Core.Bill.PlugIn.Args; using Kingdee.BOS.Orm.DataEntity; using Kingdee.BOS.Core.Metadata.EntityElement; namespace BL.K3.Plugln.APP.Material { [Description("按照物料分组设置编码属性单据体"), HotUpdate] public class MaterialCodeProprexyPlugln : AbstractBillPlugIn { public override void BeforeSave(BeforeSaveEventArgs e) { base.BeforeSave(e); var status = this.Model.DataObject["DocumentStatus"]; if (status.ToString() != "A" && status.ToString() != "Z") return; var groupData = this.Model.DataObject["MaterialGroup"]; if (groupData != null && groupData is DynamicObject) { String groupNumber = Convert.ToString(((DynamicObject)groupData)["Number"]); groupNumber = groupNumber.Split('.').LastOrDefault().IsNullOrEmptyOrWhiteSpace() ? groupNumber : groupNumber.Split('.').LastOrDefault(); if (groupNumber.EqualsIgnoreCase("BCP") || groupNumber.EqualsIgnoreCase("CP")) { var Seq =this.Model.GetValue("F_BL_ProSequence"); if (!Seq.IsNullOrEmptyOrWhiteSpace()) { var Fnumber=this.Model.GetValue("Fnumber"); GetCodesplice(); } return; } if (groupNumber.All(char.IsDigit)) //判断物料分组编码为纯数字 { this.View.ShowErrMessage("当前物料分组选择错误,请重新修改后,确认保存"); e.Cancel = true; return; } String MtlNumber = String.Format("{0}-", groupNumber); String MtlName = ""; var entity = this.View.BillBusinessInfo.GetEntity("F_BL_CodeProxyEntity"); var CodeEntity = this.View.Model.GetEntityDataObject(entity); if (CodeEntity != null) { foreach (var obj in CodeEntity) { var ParaValue = (DynamicObject)obj["F_BL_ParameterValue"]; MtlNumber += ParaValue.IsNullOrEmpty() ? "" : ParaValue["Number"].ToString(); MtlName += ParaValue.IsNullOrEmpty() ? "" : ParaValue["Name"].ToString() + " "; } } this.View.Model.SetValue("FNumber",MtlNumber); this.View.Model.SetValue("FName", MtlName); this.View.UpdateView("FNumber"); this.View.UpdateView("FName"); } } public override void AfterSave(AfterSaveEventArgs e) { base.AfterSave(e); if (!e.OperationResult.IsSuccess) return; var groupData = this.Model.DataObject["MaterialGroup"]; if (groupData != null && groupData is DynamicObject) { String groupNumber = Convert.ToString(((DynamicObject)groupData)["Number"]); groupNumber = groupNumber.Split('.').LastOrDefault().IsNullOrEmptyOrWhiteSpace() ? groupNumber : groupNumber.Split('.').LastOrDefault(); if (groupNumber.EqualsIgnoreCase("BCP") || groupNumber.EqualsIgnoreCase("CP")) { var Fnumber = Convert.ToString(this.Model.GetValue("Fnumber")); if (Fnumber.Length ==13) { this.Model.SetValue("F_BL_ProSequence", Fnumber.Substring(6, 5)); this.View.UpdateView("F_BL_ProSequence"); string sql = string.Format("update T_BD_MATERIAL set F_BL_ProSequence = '{0}' where FNUMBER ='{1}'", Fnumber.Substring(6, 5), Fnumber); DBServiceHelper.ExecuteDynamicObject(this.Context, sql); } } } } public override void AfterBindData(EventArgs e) { base.AfterBindData(e); var status = this.Model.DataObject["DocumentStatus"]; if (status.ToString() != "Z") return; var groupData = this.Model.DataObject["MaterialGroup"]; if (groupData != null && groupData is DynamicObject) { String groupNumber = Convert.ToString(((DynamicObject)groupData)["Number"]); groupNumber = groupNumber.Split('.').LastOrDefault().IsNullOrEmptyOrWhiteSpace() ? groupNumber : groupNumber.Split('.').LastOrDefault(); if (groupNumber.EqualsIgnoreCase("BCP") || groupNumber.EqualsIgnoreCase("CP")) { this.Model.SetValue("F_BL_CustVersion", this.Model.GetValue("F_BL_CustVersion").IsNullOrEmptyOrWhiteSpace() ? "A" : this.Model.GetValue("F_BL_CustVersion")); this.Model.SetValue("F_BL_InnerVersion", this.Model.GetValue("F_BL_InnerVersion").IsNullOrEmptyOrWhiteSpace() ? "0" : this.Model.GetValue("F_BL_InnerVersion")); GetCodesplice(); return; } String sql = string.Format("/*dialect*/Select bb.* from T_BL_CodeProprexy aa inner join T_BL_CodeProprexyEntity bb on aa.FID =BB.FID where aa.FNUMBER = '{0}' and bb.FDOCUMENTSTATUS='c'", groupNumber); var result = DBServiceHelper.ExecuteDynamicObject(this.Context, sql); if (result.Count > 0) { this.Model.BeginIniti(); this.Model.DeleteEntryData("F_BL_CodeProxyEntity"); for (int i = 0; i < result.Count; i++) { this.Model.BatchCreateNewEntryRow("F_BL_CodeProxyEntity", 1); this.Model.SetValue("F_BL_MtlSpctPara", result[i]["FEntryID"], i); } this.Model.EndIniti(); this.View.UpdateView("F_BL_CodeProxyEntity"); } } } public override void AfterCopyData(CopyDataEventArgs e) { base.AfterCopyData(e); this.View.GetControl("F_QPUB_layernumber").Enabled = false; this.View.GetControl("F_BL_Propattern").Enabled = false; this.View.UpdateView("F_QPUB_layernumber"); this.View.UpdateView("F_BL_Propattern"); } public override void DataChanged(Kingdee.BOS.Core.DynamicForm.PlugIn.Args.DataChangedEventArgs e) { base.DataChanged(e); var status = this.Model.DataObject["DocumentStatus"]; if (status.ToString() != "Z") return; var groupData = this.Model.DataObject["MaterialGroup"]; if (groupData != null && groupData is DynamicObject) { String groupNumber = Convert.ToString(((DynamicObject)groupData)["Number"]); groupNumber = groupNumber.Split('.').LastOrDefault().IsNullOrEmptyOrWhiteSpace() ? groupNumber : groupNumber.Split('.').LastOrDefault(); if (groupNumber.EqualsIgnoreCase("BCP") || groupNumber.EqualsIgnoreCase("CP")) { switch (e.Field.Key) { case "F_BL_ProStatus": case "F_QPUB_layernumber": case "F_BL_ProAsmMhod": case "F_BL_Propattern": case "F_BL_CustVersion": case "F_BL_InnerVersion": GetCodesplice(); break; } } switch(e.Field.Key) { case "FMaterialGroup": String sql = string.Format("/*dialect*/Select bb.* from T_BL_CodeProprexy aa inner join T_BL_CodeProprexyEntity bb on aa.FID =BB.FID where aa.FNUMBER = '{0}' and bb.FDOCUMENTSTATUS='c'", groupNumber); var result = DBServiceHelper.ExecuteDynamicObject(this.Context, sql); if (result.Count > 0) { this.Model.BeginIniti(); this.Model.DeleteEntryData("F_BL_CodeProxyEntity"); for (int i = 0; i < result.Count; i++) { this.Model.BatchCreateNewEntryRow("F_BL_CodeProxyEntity", 1); this.Model.SetValue("F_BL_MtlSpctPara", result[i]["FEntryID"], i); } this.Model.EndIniti(); this.View.UpdateView("F_BL_CodeProxyEntity"); } else { this.Model.DeleteEntryData("F_BL_CodeProxyEntity"); this.Model.SetValue("Fnumber",""); this.Model.SetValue("Fname",""); this.View.UpdateView("Fnumber"); this.View.UpdateView("Fname"); if (groupNumber !="BCP" || groupNumber!="CP") { this.Model.SetValue("F_BL_PROSEQUENCE",""); this.View.UpdateView("F_BL_PROSEQUENCE"); } } break; case "F_BL_ParameterValue": String MtlNumber = String.Format("{0}-", groupNumber); String MtlName = ""; var entity = this.View.BillBusinessInfo.GetEntity("F_BL_CodeProxyEntity"); var CodeEntity = this.View.Model.GetEntityDataObject(entity); if (CodeEntity != null) { foreach (var obj in CodeEntity) { var ParaValue = (DynamicObject)obj["F_BL_ParameterValue"]; MtlNumber += ParaValue.IsNullOrEmpty() ? "" : ParaValue["Number"].ToString(); MtlName += ParaValue.IsNullOrEmpty() ? "" : ParaValue["Name"].ToString() + " "; } } this.Model.SetValue("Fnumber", MtlNumber); this.Model.SetValue("Fname", MtlName); this.View.UpdateView("Fnumber"); this.View.UpdateView("Fname"); break; } } } public override void BeforeF7Select(Kingdee.BOS.Core.DynamicForm.PlugIn.Args.BeforeF7SelectEventArgs e) { base.BeforeF7Select(e); string Key = Convert.ToString(e.BaseDataField.IsNullOrEmptyOrWhiteSpace() ? e.FieldKey : e.BaseDataField.Key); if (Key.Equals("F_BL_MtlSpctPara")) { var groupData = this.Model.DataObject["MaterialGroup"]; if (groupData != null && groupData is DynamicObject) { String groupNumber = Convert.ToString(((DynamicObject)groupData)["Number"]); groupNumber = groupNumber.Split('.').LastOrDefault().IsNullOrEmptyOrWhiteSpace() ? groupNumber : groupNumber.Split('.').LastOrDefault(); String filter = String.Format("F_BL_MaterialTypeCode.FNumber = '{0}'", groupNumber); e.ListFilterParameter.Filter = filter; } } } public void GetCodesplice() { String[] obj = new String[7]; var billobj = this.View.Model.DataObject; var ProStatus = (DynamicObject)billobj["F_BL_ProStatus"]; var ProAsmMhod = (DynamicObject)billobj["F_BL_ProAsmMhod"]; var Propattern = (DynamicObject)billobj["F_BL_Propattern"]; obj[0] = ProStatus.IsNullOrEmptyOrWhiteSpace() ? "" : Convert.ToString(ProStatus["Fnumber"]);//产品状态 obj[1] = Convert.ToString(billobj["F_QPUB_LAYERNUMBER"]).PadLeft(2, '0');//产品层数 obj[2] = ProAsmMhod.IsNullOrEmptyOrWhiteSpace() ? "" : Convert.ToString(ProAsmMhod["Fnumber"]);//装配方式 obj[3] = Propattern.IsNullOrEmptyOrWhiteSpace() ? "" : "-" + Convert.ToString(Propattern["Fnumber"]); //产品板型 obj[4] = Convert.ToString(billobj["F_BL_ProSequence"]); //流水号 obj[5] = Convert.ToString(billobj["F_BL_CustVersion"]); //客户版本 obj[6] = Convert.ToString(billobj["F_BL_InnerVersion"]);//内部版本 String Code = String.Join("", obj); if (!obj[4].IsNullOrEmptyOrWhiteSpace() && Code.Length == 13) { this.Model.SetValue("FNumber", Code); this.View.UpdateView("FNumber"); } } } }
三,编码规则配置
四,录入数据,进行测试,改进代码
五,后续改进
后续有更改再进行补充。目前该文章仅做本人插件记录,已将更改后的编码规则Python格式上传。
编码规则Python格式.rar(2.56KB)
推荐阅读