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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huigou.cache.DictUtil;
import com.huigou.cache.SystemCache;
import com.huigou.context.Operator;
import com.huigou.context.ThreadLocalUtil;
import com.huigou.data.domain.model.CommonDomainConstants;
import com.huigou.data.query.model.QueryDescriptor;
import com.huigou.data.query.model.QueryModel;
import com.huigou.topsun.base.bsnMessage.appliction.MannualStartWorkApplication;
import com.huigou.topsun.base.task.BaseTask;
import com.huigou.topsun.common.CommonUtils;
import com.huigou.topsun.ep.epApplication.EpApplication;
import com.huigou.topsun.ep.epApplication.EpVo.EpProductInfoVo;
import com.huigou.topsun.sap.common.DefaultHttpClient;
import com.huigou.topsun.sap.common.application.SapMutualEpLogApplication;
import com.huigou.topsun.sap.common.domain.SapMutualEpLog;
import com.huigou.topsun.sap.nonProdApply.domain.SapNonProdApplyDept;
import com.huigou.topsun.sap.nonProdApply.repository.NonProdApplyDeptRepository;
import com.huigou.topsun.sap.permit.application.SapPermitApplication;
import com.huigou.topsun.sap.permit.vo.SapPermitItemVo;
import com.huigou.topsun.sap.permit.vo.SapPermitVo;
import com.huigou.topsun.sap.processOutsource.domain.ProcessOutsource;
import com.huigou.topsun.sap.processOutsource.domain.ProcessOutsourceMaterial;
import com.huigou.topsun.sap.processOutsource.domain.ProcessOutsourceOrderItem;
import com.huigou.topsun.sap.processOutsource.repository.ProcessOutsourceMaterialRepository;
import com.huigou.topsun.sap.processOutsource.repository.ProcessOutsourceOrderItemRepository;
import com.huigou.topsun.sap.processQuotedPrice.application.ProcessQuotedPriceItemApplication;
import com.huigou.topsun.sap.processQuotedPrice.domain.ProcessQuotedPriceItemNumber;
import com.huigou.topsun.sap.purchaseApproval.application.impl.SapPurchaseApprovalApplicationImpl;
import com.huigou.topsun.sap.purchaseApproval.domain.SapPurchaseApproval;
import com.huigou.topsun.sap.purchaseOrder.application.SapPurchaseOrderApplication;
import com.huigou.topsun.sap.purchaseOrder.application.SapPurchaseOrderItemApplication;
import com.huigou.topsun.sap.purchaseOrder.domain.SapPurchaseOrder;
import com.huigou.topsun.sap.purchaseOrder.domain.SapPurchaseOrderItem;
import com.huigou.topsun.sap.purchaseOrder.domain.query.SapPurchaseOrderQueryRequest;
import com.huigou.topsun.sap.purchaseOrder.domain.vo.*;
import com.huigou.topsun.sap.purchaseOrder.repository.SapPurchaseOrderRepository;
import com.huigou.topsun.sap.suppliers.domain.SuppliersInfo;
import com.huigou.topsun.sap.suppliers.domain.SuppliersPay;
import com.huigou.topsun.sap.suppliers.repository.SuppliersInfoRepository;
import com.huigou.topsun.sap.suppliers.repository.SuppliersPayRepository;
import com.huigou.uasp.bmp.common.BizBillStatus;
import com.huigou.uasp.bmp.operator.OperatorApplication;
import com.huigou.uasp.bmp.opm.application.OrgApplication;
import com.huigou.uasp.bmp.opm.domain.model.org.Org;
import com.huigou.uasp.bpm.FlowBroker;
import com.huigou.uasp.bpm.engine.domain.model.RuntimeTaskExtension;
import com.huigou.uasp.bpm.engine.repository.RuntimeTaskExtensionRepository;
import com.huigou.util.*;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.krysalis.barcode4j.HumanReadablePlacement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther: xin.lu
 * @Date: 2024/01/09/18:59
 * @Description:
 */
@Service("sapPurchaseOrderApplication")
public class SapPurchaseOrderApplicationImpl extends FlowBroker implements SapPurchaseOrderApplication {
    @Resource
    private SapPurchaseOrderRepository sapPurchaseOrderRepository;
    @Resource
    private SapPurchaseOrderItemApplication sapPurchaseOrderItemApplication;
    @Resource
    private OperatorApplication operatorApplication;
    @Autowired
    DefaultHttpClient defaultHttpClient;
    @Autowired
    SapPurchaseApprovalApplicationImpl sapPurchaseApprovalApplication;

