package com.sunda.spmsoversea.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmscommon.entity.ZSapOrgClient;
import com.sunda.spmscommon.feign.IFeignServiceCommon;
import com.sunda.spmscommon.mapper.ZSapOrgClientMapper;
import com.sunda.spmscommon.service.ISysLogMqService;
import com.sunda.spmsoversea.dto.*;
import com.sunda.spmsoversea.entity.*;
import com.sunda.spmsoversea.mapper.EamReserveInventoryMapper;
import com.sunda.spmsoversea.mapper.OverseaWhsOutMapper;
import com.sunda.spmsoversea.service.*;

import feign.FeignException;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.text.SimpleDateFormat;
import java.util.*;

import static com.sunda.spmsoversea.constant.CommonConstant.*;
import static com.sunda.spmsoversea.constant.SapConstant.SAP_FAIL;
import static com.sunda.spmsoversea.constant.SapConstant.SAP_SUCCESS;
import static com.sunda.spmsoversea.constant.WhsStorageInventoryConstant.*;
import static com.sunda.spmsoversea.enums.OverseaRequisitionEnum.REQUISITION_APPROVED;
import static com.sunda.spmsoversea.enums.OverseaRequisitionEnum.REQUISITION_DONE;
import static com.sunda.spmsoversea.enums.OverseaWhsOutEnum.*;

/**
 * <p>
 * 海外出库任务表 服务实现类
 * </p>
 *
 * @author Wayne
 * @since 2021-09-22
 */
@Service
@Slf4j
public class OverseaWhsOutServiceImpl extends ServiceImpl<OverseaWhsOutMapper, OverseaWhsOut> implements IOverseaWhsOutService {

    @Autowired
    IOverseaRequisitionService iOverseaRequisitionService;

    @Autowired
    IOverseaRequisitionDtlService iOverseaRequisitionDtlService;

    @Autowired
    IOverseaOperateLogService iOverseaOperateLogService;

    @Autowired
    IOverseaWhsOutDtlService iOverseaWhsOutDtlService;

    @Autowired
    IWhsStorageInventoryService iWhsStorageInventoryService;

    @Autowired
    IWhsOperateLogService iWhsOperateLogService;
    
    @Autowired
    ISysLogMqService iSysLogMqService;

    @Autowired
    IFormatDataToSapService iFormatDataToSapService;

    @Autowired
    IFeignServiceCommon iFeignServiceCommon;
    
    @Autowired
    ZSapOrgClientMapper zSapOrgClientMapper;

    @Autowired
    EamReserveInventoryMapper eamReserveInventoryMapper;

    /** 更新领用申请每一行实际移动类型，然后根据类型的不同拆分出库任务； */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult generateOverseaWhsOut(OverseaWhsOutGenerateDTO overseaWhsOutGenerateDTO, String userId) throws Exception {
        ResponseResult checkResult = checkGenerateOverseaWhsOut(overseaWhsOutGenerateDTO);
        if (checkResult.getCode() != SUCCESS){
            return checkResult;
        }
//        try {
            String uuidRequisition = overseaWhsOutGenerateDTO.getUuidRequisition();

            QueryWrapper<OverseaRequisition> overseaRequisitionQueryWrapper = new QueryWrapper<OverseaRequisition>().eq("UUID_REQUISITION", uuidRequisition);
            OverseaRequisition oRequisition = new OverseaRequisition();
            oRequisition.setCostCenter(overseaWhsOutGenerateDTO.getCostCenter());
            oRequisition.setCostCenterName(overseaWhsOutGenerateDTO.getCostCenterName());
            iOverseaRequisitionService.update(oRequisition, overseaRequisitionQueryWrapper);

            List<OverseaRequisitionDtlDTO> overseaRequisitionDtlDTOList = overseaWhsOutGenerateDTO.getRequisitionDtlDTOList();
            for (OverseaRequisitionDtlDTO dto : overseaRequisitionDtlDTOList){
                String actualMovementType = dto.getActualMovementType();
                Integer item = dto.getItem();
                QueryWrapper<OverseaRequisitionDtl> queryWrapper = new QueryWrapper<OverseaRequisitionDtl>()
                        .eq("UUID_REQUISITION", uuidRequisition).eq("ITEM", item);
                OverseaRequisitionDtl overseaRequisitionDtl = new OverseaRequisitionDtl();
                overseaRequisitionDtl.setActualMovementType(actualMovementType);
                iOverseaRequisitionDtlService.update(overseaRequisitionDtl, queryWrapper);
            }

            String createDate = overseaWhsOutGenerateDTO.getCreateDate();
            OverseaRequisition overseaRequisition = iOverseaRequisitionService.getOverseaRequisition(uuidRequisition);
            String relateDocument = overseaRequisition.getSpmsId();
            List<OverseaRequisitionDtl> overseaRequisitionDtlList = iOverseaRequisitionDtlService.getRequisitionDtls(uuidRequisition);

            Set<String> set = new HashSet<>();
            for (OverseaRequisitionDtl overseaRequisitionDtl : overseaRequisitionDtlList){
                double actualBasicUnit = overseaRequisitionDtl.getActualQtyBasicUnit();
                if (actualBasicUnit > 0){
                    String actualMovementType = "";
                    if(StringUtils.isNotEmpty(overseaRequisition.getRequestNum())){//EAM过来的领用单
                        String storageNo = overseaRequisitionDtl.getStorageCode();//储位
                        String werks = overseaRequisitionDtl.getWerks();//工厂
                        String storageUuid = "";
                        String storageType = "";
                        List<Map<String, String>> whsStorageList = eamReserveInventoryMapper.getWhsStorageUuid(werks, storageNo);
                        if(whsStorageList!=null && whsStorageList.size()>0){
                            storageUuid = whsStorageList.get(0).get("UUID");
                            storageType = whsStorageList.get(0).get("STORAGE_TYPE");
                        }else{
                            throw new Exception(werks+"工厂不存在储位" + storageNo );
                        }
                        if("02".equals(storageType)){//旧件
                            actualMovementType=overseaRequisitionDtl.getActualMovementType()+"_"+storageNo;
                        }else{
                            actualMovementType=overseaRequisitionDtl.getActualMovementType()+"_"+"01";//新件
                        }
                    }else{
                        actualMovementType=overseaRequisitionDtl.getActualMovementType()+"_"+"01";//新件
                    }
                    set.add(actualMovementType);
                }
            }
            for (String movementTypes : set){
                String movementType = movementTypes.split("_")[0];
                String storageTypeSpli = movementTypes.split("_")[1];
                String uuidWhsOut = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
                createOverseaWhsOut(uuidWhsOut, createDate, userId, movementType, overseaRequisition,storageTypeSpli);

                int i = 0;
                for (OverseaRequisitionDtl overseaRequisitionDtl : overseaRequisitionDtlList){
                    //String actualMovementType = overseaRequisitionDtl.getActualMovementType();

                    String actualMovementType = "";
                    String storageType = "";
                    if(StringUtils.isNotEmpty(overseaRequisition.getRequestNum())){//EAM过来的领用单
                        String storageNo = overseaRequisitionDtl.getStorageCode();//储位
                        String werks = overseaRequisitionDtl.getWerks();//工厂
                        String storageUuid = "";
                        List<Map<String, String>> whsStorageList = eamReserveInventoryMapper.getWhsStorageUuid(werks, storageNo);
                        if(whsStorageList!=null && whsStorageList.size()>0){
                            storageUuid = whsStorageList.get(0).get("UUID");
                            storageType = whsStorageList.get(0).get("STORAGE_TYPE");
                        }else{
                            throw new Exception(werks+"工厂不存在储位" + storageNo );
                        }
                        if("02".equals(storageType)){//旧件
                            actualMovementType=overseaRequisitionDtl.getActualMovementType()+"_"+storageNo;
                        }else{
                            actualMovementType=overseaRequisitionDtl.getActualMovementType()+"_"+"01";//新件
                        }
                    }else{
                        actualMovementType=overseaRequisitionDtl.getActualMovementType()+"_"+"01";//新件
                    }

                    double actualBasicUnit = overseaRequisitionDtl.getActualQtyBasicUnit();
                    if (movementTypes.equals(actualMovementType) && actualBasicUnit > 0){
                        Integer item = (i + 1) * 10;
                        createOverseaWhsOutDtl(uuidWhsOut, item, overseaRequisitionDtl, relateDocument);
                        i ++;
                    }
                }
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuidWhsOut, OVERSEA_WHS_OUT_CREATE.getDescZh(), OVERSEA_WHS_OUT_CREATE.getDescEn(), "", OVERSEA_WHS_OUT_CREATE.getDescRu());
            }

