来自 编程 2019-09-27 11:02 的文章
当前位置: 澳门三合彩票 > 编程 > 正文

流程结束处理,就有了这篇简单审批流的实现

简介

通用流程可以用于一些基本的申请,例如请假、加班
大致过程是:

1. 创建申请2. 分配给审批人(需要审批人列表,当前审批人)        -> 有下一个审批人 -> 3        -> 无 -> 43. 审批人审批        -> 同意 -> 2        -> 拒绝 -> 54. 存储数据,发送通知5. 结束

比较简单,唯一的难点就是动态设置审批人或者审批组,下面开始代码部分。

前面介绍过自定义审批流:

澳门三合彩票 1

bpmn20文件

    ...    <!-- standardRequest用来开始流程,在flowable里称为processDefinitionKey -->    <process id="standardRequest" name="标准申请流程" isExecutable="true">        <!-- 第一步:开始流程,创建申请 -->        <startEvent id="startEvent" name="创建申请"/>        <sequenceFlow sourceRef="startEvent" targetRef="assignToAuditor"/>        <!-- 第二步:分配审批人 -->        <!-- 这个AssignToAuditorDelegate类就是解决动态设置审批人的Java类 -->        <!-- 审批人列表需要从外部传入或者根据当前流程id来从数据库获取 -->        <serviceTask id="assignToAuditor" name="分配审批人" flowable:class="me.xwbz.flowable.delegate.AssignToAuditorDelegate"/>        <sequenceFlow sourceRef="assignToAuditor" targetRef="auditorExist"/>        <!-- 唯一网关:类似于switch,只能通过一个序列流 -->        <!-- 这里就是要么存在,要么不存在 -->        <!-- 使用default属性定义默认序列流,在其他序列流条件都不满足的情况下使用  -->        <exclusiveGateway id="auditorExist" name="审批人是否存在" default="auditorNotExistFlow"/>        <sequenceFlow sourceRef="auditorExist" targetRef="approveTask">            <!-- auditMethod是Spring里的一个bean,下面有提到 -->            <!-- execution是flowable内部变量,类型是org.flowable.engine.delegate.DelegateExecution,也就是serviceTask里的代理方法拿到的 -->            <conditionExpression xsi:type="tFormalExpression">                <![CDATA[                    ${auditMethod.existAuditor(execution)}                ]]>            </conditionExpression>        </sequenceFlow>        <sequenceFlow id="auditorNotExistFlow" sourceRef="auditorExist" targetRef="agreeDelegate" />        <!-- 第三步:审批人审批 -->        <userTask id="approveTask" name="等待审批"                flowable:candidateGroups="${auditMethod.getCandidateGroups(execution)}"                flowable:candidateUsers="${auditMethod.getCandidateUsers(execution)}"/>        <sequenceFlow sourceRef="approveTask" targetRef="decision"/>        <!-- 唯一网关:一个审批一个审批人 -->        <exclusiveGateway id="decision" default="rejectFlow"/>        <sequenceFlow sourceRef="decision" targetRef="assignToAuditor">            <conditionExpression xsi:type="tFormalExpression">                <![CDATA[                    ${auditMethod.isApproved(execution)}                ]]>            </conditionExpression>        </sequenceFlow>        <sequenceFlow id="rejectFlow" sourceRef="decision" targetRef="rejectDelegate" />        <!-- 第四步:同意后存储数据,发送通知 -->        <serviceTask id="agreeDelegate" name="数据存储"                     flowable:class="me.xwbz.flowable.delegate.StandardRequestAgreeDelegate"/>        <sequenceFlow sourceRef="agreeDelegate" targetRef="approveEnd"/>        <serviceTask id="rejectDelegate" name="回复拒绝消息"                     flowable:class="me.xwbz.flowable.delegate.BaseRejectDelegate"/>        <sequenceFlow sourceRef="rejectDelegate" targetRef="rejectEnd"/>        <!-- 第五步:结束 -->        <endEvent id="approveEnd" name="已同意"/>        <endEvent id="rejectEnd" name="已驳回"/>    </process>    ...

Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示

Dynamic CRM 2013学习笔记(二十一)自定义审批流2 - 配置按钮

