package com.malk.siku.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.malk.server.aliwork.YDConf;
import com.malk.server.aliwork.YDParam;
import com.malk.server.common.McR;
import com.malk.service.aliwork.YDClient;
import com.malk.service.dingtalk.DDClient;
import com.malk.service.dingtalk.DDClient_Contacts;
import com.malk.service.dingtalk.DDClient_Personnel;
import com.malk.siku.service.SikuService;
import com.malk.siku.utils.MkBxUtil;
import com.malk.siku.utils.MkYpUtil;
import com.malk.siku.utils.QyddUtil;
import com.malk.utils.UtilHttp;
import com.malk.utils.UtilMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SikuServiceImpl implements SikuService {
    @Autowired
    private YDClient ydClient;

    @Value(value = "${mk.downloadFilePath}")
    private String downloadFilePath;

    @Value(value = "${mk.downloadUrl}")
    private String downloadUrl;

    @Autowired
    private DDClient ddClient;

    //每刻报销 测试环境
    /*private static String mkbx_empId = "18857526310";//默认 周漂
    private static String mkbx_deptId = "DI205228744816739500";//默认 财务部*/

    //每刻报销 正式环境
    private static String mkbx_empId = "HZ769";//默认 周漂
    private static String mkbx_deptId = "DI205228744816739500";//默认 财务部

    //每刻云票 测试环境
//    private static String mkyp_empId = "18857526310";//默认 周漂

    //每刻云票 正式环境
    private static String mkyp_empId = "HZ769";//默认 周漂

    private static final Map<String,String> ddLegalEntity = new HashMap<>();//企业滴滴公司主体
    static{
        ddLegalEntity.put("91110105MA04B5ND7J","1125994677035472");//思库共创（北京）营销策划有限公司
        ddLegalEntity.put("91330110MA2AYPX2X1","1125994676962964");//杭州光映场景科技有限公司
        ddLegalEntity.put("91310120MA1JJJL131","1125994676938831");//上海造酷文化科技有限公司
        ddLegalEntity.put("913301060793092966","1125994676742442");//杭州思库营销策划有限公司
        ddLegalEntity.put("91330105MA27WGAY7W","1125994677125313");//思门（杭州）品牌营销策划有限公司
        ddLegalEntity.put("91330105MA2HYCM71D","1125994676919592");//思库文化传播集团有限公司
        ddLegalEntity.put("913301065995586166","1125994677114352");//杭州思库文化创意有限公司
        ddLegalEntity.put("91510100MADHQM1A62","1125994677036721");//思库（成都）文化传播有限公司
        ddLegalEntity.put("91330105MA2KGRJQ3T","1125994676949976");//光格（杭州）文化传播有限公司
        ddLegalEntity.put("91330109MA2B2A0E3N","1125994677041739");//杭州东东腔文化创意有限公司
        ddLegalEntity.put("","1125994336723042");//思库（浙江）文化传播有限公司
    }

    @Override
    public McR saveTradingPartner(Map map) {
        String formInstId = UtilMap.getString(map, "formInstId");

        String type = UtilMap.getString(map, "type");

        Map formData = ydClient.queryData(YDParam.builder()
                .formInstanceId(formInstId)
                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();

        Map partner = new HashMap();

        if ("客户".equals(type)){
            //客户
//            partner.put("parentName", "客户");//所属分类名称
            partner.put("name", UtilMap.getString(formData,"textField_mkddjwy3"));//往来单位中文名
            partner.put("partnerType", "客户");//往来关系，可选值为："供应商"、"客户"、"供应商，客户"（既是供应商又是客户的情况下以中文逗号分隔(供应商在前)）
            partner.put("partnerProperty", "公司");//往来性质，可选值为："公司"、"个体工商户"
            partner.put("businessCode", UtilMap.getString(formData,"serialNumberField_mkddjwy2"));//往来单位编码,不超过50个字符
            partner.put("taxNumber", UtilMap.getString(formData,"textField_mkddjwys"));//税务登记号,不超过200个字符
            partner.put("readOnly", false);//是否只读，默认false。如果为true，那么在每刻系统中往来单位的所有信息（如权限范围、收款账户等）均无法修改。（接口更新操作不受限制）
            partner.put("reMark", "");//往来单位备注
            partner.put("enabled", true);//是否启用（true:启用；false:禁用）。若该参数为空，新增则默认为true，更新则保持系统内状态。
        }else {
            //供应商
            String hzlx = UtilMap.getString(formData, "radioField_mketkvw7");
            String freeType = UtilMap.getString(formData, "radioField_mmyoc59n");//free类别

//            partner.put("parentBizCode", "GYS");//所属分类业务编码
            partner.put("name", "个人".equals(freeType) ? UtilMap.getString(formData,"textField_mkkixdd6") : UtilMap.getString(formData,"textField_mketkvv0"));//往来单位中文名
            partner.put("partnerType", "供应商");//往来关系，可选值为："供应商"、"客户"、"供应商，客户"（既是供应商又是客户的情况下以中文逗号分隔(供应商在前)）
            partner.put("partnerProperty", "个人".equals(freeType) ? "个体工商户" : "公司");//往来性质，可选值为："公司"、"个体工商户"
            partner.put("businessCode", UtilMap.getString(formData,"serialNumberField_mketkvw4"));//往来单位编码,不超过50个字符
            partner.put("taxNumber", "个人".equals(freeType) ? "" : UtilMap.getString(formData,"textField_mketkvxo"));//税务登记号,不超过200个字符
            partner.put("readOnly", false);//是否只读，默认false。如果为true，那么在每刻系统中往来单位的所有信息（如权限范围、收款账户等）均无法修改。（接口更新操作不受限制）
            partner.put("reMark", "");//往来单位备注
            partner.put("enabled", "启用".equals(UtilMap.getString(formData,"radioField_mketkvw8")));//是否启用（true:启用；false:禁用）。若该参数为空，新增则默认为true，更新则保持系统内状态。
        }

        Map body = new HashMap();
        body.put("partnerList", Arrays.asList(partner));

        Map result = MkBxUtil.saveTradingPartner(body);

        List<Map> data = UtilMap.getList(result, "data");

        String status = UtilMap.getString(data.get(0), "status");

        if ("ALL_FAIL".equals(status)){
            //保存往来单位失败回写错误信息
            String message = UtilMap.getString(data.get(0), "message");

            ydClient.operateData(YDParam.builder()
                    .formInstanceId(formInstId)
                    .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mmx7nk6m, textareaField_mmx7nk6r","入库失败",message)))
                    .build(), YDConf.FORM_OPERATION.update);
        }

        //保存往来单位账户
        if ("SUCCESS".equals(status)){
            Map account = new HashMap();
            account.put("businessCode",UtilMap.getString(formData,"serialNumberField_mketkvw4"));

            Map accountItem = new HashMap();
            accountItem.put("accountType","BANK");
            accountItem.put("accountName",UtilMap.getString(formData,"textField_mketkvxa"));//账户名称
            accountItem.put("accountNumber",UtilMap.getString(formData,"textField_mketkvxc"));//账号
            accountItem.put("acceptCcy",UtilMap.getString(formData,"textField_mqf1hmt2"));//币别

            String country = UtilMap.getString(formData, "selectField_mqenuvgn");
            if (!"中国".equals(country)){
                accountItem.put("bankBranchName",UtilMap.getString(formData,"selectField_mqenuvgo"));//开户银行（境外）
                accountItem.put("",UtilMap.getString(formData,"textField_mqg2ks6b"));//开户银行编码
            }else {
                accountItem.put("bankBranchNo",UtilMap.getString(formData,"textField_mp27zy92"));//联行号
            }

            account.put("accounts",Arrays.asList(accountItem));

            Map result2 = MkBxUtil.saveAccount(Arrays.asList(account));

            List<Map> data2 = UtilMap.getList(result2, "data");
            String status2 = UtilMap.getString(data2.get(0), "status");
            String message2 = UtilMap.getString(data2.get(0), "message");
            if ("ALL_FAIL".equals(status2) || Strings.isNotBlank(message2)){
                ydClient.operateData(YDParam.builder()
                        .formInstanceId(formInstId)
                        .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mmx7nk6m, textareaField_mmx7nk6r","入库成功，账号保存失败",message2)))
                        .build(), YDConf.FORM_OPERATION.update);
            }else {
                ydClient.operateData(YDParam.builder()
                        .formInstanceId(formInstId)
                        .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mmx7nk6m, textareaField_mmx7nk6r","入库成功","")))
                        .build(), YDConf.FORM_OPERATION.update);
            }
        }

        return McR.success();
    }

    @Override
    public McR saveYpApplication(Map map) {
        String formInstId = UtilMap.getString(map, "formInstId");

        Map formData = ydClient.queryData(YDParam.builder()
                .formInstanceId(formInstId)
                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();

        Map application = new HashMap();
        application.put("formSubTypeBizCode","KPSQD");//单据编码（云票系统内维护的）
        application.put("bizCode", UtilMap.getString(formData,"serialNumberField_mknspz75"));//外部系统中的开票申请单业务编码。必须系统内唯一，用于判断开票申请单是否已导入。

        application.put("clientBizCode",UtilMap.getString(formData,"textField_mkxpe3fj"));//收票方bizCode（客户的业务编码（云票系统内维护的））与收票方开票信息字段二选一必填
        application.put("clientLegalEntityBizCode",UtilMap.getString(formData,"textField_mkddjwys"));//收票方抬头code，如果不传默认第一个（云票系统内维护的）

        String jobNumber = UtilMap.getString(formData, "textField_mo0x02kw");//申请人工号

        List<Map> allEmployee = MkYpUtil.getAllEmployee();

        String employeeId = mkyp_empId;

        for (Map employee : allEmployee) {
            String employeeId2 = UtilMap.getString(employee, "employeeId");
            if (jobNumber.equals(employeeId2)){
                employeeId = employeeId2;

                break;
            }
        }

        application.put("submitterBizCode",employeeId);//提交人工号，单据状态为审批中时必填
        application.put("applicantBizCode",employeeId);//开票申请人工号

        /*Map clientLegalEntityOaDto = new HashMap();//收票方开票信息（不在云票系统内维护的）与收票方bizCode（客户的业务编码）二选一必填且优先级高于收票方bizCode（客户的业务编码）（也就是当两字段都有值时，忽略客户的业务编码）
        clientLegalEntityOaDto.put("invoiceTitle",UtilMap.getString(formData,"selectField_mkxmix7e"));//名称
        clientLegalEntityOaDto.put("dutyParagraph",UtilMap.getString(formData,"textField_mm2wj87l"));//税号
        clientLegalEntityOaDto.put("account",UtilMap.getString(formData,"textField_mm2wj87u"));//账号
        clientLegalEntityOaDto.put("bankBranchName",UtilMap.getString(formData,"textField_mm2wj87t"));//银行

        application.put("clientLegalEntityOaDto",clientLegalEntityOaDto);*/

        application.put("legalEntityBizCode",UtilMap.getString(formData,"textField_mn4dhy5g"));//公司主体code(后续传税号)
        application.put("estimatedDate",System.currentTimeMillis());//预计开票时间
        String fplx = UtilMap.getString(formData, "selectField_mkdnuvem");//发票类型
        String estimatedInvoiceType = "";
        if (!"红冲".equals(fplx)){
            estimatedInvoiceType = getEstimatedInvoiceType(fplx, estimatedInvoiceType);
            application.put("hasRedInvoice",false);//是否负数发票
            application.put("redInvoiceReason",UtilMap.getString(formData,"textareaField_mmelm9xt"));//红冲原因
        }else {
            String lzfplx = UtilMap.getString(formData, "textField_mm2wj87n");//蓝字发票类型
            estimatedInvoiceType = getEstimatedInvoiceType(lzfplx, estimatedInvoiceType);
            application.put("hasRedInvoice",true);//是否负数发票
        }

        application.put("estimatedInvoiceType",estimatedInvoiceType);//发票类型

        application.put("phoneNumber",UtilMap.getString(formData,"textField_mkdo0azf"));//收票人电话
        application.put("email",UtilMap.getString(formData,"textField_mkdo0azn"));//收票邮箱
        application.put("autoSendMail",true);//是否自动发送邮件/短信，若传true且填写正确的收票邮箱/手机号，则在开票申请单完全开票后自动发邮件/短信。不填写收票邮箱/短信或传false时，将不会自动交付电子发票。
        application.put("applicationComment",UtilMap.getString(formData,"textareaField_mkdo0aze"));//开票备注

        Map item = new HashMap();
        item.put("productBizCode","1001");//产品bizcode
        item.put("invoiceName",UtilMap.getString(formData,"textField_mn4ajusx"));//开票名称
        item.put("taxPercent",UtilMap.getDouble(formData,"numberField_mkgkboht")/100);//税率
        item.put("forexName","CNY");//币种
        item.put("exchangeRate",1);//外汇汇率
        item.put("taxClassShortCode",UtilMap.getString(formData,"textField_mm49zsli"));//税收分类编码

        if (!"红冲".equals(fplx)){
            item.put("quantity",1);//数量
            item.put("priceWithTax",UtilMap.getDouble(formData,"numberField_mkdo0azb"));//含税单价
        }else {
            item.put("quantity",-1);//数量
            item.put("priceWithTax",UtilMap.getDouble(formData,"numberField_mknspz7d"));//含税单价
            Map originInvoice = new HashMap();
            originInvoice.put("blueInvoiceNumber",UtilMap.getString(formData,"textField_mkxmix7d"));//原蓝字发票号
            item.put("blueInvoiceDto",Arrays.asList(originInvoice));
        }

        application.put("items",Arrays.asList(item));

        //若为红冲发票，先作废原蓝字发票应收单
        if ("红冲".equals(fplx)){
            //原蓝字发票应收单查询
            String lzlsh = UtilMap.getString(formData, "textField_mknspz7c");//原蓝字发票流水号
            Map body1 = new HashMap();
            body1.put("applicationInvoiceBizCodeList",Arrays.asList(lzlsh));
            body1.put("pageSize",1);
            body1.put("pageNum",1);
            List<Map> receivableList = MkYpUtil.searchReceivable(body1);
            if (!receivableList.isEmpty()){
                Map receivable = receivableList.get(0);

                String bizCode = UtilMap.getString(receivable, "bizCode");

                //作废原蓝字发票应收单
                Map body2 = new HashMap();
                body2.put("employeeId",employeeId);
                body2.put("bizCodeList",Arrays.asList(bizCode));
                MkYpUtil.receivableObsolete(body2);
            }
        }

        Map result = MkYpUtil.application(Arrays.asList(application));

        if (!isTrue(result)){
            ydClient.operateData(YDParam.builder()
                    .formInstanceId(formInstId)
                    .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("radioField_mkxripcc, textareaField_mmlzqvn0","开票失败",getErrorMsg(result))))
                    .useLatestVersion(true)
                    .build(), YDConf.FORM_OPERATION.update);
        }

        return McR.success();
    }

    private boolean isTrue(Map result){
        String messageCode = UtilMap.getString(result, "messageCode");

        String code = UtilMap.getString(result,"code");

        if ((Objects.nonNull(messageCode) && "SUCCESS".equals(messageCode)) || (Objects.nonNull(code) && "ACK".equals(code))){
            return true;
        }else {
            return false;
        }
    }

    //获取错误信息
    private String getErrorMsg(Map result) {
        String errorMsg = UtilMap.getString(result, "message");

        Map data = UtilMap.getMap(result, "data");

        if (Objects.nonNull(data)){
            List<Map> errorData = UtilMap.getList(data, "errorData");

            if (Objects.nonNull(errorData) && !errorData.isEmpty()){
                for (Map errorDatum : errorData) {
                    errorMsg = errorMsg + ";" + UtilMap.getString(errorDatum, "errorMessage");
                }
            }
        }

        return errorMsg;
    }

    private static String getEstimatedInvoiceType(String fplx, String estimatedInvoiceType) {
        switch (fplx){
            case "应/免税普票":
                estimatedInvoiceType = "ELECTRONIC_VAT";break;//电子发票(普通发票)（税号开通全电）
            case "专票":
                estimatedInvoiceType = "ELECTRONIC_SPACIAL_VAT";break;//电子发票(增值税专票)（税号开通全电）
            case "红冲":break;
            case "形式发票":break;
            case "收据":break;
            default:break;
        } return estimatedInvoiceType;
    }

    @Async
    @Override
    public void invoiceWriteBack2(Map map) {
        //获取发票信息
        Map calloutParams = UtilMap.getMap(map, "calloutParams");
        String serviceType = UtilMap.getString(calloutParams, "serviceType");
        Map bizData = UtilMap.getMap(calloutParams, "bizData");

        if ("INVOICE_VAT_INVOICED_NOTIFY_AR".equals(serviceType)){//开票成功逻辑移到应收单完成回调中
            /*//发票开具成功后回调
            String bizCode = UtilMap.getString(bizData, "bizCode");//发票号码
            String invoiceNumber = UtilMap.getString(bizData, "invoiceNumber");//发票号码
            long issueDate = UtilMap.getLong(bizData, "issueDate");//开票日期
            String pdfUrl = UtilMap.getString(bizData, "pdfUrl");//pdf文件下载地址
            String downloadPageUrl = UtilMap.getString(bizData, "downloadPageUrl");//发票下载页面链接
            List<Map> detailItems = (List<Map>) UtilMap.getList(bizData, "detailItems");
            List<Map> documentCorrelates = UtilMap.getList(detailItems.get(0), "documentCorrelates");
            String lsh = UtilMap.getString(documentCorrelates.get(0), "bizCode");//开票申请单编号

            //回写宜搭
            Map updateFormData = new HashMap();
            updateFormData.put("radioField_mkxripcc","开票成功");
            updateFormData.put("textField_mkxripc6",invoiceNumber);
            updateFormData.put("dateField_mnfpbwpd",issueDate);
            updateFormData.put("textField_mm3aixk0",downloadPageUrl);
            updateFormData.put("textareaField_mmlzqvn0","");

            if (Strings.isNotBlank(pdfUrl)){
                String fileName = invoiceNumber + ".pdf";
                String downloadPath = downloadFilePath + fileName;
                downloadFile(pdfUrl,downloadPath);//下载pdf发票

                String downloadUri = downloadUrl + "/files/" + fileName + "?option=download" + fileName;
                String previewUri = downloadUrl + "/files/"+fileName+"?option=preview" + fileName;

                Map attachmentField = new HashMap();
                attachmentField.put("downloadUrl",downloadUri);
                attachmentField.put("name",fileName);
                attachmentField.put("previewUrl",previewUri);
                attachmentField.put("url",downloadUri);
                attachmentField.put("ext","pdf");
                updateFormData.put("attachmentField_mkxripc5",Arrays.asList(attachmentField));
            }

            Map data = ((List<Map>)ydClient.queryData(YDParam.builder()
                    .formInstanceId(bizCode)
                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mknspz75",lsh)))
                    .formUuid("FORM-A9A47B0365DB437F8F4C8E01B4468220K7GU")
                    .build(), YDConf.FORM_QUERY.retrieve_list).getData()).get(0);

            String formInstanceId = UtilMap.getString(data, "formInstanceId");

            ydClient.operateData(YDParam.builder()
                    .formInstanceId(formInstanceId)
                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                    .build(), YDConf.FORM_OPERATION.update);*/

        }else if ("INVOICE_APPLICATION_VAT_FAIL_NOTIFY_AR".equals(serviceType)){
            //开票失败后回调
            String invoiceErrorMsg = UtilMap.getString(bizData, "invoiceErrorMsg");

            String bizCode = UtilMap.getString(bizData, "bizCode");

            Map data = ((List<Map>)ydClient.queryData(YDParam.builder()
                    .formInstanceId(bizCode)
                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mknspz75",bizCode)))
                    .formUuid("FORM-A9A47B0365DB437F8F4C8E01B4468220K7GU")
                    .build(), YDConf.FORM_QUERY.retrieve_list).getData()).get(0);

            String formInstanceId = UtilMap.getString(data, "formInstanceId");

            ydClient.operateData(YDParam.builder()
                    .formInstanceId(formInstanceId)
                    .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("radioField_mkxripcc, textareaField_mmlzqvn0","开票失败",invoiceErrorMsg)))
                    .build(), YDConf.FORM_OPERATION.update);
        }
    }

    @Override
    public McR saveBxReimbursement(Map map) {
        String formInstId = UtilMap.getString(map, "formInstId");

        Map formData = ydClient.queryData(YDParam.builder()
                .formInstanceId(formInstId)
                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();

        String type = UtilMap.getString(formData, "radioField_mkkmij3b");//需求单类型
        String formSubTypeBizCode = "FT208629766551519240";//项目支付单

        Double amt = UtilMap.getDouble(formData, "numberField_mkkmij6i");

        String empId = "";
        String deptBusinessCode = "";

        String ydfqr = UtilMap.getString(formData, "textField_mmwvodde");//宜搭发起人工号
        String ztcggh = UtilMap.getString(formData, "textField_mmwvfb97");//中台采购工号

        String legalEntityBizCode = UtilMap.getString(formData, "textField_mmd6hio7");//公司抬头编码

        String xqbh = UtilMap.getString(formData, "serialNumberField_mkkmij3o");//需求编号
        long ldjssj = UtilMap.getLong(formData, "dateField_mkdf8q8q");//落地结束时间
        String isFree = "FREE需求".equals(type) ? "是" : "否";//是否free
        String isDdf = "是".equals(UtilMap.getString(formData, "radioField_mkf2quln")) ? "1" : "2";//是否代垫付
        String xmsssyb = UtilMap.getString(formData, "selectField_mkdedkv7");//项目所属事业部
        String projectCode = UtilMap.getString(formData, "textField_mmoh6nvx");//项目编码

        //针对多供应商分期付款拆分多条每刻项目支付单
        if ("常规需求".equals(type)){
            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij56");//常规-采购明细

            for (Map detail : detailList) {
                String uuid = UtilMap.getString(detail, "textField_mmvhqm0q");//子表uuid
                int index = UtilMap.getInt(detail, "numberField_mn36ykxx");//子表index

                Map body = new HashMap();
                body.put("formCode",xqbh + "-" + index);//有值时会使用该值作为单据号
                body.put("formSubTypeBizCode",formSubTypeBizCode);//表单类型的业务编号

                String mktdrgh = UtilMap.getString(detail, "textField_mok5mtsh");//每刻提单人工号
                body.put("submittedUserEmployeeId",mktdrgh);//提单人工号
                body.put("coverUserEmployeeId",mktdrgh);//承担人工号

                List<Map> internalTravelPartner = new ArrayList<>();//内部参与人
                internalTravelPartner.add(new HashMap<String,String>(){{put("employeeId",ydfqr);}});
                internalTravelPartner.add(new HashMap<String,String>(){{put("employeeId",ztcggh);}});
                body.put("travelPartnerInfo",new HashMap<String,List<Map>>(){{put("internalTravelPartner",internalTravelPartner);}});//参与人

                //查询宜搭发起人部门
                Map employeeDetails = MkBxUtil.employeeDetails(UtilMap.map("employeeIds", Arrays.asList(ydfqr)));
                String coverDepartmentBizCode = mkbx_deptId;
                if (Objects.nonNull(employeeDetails)){
                    List<Map> departments = UtilMap.getList(employeeDetails, "departments");
                    coverDepartmentBizCode = UtilMap.getString(departments.get(0), "businessCode");
                }
                body.put("coverDepartmentBizCode",coverDepartmentBizCode);//承担部门编码

                body.put("reimburseName",UtilMap.getString(detail,"textareaField_mkkmij5i"));//报销事由
                body.put("legalEntityBizCode",legalEntityBizCode);//公司抬头编码
                body.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmbmohrb"));//往来单位编码


                Map customObject = new HashMap();
                customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",ldjssj);}});//落地结束时间
                customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(detail,"dateField_mmvhqm0u"));}});//期望支付日期
                customObject.put("CF6",isFree);////free  是；否
                customObject.put("CF5",isDdf);//代垫付  是：1  ；  否：2
                customObject.put("CF2",xmsssyb);//项目所属事业部
                customObject.put("CF1",projectCode);//项目
                customObject.put("CF7",UtilMap.getString(detail,"numberField_mmwt2wcn"));//逾期天数

                Map consumeAmount = new HashMap();
                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(detail,"numberField_mkkmij5e")));//结算金额
                consumeAmount.put("currency","CNY");

                customObject.put("CF42",consumeAmount);//采购金额

                body.put("customObject",customObject);

                //报销单费用导入
                Map expenseListItem = new HashMap();

                expenseListItem.put("consumeAmount",consumeAmount);
                expenseListItem.put("corpExpense",true);//是否对公费用，需要填写true
                String gysej = UtilMap.getString(detail, "selectField_mkkkw28y");//供应商二级
                expenseListItem.put("expenseTypeBizCode",UtilMap.getString(detail,"textField_mp0m3ks3"));//费用类型业务编码
                expenseListItem.put("corpType","NO_RECEIPT");//业务场景：ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
                expenseListItem.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额（预付未到票场景必填）
                expenseListItem.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间（预付未到票场景必填）
                expenseListItem.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmbmohrb"));//往来单位业务编码

                Map consumeLocation = new HashMap();
                consumeLocation.put("cityPair",null);
                consumeLocation.put("location","110001");//todo 暂时写死  110001 北京
                expenseListItem.put("consumeLocation",consumeLocation);

                expenseListItem.put("corpExpenseResponsibleEmpIds",Arrays.asList(mktdrgh));//责任人/业务经办人（预付未到票/到票部分支付或不支付 两种场景必填）

                Map body2 = new HashMap();
                body2.put("employeeId",mktdrgh);//需要导入的对应员工的工号
                body2.put("expenseList",Arrays.asList(expenseListItem));

                List<String> expenseCodes = new ArrayList<>();
                try {
                    expenseCodes = MkBxUtil.receiveExpense(body2);
                }catch (Exception e){
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送失败",e.getMessage())))
                            .build(), YDConf.FORM_OPERATION.update);

                    continue;
                }

                body.put("expenseCodes",expenseCodes);//费用类型业务编码

                //收款账户
                Map payeeAccount = new HashMap();
                payeeAccount.put("bankAcctName",UtilMap.getString(detail,"textField_mkkmij6z"));//账户名
                payeeAccount.put("bankAcctNumber",UtilMap.getString(detail,"textField_mkkmij6y"));//银行账户
                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
                payeeAccount.put("accountType","CORP");//收款账户类型：个人（员工）-PERSONAL,公司（往来单位）-CORP
                body.put("payeeAccount",payeeAccount);

                body.put("stagingFlag",true);//暂存标识，默认为false表示不暂存


                Map result = MkBxUtil.receiveReimburse(body);

                if (isTrue(result)){
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送成功","")))
                            .build(), YDConf.FORM_OPERATION.update);
                }else {
                    String message = UtilMap.getString(result, "message");
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送失败",message)))
                            .build(), YDConf.FORM_OPERATION.update);
                }
            }
        }else {
            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij61");//free-采购明细

            for (Map detail : detailList) {
                String uuid = UtilMap.getString(detail, "textField_mmvhqm0s");//子表uuid
                int index = UtilMap.getInt(detail, "numberField_mn36ykxz");//子表index

                Map body = new HashMap();
                body.put("formCode",xqbh + "-" +index);//有值时会使用该值作为单据号
                body.put("formSubTypeBizCode",formSubTypeBizCode);//表单类型的业务编号

                String mktdrgh = UtilMap.getString(detail, "textField_mok5mtsf");//每刻提单人工号
                body.put("submittedUserEmployeeId",mktdrgh);//提单人工号
                body.put("coverUserEmployeeId",mktdrgh);//承担人工号

                List<Map> internalTravelPartner = new ArrayList<>();//内部参与人
                internalTravelPartner.add(new HashMap<String,String>(){{put("employeeId",ydfqr);}});
                internalTravelPartner.add(new HashMap<String,String>(){{put("employeeId",ztcggh);}});
                body.put("travelPartnerInfo",new HashMap<String,List<Map>>(){{put("internalTravelPartner",internalTravelPartner);}});//参与人

                //查询宜搭发起人部门
                Map employeeDetails = MkBxUtil.employeeDetails(UtilMap.map("employeeIds", Arrays.asList(ydfqr)));
                String coverDepartmentBizCode = mkbx_deptId;
                if (Objects.nonNull(employeeDetails)){
                    List<Map> departments = UtilMap.getList(employeeDetails, "departments");
                    coverDepartmentBizCode = UtilMap.getString(departments.get(0), "businessCode");
                }
                body.put("coverDepartmentBizCode",coverDepartmentBizCode);//承担部门编码

                body.put("reimburseName","FREE-" + UtilMap.getString(detail,"textareaField_mkkmij64"));//报销事由
                body.put("legalEntityBizCode",legalEntityBizCode);//公司抬头编码
                body.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmekbfa2"));//往来单位编码

                Map customObject = new HashMap();
                customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",ldjssj);}});//落地结束时间
                customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(detail,"dateField_mkkkw298"));}});//期望支付日期
                customObject.put("CF6",isFree);//free  是；否
                customObject.put("CF5",isDdf);//代垫付  是：1  ；  否：2
                customObject.put("CF2",xmsssyb);//项目所属事业部
                customObject.put("CF1",projectCode);//项目
                customObject.put("CF7",UtilMap.getString(detail,"numberField_mmwswtkx"));//逾期天数

                Map consumeAmount = new HashMap();
                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(detail,"numberField_mkkmij6p")));//结算金额
                consumeAmount.put("currency","CNY");

                customObject.put("CF42",consumeAmount);//采购金额

                body.put("customObject",customObject);

                //报销单费用导入
                Map expenseListItem = new HashMap();

                expenseListItem.put("consumeAmount",consumeAmount);
                expenseListItem.put("corpExpense",true);//是否对公费用，需要填写true
                String gysej = UtilMap.getString(detail, "selectField_mmwuzaql");//供应商二级
                expenseListItem.put("expenseTypeBizCode",UtilMap.getString(detail,"textField_mp0m3ks5"));//费用类型业务编码
                expenseListItem.put("corpType","NO_RECEIPT");//业务场景：ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
                expenseListItem.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额（预付未到票场景必填）
                expenseListItem.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间（预付未到票场景必填）
                expenseListItem.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmekbfa2"));//往来单位业务编码

                Map consumeLocation = new HashMap();
                consumeLocation.put("cityPair",null);
                consumeLocation.put("location","110001");//todo 暂时写死  110001 北京
                expenseListItem.put("consumeLocation",consumeLocation);

                expenseListItem.put("corpExpenseResponsibleEmpIds",Arrays.asList(mktdrgh));//责任人/业务经办人（预付未到票/到票部分支付或不支付 两种场景必填）

                Map body2 = new HashMap();
                body2.put("employeeId",mktdrgh);//需要导入的对应员工的工号
                body2.put("expenseList",Arrays.asList(expenseListItem));

                List<String> expenseCodes = new ArrayList<>();
                try {
                    expenseCodes = MkBxUtil.receiveExpense(body2);
                }catch (Exception e){
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送失败",e.getMessage())))
                            .build(), YDConf.FORM_OPERATION.update);

                    continue;
                }

                body.put("expenseCodes",expenseCodes);//费用类型业务编码

                //收款账户
                Map payeeAccount = new HashMap();
                payeeAccount.put("bankAcctName",UtilMap.getString(detail,"textField_mketkvxa"));//账户名
                payeeAccount.put("bankAcctNumber",UtilMap.getString(detail,"textField_mketkvxc"));//银行账户
                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
                payeeAccount.put("accountType","CORP");//收款账户类型：个人（员工）-PERSONAL,公司（往来单位）-CORP
                body.put("payeeAccount",payeeAccount);

                body.put("stagingFlag",true);//暂存标识，默认为false表示不暂存


                Map result = MkBxUtil.receiveReimburse(body);

                if (isTrue(result)){
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送成功","")))
                            .build(), YDConf.FORM_OPERATION.update);
                }else {
                    String message = UtilMap.getString(result, "message");
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送失败",message)))
                            .build(), YDConf.FORM_OPERATION.update);
                }
            }

        }

        /*Map body = new HashMap();
        body.put("formCode",UtilMap.getString(formData,"serialNumberField_mkkmij3o"));//有值时会使用该值作为单据号
        body.put("formSubTypeBizCode","FT208629766551519240");//表单类型的业务编号  todo 暂时写死 FT208629766551519240 宜搭支付单
        body.put("submittedUserEmployeeId","002");//提单人工号 todo 暂时写死 002 wzy
        body.put("reimburseName",UtilMap.getString(formData,"textareaField_mmbmohr9"));//报销事由
        body.put("legalEntityBizCode",UtilMap.getString(formData,"textField_mmd6hio7"));//公司抬头编码
        body.put("coverUserEmployeeId","002");//承担人工号 todo 暂时写死 002 wzy
        body.put("coverDepartmentBizCode","DI203800035494740082");//承担部门编码 todo 暂时写死 DI203800035494740082

        Map customObject = new HashMap();
        customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(formData,"dateField_mkdf8q8q"));}});//落地结束时间
        customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(formData,"dateField_mkkkw298"));}});//预计支付日期
        customObject.put("CF6",UtilMap.getString(formData,"radioField_mkf2quln"));////free  是；否
        customObject.put("CF5","是".equals(UtilMap.getString(formData,"radioField_mkf2quln")) ? "1" : "2");//代垫付  是：1  ；  否：2
        customObject.put("CF2",UtilMap.getString(formData,"selectField_mkdedkv7"));//项目所属事业部
        customObject.put("CF1",UtilMap.getString(formData,"textField_mmoh6nvx"));//项目

        body.put("customObject",customObject);

        List<String> expenseCodes = new ArrayList<>();
        List<Map> collectionSchedule = new ArrayList<>();

        List<Map> expenseList = new ArrayList<>();

        if ("常规需求".equals(type)){
            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij56");//常规-采购明细

            for (Map result : detailList) {
                Map item = new HashMap();

                Map consumeAmount = new HashMap();
                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(result,"numberField_mkkmij5e")));//结算金额
                consumeAmount.put("currency","CNY");

                item.put("consumeAmount",consumeAmount);
                item.put("corpExpense",true);//是否对公费用，需要填写true
                item.put("expenseTypeBizCode","200140");//费用类型业务编码 todo 暂时写死 200140 其他费用
                item.put("corpType","NO_RECEIPT");//业务场景：ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
                item.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额（预付未到票场景必填）
                item.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间（预付未到票场景必填）
                item.put("tradingPartnerBizCode",UtilMap.getString(result,"textField_mmbmohrb"));//往来单位业务编码

                Map consumeLocation = new HashMap();
                consumeLocation.put("cityPair",null);
                consumeLocation.put("location","110001");
                item.put("consumeLocation",consumeLocation);

                item.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人（预付未到票/到票部分支付或不支付 两种场景必填） todo 暂时写死 002 wzy

                expenseList.add(item);


                Map collectionScheduleItem = new HashMap();
                Map payeeAccount = new HashMap();
                payeeAccount.put("bankAcctName",UtilMap.getString(result,"textField_mkkmij6z"));//账户名
                payeeAccount.put("bankAcctNumber",UtilMap.getString(result,"textField_mkkmij6y"));//银行账户
                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
                payeeAccount.put("accountType","CORP");//收款账户类型：个人（员工）-PERSONAL,公司（往来单位）-CORP
                collectionScheduleItem.put("payeeAccount",payeeAccount);
                collectionScheduleItem.put("collectionTradingPartnerBizCode",UtilMap.getString(result,"textField_mmbmohrb"));//收款往来单位编码
                collectionScheduleItem.put("amountRatio",0);//收款比例
                collectionScheduleItem.put("amount",new HashMap<>(consumeAmount));//收款金额
                collectionScheduleItem.put("collectionType","BANK");//支付类型

                collectionSchedule.add(collectionScheduleItem);
            }
        }else {
            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij61");//free-采购明细

            for (Map result : detailList) {
                Map item = new HashMap();

                Map consumeAmount = new HashMap();
                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(result,"numberField_mkkmij6p")));//结算金额
                consumeAmount.put("currency","CNY");

                item.put("consumeAmount",consumeAmount);
                item.put("corpExpense",true);//是否对公费用，需要填写true
                item.put("expenseTypeBizCode","200140");//费用类型业务编码 todo 暂时写死 200140 其他费用
                item.put("corpType","NO_RECEIPT");//业务场景：ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
                item.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额（预付未到票场景必填）
                item.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间（预付未到票场景必填）
                item.put("tradingPartnerBizCode",UtilMap.getString(result,"textField_mmekbfa2"));//往来单位业务编码

                Map consumeLocation = new HashMap();
                consumeLocation.put("cityPair",null);
                consumeLocation.put("location","110001");
                item.put("consumeLocation",consumeLocation);

                item.put("corpExpenseResponsibleEmpIds",Arrays.asList("002"));//责任人/业务经办人（预付未到票/到票部分支付或不支付 两种场景必填） todo 暂时写死 002 wzy

                expenseList.add(item);


                Map collectionScheduleItem = new HashMap();
                Map payeeAccount = new HashMap();
                payeeAccount.put("bankAcctName",UtilMap.getString(result,"textField_mketkvxa"));//账户名
                payeeAccount.put("bankAcctNumber",UtilMap.getString(result,"textField_mketkvxc"));//银行账户
                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
                payeeAccount.put("accountType","CORP");//收款账户类型：个人（员工）-PERSONAL,公司（往来单位）-CORP
                collectionScheduleItem.put("payeeAccount",payeeAccount);
                collectionScheduleItem.put("collectionTradingPartnerBizCode",UtilMap.getString(result,"textField_mmekbfa2"));//收款往来单位编码
                collectionScheduleItem.put("amountRatio",0);//收款比例
                collectionScheduleItem.put("amount",new HashMap<>(consumeAmount));//收款金额
                collectionScheduleItem.put("collectionType","BANK");//支付类型

                collectionSchedule.add(collectionScheduleItem);
            }
        }

        //报销单费用导入
        Map body2 = new HashMap();
        body2.put("employeeId","002");//需要导入的对应员工的工号
        body2.put("expenseList",expenseList);

        expenseCodes = MkBxUtil.receiveExpense(body2);

        body.put("expenseCodes",expenseCodes);//费用类型业务编码
        body.put("collectionSchedule",collectionSchedule);//多人收款，如果已填充该字段，则无需填充上方的收款账户字段，若传多人收款，则paymentSceneBizCode参数必填
        body.put("paymentSceneBizCode","DGYSSK");//多人收款场景（支付场景）表单业务编码，需要填写多人收款时必填

        body.put("stagingFlag",false);////暂存标识，默认为false表示不暂存

        Map result = MkBxUtil.receiveReimburse(body);*/

        return McR.success();
    }

    @Override
    public McR saveYpClient(Map map) {
        String formInstId = UtilMap.getString(map, "formInstId");

        Map formData = ydClient.queryData(YDParam.builder()
                .formInstanceId(formInstId)
                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();

        Map customerObj = new HashMap();
        customerObj.put("bizCode",UtilMap.getString(formData,"serialNumberField_mkddjwy2"));//客户编码， 系统内唯一。
        customerObj.put("name",UtilMap.getString(formData,"textField_mkddjwy3"));//客户名称，系统内唯一
        customerObj.put("type","CORP");//客户类型: CORP (公司，默认), SELF_EMPLOYED(个体经营商)
        customerObj.put("nameAutoCode",false);
        customerObj.put("status","ENABLED");//客户状态：DISABLED("禁用" ，默认) ENABLED("启用")

        List<Map> contacts = new ArrayList<>();
        List<Map> contactList = UtilMap.getList(formData, "tableField_mkddjwyv");
        for (Map contact : contactList) {
            Map contactObj = new HashMap();
            contactObj.put("name",UtilMap.getString(contact,"textField_mkddjwyw"));//联系人姓名
            contactObj.put("phoneNumber",UtilMap.getString(contact,"textField_mkddjwyx"));//联系电话
            contactObj.put("position",UtilMap.getString(contact,"textField_mkg8toy9"));//职位

            contacts.add(contactObj);
        }
        customerObj.put("contacts",contacts);//联系人列表

        List<Map> invoiceTitles = new ArrayList<>();

        List<Map> accounts = new ArrayList<>();

        List<Map> invoiceList = UtilMap.getList(formData, "tableField_mn496ozf");
        for (Map invoice : invoiceList) {
            Map invoiceTitle = new HashMap();
            invoiceTitle.put("invoiceTitle",UtilMap.getString(invoice,"textField_mkddjwyr"));//发票抬头
            invoiceTitle.put("dutyParagraph",UtilMap.getString(invoice,"textField_mkddjwys"));//税号
            invoiceTitle.put("bizCode",UtilMap.getString(invoice,"textField_mkddjwys"));//业务编码
            invoiceTitle.put("bankBranchName",UtilMap.getString(invoice,"textField_mkddjwyt"));//开户行
            invoiceTitle.put("account",UtilMap.getString(invoice,"textField_mkddjwyu"));//银行账户
            invoiceTitles.add(invoiceTitle);

            Map account = new HashMap();
            account.put("paymentType","BANK");//账户类型,
            account.put("bankAcctName",UtilMap.getString(invoice,"textField_mkddjwyr"));//账户名
            account.put("bankAcctNumber",UtilMap.getString(invoice,"textField_mkddjwyu"));//银行对应银行卡号
            account.put("bankName",UtilMap.getString(invoice,"textField_mkddjwyt"));//银行名称
            accounts.add(account);
        }

        customerObj.put("invoiceTitles",invoiceTitles);//账户信息
        customerObj.put("accounts",accounts);//账户信息

        MkYpUtil.saveClient(Arrays.asList(customerObj));

        return McR.success();
    }

    @Async
    @Override
    public void invoiceWriteBack(Map map) {
        Map calloutParams = UtilMap.getMap(map, "calloutParams");

        Map bizData = UtilMap.getMap(calloutParams, "bizData");

        long verifyDate = UtilMap.getLong(bizData, "verifyDate");//核销日期

        List<Map> upStreamItemList = UtilMap.getList(bizData, "upStreamItemList");//主核销方核销明细

        Double totalVerifyAmount = UtilMap.getDouble(upStreamItemList.get(0), "totalVerifyAmount");//本次核销金额

        List<Map> relatedDocuments = UtilMap.getList(bizData, "relatedDocuments");

        for (Map relatedDocument : relatedDocuments) {
            String formType = UtilMap.getString(relatedDocument, "formType");

            if ("RECEIVABLE_AR".equals(formType)){
                String bizCode = UtilMap.getString(relatedDocument, "bizCode");


                //应收单查询
                Map body = new HashMap();
                body.put("bizCodes",Arrays.asList(bizCode));
                body.put("pageNum",1);
                body.put("pageSize",1);

                Map receivable = MkYpUtil.searchReceivable(body).get(0);

                Map invoice = ((List<Map>) UtilMap.getList(receivable, "invoiceList")).get(0);

                String invoiceNumber = UtilMap.getString(invoice, "invoiceNumber");//发票号码

                Double receivedAmount = UtilMap.getDouble(receivable, "receivedAmount");//已收金额

                List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                        .formUuid("FORM-A9A47B0365DB437F8F4C8E01B4468220K7GU")
                        .searchCondition(JSONObject.toJSONString(UtilMap.map("textField_mkxripc6",invoiceNumber)))
                        .build(), YDConf.FORM_QUERY.retrieve_list).getData();

                String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");

                Map updateFormData = new HashMap();
                updateFormData.put("numberField_ml8t9c4u",receivedAmount);//已收金额
                updateFormData.put("dateField_mnfpbwpe",verifyDate);//核销日期
                updateFormData.put("numberField_mngxcnih",totalVerifyAmount);//本次核销金额

                ydClient.operateData(YDParam.builder()
                        .formInstanceId(formInstanceId)
                        .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                        .build(), YDConf.FORM_OPERATION.update);

                return;
            }

        }

    }

    @Async
    @Override
    public void invoiceWriteBack3(Map map) {
        String formCode = UtilMap.getString(map, "formCode");

        if (!formCode.contains("需求") && !formCode.contains("采购")){
            //判断是否为核销报销单
            Map formData = UtilMap.getMap(map, "formData");

            Map expenseList = UtilMap.getMap(formData, "expenseList");

            List<Map> expenseValueList = UtilMap.getList(expenseList, "value");

            for (Map expenseValue : expenseValueList) {
                Map deductionList = UtilMap.getMap(expenseValue, "deductionList");//当前对公费用核销的数据（当前到票核销场景核销了哪些“预付未到票”记录）

                List<Map> invoiceList = getMkListValue(expenseValue, "invoiceList");//发票列表
                Map invoice = invoiceList.get(0);
                Double totalTaxAmount = UtilMap.getDouble(invoice, "totalTaxAmount");//每刻实际税金

                /*Map expenseDeductionTaxAmount = UtilMap.getMap(expenseValue, "expenseDeductionTaxAmount");//费用级抵扣税额（消费币种）
                Double sj = UtilMap.getDouble(expenseDeductionTaxAmount, "amount");//每刻实际税金*/

                List<Map> deductionValueList = UtilMap.getList(deductionList, "value");

                Map deductionValue = deductionValueList.get(0);

                Double deductionAmount = UtilMap.getDouble(deductionValue, "deductionAmount");//核销金额
                String targetFormCode = UtilMap.getString(deductionValue, "targetFormCode");//核销报销单编号

                if (targetFormCode.contains("需求") || targetFormCode.contains("采购")){
                    //更新宜搭核销金额及税金
                    updateYdDeduction(targetFormCode,deductionAmount,totalTaxAmount);
                }
            }

            return;
        }

        Map reimburseDetailInfo = MkBxUtil.reimburseDetailInfo(formCode);

        Boolean installment = UtilMap.getBoolean(reimburseDetailInfo, "installment");//是否使用分期付款

        Boolean firstPeriodPayment = UtilMap.getBoolean(reimburseDetailInfo, "firstPeriodPayment");//分期情况下首期是否随本单支付

        double amt = 0;

        if (installment){
            if (firstPeriodPayment){
                List<Map> collectionSchedule = UtilMap.getList(reimburseDetailInfo, "collectionSchedule");

                Map collectionAmount = UtilMap.getMap(collectionSchedule.get(0), "collectionAmount");

                amt = UtilMap.getDouble(collectionAmount,"amount");
            }else {
                return;
            }
        }else {
            Map paymentAmount = UtilMap.getMap(reimburseDetailInfo, "paymentAmount");
            amt = UtilMap.getDouble(paymentAmount, "amount");//应付金额

        }

        long approvedAt = UtilMap.getLong(reimburseDetailInfo, "approvedAt");//审批通过时间

        String[] split = formCode.split("-");

        String bh = split[0];//采购需求编号/直接采购单编号
        int index = Integer.parseInt(split[1]);//子表索引

        Map updateFormData = new HashMap();
        List<Map> updateDetailList = new ArrayList<>();

        if (formCode.contains("需求")){
            //采购需求&结算
            List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                    .formUuid("FORM-C8C1FBBA781C4C5EBAC487C07BC5A86AD2HO")
                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", bh)))
                    .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();

            String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");

            Map ydFormData = UtilMap.getMap(data.get(0), "formData");

            String type = UtilMap.getString(ydFormData, "radioField_mkkmij3b");

            if ("常规需求".equals(type)){
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
                        Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij5e");//结算成本
                        Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqom6l");//已付款金额
                        String fkzt = UtilMap.getString(detail, "selectField_mmvhqm0p");//付款状态
                        if (yfkje + amt == jscb){
                            detailMap.put("selectField_mmvhqm0p","全部付款");
                        }else if (yfkje + amt < jscb && yfkje + amt > 0  && !"部分退款".equals(fkzt)){
                            detailMap.put("selectField_mmvhqm0p","部分付款");
                        }

                        detailMap.put("numberField_mmvqom6l",yfkje + amt);
                        detailMap.put("dateField_mnh6e4zy",approvedAt);
                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij56",updateDetailList);
            }else {
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
                        Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij6p");//结算成本
                        Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqs9h6");//已付款金额
                        String fkzt = UtilMap.getString(detail, "selectField_mkkmij6a");//付款状态

                        if (yfkje + amt == jscb){
                            detailMap.put("selectField_mkkmij6a","全部付款");
                        }else if (yfkje + amt < jscb && yfkje + amt > 0 && !"部分退款".equals(fkzt)){
                            detailMap.put("selectField_mkkmij6a","部分付款");
                        }

                        detailMap.put("numberField_mmvqs9h6",yfkje + amt);
                        detailMap.put("dateField_mnh6e4zw",approvedAt);
                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij61",updateDetailList);
            }

            Double yzf = UtilMap.getDouble(ydFormData, "numberField_mkf2qumf");//已支付

            updateFormData.put("numberField_mkf2qumf",yzf + amt);//已支付
            updateFormData.put("numberField_mnibjld0",amt);//最新支付金额

            ydClient.operateData(YDParam.builder()
                    .formInstanceId(formInstanceId)
                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                    .useLatestVersion(true)
                    .build(), YDConf.FORM_OPERATION.update);
        }else {
            //直接采购结算单
            List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                    .formUuid("FORM-1AFEDDA034C74F0DB18FA60C941CB56EHUUG")
                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", bh)))
                    .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();

            String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");

            Map ydFormData = UtilMap.getMap(data.get(0), "formData");

            String type = UtilMap.getString(ydFormData, "radioField_mkkmij3b");

            if ("常规采购".equals(type)){
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
                        Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij5e");//结算成本
                        Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqom6k");//已付款金额
                        String fkzt = UtilMap.getString(detail, "selectField_mmvhtdy0");//付款状态

                        if (yfkje + amt == jscb){
                            detailMap.put("selectField_mmvhtdy0","全部付款");
                        }else if (yfkje + amt < jscb && yfkje + amt > 0  && !"部分退款".equals(fkzt)){
                            detailMap.put("selectField_mmvhtdy0","部分付款");
                        }

                        detailMap.put("numberField_mmvqom6k",yfkje + amt);
                        detailMap.put("dateField_mnh6e4zy",approvedAt);
                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij56",updateDetailList);
            }else {
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
                        Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij6p");//结算成本
                        Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqom6l");//已付款金额
                        String fkzt = UtilMap.getString(detail, "selectField_mkkmij6a");//付款状态

                        if (yfkje + amt == jscb){
                            detailMap.put("selectField_mkkmij6a","全部付款");
                        }else if (yfkje + amt < jscb && yfkje + amt > 0 && !"部分退款".equals(fkzt)){
                            detailMap.put("selectField_mkkmij6a","部分付款");
                        }

                        detailMap.put("numberField_mmvqom6l",yfkje + amt);
                        detailMap.put("dateField_mnh6e4zw",approvedAt);
                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij61",updateDetailList);
            }
            Double yzf = UtilMap.getDouble(ydFormData, "numberField_mkf2qumf");//已支付

            updateFormData.put("numberField_mkf2qumf",yzf + amt);//已支付
            updateFormData.put("numberField_mnibjld0",amt);//最新支付金额


            ydClient.operateData(YDParam.builder()
                    .formInstanceId(formInstanceId)
                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                    .useLatestVersion(true)
                    .build(), YDConf.FORM_OPERATION.update);
        }

    }

    //更新宜搭采购已核销金额
    private void updateYdDeduction(String formCode, Double deductionAmount,Double sj) {
        String[] split = formCode.split("-");
        String bh = split[0];
        int index = Integer.parseInt(split[1]);

        Map updateFormData = new HashMap();
        List<Map> updateDetailList = new ArrayList<>();

        if (formCode.contains("需求")){
            //采购需求&结算
            List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                    .formUuid("FORM-C8C1FBBA781C4C5EBAC487C07BC5A86AD2HO")
                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", bh)))
                    .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();

            String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");

            Map ydFormData = UtilMap.getMap(data.get(0), "formData");

            String type = UtilMap.getString(ydFormData, "radioField_mkkmij3b");

            if ("常规需求".equals(type)){
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
                        Double yhxje = UtilMap.getDouble(detail, "numberField_mniatky8");//已核销金额
                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182f");//已退回金额
                        Double mksjsj = UtilMap.getDouble(detail, "numberField_mob8gv4p");//每刻实际税金
                        Double kdksj = UtilMap.getDouble(detail, "numberField_mmsvi56x");//可抵扣税金
                        Double ydcgje = UtilMap.getDouble(detail, "numberField_mkkmij5e");//采购金额

                        detailMap.put("numberField_mniatky8",yhxje + deductionAmount);
                        detailMap.put("numberField_mob8gv4p",mksjsj + sj);//每刻实际税金

                        Double totalSj = UtilMap.getDouble(ydFormData, "numberField_mkkmij6k");//总可抵扣税金

                        if (mksjsj > 0){
                            updateFormData.put("numberField_mkkmij6k",totalSj + sj);//总可抵扣税金
                            updateFormData.put("numberField_mob8gv4v",sj);//最新税金差值
                        }else {
                            updateFormData.put("numberField_mkkmij6k",totalSj - kdksj + sj);//总可抵扣税金
                            updateFormData.put("numberField_mob8gv4v",-kdksj + sj);//最新税金差值
                        }
                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij56",updateDetailList);
            }else {
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
                        Double yhxje = UtilMap.getDouble(detail, "numberField_mniatkya");//已核销金额
                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182g");//已退回金额
                        Double mksjsj = UtilMap.getDouble(detail, "numberField_mob8gv4q");//每刻实际税金
                        Double kdksj = UtilMap.getDouble(detail, "numberField_mn3zekbx");//税金
                        Double ydcgje = UtilMap.getDouble(detail, "numberField_mkkmij6p");//采购金额

                        detailMap.put("numberField_mniatkya",yhxje + deductionAmount);
                        detailMap.put("numberField_mob8gv4q",mksjsj + sj);//每刻实际税金

                        Double totalSj = UtilMap.getDouble(ydFormData, "numberField_mkkmij6k");//总可抵扣税金

                        if (mksjsj > 0){
                            updateFormData.put("numberField_mkkmij6k",totalSj + sj);//总可抵扣税金
                            updateFormData.put("numberField_mob8gv4v",sj);//最新税金差值
                        }else {
                            updateFormData.put("numberField_mkkmij6k",totalSj - kdksj + sj);//总可抵扣税金
                            updateFormData.put("numberField_mob8gv4v",-kdksj + sj);//最新税金差值
                        }
                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij61",updateDetailList);
            }

            ydClient.operateData(YDParam.builder()
                    .formInstanceId(formInstanceId)
                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                    .useLatestVersion(true)
                    .build(), YDConf.FORM_OPERATION.update);
        }else {
            //直接采购结算单
            List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                    .formUuid("FORM-1AFEDDA034C74F0DB18FA60C941CB56EHUUG")
                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", bh)))
                    .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();

            String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");

            Map ydFormData = UtilMap.getMap(data.get(0), "formData");

            String type = UtilMap.getString(ydFormData, "radioField_mkkmij3b");

            if ("常规采购".equals(type)){
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
                        Double yhxje = UtilMap.getDouble(detail, "numberField_mniatky8");//已核销金额
                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182f");//已退回金额
                        Double mksjsj = UtilMap.getDouble(detail, "numberField_mob8gv4p");//每刻实际税金
                        Double kdksj = UtilMap.getDouble(detail, "numberField_mmsvi56x");//可抵扣税金
                        Double ydcgje = UtilMap.getDouble(detail, "numberField_mkkmij5e");//采购金额

                        detailMap.put("numberField_mniatky8",yhxje + deductionAmount);
                        detailMap.put("numberField_mob8gv4p",mksjsj + sj);//每刻实际税金

                        Double totalSj = UtilMap.getDouble(ydFormData, "numberField_mkkmij6k");//总可抵扣税金

                        if (mksjsj > 0){
                            updateFormData.put("numberField_mkkmij6k",totalSj + sj);//总可抵扣税金
                            updateFormData.put("numberField_mob8gv4v",sj);//最新税金差值
                        }else {
                            updateFormData.put("numberField_mkkmij6k",totalSj - kdksj + sj);//总可抵扣税金
                            updateFormData.put("numberField_mob8gv4v",-kdksj + sj);//最新税金差值
                        }

                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij56",updateDetailList);
            }else {
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
                        Double yhxje = UtilMap.getDouble(detail, "numberField_mniatkya");//已核销金额
                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182g");//已退回金额
                        Double mksjsj = UtilMap.getDouble(detail, "numberField_mob8gv4q");//每刻实际税金
                        Double kdksj = UtilMap.getDouble(detail, "numberField_mn3zekbx");//可抵扣税金
                        Double ydcgje = UtilMap.getDouble(detail, "numberField_mkkmij6p");//采购金额

                        detailMap.put("numberField_mniatkya",yhxje + deductionAmount);
                        detailMap.put("numberField_mob8gv4q",mksjsj + sj);//每刻实际税金

                        Double totalSj = UtilMap.getDouble(ydFormData, "numberField_mkkmij6k");//总可抵扣税金

                        if (mksjsj > 0){
                            updateFormData.put("numberField_mkkmij6k",totalSj + sj);//总可抵扣税金
                            updateFormData.put("numberField_mob8gv4v",sj);//最新税金差值
                        }else {
                            updateFormData.put("numberField_mkkmij6k",totalSj - kdksj + sj);//总可抵扣税金
                            updateFormData.put("numberField_mob8gv4v",-kdksj + sj);//最新税金差值
                        }
                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij61",updateDetailList);
            }

            ydClient.operateData(YDParam.builder()
                    .formInstanceId(formInstanceId)
                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                    .useLatestVersion(true)
                    .build(), YDConf.FORM_OPERATION.update);
        }
    }

    @Override
    public McR saveBxReimbursement2(Map map) {
        String formInstId = UtilMap.getString(map, "formInstId");

        Map formData = ydClient.queryData(YDParam.builder()
                .formInstanceId(formInstId)
                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();

        String type = UtilMap.getString(formData, "radioField_mkkmij3b");//需求单类型
        String formSubTypeBizCode = "FT208629766551519240";//项目支付单

        Double amt = UtilMap.getDouble(formData, "numberField_mkkmij6i");

        String empId = "";
        String deptBusinessCode = "";

        String ydfqr = UtilMap.getString(formData, "textField_mmwvodde");//宜搭发起人工号
        String ztcggh = UtilMap.getString(formData, "textField_mmwvfb97");//中台采购工号
        String legalEntityBizCode = UtilMap.getString(formData, "textField_mmd6hio7");//公司抬头编码
        String xqbh = UtilMap.getString(formData, "serialNumberField_mkkmij3o");//需求编号
        long ldjssj = UtilMap.getLong(formData, "dateField_mkdf8q8q");//落地结束时间
        String isFree = "FREE采购".equals(UtilMap.getString(formData, "radioField_mkf2quln")) ? "是" : "否";//是否free
        String isDdf = "是".equals(UtilMap.getString(formData, "radioField_mkf2qulo")) ? "1" : "2";//是否代垫付
        String xmsssyb = UtilMap.getString(formData, "selectField_mkdedkv7");//项目所属事业部
        String projectCode = UtilMap.getString(formData, "textField_mmoh6nvx");//项目编码

        //针对多供应商分期付款拆分多条每刻项目支付单
        if ("常规采购".equals(type)){
            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij56");//常规-采购明细
            for (Map detail : detailList) {
                String uuid = UtilMap.getString(detail, "textField_mmvhqm0q");//子表uuid
                int index = UtilMap.getInt(detail, "numberField_mn36ykxx");//子表uuid

                Map body = new HashMap();
                body.put("formCode",xqbh + "-" + index);//有值时会使用该值作为单据号
                body.put("formSubTypeBizCode",formSubTypeBizCode);//表单类型的业务编号

                String mktdrgh = UtilMap.getString(detail, "textField_mok5mtsh");//每刻提单人工号
                body.put("submittedUserEmployeeId",mktdrgh);//提单人工号
                body.put("coverUserEmployeeId",mktdrgh);//承担人工号

                List<Map> internalTravelPartner = new ArrayList<>();//内部参与人
                internalTravelPartner.add(new HashMap<String,String>(){{put("employeeId",ydfqr);}});
                internalTravelPartner.add(new HashMap<String,String>(){{put("employeeId",ztcggh);}});
                body.put("travelPartnerInfo",new HashMap<String,List<Map>>(){{put("internalTravelPartner",internalTravelPartner);}});//参与人

                //查询宜搭发起人部门
                Map employeeDetails = MkBxUtil.employeeDetails(UtilMap.map("employeeIds", Arrays.asList(ydfqr)));
                String coverDepartmentBizCode = mkbx_deptId;
                if (Objects.nonNull(employeeDetails)){
                    List<Map> departments = UtilMap.getList(employeeDetails, "departments");
                    coverDepartmentBizCode = UtilMap.getString(departments.get(0), "businessCode");
                }
                body.put("coverDepartmentBizCode",coverDepartmentBizCode);//承担部门编码

                body.put("legalEntityBizCode",legalEntityBizCode);//公司抬头编码
                body.put("reimburseName",UtilMap.getString(detail,"textareaField_mkkmij5i"));//报销事由
                body.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmbmohrb"));//往来单位编码

                Map customObject = new HashMap();
                customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",ldjssj);}});//落地结束时间
                customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(detail,"dateField_mkkkw298"));}});//期望支付日期
                customObject.put("CF6",isFree);//free  是；否
                customObject.put("CF5",isDdf);//代垫付  是：1  ；  否：2
                customObject.put("CF2",xmsssyb);//项目所属事业部
                customObject.put("CF1",projectCode);//项目
                customObject.put("CF7",UtilMap.getString(detail,"numberField_mmwswtkv"));//逾期天数

                Map consumeAmount = new HashMap();
                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(detail,"numberField_mkkmij5e")));//结算金额
                consumeAmount.put("currency","CNY");

                customObject.put("CF42",consumeAmount);//采购金额

                body.put("customObject",customObject);

                //报销单费用导入
                Map expenseListItem = new HashMap();

                expenseListItem.put("consumeAmount",consumeAmount);
                expenseListItem.put("corpExpense",true);//是否对公费用，需要填写true
                String gysej = UtilMap.getString(detail, "selectField_mkkkw28y");//供应商二级
                expenseListItem.put("expenseTypeBizCode",UtilMap.getString(detail,"textField_mp0m3ks3"));//费用类型业务编码
                expenseListItem.put("corpType","NO_RECEIPT");//业务场景：ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
                expenseListItem.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额（预付未到票场景必填）
                expenseListItem.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间（预付未到票场景必填）
                expenseListItem.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmbmohrb"));//往来单位业务编码

                Map consumeLocation = new HashMap();
                consumeLocation.put("cityPair",null);
                consumeLocation.put("location","110001");//todo 暂时写死  110001 北京
                expenseListItem.put("consumeLocation",consumeLocation);

                expenseListItem.put("corpExpenseResponsibleEmpIds",Arrays.asList(mktdrgh));//责任人/业务经办人（预付未到票/到票部分支付或不支付 两种场景必填）

                Map body2 = new HashMap();
                body2.put("employeeId",mktdrgh);//需要导入的对应员工的工号
                body2.put("expenseList",Arrays.asList(expenseListItem));

                List<String> expenseCodes = new ArrayList<>();
                try {
                    expenseCodes = MkBxUtil.receiveExpense(body2);
                }catch (Exception e){
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送失败",e.getMessage())))
                            .build(), YDConf.FORM_OPERATION.update);

                    continue;
                }

                body.put("expenseCodes",expenseCodes);//费用类型业务编码

                //收款账户
                Map payeeAccount = new HashMap();
                payeeAccount.put("bankAcctName",UtilMap.getString(detail,"textField_mkkmij6z"));//账户名
                payeeAccount.put("bankAcctNumber",UtilMap.getString(detail,"textField_mkkmij6y"));//银行账户
                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
                payeeAccount.put("accountType","CORP");//收款账户类型：个人（员工）-PERSONAL,公司（往来单位）-CORP
                body.put("payeeAccount",payeeAccount);

                body.put("stagingFlag",true);//暂存标识，默认为false表示不暂存


                Map result = MkBxUtil.receiveReimburse(body);

                if (isTrue(result)){
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送成功","")))
                            .build(), YDConf.FORM_OPERATION.update);
                }else {
                    String message = UtilMap.getString(result, "message");
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送失败",message)))
                            .build(), YDConf.FORM_OPERATION.update);
                }
            }
        }else {
            List<Map> detailList = UtilMap.getList(formData, "tableField_mkkmij61");//free-采购明细

            for (Map detail : detailList) {
                String uuid = UtilMap.getString(detail, "textField_mmvhqm0s");//子表uuid
                int index = UtilMap.getInt(detail, "numberField_mn36ykxz");//子表uuid

                Map body = new HashMap();
                body.put("formCode",xqbh + "-" +index);//有值时会使用该值作为单据号
                body.put("formSubTypeBizCode",formSubTypeBizCode);//表单类型的业务编号

                String mktdrgh = UtilMap.getString(detail, "textField_mok5mtsf");//每刻提单人工号
                body.put("submittedUserEmployeeId",mktdrgh);//提单人工号
                body.put("coverUserEmployeeId",mktdrgh);//承担人工号

                List<Map> internalTravelPartner = new ArrayList<>();//内部参与人
                internalTravelPartner.add(new HashMap<String,String>(){{put("employeeId",ydfqr);}});
                internalTravelPartner.add(new HashMap<String,String>(){{put("employeeId",ztcggh);}});
                body.put("travelPartnerInfo",new HashMap<String,List<Map>>(){{put("internalTravelPartner",internalTravelPartner);}});//参与人

                //查询宜搭发起人部门
                Map employeeDetails = MkBxUtil.employeeDetails(UtilMap.map("employeeIds", Arrays.asList(ydfqr)));
                String coverDepartmentBizCode = mkbx_deptId;
                if (Objects.nonNull(employeeDetails)){
                    List<Map> departments = UtilMap.getList(employeeDetails, "departments");
                    coverDepartmentBizCode = UtilMap.getString(departments.get(0), "businessCode");
                }
                body.put("coverDepartmentBizCode",coverDepartmentBizCode);//承担部门编码


                body.put("reimburseName","FREE-" + UtilMap.getString(detail,"textareaField_mkkmij64"));//报销事由
                body.put("legalEntityBizCode",legalEntityBizCode);//公司抬头编码
                body.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmekbfa2"));//往来单位编码

                Map customObject = new HashMap();
                customObject.put("CF4",new HashMap<String,Long>(){{put("currentTime",ldjssj);}});//落地结束时间
                customObject.put("CF3",new HashMap<String,Long>(){{put("currentTime",UtilMap.getLong(detail,"dateField_mmvhtdy4"));}});//期望支付日期
                customObject.put("CF6",isFree);//free  是；否
                customObject.put("CF5",isDdf);//代垫付  是：1  ；  否：2
                customObject.put("CF2",xmsssyb);//项目所属事业部
                customObject.put("CF1",projectCode);//项目
                customObject.put("CF7",UtilMap.getString(detail,"numberField_mmwswtkx"));//逾期天数

                Map consumeAmount = new HashMap();
                consumeAmount.put("amount",String.format("%.2f", UtilMap.getDouble(detail,"numberField_mkkmij6p")));//结算金额
                consumeAmount.put("currency","CNY");

                customObject.put("CF42",consumeAmount);//采购金额

                body.put("customObject",customObject);

                //报销单费用导入
                Map expenseListItem = new HashMap();

                expenseListItem.put("consumeAmount",consumeAmount);
                expenseListItem.put("corpExpense",true);//是否对公费用，需要填写true
                String gysej = UtilMap.getString(detail, "selectField_mmwuzaql");//供应商二级
                expenseListItem.put("expenseTypeBizCode",UtilMap.getString(detail,"textField_mp0m3ks5"));//费用类型业务编码
                expenseListItem.put("corpType","NO_RECEIPT");//业务场景：ALL_RECEIPTS(全部到票) NO_RECEIPT(预付未到票) RECEIPT_DEDUCTION(到票核销) RECEIPT_PAY_SOME(到票部分支付或不支付) PAY_BEFORE_RECEIPT(支付前期已到的发票)
                expenseListItem.put("nonReceiptAmount",new HashMap<>(consumeAmount));//未到票金额（预付未到票场景必填）
                expenseListItem.put("forecastReceiptDate",System.currentTimeMillis());//预计到票时间（预付未到票场景必填）
                expenseListItem.put("tradingPartnerBizCode",UtilMap.getString(detail,"textField_mmekbfa2"));//往来单位业务编码

                Map consumeLocation = new HashMap();
                consumeLocation.put("cityPair",null);
                consumeLocation.put("location","110001");//todo 暂时写死  110001 北京
                expenseListItem.put("consumeLocation",consumeLocation);

                expenseListItem.put("corpExpenseResponsibleEmpIds",Arrays.asList(mktdrgh));//责任人/业务经办人（预付未到票/到票部分支付或不支付 两种场景必填）

                Map body2 = new HashMap();
                body2.put("employeeId",mktdrgh);//需要导入的对应员工的工号
                body2.put("expenseList",Arrays.asList(expenseListItem));

                List<String> expenseCodes = new ArrayList<>();
                try {
                    expenseCodes = MkBxUtil.receiveExpense(body2);
                }catch (Exception e){
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送失败",e.getMessage())))
                            .build(), YDConf.FORM_OPERATION.update);

                    continue;
                }

                body.put("expenseCodes",expenseCodes);//费用类型业务编码

                //收款账户
                Map payeeAccount = new HashMap();
                payeeAccount.put("bankAcctName",UtilMap.getString(detail,"textField_mketkvxa"));//账户名
                payeeAccount.put("bankAcctNumber",UtilMap.getString(detail,"textField_mketkvxc"));//银行账户
                payeeAccount.put("paymentType","BANK");//账户类型;ALIPAY-支付宝,BANK-银行账户,CASH-现金
                payeeAccount.put("accountType","CORP");//收款账户类型：个人（员工）-PERSONAL,公司（往来单位）-CORP
                body.put("payeeAccount",payeeAccount);

                body.put("stagingFlag",true);//暂存标识，默认为false表示不暂存


                Map result = MkBxUtil.receiveReimburse(body);

                if (isTrue(result)){
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送成功","")))
                            .build(), YDConf.FORM_OPERATION.update);
                }else {
                    String message = UtilMap.getString(result, "message");
                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstId)
                            .updateFormDataJson(JSONObject.toJSONString(UtilMap.map("selectField_mpp9c6w9, textareaField_mpp9c6wa","推送失败",message)))
                            .build(), YDConf.FORM_OPERATION.update);
                }
            }
        }

        return McR.success();
    }



    @Override
    public McR checkBudgetAmt(Map map) {
        String projectCode = UtilMap.getString(map, "projectCode");
        long ldqssj = UtilMap.getLong(map, "ldqssj");//落地起始时间

        //落地起始时间在几月份
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(ldqssj);
        int month = calendar.get(Calendar.MONTH) + 1;

        List<Map> list = UtilMap.getList(map, "list");

        List<String> subjectCodeList = new ArrayList<>();

        Map<String,Double> cgmxMap = new HashMap();
        for (Map map1 : list) {
            Double jscb = UtilMap.getDouble(map1, "numberField_mkkmij5e");//结算成本
            String subjectCode = UtilMap.getString(map1, "textField_mn8nhpnz");//预算科目编号
            subjectCodeList.add(subjectCode);

            if (cgmxMap.containsKey(subjectCode)){
                cgmxMap.put(subjectCode,UtilMap.getDouble(cgmxMap,subjectCode) + jscb);
            }else {
                cgmxMap.put(subjectCode,jscb);
            }
        }
        Map body = new HashMap();
        body.put("budgetPlanBizCode","全面预算");//预算方案编码
        body.put("budgetOrgBizCodes",Arrays.asList(projectCode));//预算组织编码
        body.put("budgetSubjectBizCodes",subjectCodeList);//预算科目编码
        body.put("pageNum",1);
        body.put("pageSize",50);

        List<Map> budgetList = MkBxUtil.budgetInfo(body);
        boolean flag = true;
        StringBuilder errorMsg = new StringBuilder();

        for (Map budget : budgetList) {
            String subjectCode = UtilMap.getString(budget, "subjectBizCode");
            String subjectName = UtilMap.getString(budget, "subjectName");
            List<Map> budgetUnits = UtilMap.getList(budget, "budgetUnits");

            for (Map budgetUnit : budgetUnits) {
                int periodNum = UtilMap.getInt(budgetUnit, "periodNum");

                if (periodNum == month) {
                    Double usableAmount = UtilMap.getDouble(budgetUnit, "usableAmount");

                    Double jscb = cgmxMap.get(subjectCode);
                    if (jscb > usableAmount) {
                        flag = false;
                        errorMsg.append("[").append(subjectName).append("]预算金额不足，剩余可用预算金额[").append(usableAmount).append("];");
                    }

                    break;
                }
            }

        }

        Map result = new HashMap();
        result.put("flag",flag);
        result.put("errorMsg", errorMsg.toString());

        return McR.success(result);
    }

    @Override
    public void updateBudget(Map map) {
        String formInstId = UtilMap.getString(map, "formInstId");
        String type = UtilMap.getString(map, "type");

        Map formData = ydClient.queryData(YDParam.builder()
                .formInstanceId(formInstId).build(), YDConf.FORM_QUERY.retrieve_id).getFormData();

        String projectCode = UtilMap.getString(formData, "textField_mmoh6nvx");

        long ldqssj = UtilMap.getLong(formData, "dateField_mkdf8q8p");

        //落地起始时间在几月份
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(ldqssj);
        int month = calendar.get(Calendar.MONTH) + 1;

        Map body = new HashMap();
        body.put("budgetPlanBizCode","全面预算");
        body.put("increment",false);
        body.put("onlyError",false);

        List<Map> budgets = new ArrayList<>();

        if ("冻结".equals(type)){
            Map budget = new HashMap();
            budget.put("budgetOrgBizCode",projectCode);
//            budget.put("budgetSubjectBizCode","");

            Map budgetUnit = new HashMap();
            budgetUnit.put("periodNum",month);
            budgetUnit.put("budgetAmount",0);//置零 相当于冻结
            budget.put("budgetUnits",Arrays.asList(budgetUnit));

            budgets.add(budget);
        }else {//释放
            Map budget = new HashMap();
            budget.put("budgetOrgBizCode",projectCode);
//            budget.put("budgetSubjectBizCode","");
            Double amt = UtilMap.getDouble(formData, "numberField_mkga10nj");

            Map budgetUnit = new HashMap();
            budgetUnit.put("periodNum",month);
            budgetUnit.put("budgetAmount",amt);
            budget.put("budgetUnits",Arrays.asList(budgetUnit));

            budgets.add(budget);
        }

        body.put("budgets",budgets);
        MkBxUtil.batchBudget(body);

    }

    @Async
    @Override
    public void invoiceWriteBack4(Map map) {
        String formCode = UtilMap.getString(map, "formCode");//付款单编号

        //查询付款单详情
        Map paymentDetailInfo = MkBxUtil.paymentDetailInfo(formCode);

        String reimburseFormSubTypeBizCode = UtilMap.getString(paymentDetailInfo, "reimburseFormSubTypeBizCode");//关联的报销单的单据小类编码

        //项目支付单（对公）
        if ("FT208629766551519240".equals(reimburseFormSubTypeBizCode)){
            String reimburseCode = UtilMap.getString(paymentDetailInfo, "reimburseCode");

            //宜搭推送的项目支付单编号  格式：流水号-index
            if (reimburseCode.contains("采购") || reimburseCode.contains("需求")){
                String[] split = reimburseCode.split("-");

                String ydFormCode = split[0];
                int index = Integer.parseInt(split[1]);

                Map approvedAmount = UtilMap.getMap(paymentDetailInfo, "approvedAmount");
                Double amt = UtilMap.getDouble(approvedAmount, "amount");//审批通过金额

                long settledAt = UtilMap.getLong(paymentDetailInfo, "settledAt");//支付时间

                Map updateFormData = new HashMap();
                List<Map> updateDetailList = new ArrayList<>();

                if (reimburseCode.contains("需求")){
                    //采购需求&结算
                    List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                            .formUuid("FORM-C8C1FBBA781C4C5EBAC487C07BC5A86AD2HO")
                            .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", ydFormCode)))
                            .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();

                    String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");

                    Map ydFormData = UtilMap.getMap(data.get(0), "formData");

                    String type = UtilMap.getString(ydFormData, "radioField_mkkmij3b");

                    if ("常规需求".equals(type)){
                        List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");

                        for (Map detail : detailList) {
                            Map detailMap = new HashMap();
                            if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
                                Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij5e");//结算成本
                                Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqom6l");//已付款金额
                                String fkzt = UtilMap.getString(detail, "selectField_mmvhqm0p");//付款状态
                                if (yfkje + amt == jscb){
                                    detailMap.put("selectField_mmvhqm0p","全部付款");
                                }else if (yfkje + amt < jscb && yfkje + amt > 0  && !"部分退款".equals(fkzt)){
                                    detailMap.put("selectField_mmvhqm0p","部分付款");
                                }

                                detailMap.put("numberField_mmvqom6l",yfkje + amt);
                                detailMap.put("dateField_mnh6e4zy",settledAt);
                            }
                            updateDetailList.add(detailMap);
                        }
                        updateFormData.put("tableField_mkkmij56",updateDetailList);
                    }else {
                        List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");

                        for (Map detail : detailList) {
                            Map detailMap = new HashMap();
                            if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
                                Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij6p");//结算成本
                                Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqs9h6");//已付款金额
                                String fkzt = UtilMap.getString(detail, "selectField_mkkmij6a");//付款状态

                                if (yfkje + amt == jscb){
                                    detail.put("selectField_mkkmij6a","全部付款");
                                }else if (yfkje + amt < jscb && yfkje + amt > 0 && !"部分退款".equals(fkzt)){
                                    detailMap.put("selectField_mkkmij6a","部分付款");
                                }

                                detailMap.put("numberField_mmvqs9h6",yfkje + amt);
                                detailMap.put("dateField_mnh6e4zy",settledAt);
                            }
                            updateDetailList.add(detailMap);
                        }
                        updateFormData.put("tableField_mkkmij61",updateDetailList);
                    }

                    Double yzf = UtilMap.getDouble(ydFormData, "numberField_mkf2qumf");//已支付

                    updateFormData.put("numberField_mkf2qumf",yzf + amt);//已支付
                    updateFormData.put("numberField_mnibjld0",amt);//最新支付金额

                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstanceId)
                            .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                            .build(), YDConf.FORM_OPERATION.update);
                }else {
                    //直接采购结算单
                    List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                            .formUuid("FORM-1AFEDDA034C74F0DB18FA60C941CB56EHUUG")
                            .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", ydFormCode)))
                            .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();

                    String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");

                    Map ydFormData = UtilMap.getMap(data.get(0), "formData");

                    String type = UtilMap.getString(ydFormData, "radioField_mkkmij3b");

                    if ("常规采购".equals(type)){
                        List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");

                        for (Map detail : detailList) {
                            Map detailMap = new HashMap();
                            if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
                                Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij5e");//结算成本
                                Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqom6k");//已付款金额
                                String fkzt = UtilMap.getString(detail, "selectField_mmvhtdy0");//付款状态
                                if (yfkje + amt == jscb){
                                    detailMap.put("selectField_mmvhtdy0","全部付款");
                                }else if (yfkje + amt < jscb && yfkje + amt > 0  && !"部分退款".equals(fkzt)){
                                    detailMap.put("selectField_mmvhtdy0","部分付款");
                                }

                                detailMap.put("numberField_mmvqom6k",yfkje + amt);
                                detailMap.put("dateField_mnh6e4zy",settledAt);
                            }
                            updateDetailList.add(detailMap);
                        }
                        updateFormData.put("tableField_mkkmij56",updateDetailList);
                    }else {
                        List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");

                        for (Map detail : detailList) {
                            Map detailMap = new HashMap();
                            if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
                                Double jscb = UtilMap.getDouble(detail, "numberField_mkkmij6p");//结算成本
                                Double yfkje = UtilMap.getDouble(detail, "numberField_mmvqom6l");//已付款金额
                                String fkzt = UtilMap.getString(detail, "selectField_mkkmij6a");//付款状态

                                if (yfkje + amt == jscb){
                                    detailMap.put("selectField_mkkmij6a","全部付款");
                                }else if (yfkje + amt < jscb && yfkje + amt > 0 && !"部分退款".equals(fkzt)){
                                    detailMap.put("selectField_mkkmij6a","部分付款");
                                }

                                detailMap.put("numberField_mmvqom6l",yfkje + amt);
                                detailMap.put("dateField_mnh6e4zy",settledAt);
                            }
                            updateDetailList.add(detailMap);
                        }
                        updateFormData.put("tableField_mkkmij61",updateDetailList);
                    }

                    Double yzf = UtilMap.getDouble(ydFormData, "numberField_mkf2qumf");//已支付

                    updateFormData.put("numberField_mkf2qumf",yzf + amt);//已支付
                    updateFormData.put("numberField_mnibjld0",amt);//最新支付金额

                    ydClient.operateData(YDParam.builder()
                            .formInstanceId(formInstanceId)
                            .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                            .build(), YDConf.FORM_OPERATION.update);
                }
            }
        }
    }

    @Async
    @Override
    public void invoiceWriteBack5(Map map) {
        //防止查询不到单据详情
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        String formCode = UtilMap.getString(map, "formCode");

        Map repayDetailInfo = MkBxUtil.repayDetailInfo(formCode);

        Map repayAmount = UtilMap.getMap(repayDetailInfo, "repayAmount");

        Double amount = UtilMap.getDouble(repayAmount, "amount");//还款金额

        List<Map> returnDeductions = UtilMap.getList(repayDetailInfo, "returnDeductions");

        for (Map returnDeduction : returnDeductions) {
            String recordFormCode = UtilMap.getString(returnDeduction, "recordFormCode");

            if (recordFormCode.contains("采购") || recordFormCode.contains("需求")){
                updateYdRepay(recordFormCode,amount);
            }

        }
    }

    @Async
    @Override
    public void invoiceWriteBack6(Map map) {
        String formCode = UtilMap.getString(map, "formCode");//单据号

        Map formData = UtilMap.getMap(map, "formData");

        String formSubTypeBizCode = getMkStrValue(formData, "formSubTypeBizCode");//单据类型业务编码

        Map ydFormData = new HashMap();

        switch (formSubTypeBizCode){
            case "FT210319434976347227"://押金/保证金支付单
                String isProject = getMkStrValue(formData, "CF32");//是否项目相关

                if (!"是".equals(isProject)) return;

                String loanName = getMkStrValue(formData, "loanName");//事由
                double payableAmount = Double.parseDouble(getMkStrValue(formData, "payableAmount"));//借款金额
                String legalEntity = getMkStrValue(formData, "legalEntity");//所属公司

                Map loanUser = getMkListValue(formData, "loanUser").get(0);//借款人
                String employeeName = UtilMap.getString(loanUser, "text");//借款人姓名
                List<String> loanDdUser = getDdUserId(employeeName);

                Map cf0 = getMkMapValue(formData, "CF0");
                String projectCode = UtilMap.getString(cf0, "businessCode");//项目流水号
                String projectName = UtilMap.getString(cf0, "text");//项目名称

                Long expectRepayDate = getMkDateValue(formData, "expectRepayDate");//预计归还时间

                String loanDepartment = getMkStrValue(formData, "loanDepartment");//借款部门

                Map payeeAccount = getMkMapValue(formData, "payeeAccount");
                String bankAcctNumber = UtilMap.getString(payeeAccount, "bankAcctNumber");//收款账户

                ydFormData.put("textField_mnsm4ozj",legalEntity);
                ydFormData.put("textField_mnsm4p09",projectName);
                ydFormData.put("textField_mnsm4ozk",formCode);
                ydFormData.put("textareaField_mnsm4ozp",loanName);
                ydFormData.put("employeeField_mnsm4ozu",loanDdUser);
                ydFormData.put("textField_mnsm4ozv",loanDepartment);
                ydFormData.put("numberField_mnsm4p00",payableAmount);
                ydFormData.put("dateField_mnsm4p01",expectRepayDate);
                ydFormData.put("textField_mnsm4p07",bankAcctNumber);
                ydFormData.put("textField_mnwtck7h","押金/保证金支付单");
                ydFormData.put("textField_mnwtwu9z",projectCode);
                break;
            case "FT203800208910336098"://借款单（项目）
                String loanName2 = getMkStrValue(formData, "loanName");//事由
                double payableAmount2 = Double.parseDouble(getMkStrValue(formData, "payableAmount"));//借款金额
                String legalEntity2 = getMkStrValue(formData, "legalEntity");//所属公司

                Map loanUser2 = getMkListValue(formData, "loanUser").get(0);//借款人
                String employeeName2 = UtilMap.getString(loanUser2, "text");//借款人姓名
                List<String> loanDdUser2 = getDdUserId(employeeName2);

                Map cf0_2 = getMkMapValue(formData, "CF0");
                String projectCode2 = UtilMap.getString(cf0_2, "businessCode");//项目流水号
                String projectName2 = UtilMap.getString(cf0_2, "text");//项目名称

                Long expectRepayDate2 = getMkDateValue(formData, "expectRepayDate");//预计归还时间

                String loanDepartment2 = getMkStrValue(formData, "loanDepartment");//借款部门

                Map payeeAccount2 = getMkMapValue(formData, "payeeAccount");
                String bankAcctNumber2 = UtilMap.getString(payeeAccount2, "bankAcctNumber");//收款账户

                String comments = getMkStrValue(formData, "comments");//备用金用途

                ydFormData.put("textField_mnsm4ozj",legalEntity2);
                ydFormData.put("textField_mnsm4p09",projectName2);
                ydFormData.put("textField_mnsm4ozk",formCode);
                ydFormData.put("textareaField_mnsm4ozp",loanName2);
                ydFormData.put("employeeField_mnsm4ozu",loanDdUser2);
                ydFormData.put("textField_mnsm4ozv",loanDepartment2);
                ydFormData.put("numberField_mnsm4p00",payableAmount2);
                ydFormData.put("dateField_mnsm4p01",expectRepayDate2);
                ydFormData.put("textField_mnsm4p07",bankAcctNumber2);
                ydFormData.put("textField_mnwtck7h","借款单（项目）");
                ydFormData.put("textField_mnwtwu9z",projectCode2);
                ydFormData.put("textareaField_mnsm4p0c",comments);
                break;
            default:
                return;
        }



        ydClient.operateData(YDParam.builder()
                .formUuid("FORM-204D3E39C2EB49FEA4121D73E8A71F796A2U")
                .formDataJson(JSONObject.toJSONString(ydFormData))
                .build(), YDConf.FORM_OPERATION.create);


    }

    @Async
    @Override
    public void invoiceWriteBack7(Map map) {
        String formDataCode = UtilMap.getString(map, "formDataCode");//单据类型
        String formCode = UtilMap.getString(map, "formCode");//单据号

        Map formData = UtilMap.getMap(map, "formData");

        String repaymentName = getMkStrValue(formData, "repaymentName");//事由
        double repayAmount = Double.parseDouble(getMkStrValue(formData, "repayAmount"));//还款金额
        String legalEntity = getMkStrValue(formData, "legalEntity");//所属公司

        Map repayUser = getMkListValue(formData, "repayUser").get(0);//责任人
        String employeeName = UtilMap.getString(repayUser, "text");//责任人姓名
        List<String> repayDdUser = getDdUserId(employeeName);

//        Long repaymentDate = getMkDateValue(formData, "repaymentDate");//还款日期

        String repayDept = getMkStrValue(formData, "repayDept");//责任人部门

        String comments = getMkStrValue(formData, "comments");//备注

        List<Map> loanDeductionList = getMkListValue(formData, "loanDeductionList");//核销借款

        List<Map> ydLoanDeductionList = new ArrayList<>();

        for (Map loanDeduction : loanDeductionList) {
            Map ydLoanDeduction = new HashMap();

            Double deductionAmount = UtilMap.getDouble(loanDeduction, "deductionAmount");//核销金额
            String loanFormCode = UtilMap.getString(loanDeduction, "loanFormCode");//借款单单据号

            //借款单详情
            Map loanDetailInfo = MkBxUtil.loanDetailInfo(loanFormCode);
            Map customObject = UtilMap.getMap(loanDetailInfo, "customObject");

            Map cf0 = UtilMap.getMap(customObject, "CF0");
            String projectCode = UtilMap.getString(cf0, "detailBusinessCode");//项目流水号
            String projectName = UtilMap.getString(cf0, "text");//项目名称

            String loanName = UtilMap.getString(loanDetailInfo, "loanName");//事由

            ydLoanDeduction.put("textField_mnsmfo6t",loanName);
            ydLoanDeduction.put("textField_mnxzo8la",loanFormCode);
            ydLoanDeduction.put("textField_mnwlnnmz",projectName);
            ydLoanDeduction.put("textField_mnwtwu9z",projectCode);
            ydLoanDeduction.put("numberField_mnxzo8l8",deductionAmount);

            ydLoanDeductionList.add(ydLoanDeduction);
        }

        Map ydFormData = new HashMap();
        ydFormData.put("textField_mnsmfo6f",legalEntity);

        ydFormData.put("textField_mnxzo8l5",formCode);
        ydFormData.put("textareaField_mnsmfo6k",repaymentName);
        ydFormData.put("employeeField_mnsmfo6l",repayDdUser);
        ydFormData.put("textField_mnsmfo6m",repayDept);
        ydFormData.put("numberField_mnsmfo6s",repayAmount);
        ydFormData.put("textareaField_mnsmfo70",comments);
        ydFormData.put("textField_mnwtck7h","还款/退款单");
        ydFormData.put("tableField_mnxzo8l6",ydLoanDeductionList);

        ydClient.operateData(YDParam.builder()
                .formUuid("FORM-D8589EE237894F4E9FF9B1A0D4BDCABFKNYM")
                .formDataJson(JSONObject.toJSONString(ydFormData))
                .build(), YDConf.FORM_OPERATION.create);

    }

    @Async
    @Override
    public void invoiceWriteBack8(Map map) {
        String formCode = UtilMap.getString(map, "formCode");//单据号

        Map formData = UtilMap.getMap(map, "formData");

        String formSubTypeBizCode = getMkStrValue(formData, "formSubTypeBizCode");//单据类型业务编码

        Map ydFormData = new HashMap();

        switch (formSubTypeBizCode){
            case "FT204655110165381205"://项目报销单(个人)
                String reimburseName = getMkStrValue(formData, "reimburseName");//事由
                String legalEntity = getMkStrValue(formData, "legalEntity");//公司抬头

                Map coverUser = getMkListValue(formData, "coverUser").get(0);//承担人
                String coverUserName = UtilMap.getString(coverUser, "text");//承担人姓名
                List<String> coverDdUser = getDdUserId(coverUserName);//承担人钉钉id

                String coverDepartment = getMkStrValue(formData, "coverDepartment");//承担部门

                Map cf0 = getMkMapValue(formData, "CF0");
                String projectCode = UtilMap.getString(cf0, "businessCode");//项目流水号
                String projectName = UtilMap.getString(cf0, "text");//项目名称

                String cf31 = getMkStrValue(formData, "CF31");//代垫付

                Map payeeAccount = getMkMapValue(formData, "payeeAccount");
                String bankAcctNumber = UtilMap.getString(payeeAccount, "bankAcctNumber");//收款账户

                List<Map> expenseList = getMkListValue(formData, "expenseList");

                List<Map> ydExpenseList = new ArrayList<>();

                double totalAmt = 0d;
                double totalTaxAmt = 0d;

                for (Map expense : expenseList) {
                    String expenseType = getMkStrValue(expense, "expenseTypeCode");//费用类型
                    double acceptAmount = Double.parseDouble(getMkStrValue(expense, "acceptAmount"));//收款金额
                    String comments = getMkStrValue(expense, "comments");//用途
                    long consumeTime = getMkDateValue(expense, "consumeTime");//消费日期

                    List<Map> invoiceTaxList = getMkListValue(expense, "invoiceTaxList");//税票信息
                    double deductionTaxAmount = 0;
                    for (Map invoiceTax : invoiceTaxList) {
                        deductionTaxAmount += Double.parseDouble(getMkStrValue(invoiceTax, "deductionTaxAmount"));//抵扣税额
                    }

                    Map expenseMap = new HashMap();
                    expenseMap.put("textField_mnwlpiwc",expenseType);
                    expenseMap.put("numberField_mnwlpiwd",acceptAmount);
                    expenseMap.put("textareaField_mnwlpiwh",comments);
                    expenseMap.put("dateField_mnwlpiwe",consumeTime);
                    expenseMap.put("numberField_mol7a35x",deductionTaxAmount);

                    ydExpenseList.add(expenseMap);

                    totalAmt += acceptAmount;
                    totalTaxAmt += deductionTaxAmount;
                }

                ydFormData.put("textField_mnyfvfxr",formCode);
                ydFormData.put("textField_mnwtck7h","项目报销单(个人)");
                ydFormData.put("textField_mnwtwu9z",projectCode);
                ydFormData.put("textField_mnwlpivn",projectName);
                ydFormData.put("textareaField_mnwlpivb",reimburseName);
                ydFormData.put("textField_mnwlpivg",legalEntity);
                ydFormData.put("textField_mnwlpivi",coverDepartment);
                ydFormData.put("employeeField_mnwlpivh",coverDdUser);
                ydFormData.put("textField_mnwlpiw6",bankAcctNumber);
                ydFormData.put("textField_mnwlpivq",cf31);
                ydFormData.put("tableField_mnwlpiwb",ydExpenseList);
                ydFormData.put("numberField_mo007gcg",totalAmt);
                ydFormData.put("numberField_mowkibv8",totalTaxAmt);

                break;
            case "FT212801282906280987"://打车(企业支付)
                String cf36 = getMkStrValue(formData, "CF36");//是否有项目

                if (!"是".equals(cf36)) return;

                String reimburseName2 = getMkStrValue(formData, "reimburseName");//事由
                String legalEntity2 = getMkStrValue(formData, "legalEntity");//公司抬头

                Map coverUser2 = getMkListValue(formData, "coverUser").get(0);//承担人
                String coverUserName2 = UtilMap.getString(coverUser2, "text");//承担人姓名
                List<String> coverDdUser2 = getDdUserId(coverUserName2);//承担人钉钉id

                String coverDepartment2 = getMkStrValue(formData, "coverDepartment");//承担部门

                Map cf0_2 = getMkMapValue(formData, "CF0");
                String projectCode2 = UtilMap.getString(cf0_2, "businessCode");//项目流水号
                String projectName2 = UtilMap.getString(cf0_2, "text");//项目名称

                String cf31_2 = getMkStrValue(formData, "CF31");//代垫付

                Map payeeAccount2 = getMkMapValue(formData, "payeeAccount");
                String bankAcctNumber2 = UtilMap.getString(payeeAccount2, "bankAcctNumber");//收款账户

                List<Map> expenseList2 = getMkListValue(formData, "expenseList");

                List<Map> ydExpenseList2 = new ArrayList<>();

                double totalAmt2 = 0d;
                double totalTaxAmt2 = 0d;

                for (Map expense : expenseList2) {
                    String expenseType = getMkStrValue(expense, "expenseTypeCode");//费用类型
                    double acceptAmount = Double.parseDouble(getMkStrValue(expense, "acceptAmount"));//收款金额
                    String comments = getMkStrValue(expense, "comments");//用途
                    long consumeTime = getMkDateValue(expense, "consumeTime");//消费日期

                    List<Map> invoiceTaxList = getMkListValue(expense, "invoiceTaxList");//税票信息
                    double deductionTaxAmount = 0;
                    for (Map invoiceTax : invoiceTaxList) {
                        deductionTaxAmount += Double.parseDouble(getMkStrValue(invoiceTax, "deductionTaxAmount"));//抵扣税额
                    }

                    Map expenseMap = new HashMap();
                    expenseMap.put("textField_mnwlpiwc",expenseType);
                    expenseMap.put("numberField_mnwlpiwd",acceptAmount);
                    expenseMap.put("textareaField_mnwlpiwh",comments);
                    expenseMap.put("dateField_mnwlpiwe",consumeTime);
                    expenseMap.put("numberField_mol7a35x",deductionTaxAmount);

                    ydExpenseList2.add(expenseMap);

                    totalAmt2 += acceptAmount;
                    totalTaxAmt2 += deductionTaxAmount;
                }

                ydFormData.put("textField_mnyfvfxr",formCode);
                ydFormData.put("textField_mnwtck7h","打车(企业支付)");
                ydFormData.put("textField_mnwtwu9z",projectCode2);
                ydFormData.put("textField_mnwlpivn",projectName2);
                ydFormData.put("textareaField_mnwlpivb",reimburseName2);
                ydFormData.put("textField_mnwlpivg",legalEntity2);
                ydFormData.put("textField_mnwlpivi",coverDepartment2);
                ydFormData.put("employeeField_mnwlpivh",coverDdUser2);
                ydFormData.put("textField_mnwlpiw6",bankAcctNumber2);
                ydFormData.put("textField_mnwlpivq",cf31_2);
                ydFormData.put("tableField_mnwlpiwb",ydExpenseList2);
                ydFormData.put("numberField_mo007gcg",totalAmt2);
                ydFormData.put("numberField_mowkibv8",totalTaxAmt2);

                break;
            case "FT204524106635297811"://项目差旅报销单
                String reimburseName3 = getMkStrValue(formData, "reimburseName");//事由
                String legalEntity3 = getMkStrValue(formData, "legalEntity");//公司抬头

                Map coverUser3 = getMkListValue(formData, "coverUser").get(0);//承担人
                String coverUserName3 = UtilMap.getString(coverUser3, "text");//承担人姓名
                List<String> coverDdUser3 = getDdUserId(coverUserName3);//承担人钉钉id

                String coverDepartment3 = getMkStrValue(formData, "coverDepartment");//承担部门

                Map cf0_3 = getMkMapValue(formData, "CF0");
                String projectCode3 = UtilMap.getString(cf0_3, "businessCode");//项目流水号
                String projectName3 = UtilMap.getString(cf0_3, "text");//项目名称

                String cf31_3 = getMkStrValue(formData, "CF31");//代垫付

                Map payeeAccount3 = getMkMapValue(formData, "payeeAccount");
                String bankAcctNumber3 = UtilMap.getString(payeeAccount3, "bankAcctNumber");//收款账户

                List<Map> expenseList3 = getMkListValue(formData, "expenseList");

                List<Map> ydExpenseList3 = new ArrayList<>();

                double totalAmt3 = 0d;
                double totalTaxAmt3 = 0d;

                for (Map expense : expenseList3) {
                    String expenseType = getMkStrValue(expense, "expenseTypeCode");//费用类型
                    double acceptAmount = Double.parseDouble(getMkStrValue(expense, "acceptAmount"));//收款金额
                    String comments = getMkStrValue(expense, "comments");//用途
                    long consumeTime = getMkDateValue(expense, "consumeTime");//消费日期

                    List<Map> invoiceTaxList = getMkListValue(expense, "invoiceTaxList");//税票信息
                    double deductionTaxAmount = 0;
                    for (Map invoiceTax : invoiceTaxList) {
                        deductionTaxAmount += Double.parseDouble(getMkStrValue(invoiceTax, "deductionTaxAmount"));//抵扣税额
                    }

                    Map expenseMap = new HashMap();
                    expenseMap.put("textField_mnwlpiwc",expenseType);
                    expenseMap.put("numberField_mnwlpiwd",acceptAmount);
                    expenseMap.put("textareaField_mnwlpiwh",comments);
                    expenseMap.put("dateField_mnwlpiwe",consumeTime);
                    expenseMap.put("numberField_mol7a35x",deductionTaxAmount);

                    ydExpenseList3.add(expenseMap);

                    totalAmt3 += acceptAmount;
                    totalTaxAmt3 += deductionTaxAmount;
                }

                ydFormData.put("textField_mnyfvfxr",formCode);
                ydFormData.put("textField_mnwtck7h","项目差旅报销单");
                ydFormData.put("textField_mnwtwu9z",projectCode3);
                ydFormData.put("textField_mnwlpivn",projectName3);
                ydFormData.put("textareaField_mnwlpivb",reimburseName3);
                ydFormData.put("textField_mnwlpivg",legalEntity3);
                ydFormData.put("textField_mnwlpivi",coverDepartment3);
                ydFormData.put("employeeField_mnwlpivh",coverDdUser3);
                ydFormData.put("textField_mnwlpiw6",bankAcctNumber3);
                ydFormData.put("textField_mnwlpivq",cf31_3);
                ydFormData.put("tableField_mnwlpiwb",ydExpenseList3);
                ydFormData.put("numberField_mo007gcg",totalAmt3);
                ydFormData.put("numberField_mowkibv8",totalTaxAmt3);

                break;
            default:
                return;
        }

        ydClient.operateData(YDParam.builder()
                .formUuid("FORM-4F0DF576764A472AA6CF4AC0E26061559AR4")
                .formDataJson(JSONObject.toJSONString(ydFormData))
                .build(), YDConf.FORM_OPERATION.create);
    }

    @Override
    public McR saveRepayment(Map map) {
        String formInstId = UtilMap.getString(map, "formInstId");

        Map formData = ydClient.queryData(YDParam.builder()
                .formInstanceId(formInstId)
                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();

        String thbh = UtilMap.getString(formData, "serialNumberField_mkkmij3o");//退回编号

        String type = UtilMap.getString(formData, "radioField_mkkmij3b");
        String ssgssh = UtilMap.getString(formData, "textField_mmd6hio7");//所属公司税号

        String sqrgh = UtilMap.getString(formData, "textField_mmwvodde");//申请人工号

        Map employeeDetails = MkBxUtil.employeeDetails(UtilMap.map("employeeIds", Arrays.asList(sqrgh)));
        String deptBusinessCode = "";
        String empId = "";
        if (Objects.nonNull(employeeDetails)){
            List<Map> departments = UtilMap.getList(employeeDetails, "departments");
            deptBusinessCode = UtilMap.getString(departments.get(0), "businessCode");

            empId = sqrgh;
        }else {
            empId = mkbx_empId;
            deptBusinessCode = mkbx_deptId;
        }

        if ("直接采购".equals(type)){
            String cgbh = UtilMap.getString(formData, "textField_mn4fwdj5");//采购编号

            List<Map> cgmxList = UtilMap.getList(formData, "tableField_mkkmij56");

            for (Map cgmx : cgmxList) {
                Double amt = UtilMap.getDouble(cgmx, "numberField_mn2wqvpp");//退回金额
                if (amt == 0) continue;

                int index = UtilMap.getInt(cgmx, "numberField_mn36ykxx");//索引
                String thsy = UtilMap.getString(cgmx, "textareaField_mo2k0ien");//退回事由
                String gysbh = UtilMap.getString(cgmx, "textField_mmbmohrb");//供应商编号

                Map reimburseDetailInfo = MkBxUtil.reimburseDetailInfo(cgbh + "-" + index);

                Map expense = ((List<Map>) UtilMap.getList(reimburseDetailInfo, "expenseList")).get(0);

                String expenseCode = UtilMap.getString(expense, "code");//费用编码

                Map noReceiptReturn = new HashMap();
                noReceiptReturn.put("recordExpenseCode",expenseCode);
                noReceiptReturn.put("recordDeductionAmount",new HashMap<String,Object>(){{put("currency","CNY");put("amount",amt);}});

                Map body = new HashMap();
                body.put("formCode",thbh + index);
                body.put("repaymentName",thsy);
                body.put("formSubTypeBizCode","FT212654855978767371");
                body.put("submittedUserEmployeeId",empId);
                body.put("coverEmployeeId",empId);
                body.put("departmentBizCode",deptBusinessCode);
                body.put("legalEntityBizCode",ssgssh);
                body.put("repayAmount",new HashMap<String,Object>(){{put("currency","CNY");put("amount",amt);}});
                body.put("repaymentDate",System.currentTimeMillis());
                body.put("tradingPartnerBizCode",gysbh);
                body.put("paymentType","BANK");
                body.put("noReceiptReturnList",Arrays.asList(noReceiptReturn));
                body.put("stagingFlag",false);

                MkBxUtil.receiveRepayment(body);
            }

        }else {//需求采购
            String xqbh = UtilMap.getString(formData, "textField_mn4fwdj4");//需求编号

            List<Map> cgmxList = UtilMap.getList(formData, "tableField_mn2xmq2b");

            for (Map cgmx : cgmxList) {
                Double amt = UtilMap.getDouble(cgmx, "numberField_mn2xmq1p");//退回金额
                if (amt == 0) continue;

                int index = UtilMap.getInt(cgmx, "numberField_mn39fdfe");//索引
                String thsy = UtilMap.getString(cgmx, "textareaField_mo2k0iep");//退回事由
                String gysbh = UtilMap.getString(cgmx, "textField_mn2xmq27");//供应商编号

                Map reimburseDetailInfo = MkBxUtil.reimburseDetailInfo(xqbh + "-" + index);

                Map expense = ((List<Map>) UtilMap.getList(reimburseDetailInfo, "expenseList")).get(0);

                String expenseCode = UtilMap.getString(expense, "code");//费用编码

                Map noReceiptReturn = new HashMap();
                noReceiptReturn.put("recordExpenseCode",expenseCode);
                noReceiptReturn.put("recordDeductionAmount",new HashMap<String,Object>(){{put("currency","CNY");put("amount",amt);}});

                Map body = new HashMap();
                body.put("formCode",thbh + index);
                body.put("repaymentName",thsy);
                body.put("formSubTypeBizCode","FT212654855978767371");
                body.put("submittedUserEmployeeId",empId);
                body.put("coverEmployeeId",empId);
                body.put("departmentBizCode",deptBusinessCode);
                body.put("legalEntityBizCode",ssgssh);
                body.put("repayAmount",new HashMap<String,Object>(){{put("currency","CNY");put("amount",amt);}});
                body.put("repaymentDate",System.currentTimeMillis());
                body.put("tradingPartnerBizCode",gysbh);
                body.put("paymentType","BANK");
                body.put("noReceiptReturnList",Arrays.asList(noReceiptReturn));
                body.put("stagingFlag",false);

                MkBxUtil.receiveRepayment(body);
            }
        }

        return McR.success();
    }

    @Async
    @Override
    public void invoiceWriteBack9(Map map) {
        Map calloutParams = UtilMap.getMap(map, "calloutParams");
        String serviceType = UtilMap.getString(calloutParams, "serviceType");
        Map bizData = UtilMap.getMap(calloutParams, "bizData");

        if ("RECEIVABLE_AR_COMPLETED_NOTIFY_AR".equals(serviceType)){
            List<Map> invoiceList = UtilMap.getList(bizData, "invoiceList");

            Map invoiceMap = invoiceList.get(0);

            String invoiceNumber = UtilMap.getString(invoiceMap, "invoiceNumber");//发票号码
            long formDate = UtilMap.getLong(invoiceMap, "formDate");//开票日期

            String invoiceApplicationBizCode = ((List<String>)UtilMap.getList(bizData, "invoiceApplicationBizCodes")).get(0);//开票申请单编号

            Map updateFormData = new HashMap();
            updateFormData.put("radioField_mkxripcc","开票成功");
            updateFormData.put("textField_mkxripc6",invoiceNumber);
            updateFormData.put("dateField_mnfpbwpd",formDate);
            updateFormData.put("textareaField_mmlzqvn0","");

            //发票下载信息查询
            Map invoiceInfo = MkYpUtil.getInvoiceInfo(invoiceNumber);

            if (Objects.nonNull(invoiceInfo)){
                String pdfUrl = UtilMap.getString(invoiceInfo, "pdfUrl");//发票下载地址
                String downloadPageUrl = UtilMap.getString(invoiceInfo, "downloadPageUrl");//发票下载页面地址

                if (Strings.isNotBlank(pdfUrl)){
                    String fileName = invoiceNumber + ".pdf";
                    String downloadPath = downloadFilePath + fileName;
                    downloadFile(pdfUrl,downloadPath);//下载pdf发票

                    String downloadUri = downloadUrl + "files/" + fileName + "?option=download";
                    String previewUri = downloadUrl + "files/" + fileName + "?option=preview";

                    Map attachmentField = new HashMap();
                    attachmentField.put("downloadUrl",downloadUri);
                    attachmentField.put("name",fileName);
                    attachmentField.put("previewUrl",previewUri);
                    attachmentField.put("url",downloadUri);
                    attachmentField.put("ext","pdf");
                    updateFormData.put("attachmentField_mkxripc5",Arrays.asList(attachmentField));
                }

                if (Strings.isNotBlank(downloadPageUrl)){
                    updateFormData.put("textField_mm3aixk0",downloadPageUrl);
                }
            }

            //回写宜搭
            Map data = ((List<Map>)ydClient.queryData(YDParam.builder()
                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mknspz75",invoiceApplicationBizCode)))
                    .formUuid("FORM-A9A47B0365DB437F8F4C8E01B4468220K7GU")
                    .build(), YDConf.FORM_QUERY.retrieve_list).getData()).get(0);

            String formInstanceId = UtilMap.getString(data, "formInstanceId");

            ydClient.operateData(YDParam.builder()
                    .formInstanceId(formInstanceId)
                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                    .build(), YDConf.FORM_OPERATION.update);
        }
    }

    @Override
    public McR ddProject(Map map) {
        String formInstId = UtilMap.getString(map, "formInstId");
        String type = UtilMap.getString(map, "type");

        Map formData = ydClient.queryData(YDParam.builder()
                .formInstanceId(formInstId)
                .build(), YDConf.FORM_QUERY.retrieve_id).getFormData();

        String projectCode = UtilMap.getString(formData, "serialNumberField_mknemyna");//项目流水号
        String projectName = UtilMap.getString(formData, "textField_mkdedkvu");//项目名称
        String projectProgress = UtilMap.getString(formData, "selectField_mkdf8q80");//项目进度
        String projectManager = UtilMap.getString(formData, "textField_mo8lkotd");//项目负责人工号
        List<String> projectMember = UtilMap.getList(formData, "multiSelectField_mo9iilfl");//项目成员工号
        String ztcg = UtilMap.getString(formData, "textField_mo9iilfm");//中台采购工号

        List<String> leader_employee_id = new ArrayList<>();
        leader_employee_id.add(projectManager);//第一个为主负责人，后续为其他负责人
        leader_employee_id.addAll(projectMember);
        leader_employee_id.add(ztcg);
        //leader_employee_id去重
        leader_employee_id = leader_employee_id.stream().distinct().collect(Collectors.toList());

        String htqygssh = UtilMap.getString(formData, "textField_mo9nav1d");//合同签约公司税号

        if ("add".equals(type)){//新增
            String startDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());//项目开始时间
            //当前时间+一年半
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.YEAR, 1);
            calendar.add(Calendar.MONTH, 6);
            String endDate = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());//项目结束时间

            Map body = new HashMap();
            body.put("out_budget_id",projectCode);
            body.put("name",projectName);
            body.put("type",2);
            body.put("budget_cycle",0);
            body.put("total_quota",0);
            body.put("member_used",1);//0 ：全员可见 1：项目成员可见 2：公司主体可见
            body.put("legal_entity_id",ddLegalEntity.get(htqygssh));//项目所属公司主体ID
            body.put("start_date",startDate);
            body.put("expiry_date",endDate);
            body.put("leader_employee_id",JSONObject.toJSONString(leader_employee_id));

            Map result = QyddUtil.BudgetCenterAdd(body);

            return McR.success(result);
        }else if ("update".equals(type)){//更新
            Map body = new HashMap();
            body.put("out_budget_id",projectCode);
            body.put("name",projectName);
            body.put("type",2);
            body.put("member_used",1);//0 ：全员可见 1：项目成员可见 2：公司主体可见
            body.put("legal_entity_id",ddLegalEntity.get(htqygssh));//项目所属公司主体ID
            body.put("leader_employee_id",JSONObject.toJSONString(leader_employee_id));

            Map result = QyddUtil.BudgetCenterEdit(body);

            return McR.success(result);
        }else{//封账
            Map body = new HashMap();
            body.put("out_budget_id",projectCode);
            body.put("name",projectName);
            body.put("type",2);
            body.put("expiry_date",new SimpleDateFormat("yyyy-MM-dd").format(new Date()));//项目结束时间  封账时间

            Map result = QyddUtil.BudgetCenterEdit(body);

            return McR.success(result);
        }
    }

    private static String getMkStrValue(Map formData, String entityName) {
        Map title = UtilMap.getMap(formData, entityName);
        Map value = UtilMap.getMap(title, "value");
        String text = UtilMap.getString(value, "text");

        return text;
    }

    private static Map getMkMapValue(Map formData, String entityName) {
        Map title = UtilMap.getMap(formData, entityName);
        Map value = UtilMap.getMap(title, "value");

        return value;
    }

    private static List<Map> getMkListValue(Map formData, String entityName) {
        Map title = UtilMap.getMap(formData, entityName);
        List<Map> value = UtilMap.getList(title, "value");

        return value;
    }

    private static Long getMkDateValue(Map formData, String entityName) {
        Map title = UtilMap.getMap(formData, entityName);
        Map value = UtilMap.getMap(title, "value");
        String type = UtilMap.getString(title, "type");

        long currentTime = new Date().getTime();

        if ("DateTimeInput".equals(type)){
            currentTime = UtilMap.getLong(value, "currentTime");
        }else if ("DateRangeInput".equals(type)){
            currentTime = UtilMap.getLong(value, "startTime");
        }

        return currentTime;
    }

    //根据员工名字匹配员工id
    private List<String> getDdUserId(String Name){
        HashMap body = new HashMap();

        body.put("queryWord", Name);
        body.put("offset",0);
        body.put("size",1);

        String s1 = UtilHttp.doPost("https://api.dingtalk.com/v1.0/contact/users/search", ddClient.initTokenHeader(), null, body);

        List<String> list = JSONObject.parseObject(s1).getJSONArray("list").toJavaList(String.class);

        return list;
    }

    //更新宜搭采购已退回金额
    private void updateYdRepay(String formCode, Double amount) {
        String[] split = formCode.split("-");
        String bh = split[0];
        int index = Integer.parseInt(split[1]);

        Map updateFormData = new HashMap();
        List<Map> updateDetailList = new ArrayList<>();

        if (formCode.contains("需求")){
            //采购需求&结算
            List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                    .formUuid("FORM-C8C1FBBA781C4C5EBAC487C07BC5A86AD2HO")
                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", bh)))
                    .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();

            String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");

            Map ydFormData = UtilMap.getMap(data.get(0), "formData");

            String type = UtilMap.getString(ydFormData, "radioField_mkkmij3b");

            if ("常规需求".equals(type)){
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182f");//已退回金额

                        detailMap.put("numberField_mn4g182f",ythje + amount);
                        detailMap.put("selectField_mmvhqm0p","部分退款");
                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij56",updateDetailList);
            }else {
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182g");//已退回金额

                        detailMap.put("numberField_mn4g182g",ythje + amount);
                        detailMap.put("selectField_mkkmij6a","部分退款");
                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij61",updateDetailList);
            }

            Double totalAmt = UtilMap.getDouble(ydFormData, "numberField_mn4g5e28");//已退回

            updateFormData.put("numberField_mn4g5e28",totalAmt + amount);

            ydClient.operateData(YDParam.builder()
                    .formInstanceId(formInstanceId)
                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                    .useLatestVersion(true)
                    .build(), YDConf.FORM_OPERATION.update);
        }else {
            //直接采购结算单
            List<Map> data = (List<Map>) ydClient.queryData(YDParam.builder()
                    .formUuid("FORM-1AFEDDA034C74F0DB18FA60C941CB56EHUUG")
                    .searchCondition(JSONObject.toJSONString(UtilMap.map("serialNumberField_mkkmij3o", bh)))
                    .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();

            String formInstanceId = UtilMap.getString(data.get(0), "formInstanceId");

            Map ydFormData = UtilMap.getMap(data.get(0), "formData");

            String type = UtilMap.getString(ydFormData, "radioField_mkkmij3b");

            if ("常规采购".equals(type)){
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij56");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxx")){
                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182f");//已退回金额

                        detailMap.put("numberField_mn4g182f",ythje + amount);
                        detailMap.put("selectField_mmvhtdy0","部分退款");
                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij56",updateDetailList);
            }else {
                List<Map> detailList = UtilMap.getList(ydFormData, "tableField_mkkmij61");

                for (Map detail : detailList) {
                    Map detailMap = new HashMap();
                    if (index == UtilMap.getInt(detail, "numberField_mn36ykxz")){
                        Double ythje = UtilMap.getDouble(detail, "numberField_mn4g182g");//已退回金额

                        detailMap.put("numberField_mn4g182g",ythje + amount);
                        detailMap.put("selectField_mkkmij6a","部分退款");
                    }
                    updateDetailList.add(detailMap);
                }
                updateFormData.put("tableField_mkkmij61",updateDetailList);
            }

            Double totalAmt = UtilMap.getDouble(ydFormData, "numberField_mn4g5e28");//已退回

            updateFormData.put("numberField_mn4g5e28",totalAmt + amount);

            ydClient.operateData(YDParam.builder()
                    .formInstanceId(formInstanceId)
                    .updateFormDataJson(JSONObject.toJSONString(updateFormData))
                    .useLatestVersion(true)
                    .build(), YDConf.FORM_OPERATION.update);
        }

    }

    //文件下载到本地
    private void downloadFile(String downloadUri,String downloadPath){
        try {
            URL url = new URL(downloadUri);

            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
            int responseCode = httpConn.getResponseCode();

            // 检查HTTP响应代码是否为200
            if (responseCode == HttpURLConnection.HTTP_OK) {
                InputStream inputStream = httpConn.getInputStream();
                FileOutputStream outputStream = new FileOutputStream(downloadPath);

                byte[] buffer = new byte[4096];
                int bytesRead = -1;

                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }

                outputStream.close();
                inputStream.close();
            } else {
                System.out.println("无法下载文件。HTTP响应代码: " + responseCode);
            }
            httpConn.disconnect();
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}