    @Autowired
    private MannualStartWorkApplication mannualStartWorkApplication;
    @Autowired
    private OrgApplication orgApplication;
    @Autowired
    private SapPermitApplication sapPermitApplication;
    @Autowired
    private TaskExecutor asyncWriteExecutor;
    @Autowired
    private SuppliersInfoRepository suppliersInfoRepository;
    @Autowired
    private SuppliersPayRepository suppliersPayRepository;
    @Autowired
    private EpApplication epApplication;
    @Autowired
    private ProcessOutsourceOrderItemRepository processOutsourceOrderItemRepository;
    @Autowired
    private ProcessOutsourceMaterialRepository processOutsourceMaterialRepository;
    @Autowired
    private ProcessQuotedPriceItemApplication processQuotedPriceItemApplication;
    @Autowired
    SapMutualEpLogApplication sapMutualEpLogApplication;
    @Autowired
    private BaseTask baseTask;
    @Autowired
    private NonProdApplyDeptRepository nonProdApplyDeptRepository;

    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        SDO sdo = this.getBizAndApprovalData();
        SapPurchaseOrder sapPurchaseOrder = getBizEntity(SapPurchaseOrder.class);
        if (sapPurchaseOrder.isNew()) {
            sapPurchaseOrder.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            sapPurchaseOrder = (SapPurchaseOrder) commonDomainService.loadAndFillinProperties(sapPurchaseOrder);
        }
        sapPurchaseOrder = sapPurchaseOrderRepository.save(sapPurchaseOrder);
//        SapPurchaseOrderItem sapPurchaseOrderItem = getBizEntity(SapPurchaseOrderItem.class);
//        if(sapPurchaseOrderItem!=null){
//            sapPurchaseOrderItem.setPurchaseOrderId(sapPurchaseOrder.getId());
//            sapPurchaseOrderItemApplication.saveSapPurchaseOrderItem(sapPurchaseOrderItem);
//        }
        return sapPurchaseOrder.getId();
    }

    @Override
    protected void setTaskDescription(DelegateTask delegateTask) {
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        delegateTask.setDescription(this.getApprovalSubjectName(bizId));
    }

    /**
     * 获取任务标题
     *
     * @param bizId
     * @return
     */
    private String getApprovalSubjectName(String bizId) {
        SapPurchaseOrder sapPurchaseOrder = this.sapPurchaseOrderRepository.findOne(bizId);
        //查询 单据日期
        String fillinDateStr = DateUtil.getDateFormat("yyyy-MM-dd HH:mm:ss", sapPurchaseOrder.getFillinDate());
        String title = "";
        if ("update".equals(sapPurchaseOrder.getOrderRevokeType())){
            title = "撤审修改-";
        }else if ("close".equals(sapPurchaseOrder.getOrderRevokeType())){
            title = "撤审关单-";
        }else if ("delete".equals(sapPurchaseOrder.getOrderRevokeType())){
            title = "撤审删除-";
        }
        //设置标题
        if ("X".equals(sapPurchaseOrder.getRetpo())) {
            return String.format("%s-%s(%s)", title + "采购订单退货", sapPurchaseOrder.getEbeln(), fillinDateStr);
        }
        if ("X0".equals(sapPurchaseOrder.getRetpo())) {
            return String.format("%s-%s(%s)", title + "采购订单换货", sapPurchaseOrder.getEbeln(), fillinDateStr);
        }
        return String.format("%s-%s(%s)", title + sapPurchaseOrder.getBatxt(), sapPurchaseOrder.getEbeln(), fillinDateStr);
    }

    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        // 返回业务数据给流程实例
        SapPurchaseOrder purchaseOrder = sapPurchaseOrderRepository.getOne(bizId);
        if (StringUtil.isBlank(purchaseOrder.getKnttp())) {
            //防止审批要素knttp没有赋值。
            purchaseOrder.setKnttp("无");
        }
        return ClassHelper.toMap(purchaseOrder);
    }
    /**
     * 流程撤销事件
     **/
    @Override
    protected void onRecallProcessInstance(DelegateExecution delegateExecution) {
        String bizId = delegateExecution.getProcessBusinessKey();
        // 修改单据状态为申请
        updateStatus(bizId, BizBillStatus.APPLYING);
    }

    /**
     * 任务完成前执行
     */
    @Override
    protected void onBeforeComplete(DelegateTask delegateTask) {
        super.onBeforeComplete(delegateTask);
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        updateStatus(bizId, BizBillStatus.APPROVING);
    }

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

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

    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        //取消待办任务办结提醒
        //super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
        SapPurchaseOrder sapPurchaseOrder = sapPurchaseOrderRepository.findOne(bizId);
        sapPurchaseOrder.setStatusId(status.getId());
        SapPurchaseOrder save = sapPurchaseOrderRepository.save(sapPurchaseOrder);
        if (StringUtil.isBlank(sapPurchaseOrder.getRevokeReason())){
            //如果没有撤销原因，才去调用sap接口；撤审通知去sap主动撤审
            this.sendSapDate(save, "Y","");
        }else {
            this.sendSapDate(save, "N","3");
        }