Dynamic CRM 2013学习笔记(三十二)自定义审批流3 - 节点及实体配置

Dynamic CRM 2013学习笔记(三十三)自定义审批流4 - 规则节点 -有分支的流程处理

Dynamic CRM 2013学习笔记(三十四)自定义审批流5 - 自动邮件通知

[Dynamic CRM 2013学习笔记(三十五)自定义审批流6 - 审批通过后,再审批

  • 二次审批]()

Dynamic CRM 2013学习笔记(三十七)自定义审批流7 - 初始化(整套审批流下载、安装)

本次更新中,重点要介绍一下这个关联控件任务作为最高频的功能,经常要和其他模块产生关联,例如:任务和日程,动态,审批,项目等从今天起,您的任务信息能够变得更完整,不必在各个功能中频繁切换除此之外,本次还有:项目免打扰,项目可见性设置,以及审批和人事模块增强,下面是详细介绍。

常量部分

这次没有另外存储数据,所以变量都是直接存储到flowable自带的变量表里 强烈建议大家另外存储,自带的查询起来非常麻烦!

  • 审批人列表:AUDITOR_LIST_KEY = "AUDITOR_LIST";
  • 当前审批人:AUDITOR_KEY = "AUDITOR";
  • 当前审批人下标:AUDITOR_IDX_KEY = "AUDITOR_IDX";
  • 是否已审批:APPROVED_KEY = "AUDIT_APPROVED";
  • 申请类型:AUDIT_TYPE_KEY = "AUDIT_TYPE";
  • 申请状态:AUDIT_STATUS_KEY = "AUDIT_STATUS";
  • 其他参数:AUDIT_PARAMS_KEY = "AUDIT_PARAMS";
  • 申请状态
public enum AuditStatus {    /** 待审批 */    WAIT_AUDIT,    /** 已同意申请 */    AGREE_AUDIT,    /** 已拒绝申请 */    REJECT_AUDIT,    /** 已取消 */    CANCEL}
  • 申请人类型
public enum CandidateType{    /** 候选人 */    USER,    /** 候选组 */    GROUP}

虽然灵活,功能强大,不用修改代码,完全用配置就可以搞定。

一、任务模块

【新增】自定义控件增加关联控件

自定义任务内容 - 控件 - 关联,在项目中开启关联控件,即可对需要的任务,项目,日程,文件,表单进行关联添加,添加后即可随时查看避开反复查找任务及对应的日程,文件,表单,让项目管理变得更轻松。

澳门三合彩票 2

进入项目中的自定义任务内容

澳门三合彩票 3

从自定义任务内容中增加关联控件                                           

澳门三合彩票 4

在项目中关联任务,项目,日程,文件,表单

【新增】项目消息免打扰

开启项目消息免打扰模式,从此进入“飞行模式”,不用担心中途被通知打断思路。当然@某人功能依然是有效的哦。

澳门三合彩票 5

【新增】项目可见性

项目配置 - 成员对项目下任务的可见权限,可以对项目可见性进行设置,默认为“不可见未参与的任务”根据管理员的需求对任务可见性进行调整,分为以下三种选项(管理员固定为能查看所有任务及详情):

1.项目成员可查看所有的任务及任务详情

2.项目成员只能查看自己参与任务的详情和项目下所有任务标题

3.项目成员只能查看自己参与任务的标题和详情

澳门三合彩票 6

审批使用的方法定义

一个普通的Java类

