package com.iformall.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.IdWorker;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.*;
import com.iformall.domain.po.msg.MailMsg;
import com.iformall.domain.po.msg.WxMsgRecord;
import com.iformall.domain.vo.FlowUserVo;
import com.iformall.domain.vo.UserTaskVo;
import com.iformall.domain.vo.WxBillAll;
import com.iformall.enums.*;
import com.iformall.mapper.*;
import com.iformall.mq.MqBaseProducer;
import com.iformall.service.*;
import com.iformall.utils.Constant;
import com.iformall.utils.JsonUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.api.FlowableIllegalArgumentException;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.DeploymentBuilder;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author luozukai
 * @date 2019/1/10 14:59
 */
@Service
public class WxFlowServiceImpl implements WxFlowService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ProcessEngine processEngine;
    @Autowired
    private WxRentContractService wxRentContractService;
    @Autowired
    private WxFlowRecordService wxFlowRecordService;
    @Autowired
    private MallUserInfoService mallUserInfoService;
    @Autowired
    private WxPropertyContractMapper wxPropertyContractMapper;
    @Autowired
    private WxPropertyContractService wxPropertyContractService;
    @Autowired
    private WxFlowRecordMapper wxFlowRecordMapper;
    @Autowired
    private MqBaseProducer mqBaseProducer;
    @Autowired
    private WxFlowModelMapper wxFlowModelMapper;
    @Autowired
    private WxFlowConfigMapper wxFlowConfigMapper;
    @Autowired
    private WxBillAllService wxBillAllService;
    @Autowired
    private WxCouponMapper wxCouponMapper;
    @Autowired
    private WxCouponService wxCouponService;
    @Autowired
    private WxRentContractMapper wxRentContractMapper;
    @Autowired
    private WxBillSettleMapper wxBillSettleMapper;
    @Autowired
    private WxBillSettleService wxBillSettleService;

    /**
     * 获取流程key
     * @param flowType
     * @return
     */
    public WxFlowModel getModelByType(int flowType,String tenantId){
        WxFlowModel model = new WxFlowModel();
        model.setTenantId(tenantId);
        model.setFlowType(flowType);
        List<WxFlowModel> list = getModelBybusiness(model);
        if(CollectionUtils.isNotEmpty(list)){
            return list.get(0);
        }
        return null;
    }

    /**
     * 更新业务数据状态
     * @param mapInfo
     * @param applyStatus
     */
    @Override
    public void updateBusinessStatus(Map<String, Object> mapInfo,Integer applyStatus){
        Long businessId = Long.parseLong(mapInfo.get("businessId").toString());
        Integer flowType = getIngeter(mapInfo.get("flowType"));
        List<Map<String,Object>> variables = (List)mapInfo.get("variables");
        Integer contractType = 0;
        String str = (String)getVariableByKey(variables,"contractType");
        Integer operateType = getIngeter(getVariableByKey(variables,"approvalType"));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if(StringUtils.isNotBlank(str)){
            contractType = Integer.parseInt(str);
        }

        if(EnumFlowKey.CONTRACT.getCode().equals(flowType) ||
                EnumFlowKey.NEW_RENT_CONTRACT.getCode().equals(flowType) ||
                EnumFlowKey.NEW_SHOP_CONTRACT.getCode().equals(flowType)||
                EnumFlowKey.NEW_PRO_CONTRACT.getCode().equals(flowType)||
                EnumFlowKey.NEW_PRO_POINT_CONTRACT.getCode().equals(flowType)||
                EnumFlowKey.NNEW_RENT_CONTRACT.getCode().equals(flowType)||
                EnumFlowKey.NEW_RENT_POINT_CONTRACT.getCode().equals(flowType)
                ){
            // 1租赁合同 2点位合同 3物业 4点位物业合同 5 合并合同-店铺 6 合并合同-多经点位
            if (EnumFlowContractType.RENT.getCode().equals(contractType) ||
                    EnumFlowContractType.RENT_POINT.getCode().equals(contractType) ||
                    EnumFlowContractType.WHOLE_SHOP.getCode().equals(contractType) ||
                    EnumFlowContractType.WHOLE_POINT.getCode().equals(contractType)) {
                WxRentContract rent = new WxRentContract();
                rent.setId(businessId);
                rent.setApplyStatus(applyStatus);
                rent.setBusinessType(flowType);
                wxRentContractService.updateApplyStatus(rent);

                //如果审批完成，而且是补录直接改为已签约状态(普通需要绑定商户才是已签约)
                WxRentContract record = wxRentContractMapper.selectById(businessId);
                if(record != null && record.getMerchantId()!=null && EnumRentContractAppStatus.FINISH.getCode().intValue() == applyStatus.intValue()) {
                    wxRentContractService.updateRentContractStatus(businessId);
                }
            }else if(EnumFlowContractType.PROPERTY.getCode().equals(contractType) || EnumFlowContractType.PROPERTY_POINT.getCode().equals(contractType)){
                WxPropertyContract wxPropertyContract = new WxPropertyContract();
                wxPropertyContract.setId(businessId);
                wxPropertyContract.setApplyStatus(applyStatus);
                wxPropertyContract.setBusinessType(flowType);
                wxPropertyContractMapper.updateApplyStatus(wxPropertyContract);

                // 审批完成，物业合同的合同状态需要和租赁合同同步（一致）
                if(EnumRentContractAppStatus.FINISH.getCode().intValue() == applyStatus.intValue()) {
                    wxPropertyContractService.updatePropertyContractStatus(businessId);
                }
            }
        }else if(EnumFlowKey.END_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_RENT_END_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_SHOP_END_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_PRO_END.getCode().equals(flowType)
                || EnumFlowKey.NEW_PRO_POINT_CONTRACT_END.getCode().equals(flowType)
                || EnumFlowKey.NEW_RENT_END.getCode().equals(flowType)
                || EnumFlowKey.NEW_RENT_POINT_CONTRACT_END.getCode().equals(flowType)
                ){
            if(EnumFlowContractType.RENT.getCode().equals(contractType) ||
                    EnumFlowContractType.RENT_POINT.getCode().equals(contractType) ||
                    EnumFlowContractType.RENT_POINT.getCode().equals(contractType) ||
                    EnumFlowContractType.WHOLE_SHOP.getCode().equals(contractType) ||
                    EnumFlowContractType.WHOLE_POINT.getCode().equals(contractType)){
                WxRentContract rent = new WxRentContract();
                rent.setId(businessId);
                rent.setApplyStatus(applyStatus);
                rent.setBusinessType(flowType);

                if(EnumRentContractAppStatus.FINISH.getCode().intValue() == applyStatus.intValue()) {
                    rent.setStatus(EnumRentContractStatus.CONTRACT_TERMINATE.getCode());

                    //终止租赁合同，同时终止物业合同
                    Integer endProperty = getIngeter(getVariableByKey(variables,"endProperty"));
                    rent.setEndProperty(endProperty);
                    wxRentContractService.endContract(rent);
                }
                wxRentContractService.updateApplyStatus(rent);
            }else if(EnumFlowContractType.PROPERTY.getCode().equals(contractType)  || EnumFlowContractType.PROPERTY_POINT.getCode().equals(contractType)){
                WxPropertyContract wxPropertyContract = new WxPropertyContract();
                wxPropertyContract.setId(businessId);
                wxPropertyContract.setApplyStatus(applyStatus);
                wxPropertyContract.setBusinessType(flowType);

                if(EnumRentContractAppStatus.FINISH.getCode().intValue() == applyStatus.intValue()) {
                    wxPropertyContract.setStatus(EnumRentContractStatus.CONTRACT_TERMINATE.getCode());

                    //账单失效
                    wxPropertyContractService.endContract(wxPropertyContract);
                }
                wxPropertyContractMapper.updateApplyStatus(wxPropertyContract);
            }
        } else if (EnumFlowKey.BILL.getCode().equals(flowType) || EnumFlowKey.NEW_BILL_CHANGE.getCode().equals(flowType)) {
            Integer billType = getIngeter(getVariableByKey(variables, "billType"));
            if(EnumRentContractAppStatus.FINISH.getCode().intValue() == applyStatus.intValue()) {
                //账单审批
                MallUserInfo user = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute("userSession");
                Integer billUpdateType = getIngeter(getVariableByKey(variables, "billUpdateType"));
                Long oldPrice = Long.parseLong(getVariableByKey(variables, "oldPrice").toString());
                Long newPrice = Long.parseLong(getVariableByKey(variables, "newPrice").toString());
                WxBillAll wxBillAll = new WxBillAll();
                wxBillAll.setId(businessId);
                wxBillAll.setBillTypeValue(billType);
                if(EnumBillUpdateType.LATEPAY.getCode().equals(billUpdateType)){ //修改滞纳金
                    wxBillAll.setOldLatePrice(oldPrice);
                    wxBillAll.setNewLatePrice(newPrice);
                }else{
                    wxBillAll.setOldPrice(oldPrice);
                    wxBillAll.setNewPrice(newPrice);
                }
                wxBillAllService.updateReceivePay(wxBillAll, user);

                //账单修改金额，解冻
                List<WxBillSettleBill> billList = new ArrayList<>();
                WxBillSettleBill settleBill = new WxBillSettleBill();
                settleBill.setBillType(billType);
                settleBill.setBillId(businessId);
                billList.add(settleBill);
                wxBillSettleService.updateFreezeOrStatus(billList,EnumFreezeType.DEF.getCode(),null);
            }else if(EnumRentContractAppStatus.APPLYING.getCode().intValue() == applyStatus.intValue()) {
                //账单修改金额，冻结
                List<WxBillSettleBill> billList = new ArrayList<>();
                WxBillSettleBill settleBill = new WxBillSettleBill();
                settleBill.setBillType(billType);
                settleBill.setBillId(businessId);
                billList.add(settleBill);
                wxBillSettleService.updateFreezeOrStatus(billList,EnumFreezeType.YES.getCode(),null);
            }else if(EnumRentContractAppStatus.SETBACK.getCode().intValue() == applyStatus.intValue() || EnumRentContractAppStatus.REJECT.getCode().intValue() == applyStatus.intValue()) {
                //账单修改金额，解冻
                List<WxBillSettleBill> billList = new ArrayList<>();
                WxBillSettleBill settleBill = new WxBillSettleBill();
                settleBill.setBillType(billType);
                settleBill.setBillId(businessId);
                billList.add(settleBill);
                wxBillSettleService.updateFreezeOrStatus(billList,EnumFreezeType.DEF.getCode(),null);
            }
        } else if (EnumFlowKey.NEW_COUPON_UPLINE.getCode().equals(flowType)
                || EnumFlowKey.NEW_CARD_UPLINE.getCode().equals(flowType)
                || EnumFlowKey.NEW_GROUP_UPLINE.getCode().equals(flowType)
                || EnumFlowKey.NEW_PRESS_UPLINE.getCode().equals(flowType)) {
            WxCoupon wxCoupon = new WxCoupon();
            wxCoupon.setId(businessId);
            wxCoupon.setUpdateDate(new Date());

            if(EnumCouponAppType.PUT.getCode().equals(operateType)){
                wxCoupon.setPutApplyStatus(applyStatus);
            }else if(EnumCouponAppType.STOCK.getCode().equals(operateType)){
                wxCoupon.setStockApplyStatus(applyStatus);
                if(EnumRentContractAppStatus.FINISH.getCode().intValue() == applyStatus.intValue()) {
                    //减库存
                    Integer inventory = getIngeter(getVariableByKey(variables, "inventory"));
                    Integer remainInventory = getIngeter(getVariableByKey(variables, "remainInventory"));
                    Integer type = getIngeter(getVariableByKey(variables, "type"));
                    Integer validDays = getIngeter(getVariableByKey(variables, "validDays"));
                    Integer validType = getIngeter(getVariableByKey(variables, "validType"));

                    String validStartDate = (String) getVariableByKey(variables, "validStartDate");
                    String validEndDate = (String) getVariableByKey(variables, "validEndDate");
                    try {
                        if(validStartDate != null) {
                            wxCoupon.setValidStartDate(sdf.parse(validStartDate));
                        }
                        if(validEndDate != null){
                            wxCoupon.setValidEndDate(sdf.parse(validEndDate));
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }

                    if(validDays != null){
                        wxCoupon.setValidDays(validDays);
                    }
                    wxCoupon.setInventory(inventory);
                    wxCoupon.setRemainInventory(remainInventory);
                    wxCoupon.setType(type);
                    wxCoupon.setValidType(validType);
                    wxCouponService.updateCouponStockAndEndTime(wxCoupon);
                }
            }else if(EnumCouponAppType.CANCLE.getCode().equals(operateType)){
                wxCoupon.setCancleApplyStatus(applyStatus);
                if(EnumRentContractAppStatus.FINISH.getCode().intValue() == applyStatus.intValue()) {
                    //作废
                    wxCoupon.setStatus(EnumCouponStatus.COUPON_STATUS_TAKE_OFFF.getCode());
                    wxCouponMapper.updateById(wxCoupon);
                }
            }
            wxCoupon.setApprovalType(operateType);
            wxCouponMapper.updateById(wxCoupon);
        }else if(EnumFlowKey.SETTLE.getCode().equals(flowType)){
            WxBillSettle wxBillSettle = new WxBillSettle();
            wxBillSettle.setId(businessId);
            wxBillSettle.setApplyStatus(applyStatus);

            //审批完成,账单解冻
            WxBillSettle settle = wxBillSettleService.getById(businessId, EnumFilterSettle.NO.getCode());
            if(EnumRentContractAppStatus.FINISH.getCode().intValue() == applyStatus.intValue()) {
                wxBillSettle.setStatus(EnumSettleStatus.NOT_FINISH.getCode());
                wxBillSettleService.updateFreezeOrStatus(settle.getReceiveBillIds(), EnumFreezeType.DEF.getCode(),EnumBillRentStatus.PAID.getCode());
                wxBillSettleService.updateFreezeOrStatus(settle.getPayBillIds(),EnumFreezeType.DEF.getCode(),EnumBillRentStatus.PAID.getCode());

                //刚好结清
                if(settle.getReceiveMoney().equals(settle.getPayMoney())){
                    wxBillSettle.setStatus(EnumSettleStatus.FINISH.getCode());
                }
            }else if(EnumRentContractAppStatus.SETBACK.getCode().intValue() == applyStatus.intValue() || EnumRentContractAppStatus.REJECT.getCode().intValue() == applyStatus.intValue()) {
                //解冻
                wxBillSettleService.updateFreezeOrStatus(settle.getReceiveBillIds(), EnumFreezeType.DEF.getCode(),null);
                wxBillSettleService.updateFreezeOrStatus(settle.getPayBillIds(),EnumFreezeType.DEF.getCode(),null);
            }
            wxBillSettleMapper.updateById(wxBillSettle);
        }
    }

    public Map<String,Object> mallUserInfoToMap(MallUserInfo userInfo){
        try {
            Map<String, Object> map = new HashMap<>();
            Class<?> clazz = userInfo.getClass();
            for (Field field : clazz.getDeclaredFields()) {
                field.setAccessible(true);
                String fieldName = field.getName();
                Object value = field.get(userInfo);
                map.put(fieldName, value);
            }
            return map;
        }catch (IllegalAccessException e){
            logger.error("mallUserInfoToMap error",e);
        }
        return new HashMap<>();
    }

    /**
     * 设置会签代办人
     */
    public void setSignAssignee(Map<String, Object> map, String flowJsoin){
        WxFlowModel flowModel = (WxFlowModel)JsonUtil.readValue(flowJsoin,WxFlowModel.class);
        List<UserTaskVo> taskAssigneeList = flowModel.getLists();
        for (UserTaskVo userTaskVo:taskAssigneeList) {
            if(EnumTaskType.AND.getCode().equals(userTaskVo.getType())){
                List<String> assigneeList = new ArrayList<>();
                for (FlowUserVo flowUserVo:userTaskVo.getUserList()) {
                    assigneeList.add(flowUserVo.getId());
                }
                map.put(userTaskVo.getKey()+"_signAssignee",assigneeList);
            }
        }
    }

    public Integer getIngeter(Object obj){
        if(obj == null) return null;
        if(obj instanceof String){
            return Integer.parseInt((String)obj);
        }else if(obj instanceof Integer){
            return (Integer)obj;
        }
        return null;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = {Exception.class})
    public ResultData start(Map<String, Object> params,Long userId,String userName,String tenantId) {
        String remark = (String)params.get("remark");
        Long businessId = Long.parseLong(params.get("businessId").toString());
        Integer flowType = getIngeter(params.get("businessType"));
        List<Map<String,Object>> variables = (List)params.get("variables");

        WxFlowModel flowModel = getModelByType(flowType,tenantId);
        if(flowModel== null || StringUtils.isBlank(flowModel.getFlowId())){
            return new ResultData(ResultData.ERROR, "您尚未设置审批模板，请先设置。");
        }

        // 设置节点处理人
        HashMap<String, Object> map = new HashMap<>();
        // map info,设置发起人等信息
        Date startDate = new Date();
        MallUserInfo starterInfo = this.mallUserInfoService.getById(userId);
        map.put("starter", mallUserInfoToMap(starterInfo));
        map.put("startTime", startDate.getTime());
        map.put("startDate", startDate);
        map.put("businessId",businessId+"");
        map.put("flowType",flowType);
        map.put("variables",variables);
        map.put("taskAssignee",flowModel.getFlow());
        setSignAssignee(map,flowModel.getFlow());
        map.put("tenantId",tenantId);

        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(flowModel.getFlowId(), map);
        logger.debug("流程启动，流程id:{}",processInstance.getId());

        params.put("flowType",flowType);
        updateBusinessStatus(params,EnumRentContractAppStatus.APPLYING.getCode());

        // 保存wx_flow_record表审批记录
        WxFlowRecord wxFlowRecord = new WxFlowRecord();
        wxFlowRecord.setBusinessId(businessId);
        wxFlowRecord.setBusinessType(flowType);
        wxFlowRecord.setProcessInstanceId(processInstance.getId());
        wxFlowRecord.setRemark(remark);
        wxFlowRecord.setUserId(userId);
        wxFlowRecord.setUserName(userName);
        wxFlowRecord.setStatus(EnumFlowRecordStatus.NEW.getCode());
        wxFlowRecord.setTaskName("发起");
        wxFlowRecord.setCurrStatus(EnumRentContractAppStatus.APPLYING.getCode());
        wxFlowRecord.setVariables(variablesToJson(variables));
        wxFlowRecord.setStartDate(startDate);
        wxFlowRecordService.saveOrUpdate(wxFlowRecord);

        //给审批人发送代办通知短信
        List<MallUserInfo> mallUserInfoList = getUserByProcessInstanceId(processInstance.getId());
        for (MallUserInfo mallUserInfo:mallUserInfoList) {
            sendAssigneeMsgAndEmail(tenantId, mallUserInfo.getPhone(), mallUserInfo.getEmail(), starterInfo.getName(), businessId, flowType, variables);
        }
        return new ResultData();
    }

    public void sendAssigneeMsgAndEmail(String tenantId, String phone, String email, String userName, Long businessId, Integer flowType, List<Map<String, Object>> variables) {
        Map<String,String> dynamicContentMap = new HashMap<>();
        dynamicContentMap.put("userName",userName);
        dynamicContentMap.put("page", Constant.adminPage);
        WxMsgRecord wxMsgRecord = new WxMsgRecord();
        wxMsgRecord.setMsgType(EnumMsgRecordType.SMS.getCode());
        wxMsgRecord.setModelType(EnumMsgModel.FLOW_ASSIGNEE_NODIFY.getCode());
        wxMsgRecord.setReceiver(phone);
        wxMsgRecord.setTenantId(tenantId);
        if(isContract(flowType)){
            dynamicContentMap.put("bustype","合同");
        }else if(isBill(flowType)){
            dynamicContentMap.put("bustype","账单");
            dynamicContentMap.put("contract", businessId.toString());
        }else if(isCoupon(flowType)){
            wxMsgRecord.setModelType(EnumMsgModel.FLOW_C_ASSIGNEE_NODIFY.getCode());
        }else if(isSettle(flowType)){
            dynamicContentMap.put("bustype","结算单");
            dynamicContentMap.put("contract", (String) getVariableByKey(variables, "settleNumber"));
        }
        wxMsgRecord.setDynamicContentMap(dynamicContentMap);
        mqBaseProducer.sendMessage(wxMsgRecord, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode());

        //发邮件
        Map msgReplaceMap = new HashedMap();
        msgReplaceMap.put("page", Constant.adminPage);
        msgReplaceMap.put("applyTime", new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date()));
        msgReplaceMap.put("name",userName);
        msgReplaceMap.put("linkName",userName);
        msgReplaceMap.put("linkPhone",phone);
        ResultData resultData = getTaskStatusList(businessId, tenantId);
        List<WxFlowRecord> flowRecordList = (List<WxFlowRecord>) resultData.data;
        String taskListHtml = "";
        for (int i = flowRecordList.size() -1; i>=0; i--) {
            WxFlowRecord record = flowRecordList.get(i);
            String remark = record.getRemark()==null?"":record.getRemark();
            if (record.getStatus().equals(EnumFlowRecordStatus.NEW.getCode())) {
                taskListHtml += "<div style=\"overflow: hidden;\">";
                taskListHtml += "<div style=\"overflow: hidden;\">";
                taskListHtml += "<div style=\"float: left; width: 40px;height: 30px;\"><img src=\"https://s3.cn-northwest-1.amazonaws.com.cn/iformall-net/cimg/emailduihao.png\" style=\"display: block; width: 20px;height: 20px;margin-top: 10px;\"></div>";
                taskListHtml += "<div style=\"float: left; width: auto;margin-right:10px;height: 30px;line-height: 18px;font-size:18px;font-family:MicrosoftYaHei;font-weight:400;color:rgba(51,51,51,1);margin-top: 11px;\">发起申请</div>";
                taskListHtml += "<div style=\"float: left; width: auto;margin-right:10px;height: 30px;margin-top:15px;line-height: 14px;font-size:14px;font-family:MicrosoftYaHei;font-weight:400;color:rgba(51,51,51,1);\">"+record.getUserName()+"</div>";
                taskListHtml += "</div>";
                if(i == 0){
                    taskListHtml += "<div style=\"width: 80%; overflow: hidden;font-size:14px;font-family:MicrosoftYaHei;font-weight:400;padding-left: 30px;margin-left: 10px;padding-bottom: 20px; line-height: 24px; color:rgba(153,153,153,1);\">"+remark+"</div>";
                }else{
                    taskListHtml += "<div style=\"width: 80%; overflow: hidden;font-size:14px;font-family:MicrosoftYaHei;font-weight:400;padding-left: 30px;margin-left: 10px;padding-bottom: 20px; line-height: 24px; border-left: 2px dashed #DEDEDE; color:rgba(153,153,153,1);\">"+remark+"</div>";
                }
                taskListHtml += "</div>";
            } else if (record.getStatus().equals(EnumFlowRecordStatus.ASSIGNEE.getCode())) {
                taskListHtml += "<div style=\"overflow: hidden;\">";
                taskListHtml += "<div style=\"overflow: hidden;\">";
                taskListHtml += "<div style=\"float: left; width: 40px;height: 30px;\"><img src=\"https://s3.cn-northwest-1.amazonaws.com.cn/iformall-net/cimg/emailhong.png\" style=\"display: block; width: 20px;height: 20px;margin-top: 10px;\"></div>";
                taskListHtml += "<div style=\"float: left; width: auto;margin-right:10px;height: 30px;line-height: 18px;font-size:18px;font-family:MicrosoftYaHei;font-weight:400;color:rgba(200,89,98,1);margin-top: 11px;\">待审批</div>";
                taskListHtml += "<div style=\"float: left; width: auto;margin-right:10px;height: 30px;margin-top:15px;line-height: 14px;font-size:14px;font-family:MicrosoftYaHei;font-weight:400;color:rgba(200,89,98,1);\">"+record.getUserName()+"</div>";
                taskListHtml += "</div>";
                if(i == 0){
                    taskListHtml += "<div style=\"width: 80%; overflow: hidden;font-size:14px;font-family:MicrosoftYaHei;font-weight:400;padding-left: 30px;margin-left: 10px;padding-bottom: 20px; line-height: 24px; color:rgba(153,153,153,1);\">"+remark+"</div>";
                }else{
                    taskListHtml += "<div style=\"width: 80%; overflow: hidden;font-size:14px;font-family:MicrosoftYaHei;font-weight:400;padding-left: 30px;margin-left: 10px;padding-bottom: 20px; line-height: 24px; border-left: 2px dashed #DEDEDE; color:rgba(153,153,153,1);\">"+remark+"</div>";
                }
                taskListHtml += "</div>";
            } else {
                taskListHtml += "<div style=\"overflow: hidden;\">";
                taskListHtml += "<div style=\"overflow: hidden;\">";
                taskListHtml += "<div style=\"float: left; width: 40px;height: 30px;\"><img src=\"https://s3.cn-northwest-1.amazonaws.com.cn/iformall-net/cimg/emailhui.png\" style=\"display: block; width: 20px;height: 20px;margin-top: 10px;\"></div>";
                taskListHtml += "<div style=\"float: left; width: auto;margin-right:10px;height: 30px;line-height: 18px;font-size:18px;font-family:MicrosoftYaHei;font-weight:400;color:rgba(153,153,153,1);margin-top: 11px;\">审批通过</div>";
                taskListHtml += "<div style=\"float: left; width: auto;margin-right:10px;height: 30px;margin-top:15px;line-height: 14px;font-size:14px;font-family:MicrosoftYaHei;font-weight:400;color:rgba(153,153,153,1);\">"+record.getUserName()+"</div>";
                taskListHtml += "</div>";
                if(i == 0){
                    taskListHtml += "<div style=\"width: 80%; overflow: hidden;font-size:14px;font-family:MicrosoftYaHei;font-weight:400;padding-left: 30px;margin-left: 10px;padding-bottom: 20px; line-height: 24px; color:rgba(153,153,153,1);\">"+remark+"</div>";
                }else{
                    taskListHtml += "<div style=\"width: 80%; overflow: hidden;font-size:14px;font-family:MicrosoftYaHei;font-weight:400;padding-left: 30px;margin-left: 10px;padding-bottom: 20px; line-height: 24px; border-left: 2px dashed #DEDEDE; color:rgba(153,153,153,1);\">"+remark+"</div>";
                }
                taskListHtml += "</div>";
            }
        }
        msgReplaceMap.put("taskList", taskListHtml);

        if(StringUtils.isBlank(email)){
            logger.info("phone:{},userName:{}邮件地址为空，不发送代办邮件",phone,userName);
        }else{
            MailMsg mailMsg = new MailMsg();
            mailMsg.setSubject("待办通知");
            mailMsg.setHtml(true);
            mailMsg.setMsgType(EnumMsgRecordType.EMAIL.getCode());
            mailMsg.setModelType(EnumMailMsgModel.MAIL_ASSIGNEE_NODIFY.getCode());
            mailMsg.setModelId(EnumMsgModelId.MAIL_MSG_FLOW.getCode());
            mailMsg.setTo(new String[]{email});
            mailMsg.setTenantId(tenantId);
            if(isContract(flowType)){
                msgReplaceMap.put("bustype","合同");
            }else if(isBill(flowType)){
                msgReplaceMap.put("bustype","账单");
                msgReplaceMap.put("contract", businessId.toString());
            }else if(isCoupon(flowType)){
                mailMsg.setModelType(EnumMailMsgModel.MAIL_C_ASSIGNEE_NODIFY.getCode());
            }else if(isSettle(flowType)){
                msgReplaceMap.put("bustype","结算单");
                msgReplaceMap.put("contract", getVariableByKey(variables, "settleNumber"));
            }
            mailMsg.setDynamicContentMap(msgReplaceMap);
            mqBaseProducer.sendMessage(mailMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode());
        }
    }

    public boolean isContract(Integer flowType){
        if(EnumFlowKey.CONTRACT.getCode().equals(flowType)
                ||EnumFlowKey.END_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_RENT_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_SHOP_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_RENT_END_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_SHOP_END_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_PRO_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_PRO_POINT_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_PRO_END.getCode().equals(flowType)
                || EnumFlowKey.NEW_PRO_POINT_CONTRACT_END.getCode().equals(flowType)
                || EnumFlowKey.NNEW_RENT_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_RENT_END.getCode().equals(flowType)
                || EnumFlowKey.NEW_RENT_POINT_CONTRACT.getCode().equals(flowType)
                || EnumFlowKey.NEW_RENT_POINT_CONTRACT_END.getCode().equals(flowType)
                ){
            return true;
        }
        return false;
    }

    public boolean isBill(Integer flowType){
        if(EnumFlowKey.BILL.getCode().equals(flowType)
                ||EnumFlowKey.NEW_BILL_CHANGE.getCode().equals(flowType)){
           return true;
        }
        return false;
    }
    public boolean isCoupon(Integer flowType){
        if(EnumFlowKey.NEW_COUPON_UPLINE.getCode().equals(flowType)
                ||EnumFlowKey.NEW_CARD_UPLINE.getCode().equals(flowType)
                ||EnumFlowKey.NEW_GROUP_UPLINE.getCode().equals(flowType)
                ||EnumFlowKey.NEW_PRESS_UPLINE.getCode().equals(flowType)
                ){
            return true;
        }
        return false;
    }
    public boolean isSettle(Integer flowType){
        if(EnumFlowKey.SETTLE.getCode().equals(flowType)){
            return true;
        }
        return false;
    }

    public String variablesToJson(List<Map<String,Object>> variables){
        HashMap<String,Object> map = new HashMap<>();
        for (Map<String,Object> mapInfo:variables) {
            map.put((String)mapInfo.get("key"),mapInfo.get("value"));
        }
        return JSONUtils.toJSONString(map);
    }

    @Override
    public ResultData list(String flowType, Integer pageNum, Integer pageSize,Long userId,String tenantId) {
        TaskQuery taskQuery = taskService.createTaskQuery();
        //流程过滤条件
        if(StringUtils.isNotBlank(flowType)) {
            List<String> definitionKeyList = new ArrayList<>();
            for (String ft : flowType.split(",")) {
                WxFlowModel flowModel = getModelByType(Integer.parseInt(ft),tenantId);
                if(flowModel!=null) {
                    definitionKeyList.add(flowModel.getFlowId());
                }
            }
            if(CollectionUtils.isNotEmpty(definitionKeyList)){
                taskQuery.processDefinitionKeyIn(definitionKeyList);
            }
        }

        int total = taskQuery.taskCandidateOrAssigned(userId.toString()).list().size();
        int pages;
        if(total % pageSize == 0){
            pages = total / pageSize;
        }else{
            pages = total / pageSize +1;
        }

        List<Task> tasks = taskQuery.orderByTaskCreateTime().desc()
                .listPage((pageNum -1) * pageSize,pageSize);
        List<Map<String,Object>> result = new ArrayList<>();

        for (Task task : tasks) {
            Map<String,Object> taskInfoMap = new HashedMap();
            Map<String,Object> mapInfo = taskService.getVariables(task.getId());
            if(mapInfo!=null){
                Map<String,Object> userMap = (Map<String,Object>)mapInfo.get("starter");
                taskInfoMap.put("starter",userMap!=null?userMap.get("name"):"");
                taskInfoMap.put("startTime",mapInfo.get("startTime"));
                taskInfoMap.put("processInstanceId",task.getProcessInstanceId());
                taskInfoMap.put("taskId",task.getId());
                taskInfoMap.put("businessId",mapInfo.get("businessId"));
                taskInfoMap.put("businessType",mapInfo.get("flowType"));
                List<Map<String,Object>> variables = (List)mapInfo.get("variables"); //定制variables，回传
                Map<String,Object> variablesMap = new HashedMap();
                if(CollectionUtils.isNotEmpty(variables)){
                    for (Map<String,Object> m:variables) {
                        taskInfoMap.put((String)m.get("key"),m.get("value"));
                        variablesMap.put((String)m.get("key"),m.get("value"));
                    }
                }
                taskInfoMap.put("businessType",mapInfo.get("flowType"));
                taskInfoMap.put("variables",JSONUtils.toJSONString(variablesMap));
                result.add(taskInfoMap);
            }
        }
        PageHelper.startPage(pageNum, pageSize);
        PageInfo<Map<String,Object>> pageInfo = new PageInfo<>(result);
        pageInfo.setPages(pages);
        pageInfo.setTotal(total);
        PageHelper.clearPage();
        return new ResultData(pageInfo);
    }

    @Override
    public ResultData applyHistory(Long businessId,String tenantId) {
        List<WxFlowRecord> result;
        WxCoupon query = new WxCoupon();
        query.setTenantId(tenantId);
        query.setId(businessId);
        List<WxCoupon> couponList = wxCouponMapper.findList(query);
        if(CollectionUtils.isNotEmpty(couponList)) {
            WxCoupon coupon = couponList.get(0);
            result = wxFlowRecordService.findList(new WxFlowRecord(businessId,tenantId,coupon.getApprovalType()));
        }else{
            result = wxFlowRecordService.findList(new WxFlowRecord(businessId,tenantId));
        }

        if(CollectionUtils.isNotEmpty(result)){
            String processInstanceId = result.get(0).getProcessInstanceId();
            List<MallUserInfo> mallUserInfoList = getUserByProcessInstanceId(processInstanceId);

            // 如果有代办，加一条待审批
            if(CollectionUtils.isNotEmpty(mallUserInfoList)){
                String assignee = "";
                for (MallUserInfo mallUserInfo:mallUserInfoList) {
                    assignee += mallUserInfo.getName()+" ";
                }

                WxFlowRecord wxFlowRecord = new WxFlowRecord();
                wxFlowRecord.setUserName(assignee.trim());
                wxFlowRecord.setStatus(EnumFlowRecordStatus.ASSIGNEE.getCode());
                result.add(0,wxFlowRecord);
            }
        }
        return new ResultData(result);
    }

    @Override
    public ResultData getTaskStatusList(Long businessId, String tenantId) {
        List<WxFlowRecord> resultList = wxFlowRecordService.findList(new WxFlowRecord(businessId,tenantId));
        if(CollectionUtils.isEmpty(resultList)){
            return new ResultData();
        }
        Integer flowType = resultList.get(0).getBusinessType();
        String processInstanceId = resultList.get(0).getProcessInstanceId();
        ProcessInstance pi = null;
        try {
            pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        }catch (FlowableIllegalArgumentException e){
            logger.error("getTaskStatusList query inst error",e);
        }
        if(pi == null){
            return new ResultData(ErrorCode.FLOW_INST_NOT_EXIST.getCode(), "任务不存在");
        }

        if(flowType.intValue() <= EnumFlowKey.END_CONTRACT.getCode().intValue()){
            //老数据
            Task task = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
            Map<String,Object> mapInfo = taskService.getVariables(task.getId());
            List<Map<String,String>> taskAssigneeList = (List)mapInfo.get("taskAssignee");
            for (int i = 0; i < taskAssigneeList.size(); i++) {
                Map<String,String> assignee = taskAssigneeList.get(i);
                if(task.getTaskDefinitionKey().equals(assignee.get("taskKey"))){
                    //设置当前节点代办人信息
                    String[] assigneeArray = assignee.get("assignee").split(",");
                    String userName = "";
                    for (int j = 0; j < assigneeArray.length; j++) {
                        String userid = assigneeArray[j];
                        MallUserInfo mallUserInfo = this.mallUserInfoService.getById(Long.parseLong(userid));
                        if(j != assigneeArray.length-1){
                            userName += mallUserInfo.getName()+",";
                        }else{
                            userName += mallUserInfo.getName()+"";
                        }
                    }
                    WxFlowRecord wxFlowRecord = new WxFlowRecord();
                    wxFlowRecord.setUserName(userName.trim());
                    wxFlowRecord.setStatus(EnumFlowRecordStatus.ASSIGNEE.getCode());
                    wxFlowRecord.setTaskKey(task.getTaskDefinitionKey());
                    resultList.add(0,wxFlowRecord);

                    //不是最后一个节点,设置下一个待审批节点代办人
                    if(i != taskAssigneeList.size()-1){
                        assignee = taskAssigneeList.get(i+1);
                        // 下一个节点没设置代办人
                        if(StringUtils.isBlank(assignee.get("assignee"))){
                            continue;
                        }
                        assigneeArray = assignee.get("assignee").split(",");
                        userName = "";
                        for (String userid:assigneeArray) {
                            MallUserInfo mallUserInfo = this.mallUserInfoService.getById(Long.parseLong(userid));
                            userName += mallUserInfo.getName()+" ";
                        }

                        wxFlowRecord = new WxFlowRecord();
                        wxFlowRecord.setUserName(userName.trim());
                        wxFlowRecord.setStatus(EnumFlowRecordStatus.ASSIGNEE.getCode());
                        wxFlowRecord.setTaskKey(UUID.randomUUID().toString());
                        resultList.add(0,wxFlowRecord);
                        break;
                    }
                }else{
                    continue;
                }
            }
        }else{
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(pi.getId()).list();
            Map<String,Object> mapInfo = taskService.getVariables(taskList.get(0).getId());
            //WxFlowModel flowModelDb = getModelByType(flowType,tenantId);
            String flowJson = (String)mapInfo.get("taskAssignee");
            WxFlowModel flowModel = (WxFlowModel)JsonUtil.readValue(flowJson,WxFlowModel.class);
            List<UserTaskVo> taskAssigneeList = flowModel.getLists();
            for (int i = 0; i < taskAssigneeList.size(); i++) {
                UserTaskVo assignee = taskAssigneeList.get(i);
                if(taskList.get(0).getTaskDefinitionKey().equals(assignee.getKey())){
                    //设置当前节点代办人信息
                    String userName = "";
                    for (int j = 0; j < assignee.getUserList().size(); j++) {
                        FlowUserVo userVo = assignee.getUserList().get(j);
                        if(j != assignee.getUserList().size() - 1){
                            userName += userVo.getName()+",";
                        }else{
                            userName += userVo.getName()+"";
                        }
                    }

                    WxFlowRecord wxFlowRecord = new WxFlowRecord();
                    wxFlowRecord.setUserName(userName.trim());
                    wxFlowRecord.setStatus(EnumFlowRecordStatus.ASSIGNEE.getCode());
                    wxFlowRecord.setTaskKey(assignee.getKey());
                    wxFlowRecord.setTaskType(assignee.getType());
                    resultList.add(0,wxFlowRecord);

                    //不是最后一个节点,设置下一个待审批节点代办人
                    if(i != taskAssigneeList.size()-1){
                        assignee = taskAssigneeList.get(i+1);
                        // 下一个节点没设置代办人
                        if(CollectionUtils.isEmpty(assignee.getUserList())){
                            continue;
                        }
                        userName = "";
                        for (int j = 0; j < assignee.getUserList().size(); j++) {
                            FlowUserVo userVo = assignee.getUserList().get(j);
                            if(j != assignee.getUserList().size() - 1){
                                userName += userVo.getName()+",";
                            }else{
                                userName += userVo.getName()+"";
                            }
                        }
                        wxFlowRecord = new WxFlowRecord();
                        wxFlowRecord.setUserName(userName.trim());
                        wxFlowRecord.setStatus(EnumFlowRecordStatus.ASSIGNEE.getCode());
                        wxFlowRecord.setTaskKey(UUID.randomUUID().toString());
                        wxFlowRecord.setTaskType(assignee.getType());
                        resultList.add(0,wxFlowRecord);
                        break;
                    }
                }else{
                    continue;
                }
            }
        }
        // 只展示最后一次发起，设置最后一个发起节点
        if(CollectionUtils.isNotEmpty(resultList)){
            for (int i = 0; i < resultList.size() ; i++) {
                if(resultList.get(i).getStatus() == 1){
                    resultList.get(i).setIsLastStart(1);
                    resultList = resultList.subList(0,i+1);
                    break;
                }
            }
        }

        // 合并会签节点展示
        Map<String,WxFlowRecord> map = new LinkedHashMap<>();
        for (WxFlowRecord r:resultList) {
            if(r.getTaskKey() == null)
                r.setTaskKey(r.getTaskName());
            WxFlowRecord mapR = map.get(r.getTaskKey());
            if(mapR != null) {
                //如果是会签代办，合并后去掉已经完成的
                if(EnumTaskType.AND.getCode().equals(mapR.getTaskType())
                        && EnumFlowRecordStatus.ASSIGNEE.getCode().equals(mapR.getStatus())
                        && r.getTaskKey().equals(mapR.getTaskKey())
                        ){
                    String newName = mapR.getUserName().replace(r.getUserName(),"");
                    mapR.setUserName(subUserName(newName));
                    continue;
                }
                mapR.setUserName(mapR.getUserName() + "," + r.getUserName());
            }else{
                map.put(r.getTaskKey(), r);
            }
        }

        List<WxFlowRecord> flowRecordList = new ArrayList<>();
        for (String key:map.keySet()) {
            flowRecordList.add(map.get(key));
        }

        return new ResultData(flowRecordList);
    }

    public String subUserName(String name){
        if(name.startsWith(",")){
            return name.substring(1,name.length());
        }
        if(name.endsWith(",")){
            return name.substring(0,name.length()-1);
        }
        return name.replace(",,",",");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = {Exception.class})
    public ResultData apply(Map<String, String> params,Long userId,String userName,String tenantId) {
        String taskId = params.get("taskId");
        String processInstanceId = params.get("processInstanceId");
        String remark = params.get("remark");
        String taskName;
        String taskKey;

        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            return new ResultData(ErrorCode.FLOW_INST_NOT_EXIST.getCode(), "任务不存在");
        }
        taskName = task.getName();
        taskKey = task.getTaskDefinitionKey();
        Map<String,Object> mapInfo = taskService.getVariables(task.getId());
        Long businessId = Long.parseLong(mapInfo.get("businessId").toString());
        Integer flowType = (Integer)mapInfo.get("flowType");
        List<Map<String,Object>> variables = (List)mapInfo.get("variables");
        Date startDate = (Date)mapInfo.get("startDate");
        taskService.complete(taskId);

        //保存wx_flow_record表审批记录
        WxFlowRecord wxFlowRecord = new WxFlowRecord();
        wxFlowRecord.setTaskId(taskId);
        wxFlowRecord.setProcessInstanceId(processInstanceId);
        wxFlowRecord.setRemark(remark);
        wxFlowRecord.setUserId(userId);
        wxFlowRecord.setStatus(EnumFlowRecordStatus.APPLY.getCode());
        wxFlowRecord.setBusinessId(businessId);
        wxFlowRecord.setBusinessType(flowType);
        wxFlowRecord.setUserName(userName);
        wxFlowRecord.setTaskName(taskName);
        wxFlowRecord.setTaskKey(taskKey);
        wxFlowRecord.setVariables(variablesToJson(variables));
        wxFlowRecord.setStartDate(startDate);
        wxFlowRecordService.saveOrUpdate(wxFlowRecord);

        // 判断流程是否结束，并发送短信通知
        boolean end = isEndAndSendMsg(mapInfo,taskKey,processInstanceId,tenantId,userName);

        //修改记录表当前状态
        if(end){
            wxFlowRecordMapper.updateCurrStatus(new WxFlowRecord(processInstanceId,EnumRentContractAppStatus.FINISH.getCode()));
        }else{
            wxFlowRecordMapper.updateCurrStatus(new WxFlowRecord(processInstanceId,EnumRentContractAppStatus.APPLYING.getCode()));
        }
        return new ResultData();
    }

    /**
     * 判断流程是否结束，并发送短信通知
     * @param taskKey
     * @param processInstanceId
     * @param tenantId
     */
    public boolean isEndAndSendMsg(Map<String,Object> mapInfo,String taskKey,String processInstanceId,String tenantId,String userName){
        // 发送短信
        Map<String,String> msgReplaceMap;
        WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode();
        wxMsgValidationcode.setTenantId(tenantId);
        Map<String,Object> userMap = (Map<String,Object>)mapInfo.get("starter");
        Long businessId = Long.parseLong(mapInfo.get("businessId").toString());
        String email = (String)userMap.get("email");
        List<Map<String,Object>> variables = (List)mapInfo.get("variables");
        Integer flowType = (Integer)mapInfo.get("flowType");

        // 判断下个节点是否有设置审批人，没有，直接通过,有，发短信通知
        if(!isEnded(processInstanceId)){
            boolean hasAssignee;
            if(flowType.intValue() <= EnumFlowKey.END_CONTRACT.getCode().intValue()) {
                //老数据
                List<Map<String, String>> taskAssigneeList = (List) mapInfo.get("taskAssignee");
                hasAssignee = hasAssignee(taskAssigneeList,taskKey,processInstanceId);
            }else{
                WxFlowModel flowModel = (WxFlowModel)JsonUtil.readValue((String)mapInfo.get("taskAssignee"),WxFlowModel.class);
                List<UserTaskVo> taskAssigneeList = flowModel.getLists();
                hasAssignee = hasAssigneeForNew(taskAssigneeList,taskKey,processInstanceId);
            }

            if(hasAssignee){
                // 给代办人发送通知短信
                String assignee = "";
                List<MallUserInfo> mallUserInfoList = getUserByProcessInstanceId(processInstanceId);
                for (int i = 0; i < mallUserInfoList.size(); i++) {
                    MallUserInfo mallUserInfo = mallUserInfoList.get(i);
                    sendAssigneeMsgAndEmail(tenantId, mallUserInfo.getPhone(), mallUserInfo.getEmail(), userName, businessId, flowType, variables);
                    if(i == mallUserInfoList.size()-1){
                        assignee += mallUserInfo.getName();
                    }else{
                        assignee += mallUserInfo.getName() +",";
                    }
                }
                // 给发起人发送短信
                msgReplaceMap = new HashedMap();
                msgReplaceMap.put("userName",userName);
                msgReplaceMap.put("page",Constant.adminPage);
                msgReplaceMap.put("contract", (String)getVariableByKey(variables,"contractNumber"));
                msgReplaceMap.put("toUserName",assignee);

                WxMsgRecord wxMsgRecord = new WxMsgRecord();
                wxMsgRecord.setMsgType(EnumMsgRecordType.SMS.getCode());
                wxMsgRecord.setModelType(EnumMsgModel.FLOW_APPLY_NODIFY.getCode());
                wxMsgRecord.setReceiver(userMap!=null?(String)userMap.get("phone"):"");
                wxMsgRecord.setTenantId(tenantId);
                if(isContract(flowType)){
                    msgReplaceMap.put("bustype","合同");
                }else if(isBill(flowType)){
                    msgReplaceMap.put("bustype","账单");
                    msgReplaceMap.put("contract", businessId.toString());
                }else if(isCoupon(flowType)){
                    wxMsgRecord.setModelType(EnumMsgModel.FLOW_C_APPLY_NODIFY.getCode());
                    WxCoupon wxCoupon = this.wxCouponMapper.selectById(businessId);
                    msgReplaceMap.put("type",EnumCouponType.getEnum(wxCoupon.getType()).getMessage());
                    msgReplaceMap.put("name",wxCoupon.getTitle());
                }else if(isSettle(flowType)){
                    msgReplaceMap.put("bustype","结算单");
                    msgReplaceMap.put("contract", (String) getVariableByKey(variables, "settleNumber"));
                }
                wxMsgRecord.setDynamicContentMap(msgReplaceMap);
                mqBaseProducer.sendMessage(wxMsgRecord, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode());

                //发邮件
                if(StringUtils.isNotBlank(email)){
                    MailMsg mailMsg = new MailMsg();
                    mailMsg.setSubject("审批通知");
                    mailMsg.setHtml(true);
                    mailMsg.setMsgType(EnumMsgRecordType.EMAIL.getCode());
                    mailMsg.setModelType(EnumMailMsgModel.MAIL_APPLY_NODIFY.getCode());
                    mailMsg.setModelId(EnumMsgModelId.MAIL_MSG_FLOW.getCode());
                    mailMsg.setTo(new String[]{email});
                    mailMsg.setTenantId(tenantId);
                    if(isContract(flowType)){
                        msgReplaceMap.put("bustype","合同");
                    }else if(isBill(flowType)){
                        msgReplaceMap.put("bustype","账单");
                        msgReplaceMap.put("contract", businessId.toString());
                    }else if(isCoupon(flowType)){
                        mailMsg.setModelType(EnumMailMsgModel.MAIL_C_APPLY_NODIFY.getCode());
                        WxCoupon wxCoupon = this.wxCouponMapper.selectById(businessId);
                        msgReplaceMap.put("type",EnumCouponType.getEnum(wxCoupon.getType()).getMessage());
                        msgReplaceMap.put("name",wxCoupon.getTitle());
                    }else if(isSettle(flowType)){
                        msgReplaceMap.put("bustype","结算单");
                        msgReplaceMap.put("contract", (String) getVariableByKey(variables, "settleNumber"));
                    }
                    mailMsg.setDynamicContentMap(msgReplaceMap);
                    mqBaseProducer.sendMessage(mailMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode());
                }else{
                    logger.info("邮件地址为空，不发送审批通知邮件");
                }
                return false;
            }else{
                //继续递归判断
                return isEndAndSendMsg(mapInfo,taskKey,processInstanceId,tenantId,userName);
            }
        }else{
            updateBusinessStatus(mapInfo,EnumRentContractAppStatus.FINISH.getCode());

            // 给发起人发送审批通过消息
            msgReplaceMap = new HashedMap();
            msgReplaceMap.put("contract",(String)getVariableByKey(variables,"contractNumber"));
            msgReplaceMap.put("page",Constant.adminPage);

            WxMsgRecord wxMsgRecord = new WxMsgRecord();
            wxMsgRecord.setMsgType(EnumMsgRecordType.SMS.getCode());
            wxMsgRecord.setModelType(EnumMsgModel.FLOW_PASS_NODIFY.getCode());
            wxMsgRecord.setReceiver(userMap!=null?(String)userMap.get("phone"):"");
            wxMsgRecord.setTenantId(tenantId);
            if(isContract(flowType)){
                msgReplaceMap.put("bustype","合同");
            }else if(isBill(flowType)){
                msgReplaceMap.put("bustype","账单");
                msgReplaceMap.put("contract", businessId.toString());
            }else if(isCoupon(flowType)){
                wxMsgRecord.setModelType(EnumMsgModel.FLOW_C_PASS_NODIFY.getCode());
                WxCoupon wxCoupon = this.wxCouponMapper.selectById(businessId);
                msgReplaceMap.put("type",EnumCouponType.getEnum(wxCoupon.getType()).getMessage());
                msgReplaceMap.put("name",wxCoupon.getTitle());
            }else if(isSettle(flowType)){
                msgReplaceMap.put("bustype","结算单");
                msgReplaceMap.put("contract", (String) getVariableByKey(variables, "settleNumber"));
            }
            wxMsgRecord.setDynamicContentMap(msgReplaceMap);
            mqBaseProducer.sendMessage(wxMsgRecord, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode());

            //发邮件
            if(StringUtils.isNotBlank(email)){
                MailMsg mailMsg = new MailMsg();
                mailMsg.setSubject("审批通过通知");
                mailMsg.setHtml(true);
                mailMsg.setMsgType(EnumMsgRecordType.EMAIL.getCode());
                mailMsg.setModelType(EnumMailMsgModel.MAIL_PASS_NODIFY.getCode());
                mailMsg.setModelId(EnumMsgModelId.MAIL_MSG_FLOW.getCode());
                mailMsg.setTo(new String[]{email});
                mailMsg.setTenantId(tenantId);
                if(isContract(flowType)){
                    msgReplaceMap.put("bustype","合同");
                }else if(isBill(flowType)){
                    msgReplaceMap.put("bustype","账单");
                    msgReplaceMap.put("contract", businessId.toString());
                }else if(isCoupon(flowType)){
                    mailMsg.setModelType(EnumMailMsgModel.MAIL_C_PASS_NODIFY.getCode());
                    WxCoupon wxCoupon = this.wxCouponMapper.selectById(businessId);
                    msgReplaceMap.put("type",EnumCouponType.getEnum(wxCoupon.getType()).getMessage());
                    msgReplaceMap.put("name",wxCoupon.getTitle());
                }else if(isSettle(flowType)){
                    msgReplaceMap.put("bustype","结算单");
                    msgReplaceMap.put("contract", (String) getVariableByKey(variables, "settleNumber"));
                }
                mailMsg.setDynamicContentMap(msgReplaceMap);
                mqBaseProducer.sendMessage(mailMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode());
            }else{
                logger.info("邮件地址为空，不发送通过邮件");
            }
            return true;
        }
    }

    /**
     * 判断下个节点是否有设置审批人，没有，直接通过
     * @param
     * @param taskKey
     * @param processInstanceId
     */
    public boolean hasAssigneeForNew(List<UserTaskVo> taskAssigneeList,String taskKey,String processInstanceId){
        boolean has = true;
        for (int i = 0; i < taskAssigneeList.size(); i++) {
            UserTaskVo taskAssignee = taskAssigneeList.get(i);
            if(taskAssignee.getKey().equals(taskKey)){
                if(i != taskAssigneeList.size() -1){
                    UserTaskVo nextTaskAssignee = taskAssigneeList.get(i+1);
                    if(CollectionUtils.isEmpty(nextTaskAssignee.getUserList())){
                        List<Task> task = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
                        taskService.complete(task.get(0).getId());
                        has = false;
                        break;
                    }
                }
            }
        }
        return has;
    }

    public boolean hasAssignee(List<Map<String,String>> taskAssigneeList,String taskKey,String processInstanceId){
        boolean has = true;
        for (int i = 0; i < taskAssigneeList.size(); i++) {
            Map<String,String> taskAssignee = taskAssigneeList.get(i);
            if(taskAssignee.get("taskKey").equals(taskKey)){
                if(i != taskAssigneeList.size() -1){
                    Map<String,String> nextTaskAssignee = taskAssigneeList.get(i+1);
                    if(StringUtils.isBlank(nextTaskAssignee.get("assignee"))){
                        List<Task> task = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
                        taskService.complete(task.get(0).getId());
                        has = false;
                        break;
                    }
                }
            }
        }
        return has;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = {Exception.class})
    public ResultData reject(Map<String, Object> params,Long userId,String userName,String userPhone,String tenantId) {
        String processInstanceId = (String)params.get("processInstanceId");
        String remark = (String)params.get("remark");

        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        if (CollectionUtils.isEmpty(taskList)) {
            return new ResultData(ErrorCode.FLOW_INST_NOT_EXIST.getCode(), "任务不存在");
        }
        Map<String,Object> mapInfo = taskService.getVariables(taskList.get(0).getId());
        Long businessId = Long.parseLong(mapInfo.get("businessId").toString());
        Integer flowType = (Integer)mapInfo.get("flowType");
        Map<String,Object> userMap = (Map<String,Object>)mapInfo.get("starter");
        String email = (String) userMap.get("email");
        List<Map<String,Object>> variables = (List)mapInfo.get("variables");
        Date startDate = (Date)mapInfo.get("startDate");

        String taskName;
        String taskKey;

        taskName = taskList.get(0).getName();
        taskKey = taskList.get(0).getTaskDefinitionKey();

        runtimeService.deleteProcessInstance(processInstanceId, "驳回");

        // 修改合同审核状态为驳回
        params.putAll(mapInfo);
        updateBusinessStatus(params,EnumRentContractAppStatus.REJECT.getCode());

        //保存wx_flow_record表审批记录
        WxFlowRecord wxFlowRecord = new WxFlowRecord();
        wxFlowRecord.setBusinessId(businessId);
        wxFlowRecord.setTaskId(taskList.get(0).getId());
        wxFlowRecord.setProcessInstanceId(processInstanceId);
        wxFlowRecord.setRemark(remark);
        wxFlowRecord.setUserId(userId);
        wxFlowRecord.setStatus(EnumFlowRecordStatus.REJECT.getCode());
        wxFlowRecord.setBusinessType(flowType);
        wxFlowRecord.setUserName(userName);
        wxFlowRecord.setTaskKey(taskKey);
        wxFlowRecord.setTaskName(taskName);
        wxFlowRecord.setVariables(variablesToJson(variables));
        wxFlowRecord.setStartDate(startDate);
        wxFlowRecordService.saveOrUpdate(wxFlowRecord);
        //修改记录表当前状态
        wxFlowRecordMapper.updateCurrStatus(new WxFlowRecord(processInstanceId,EnumRentContractAppStatus.REJECT.getCode()));

        //给发起人发送驳回消息
        Map<String, String> msgReplaceMap = new HashedMap();
        String phone = userMap!=null?(String)userMap.get("phone"):"";
        if(phone.length() > 0) {
            msgReplaceMap.put("contract", (String) getVariableByKey(variables, "contractNumber"));
            msgReplaceMap.put("page", Constant.adminPage);
            WxMsgRecord wxMsgRecord = new WxMsgRecord();
            wxMsgRecord.setMsgType(EnumMsgRecordType.SMS.getCode());
            wxMsgRecord.setModelType(EnumMsgModel.FLOW_REJECT_NODIFY.getCode());
            wxMsgRecord.setReceiver(userMap != null ? (String) userMap.get("phone") : "");
            wxMsgRecord.setTenantId(tenantId);
            if (isContract(flowType)) {
                msgReplaceMap.put("bustype", "合同");
            } else if (isBill(flowType)) {
                msgReplaceMap.put("bustype", "账单");
                msgReplaceMap.put("contract", businessId.toString());
            } else if (isCoupon(flowType)) {
                wxMsgRecord.setModelType(EnumMsgModel.FLOW_C_REJECT_NODIFY.getCode());
                WxCoupon wxCoupon = this.wxCouponMapper.selectById(businessId);
                msgReplaceMap.put("type",EnumCouponType.getEnum(wxCoupon.getType()).getMessage());
                msgReplaceMap.put("name",wxCoupon.getTitle());
            }else if (isSettle(flowType)) {
                msgReplaceMap.put("bustype", "结算单");
                msgReplaceMap.put("contract", (String) getVariableByKey(variables, "settleNumber"));
            }
            wxMsgRecord.setDynamicContentMap(msgReplaceMap);
            mqBaseProducer.sendMessage(wxMsgRecord, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode());
        }

        //发送邮件
        if(StringUtils.isNotBlank(email)) {
            msgReplaceMap = new HashedMap();
            msgReplaceMap.put("contract",(String)getVariableByKey(variables,"contractNumber"));
            msgReplaceMap.put("page", Constant.adminPage);
            msgReplaceMap.put("name",userName);
            msgReplaceMap.put("remark",remark==null?"":remark);
            msgReplaceMap.put("linkName",userName);
            msgReplaceMap.put("linkPhone",userPhone==null?"":userPhone);
            MailMsg mailMsg = new MailMsg();
            mailMsg.setSubject("驳回通知");
            mailMsg.setHtml(true);
            mailMsg.setMsgType(EnumMsgRecordType.EMAIL.getCode());
            mailMsg.setModelType(EnumMailMsgModel.MAIL_REJECT_NODIFY.getCode());
            mailMsg.setModelId(EnumMsgModelId.MAIL_MSG_FLOW.getCode());
            mailMsg.setTo(new String[]{email});
            mailMsg.setTenantId(tenantId);
            if(isContract(flowType)){
                msgReplaceMap.put("bustype","合同");
            }else if(isBill(flowType)){
                msgReplaceMap.put("bustype","账单");
                msgReplaceMap.put("contract", businessId.toString());
            }else if(isCoupon(flowType)){
                mailMsg.setModelType(EnumMailMsgModel.MAIL_C_REJECT_NODIFY.getCode());
                WxCoupon wxCoupon = this.wxCouponMapper.selectById(businessId);
                msgReplaceMap.put("type",EnumCouponType.getEnum(wxCoupon.getType()).getMessage());
                msgReplaceMap.put("name",wxCoupon.getTitle());
            }else if(isSettle(flowType)){
                msgReplaceMap.put("bustype","结算单");
                msgReplaceMap.put("contract", (String) getVariableByKey(variables, "settleNumber"));
            }
            mailMsg.setDynamicContentMap(msgReplaceMap);
            mqBaseProducer.sendMessage(mailMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode());
        }else{
            logger.info("邮件地址为空，不发送驳回邮件");
        }
        return new ResultData();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = {Exception.class})
    public ResultData setBack(Map<String, Object> params,Long userId,String userName) {
        String processInstanceId = (String)params.get("processInstanceId");
        String remark = (String)params.get("remark");

        List<Task> task = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        Map<String,Object> mapInfo = taskService.getVariables(task.get(0).getId());
        Long businessId = Long.parseLong(mapInfo.get("businessId").toString());
        Integer flowType = (Integer)mapInfo.get("flowType");
        List<Map<String,Object>> variables = (List)mapInfo.get("variables");
        Date startDate = (Date)mapInfo.get("startDate");

        String taskName;
        String taskKey;
        if (task == null) {
            return new ResultData(ErrorCode.FLOW_INST_NOT_EXIST.getCode(), "任务不存在");
        }
        taskName = task.get(0).getName();
        taskKey = task.get(0).getTaskDefinitionKey();

        runtimeService.deleteProcessInstance(processInstanceId, "撤回");

        // 修改合同审核状态为撤回
        params.putAll(mapInfo);
        updateBusinessStatus(params,EnumRentContractAppStatus.SETBACK.getCode());

        //保存wx_flow_record表审批记录
        WxFlowRecord wxFlowRecord = new WxFlowRecord();
        wxFlowRecord.setBusinessId(businessId);
        wxFlowRecord.setTaskId(task.get(0).getId());
        wxFlowRecord.setProcessInstanceId(processInstanceId);
        wxFlowRecord.setRemark(remark);
        wxFlowRecord.setUserId(userId);
        wxFlowRecord.setStatus(EnumFlowRecordStatus.SETBACK.getCode());
        wxFlowRecord.setBusinessType(flowType);
        wxFlowRecord.setUserName(userName);
        wxFlowRecord.setTaskKey(taskKey);
        wxFlowRecord.setTaskName(taskName);
        wxFlowRecord.setVariables(variablesToJson(variables));
        wxFlowRecord.setStartDate(startDate);
        wxFlowRecordService.saveOrUpdate(wxFlowRecord);
        //修改记录表当前状态
        wxFlowRecordMapper.updateCurrStatus(new WxFlowRecord(processInstanceId,EnumRentContractAppStatus.SETBACK.getCode()));
        return new ResultData();
    }

    /**
     * 判断流程是否结束
     * @param processInstanceId
     * @return
     */
    public boolean isEnded(String processInstanceId) {
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if(processInstance == null){
            return true;
        }
        return processInstance.isEnded();
    }

    /**
     * 根据流程实例id获取当前节点的代办人信息
     * @return
     */
    public List<MallUserInfo> getUserByProcessInstanceId(String processInstanceId){
        List<MallUserInfo> result = new ArrayList<>();
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).orderByTaskCreateTime().desc().list();
        if(CollectionUtils.isNotEmpty(tasks)){
            for (Task task:tasks) {
                List<String> userIdList = getTaskCandidateUserId(task.getId());
                for (String userId:userIdList) {
                    MallUserInfo mallUserInfo = this.mallUserInfoService.getById(Long.parseLong(userId));
                    if(mallUserInfo != null) {
                        mallUserInfo.setPassword(null);
                        mallUserInfo.setBopenId(null);
                        if (StringUtils.isNotBlank(mallUserInfo.getWebOpenId())) {
                            mallUserInfo.setWebOpenId("保密");
                        }
                        result.add(mallUserInfo);
                    }
                }
            }
        }
        return result;
    }

    /**
     * 获得任务中的候选人
     * @param taskId
     * @return
     */
    private List<String> getTaskCandidateUserId(String taskId) {
        List<String> userIdList = new ArrayList<>();
        List identityLinkList = taskService.getIdentityLinksForTask(taskId);
        if (identityLinkList != null && identityLinkList.size() > 0) {
            for (Iterator iterator = identityLinkList.iterator(); iterator.hasNext();) {
                IdentityLink identityLink = (IdentityLink) iterator.next();
                if (identityLink.getUserId() != null) {
                    userIdList.add(identityLink.getUserId());
                }
//                if (identityLink.getGroupId() != null) {
//                    // 根据组获得对应人员
//                    List userList = identityService.createUserQuery()
//                            .memberOfGroup(identityLink.getGroupId()).list();
//                    if (userList != null && userList.size() > 0)
//                        users.addAll(userList);
//                }
            }
        }
        return userIdList;
    }

    @Override
    public PageInfo<WxFlowRecord> listAsPage(WxFlowRecord record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxFlowRecordMapper.findList(record));
    }

    @Override
    public PageInfo<WxFlowRecord> myHandelList(WxFlowRecord record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxFlowRecordMapper.myHandelList(record));
    }


    public static Object getVariableByKey(List<Map<String,Object>> variables,String key){
        if(variables == null) return null;
        for (Map<String,Object> map:variables) {
            if(map.get("key").equals(key)){
                return map.get("value");
            }
        }
        return null;
    }

    @Override
    public ResultData createModel(WxFlowModel wxFlowModel) {
        Process process = new Process();
        process.setId(getRandomReqNo());
        List<SequenceFlow> flowList = createFlow(wxFlowModel.getLists().size());

        for (int i = 0; i < wxFlowModel.getLists().size(); i++) {
            UserTaskVo taskVo = wxFlowModel.getLists().get(i);
            taskVo.setKey("userTask" + (i + 1));
            if (i == 0) {
                StartEvent start = new StartEvent();
                start.setId("start");
                start.setName("开始节点");
                start.setOutgoingFlows(Arrays.asList(flowList.get(0)));
                process.addFlowElement(start);
                process.addFlowElement(flowList.get(0));
            }

            UserTask userTask = new UserTask();
            userTask.setName("节点" + (i + 1));
            userTask.setId("userTask" + (i + 1));
            List<String> userIdList = new ArrayList<>();
            for (FlowUserVo userVo:taskVo.getUserList()) {
                userIdList.add(userVo.getId() + "");
            }

            if(EnumTaskType.NORMAL.getCode().equals(taskVo.getType()) || EnumTaskType.OR.getCode().equals(taskVo.getType())){
                userTask.setCandidateUsers(userIdList);
            }else if (EnumTaskType.AND.getCode().equals(taskVo.getType())) {
                userTask.setAssignee("${assignee}");
                MultiInstanceLoopCharacteristics mi = new MultiInstanceLoopCharacteristics();
                mi.setLoopCardinality(userIdList.size()+"");
                mi.setInputDataItem("${"+userTask.getId()+"_signAssignee}");
                mi.setElementVariable("assignee");
                userTask.setLoopCharacteristics(mi);
            }

            userTask.setIncomingFlows(Arrays.asList(flowList.get(i)));
            userTask.setOutgoingFlows(Arrays.asList(flowList.get(i + 1)));
            process.addFlowElement(userTask);
            process.addFlowElement(flowList.get(i + 1));

            if (i == wxFlowModel.getLists().size() - 1) {
                EndEvent endEvent = new EndEvent();
                endEvent.setId("end");
                endEvent.setName("结束节点");
                endEvent.setIncomingFlows(Arrays.asList(flowList.get(i + 1)));
                process.addFlowElement(endEvent);
            }
        }

        //部署
        BpmnModel bpmnModel = new BpmnModel();
        bpmnModel.addProcess(process);
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment().addBpmnModel(process.getId()+".bpmn20.xml", bpmnModel);
        deploymentBuilder.deploy();

        wxFlowModel.setFlowId(process.getId());
        wxFlowModel.setFlow(JsonUtil.obj2Json(wxFlowModel));
        if(wxFlowModel.getId() == null) {
            final IdWorker idWorker = IdWorker.get();
            wxFlowModel.setId(idWorker.nextId());
            wxFlowModelMapper.insert(wxFlowModel);
        }else{
            wxFlowModel.setUpdateDate(new Date());
            wxFlowModelMapper.updateById(wxFlowModel);
        }
        return new ResultData();
    }

    /**
     * 创建连接线
     * @param size
     * @return
     */
    public List<SequenceFlow> createFlow(int size){
        List<SequenceFlow> result = new ArrayList<>();
        for (int i = 0; i < size+1; i++) {
            SequenceFlow sequenceFlow = new SequenceFlow();
            sequenceFlow.setId("sf"+i);
            if(i==0){
                sequenceFlow.setName("开始");
                sequenceFlow.setSourceRef("start");
                sequenceFlow.setTargetRef("userTask"+(i+1));
            }else if(i == size){
                sequenceFlow.setName("结束");
                sequenceFlow.setSourceRef("userTask"+i);
                sequenceFlow.setTargetRef("end");
            }else{
                sequenceFlow.setName("sf"+i);
                sequenceFlow.setSourceRef("userTask"+i);
                sequenceFlow.setTargetRef("userTask"+(i+1));
            }
            result.add(sequenceFlow);
        }
        return result;
    }

    /**
     * 获取随机的流水号(10位)
     * @return
     */
    public static String getRandomReqNo() {
        int length=10;
        String base = "abcdefghijklmnopqrstuvwxyz";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    @Override
    public PageInfo<WxFlowModel> modelList(WxFlowModel wxFlowModel,Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxFlowModelMapper.findList(wxFlowModel));
    }

    @Override
    public ResultData findModelById(WxFlowModel wxFlowModel) {
        return new ResultData(wxFlowModelMapper.selectById(wxFlowModel.getId()));
    }

    @Override
    public ResultData delModel(WxFlowModel wxFlowModel) {
        WxFlowConfig query = new WxFlowConfig();
        query.setTenantId(wxFlowModel.getTenantId());
        query.setModelId(wxFlowModel.getId());
        if(CollectionUtils.isNotEmpty(wxFlowConfigMapper.findList(query))){
            return new ResultData(Result.ERROR, "该流程模板在使用中，须先停用正在\n" +
                    "使用该模板的审批类型。");
        }
        wxFlowModelMapper.deleteById(wxFlowModel.getId());
        return new ResultData();
    }

    @Override
    public PageInfo<WxFlowConfig> configList(WxFlowConfig wxFlowConfig, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxFlowConfigMapper.findList(wxFlowConfig));
    }

    @Override
    public ResultData updateConfig(WxFlowConfig wxFlowConfig) {
        wxFlowConfig.setUpdateDate(new Date());
        wxFlowConfigMapper.updateById(wxFlowConfig);
        return new ResultData();
    }

    @Override
    public List<WxFlowModel> getModelBybusiness(WxFlowModel wxFlowModel) {
        return wxFlowModelMapper.getModelBybusiness(wxFlowModel);
    }

    public static void main(String[] args) {
        new Thread(() -> System.out.println(1 + "hello world")).start();

    }
}
