业务校验的四种方式原创
金蝶云社区-陈来珍
陈来珍
34人赞赏了该文章 8764次浏览 未经作者许可,禁止转载编辑于2023年07月28日 13:51:49

关键词:操作代码、服务插件自定义校验器、操作校验、前端按钮校验

一、需求背景

(1)需求一:新增的采购申请单提交的时候需要校验:采购方式为自费时,采购单价不能为空或小于等于0,其中提交绑定了操作代码submit。

1.png

图1

2.png

图2

(2)需求二:采购申请单的采购信息(单据体)上有一个按钮(查看库存),没有绑定操作代码,点击查看库存直接,需要校验是否选择了采购信息分录行,且分录行上的物料不为空

3.png

图3

二、实现方案

1、分析思路

业务校验主要看按钮是否绑定了操作代码以及是否是界面操作,还是后台操作

   (1)如果没有绑定操作代码,只能通过beforeClick或beforeItemClick监听按钮的点击前事件进行校验

   (2)如果按钮绑定了操作代码但是只在用户点击按钮的时候触发校验,那么可以通过以下四种方法实现校验

          ①beforeClick,beforeItemclick 按钮点击前事件

          ②操作类型为savesubmit等实体操作(和数据库有数据交互的操作为实体操作)操作还可以通过校验规则配置实现校验

          ③beforeDoOperation操作前事件

          ④服务插件校验:继承操作服务类AbstractOperationServicePlugIn,添加自定义校验器onAddValidators

   (3)如果通过后台代码而非界面操作触发的操作,则只只能通过以下方式实现业务校验

          ①服务校验插件,即继承操作服务类AbstractOperationServicePlugIn,添加自定义校验器onAddValidators

          ②操作类型为savesubmit等个别操作还可以通过校验规则配置实现校验

2、实现方案

        ①beforeClick触发的是按钮控件的点击前事件,beforeItemClick触发的是工具栏按钮的点击前事件

        ②beforeDoOperation操作前事件对比于beforeClick、beforeItemClick点击前事件:beforeClick、        beforeItemClick可以触发无操作按钮的点击事件,beforeDoOperation可以传递一些给自定义操作参数给操作服务、操作插件;

        ③不要同时使用多种方式对同一个校验需求进行校验,一般能通过校验规则配置实现的就用校验规则,界面规则不能实现的一般都是用服务插件实现,因为每个绑定操作的校验都会走服务插件的校验。

        另外,存在校验规则校验不通过,则不会再触发自定义校验器逻辑


        image.png

图4

三、实现过程

1、无操作代码的按钮校

以需求二为例,没有绑定操作代码,只能通过beforeClick或beforeItemClick监听按钮的点击前事件进行校验。因为需求二上面的查看库存是工具栏的按钮,需要需要通过监听beforeItemClick点击前事件

5.png

图5

(1)添加”查看库存”所在工具栏的监听

@Override
    public void registerListener(EventObject e) {
    //kded_lookstock添加单据体工具栏的监听
    Toolbar tb = this.getView().getControl("kded_advcontoolbarap");
    tb.addItemClickListener(this);
    }

(2)编写校验逻辑

@Override
    public void beforeItemClick(BeforeItemClickEvent evt) {
       EntryGrid entryGrid = this.getView().getControl("kded_entryentity");
       //获取选中行
       int[] selectRows = entryGrid.getSelectRows();
       StringBuilder strbd = new StringBuilder();
       for (int i = 0; i < selectRows.length; i++) {
           Object materie = this.getModel().getValue("kded_materielfield", selectRows[i]);
           if (materie == null) {//添加为空的行号
              strbd.append(String.valueOf(selectRows[i]+1));
              strbd.append("、");
           }
       }
       if (strbd.length()>0) {
           strbd.deleteCharAt(strbd.length()-1);
           this.getView().showErrorNotification(String.format("第%s行物料值不能为空", strbd.toString()));
evt.setCancel(true);
       }
       super.beforeItemClick(evt);
    }

(3)效果图

6.png

图6

2、有操作代码的按钮校验

以需求一为例介绍绑定了操作代码的校验方案,该场景有四种校验方式(1、校验方案总体介绍),其中界面点击,用beforeItemClick事件的校验参考2.1、无操作代码的按钮校验

2.1、操作校验规则

(1)以需求一为例:当采购方式为自费时,采购单价不能小于等于0,配置的校验规则如下,选中提交按钮-操作代码-选择操作-选中提交操作-修改-操作编辑-其他控制-校验规则-新增一个合法性校验,设置合法性校验规则如下

7.png

图7

2.2、beforeDoOperation事件的业务校验

(1)beforeDoOperation(BeforeDoOperationEventArgs args)事件界面操作事件,是用户点击保存、提交等执行报保存、提交绑定的操作之前触发的事件,我们可以在该事件中做相关的业务校验。以需求一为例:当采购方式为自费时,采购单价不能小于等于0,实现的校验逻辑如下

@Override
    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
       if (args.getSource() instanceof Submit) {
           Submit opp = (Submit) args.getSource();
           //获取采购申请单实体数据
           DynamicObject dataEntity = this.getModel().getDataEntity(true);
           //获取采购信息单据体数据
           DynamicObjectCollection dynamicObjectCollection = dataEntity.getDynamicObjectCollection("kded_entryentity");
           StringBuilder strbd = new StringBuilder();
           for (int i = 0; i < dynamicObjectCollection.size(); i++) {
              //各分录行数据
              DynamicObject entryObj = dynamicObjectCollection.get(i);
              BigDecimal price = entryObj.getBigDecimal("kded_pricefield");
              int reqWay = entryObj.getInt("kded_combofield");
              //采购方式为自费时,采购单价不能小于0
              if (reqWay==1&&price.compareTo(BigDecimal.ZERO)<1) {
                  strbd.append(i+1);
                  strbd.append("、");
              }
           }
           if (strbd.length()>0) {
              strbd.deleteCharAt(strbd.length()-1);
              this.getView().showErrorNotification(String.format("第%s行采购方式为自费时,采购单价不能小于0", strbd.toString()));
              //取消提交操作
              args.setCancel(true);
           }
       }
       super.beforeDoOperation(args);
    }

(2)效果图

8.png

图8

2.3、操作服务插件校验

(1)主要工具栏上的提交按钮绑定了提交操作,不管是用户点击提交的界面操作,还是通过OperateServiceHelper.executeOperate(“submit”, entityNumber, dataEntities, option)等方式后台调用的提交操作,都会触发提交操作服务插件的校验逻辑。以需求一为例:当采购方式为自费时,采购单价不能小于等于0,实现的校验逻辑如下

①添加服务插件类,继承于AbstractOperationServicePlugIn,添加自定义校验器ReqSubmitValidator()

public class ReqOppSubmitServicePlugin extends AbstractOperationServicePlugIn {
    /**
     * 插件需要在此事件,添加需要用到的字段;
     * 否则,操作引擎加载出的单据数据包,可能没有插件要用到的字段值,从而引发中断
     */
    @Override
    public void onPreparePropertys(PreparePropertysEventArgs e) {
       //加载“采购方式”字段
       e.getFieldKeys().add("kded_combofield");
       //加载“采购单价”字段
       e.getFieldKeys().add("kded_pricefield");
    }
    /**
     * 执行操作校验前,触发此事件
     * @remark
     * 插件可以在此事件,调整预置的操作校验器;或者增加自定义操作校验器
     */
    @Override
    public void onAddValidators(AddValidatorsEventArgs e) {
       //添加自定义的校验器: 
       e.addValidator(new ReqSubmitValidator());
    }
}

②实现自定义校验器逻辑,校验器类基类AbstractValidator,覆盖方法validate

public class ReqSubmitValidator extends AbstractValidator {
    @Override
    public void validate() {
       for (ExtendedDataEntity extendedDataEntity : this.getDataEntities()) {
           DynamicObject dataEntity = extendedDataEntity.getDataEntity();
           DynamicObjectCollection entrys = dataEntity.getDynamicObjectCollection("kded_entryentity");
           StringBuilder strbd = new StringBuilder();
           for (int i = 0; i < entrys.size(); i++) {
              //各分录行数据
              DynamicObject entryObj = entrys.get(i);
              BigDecimal price = entryObj.getBigDecimal("kded_pricefield");
              int reqWay = entryObj.getInt("kded_combofield");
              //采购方式为自费时,采购单价不能小于0
              if (reqWay==1&&price.compareTo(BigDecimal.ZERO)<1) {
                  strbd.append(i+1);
                  strbd.append("、");
              }
           }
           if (strbd.length()>0) {
              strbd.deleteCharAt(strbd.length()-1);
              //提示校验失败,终止提交操作
              this.addErrorMessage(extendedDataEntity, String.format("第%s行采购方式为自费时,采购单价不能小于0!", strbd.toString()));
           }}}}

③注册提交操作的服务插件

9.png

图9

(2)效果图

10.png

图10

四、开发环境版本

COSMICV4.0.010.0

五、注意事项

 案例补充:有个定时任务:采购申请单下推生成采购订单之后,定时任务自动提交暂存状态的采购订单。有个开发在beforeDoOperation中写了对采购订单的的校验逻辑,但是定时任务执行提交操作时并没有触发beforeDoOperation的校验逻辑。

 解决方案:因为beforeDoOperation是界面点击操作触发的事件,所以需要在服务插件中写校验逻辑

六、参考资料

【开发平台】指导手册

学习成长中心



赞 34