package me.xwbz.flowable.method;import com.alibaba.fastjson.JSONObject;import org.flowable.engine.delegate.DelegateExecution;/** * 审批相关的方法 * * 用于flowable流程使用 */public class AuditMethod {    /**     * 是否存在审批者     * <sequenceFlow sourceRef="decision" targetRef="assignToAuditor">     *        <conditionExpression xsi:type="tFormalExpression">     *                 <![CDATA[     *                     ${auditMethod.existAuditor(execution)}     *                 ]]>     *    </conditionExpression>     *  </sequenceFlow>     */    public boolean existAuditor(DelegateExecution execution){        return execution.hasVariable(AUDITOR_KEY);    }    /**     * 获取当前审批者     */    public JSONObject getCurrentAuditor(DelegateExecution execution){        return JSONObject.parseObjectexecution.getVariable(AUDITOR_KEY));    }    /**     * 获取当前候选组     */    public String getCandidateGroups(DelegateExecution execution){        JSONObject candidate = getCurrentAuditor(execution);        if(candidate.getIntValue("type") == CandidateType.GROUP.ordinal {            return candidate.getString("id");        }        return null;    }    public String getCandidateUsers(DelegateExecution execution){        JSONObject candidate = getCurrentAuditor(execution);        if(candidate.getIntValue("type") == CandidateType.USER.ordinal {            return candidate.getString("id");        }        return null;    }    /**     * 获取当前审批者id     * <userTask id="approveTask" name="等待审批" flowable:assignee="${auditMethod.getCurrentAuditorId(execution)}" />     */    public String getCurrentAuditorId(DelegateExecution execution){        JSONObject auditor = getCurrentAuditor(execution);        return JSONObject.toJavaObject(auditor, User.class).getId();    }    /**     * 是否同意申请     */    public boolean isApproved(DelegateExecution execution){        Boolean approved = execution.getVariable(APPROVED_KEY, Boolean.class);        return approved != null && approved;    }}

流程结束处理

下面是同意处理,主要是更改状态。“拒绝处理”同理

可以根据业务增加消息通知,保存数据等。

package me.xwbz.flowable.delegate;import lombok.extern.slf4j.Slf4j;import org.flowable.engine.delegate.DelegateExecution;import org.flowable.engine.delegate.JavaDelegate;@Slf4jpublic class BaseAgreeDelegate implements JavaDelegate {    @Override    public void execute(DelegateExecution execution) {        log.info("{}已被同意", execution.getVariables;        execution.setVariable(AUDIT_STATUS_KEY, AuditStatus.AGREE_AUDIT.toString;    }}

flowable结合Spring可以直接使用Spring里的bean。

像下面这样定义,然后直接${auditMethod.isApproved(execution)}就可以调用auditMethod里的isApproved方法。

import me.xwbz.flowable.method.AuditMethod;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class FlowableConfig {    @Bean(name = "auditMethod")    public AuditMethod auditMethod(){        return new AuditMethod();    }}

最近客户需要实现一个很简单的审批流,就有了这篇简单审批流的实现。

二、审批优化

【优化】会签组审批优化:设置一人通过即通过,其他未操作人可以按需查看,不需要再次审批操作

【优化】表单统计整体优化:新增表单时间字段作为时间纬度,优化表头时间显示

【优化】表单统计优化:按部门和人员进行合并统计

【优化】明细打印精简:明细打印从1行2列改为1行6列,节约用纸

【优化】审批实时通知:用户可以通过企业账户管理 - 设置 - 开发者选项获取AppKey和SecretKey来调用Webhook,获取网络的审批表单,审批申请列表和审批申请详情

【新增】审批流程增加设置:申请发出立即通知抄送人选项

【新增】审批流程增加设置:申请人和审批人重复,自动通过审批选项

【新增】表单查询 - 搜索增加表单参与人的名字:搜索条件增加申请人/审批人/经办人/抄送人

动态设置审批人

这个是配置在serviceTask里的,所以需要实现JavaDelegate接口

package me.xwbz.flowable.delegate;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;import org.flowable.engine.delegate.DelegateExecution;import org.flowable.engine.delegate.JavaDelegate;/** * delegate - 分配审批人 */public class AssignToAuditorDelegate implements JavaDelegate {    @Override    public void execute(DelegateExecution execution) {        // 初始化变量,清空临时变量        execution.removeVariable(APPROVED_KEY);        execution.removeVariable(AUDITOR_KEY);        execution.setVariable(AUDIT_STATUS_KEY, AuditStatus.WAIT_AUDIT.toString;        // 拿到审批人列表        JSONArray auditorList = JSON.parseArray(execution.getVariable(AUDITOR_LIST_KEY).toString;        // 当前审批人在审批人列表的下标        Integer auditorIdx = execution.getVariable(AUDITOR_IDX_KEY, Integer.class);        if (auditorIdx == null) {            // 第一次分配,初始化为第一个            auditorIdx = 0;        } else if (auditorIdx + 1 >= auditorList.size {            //  所有审批人审批完成,结束分配            return;        } else {            // 下一个            auditorIdx++;        }        JSONObject auditor = auditorList.getJSONObject(auditorIdx);        execution.setVariable(AUDITOR_KEY, auditor.toJSONString;        execution.setVariable(AUDITOR_IDX_KEY, auditorIdx);    }}

首先根据需求文档分析流程:

三、人事优化

【优化】字段权限配置:HR总监可根据公司需求,针对不同HR的管理职能,配置不同管理职能的HR查看/编辑员工档案的权限。

澳门三合彩票 7

档案编辑/查看权限配置                                           

以上即为本次更新内容,如您对明道有更多的建议,意见,欢迎下方留言

开始流程

使用runtimeService#startProcessInstanceByKey开始这个流程,记得开始之前要使用identityService#setAuthenticatedUserId设置当前用户编号,这个是绑定到线程的,单线程环境下设置一次就行了。

Map<String, Object> vars = new HashMap<>();// 放入申请类型vars.put(AUDIT_TYPE_KEY, param.getType;// 放入审批人人列表vars.put(AUDITOR_LIST_KEY, JSONObject.toJSONString(param.getAuditors;// 放入其他参数vars.put(AUDIT_PARAMS_KEY, param.getParams;// 放入审批状态vars.put(AUDIT_STATUS_KEY, AuditStatus.WAIT_AUDIT.toString;logger.debug("当前用户id: {} ", Authentication.getAuthenticatedUserId;// 设置发起人// identityService.setAuthenticatedUserId(user.getId;ProcessInstance pro = runtimeService.startProcessInstanceByKey("standardRequest", 生成的编号, vars);// 文件材料if (param.getFiles() != null && !param.getFiles().isEmpty {    // 上传附件,可以直接上传字节流    param.getFiles().forEach(file ->            taskService.createAttachment("application/octet-stream", null,                    pro.getId(), file.getName(), null, file.getId;}

澳门三合彩票 8

查看待我审批的任务

taskService.createTaskQuery()只能查询到正在进行的任务

要是想既能查询到正在进行的,也要结束的可以使用下面的语句:

TaskInfoQueryWrapper taskInfoQueryWrapper = runtime ? new TaskInfoQueryWrapper(taskService.createTaskQuery : new TaskInfoQueryWrapper(historyService.createHistoricTaskInstanceQuery;

也就是说你要先确定是要那种。

TaskQuery query = taskService.createTaskQuery()        // or() 和 endOr()就像是左括号和右括号,中间用or连接条件        // 指定是我审批的任务或者所在的组别审批的任务        // 实在太复杂的情况,建议不使用flowable的查询        .or()        .taskAssignee(user.getId        .taskCandidateUser(user.getId        .taskCandidateGroup(user.getGroup        .endOr();        // 查询自定义字段    if (StringUtils.isNotEmpty(auditType)) {        query.processVariableValueEquals(AUDIT_TYPE_KEY, auditType);    }    if(auditStatus != null){        query.processVariableValueEquals(AUDIT_STATUS_KEY, auditStatus.toString;    }    // 根据创建时间倒序query.orderByTaskCreateTime    // 分页    .listPage    .stream().map(t -> {    // 拿到这个任务的流程实例,用于显示流程开始时间、结束时间、业务编号    HistoricProcessInstance p = historyService.createHistoricProcessInstanceQuery()            .processInstanceId(t.getProcessInstanceId            .singleResult();    return new Process.withTask // 拿到任务编号和任务名称            // 拿到创建时和中途加入的自定义参数            .withVariables(taskService.getVariables))            .withFiles(taskService.getProcessInstanceAttachments));}).collect(Collectors.toList()

功能实现如下:

查看我已审批的任务

任务审批后就走下一个序列流,这里只能从历史纪录里获取已审批的。

当前设置历史纪录(HistoryLevel)粒度为audit,这是默认的。

注意这里不能筛选自定义参数,所以要么自定义sql,要么另外存储。

// 如果不需要筛选自定义参数if(auditStatus == null && StringUtils.isEmpty(auditType)){    return historyService.createHistoricActivityInstanceQuery()            // 我审批的            .taskAssignee            // 按照结束时间倒序            .orderByHistoricActivityInstanceEndTime            // 已结束的(其实就是判断有没有结束时间)            .finished()            // 分页            .listPage(firstIdx, pageSize);}// 否则需要自定义sql// managementService.getTableName是用来获取表名的(加上上一篇提到的liquibase,估计flowable作者对数据表命名很纠结)// 这里从HistoricVariableInstance对应的表里找到自定义参数// 筛选对象类型不支持二进制,存储的时候尽量使用字符串、数字、布尔值、时间,用来比较的值也有很多限制,例如null不能用like比较。String sql = "SELECT DISTINCT RES.* " +            "FROM " + managementService.getTableName(HistoricActivityInstance.class) + " RES " +            "INNER JOIN " + managementService.getTableName(HistoricVariableInstance.class) + " var " +            "ON var.PROC_INST_ID_ = res.PROC_INST_ID_  " +            "WHERE RES.ASSIGNEE_ = #{assignee} " +            "AND RES.END_TIME_ IS NOT NULL ";if(auditStatus != null && StringUtils.isNotEmpty(auditType)){    sql += "AND ((var.name_ = #{typeKey} AND var.TEXT_ = #{typeValue}) OR  (var.name_ = #{statusKey} AND var.TEXT_ = #{statusValue}))";} else if(auditStatus != null){    sql += "AND var.name_ = #{statusKey} AND var.TEXT_ = #{statusValue}";} else {    sql += "AND var.name_ = #{typeKey} AND var.TEXT_ = #{typeValue}";}sql +=  " ORDER BY RES.END_TIME_ DESC";    return historyService.createNativeHistoricActivityInstanceQuery().sql    // 参数用#{assignee}占位后,再调用parameter("assignee", assignee)填入值    // 参数值可以多出来没用到的,比hibernate好多了            .parameter("assignee", assignee)            .parameter("typeKey", AUDIT_TYPE_KEY)            .parameter("typeValue", auditType)            .parameter("statusKey", AUDIT_STATUS_KEY)            .parameter("statusValue", auditStatus == null ? null : auditStatus.toString            .listPage(firstIdx, pageSize);

后续获取详细和自定义参数

list.stream().map(a -> {    // 同上面的拿到这个任务的流程实例    HistoricProcessInstance p = historyService.createHistoricProcessInstanceQuery()            .processInstanceId(a.getProcessInstanceId            .singleResult();    // 因为任务已结束(我看到有提到删除任务TaskHelper#completeTask),所以只能从历史里获取    Map<String, Object> params = historyService.createHistoricVariableInstanceQuery()            .processInstanceId(a.getProcessInstanceId            // 拿到的是HistoricVariableInstance对象,需要转成原来存储的方式            .stream().collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue));    return new Process.withActivity.withVariables;}).collect(Collectors.toList

一、 添加字段

查看我创建的任务

这个比较方便拿到,但是当前最新的任务比较难拿到,有时还不准确

// startedBy:创建任务时设置的发起人HistoricProcessInstanceQuery instanceQuery = historyService.createHistoricProcessInstanceQuery()        .startedBy(user.getId;// 自定义参数筛选if (StringUtils.isNotEmpty(auditType)) {    instanceQuery.variableValueEquals(AUDIT_TYPE_KEY, auditType);}if(auditStatus != null){    instanceQuery.variableValueEquals(AUDIT_STATUS_KEY, auditStatus.toString;}instanceQuery    .orderByProcessInstanceStartTime    .listPage(firstIdx, pageSize).stream()    //  获取其中的详细和自定义参数    .map(this::convertHostoryProcess)    .collect(Collectors.toList

获取其中的详细和自定义参数

    private Process convertHostoryProcess(HistoricProcessInstance p) {        // 不管流程是否结束,到历史里查,最方便        Map<String, Object> params = historyService.createHistoricVariableInstanceQuery().processInstanceId).list()                .stream().collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue));        // 获取最新的一个userTask,也就是任务活动纪录        List<HistoricActivityInstance> activities = historyService.createHistoricActivityInstanceQuery()                .processInstanceId)                .orderByHistoricActivityInstanceStartTime                .orderByHistoricActivityInstanceEndTime.                        listPage;        Process data = new Process;        if (!activities.isEmpty {            data.withActivity(activities.get;        }        return data.withVariables;    }

一个是让用户修改的审批状态,如果当前用户是审批人,放开审批状态字段,让用户审批或拒绝;值为 Pending, Approved, Rejected

一个是实体的状态,用户审批后根据业务逻辑来判断实体的状态;值为 Pending, Approved, Rejected

一个审批人字段,提交或用户修改了审批状态后,设置下一个审批人

另外可以设置几个隐藏审批人的字段,方便在插件里一次得出,js里就方便设置了(尽量避免在js里运行大量逻辑),如上图主要是把 sales director, gm 存下来

 

撤销流程实例

撤销后,流程直接中断,除了用户不能操作和多了结束时间、删除理由外,其他停留在撤销前的状态。

ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId.singleResult();if (process == null) {    throw new RuntimeException("该流程不在运行状态");}Task task = taskService.createTaskQuery().processInstanceId.singleResult();runtimeService.setVariable(task.getExecutionId(), AUDIT_STATUS_KEY, AuditStatus.CANCEL.toString;runtimeService.deleteProcessInstance(id, "用户撤销");

二. JS控制提交按钮和审批状态字段

用户操作

注意:如果beforeAgreeOrRejecttaskService.complete在同一个事物里,且beforeAgreeOrReject里跟AssignToAuditorDelegate有更新数据库数据,会导致事物异常。

澳门三合彩票,是否有审批权限需要自己判断。

操作后进入下一序列流,再次拿这个taskId会获取不到这个Task,所以上传审批意见和附件什么的要在操作前。

if(!isAssigneeOrCandidate(user, taskId)){    throw new RuntimeException("无法操作");}// 同意前设置,上传审批意见和附件beforeAgreeOrReject(user, taskId, AuditStatus.AGREE_AUDIT, "同意", reason);// 拒绝前设置,上传审批意见和附件// beforeAgreeOrReject(user, taskId, AuditStatus.REJECT_AUDIT, "拒绝", reason);// 同意taskService.complete(taskId, Collections.singletonMap(APPROVED_KEY, true));// 拒绝// taskService.complete(taskId, Collections.singletonMap(APPROVED_KEY, false));

判断是否有权限

public boolean isAssigneeOrCandidate(User user, String taskId){    long count = taskService.createTaskQuery()            .taskId            .or()            .taskAssignee(user.getId            .taskCandidateUser(user.getId            .taskCandidateGroup(user.getGroup            .endOr;    return count > 0;}

操作前设置,上传审批意见和附件

附件一般都另外存储,这里存一个id就行了 这里是存在ftp文件服务器里的

public void beforeAgreeOrReject(User user, String taskId, AuditStatus auditStatus, String operate, ReasonParam reason){    // 组成员操作后方便查询    taskService.setAssignee(taskId, user.getId;    if(StringUtils.isNotEmpty(reason.getText{        // 审批意见        taskService.addComment(taskId, null, null, reason.getText;    }    if (reason.getFiles() != null && !reason.getFiles().isEmpty {        files.forEach(file ->            // 上传附件,可以直接上传字节流            taskService.createAttachment("application/octet-stream", taskId,                    null, file.getName(), null, file.getId;    }}

1. 提交控制

AllowSubmit: function () {

        var currentUserId = Xrm.Page.context.getUserId();

        var userHasRole = HP.QuoteRibbon.UserHasRole(["Reginal Sales"], currentUserId);

        var Approver = Xrm.Page.getAttribute("tm_approver").getValue();

        var AccountTypeValue = Xrm.Page.getAttribute("wf_accounttype").getValue();

        var QuoteTypeValue = Xrm.Page.getAttribute("tm_quote_type").getValue();

        var TotalAmount = Xrm.Page.getAttribute("tm_total_amount").getValue() / 1000;

 

        var AccountType = {};

        AccountType.House = 3;

 

        var QuoteType = {};

        QuoteType.Standard = 1;

        QuoteType.Custom = 2;

 

        if (userHasRole && Approver == null) {

            if (TotalAmount < 100 && QuoteTypeValue == QuoteType.Custom && AccountTypeValue != AccountType.House) {

                return false;

            }

 

            return true;

        }

        else {

            return false;

        }

    },

 

    Submit: function () {

        var AccountTypeValue = Xrm.Page.getAttribute("wf_accounttype").getValue();

        var QuoteTypeValue = Xrm.Page.getAttribute("tm_quote_type").getValue();

        var TotalAmount = Xrm.Page.getAttribute("tm_total_amount").getValue() / 1000;

        var ApproverAttribute = Xrm.Page.getAttribute("tm_approver");

        var Approver = ApproverAttribute.getValue();

        var QuoteStatusAttribute = Xrm.Page.getAttribute("tm_quote_status");

        var ApprovalResultAttribute = Xrm.Page.getAttribute("tm_approval_result");

        var CentralizedValue = Xrm.Page.getAttribute("tm_centralized").getValue();

        var SubmitAttribute = Xrm.Page.getAttribute("tm_submit");        

        SubmitAttribute.setSubmitMode("always");

        QuoteStatusAttribute.setSubmitMode("always");

        ApprovalResultAttribute.setSubmitMode("always");

        var AccountType = {};

        AccountType.House = 3;

 

        var QuoteType = {};

        QuoteType.Standard = 1;

        QuoteType.Custom = 2;

 

        var QuoteStatus = {};

        QuoteStatus.Pending = 1;

        QuoteStatus.Approved = 2;

        QuoteStatus.Rejected = 3;

 

        var ApprovalStatus = {};

        ApprovalStatus.Pending = 1;

        ApprovalStatus.Approved = 2;

        ApprovalStatus.Rejected = 3;

 

        if (QuoteTypeValue == QuoteType.Standard) {

            if (TotalAmount <= 500) {

                QuoteStatusAttribute.setValue(QuoteStatus.Approved);

                ApprovalResultAttribute.setValue(ApprovalStatus.Approved);

            }

            else {

                //var sd = HP.QuoteRibbon.GetSalesDirector();

                //var user = [{ "id": sd.guid, "name": sd.name, "entityType": sd.logicalName }];

                //ApproverAttribute.setValue(user);

                QuoteStatusAttribute.setValue(QuoteStatus.Pending);

                ApprovalResultAttribute.setValue(ApprovalStatus.Pending);

            }

        }

        else {

            if (AccountTypeValue == AccountType.House) {

                if (TotalAmount < 500) {

                    ApproverAttribute.setValue(CentralizedValue);

                    QuoteStatusAttribute.setValue(QuoteStatus.Pending);

                    ApprovalResultAttribute.setValue(ApprovalStatus.Pending);

                }

                else if (TotalAmount >= 500) {

                    //var sd = HP.QuoteRibbon.GetSalesDirector();

                    //var user = [{ "id": sd.guid, "name": sd.name, "entityType": sd.logicalName }];

                    //ApproverAttribute.setValue(user);

                    QuoteStatusAttribute.setValue(QuoteStatus.Pending);

                    ApprovalResultAttribute.setValue(ApprovalStatus.Pending);

                }

            }

            else {

                if (TotalAmount >= 100 && TotalAmount < 500) {

                    ApproverAttribute.setValue(CentralizedValue);

                    QuoteStatusAttribute.setValue(QuoteStatus.Pending);

                    ApprovalResultAttribute.setValue(ApprovalStatus.Pending);

                }

                else if (TotalAmount >= 500) {

                    //var sd = HP.QuoteRibbon.GetSalesDirector();

                    //var user = [{ "id": sd.guid, "name": sd.name, "entityType": sd.logicalName }];

                    //ApproverAttribute.setValue(user);

                    QuoteStatusAttribute.setValue(QuoteStatus.Pending);

                    ApprovalResultAttribute.setValue(ApprovalStatus.Pending);

                }

            }

        }

        SubmitAttribute.setValue("Submit_" + new Date());

        Xrm.Page.data.entity.save();

    },

 

2. 审批状态修改事件

ApprovalResultChanged: function () {

 

       var ApprovalStatus = {};

       ApprovalStatus.Pending = 1;

       ApprovalStatus.Approved = 2;

       ApprovalStatus.Rejected = 3;

 

       var QuoteType = {};

       QuoteType.Standard = 1;

       QuoteType.Custom = 2;

 

       var QuoteStatus = {};

       QuoteStatus.Pending = 1;

       QuoteStatus.Approved = 2;

       QuoteStatus.Rejected = 3;

 

       var ApproverAttribute = Xrm.Page.getAttribute("tm_approver");

       var CentralizedValue = Xrm.Page.getAttribute("tm_centralized").getValue();

       var approvalResultValue = Xrm.Page.getAttribute("tm_approval_result").getValue();

       var QuoteStatusAttribute = Xrm.Page.getAttribute("tm_quote_status");

       var ApprovalResultAttribute = Xrm.Page.getAttribute("tm_approval_result");

       var GMValue = Xrm.Page.getAttribute("tm_gmid").getValue();

 

       var AccountTypeValue = Xrm.Page.getAttribute("wf_accounttype").getValue();

       var QuoteTypeValue = Xrm.Page.getAttribute("tm_quote_type").getValue();

       var TotalAmount = Xrm.Page.getAttribute("tm_total_amount").getValue() / 1000;

       QuoteStatusAttribute.setSubmitMode("always");

       ApproverAttribute.setSubmitMode("always");

 

       if (approvalResultValue == ApprovalStatus.Approved) {

           if (QuoteTypeValue == QuoteType.Standard) {

               if (TotalAmount >= 500 && TotalAmount < 1000) {

                   QuoteStatusAttribute.setValue(QuoteStatus.Approved);

                   //ApprovalResultAttribute.setValue(ApprovalStatus.Approved);

               }

               else if (TotalAmount >= 1000) {

                   if (HP.QuoteForm.UserHasRole(["General Manager"]) == true) {

                       QuoteStatusAttribute.setValue(QuoteStatus.Approved);

                       //ApprovalResultAttribute.setValue(ApprovalStatus.Approved);

                   }

                   else {

                       if (CentralizedValue && HP.QuoteForm.GuidsisEqual(Xrm.Page.context.getUserId(), CentralizedValue[0].id)) {

                           HP.QuoteForm.SetLookupValue(ApproverAttribute, GMValue);

                       }

                       else {

                           HP.QuoteForm.SetLookupValue(ApproverAttribute, CentralizedValue);

                       }

                       QuoteStatusAttribute.setValue(QuoteStatus.Pending);

                       ApprovalResultAttribute.setValue(ApprovalStatus.Pending);

                   }

               }

           }

           else {

               if (TotalAmount < 1000) {

                   QuoteStatusAttribute.setValue(QuoteStatus.Approved);

                   //ApprovalResultAttribute.setValue(ApprovalStatus.Approved);

               }

               else if (TotalAmount >= 1000) {

                   if (CentralizedValue && HP.QuoteForm.GuidsisEqual(Xrm.Page.context.getUserId(), CentralizedValue[0].id)) {

                       QuoteStatusAttribute.setValue(QuoteStatus.Approved);

                       //ApprovalResultAttribute.setValue(ApprovalStatus.Approved);

                   }

                   else {

                       if (HP.QuoteForm.UserHasRole(["General Manager"]) == true) {

                           HP.QuoteForm.SetLookupValue(ApproverAttribute, CentralizedValue);

                       }

                       else {

                           HP.QuoteForm.SetLookupValue(ApproverAttribute, GMValue);

                       }

                       QuoteStatusAttribute.setValue(QuoteStatus.Pending);

                       ApprovalResultAttribute.setValue(ApprovalStatus.Pending);

                   }

               }

           }

       }

       else if (approvalResultValue == ApprovalStatus.Rejected) {

           ApproverAttribute.setValue(null);

           QuoteStatusAttribute.setValue(QuoteStatus.Rejected);

           //ApprovalResultAttribute.setValue(ApprovalStatus.Rejected);

       }

   },

 

本文由澳门三合彩票发布于编程,转载请注明出处:流程结束处理,就有了这篇简单审批流的实现

关键词: