寻源二开指南--寻源项目变更
1. 增加寻源变更类型
1.1 业务场景简介
在寻源执行过程中,可能会遇到各种需要变更项目内容的场景,如变更投标截止时间、补充供应商、定标结果变更、寻源终止项目等。系统预置了大部分常用的变更类型,例如:
SYS036 投标截止时间变更
SYS037 仅变更品类(不变更供应商)
SYS038 需求扩充(立项预估采购金额)
SYS040 定标份额变更
SYS041 定标结果和份额变更
SYS042 项目终止/废标
SYS043 需求扩充(供应商中标金额)
SYS044 中标供应商数量变更
SYS045 申请开标
SYS046 补充供应商
SYS063 议价终止
SYS064 议价报价截止时间变更
SYS069 供应商废标
SYS072 更新标的基本信息
…
二开可以增加新的变更类型,以支持客户化的变更场景。
1.2 简要实现方案
步骤 | 开发内容 | 备注 |
1 | 增加 变更组件的元数据 | 元数据开发 |
2 | 增加 变更组件的表结构 | 表结构开发,一般会自动创建 |
3 | 增加 变更组件的编辑插件 | 代码开发 |
4 | 增加 变更判断条件 | 代码开发 |
5 | 增加 变更处理逻辑 | 代码开发 |
6 | 注册 变更组件 | 应用注册 |
7 | 注册 变更类型 | 应用注册 |
8 | 注册 变更判断条件 | 应用注册 |
9 | 注册 变更处理逻辑 | 应用注册 |
1.3 详细开发步骤及示例代码
下面以变更类型“更新标的基本信息” 为例。该变更类型支持在定标审核后,可修改标的基本信息,如物料编码、名称、规格等,实际运行界面如下:
1.3.1 增加 变更组件的元数据
1 增加元数据src_materialchg,需继承自组件基类 pds_comptpl
2 根据客户的实际需求,完善组件元数据的字段及页面布局。
注意:字段名和字段标识名,需要修改为有业务语语义的名称,不能直接用系统自动创建的名称。
1.3.2 增加 变更组件的表结构
该场景中,需要有2个数据表,用于存储变更信息:
表头为:t_src_materialchg
分录为:t_src_materialchgentry
注意:二开时,一般情况下保存元数据时,就会创建出相应的表结构,无需额外开发。
1.3.3 增加 变更组件的编辑插件
该编辑插件用于取数或对数据进行处理,继承自平台的AbstractBillPlugIn即可,代码如下:
/** * 补充或更新标的编码名称 * * @author rd_fumin_huang */ public class SrcMaterialchgEdit extends AbstractBillPlugIn {
@Override public void beforeBindData(EventObject e) { // 创建标的分录 createEntryEntity(); }
@Override public void propertyChanged(PropertyChangedArgs evt) { int index = evt.getChangeSet()[0].getRowIndex(); if (index < 0) { return; } String fieldName = evt.getProperty().getName(); if (SrcCommonConstant.SRCENTRYID.equals(fieldName) || SrcCommonConstant.ISCHANGED.equals(fieldName)) { return; }
Object newValue = evt.getChangeSet()[0].getNewValue(); switch (fieldName) { case SrcCommonConstant.MATERIALNAME: if (Objects.isNull(newValue) || StringUtils.isEmpty(newValue.toString())) { Object oldValue = evt.getChangeSet()[0].getOldValue(); // 如果新值为空 则把旧值塞回去 this.getModel().setValue(SrcCommonConstant.MATERIALNAME, oldValue, index); } // 设置为已修改 this.getModel().setValue(SrcCommonConstant.ISCHANGED, "1", index); break; case SrcPurlistConstant.MATERIAL: if (Objects.nonNull(newValue)) { // 设置为已修改 this.getModel().setValue(SrcCommonConstant.MATERIALNAME, ((DynamicObject) newValue).getString(BillAssistConstant.NAME), index); this.getModel().setValue(SrcCommonConstant.MATERIALMODEL, ((DynamicObject) newValue).getString(BillAssistConstant.MODELNUM), index); this.getModel().setValue(SrcCommonConstant.DESCRIPTION, ((DynamicObject) newValue).getString(SrcCommonConstant.DESCRIPTION), index); } case SrcPurlistConstant.MATERIALMODEL: case SrcPurlistConstant.DESCRIPTION: case SrcPurlistConstant.CATEGORY: // 设置为已修改 this.getModel().setValue(SrcCommonConstant.ISCHANGED, "1", index); break; default: break; } }
/** * 创建分录 */ private void createEntryEntity() { // 父表单的view IFormView parentView = this.getView().getParentView(); if (parentView == null) { return; } DynamicObject bidChangeObj = parentView.getModel().getDataEntity(); long pProjectId = SrmCommonUtil.getPkValue(bidChangeObj.getDynamicObject(SrcCommonConstant.PROJECT)); if (pProjectId == 0) { return; } long projectId = PdsCommonUtils.object2Long(this.getModel().getValue(SrcCommonConstant.PROJECTID)); if (pProjectId == projectId) { return; } // 项目相同 QFilter qfilter = new QFilter(SrcCommonConstant.PROJECT, QCP.equals, pProjectId); // 类型为 采购清单 qfilter.and(SrcCommonConstant.BILLTYPE, QCP.equals, "1"); // 创建分录 PdsCommonUtils.createEntryEntity(this.getView(), SrcMetadataConstant.SRC_PURLISTF7, qfilter, null, SrcCommonConstant.ENTRYENTITY); // 设置寻源项目id this.getModel().setValue(SrcCommonConstant.PROJECTID, pProjectId); }
} |
1.3.4 增加 变更判断条件
在寻源变更单提交时,根据这些判断条件,判断是否允许变更处理。
如果有多个条件,最好写成多个插件,符合单一职责,便于维护和启用/禁用。
代码示例:更新标的基本信息--校验:SrcMaterialChgValidateService
注意:需要实现 IDataValidateService 接口
/** * 更新标的基本信息--校验 * * @author rd_fumin_huang * */ public class SrcMaterialChgValidateService implements IDataValidateService { private static final long serialVersionUID = 1L;
@Override public ValidateResult validate(ValidateEvent validateEvent) { ValidateResult result = new ValidateResult(); DynamicObject projectObj = (DynamicObject) validateEvent.getObj().get(SrcCommonConstant.PROJECT); if (null == projectObj) { result.setSuccess(false); return result; } else { // 判断是否已下推采购合同/采购订单/价目表/货源清单,如果下推,则不允许变更 String message = SrcContractUtils.contractHasPush(projectObj); if (null != message) { result.setMessage(message); result.setSuccess(false); return result; } }
// 是否允许定标后修改物料信息 String message = allowChangeMaterialInfo(projectObj); if (null != message) { result.setMessage(message); result.setSuccess(false); return result; }
result.setSuccess(true); return result; } } 注意:在变更校验插件获取组件,应该从 model 获取最新数据,特别是没有点“保存”,直接点“提交”的情况。可以通过接口提供的方法获取: 错误: DynamicObject compObj = TemplateUtil.getComponentData(validateEvent.getObj().getString(SrcCommonConstant.ID), SrcMetadataConstant.SRC_RETENDER); 正确: DynamicObject compObj = getCompObj(validateEvent, SrcMetadataConstant.SRC_RETENDER); |
1.3.5 增加 变更处理逻辑
在寻源变更单审核时,根据这些处理逻辑,对寻源项目的数据进行处理。
如果有多个处理逻辑,最好写成多个插件,符合单一职责,便于维护和启用/禁用。
代码示例:更新标的基本信息--处理:SrcMaterialChgHandleService
注意:需要实现 IDataHandleService接口
/** * 更新标的基本信息--处理 * * @author rd_fumin_huang * */ public class SrcMaterialChgHandleService implements IDataHandleService { private static final long serialVersionUID = 1L;
/** * 变更处理 */ @Override public HandleResult handle(HandleEvent handleEvent) { HandleResult result = new HandleResult(); DynamicObject bidChangeObj = handleEvent.getObj(); long projectId = SrmCommonUtil.getPkValue(bidChangeObj.getDynamicObject(SrcCommonConstant.PROJECT));
// 变更单--标的对象 DynamicObject newMaterialObj = TemplateUtil.getComponentData(bidChangeObj.getString(SrcCommonConstant.ID), SrcMetadataConstant.SRC_MATERIALCHG); if (null == newMaterialObj) { return result; } // 变更单--标的分录 DynamicObjectCollection newMaterialRows = newMaterialObj.getDynamicObjectCollection(SrcCommonConstant.ENTRYENTITY); List<DynamicObject> newMaterialList = newMaterialRows.stream().filter(e -> e.getBoolean(SrcCommonConstant.ISCHANGED)).collect(Collectors.toList());
if (newMaterialList == null || newMaterialList.size() == 0) { return result; } // 属性结合 List<String> propertys = DynamicObjectUtil.getDynamicAllProperties(newMaterialList.get(0));
// 更新采购清单 updateMaterialInfo(newMaterialList, SrcMetadataConstant.SRC_PURLISTF7, propertys, projectId); // 更新签约单 updateMaterialInfo(newMaterialList, SrcMetadataConstant.SRC_CONTRACTENTRY, propertys, projectId);
// 处理变更日志 String message = ResManager.loadKDString("变更成功", "SrcMaterialChgHandleService_0", "scm-src-common"); result.setSuccess(true); result.setMessage(message); handleLog(handleEvent, message); return result; } |
1.3.6 注册 变更组件
将 变更组件元数据,注册到 寻源变更 节点上:
1.3.7 注册 变更类型
通过模板配置,注册新的变更类型:
在详情页面,设置该模板包含的组件:
1.3.8 注册 变更判断条件
将 变更判断条件 注册 到 寻源变更条件 上,业务节点默认为 项目启动 即可。
1.3.9 注册 变更处理逻辑
将 变更处理逻辑 注册到 寻源变更逻辑 上,业务节点默认为 项目启动 即可。
1.4 参考开发工作量(人/天)
步骤 | 开发内容 | 估计开发人天 |
1 | 增加 变更组件的元数据 | 0.5 |
2 | 增加 变更组件的表结构 | 0~0.5 |
3 | 增加 变更组件的编辑插件 | 0.5 |
4 | 增加 变更判断条件 | 0.5 |
5 | 增加 变更处理逻辑 | 0.5 |
6 | 注册 变更组件 | 0.5 |
7 | 注册 变更类型 | |
8 | 注册 变更判断条件 | |
9 | 注册 变更处理逻辑 |
合计:约2~3开发人天。
寻源二开指南--寻源项目变更
本文2024-09-22 23:57:33发表“云星瀚知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-xinghan-136362.html