package com.huigou.topsun.sap.exceptionReport.application.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.huigou.cache.DictUtil;
import com.huigou.cache.SystemCache;
import com.huigou.context.Operator;
import com.huigou.context.OrgUnit;
import com.huigou.context.ThreadLocalUtil;
import com.huigou.data.domain.model.CommonDomainConstants;
import com.huigou.data.query.model.QueryDescriptor;
import com.huigou.data.query.model.QueryModel;
import com.huigou.topsun.base.bsnMessage.appliction.MannualStartWorkApplication;
import com.huigou.topsun.common.CommonUtils;
import com.huigou.topsun.sap.common.HttpClient;
import com.huigou.topsun.sap.common.application.SapMutualEpLogApplication;
import com.huigou.topsun.sap.common.domain.SapResult;
import com.huigou.topsun.sap.exceptionReport.application.*;
import com.huigou.topsun.sap.exceptionReport.domain.*;
import com.huigou.topsun.sap.exceptionReport.domain.query.ExceptionReportQueryRequest;
import com.huigou.topsun.sap.exceptionReport.domain.vo.ExceptionReportPayableVo;
import com.huigou.topsun.sap.exceptionReport.domain.vo.PurchaseOrderItemVo;
import com.huigou.topsun.sap.exceptionReport.domain.vo.PurchaseOrderVo;

import com.huigou.topsun.sap.exceptionReport.repository.ExceptionReportRepository;
import com.huigou.topsun.sap.exceptionReport.repository.ExceptionReportResponsibleRepository;

import com.huigou.uasp.bmp.common.BizBillStatus;
import com.huigou.uasp.bmp.fn.CodeGenerator;
import com.huigou.uasp.bmp.operator.OperatorApplication;

import com.huigou.uasp.bmp.opm.domain.model.org.Org;
import com.huigou.uasp.bpm.FlowBroker;
import com.huigou.uasp.bpm.ProcessAction;
import com.huigou.uasp.bpm.ProcessStartModel;
import com.huigou.uasp.bpm.engine.application.WorkflowApplication;
import com.huigou.uasp.bpm.engine.domain.model.ProcUnitHandler;
import com.huigou.uasp.bpm.engine.domain.model.RuntimeTaskExtension;
import com.huigou.uasp.bpm.engine.domain.model.TaskExtension;
import com.huigou.uasp.bpm.engine.repository.ProcUnitHandlerRepository;
import com.huigou.util.*;
import freemarker.template.Template;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther: xin.lu
 * @Date: 2024/03/20/19:36
 * @Description:
 */
@Service("exceptionReportApplication")
public class ExceptionReportApplicationImpl extends FlowBroker implements ExceptionReportApplication {
    @Autowired
    private ExceptionReportRepository exceptionReportRepository;

    @Autowired
    private ExceptionReportItemApplication exceptionReportItemApplication;

    @Autowired
    private ProcUnitHandlerRepository procUnitHandlerRepository;
    @Autowired
    private ExceptionReportDutyPersonApplication exceptionReportDutyPersonApplication;
    @Autowired
    private ExceptionReportPayableApplication exceptionReportPayableApplication;

    @Autowired
    private ExceptionReportCashApplication exceptionReportCashApplication;

    @Autowired
    private ExceptionReportGoodsApplication exceptionReportGoodsApplication;
    @Autowired
    private HttpClient httpClient;
    @Autowired
    private SapMutualEpLogApplication sapMutualEpLogApplication;
    @Autowired
    private FreeMarkerConfigurer freemarkerConfigurer;
    @Resource
    private OperatorApplication operatorApplication;
    @Autowired
    private MannualStartWorkApplication mannualStartWorkApplication;
    @Autowired
    private WorkflowApplication workflowApplication;
    @Autowired
    private ExceptionReportResponsibleRepository exceptionReportResponsibleRepository;

    @Autowired
    private TaskExecutor asyncWriteExecutor;

    private final String respNodeCode="responsibleAudit"; //责任人审批的节点名称

    @Override
    public Map<String, Object> slicedExceptionReportList(ExceptionReportQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "exceptionReport");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);