//        asyncWriteExecutor.execute(()->
//                //创建放行条
//                this.startSapPermit(sapPurchaseOrder)
//        );
    }

    public void startSapPermit(SapPurchaseOrder purchaseOrder){
        SapPermitVo sapPermitVo = new SapPermitVo();
        sapPermitVo.setCompany(purchaseOrder.getNamel());//供应商
        sapPermitVo.setApplyPerson(purchaseOrder.getPersonMemberId());
        sapPermitVo.setApplyPersonName(purchaseOrder.getPersonMemberName());
        sapPermitVo.setDutyDepart(purchaseOrder.getDeptId());
        sapPermitVo.setDutyDepartName(purchaseOrder.getDeptName());
        sapPermitVo.setPermitDate(new Date());
        List<SapPermitItemVo> sapPermitItemVos = new ArrayList<>();
        List<SapPurchaseOrderItem> purchaseOrderItems = sapPurchaseOrderItemApplication.getPurchaseOrderItems(purchaseOrder.getId());
        for (SapPurchaseOrderItem purchaseOrderItem : purchaseOrderItems) {
            //退货项目创建放行条
            if ("X".equals(purchaseOrderItem.getRetpo())){
                SapPermitItemVo sapPermitItemVo = new SapPermitItemVo();
                sapPermitItemVo.setBelongings(purchaseOrderItem.getMatnr() + "/" + purchaseOrderItem.getTxz01());
                sapPermitItemVo.setUnit(purchaseOrderItem.getMeins());

                String remark="采购订单项:"+purchaseOrder.getEbeln()+"："+purchaseOrderItem.getEbelp();
                sapPermitItemVo.setRemark(remark);
                sapPermitItemVo.setQuantity(new BigDecimal(purchaseOrderItem.getMenge()));
                sapPermitItemVo.setUnitName(purchaseOrderItem.getMsehl());
                sapPermitItemVos.add(sapPermitItemVo);
            }
        }
        if (!CollectionUtils.isEmpty(sapPermitItemVos)){
            sapPermitVo.setItemVos(sapPermitItemVos);
            //创建放行条
            sapPermitApplication.saveSapPermitVo(sapPermitVo);
        }

    }


    @Override
    protected void onAbortProcessInstance(DelegateExecution delegateExecution) {
        super.onAbortProcessInstance(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        SapPurchaseOrder sapPurchaseOrder = sapPurchaseOrderRepository.findOne(bizId);
        sapPurchaseOrder.setStatusId(BizBillStatus.ABORTED.getId());
        sapPurchaseOrderRepository.save(sapPurchaseOrder);
    }

    /**
     * @param delegateTask
     * @param destActivityId 回退到的目标节点id
     */
    @Override
    protected void onBack(DelegateTask delegateTask, String destActivityId) {
        super.onBack(delegateTask, destActivityId);
        if ("Apply".equalsIgnoreCase(destActivityId)) {
            String bizId = delegateTask.getExecution().getProcessBusinessKey();
            SapPurchaseOrder sapPurchaseOrder = sapPurchaseOrderRepository.findOne(bizId);
            sapPurchaseOrder.setStatusId(BizBillStatus.APPLYING.getId());
            SapPurchaseOrder save = sapPurchaseOrderRepository.save(sapPurchaseOrder);
            this.sendSapDate(save, "N","0");
            // 调用 onEnd 方法
//            DelegateExecution execution = delegateTask.getExecution();
//            onEnd(execution);
        }
    }

    @Override
    public Map<String, Object> slicedSapPurchaseOrderList(SapPurchaseOrderQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "sapPurchaseOrderList");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
        queryModel.putDictionary("status", BizBillStatus.getMap());
        if (queryRequest.getBillCode() != null) {
            queryModel.addCriteria(" and t.bill_code like:billCode");
            queryModel.putLikeParam("billCode", queryRequest.getBillCode());
        }
        if (queryRequest.getEbeln() != null) {
            queryModel.addCriteria(" and t.ebeln like:ebeln");
            queryModel.putLikeParam("ebeln", queryRequest.getEbeln());
        }
        queryModel.addCriteria(" order by fillin_date desc ");
        return this.sqlExecutorDao.executeSlicedQuery(queryModel);
    }

    @Override
    public SapPurchaseOrder loadSapPurchaseOrder(String id) {
        return sapPurchaseOrderRepository.findOne(id);
    }

    @Override
    @Transactional
    public void saveSapPurchaseOrderDto(SapPurchaseOrderDto sapPurchaseOrderDto) {
        SapPurchaseOrderVo sapPurchaseOrderVo = sapPurchaseOrderDto.getLsHeader();
        List<SapPurchaseOrder> purchaseOrders = sapPurchaseOrderRepository.findAllByEbeln(sapPurchaseOrderVo.getEbeln());
        String purchaseOrderId = "";
        //数据第一次接收，创建流程任务
            SapPurchaseOrder sapPurchaseOrder = new SapPurchaseOrder();
            BeanUtil.copyProperties(sapPurchaseOrderVo, sapPurchaseOrder);
        String ernam = sapPurchaseOrderVo.getErnam();
        Org org = orgApplication.loadMainOrgByLoginName(ernam);
        String acceptPersonCode = SystemCache.getParameter("acceptPersonCode", String.class);
        if (ObjectUtil.isNull(org)){
            org = orgApplication.loadMainOrgByLoginName(acceptPersonCode);
        }
        if (ObjectUtil.isNotNull(org)){
            Operator operator = operatorApplication.createOperatorByPersonMemberId(org.getId());
            ThreadLocalUtil.putOperator(operator);
        }else {
            //throw new RuntimeException("未找到采购订单创建人：" + ernam);
        }

        List<SapPurchaseOrderItemVo> ltItems = sapPurchaseOrderDto.getLtItems();
        List<SapPurchaseOrderItem> purchaseOrderItems = new ArrayList<>();
        String retpo = "E";//审批要素不能为空，赋值E
        String loekz = "";//删除标识
        for (SapPurchaseOrderItemVo approvalItemVo : ltItems) {
            SapPurchaseOrderItem sapPurchaseApprovalItem = new SapPurchaseOrderItem();
            BeanUtil.copyProperties(approvalItemVo, sapPurchaseApprovalItem);
            purchaseOrderItems.add(sapPurchaseApprovalItem);
            if ("X".equals(approvalItemVo.getRetpo())){
                retpo = "X";//退货
            }
            if ("X".equals(retpo) && "".equals(approvalItemVo.getRetpo())){
                retpo = "X0";//换货
            }
            if ("L".equals(approvalItemVo.getLoekz())){
                loekz = "L";
            }
            sapPurchaseOrder.setKnttp(approvalItemVo.getKnttp());
        }
        sapPurchaseOrder.setRetpo(retpo);
        if (CollectionUtils.isEmpty(purchaseOrders)) {
            //存在也新建 04.28注释的    05.11 把存在的作废掉
            purchaseOrderId=mannualStartWorkApplication.startWorkflow(sapPurchaseOrder,PROCESS_DEFINITION_KEY,"sapPurchaseOrder");
        } else {
            //将存在的作废掉   05.11 lxh
            boolean needStartWorkflow = true;
            for (SapPurchaseOrder purchaseOrder : purchaseOrders) {

                //审批完成的，SAP撤审触发，终止审批完成的，并发起新的流程
                if (purchaseOrder.getStatusId() == BizBillStatus.COMPLETED.getId() || purchaseOrder.getStatusId() == BizBillStatus.ABORTED.getId()){
                    purchaseOrder.setStatusId(BizBillStatus.ABORTED.getId());
                    if ("L".equals(loekz)){
                        //如果在SAP中删除了，终止流程，不另外发起新的流程
                        needStartWorkflow = false;
                    }
                }
                //在审批中，更新明细数据的（先删除，再新增）
                if (purchaseOrder.getStatusId() == BizBillStatus.APPROVING.getId() || purchaseOrder.getStatusId() == BizBillStatus.APPLYING.getId()){
                    needStartWorkflow = false;
                    //更新订单主表数据
                    purchaseOrder.setBsart(sapPurchaseOrder.getBsart());
                    purchaseOrder.setBatxt(sapPurchaseOrder.getBatxt());
                    purchaseOrder.setEkgrp(sapPurchaseOrder.getEkgrp());
                    purchaseOrder.setEknam(sapPurchaseOrder.getEknam());
                    purchaseOrder.setWaers(sapPurchaseOrder.getWaers());
                    purchaseOrder.setTotalMoney(sapPurchaseOrder.getTotalMoney());
                    purchaseOrder.setKnttp(sapPurchaseOrder.getKnttp());
                    purchaseOrder.setRetpo(sapPurchaseOrder.getRetpo());
                    purchaseOrder.setNamel(sapPurchaseOrder.getNamel());
                    purchaseOrder.setLifnr(sapPurchaseOrder.getLifnr());
                    List<SapPurchaseOrderItem> itemList = sapPurchaseOrderItemApplication.getPurchaseOrderItems(purchaseOrder.getId());
                    sapPurchaseOrderItemApplication.deletePurchaseOrderItems(itemList);
                    purchaseOrderId = purchaseOrder.getId();
                    if ("L".equals(loekz)){
                        purchaseOrder.setStatusId(BizBillStatus.ABORTED.getId());
                        baseTask.deleteRunTimeTaskExtensionByBizId(purchaseOrder.getId());
                        baseTask.updateHistoricTaskInstanceExtensionByBizId(purchaseOrder.getId());
                    }
                }
                this.sapPurchaseOrderRepository.save(purchaseOrder);
            }
            if (needStartWorkflow){
                purchaseOrderId=mannualStartWorkApplication.startWorkflow(sapPurchaseOrder,PROCESS_DEFINITION_KEY,"sapPurchaseOrder");
            }

            //数据第n次接收覆盖上一次数据
          /*    BeanUtil.copyProperties(sapPurchaseOrderVo, purchaseOrder);
            this.sapPurchaseOrderRepository.save(purchaseOrder);

            List<SapPurchaseOrderItem> purchaseOrderItems = sapPurchaseOrderItemApplication.getPurchaseOrderItems(purchaseOrder.getId());
            sapPurchaseOrderItemApplication.deletePurchaseOrderItems(purchaseOrderItems);
            purchaseOrderId = purchaseOrder.getId();*/
        }  //  lxh 04.28

        sapPurchaseOrderItemApplication.saveSapPurchaseOrderItems(purchaseOrderId, purchaseOrderItems);

    }


     /**
     * 远程调用sap接口，传递数据
     */
    public void sendSapDate(SapPurchaseOrder sapPurchaseOrder, String flag,String status) {
        Map<String, Object> paramItem = new HashMap<>();
        paramItem.put("ebeln", sapPurchaseOrder.getEbeln());
        paramItem.put("BEDNR", sapPurchaseOrder.getBillCode());
        paramItem.put("frgkz", "10");
        paramItem.put("flag", flag);
        paramItem.put("status", status);
        //如果是关单，传X
        if ("close".equals(sapPurchaseOrder.getOrderRevokeType())){
            paramItem.put("ELIKZ", "X");
            paramItem.put("status", 0);
        }
        //如果是删除，传X和1
        if ("delete".equals(sapPurchaseOrder.getOrderRevokeType())){
            paramItem.put("ELIKZ", "X");
            paramItem.put("status", 1);
        }
        List<Map<String, Object>> paramList = new ArrayList<>();
        paramList.add(paramItem);
        Map<String, Object> param = new HashMap<>();
        param.put("MODE", "PO");
        param.put("DATA", paramList);

        ObjectMapper objectMapper = new ObjectMapper();
        String url = "pass_approval/approval";
        String type = "";
        String message = "";
        Map<String, Object> logMap = new HashMap<>();
        logMap.put("businessType", "采购订单审批");
        logMap.put("businessId", sapPurchaseOrder.getId());
        logMap.put("parameter", JSON.toJSONString(param));
        try {
            String result = defaultHttpClient.execute(param, url);
            List<Map<String, Object>> resultList = objectMapper.readValue(result, new TypeReference<List<Map<String, Object>>>() {
            });
            Map<String, Object> resultMap = resultList.get(0);
            type = (String) resultMap.get("TYPE");
            message = (String) resultMap.get("MESSAGE");
            logMap.put("TYPE", type);
            logMap.put("MESSAGE", message);
            if (!"S".equals(type)) {
                throw new RuntimeException("数据传输失败，请稍后手动重试！" + resultMap.get("MESSAGE"));
            }
        } catch (Exception e) {
            throw new RuntimeException("数据传输失败请检查数据后重试！" + e.getMessage());
        }finally {
            sapPurchaseOrder.setMsgType(type);
            sapPurchaseOrder.setMessage(message);
            this.sapPurchaseOrderRepository.save(sapPurchaseOrder);
            sapMutualEpLogApplication.saveSapMutualEpLog(logMap);
        }
    }

    @Override
    public  String revokeApproval(String id,String revokeReason,String revokeType){
        SapPurchaseOrder sapPurchaseOrder = this.sapPurchaseOrderRepository.findOne(id);
        if (sapPurchaseOrder.getStatusId()!=BizBillStatus.COMPLETED.getId()){
            throw new RuntimeException("审批完成的单据才能撤销！");
        }
        sapPurchaseOrder.setStatusId(BizBillStatus.ABORTED.getId());
        sapPurchaseOrderRepository.save(sapPurchaseOrder);
        List<SapPurchaseOrderItem> sapPurchaseOrderItemList=this.sapPurchaseOrderItemApplication.getPurchaseOrderItems(id);
        //发起流程
        SapPurchaseOrder newSapPurchaseOrder=new SapPurchaseOrder();
        ClassHelper.copyProperties(sapPurchaseOrder,newSapPurchaseOrder);
        newSapPurchaseOrder.setId("");
        newSapPurchaseOrder.setBillCode("");
        newSapPurchaseOrder.setRevokeReason(revokeReason);//撤审原因
        newSapPurchaseOrder.setOrderRevokeType(revokeType);//撤审类型
        newSapPurchaseOrder.setMsgType(null);
        newSapPurchaseOrder.setMessage(null);
        String pId=mannualStartWorkApplication.startWorkflow(newSapPurchaseOrder,PROCESS_DEFINITION_KEY,"sapPurchaseOrder");
        newSapPurchaseOrder=this.sapPurchaseOrderRepository.findOne(pId);


        List<SapPurchaseOrderItem> newSapPurchaseOrderItemList=new ArrayList<>();
        for (SapPurchaseOrderItem sapPurchaseOrderItem:sapPurchaseOrderItemList){
            SapPurchaseOrderItem newSapPurchaseOrderItem=new SapPurchaseOrderItem();
            ClassHelper.copyProperties(sapPurchaseOrderItem,newSapPurchaseOrderItem);
            newSapPurchaseOrderItem.setId("");
            newSapPurchaseOrderItemList.add(newSapPurchaseOrderItem);
        }
        sapPurchaseOrderItemApplication.saveSapPurchaseOrderItems(newSapPurchaseOrder.getId(),newSapPurchaseOrderItemList);

        return newSapPurchaseOrder.getId();
    }

    @Override
    public Map<String, Object> print(String id,Integer num) {
        SapPurchaseOrder sapPurchaseOrder = this.sapPurchaseOrderRepository.findOne(id);
        Map<String, Object> map = ClassHelper.beanToMap(sapPurchaseOrder);
        if (sapPurchaseOrder.getFillinDate()!=null){
            map.put("fillinDate", DateUtil.getDateFormat(sapPurchaseOrder.getFillinDate(),"yyyy-MM-dd"));
        }
        //获取加工商信息
        String lifnr = sapPurchaseOrder.getLifnr();
        map = this.getSupplierInfo(map,lifnr);
        //获取产品信息
        //map = this.getProductInfo(map);
        //map.put("page","/print/topsun/productProcessOuter.ftl");

        List<SapPurchaseOrderItem> purchaseOrderItems = this.sapPurchaseOrderItemApplication.getPurchaseOrderItems(sapPurchaseOrder.getId());
        String eindt ="";
        if (purchaseOrderItems.get(0).getEindt() != null){
            eindt = DateUtil.getDateFormat(purchaseOrderItems.get(0).getEindt(),"yyyy-MM-dd");
        }
        map.put("eindt",eindt);//交货时间
        map.put("telf1",purchaseOrderItems.get(0).getTelf1());//联系电话
        map.put("lgobe",purchaseOrderItems.get(0).getLgobe());//仓库
        map.put("werks",purchaseOrderItems.get(0).getWerks());//工厂
        if (!"虚拟库".equals(purchaseOrderItems.get(0).getLgobe())){
            map.put("strSuppl",purchaseOrderItems.get(0).getStrSuppl());//交货地点
        }
        if ("1000".equals(purchaseOrderItems.get(0).getWerks())){
            map.put("strSuppl","广东省广州市白云区江高镇小塘南路68号");//交货地点
        }else if ("1010".equals(purchaseOrderItems.get(0).getWerks())){
            map.put("strSuppl","广东省广州市白云区广花三路382号广州市宝绅科技应用有限公司RFID大楼");//交货地点
        }

        //订单类型是ZNB3时对应工序外发（临时工序外协）
        if ("ZNB3".equals(sapPurchaseOrder.getBsart())){
            //工序外协
            map = this.getProcessOutInfo(map,num);
        }else {
            //成品外购
            //获取订单信息
            map = this.getSaleOrderInfo(map,purchaseOrderItems,num);

            //销售单备注信息
            String headText2 = "";
            for (SapPurchaseOrderItem purchaseOrderItem : purchaseOrderItems) {
                List<String> strList = new ArrayList<>();
                String vbeln = purchaseOrderItem.getVbeln();
                String zpackrequ = purchaseOrderItem.getZpackrequ();
                String zpacknum = purchaseOrderItem.getZpackrequnum();
                String zpackunit = purchaseOrderItem.getZpackunit();
                String zlosspack = purchaseOrderItem.getZlosspack();
                String ltext = purchaseOrderItem.getLtext();
                if (StringUtil.isNotBlank(zpackrequ)){
                    strList.add(zpackrequ);
                }
                if (StringUtil.isNotBlank(zpacknum)){
                    strList.add(zpacknum);
                }
                if (StringUtil.isNotBlank(zpackunit)){
                    strList.add(zpackunit);
                }
                if (StringUtil.isNotBlank(zlosspack)){
                    strList.add(zlosspack);
                }
                if (StringUtil.isNotBlank(ltext)){
                    strList.add(ltext);
                }
                if (StringUtil.isNotBlank(vbeln) && strList.size()>0){
                    headText2 = headText2 + vbeln + "："+ String.join(";", strList);
                }
            }
            map.put("headText2",headText2);
        }
        return map;
    }

    public Map<String, Object> getSupplierInfo(Map<String, Object> map, String lifnr){
        List<SuppliersInfo> suppliersInfoList = new ArrayList<>();
        suppliersInfoList = suppliersInfoRepository.findByPartner(lifnr);
        lifnr = lifnr.replaceFirst("^0*", "");
        List<SuppliersInfo> suppliersInfoList2 = suppliersInfoRepository.findByPartner(lifnr);
        suppliersInfoList.addAll(suppliersInfoList2);
        if (CollectionUtils.isEmpty(suppliersInfoList)){
            throw new RuntimeException("根据编码：" + lifnr + "未找到供应商信息");
        }
        SuppliersInfo suppliersInfo = suppliersInfoList
                .stream()
                .sorted(Comparator.comparing(SuppliersInfo::getFillinDate, Comparator.reverseOrder()))
                .collect(Collectors.toList()).get(0);
        StringBuffer addressBuf = new StringBuffer();
        addressBuf.append(suppliersInfo.getLand1Name())
                .append(suppliersInfo.getRegionName())
                .append(suppliersInfo.getCity1())
                .append(suppliersInfo.getStreet())
                .append(suppliersInfo.getStrSuppl1())
                .append(suppliersInfo.getStrSuppl2())
                .append(suppliersInfo.getStrSuppl3())
                .append(suppliersInfo.getStrSuppl4());
        String address = addressBuf.toString();
        map.put("address",address);
        List<SuppliersPay> payList = suppliersPayRepository.findAllBySId(suppliersInfo.getId());
        SuppliersPay suppliersPay = payList.get(0);
        String zterm = suppliersPay.getZterm();//付款条件（月结方式）
        String zwels = suppliersPay.getZwels();//付款方式清单（付款方式）
        map.put("zterm", DictUtil.getDictionaryDetailText("zterm",zterm));
        map.put("zwels",DictUtil.getDictionaryDetailText("zwels",zwels));
        return map;
    }

    public Map<String, Object> getSaleOrderInfo(Map<String, Object> map,List<SapPurchaseOrderItem> purchaseOrderItems,Integer num){
        //根据产品合并明细项
        List<String> matnrList = new ArrayList<>(purchaseOrderItems
                .stream()
                .map(SapPurchaseOrderItem::getMatnr2).collect(Collectors.toSet()));

        String s = matnrList.get(num);
        //根据产品和单价合并明细项
        List<MatnrNetprPair> result = purchaseOrderItems.stream()
                .map(item -> new MatnrNetprPair(item.getMatnr2(), item.getNetpr()))
                .filter(item -> item.getMatnr2().equals(s))
                .distinct()  // 如果类正确实现了 equals() 和 hashCode()
                .collect(Collectors.toList());

        ////获取产品信息
        List<EpProductInfoVo> productInfoVoList = this.getProductInfo(s);
        map.put("productInfoVoList",productInfoVoList);
        //生产制程
        map.put("productionProcess",productInfoVoList.get(0).getProductionProcess());

        //获取订单明细信息
        List<Map<String,Object>> detailList = new ArrayList<>();
        for (int i = 1; i <= result.size(); i++) {
            MatnrNetprPair matnrNetprPair = result.get(i-1);
            Map<String, Object> detailMap = new HashMap<>();
            detailMap.put("no",i);
            BigDecimal number = BigDecimal.ZERO;
            BigDecimal amount = BigDecimal.ZERO;
            for (int j = 0; j < purchaseOrderItems.size(); j++) {
                SapPurchaseOrderItem purchaseOrderItem = purchaseOrderItems.get(j);
                if (matnrNetprPair.getMatnr2().equals(purchaseOrderItem.getMatnr2())){
                    detailMap.put("matnr2",matnrNetprPair.getMatnr2().replaceFirst("^0*", ""));

                    //查询仓库
                    String matnr2 = matnrNetprPair.getMatnr2();
                    List<SapNonProdApplyDept> deptList = nonProdApplyDeptRepository.findByMatnrAndWerks(matnr2, purchaseOrderItem.getWerks());
                    if (!CollectionUtils.isEmpty(deptList)){
                        SapNonProdApplyDept sapNonProdApplyDept = deptList
                                .stream()
                                .filter(item -> StringUtil.isNotBlank(item.getLgortName()))
                                .collect(Collectors.toList())
                                .get(0);
                        detailMap.put("lgortName",sapNonProdApplyDept.getLgortName());
                    }
                    detailMap.put("maktx",purchaseOrderItem.getTxz01());
                    detailMap.put("msehl",purchaseOrderItem.getMsehl());
                    number = number.add(new BigDecimal(purchaseOrderItem.getMenge()));
                    //计算总额 = （含税单价+运输费）* 成品数量
                    BigDecimal netpr = purchaseOrderItem.getNetpr();//含税单价
                    Integer peinh = purchaseOrderItem.getPeinh();//价格基数
                    if (peinh > 1){
                        netpr = netpr.divide(BigDecimal.valueOf(peinh),4, RoundingMode.HALF_UP);
                    }
                    BigDecimal kbetr2 = purchaseOrderItem.getKbetr2() == null ? BigDecimal.ZERO:purchaseOrderItem.getKbetr2();//运输费
                    BigDecimal kbetr3 = purchaseOrderItem.getKbetr3() == null ? BigDecimal.ZERO:purchaseOrderItem.getKbetr3();//包装费
                    amount = amount.add(netpr.add(kbetr2).add(kbetr3).multiply(purchaseOrderItem.getKwmeng()));
                    detailMap.put("netpr",netpr);
                    detailMap.put("kbetr2",kbetr2);
                    detailMap.put("kbetr3",kbetr3);
                    detailMap.put("priceAmount",netpr.add(kbetr2).add(kbetr3));//合计单价
                    detailMap.put("loss","1%");//LOSS数，默认1%
                    String vbeln = purchaseOrderItem.getVbeln();
                    if (StringUtil.isNotBlank(vbeln)){
                        vbeln = vbeln.replaceFirst("^0*", "");
                    }
                    detailMap.put("vbeln",vbeln);//生产单号
                }
            }
            detailMap.put("number",number);
            detailMap.put("amount",amount);
            detailList.add(detailMap);
        }
        map.put("materialList",detailList);
        return map;
    }

    private List<EpProductInfoVo> getProductInfo(String matnr2) {
        List<EpProductInfoVo> epProductInfoVos = new ArrayList<>();
        EpProductInfoVo epProductInfoVo = epApplication.queryEpProductInfo(matnr2);
        epProductInfoVos.add(epProductInfoVo);
        return epProductInfoVos;
    }

    private Map<String, Object> getProcessOutInfo(Map<String, Object> map,Integer num) {
        String ebeln = (String) map.get("ebeln");//采购订单号
        //根据订单号查询外协单明细
        List<ProcessOutsourceOrderItem> outsourceOrderItemList = processOutsourceOrderItemRepository.findByEbeln(ebeln);
        Set<String> remarks = outsourceOrderItemList
                .stream()
                .map(ProcessOutsourceOrderItem::getRemark)
                .collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(remarks)){
            String remark = String.join("；", remarks);
            //备注1
            String s1 = (String) map.get("headText");
            if (StringUtil.isBlank(s1)){
                map.put("headText",remark);
            }else {
                s1 = s1 + "；" + remark;
                map.put("headText",s1);
            }
        }
        //根据产品合并明细项，获取产品图片信息
        List<String> matnrList = new ArrayList<>(outsourceOrderItemList
                .stream()
                .map(ProcessOutsourceOrderItem::getProductCode).collect(Collectors.toSet()));
        String s = matnrList.get(num);
        //获取产品信息
        List<EpProductInfoVo> productInfoVoList = this.getProductInfo(s);
        map.put("productInfoVoList",productInfoVoList);
        //生产制程
        map.put("productionProcess",productInfoVoList.get(0).getProductionProcess());
        //产品和工序合并明细项，获取数量合计，loss合计，总金额合计
        List<ProductKey> uniqueProductList = new ArrayList<>(outsourceOrderItemList.stream()
                .map(p -> new ProductKey(p.getProductCode(), p.getWempf(),p.getKbetr()))
                .filter(item->item.getProductCode().equals(s))
                .distinct()  // 如果类正确实现了 equals() 和 hashCode()
                .collect(Collectors.toList()));
        //map.put("eindt",outsourceOrderItemList.get(0).getEeind());
        List<Map<String,Object>> detailList = new ArrayList<>();
        for (int i = 0; i < uniqueProductList.size(); i++) {
            Map<String, Object> detailMap = new HashMap<>();
            detailMap.put("no",i+1);
            ProductKey productKey = uniqueProductList.get(i);
            BigDecimal number = BigDecimal.ZERO;
            BigDecimal loss = BigDecimal.ZERO;
            BigDecimal amount = BigDecimal.ZERO;
            for (int j = 0; j < outsourceOrderItemList.size(); j++) {
                ProcessOutsourceOrderItem outsourceOrderItem = outsourceOrderItemList.get(j);
                if (productKey.getProductCode().equals(outsourceOrderItem.getProductCode()) && productKey.getKbetr().equals(outsourceOrderItem.getKbetr())){
                    detailMap.put("matnr2",outsourceOrderItem.getProductCode().replaceFirst("^0*", ""));
                    //查询仓库
                    String matnr2 = outsourceOrderItem.getProductCode();
                    List<SapNonProdApplyDept> deptList = nonProdApplyDeptRepository.findByMatnrAndWerks(matnr2, map.get("werks").toString());
                    if (!CollectionUtils.isEmpty(deptList)){
                        SapNonProdApplyDept sapNonProdApplyDept = deptList
                                .stream()
                                .filter(item -> StringUtil.isNotBlank(item.getLgortName()))
                                .collect(Collectors.toList())
                                .get(0);
                        detailMap.put("lgortName",sapNonProdApplyDept.getLgortName());
                    }

                    detailMap.put("maktx",outsourceOrderItem.getProductName());
                    detailMap.put("msehl",outsourceOrderItem.getMeinsName());
                    detailMap.put("outProcess01",outsourceOrderItem.getWempf());
                    //临时工序外发，计算印张数；实际送货数量，LOSS数
                    number = number.add(outsourceOrderItem.getMenge());//成品数量
                    loss = loss.add(outsourceOrderItem.getPrintLoss() != null ? outsourceOrderItem.getPrintLoss() : BigDecimal.ZERO);//印张LOSS数改为LOSS数
                    //查询工序报价
                    ProcessQuotedPriceItemNumber quotedPriceItemNumber = processQuotedPriceItemApplication.findQuotedPriceByProductAndProcess(outsourceOrderItem.getProductCode(), outsourceOrderItem.getWempf(), outsourceOrderItem.getMenge(), outsourceOrderItem.getLifnr());
                    BigDecimal freight = quotedPriceItemNumber.getFreight();//运输费
                    BigDecimal packMoney = quotedPriceItemNumber.getPackMoney();//包装费
                    BigDecimal priceAmount = productKey.getKbetr();
                    BigDecimal kbetr = productKey.getKbetr();
                    if (freight != null){
                        kbetr = kbetr.subtract(quotedPriceItemNumber.getFreight());
                    }
                    if (packMoney != null){
                        kbetr = kbetr.subtract(quotedPriceItemNumber.getPackMoney());
                    }
                    BigDecimal priceUnit = quotedPriceItemNumber.getPriceUnit();//价格单位
                    if (priceUnit != null && priceUnit.compareTo(BigDecimal.ONE) > 0){
                        kbetr = kbetr.divide(priceUnit,4, RoundingMode.HALF_UP);

                        if (freight != null){
                            freight = freight.divide(priceUnit,4, RoundingMode.HALF_UP);
                        }
                        if (packMoney!= null){
                            packMoney = packMoney.divide(priceUnit,4, RoundingMode.HALF_UP);
                        }

                        priceAmount = priceAmount.divide(priceUnit,4, RoundingMode.HALF_UP);
                    }
                    detailMap.put("netpr",kbetr);//含税单价
                    detailMap.put("kbetr2",freight);
                    detailMap.put("kbetr3",packMoney);
                    detailMap.put("priceAmount",priceAmount);//合计单价
                    amount = amount.add(priceAmount.multiply(outsourceOrderItem.getMenge()));//合计金额
                    String aufnr = outsourceOrderItem.getAufnr();
                    if (StringUtil.isNotBlank(aufnr)){
                        aufnr = aufnr.replaceFirst("^0*", "");
                    }
                    detailMap.put("vbeln",aufnr);//生产单号
                }
            }
            detailMap.put("number",number);
            detailMap.put("loss",loss);
            detailMap.put("amount",amount);//总价
            detailList.add(detailMap);


        }

        map.put("materialList",detailList);
        return map;
    }

    @Override
    public void updateProcessOutStatus(List<String> ids) {
        List<SapPurchaseOrder> orderList = sapPurchaseOrderRepository.findAll(ids);
        for (SapPurchaseOrder sapPurchaseOrder : orderList) {
            sapPurchaseOrder.setSendOut("1");
        }
        sapPurchaseOrderRepository.save(orderList);
    }

    @Override
    public void abortPurchaseOrder(String id, String jobPageId) {
        //先标记终止状态
        SapPurchaseOrder purchaseOrder = sapPurchaseOrderRepository.findOne(id);
        List<SapMutualEpLog> logList = sapMutualEpLogApplication.findByBusinessId(purchaseOrder.getId());
        if (!CollectionUtils.isEmpty(logList)){
            List<String> types = logList
                    .stream()
                    .map(SapMutualEpLog::getType)
                    .collect(Collectors.toList());
            if (types.contains("E")){
                purchaseOrder.setStatusId(BizBillStatus.ABORTED.getId());
                //删除待办
                actApplication.deleteRuntimeTaskExtension(jobPageId);
                sapPurchaseOrderRepository.save(purchaseOrder);
            }
            else {
                throw new RuntimeException("正常流程不能强制终止");
            }
        }else {
            throw new RuntimeException("正常流程不能强制终止");
        }
    }
}