            updateOverseaRequisition(overseaRequisition, REQUISITION_DONE.getCode());
            iOverseaOperateLogService.addOverseaOperateLog(userId, overseaRequisition.getUuidRequisition(), REQUISITION_DONE.getDescZh(), REQUISITION_DONE.getDescEn(), "", REQUISITION_DONE.getDescRu());

            QueryWrapper<OverseaWhsOut> queryWrapper = new QueryWrapper<OverseaWhsOut>()
                    .eq("RELATE_DOCUMENT", relateDocument).orderByAsc("SPMS_ID");
            return ResponseResult.success()
                    .add("whsOutList", this.baseMapper.selectList(queryWrapper))
                    .add("overseaRequisition", iOverseaRequisitionService.getOverseaRequisition(uuidRequisition))
                    .add("overseaRequisitionDtlList", iOverseaRequisitionDtlService.getRequisitionDtlList(uuidRequisition));
//        }catch (Exception e){
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error().add("error", e.getMessage());
//        }
    }

    ResponseResult checkGenerateOverseaWhsOut(OverseaWhsOutGenerateDTO overseaWhsOutGenerateDTO){
        if (overseaWhsOutGenerateDTO == null){
            return ResponseResult.error("请求参数错误");
        }
        String uuidRequisition = overseaWhsOutGenerateDTO.getUuidRequisition();
        String createDate = overseaWhsOutGenerateDTO.getCreateDate();
        Integer dataVersion = overseaWhsOutGenerateDTO.getDataVersion();
        if (StringUtils.isEmpty(uuidRequisition) || StringUtils.isEmpty(createDate) || INVALID_DATE.equals(createDate)){
            return ResponseResult.error("请求参数错误");
        }
        OverseaRequisition overseaRequisition = iOverseaRequisitionService.getOverseaRequisition(uuidRequisition);
        if (overseaRequisition == null){
            return ResponseResult.error("领用申请查询不存在");
        }
        if (!dataVersion.equals(overseaRequisition.getDataVersion())){
            return ResponseResult.error("数据已刷新请刷新后重试");
        }
        if (!overseaRequisition.getSpmsStatus().equals(REQUISITION_APPROVED.getCode())){
            return ResponseResult.error("领用申请当前状态禁止此操作");
        }
        List<OverseaRequisitionDtlDTO> overseaRequisitionDtlDTOList = overseaWhsOutGenerateDTO.getRequisitionDtlDTOList();
        if (overseaRequisitionDtlDTOList == null || overseaRequisitionDtlDTOList.size() == 0){
            return ResponseResult.error("请求参数明细行数据为空");
        }
        for (OverseaRequisitionDtlDTO dto : overseaRequisitionDtlDTOList){
            String actualMovementType = dto.getActualMovementType();
            if (StringUtils.isEmpty(actualMovementType)){
                return ResponseResult.error("领用申请明细行" + dto.getItem() + "实际移动类型为空");
            }
        }
        return ResponseResult.success();
    }

    int createOverseaWhsOut(String uuidWhsOut, String createDate, String userId, String movementType, OverseaRequisition overseaRequisition,String documentType){
        OverseaWhsOut overseaWhsOut = new OverseaWhsOut();
        overseaWhsOut.setUuidWhsOut(uuidWhsOut);
        overseaWhsOut.setCreateDate(createDate);
        overseaWhsOut.setMovementType(movementType);
        overseaWhsOut.setSpmsStatus(OVERSEA_WHS_OUT_IN_DELIVERY.getCode());
        overseaWhsOut.setCreateUserid(userId);
        overseaWhsOut.setWerks(overseaRequisition.getWerks());
        overseaWhsOut.setWorkshopCode(overseaRequisition.getWorkshopCode());
        overseaWhsOut.setWhsLocationCode(overseaRequisition.getWhsLocationCode());
        overseaWhsOut.setRelateDocument(overseaRequisition.getSpmsId());
        overseaWhsOut.setCostCenter(overseaRequisition.getCostCenter());
        overseaWhsOut.setCostCenterName(overseaRequisition.getCostCenterName());
        overseaWhsOut.setComments(overseaRequisition.getComments());
        overseaWhsOut.setOaNumber(overseaRequisition.getOaNumber());
        overseaWhsOut.setRemarks(overseaRequisition.getRemarks());
        overseaWhsOut.setDocumentType(documentType);
        return this.baseMapper.insert(overseaWhsOut);
    }

    void createOverseaWhsOutDtl(String uuidWhsOut, Integer item, OverseaRequisitionDtl requisitionDtl, String relateDocument){
        OverseaWhsOutDtl whsOutDtl = new OverseaWhsOutDtl();
        whsOutDtl.setUuidWhsOut(uuidWhsOut);
        whsOutDtl.setItem(item);
        whsOutDtl.setWerks(requisitionDtl.getWerks());
        whsOutDtl.setWorkshopCode(requisitionDtl.getWorkshopCode());
        whsOutDtl.setWhsLocationCode(requisitionDtl.getWhsLocationCode());
        whsOutDtl.setMaterialNo(requisitionDtl.getMaterialNo());
        whsOutDtl.setIssueQtyBasicUnit(requisitionDtl.getActualQtyBasicUnit());
        whsOutDtl.setActualQtyBasicUnit(0.0);
        whsOutDtl.setBasicUnit(requisitionDtl.getBasicUnit());
        whsOutDtl.setIssueQtyUnitSales(requisitionDtl.getActualQtyUnitSales());
        whsOutDtl.setActualQtyUnitSales(0.0);
        whsOutDtl.setStorageInfo("[]");
        whsOutDtl.setUnitSales(requisitionDtl.getUnitSales());
        whsOutDtl.setMovementType(requisitionDtl.getActualMovementType());
        whsOutDtl.setRelateDocument(relateDocument);
        whsOutDtl.setRelateDocumentItem(String.valueOf(requisitionDtl.getItem()));
        whsOutDtl.setRemarks(requisitionDtl.getRemarks());
        whsOutDtl.setProjectOaNumber(requisitionDtl.getProjectOaNumber());
        whsOutDtl.setCountry(requisitionDtl.getCountry());
        whsOutDtl.setEamItemNo(StringUtils.isNotEmpty(requisitionDtl.getEamItemNo()) ? requisitionDtl.getEamItemNo() : "");
        whsOutDtl.setLicenseNo(StringUtils.isNotEmpty(requisitionDtl.getLicenseNo()) ? requisitionDtl.getLicenseNo() : "");
        iOverseaWhsOutDtlService.createOverseaWhsOutDtl(whsOutDtl);
    }

    int updateOverseaRequisition(OverseaRequisition overseaRequisition, String spmsStatus){
        overseaRequisition.setSpmsStatus(spmsStatus);
        return iOverseaRequisitionService.updateRequisition(overseaRequisition);
    }

    @Override
    public ResponseResult getWhsOutAndDtl(String uuidWhsOut) {
        if (StringUtils.isEmpty(uuidWhsOut)){
            return ResponseResult.error("请求参数错误");
        }
        return ResponseResult.success()
                .add("overseaWhsOut", this.baseMapper.selectOne(new QueryWrapper<OverseaWhsOut>().eq("UUID_WHS_OUT", uuidWhsOut)))
                .add("overseaWhsOutDtl", iOverseaWhsOutDtlService.getOverseaWhsOutDtlListMap(uuidWhsOut));
    }

    @Override
    public IPage getWhsOutPage(OverseaWhsOutQueryDTO overseaWhsOutQueryDTO) {
        IPage iPage = overseaWhsOutQueryDTO.getPage();
        List<Map<String, Object>> mapList = this.baseMapper.getWhsOutPage(iPage, overseaWhsOutQueryDTO);
        return iPage.setRecords(mapList);
    }

    /** 出库任务关闭：1-0； */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult closeWhsOut(String uuidWhsOut, Integer dataVersion, String userId, String cancelReason)throws Exception {
//        try {
            if (StringUtils.isEmpty(uuidWhsOut) || dataVersion == null){
                return ResponseResult.error("请求参数错误");
            }
            if (StringUtils.isEmpty(cancelReason)) {
            	return ResponseResult.error("请填写作废原因");
            }
            QueryWrapper<OverseaWhsOut> queryWrapper = new QueryWrapper<OverseaWhsOut>().eq("UUID_WHS_OUT", uuidWhsOut);
            OverseaWhsOut overseaWhsOut = this.baseMapper.selectOne(queryWrapper);
            if (overseaWhsOut == null){
                return ResponseResult.error("请求出库任务不存在");
            }
            if (overseaWhsOut.getDataVersion().equals(dataVersion)){
                ResponseResult.error("数据已更新请刷新重试");
            }
            if (!OVERSEA_WHS_OUT_IN_DELIVERY.getCode().equals(overseaWhsOut.getSpmsStatus())){
                return ResponseResult.error("当前状态禁止此操作");
            }
            overseaWhsOut.setSpmsStatus(OVERSEA_WHS_OUT_DELETE.getCode());
            overseaWhsOut.setCancelReason(cancelReason);
            this.baseMapper.update(overseaWhsOut, queryWrapper);
            iOverseaOperateLogService.addOverseaOperateLog(userId, uuidWhsOut, OVERSEA_WHS_OUT_DELETE.getDescZh(), OVERSEA_WHS_OUT_DELETE.getDescEn(), "", OVERSEA_WHS_OUT_DELETE.getDescRu());
            return ResponseResult.success("出库任务关闭");
//        }catch (Exception e){
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error().add("error", e.getMessage());
//        }
    }

    /** 更新出库任务及明细：1-1；1-2(扣库存)； */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult updateWhsOut(OverseaWhsOutDTO overseaWhsOutDTO, String userId)throws Exception {
        ResponseResult checkResult = checkUpdate(overseaWhsOutDTO);
        if (checkResult.getCode() != SUCCESS){
            return checkResult;
        }
        String uuidWhsOut = overseaWhsOutDTO.getUuidWhsOut();
        OverseaWhsOut overseaWhsOut = getOverWhsOut(uuidWhsOut);

        String spmsStatus = overseaWhsOutDTO.getSpmsStatus();

        /** 更新出库任务表头 */
        ResponseResult updateResult = updateOverseaWhsOut(overseaWhsOut, overseaWhsOutDTO);
        if (updateResult.getCode() != SUCCESS){
            log.info("=======RuntimeException=========\n" + updateResult.getMsg());
            throw new RuntimeException("出库任务表头更新失败：" + updateResult.getMsg());
        }

        /** 更新出库任务行项目 */
        ResponseResult updateDtlResult = updateOverseaWhsOutDtl(overseaWhsOutDTO);
        if (updateDtlResult.getCode() != SUCCESS){
            log.info("=======RuntimeException=========\n" + updateDtlResult.getMsg());
            throw new RuntimeException("出库任务明细更新失败：" + updateResult.getMsg());
        }
        /** 增加出库任务操作日志 */
        addOperateLog(uuidWhsOut, spmsStatus, userId);
        return getWhsOutAndDtl(uuidWhsOut);
    }

    ResponseResult updateOverseaWhsOut(OverseaWhsOut overseaWhsOut, OverseaWhsOutDTO overseaWhsOutDTO){
        try {
            QueryWrapper<OverseaWhsOut> queryWrapper = new QueryWrapper<OverseaWhsOut>().eq("UUID_WHS_OUT", overseaWhsOut.getUuidWhsOut());
            overseaWhsOut.setSpmsStatus(overseaWhsOutDTO.getSpmsStatus());
            overseaWhsOut.setRemarks(overseaWhsOutDTO.getRemarks());
            overseaWhsOut.setComments(overseaWhsOutDTO.getComments());
            overseaWhsOut.setOaNumber(overseaWhsOutDTO.getOaNumber());
            overseaWhsOut.setOaId(overseaWhsOutDTO.getOaId());
            overseaWhsOut.setPdaSN(StringUtils.isNotEmpty(overseaWhsOutDTO.getPdaSN()) ? overseaWhsOutDTO.getPdaSN() : "");
            overseaWhsOut.setPdaTime(StringUtils.isNotEmpty(overseaWhsOutDTO.getPdaTime()) ? overseaWhsOutDTO.getPdaTime() : DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            this.baseMapper.update(overseaWhsOut, queryWrapper);
            return ResponseResult.success();
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.error().add("error", e.getMessage());
        }
    }

    ResponseResult updateOverseaWhsOutDtl(OverseaWhsOutDTO overseaWhsOutDTO){
        List<OverseaWhsOutDtlDTO> whsOutDtlDTOList = overseaWhsOutDTO.getWhsOutDtlDTOList();
        for (OverseaWhsOutDtlDTO whsOutDtlDTO : whsOutDtlDTOList){
            OverseaWhsOutDtl overseaWhsOutDtl = new OverseaWhsOutDtl();
            overseaWhsOutDtl.setUuidWhsOut(whsOutDtlDTO.getUuidWhsOut());
            overseaWhsOutDtl.setItem(whsOutDtlDTO.getItem());
            double actualQtyBasicUnit = whsOutDtlDTO.getActualQtyBasicUnit() == null ? 0.0 : whsOutDtlDTO.getActualQtyBasicUnit();
            double actualQtyUnitSales = whsOutDtlDTO.getActualQtyUnitSales() == null ? 0.0 : whsOutDtlDTO.getActualQtyUnitSales();
            overseaWhsOutDtl.setActualQtyBasicUnit(actualQtyBasicUnit);
            overseaWhsOutDtl.setActualQtyUnitSales(actualQtyUnitSales);
            overseaWhsOutDtl.setUnitSales(whsOutDtlDTO.getUnitSales());
            overseaWhsOutDtl.setProjectOaNumber(whsOutDtlDTO.getProjectOaNumber());
            overseaWhsOutDtl.setCountry(whsOutDtlDTO.getCountry());
            overseaWhsOutDtl.setStorageInfo(whsOutDtlDTO.getStorageInfo() == null ? "[]" : whsOutDtlDTO.getStorageInfo());
            overseaWhsOutDtl.setRemarks(whsOutDtlDTO.getRemarks() == null ? "" : whsOutDtlDTO.getRemarks());
            int whsOutDtlUpdateResult = iOverseaWhsOutDtlService.updateWhsOutDtl(overseaWhsOutDtl);
            if (whsOutDtlUpdateResult < 1){
                return ResponseResult.error().add("error", "出库任务明细行更新错误");
            }
        }
        return ResponseResult.success();
    }
    
    ResponseResult updateOverseaWhsOutInventory(String uuidWhsOut, String operateType, String userId, String logType, String werks, String whsLocationCode, String movementType, String remark){
        List<OverseaWhsOutDtl> overseaWhsOutDtlList = iOverseaWhsOutDtlService.getOverseaWhsOutDtlList(uuidWhsOut);
        if (overseaWhsOutDtlList == null || overseaWhsOutDtlList.size() == 0){
            return ResponseResult.error("出库任务明细数据查询不存在");
        }
        for (OverseaWhsOutDtl overseaWhsOutDtl : overseaWhsOutDtlList){
            String materialNo = overseaWhsOutDtl.getMaterialNo();
            Integer item = overseaWhsOutDtl.getItem();
            double actualQtyBasicUnit = overseaWhsOutDtl.getActualQtyBasicUnit();
            if (actualQtyBasicUnit > 0){
                //storageInfoArray 结构参考：[{"storageUuid":"f17e13b4d9ad4d39ba55548eff544391","qty":100,"storageNo":"C010101"}]
                JSONArray storageInfoArray = JSONArray.parseArray(overseaWhsOutDtl.getStorageInfo());
                for (int i = 0; i < storageInfoArray.size(); i ++){
                    JSONObject storageInfoObj = storageInfoArray.getJSONObject(i);
                    String storageUuid = storageInfoObj.getString("storageUuid");
                    double qty = storageInfoObj.getDoubleValue("qty");
                    if (qty > 0){
                        ResponseResult updateInventory = iWhsStorageInventoryService.updateWhsStorageInventory(storageUuid, materialNo, qty, operateType);
                        if (updateInventory.getCode() != SUCCESS){
                            return updateInventory;
                        }
                        String comments = operateType.equals(ADD) ? WHS_OPERATE_LOG_ADD : WHS_OPERATE_LOG_SUB;
                        iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, logType, uuidWhsOut, comments, userId, remark, werks, whsLocationCode, movementType, String.valueOf(item));
                    }
                }
            }
        }
        return ResponseResult.success();
    }

    ResponseResult checkUpdate(OverseaWhsOutDTO overseaWhsOutDTO){
        if (overseaWhsOutDTO == null){
            return ResponseResult.error("请求参数错误");
        }
        String uuidWhsOut = overseaWhsOutDTO.getUuidWhsOut();
        String spmsStatus = overseaWhsOutDTO.getSpmsStatus();
        Integer dataVersion = overseaWhsOutDTO.getDataVersion();
        if (StringUtils.isEmpty(uuidWhsOut) || StringUtils.isEmpty(spmsStatus) || dataVersion == null){
            return ResponseResult.error("请求参数错误");
        }
        if (!OVERSEA_WHS_OUT_IN_DELIVERY.getCode().equals(spmsStatus) && !OVERSEA_WHS_OUT_DELIVERY_COMPLETED.getCode().equals(spmsStatus)){
            return ResponseResult.error("请求数据目标状态错误");
        }
        QueryWrapper<OverseaWhsOut> queryWrapper = new QueryWrapper<OverseaWhsOut>().eq("UUID_WHS_OUT", uuidWhsOut);
        OverseaWhsOut overseaWhsOut = this.baseMapper.selectOne(queryWrapper);
        if (overseaWhsOut == null){
            return ResponseResult.error("请求出库任务不存在");
        }
        if (!overseaWhsOut.getDataVersion().equals(dataVersion)){
            return ResponseResult.error("数据已更新请刷新重试");
        }
        if (!OVERSEA_WHS_OUT_IN_DELIVERY.getCode().equals(overseaWhsOut.getSpmsStatus())){
            return ResponseResult.error("请求出库任务当前状态禁止此操作");
        }
        return ResponseResult.success();
    }

    @Override
    public  ResponseResult checkSapKeyCode(String uuidWhsOut,Integer dataVersion){
        QueryWrapper<OverseaWhsOut> queryWrapper = new QueryWrapper<OverseaWhsOut>().eq("UUID_WHS_OUT", uuidWhsOut);
        OverseaWhsOut overseaWhsOut = this.baseMapper.selectOne(queryWrapper);
        if (!dataVersion.equals(overseaWhsOut.getDataVersion())){
            return ResponseResult.error("数据已更新请刷新重试");
        }
        if(StringUtils.isEmpty(overseaWhsOut.getSapKeyCode())){//缺少幂等ID
            SimpleDateFormat simp = new SimpleDateFormat("yyyy:MM:ddHH:mm:ss:SS");//月日时分秒 毫秒
            String serialNumber=simp.format(new Date()).replace(":","" );
            overseaWhsOut.setSapKeyCode("SPMS"+serialNumber);
            this.baseMapper.update(overseaWhsOut, queryWrapper);
        }
        return ResponseResult.success();
    }

    /** 出库任务提交SAP：2-3；2-4；4-3；4-4；
     * 单据状态(0已删除;1出库中;2出库完成;3提交SAP成功;4提交SAP失败;5已撤销;)
     * */
    @SuppressWarnings("unchecked")
	@Override
	@Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult toSapWhsOut(String uuidWhsOut, Integer dataVersion, String postingDate, String userId) throws Exception {
        ResponseResult checkResult = checkToSapWhsOut(uuidWhsOut, dataVersion, postingDate);
        if (checkResult.getCode() != SUCCESS){
            return checkResult;
        }
        QueryWrapper<OverseaWhsOut> queryWrapper = new QueryWrapper<OverseaWhsOut>().eq("UUID_WHS_OUT", uuidWhsOut);
        OverseaWhsOut overseaWhsOut = this.baseMapper.selectOne(queryWrapper);
        String werks = overseaWhsOut.getWerks();
        String whsLocationCode = overseaWhsOut.getWhsLocationCode();
        // 扣减库存数量
//        boolean updateInventory = true;
//        if(StringUtils.isNotEmpty(overseaWhsOut.getRelateDocument())){
//        	OverseaRequisition overseaRequisition = iOverseaRequisitionService.getOne(new QueryWrapper<OverseaRequisition>().eq("SPMS_ID", overseaWhsOut.getRelateDocument()));
//        	if(overseaRequisition!=null && StringUtils.isNotEmpty(overseaRequisition.getRequestNum())){
//        		updateInventory = false;
//        	}
//        }
        ResponseResult updateInventoryResult = updateOverseaWhsOutInventory(uuidWhsOut, SUB, userId, OPERATION_TYPE3, werks, whsLocationCode, overseaWhsOut.getMovementType(), "领用出库");
        if (updateInventoryResult.getCode() != SUCCESS){
        	throw new Exception("储位库存更新错误\n" + updateInventoryResult.getMsg());
        }
        if("02".equals(overseaWhsOut.getDocumentType())){//旧件出库不需要提交SAP
            overseaWhsOut.setPostingDate(postingDate);
            overseaWhsOut.setSpmsStatus(OVERSEA_WHS_OUT_SAP_SUCCESS.getCode());
            this.baseMapper.update(overseaWhsOut, queryWrapper);
            iOverseaOperateLogService.addOverseaOperateLog(userId, uuidWhsOut, OVERSEA_WHS_OUT_SAP_SUCCESS.getDescZh() ,
                    OVERSEA_WHS_OUT_SAP_SUCCESS.getDescEn(), spmsLog,"", "", "出库任务过账", OVERSEA_WHS_OUT_SAP_SUCCESS.getDescRu());

            return ResponseResult.success()
                    .add("overseaWhsOut", this.baseMapper.selectOne(queryWrapper))
                    .add("overseaWhsOutDtl", iOverseaWhsOutDtlService.getOverseaWhsOutDtlListMap(uuidWhsOut));
        }
        // 调用接口同步SAP
        Map<String, Object> dataHeadWhsOut = this.baseMapper.dataHeadWhsOut(uuidWhsOut, postingDate);
        List<Map<String, Object>> dataItemWhsOut = this.baseMapper.dataItemWhsOut(uuidWhsOut);
        JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(dataHeadWhsOut, dataItemWhsOut, "Z_SPMS_ANOMALY_POST", "ANOMALY_POST");
        // 根据工厂查询对应的SAP Clinet
        List<ZSapOrgClient> selectList = zSapOrgClientMapper.selectList(new QueryWrapper<ZSapOrgClient>().eq("WERKS", dataHeadWhsOut.get("WERKS")));
        if (CollectionUtils.isNotEmpty(selectList)) {
            JSONObject obj = dataToSap.getJSONObject("REQUEST").getJSONObject("ESB_ATTRS");
            obj.put("Target_ID", "SAP-"+selectList.get(0).getZmandt());
        } else {
        	throw new Exception("工厂："+dataHeadWhsOut.get("werks")+"未找到对应的SAP Clinet");
        }
        log.info("=======海外领用出库请求SAP dataToSap=========\n" + dataToSap);
        JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
        log.info("=======海外领用出库请求SAP响应结果 message=========\n" + message);
        JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
        if (SAP_SUCCESS.equals(RETURN_DATA.getString("O_TYPE"))){
            String sapVoucherNumber = RETURN_DATA.getString("O_MBLNR").trim();
            String sapVoucherYear = RETURN_DATA.getString("O_MJAHR").trim();
            overseaWhsOut.setPostingDate(postingDate);
            overseaWhsOut.setSpmsStatus(OVERSEA_WHS_OUT_SAP_SUCCESS.getCode());
            overseaWhsOut.setSapVoucherNumber(sapVoucherNumber);
            overseaWhsOut.setSapVoucherYear(sapVoucherYear);
            this.baseMapper.update(overseaWhsOut, queryWrapper);
            iOverseaOperateLogService.addOverseaOperateLog(userId, uuidWhsOut, OVERSEA_WHS_OUT_SAP_SUCCESS.getDescZh() + ":" + sapVoucherNumber,
                    OVERSEA_WHS_OUT_SAP_SUCCESS.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "出库任务提交SAP", OVERSEA_WHS_OUT_SAP_SUCCESS.getDescRu());
            try {
            	JSONArray costArray = RETURN_DATA.getJSONArray("IT_COST");
            	if (costArray != null && costArray.size() > 0) {
            		List<OverseaWhsOutDtl> itemList = new ArrayList<OverseaWhsOutDtl>();
            		for (int i = 0; i < costArray.size(); i++) {
            			Map<String, Object> map = (Map<String, Object>) costArray.get(i);
            			if (map.get("ZEILE1") != null && map.get("DMBTR") != null) {
            				OverseaWhsOutDtl dtl = new OverseaWhsOutDtl();
            				String zeile = (String) map.get("ZEILE1");
            				String zeileRepla = zeile.replaceAll("^(0+)", "");
            				dtl.setUuidWhsOut(uuidWhsOut);
            				dtl.setItem(Integer.valueOf(zeileRepla));
            				dtl.setDmbtr(map.get("DMBTR").toString());
            				dtl.setWaers(map.get("WAERS") != null ? map.get("WAERS").toString() : "");
            				itemList.add(dtl);
            			}
            		}
            		if (CollectionUtils.isNotEmpty(itemList)) {
            			if (itemList.size() > 1000) {
            				List<List<OverseaWhsOutDtl>> partition = Lists.partition(itemList, 1000);
            				for (List<OverseaWhsOutDtl> pa : partition) {
            					this.baseMapper.updateBatchDtl(pa);
            				}
            			} else {
            				this.baseMapper.updateBatchDtl(itemList);
            			}
            		}
            	}
            } catch (Exception e) {
            }
            // 来源EAM的领用单生成的出库单提交SAP成功后调用接口Z_SPMS_OV_OUT_TO_EAM同步EAM
            if(StringUtils.isNotEmpty(overseaWhsOut.getRelateDocument())){
            	OverseaRequisition overseaRequisition = iOverseaRequisitionService.getOne(new QueryWrapper<OverseaRequisition>().eq("SPMS_ID", overseaWhsOut.getRelateDocument()));
            	if(overseaRequisition!=null && StringUtils.isNotEmpty(overseaRequisition.getRequestNum())){
            		// 查询出库单行
            		QueryWrapper<OverseaWhsOutDtl> query = new QueryWrapper<OverseaWhsOutDtl>().eq("UUID_WHS_OUT", uuidWhsOut);
            		List<OverseaWhsOutDtl> list = this.iOverseaWhsOutDtlService.list(query);
            		List<Map<String, Object>> itemList = new ArrayList<>();
            		for (OverseaWhsOutDtl dtl : list) {
            			Map<String, Object> map = new HashMap<>();
            			map.put("LINENUM", StringUtils.isNotEmpty(dtl.getEamItemNo()) ? dtl.getEamItemNo() : "");
            			map.put("MATERIALNO", dtl.getMaterialNo());
            			map.put("SPMSOUTID", overseaWhsOut.getSpmsId());
            			map.put("SAPVOUCHERNUMBER", sapVoucherNumber);
            			map.put("DMBTR", StringUtils.isNotEmpty(dtl.getDmbtr()) ? dtl.getDmbtr() : "");
            			map.put("WAERS", StringUtils.isNotEmpty(dtl.getWaers()) ?dtl.getWaers() : "");
            			itemList.add(map);
            		}
            		try {
            			JSONObject toSapData = this.formatDataToSap(overseaRequisition.getRelateDocument(), "0", overseaWhsOut.getSpmsId(), itemList, overseaRequisition.getSpmsId(), overseaRequisition.getComments());
            			log.info("=======Z_SPMS_OV_OUT_TO_EAM =========\n" + toSapData);
            			JSONObject returnObject = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(toSapData));
            			log.info("=======message =========\n" + returnObject);
            			JSONObject returnData = returnObject.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
            			iSysLogMqService.addSysLogMq("3", "Z_SPMS_OV_OUT_TO_EAM", "出库单推送SAP后同步EAM", "Z_SPMS_OV_OUT_TO_EAM", JSON.toJSONString(toSapData), JSON.toJSONString(returnObject), null);
            			if (!"10000".equals(returnData.getString("code"))) {
            				throw new Exception("出库推送EAM接口异常！");
            			}
            		} catch (Exception e) {
            			
            		}
            	}
            }
            return ResponseResult.success()
                    .add("overseaWhsOut", this.baseMapper.selectOne(queryWrapper))
                    .add("overseaWhsOutDtl", iOverseaWhsOutDtlService.getOverseaWhsOutDtlListMap(uuidWhsOut))
                    .add("sapReturnedMessage", message)
                    .add("dataToSap", dataToSap);
        } else {
        	throw new Exception("同步SAP失败："+message.toJSONString());
        }
    }

    ResponseResult checkToSapWhsOut(String uuidWhsOut, Integer dataVersion, String postingDate){
        if (StringUtils.isEmpty(uuidWhsOut) || StringUtils.isEmpty(postingDate) || dataVersion == null){
            return ResponseResult.error("请求参数错误");
        }
        OverseaWhsOut overseaWhsOut = getOverWhsOut(uuidWhsOut);
        if (overseaWhsOut == null){
            return ResponseResult.error("请求出库任务不存在");
        }
        String spmsStatus = overseaWhsOut.getSpmsStatus();
        if (!spmsStatus.equals(OVERSEA_WHS_OUT_DELIVERY_COMPLETED.getCode()) &&
                !spmsStatus.equals(OVERSEA_WHS_OUT_SAP_ERROR.getCode())){
            return ResponseResult.error("出库任务当前状态禁止此操作");
        }
        // 验证库存量
        if (OVERSEA_WHS_OUT_DELIVERY_COMPLETED.getCode().equals(spmsStatus) || spmsStatus.equals(OVERSEA_WHS_OUT_SAP_ERROR.getCode())){
        	List<OverseaWhsOutDtl> whsOutDtlDTOList = this.iOverseaWhsOutDtlService.getOverseaWhsOutDtlList(uuidWhsOut);
        	if (whsOutDtlDTOList == null || whsOutDtlDTOList.size() == 0){
        		return ResponseResult.error("出库任务明细行不能为空");
        	}
//        	boolean updateInventory = true;
//            if(StringUtils.isNotEmpty(overseaWhsOut.getRelateDocument())){
//                OverseaRequisition overseaRequisition = iOverseaRequisitionService.getOne(new QueryWrapper<OverseaRequisition>().eq("SPMS_ID", overseaWhsOut.getRelateDocument()));
//                if(overseaRequisition!=null && StringUtils.isNotEmpty(overseaRequisition.getRequestNum())){
//                    updateInventory = false;
//                }
//            }
        	for (OverseaWhsOutDtl whsOutDtl : whsOutDtlDTOList){
        		String uuidWhsOutItem = whsOutDtl.getUuidWhsOut();
        		Integer item = whsOutDtl.getItem();
        		double actualQtyBasicUnit = whsOutDtl.getActualQtyBasicUnit();
        		if (actualQtyBasicUnit > 0){
        			OverseaWhsOutDtl overseaWhsOutDtl = iOverseaWhsOutDtlService.getWhsOutDtl(uuidWhsOutItem, item);
        			if (overseaWhsOutDtl == null){
        				return ResponseResult.error("请求出库明细数据不存在");
        			}
        			String materialNo = overseaWhsOutDtl.getMaterialNo();
        			JSONArray storageInfoArray = JSONArray.parseArray(whsOutDtl.getStorageInfo());
        			if (storageInfoArray == null || storageInfoArray.size() == 0){
        				return ResponseResult.error("储位信息不正确");
        			}
        			for (int i = 0; i < storageInfoArray.size(); i ++){
        				JSONObject storageInfoObj = storageInfoArray.getJSONObject(i);
        				String storageUuid = storageInfoObj.getString("storageUuid");
        				double qty = storageInfoObj.getDoubleValue("qty");
        				String storageNo = storageInfoObj.getString("storageNo");
        				if (qty > 0){
        					WhsStorageInventory whsStorageInventory = iWhsStorageInventoryService.getWhsStorageInventory(storageUuid, materialNo);
        					if (whsStorageInventory == null){
        						return ResponseResult.error("物料号" + materialNo + "在储位" + storageNo + "无可用库存");
        					}
        					if (qty > whsStorageInventory.getAvailableQty()){
        						return ResponseResult.error("物料号" + materialNo + "在储位" + storageNo + "可用库存不足");
        					}
        				}
        			}
        		}
        	}
        }
        return ResponseResult.success();
    }


    /**
     单据状态(0已删除;1出库中;2出库完成;3提交SAP成功;4提交SAP失败;5已撤销;)
     出库任务撤销/退回操作：3-1(加库存)；2-1(加库存)；4-1(加库存)；
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult cancelWhsOut(String uuidWhsOut, Integer dataVersion, String cancelPostingDate, String userId) throws Exception{
        ResponseResult checkResult = cancelCheck(uuidWhsOut, dataVersion, cancelPostingDate);
        if (checkResult.getCode() != SUCCESS){
            return checkResult;
        }
        OverseaWhsOut overseaWhsOut = getOverWhsOut(uuidWhsOut);
        String spmsStatus = overseaWhsOut.getSpmsStatus();
        String werks = overseaWhsOut.getWerks();
        String whsLocationCode = overseaWhsOut.getWhsLocationCode();
        QueryWrapper<OverseaWhsOut> queryWrapper = new QueryWrapper<OverseaWhsOut>().eq("UUID_WHS_OUT", uuidWhsOut);
        if (spmsStatus.equals(OVERSEA_WHS_OUT_DELIVERY_COMPLETED.getCode()) ||
                spmsStatus.equals(OVERSEA_WHS_OUT_SAP_ERROR.getCode())){
            overseaWhsOut.setSpmsStatus(OVERSEA_WHS_OUT_IN_DELIVERY.getCode());
            this.baseMapper.update(overseaWhsOut, queryWrapper);
            addOperateLog(uuidWhsOut, OVERSEA_WHS_OUT_GO_BACK.getCode(), userId);
            return getWhsOutAndDtl(uuidWhsOut);
        }
        if (spmsStatus.equals(OVERSEA_WHS_OUT_SAP_SUCCESS.getCode())){
            overseaWhsOut.setSapKeyCode("");//冲销的时候将幂等ID置空，下次提交的时候再新建值
        	// 增加库存
//        	boolean updateInventory = true;
//            if(StringUtils.isNotEmpty(overseaWhsOut.getRelateDocument())){
//                OverseaRequisition overseaRequisition = iOverseaRequisitionService.getOne(new QueryWrapper<OverseaRequisition>().eq("SPMS_ID", overseaWhsOut.getRelateDocument()));
//                if(overseaRequisition!=null && StringUtils.isNotEmpty(overseaRequisition.getRequestNum())){//存在领用单，并且领用单是EAM生成的有预留单，不进行库存变更
//                    updateInventory = false;
//                }
//            }
        	ResponseResult updateInventoryResult = updateOverseaWhsOutInventory(uuidWhsOut, ADD, userId, OPERATION_TYPE2, werks, whsLocationCode, "", "领用出库撤销");
        	if (updateInventoryResult.getCode() != SUCCESS){
        		log.info("=======RuntimeException=========\n" + updateInventoryResult.getMsg());
        		throw new Exception("储位库存更新错误\n" + updateInventoryResult.getMsg());
        	}
            if("02".equals(overseaWhsOut.getDocumentType())){//旧件出库不需要提交SAP
                overseaWhsOut.setSpmsStatus(OVERSEA_WHS_OUT_IN_DELIVERY.getCode());
                overseaWhsOut.setCancelPostingDate(cancelPostingDate);
                this.baseMapper.update(overseaWhsOut, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuidWhsOut, OVERSEA_WHS_OUT_CANCEL.getDescZh() ,
                        OVERSEA_WHS_OUT_CANCEL.getDescEn(), spmsLog,"", "", "出库任务撤销过账", OVERSEA_WHS_OUT_CANCEL.getDescRu());

                return ResponseResult.success()
                        .add("overseaWhsOut", this.baseMapper.selectOne(queryWrapper))
                        .add("overseaWhsOutDtl", iOverseaWhsOutDtlService.getOverseaWhsOutDtlListMap(uuidWhsOut));
            }
            // 撤销同步SAP
            Map<String, Object> dataHead = this.baseMapper.dataHeadCancelWhsOut(uuidWhsOut, cancelPostingDate);
            JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(dataHead, null, "Z_SPMS_CANCEL", "SPMS_CANCEL");
            // 根据工厂查询对应的SAP Clinet
            List<ZSapOrgClient> clinetList = zSapOrgClientMapper.selectList(new QueryWrapper<ZSapOrgClient>().eq("WERKS", overseaWhsOut.getWerks()));
            if (!CollectionUtils.isEmpty(clinetList)) {
            	JSONObject esbObj = dataToSap.getJSONObject("REQUEST").getJSONObject("ESB_ATTRS");
            	esbObj.put("Target_ID", "SAP-"+clinetList.get(0).getZmandt());
            } else {
            	throw new Exception("工厂："+overseaWhsOut.getWerks()+"未找到对应的SAP Clinet");
            }
            log.info("=======dataToSap=========\n" + dataToSap);
            JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
            log.info("=======message=========\n" + message);
            JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
            if (SAP_SUCCESS.equals(RETURN_DATA.getString("O_TYPE"))){
                String cancelVoucherNumber = RETURN_DATA.getString("0_MBLNR");
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuidWhsOut, OVERSEA_WHS_OUT_CANCEL.getDescZh() + ":" + cancelVoucherNumber,
                        OVERSEA_WHS_OUT_CANCEL.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "出库任务撤销提交SAP", OVERSEA_WHS_OUT_CANCEL.getDescRu());
                overseaWhsOut.setSpmsStatus(OVERSEA_WHS_OUT_IN_DELIVERY.getCode());
                overseaWhsOut.setCancelPostingDate(cancelPostingDate);
                overseaWhsOut.setSapCancelVoucherNumber(cancelVoucherNumber);
                this.baseMapper.update(overseaWhsOut, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuidWhsOut, OVERSEA_WHS_OUT_IN_DELIVERY.getDescZh(),
                        OVERSEA_WHS_OUT_IN_DELIVERY.getDescEn(), "", OVERSEA_WHS_OUT_IN_DELIVERY.getDescRu());
                return ResponseResult.success()
                        .add("overseaWhsOut", this.baseMapper.selectOne(queryWrapper))
                        .add("overseaWhsOutDtl", iOverseaWhsOutDtlService.getOverseaWhsOutDtlListMap(uuidWhsOut))
                        .add("sapReturnedMessage", message)
                        .add("dataToSap", dataToSap);
            } else {
            	throw new Exception("撤销同步SAP失败："+message.toJSONString()); 
            }
        }
        return ResponseResult.error("当前状态禁止此操作");
    }

    ResponseResult cancelCheck(String uuidWhsOut, Integer dataVersion, String cancelPostingDate){
        if (StringUtils.isEmpty(uuidWhsOut) || dataVersion == null){
            return ResponseResult.error("请求参数错误");
        }
        OverseaWhsOut overseaWhsOut = getOverWhsOut(uuidWhsOut);
        if (overseaWhsOut == null){
            return ResponseResult.error("请求出库任务不存在");
        }
        if (!dataVersion.equals(overseaWhsOut.getDataVersion())){
            return ResponseResult.error("数据已更新请刷新重试");
        }
        String spmsStatus = overseaWhsOut.getSpmsStatus();
        if (!spmsStatus.equals(OVERSEA_WHS_OUT_DELIVERY_COMPLETED.getCode()) &&
                !spmsStatus.equals(OVERSEA_WHS_OUT_SAP_SUCCESS.getCode()) &&
                !spmsStatus.equals(OVERSEA_WHS_OUT_SAP_ERROR.getCode())){
            return ResponseResult.error("出库任务当前状态禁止此操作");
        }
        if (spmsStatus.equals(OVERSEA_WHS_OUT_SAP_SUCCESS.getCode())){
            if (StringUtils.isEmpty(overseaWhsOut.getSapVoucherNumber()) || StringUtils.isEmpty(cancelPostingDate)
                    || INVALID_DATE.equals(cancelPostingDate)){
                return ResponseResult.error("请求参数错误");
            }
        }
        return ResponseResult.success();
    }

    OverseaWhsOut getOverWhsOut(String uuidWhsOut){
        if (StringUtils.isEmpty(uuidWhsOut)){
            return null;
        }
        QueryWrapper<OverseaWhsOut> queryWrapper = new QueryWrapper<OverseaWhsOut>().eq("UUID_WHS_OUT", uuidWhsOut);
        return this.baseMapper.selectOne(queryWrapper);
    }

    void addOperateLog(String uuidWhsOut, String targetStatus, String userId){
        if (targetStatus.equals(OVERSEA_WHS_OUT_IN_DELIVERY.getCode())){
            // 出库中
            iOverseaOperateLogService.addOverseaOperateLog(userId, uuidWhsOut, OVERSEA_WHS_OUT_IN_DELIVERY.getDescZh(), OVERSEA_WHS_OUT_IN_DELIVERY.getDescEn(), "", OVERSEA_WHS_OUT_IN_DELIVERY.getDescRu());
        }
        if (targetStatus.equals(OVERSEA_WHS_OUT_DELIVERY_COMPLETED.getCode())){
            // 出库完成
            iOverseaOperateLogService.addOverseaOperateLog(userId, uuidWhsOut, OVERSEA_WHS_OUT_DELIVERY_COMPLETED.getDescZh(), OVERSEA_WHS_OUT_DELIVERY_COMPLETED.getDescEn(), "", OVERSEA_WHS_OUT_DELIVERY_COMPLETED.getDescRu());
        }
        if (targetStatus.equals(OVERSEA_WHS_OUT_GO_BACK.getCode())){
            //退回修改
            iOverseaOperateLogService.addOverseaOperateLog(userId, uuidWhsOut, OVERSEA_WHS_OUT_GO_BACK.getDescZh(), OVERSEA_WHS_OUT_GO_BACK.getDescEn(), "", OVERSEA_WHS_OUT_GO_BACK.getDescRu());
        }

    }

	@Override
	public List<OverseaWhsOut> findListByRecord(String relateDocument) {
		if (StringUtils.isEmpty(relateDocument)){
            return null;
        }
        QueryWrapper<OverseaWhsOut> queryWrapper = new QueryWrapper<OverseaWhsOut>().eq("RELATE_DOCUMENT", relateDocument);
        return this.baseMapper.selectList(queryWrapper);
	}

	@Override
	public ResponseResult getOverseaWhsOutHead(String spmsId) {
		if (StringUtils.isEmpty(spmsId)) {
			ResponseResult.error("SPMS单号为空，请求失败");
		}
		// 查询头信息
		OverseaWhsOut headVO = this.baseMapper.selectOne(new QueryWrapper<OverseaWhsOut>().eq("SPMS_ID", spmsId));
		// 查询行项目
        List<Map<String, Object>> dtlListMap = iOverseaWhsOutDtlService.getOverseaWhsOutDtlListMap(headVO != null ? headVO.getUuidWhsOut() : "");
        return ResponseResult.success().add("headVO", headVO).add("itemList", dtlListMap);
	}


    private JSONObject formatDataToSap(String overseaRequisitionNum,String state,String outNum, List<Map<String, Object>> itemList, String requisitionId, String comments) {
        JSONObject dataToSap = new JSONObject();
        JSONObject REQUEST = new JSONObject();
        JSONObject ESB_ATTRS = new JSONObject();
        JSONObject REQUEST_DATA = new JSONObject();
        Map<String, Object> head = new HashMap<String, Object>();
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("WONUM", overseaRequisitionNum);//EAM领用单号
        data.put("OUTBOUND", StringUtils.isNotEmpty(outNum) ? outNum : "");//出库单号
        data.put("SPMSID", StringUtils.isNotEmpty(requisitionId) ? requisitionId : "");//领用单号
        data.put("COMMENTS", StringUtils.isNotEmpty(comments) ? comments : "");//领用单标题
        data.put("STATE", state);//状态（0=已完成，1=已撤回）
        head.put("OVDATA", data);
        if (CollectionUtils.isNotEmpty(itemList)) {
        	head.put("ITEMDATA", itemList);
        }
        REQUEST_DATA.put("SendData", head);
        REQUEST_DATA.put("Operation", "Z_SPMS_OV_OUT_TO_EAM");
        REQUEST_DATA.put("Type", "OV_OUT_TO_EAM");
        ESB_ATTRS.put("App_ID", "SPMS");
        ESB_ATTRS.put("Target_ID", "EAM");
        ESB_ATTRS.put("Application_ID", "00020000000002");
        ESB_ATTRS.put("Transaction_ID", UUID.randomUUID().toString());
        REQUEST.put("ESB_ATTRS", ESB_ATTRS);
        REQUEST.put("REQUEST_DATA", REQUEST_DATA);
        dataToSap.put("REQUEST", REQUEST);
        return dataToSap;
    }

}