//        if (queryRequest.getStartDate() != null&&!"".equals(queryRequest.getStartDate())) {
//            queryModel.addCriteria(" and t.report_date >=:startDate");
//            queryModel.putParam("startDate", queryRequest.getStartDate());
//        }
//        if (queryRequest.getEndDate() != null&&!"".equals(queryRequest.getEndDate())) {
//            queryModel.addCriteria(" and t.report_date <=:endDate");
//            queryModel.putParam("endDate", queryRequest.getEndDate());
//        }
        queryModel.putDictionary("status", BizBillStatus.getMap());
        queryModel.putDictionary("needImproveReport",DictUtil.getDictionary("yesorno"));
        queryModel.putDictionary("needGuarantee",DictUtil.getDictionary("yesorno"));
        return this.sqlExecutorDao.executeSlicedQuery(queryModel);
    }

    @Override
    public Map<String, Object> slicedExceptionReportExportList(ExceptionReportQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "exceptionReportExport");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
        queryModel.putDictionary("status", BizBillStatus.getMap());
        return this.sqlExecutorDao.executeSlicedQuery(queryModel);
    }

    @Override
    public ExceptionReport findById(String id) {
        return exceptionReportRepository.findOne(id);
    }

    @Override
    public void deleteById(String id) {
        exceptionReportRepository.delete(id);
    }

    @Override
    public ExceptionReport saveExceptionReport(ExceptionReport exceptionReport) {
        return exceptionReportRepository.save(exceptionReport);
    }

    @Transactional
    void updateStatus(String bizId, BizBillStatus status) {
        Assert.hasText(bizId, CommonDomainConstants.ID_NOT_BLANK);
        this.commonDomainService.updateStatus(ExceptionReport.class, bizId, status.getId());
    }

    /**
     * 保存业务数据
     */
    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        ExceptionReport exceptionReport = this.getBizEntity(ExceptionReport.class);
        List<ExceptionReportItem> exceptionReportItems = this.getBizEntities(ExceptionReportItem.class, "exceptionReportItems");
        List<ExceptionReportDutyPerson> exceptionReportDutyPersonList = this.getBizEntities(ExceptionReportDutyPerson.class, "personList");
        if (StringUtils.isBlank(exceptionReport.getDutyDept())){
            exceptionReport.setDutyDept("0");
        }
        //异常原因分类是供应商原材料问题
        if (!"supplier".equals(exceptionReport.getBillType())&&"1".equals(exceptionReport.getExceptionReasonType())){
            exceptionReport.setCustomerNo(exceptionReport.getCustomerNoPur());
            exceptionReport.setCustomerName(exceptionReport.getCustomerNamePur());
            exceptionReport.setCustomerOrderNo(exceptionReport.getCustomerOrderNoPur());
       }
       /* 采购的单据 根据加减签 去更改为责任人
        if (exceptionReport.getStatusId()==1&&("purchase".equals(exceptionReport.getBillType())||"outgoing".equals(exceptionReport.getBillType()))
          //&&!"auditDept".equals(exceptionReport.getHandleNodeId())  //不是审计部审批的
         //  &&StringUtils.isBlank(exceptionReport.getDutyDept())   //责任部门是空 最后的审批人就是责任人
         ){
           // String ds=exceptionReport.getHandleNodeId();       // 加减签的转为责任人
            Map<String, Object>  mapSigns=workflowApplication.queryCounterSignHandlers(exceptionReport.getId(),"Approve");

            List <Map<String,Object>>plist=(List)mapSigns.get("Rows");
           if (Integer.parseInt(mapSigns.get("Total").toString())>0) {
               Map map = plist.get(Integer.parseInt(mapSigns.get("Total").toString()) - 1);
//             if (StringUtils.isBlank(exceptionReport.getDutyDept())  //没有责任人 或者责任人与审批人不一致
//                ||!exceptionReport.getDutyDept().equals(map.get("handlerId").toString())
//             ) {
                   exceptionReport.setCheckOperator(map.get("handlerId").toString());
                   exceptionReport.setCheckOperatorName(map.get("handlerName").toString());
                   exceptionReport.setDutyDeptName(map.get("deptName").toString());
                   Org org = orgApplication.loadOrg(map.get("handlerId").toString());
                   exceptionReport.setDutyDept(org.getDeptId());
           }
        } */
        //
           SDO params = this.getBizAndApprovalData();
        if ("produce".equals(exceptionReport.getBillType())
          &&"advance".equals(params.getProperty("processAction"))  // 提交
        ) {
            Operator operator = ThreadLocalUtil.getOperator();
            if (StringUtil.isNotBlank(exceptionReport.getDutyDept())&&StringUtil.isBlank(exceptionReport.getCheckOperator())){
                throw new IllegalArgumentException("指定责任部门同时必须指定负责人！");
            }
            //当前操作人 不是责任人
            if (!exceptionReport.getCheckOperator().equals(operator.getPersonMemberId())) {
                saveResponsibleToApprover(params, exceptionReport);
            }
        }

        exceptionReport = this.saveExceptionReport(exceptionReport);

        if (CollectionUtil.isNotEmpty(exceptionReportItems)){
            this.exceptionReportItemApplication.saveExceptionReportItemList(exceptionReport.getId(),exceptionReport.getExceptionReasonType(), exceptionReportItems);
        }
        if (CollectionUtil.isNotEmpty(exceptionReportDutyPersonList)) {
            this.exceptionReportDutyPersonApplication.saveExceptionReportDutyPersonList(exceptionReport.getId(), exceptionReportDutyPersonList);
        }

        List<ExceptionReportPayable> exceptionReportPayableList = this.getBizEntities(ExceptionReportPayable.class, "handlePayable");
        List<ExceptionReportCash> exceptionReportCashList = this.getBizEntities(ExceptionReportCash.class, "handleCash");
        List<ExceptionReportGoods> exceptionReportGoodsList = this.getBizEntities(ExceptionReportGoods.class, "handleGoods");
        if ("supplier".equals(exceptionReport.getBillType())){ //供应商 默认类型
            exceptionReport.setExceptionType("out");
         //   exceptionReport.setExceptionReasonType("3");
        }

        if (("supplier".equals(exceptionReport.getBillType()))&&"pay".equals(exceptionReport.getDealWay())
           &&CollectionUtil.isEmpty(exceptionReportPayableList)
         ) {
            throw new IllegalArgumentException("扣除应付款必须填写一项！");
         }
        if (("supplier".equals(exceptionReport.getBillType()))&&"cash".equals(exceptionReport.getDealWay())
                &&CollectionUtil.isEmpty(exceptionReportCashList)
        ) {
            throw new IllegalArgumentException("现金或转账必须填写一项！");
        }
        if (("supplier".equals(exceptionReport.getBillType()))&&"goods".equals(exceptionReport.getDealWay())
                &&CollectionUtil.isEmpty(exceptionReportGoodsList)
        ) {
            throw new IllegalArgumentException("商品结算必须填写一项！");
        }
       if (CollectionUtil.isNotEmpty(exceptionReportPayableList)) {
            exceptionReportPayableApplication.saveExceptionReportPayableList(exceptionReport.getId(),exceptionReportPayableList);
       }
        if (CollectionUtil.isNotEmpty(exceptionReportCashList)) {
            exceptionReportCashApplication.saveExceptionReportCashList(exceptionReport.getId(),exceptionReportCashList);
        }
        if (CollectionUtil.isNotEmpty(exceptionReportGoodsList)) {
            exceptionReportGoodsApplication.saveExceptionReportGoodsList(exceptionReport.getId(),exceptionReportGoodsList);
        }
        return exceptionReport.getId();
    }
    @Override
    public String getResponsibleTimes(String id){
        String str="0";
        List<ExceptionReportResponsible> rslist = exceptionReportResponsibleRepository.findByExceptionReportId(id);
        if (!ObjectUtils.isEmpty(rslist)) {
            if (rslist.size() > 3) {
                str="1";
            }
        }
        return str;
    }

    private void saveResponsibleToApprover(SDO params,ExceptionReport exceptionReport){
        List <ExceptionReportResponsible>rslist=exceptionReportResponsibleRepository.findByExceptionReportId(exceptionReport.getId());
        if (!ObjectUtils.isEmpty(rslist)){
            ExceptionReportResponsible lastResponsible=rslist.get(rslist.size()-1);
            Operator operator = ThreadLocalUtil.getOperator();
            boolean  currOperatorIsResponse=false; //当前操作人是否是责任人
            for (ExceptionReportResponsible responsible:rslist) {
                if (responsible.getCheckOperator().equals(operator.getPersonMemberId())){
                    currOperatorIsResponse=true;
                    break;
                }
            }

            RuntimeTaskExtension runtimeTaskExtension = actApplication.loadRuntimeTaskExtension(params.getString("taskId"));
            ProcUnitHandler procUnitHandler = procUnitHandlerApplication.loadProcUnitHandler(runtimeTaskExtension.getProcUnitHandlerId());
            String nodeCode=procUnitHandler.getSubProcUnitId();
           // procUnitHandler.getApprovalRuleHandlerId();
           // select handler_kind_id from topsun_dev.wf_approvalrulehandler  where id='d30bb1717a1b11ef98170242ac110002'
            params.putProperty("subProcUnitId",nodeCode);
            //责任人审批阶段  更换责任人不能超过三次
            if (respNodeCode.equals(nodeCode)&&currOperatorIsResponse&&rslist.size()>=3&&!lastResponsible.getCheckOperator().equals(exceptionReport.getCheckOperator())){
                throw new RuntimeException("责任人的更换不能超过三次！");
            }
            boolean  currResponseExist=false; //当前操作部门是否已经被指定过
            for (int i=0;i<rslist.size()-1;i++) {
                if (rslist.get(i).getDutyDept().equals(exceptionReport.getDutyDept())){
                    currResponseExist=true;
                    break;
                }
            }
            if (respNodeCode.equals(nodeCode)&&currResponseExist){
                throw new RuntimeException("责任部门:"+exceptionReport.getDutyDeptName()+"已经被指定过！");
            }
            if (!lastResponsible.getCheckOperator().equals(exceptionReport.getCheckOperator())){
                saveResponsibles(params,exceptionReport);
            }
        } else {
            saveResponsibles(params,exceptionReport);
        }
    }

    private void saveResponsibles(SDO params,ExceptionReport exceptionReport){

        if (StringUtils.isNotBlank(exceptionReport.getDutyDept())){ //责任部门不为空
            //增加责任人的审批 params.getProperty("processAction")  advance
            saveHistoryCheckOperator(exceptionReport);
            if (respNodeCode.equals(params.getString("subProcUnitId"))) { //是责任人审批，才产生待办任务
               this.saveResponsibleApprover(params, exceptionReport);
            }
        }
    }

    private  void  saveHistoryCheckOperator(ExceptionReport exceptionReport){
        Operator operator = ThreadLocalUtil.getOperator();
        ExceptionReportResponsible exceptionReportResponsible = new ExceptionReportResponsible();
        exceptionReportResponsible.setExceptionReportId(exceptionReport.getId());
        exceptionReportResponsible.setBillCode(exceptionReport.getBillCode());
        exceptionReportResponsible.setDutyDept(exceptionReport.getDutyDept());
        exceptionReportResponsible.setDutyDeptName(exceptionReport.getDutyDeptName());
        exceptionReportResponsible.setCheckOperator(exceptionReport.getCheckOperator());
        exceptionReportResponsible.setCheckOperatorName(exceptionReport.getCheckOperatorName());
        exceptionReportResponsible.setCreateDate(new Date());
        exceptionReportResponsible.setCreatedId(operator.getPersonMemberId());
        exceptionReportResponsible.setCreatedName(operator.getPersonMemberName());

        exceptionReportResponsibleRepository.save(exceptionReportResponsible);
    }
    //责任人审批
    private void  saveResponsibleApprover(SDO params,ExceptionReport exceptionReport){
        String bizId = params.getString("bizId");
        String procUnitId = params.getString("procUnitId");// subProcUnitId
        String currentProcUnitHandlerId = params.getString("currentHandleId");
        Long version = params.getLong("hiProcUnitHandlerInstVersion");
        version=params.getLong("version");
        List<String> minusSignIds = params.getStringList("deleted");
        List<ProcUnitHandler> countersigns = params.getList("detailData", ProcUnitHandler.class);
        //是否存在
        long zs=procUnitHandlerRepository.countProcUnitHandlers(bizId,procUnitId,exceptionReport.getCheckOperator());

      //  if (!operator.getPersonMemberId().equals(exceptionReport.getCheckOperator())) {
        if (zs<1) {
            ProcUnitHandler procUnitHandler = new ProcUnitHandler();
            Org org = orgApplication.loadOrg(exceptionReport.getCheckOperator());
            procUnitHandler.setHandlerId(exceptionReport.getCheckOperator());
            procUnitHandler.setHandlerName(exceptionReport.getCheckOperatorName());
            procUnitHandler.setDeptId(exceptionReport.getDutyDept());
            procUnitHandler.setDeptName(exceptionReport.getDutyDeptName());
            procUnitHandler.setPositionId(org.getPositionId());
            procUnitHandler.setPositionName(org.getPositionName());
            procUnitHandler.setFullId(org.getFullId());
            procUnitHandler.setFullName(org.getFullName());
            procUnitHandler.setOrgId(org.getOrgId());
            procUnitHandler.setOrgName(org.getOrgName());
            procUnitHandler.setSubProcUnitName(exceptionReport.getDutyDeptName());
            procUnitHandler.setProcUnitId(procUnitId);
            procUnitHandler.setProcUnitName("品质异常报告审批");
            procUnitHandler.setBizId(bizId);
            procUnitHandler.setStatus(0);
            procUnitHandler.setSequence(1);
            procUnitHandler.setSubProcUnitId(params.getString("subProcUnitId")); //审批节点固定名称
            procUnitHandler.setBizCode(exceptionReport.getBillCode());
            procUnitHandler.setCooperationModelId(params.getProperty("currentHandleCooperationModelId") != null ? params.getProperty("currentHandleCooperationModelId").toString() : "chief");

            procUnitHandler.setGroupId(Integer.parseInt(params.getProperty("currentHandleGroupId").toString()) + 1);
            //System.out.print("isNew=========" + procUnitHandler.isNew());

            countersigns.add(procUnitHandler);
            workflowApplication.saveCounterSignHandlers(bizId, procUnitId, version, currentProcUnitHandlerId, minusSignIds, countersigns);
          }
        }
    /**
     * 获取流程参数
     */
    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        return ClassHelper.toMap(exceptionReportRepository.findOne(bizId));
    }
    @Override
    public void onCreate(DelegateTask delegateTask) {
        super.onCreate(delegateTask);
        if (!isApplyProcUnit(delegateTask)) {
            TaskExtension te = actApplication.loadRuntimeTaskExtension(delegateTask.getId());
            Assert.notNull(te, String.format("未查询到流程任务【%s】的扩展信息", delegateTask.getId()));
            // 获取流程任务对应的审批环节信息
            ProcUnitHandler procUnitHandler = procUnitHandlerApplication.loadProcUnitHandler(te.getProcUnitHandlerId());
             // 审批环节名称
            String id = delegateTask.getExecution().getProcessBusinessKey();
            ExceptionReport exceptionReport = this.exceptionReportRepository.findOne(id);
            exceptionReport.setHandleNodeName(procUnitHandler.getSubProcUnitName());
            exceptionReport.setHandleNodeId(procUnitHandler.getSubProcUnitId());
            exceptionReportRepository.save(exceptionReport);
        }
    }
    /**
     * 删除流程实例事件
     */
    @Override
    protected void onDeleteProcessInstance(DelegateExecution delegateExecution) {
        String bizId = delegateExecution.getProcessBusinessKey();
        deleteApplyAcceptance(bizId);
    }

    /**
     * 终止流程事件
     */
    @Override
    protected void onAbortProcessInstance(DelegateExecution delegateExecution) {
        super.onAbortProcessInstance(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        updateStatus(bizId, BizBillStatus.ABORTED);
    }


    /**
     * 流程结束事件
     */
    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        //super.onEnd(delegateExecution);
        BizBillStatus status = BizBillStatus.COMPLETED;
        String bizId = delegateExecution.getProcessBusinessKey();
        ExceptionReport exceptionReport = this.findById(bizId);
        exceptionReport.setStatusId(status.getId());

         //供应商异常 商品赔付 创建采购订单
        if ("supplier".equals(exceptionReport.getBillType())&&"goods".equals(exceptionReport.getDealWay())) {
            List  <ExceptionReportGoods> goodslist=exceptionReportGoodsApplication.findByExceptionReportId(exceptionReport.getId());
            int u=0;
            for  (ExceptionReportGoods goods:goodslist ) {
                u++;
                PurchaseOrderVo purchaseOrderVo = new PurchaseOrderVo();
                purchaseOrderVo.setBsart("ZMF");
                purchaseOrderVo.setBukrs(goods.getCompany());  //公司代码
                purchaseOrderVo.setEkorg(goods.getPurchaseTeam()); // 采购组织
                purchaseOrderVo.setEkgrp(goods.getEkgrp()); //采购组
                purchaseOrderVo.setAfnam(exceptionReport.getPersonMemberName());

                purchaseOrderVo.setLifnr(exceptionReport.getCustomerNo());// 供应商编码
                List<PurchaseOrderItemVo> itemVos = new ArrayList<>();
                PurchaseOrderItemVo itemVo = new PurchaseOrderItemVo();

                itemVo.setMatnr(goods.getProductCode());
                itemVo.setTxz01(goods.getProductName());
                itemVo.setMenge(goods.getNumber());
                itemVo.setMeins(goods.getUnit());
                itemVo.setEeind(DateUtil.getDateFormat("yyyyMMdd", goods.getNeedDate()));
                itemVo.setLgort(goods.getLocation()); //收货地点
                itemVo.setWerks(goods.getWerks()); //收货工厂
                itemVo.setEbelp(Integer.toString(u));
                itemVo.setKoein("CNY");
                itemVo.setKpein(new BigDecimal(0)); //定价基数
                itemVo.setKbetr(new BigDecimal(0)); //价格
                itemVo.setPurchaseMwskz("J0"); //税码
                itemVo.setUmson("X"); //免费项目
                itemVos.add(itemVo);
                purchaseOrderVo.setItem(itemVos);

                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("businessType", "供应商异常的商品结算");
                resultMap.put("businessId", exceptionReport.getId());
                resultMap.put("parameter", JSON.toJSONString(purchaseOrderVo));
                try {
                    String url = "cud_po_zub/po_zub";
                    //String url = SystemCache.getParameter("", String.class);
                    String execute = httpClient.execute(purchaseOrderVo, url);
                    List<SapResult> resultList = JSONObject.parseArray(execute, SapResult.class);
                    //TODO 待SAP返回数据结构
                    SapResult sapResult = resultList.get(0);
                    if (!"S".equals(sapResult.getTYPE())) {
                        List<String> messages = resultList
                                .stream()
                                .map(SapResult::getMESSAGE).collect(Collectors.toList());
                        throw new RuntimeException("数据传输失败，" + String.join("；", messages));
                    } else {
                        resultMap.put("TYPE", sapResult.getTYPE());
                        resultMap.put("MESSAGE", sapResult.getMESSAGE());
                    }
                    //SAP单据编号
                    exceptionReport.setSapBillNo(sapResult.getMESSAGE_V1());
                    //exceptionReport.setDealResult(sapResult.getMESSAGE_V1());

                } catch (IOException e) {
                    resultMap.put("TYPE", "E");
                    resultMap.put("MESSAGE", e.getMessage());
                    throw new RuntimeException(e);
                } finally {
                    sapMutualEpLogApplication.saveSapMutualEpLog(resultMap);
                }
            }
        }
        //供应商异常 货币结算(扣除应付款）
        if (("supplier".equals(exceptionReport.getBillType()))&&"pay".equals(exceptionReport.getDealWay())){
            List<ExceptionReportPayable> payableList = exceptionReportPayableApplication.findByExceptionReportId(exceptionReport.getId());
            List<ExceptionReportPayableVo> payableVoList = new ArrayList<>();
            payableList.forEach(
                    payable -> {
                        ExceptionReportPayableVo payableVo = new ExceptionReportPayableVo();
                        BeanUtil.copyProperties(payable, payableVo);
                        payableVoList.add(payableVo);
                    }
            );
            Map<String,Object> map = new HashMap<>();
            map.put("ZTYPE","SUPPDR");
            map.put("ZCODE","I");
            map.put("SUPPDR",payableVoList);
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("businessType", "供应商异常的货币结算(扣除应付款）");
            resultMap.put("businessId", exceptionReport.getId());
            resultMap.put("parameter", JSON.toJSONString(map));
            try {
                String url = "cud_table";
                //String url = SystemCache.getParameter("", String.class);
                String execute = httpClient.execute(map, url);
                List<SapResult> resultList = JSONObject.parseArray(execute, SapResult.class);
                //SAP返回数据结构
                SapResult sapResult = resultList.get(0);
                if (!"S".equals(sapResult.getTYPE())) {
                    List<String> messages = resultList
                            .stream()
                            .map(SapResult::getMESSAGE).collect(Collectors.toList());
                    throw new RuntimeException("数据传输失败，" + String.join("；", messages));
                } else {
                    resultMap.put("TYPE", sapResult.getTYPE());
                    resultMap.put("MESSAGE", sapResult.getMESSAGE());
                }
                //SAP单据编号
                exceptionReport.setSapBillNo(sapResult.getMESSAGE_V1());
                //exceptionReport.setDealResult(sapResult.getMESSAGE_V1());

            } catch (IOException e) {
                resultMap.put("TYPE", "E");
                resultMap.put("MESSAGE", e.getMessage());
                throw new RuntimeException(e);
            } finally {
                sapMutualEpLogApplication.saveSapMutualEpLog(resultMap);
            }
        }
         this.saveExceptionReport(exceptionReport);
        //根据责任部门是采购部门 则生成供应商异常单
        if ("produce".equals(exceptionReport.getBillType())
                //&&StringUtil.isNotBlank(exceptionReport.getDutyDept())
                &&!"0".equals(exceptionReport.getDutyDept())) {
           Org org = orgApplication.loadOrg(exceptionReport.getDutyDept());
           if (org.getCode().startsWith("CGB")){ //是采购部
               ExceptionReport suppExceptionReport = new ExceptionReport();
               suppExceptionReport.setBillType("supplier");
               suppExceptionReport.setSourceBillCode(exceptionReport.getBillCode());
               suppExceptionReport.setReportDate(exceptionReport.getReportDate());
               suppExceptionReport.setExceptionReasonType(exceptionReport.getExceptionReasonType());
               suppExceptionReport.setExceptionType(exceptionReport.getExceptionType());
               suppExceptionReport.setExceptionTitle(exceptionReport.getExceptionTitle());
               suppExceptionReport.setExceptionDate(exceptionReport.getExceptionDate());
              // suppExceptionReport.setCustomerOrderNo(exceptionReport.getCustomerOrderNo());
              // suppExceptionReport.setCustomerName(exceptionReport.getCustomerName());
               suppExceptionReport.setUrgency(exceptionReport.getUrgency());
               suppExceptionReport.setExceptionState(exceptionReport.getExceptionState());
               suppExceptionReport.setExceptionReason(exceptionReport.getExceptionReason());
               suppExceptionReport.setNeedGuarantee(exceptionReport.getNeedGuarantee());
               suppExceptionReport.setNeedImproveReport(exceptionReport.getNeedImproveReport());

               suppExceptionReport.setWerks(exceptionReport.getWerks());
               suppExceptionReport.setWerksName(exceptionReport.getWerksName());
               suppExceptionReport.setBrandName(exceptionReport.getBrandName());

               suppExceptionReport.setManager(exceptionReport.getManager());
               suppExceptionReport.setDeputyManager(exceptionReport.getDeputyManager());
               suppExceptionReport.setGeneralManager(exceptionReport.getGeneralManager());

               suppExceptionReport.setDutyDept(exceptionReport.getDutyDept());
               suppExceptionReport.setDutyDeptName(exceptionReport.getDutyDeptName());
               suppExceptionReport.setCheckOperator(exceptionReport.getCheckOperator());
               suppExceptionReport.setCheckOperatorName(exceptionReport.getCheckOperatorName());

               suppExceptionReport.setLoseMoney(exceptionReport.getLoseMoney());
               suppExceptionReport.setAttbizId(exceptionReport.getAttbizId());
               suppExceptionReport.setDealWay("special");

                Operator operator = operatorApplication.createOperatorByPersonMemberId(exceptionReport.getCheckOperator());
                suppExceptionReport.setPersonMemberId(operator.getPersonMemberId());
                suppExceptionReport.setPersonMemberName(operator.getPersonMemberName());


               ExceptionReportQueryRequest queryRequest = new ExceptionReportQueryRequest();
               queryRequest.setExceptionReportId(bizId);

               QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "exceptionReportItems");
               QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
               queryModel.setPageIndex(1);
               queryModel.setPageSize(200);
               Map<String,Object> mapItems= this.sqlExecutorDao.executeSlicedQuery(queryModel);
                List<Map<String,Object>> itemList=(List)mapItems.get("Rows");
                StringBuffer  orderNos=new StringBuffer("");
                StringBuffer  matnrs=new StringBuffer("");
                StringBuffer  maktxs=new StringBuffer("");
               List<Map<String,Object>> newItemList=new ArrayList<Map<String,Object>>();
                for (int u=0;u<itemList.size();u++){
                    Map map=(Map)itemList.get(u);
                    orderNos.append(map.get("produceNo"));
                    matnrs.append(map.get("productCode"));
                    maktxs.append(map.get("productName"));
                    if (u<itemList.size()-1){
                        orderNos.append("/");
                        matnrs.append("/");
                        maktxs.append("/");
                    }
                    map.put("id","");
                    newItemList.add(u,map);
                }
               suppExceptionReport.setCustomerOrderNo(orderNos.toString());
               suppExceptionReport.setMaktx(maktxs.toString());
               suppExceptionReport.setMatnr(matnrs.toString());

/*
               queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "exceptionReportDutyPersons");
               queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
               queryModel.setPageIndex(1);
               queryModel.setPageSize(200);

               Map<String,Object> mapDutyItems= this.sqlExecutorDao.executeSlicedQuery(queryModel);
               List<ExceptionReportDutyPerson> exceptionDutyItems=(List<ExceptionReportDutyPerson>)mapDutyItems.get("Rows");
                */

               //创建供应商异常
               asyncWriteExecutor.execute(()->
                // mannualStartWorkApplication.startWorkflow(suppExceptionReport,PROCESS_DEFINITION_KEY,"exceptionReport")
                 saveSupplierExceptionReport(suppExceptionReport,newItemList)
               );

          }
        }
    }

    public void saveSupplierExceptionReport(ExceptionReport exceptionReportVo, List<Map<String,Object>> exceptionItems){
        ExceptionReport exceptionReport = new ExceptionReport();
        BeanUtil.copyProperties(exceptionReportVo,exceptionReport);
        //初始化用户信息
        Operator operator = operatorApplication.createOperatorByPersonMemberId(exceptionReport.getPersonMemberId());
        exceptionReport.setDefaultValues(new OrgUnit(operator.getFullId(), operator.getFullName()));

        Map<String, Object> formData = BeanUtil.beanToMap(exceptionReport);
        formData.put("exceptionReportItems",exceptionItems);
//        formData.put("personList",exceptionDutyItems);
           //启动流程实例
        this.startProcessInstance(PROCESS_DEFINITION_KEY, formData);

    }

    public String startProcessInstance(String processDefinitionKey,Map<String, Object> formData){
        Map<String, Object> variables = new HashMap();
        SDO localSdo = this.buildSDO(formData);
        ThreadLocalUtil.putVariable(Constants.SDO, localSdo);
        variables.put("startModel", ProcessStartModel.MANUAL.getId());
        Operator operator = localSdo.getOperator();
        variables.put("executorFullId", operator.getFullId());
        variables.put("executorFullName", operator.getFullName());
        ThreadLocalUtil.putOperator(operator);
        ThreadLocalUtil.putVariable("client.ip", "127.0.0.1");
        ProcessInstance processInstance = this.workflowApplication.startProcessInstanceByKey(processDefinitionKey, variables);
        String businessKey = processInstance.getBusinessKey();
        return businessKey;
    }

    private SDO buildSDO(Map<String, Object> formData) {
        String createdById = (String) formData.get("personMemberId");
        Operator operator = operatorApplication.createOperatorByPersonMemberId(createdById);
        SDO localSdo = new SDO();
        // 将业务数据传递给工作流
        formData.forEach(localSdo::putProperty);
        // 将业务流程信息传递给工作流
        localSdo.putProperty("processAction", ProcessAction.SAVE);
        localSdo.putProperty("procUnitId", "Apply");
        localSdo.setOperator(operator);
        return localSdo;
    }
    /**
     * 流程撤销事件
     **/
    @Override
    protected void onRecallProcessInstance(DelegateExecution delegateExecution) {
        String bizId = delegateExecution.getProcessBusinessKey();
        // 修改单据状态为申请
        updateStatus(bizId, BizBillStatus.APPLYING);
    }

    /**
     * 任务完成前执行
     */
    @Override
    protected void onBeforeComplete(DelegateTask delegateTask) {
        super.onBeforeComplete(delegateTask);
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        updateStatus(bizId, BizBillStatus.APPROVING);
      /*  if (this.isApplyProcUnit(delegateTask)) {   //申请后的提交  去掉 改在流程中配置有责任部门来实现
           System.out.println("===============提交======================= ");
            SDO params = this.getBizAndApprovalData();
            ExceptionReport exceptionReport=this.exceptionReportRepository.findOne(bizId);
            params.putProperty("procUnitId","Approve");
            saveResponsibleToApprover(params,exceptionReport);
        } */
        if (this.isApplyProcUnit(delegateTask)) {   //申请后的提交
            //首次 提交时  保存责任人历史记录
            ExceptionReport exceptionReport=this.exceptionReportRepository.findOne(bizId);
            if (StringUtils.isNotBlank(exceptionReport.getDutyDept())) { //责任部门不为空
                List<ExceptionReportResponsible> rslist = exceptionReportResponsibleRepository.findByExceptionReportId(exceptionReport.getId());
                if (!ObjectUtils.isEmpty(rslist)) {
                    ExceptionReportResponsible lastResponsible = rslist.get(rslist.size() - 1);
                    if (exceptionReport.getCheckOperator()!=null&&!lastResponsible.getCheckOperator().equals(exceptionReport.getCheckOperator())) {
                        saveHistoryCheckOperator(exceptionReport);
                    }
                } else {
                    saveHistoryCheckOperator(exceptionReport);
                }
            }
        }
    }

    /**
     * 回退
     */
    @Override
    protected void onBack(DelegateTask delegateTask, String destActivityId) {
        super.onBack(delegateTask, destActivityId);
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        if (destActivityId.equalsIgnoreCase("apply")) {
            updateStatus(bizId, BizBillStatus.APPLYING);
        }
        //回退删除责任人历史记录
        ExceptionReport exceptionReport=this.exceptionReportRepository.findOne(bizId);
        if (StringUtils.isNotBlank(exceptionReport.getDutyDept())) { //责任部门不为空
            List<ExceptionReportResponsible> rslist = exceptionReportResponsibleRepository.findByExceptionReportId(exceptionReport.getId());
            if (!ObjectUtils.isEmpty(rslist)) {
                ExceptionReportResponsible lastResponsible = rslist.get(rslist.size() - 1);
                if (exceptionReport.getCheckOperator()!=null&&lastResponsible.getCheckOperator().equals(exceptionReport.getCheckOperator())) {
                    exceptionReportResponsibleRepository.delete(lastResponsible);
                }
            }
        }
        //删除异常的待处理记录
      //  WF_ProcUnitHandler procunitha0_  where `BIZ_CODE`='ER20241023-0001' and
      //  and `HANDLER_ID`='8b2ff3c3ed0011eea8a50242ac110003@FAD723F9507946628516EFBF316DC59F' and `STATUS`=0
       // String sql="DELETE FROM WF_ProcUnitHandler where BIZ_ID='"+bizId+"' and SUB_PROC_UNIT_ID='"+respNodeCode+"'";
        //sqlExecutorDao.executeUpdate(sql);
    }

    /**
     * 回收事件
     **/
    @Override
    protected void onWithdraw(DelegateTask delegateTask, String destActivityId) {
        super.onWithdraw(delegateTask, destActivityId);
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        if (destActivityId.equalsIgnoreCase("apply")) {
            updateStatus(bizId, BizBillStatus.APPLYING);
        }
    }


    @Transactional
    public void deleteApplyAcceptance(String id) {
        Assert.hasText(id, CommonDomainConstants.ID_NOT_BLANK);
        exceptionReportRepository.delete(id);
    }


    public ByteArrayOutputStream printInfo(HttpServletResponse response, String id) {

        ExceptionReport exceptionReport=this.exceptionReportRepository.findOne(id);
        List<ExceptionReportItem> itemList=exceptionReportItemApplication.findByExceptionReportId(id);
        //去掉前导零
        for (ExceptionReportItem exceptionReportItem : itemList) {
            String productCode = exceptionReportItem.getProductCode();
            String replaced = productCode.replaceFirst("^0*", "");
            exceptionReportItem.setProductCode(replaced);
        }
        List<ExceptionReportDutyPerson> dutyList=exceptionReportDutyPersonApplication.findByExceptionReportId(id);
        if ("in".equals(exceptionReport.getExceptionType())){
            exceptionReport.setExceptionType("内部");
        } else{
            exceptionReport.setExceptionType("外部");
        }
        String sql="select s.code,w.handler_name,w.handler_id,w.dept_name,w.full_id,w.HANDLED_DATE,w.opinion  FROM WF_PROCUNITHANDLER w left join sa_oporg s on s.id=w.HANDLER_ID";
        sql+="  where  biz_id='"+id+"' order  by w.HANDLED_DATE desc ";
        List<Map<String, Object>> mapList=sqlExecutorDao.queryToListMap(sql);
        Map<String ,Object> data = new HashMap<>();
        if  (mapList.size()>0){
           String lastAuditPerson=mapList.get(0).get("handlerName").toString();
            data.put("lastAuditPerson",lastAuditPerson);
        }
        if  (mapList.size()>1) {
            String preLastAuditPerson = mapList.get(1).get("handlerName").toString();
            String opinion = mapList.get(1).get("opinion").toString();
            data.put("preAuditPerson",preLastAuditPerson);
            data.put("opinion",opinion);
        }
       if ("supplier".equals(exceptionReport.getBillType())){
           //StringBuffer dealmethod=new StringBuffer("");
           List  <ExceptionReportPayable> paylist=exceptionReportPayableApplication.findByExceptionReportId(id);
           if (CollectionUtil.isNotEmpty(paylist)){
              // dealmethod.append("货币结算:(扣除应付款)");
               int u=0;
               for (ExceptionReportPayable pay:paylist){
                   Date da=pay.getSendDate();
                 //  String dateStr = DateUtil.getDateFormat("yyyy-MM-dd", pay.getSendDate());
                 //  pay.setSendDate(dateStr);
                  // paylist.set(u,pay);
                   u++;
               }
               data.put("paylist",paylist);
           }
           /*for (ExceptionReportPayable pay:paylist){
               dealmethod.append("采购订单:").append(pay.getPurchaseNo());
               dealmethod.append(",金额:").append(pay.getMoney());
               dealmethod.append(",日期:").append(pay.getSendDate());
           }*/
           List  <ExceptionReportCash> cashlist=exceptionReportCashApplication.findByExceptionReportId(id);
           if (CollectionUtil.isNotEmpty(cashlist)){
               //dealmethod.append("货币结算:(现金/转帐)");
               int u=0;
               for (ExceptionReportCash cash:cashlist){
                   String payName=DictUtil.getDictionaryDetailText("zwels",cash.getPayment());
                   cash.setPayment(payName);
                   cashlist.set(u,cash);
                   u++;
               }
               data.put("cashlist",cashlist);
           }

           List  <ExceptionReportGoods> goodslist=exceptionReportGoodsApplication.findByExceptionReportId(id);
           if (CollectionUtil.isNotEmpty(goodslist)){
              // dealmethod.append("商品赔付:");
               data.put("goodslist",goodslist);
           }
           /*for (ExceptionReportGoods goods:goodslist){
               dealmethod.append("公司:").append(goods.getCompanyName());
               dealmethod.append(",采购组织:").append(goods.getPurchaseTeamName());
               dealmethod.append(",物料名称:").append(goods.getProductName());
               dealmethod.append(",数量:").append(goods.getNumber());
               dealmethod.append(",单位:").append(goods.getUnitName());
               dealmethod.append(",需求日期:").append(goods.getNeedDate());
               dealmethod.append(",收货工厂:").append(goods.getWerksName());
               dealmethod.append(",收货地点:").append(goods.getLocationName());
           }*/
          // exceptionReport.setDealMethod(dealmethod.toString());
        }
        data.put("head",exceptionReport);
        data.put("itemList",itemList);
        data.put("dutyList",dutyList);

        //Document document = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            response.reset();
            response.setHeader("Content-Type", "application/pdf-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("异常单据.pdf", "UTF-8"));

            File  fileb = new File("baoshen.png");
            data.put("baoshen",fileb);
            Template template = null;
            if ("supplier".equals(exceptionReport.getBillType())){
                template = freemarkerConfigurer.getConfiguration().getTemplate("exceptionReportSupplier.ftl");
            } else {
                template = freemarkerConfigurer.getConfiguration().getTemplate("exceptionReport.ftl");
            }
            byteArrayOutputStream = CommonUtils.createPDF(data,template);

        }catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("PDF生成失败！");
        } finally {

        }
        return  byteArrayOutputStream;
    }

    /**
     * 设置任务名称
     */
    @Override
    protected void setTaskDescription(DelegateTask delegateTask) {
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        delegateTask.setDescription(this.getApprovalSubjectName(bizId));

    }

    /**
     * 获取任务标题
     *
     * @param bizId
     * @return
     */
    private String getApprovalSubjectName(String bizId) {
        ExceptionReport exceptionReport = this.exceptionReportRepository.findOne(bizId);
        //查询 单据日期
        String fillinDateStr = DateUtil.getDateFormat("yyyy-MM-dd HH:mm:ss", exceptionReport.getFillinDate());
        String title="品质异常报告单";
        //设置标题
        if ("supplier".equals(exceptionReport.getBillType())){
           title+="(供应商)";
        }
        return String.format("%s%s(%s)%s", exceptionReport.getDeptName(),exceptionReport.getPersonMemberName(), fillinDateStr,title);
    }

     @Override
   public  List<Map<String,Object>> getCustomerOrders(String customerNo){
         List<Map<String,Object>> list=new ArrayList<>();

        return list;
    }

}
