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.spmsoversea.dto.*;
import com.sunda.spmsoversea.entity.*;
import com.sunda.spmsoversea.mapper.OverseaOtherTaskMapper;
import com.sunda.spmsoversea.service.*;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.sunda.spmsoversea.constant.CommonConstant.INVALID_DATE;
import static com.sunda.spmsoversea.constant.CommonConstant.SUCCESS;
import static com.sunda.spmsoversea.constant.CommonConstant.sapLog;
import static com.sunda.spmsoversea.constant.OverseaOtherTaskConstant.*;
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.OverseaDnEnum.DN_DELETE;
import static com.sunda.spmsoversea.enums.OverseaOtherEnum.*;
import static com.sunda.spmsoversea.enums.OverseaRequisitionEnum.REQUISITION_APPROVED;

/**
 * <p>
 * 海外仓其他出入库 服务实现类
 * </p>
 *
 * @author Wayne
 * @since 2021-12-27
 */
@Service
@Slf4j
public class OverseaOtherTaskServiceImpl extends ServiceImpl<OverseaOtherTaskMapper, OverseaOtherTask> implements IOverseaOtherTaskService {

    @Autowired
    IFeignServiceCommon iFeignServiceCommon;

    @Autowired
    IFormatDataToSapService iFormatDataToSapService;

    @Autowired
    IWhsStorageInventoryService iWhsStorageInventoryService;

    @Autowired
    IWhsOperateLogService iWhsOperateLogService;

    @Autowired
    IOverseaOperateLogService iOverseaOperateLogService;

    @Autowired
    IOverseaOtherDtlService iOverseaOtherDtlService;

    @Autowired
    IEamReturnSkuService iEamReturnSkuService;

    @Autowired
    IEamReturnSkuDtlService iEamReturnSkuDtlService;

    @Autowired
    IEamFormerSkuService iEamFormerSkuService;

    @Autowired
    IEamFormerSkuDtlService iEamFormerSkuDtlService;
    
    @Autowired
    ZSapOrgClientMapper zSapOrgClientMapper;

    /** 获取其他出入库表头分页列表 */
    @Override
    public IPage getOtherTaskPage(OverseaOtherSearchDTO overseaOtherSearchDTO) {
        IPage iPage = overseaOtherSearchDTO.getPage();
        List<Map<String, Object>> mapList = this.baseMapper.getOtherTaskPage(iPage, overseaOtherSearchDTO);
        iPage.setRecords(mapList);
        return iPage;
    }

    /** 获取其他出入库表头信息 */
    @Override
    public OverseaOtherTask getOtherTask(String uuid) {
        if (StringUtils.isEmpty(uuid)){
            return null;
        }
        return this.baseMapper.selectOne(new QueryWrapper<OverseaOtherTask>().eq("UUID", uuid));
    }

    /** 获取其他出入库表头详细信息 */
    @Override
    public Map<String, Object> getOtherTaskInfo(String uuid) {
        return this.baseMapper.getOtherTaskInfo(uuid);
    }

    /** 获取其他出入库详细明细信息 */
    @Override
    public List<Map<String, Object>> getOtherDtlList(String uuid) {
        return iOverseaOtherDtlService.getOtherDtlList(uuid);
    }

    /** 其他出入库任务关闭 */
    @Override
    public ResponseResult closeOtherTask(String uuid, Integer dataVersion, String userId, String cancelReason) {
        if (StringUtils.isEmpty(uuid) || dataVersion == null){
            return ResponseResult.error("请求参数错误");
        }
        if (StringUtils.isEmpty(cancelReason)) {
        	return ResponseResult.error("请填写作废原因");
        }
        QueryWrapper<OverseaOtherTask> queryWrapper = new QueryWrapper<OverseaOtherTask>().eq("UUID", uuid);
        OverseaOtherTask overseaOtherTask = this.baseMapper.selectOne(queryWrapper);
        if (overseaOtherTask == null){
            return ResponseResult.error("请求其他出入库任务不存在");
        }
        if (!overseaOtherTask.getDataVersion().equals(dataVersion)){
            return ResponseResult.error("其他出入库任务信息已更新请刷新后重试");
        }
        String spmsStatus = overseaOtherTask.getSpmsStatus();
        if (!spmsStatus.equals(OTHER_SAVE.getCode()) && !spmsStatus.equals(OTHER_REJECT.getCode())){
            return ResponseResult.error("其他出入库任务当前状态禁止此操作");
        }
        overseaOtherTask.setSpmsStatus(OTHER_CLOSE.getCode());
        overseaOtherTask.setCancelReason(cancelReason);
        this.baseMapper.update(overseaOtherTask, queryWrapper);

        iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, DN_DELETE.getDescZh(), DN_DELETE.getDescEn(), "", DN_DELETE.getDescRu());
        return ResponseResult.success("其他出入库任务关闭成功")
                .add("otherTask", getOtherTaskInfo(uuid));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult createOtherTask(OverseaOtherDTO overseaOtherDTO, String userId) throws Exception {
//        try {
            ResponseResult checkResult = checkCreate(overseaOtherDTO);
            if (checkResult.getCode() != SUCCESS){
                return checkResult;
            }
            String uuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();

            int createOtherTask =  createOverseaOtherTask(uuid, overseaOtherDTO, userId);
            if (createOtherTask < 1){
                log.info("=======createOverseaOtherTask RuntimeException=========\n");
                throw new RuntimeException("创建其他出入库任务错误");
            }

            int createOtherDtl = createOtherDtl(uuid, overseaOtherDTO);
            if (createOtherDtl < 1){
                log.info("=======createOtherDtl RuntimeException=========\n");
                throw new RuntimeException("创建其他出入库任务行项目错误");
            }
            iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_CREATE.getDescZh(), OTHER_CREATE.getDescEn(), "", OTHER_CREATE.getDescRu());
            return ResponseResult.success("其他出入库任务创建成功")
                    .add("otherTask", getOtherTaskInfo(uuid))
                    .add("otherDtlList", getOtherDtlList(uuid));
//        } catch (Exception e){
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error().add("error", e.getMessage());
//        }
    }

    ResponseResult checkCreate(OverseaOtherDTO overseaOtherDTO){
        if (overseaOtherDTO == null){
            return ResponseResult.error("请求参数不能为空");
        }
        String movementType = overseaOtherDTO.getMovementType();
        String spmsStatus = overseaOtherDTO.getSpmsStatus();
        String werks = overseaOtherDTO.getWerks();
        String whsLocationCode = overseaOtherDTO.getWhsLocationCode();
        String createDate = overseaOtherDTO.getCreateDate();
        List<OverseaOtherDtl> otherDtlList = overseaOtherDTO.getOtherDtlList();

        if (StringUtils.isEmpty(movementType)){
            return ResponseResult.error("其他出入库任务移动类型不能为空");
        }
        if (StringUtils.isEmpty(spmsStatus)){
            return ResponseResult.error("其他出入库任务目标状态不能为空");
        }
        if (StringUtils.isEmpty(werks) || StringUtils.isEmpty(whsLocationCode)){
            return ResponseResult.error("其他出入库任务工厂和仓库不能为空");
        }
        if (StringUtils.isEmpty(createDate)){
            return ResponseResult.error("其他出入库任务创建日期不能为空");
        }
        if (otherDtlList == null || otherDtlList.size() == 0){
            return ResponseResult.error("其他出入库任务明细行不能为空");
        }
        // 领用出库冲销业务，按其他出入库任务实现，新增以下 17 种领用冲销移动类型 ——— 20220121
        // 新增移动类型 建安固定资产领用Z57;建安固定资产领用撤销Z58; ———— 20220307
        // 新增移动类型 行政：安防领用 Z81\Z82 ———— 20221111
        if (!M_551.equals(movementType) && !M_Z56.equals(movementType) && !M_Z55.equals(movementType) &&
                !M_Z16.equals(movementType) && !M_309.equals(movementType) && !M_Z13.equals(movementType) &&
                !M_Z47.equals(movementType) && !M_561.equals(movementType) && !M_562.equals(movementType) &&

                !M_Z08.equals(movementType) && !M_Z10.equals(movementType) && !M_Z12.equals(movementType) &&
                !M_Z14.equals(movementType) && !M_Z18.equals(movementType) && !M_Z22.equals(movementType) &&
                !M_Z30.equals(movementType) && !M_Z42.equals(movementType) && !M_Z44.equals(movementType) &&
                !M_Z58.equals(movementType) && !M_Z62.equals(movementType) && !M_Z66.equals(movementType) &&
                !M_Z68.equals(movementType) && !M_Z70.equals(movementType) && !M_Z72.equals(movementType) &&
                !M_Z74.equals(movementType) && !M_Z80.equals(movementType) && !M_Z49.equals(movementType) &&
                !M_Z54.equals(movementType) && !M_Z81.equals(movementType) && !M_Z82.equals(movementType) &&
                !M_Z57.equals(movementType) && !M_Z15.equals(movementType) && !M_Z53.equals(movementType) && 
                !M_Z90.equals(movementType) && !M_Z92.equals(movementType) && !M_Z94.equals(movementType) && 
                !M_Z96.equals(movementType) && !M_552.equals(movementType) && !M_Z04.equals(movementType) && 
                !M_Z24.equals(movementType) && !M_Z86.equals(movementType) && !MoveOut311.equals(movementType) &&
                !MoveIn311.equals(movementType)){
            return ResponseResult.error("请求移动类型错误");
        }
        /** 收货多收Z16，需要校验输入交货单号等信息 */
//        2022年12月6日 -- 尧钦提需求不再强控收货多收交货单必填的校验 OA编码： 0901-2022110033N
//        if (M_Z16.equals(movementType)){
//            if (StringUtils.isEmpty(overseaOtherDTO.getSapDeliveryNote())){
//                return ResponseResult.error("收货多收Z16，交货单号不允许为空");
//            }
//        }
//        if (M_Z54.equals(movementType)){
//        	if (StringUtils.isEmpty(overseaOtherDTO.getSapDeliveryNote())){
//        		return ResponseResult.error("收货多收(生产)Z54，交货单号不允许为空");
//        	}
//        }
        /** 串货调整309，需校验输入调整前后物料编号都有值 */
        if (M_309.equals(movementType)){

        }
        return ResponseResult.success();
    }

    int createOverseaOtherTask(String uuid, OverseaOtherDTO overseaOtherDTO, String userId){
        OverseaOtherTask overseaOtherTask = new OverseaOtherTask();
        overseaOtherTask.setUuid(uuid);
        overseaOtherTask.setOperateTitle(overseaOtherDTO.getOperateTitle());
        overseaOtherTask.setMovementType(overseaOtherDTO.getMovementType());
        overseaOtherTask.setSpmsStatus(overseaOtherDTO.getSpmsStatus());
        overseaOtherTask.setWerks(overseaOtherDTO.getWerks());
        overseaOtherTask.setWorkshopCode(overseaOtherDTO.getWorkshopCode());
        overseaOtherTask.setWhsLocationCode(overseaOtherDTO.getWhsLocationCode());
        overseaOtherTask.setCreateDate(overseaOtherDTO.getCreateDate());
        overseaOtherTask.setSapDeliveryNote(overseaOtherDTO.getSapDeliveryNote());
        overseaOtherTask.setCreateUserid(userId);
        overseaOtherTask.setCostCenter(overseaOtherDTO.getCostCenter());
        overseaOtherTask.setRemarks(overseaOtherDTO.getRemarks());
        overseaOtherTask.setComments(overseaOtherDTO.getComments());
        overseaOtherTask.setFactoryType(overseaOtherDTO.getFactoryType());
        overseaOtherTask.setOtherWerks(overseaOtherDTO.getOtherWerks());
        overseaOtherTask.setOtherWhsLocationCode(overseaOtherDTO.getOtherWhsLocationCode());
        return this.baseMapper.insert(overseaOtherTask);
    }

    int createOtherDtl(String uuid, OverseaOtherDTO overseaOtherDTO){
        String werks = overseaOtherDTO.getWerks();
        String workshopCode = overseaOtherDTO.getWorkshopCode();
        String whsLocationCode = overseaOtherDTO.getWhsLocationCode();
        String costCenter = overseaOtherDTO.getCostCenter();
        String sapDeliveryNote = overseaOtherDTO.getSapDeliveryNote();
        List<OverseaOtherDtl> otherDtlList = overseaOtherDTO.getOtherDtlList();
        int i = 0;
        for (OverseaOtherDtl otherDtl : otherDtlList){
            OverseaOtherDtl overseaOtherDtl = new OverseaOtherDtl();
            overseaOtherDtl.setUuid(uuid);
            overseaOtherDtl.setItem(String.valueOf((i + 1) * 10));
            overseaOtherDtl.setWerks(werks);
            overseaOtherDtl.setWorkshopCode(workshopCode);
            overseaOtherDtl.setWhsLocationCode(whsLocationCode);
            overseaOtherDtl.setMaterialNo(otherDtl.getMaterialNo());
            overseaOtherDtl.setActualQtyBasicUnit(otherDtl.getActualQtyBasicUnit());
            overseaOtherDtl.setStorageInfo(otherDtl.getStorageInfo());
            overseaOtherDtl.setBasicUnit(otherDtl.getBasicUnit());
            overseaOtherDtl.setCostCenter(costCenter);
            overseaOtherDtl.setMaterialNoAdjusted(otherDtl.getMaterialNoAdjusted());
            overseaOtherDtl.setActualQtyBasicUnitAdjusted(otherDtl.getActualQtyBasicUnitAdjusted());
            overseaOtherDtl.setStorageInfoAdjusted(otherDtl.getStorageInfoAdjusted());
            overseaOtherDtl.setSupplierNo(otherDtl.getSupplierNo());
            overseaOtherDtl.setSapDeliveryNote(sapDeliveryNote);
            overseaOtherDtl.setSapDeliveryNoteItem(otherDtl.getSapDeliveryNoteItem());
            overseaOtherDtl.setRemarks(otherDtl.getRemarks());
            overseaOtherDtl.setComments(otherDtl.getComments());
            overseaOtherDtl.setActualQtyDeliveryUnit(otherDtl.getActualQtyDeliveryUnit());
            overseaOtherDtl.setDeliveryUnit(otherDtl.getDeliveryUnit());

            overseaOtherDtl.setInternalOrderNumber(otherDtl.getInternalOrderNumber());
            // 零价格出入库金额默认为空 2022-12-03 xzp add
            if (M_Z55.equals(overseaOtherDTO.getMovementType()) || M_Z56.equals(overseaOtherDTO.getMovementType())) {
            	overseaOtherDtl.setLocalCurrency(null);
            } else {
            	overseaOtherDtl.setLocalCurrency(otherDtl.getLocalCurrency());
            }
            if (iOverseaOtherDtlService.save(overseaOtherDtl)){
                i ++;
            }
        }
        return i;
    }

    /**
     1-1；保存修改
     1-2；提交审批：更新单据状态备注等信息，更新明细数量储位备注等信息；
     2-4；审批通过：更新单据状态，按行扣减/增加仓库库存；
     3-4；审批通过
     spmsStatus：SPMS状态(0已删除;1保存;2提交/待审批;3审批不通过;4审批通过;5提交SAP失败;6提交SAP成功;)
     movementType：报废出库551;零价格出库Z55;零价格入库Z56;收货多收Z16;串货调整309;不可抗力出库Z13;IT专用出库Z47;期初库存增加561;期初库存减少562;建安固定资产领用Z57;建安固定资产领用撤销Z58;
     出库 551, Z13, Z47, Z55, 562, Z57
     入库 Z56, Z16, 561
     有出有入 309

     领用出库冲销17种移动类型，增加库存：
     M_Z08, M_Z10, M_Z12, M_Z14, M_Z18, M_Z22, M_Z30, M_Z42, M_Z44, M_Z58, M_Z62, M_Z66, M_Z68, M_Z70, M_Z72, M_Z74, M_Z80
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult updateOtherTask(OverseaOtherUpdateDTO overseaOtherUpdateDTO, String userId) throws Exception {
//        try {
            ResponseResult checkResult = checkUpdate(overseaOtherUpdateDTO);
            if (checkResult.getCode() != SUCCESS){
                return checkResult;
            }
            String uuid = overseaOtherUpdateDTO.getUuid();
            String targetStatus = overseaOtherUpdateDTO.getSpmsStatus();

        if (OTHER_SUBMITTED.getCode().equals(targetStatus)){
            if("Z551".equals(overseaOtherUpdateDTO.getMovementType())){//旧件移动类型
                List<OverseaOtherDtl> otherDtlList = overseaOtherUpdateDTO.getOtherDtlList();
                for (OverseaOtherDtl otherDtl : otherDtlList){
                    if(StringUtils.isNotEmpty(otherDtl.getStorageInfo())){
                        JSONArray storageInfoArray = JSON.parseArray(otherDtl.getStorageInfo());
                        for(int i = 0; i<storageInfoArray.size(); i++) {
                            JSONObject storageInfo = storageInfoArray.getJSONObject(i);
                            if(StringUtils.isEmpty(storageInfo.get("storageUuid").toString()) ){
                                if(StringUtils.isEmpty(storageInfo.get("qty").toString()) ){
                                    int qty = Integer.parseInt(storageInfo.get("qty").toString());
                                    if(qty>0){
                                        throw new RuntimeException("物料："+otherDtl.getMaterialNo()+"请重新填充入库数量，选择入库出库！");
                                    }
                                }
                            }
                        }

                    }else{
                        throw new RuntimeException("物料："+otherDtl.getMaterialNo()+"请重新填充入库数量，选择入库出库！");
                    }

                }
            }
        }

            int updateOtherTask = updateOverseaOtherTask(overseaOtherUpdateDTO);
            if (updateOtherTask < 1){
                log.info("=======updateOverseaOtherTask RuntimeException=========\n");
                throw new RuntimeException("更新其他出入库任务表错误");
            }

            int updateOtherDtl = updateOverseaOtherDtl(overseaOtherUpdateDTO);
            if (updateOtherDtl < 1){
                log.info("=======updateOverseaOtherDtl RuntimeException=========\n");
                throw new RuntimeException("更新其他出入库任务明细表错误");
            }

            /** 审批通过，目标状态为 4 时需扣除或增加对应库存 */
            if (OTHER_APPROVED.getCode().equals(targetStatus)){
                ResponseResult updateStorageInventory = updateWhsStorageInventory(uuid, userId);
                if (updateStorageInventory.getCode() != SUCCESS){
                    log.info("=======RuntimeException=========\n" + updateStorageInventory.getMsg());
                    throw new RuntimeException("储位库存更新错误\n" + updateStorageInventory.getMsg());
                }
            }

            if (OTHER_SAVE.getCode().equals(targetStatus)){
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_SAVE.getDescZh(), OTHER_SAVE.getDescEn(), "", OTHER_SAVE.getDescRu());
            }
            if (OTHER_SUBMITTED.getCode().equals(targetStatus)){
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_SUBMITTED.getDescZh(), OTHER_SUBMITTED.getDescEn(), "", OTHER_SUBMITTED.getDescRu());
            }
            if (OTHER_APPROVED.getCode().equals(targetStatus)){
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_APPROVED.getDescZh(), OTHER_APPROVED.getDescEn(), "", OTHER_APPROVED.getDescRu());
            }
            return ResponseResult.success("其他出入库任务更新成功")
                    .add("otherTask", getOtherTaskInfo(uuid))
                    .add("otherDtlList", getOtherDtlList(uuid));
//        } catch (Exception e){
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error().add("error", e.getMessage());
//        }
    }

    /**
     1-1；保存修改
     1-2；提交审批：更新单据状态备注等信息，更新明细数量储位备注等信息；
     2-4；审批通过：更新单据状态，按行扣减/增加仓库库存；
     spmsStatus：SPMS状态(0已删除;1保存;2提交/待审批;3审批不通过;4审批通过;5提交SAP失败;6提交SAP成功;)
     movementType：报废出库551;零价格出库Z55;零价格入库Z56;收货多收Z16;串货调整309;不可抗力出库Z13;IT专用出库Z47;期初库存增加561;期初库存减少562;建安固定资产领用Z57;建安固定资产领用撤销Z58;
     出库 551, Z13, Z47, Z55, 562, Z57
     入库 Z56, Z16, 561
     有出有入 309

     领用出库冲销17种移动类型，增加库存：
     M_Z08, M_Z10, M_Z12, M_Z14, M_Z18, M_Z22, M_Z30, M_Z42, M_Z44, M_Z58, M_Z62, M_Z66, M_Z68, M_Z70, M_Z72, M_Z74, M_Z80
     */
    synchronized ResponseResult updateWhsStorageInventory(String uuid, String userId){
        OverseaOtherTask otherTask = getOtherTask(uuid);
        List<OverseaOtherDtl> otherDtlList = iOverseaOtherDtlService.getOverseaOtherDtlList(uuid);
        String werks = otherTask.getWerks();
        String whsLocationCode = otherTask.getWhsLocationCode();
        String movementType = otherTask.getMovementType();
        if (M_551.equals(movementType) || M_Z13.equals(movementType) || M_Z47.equals(movementType) || 
        		M_Z55.equals(movementType) || M_562.equals(movementType) || M_Z57.equals(movementType) ||
                M_Z81.equals(movementType) || M_Z85.equals(movementType) ||
                M_Z49.equals(movementType) || M_Z15.equals(movementType) || M_Z53.equals(movementType) || 
                MoveOut311.equals(movementType)){
            for (OverseaOtherDtl otherDtl : otherDtlList){
                String materialNo = otherDtl.getMaterialNo();
                String item = otherDtl.getItem();
                double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnit() == null ? 0 : otherDtl.getActualQtyBasicUnit();
                if (actualQtyBasicUnit > 0){
                    JSONArray storageInfoArray = JSONArray.parseArray(otherDtl.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, SUB);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 报废出库551;零价格出库Z55;零价格入库Z56;收货多收Z16;串货调整309;不可抗力出库Z13;IT专用出库Z47;期初库存增加561;期初库存减少562;建安固定资产领用Z57;建安固定资产领用撤销Z58; **/
                            String comments = M_551.equals(movementType) ? "报废出库" :  M_Z13.equals(movementType) ? "不可抗力出库" :
                                            M_Z47.equals(movementType) ? "IT专用出库" : M_Z55.equals(movementType) ? "零价格出库" :
                                            M_562.equals(movementType) ? "期初库存减少" : M_Z57.equals(movementType) ? "建安固定资产领用" : 
                                            M_Z49.equals(movementType) ? "报废出库(生产)" : M_Z15.equals(movementType) ? "收货少收(贸易)" :
                                            M_Z81.equals(movementType) ? "行政：安防领用" : M_Z85.equals(movementType) ? "生产领用(工量刃器具)" :
                                            M_Z53.equals(movementType) ? "收货少收(生产)" : MoveOut311.equals(movementType) ? "其他移出" : "其它出库";

                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE3, uuid, comments, userId, "海外仓其他出入库", werks, whsLocationCode, movementType, item);
                        }
                    }
                }
            }
        }
        if (M_Z56.equals(movementType) || M_Z16.equals(movementType) || M_561.equals(movementType) || M_Z54.equals(movementType)
                || M_Z551.equals(movementType) || MoveIn311.equals(movementType)){
            for (OverseaOtherDtl otherDtl : otherDtlList){
                String materialNo = otherDtl.getMaterialNo();
                String item = otherDtl.getItem();
                double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnit() == null ? 0 : otherDtl.getActualQtyBasicUnit();
                if (actualQtyBasicUnit > 0){
                    JSONArray storageInfoArray = JSONArray.parseArray(otherDtl.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, ADD);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 报废出库551;零价格出库Z55;零价格入库Z56;收货多收Z16;串货调整309;不可抗力出库Z13;IT专用出库Z47;期初库存增加561;期初库存减少562;建安固定资产领用Z57;建安固定资产领用撤销Z58; **/
                            String comments = M_Z56.equals(movementType) ? "零价格入库" :  M_Z16.equals(movementType) ? "收货多收" :
                                    M_561.equals(movementType) ? "期初库存增加" : M_Z551.equals(movementType) ? "旧件入库" : M_Z54.equals(movementType) ? "收货多收(生产)" : MoveIn311.equals(movementType) ? "其他移入" :"其它入库";

                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE2, uuid, comments, userId, "海外仓其他出入库", werks, whsLocationCode, movementType, item);
                        }
                    }
                }
            }
        }
        //领用出库冲销17种移动类型，增加库存：M_Z08, M_Z10, M_Z12, M_Z14, M_Z18, M_Z22, M_Z30, M_Z42, M_Z44, M_Z58, M_Z62, M_Z66, M_Z68, M_Z70, M_Z72, M_Z74, M_Z80
        if (M_Z08.equals(movementType) || M_Z10.equals(movementType) || M_Z12.equals(movementType) || M_Z14.equals(movementType) || M_Z18.equals(movementType)
                || M_Z22.equals(movementType) || M_Z30.equals(movementType) || M_Z42.equals(movementType) || M_Z44.equals(movementType) || M_Z58.equals(movementType)
                || M_Z62.equals(movementType) || M_Z66.equals(movementType) || M_Z68.equals(movementType) || M_Z70.equals(movementType) || M_Z72.equals(movementType)
                || M_Z82.equals(movementType) || M_Z86.equals(movementType)
                || M_Z74.equals(movementType) || M_Z80.equals(movementType) || M_Z90.equals(movementType) || M_Z92.equals(movementType) 
                || M_Z94.equals(movementType) || M_Z96.equals(movementType) || M_552.equals(movementType) || M_Z04.equals(movementType) 
                || M_Z24.equals(movementType)){
            for (OverseaOtherDtl otherDtl : otherDtlList){
                String materialNo = otherDtl.getMaterialNo();
                String item = otherDtl.getItem();
                double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnit() == null ? 0 : otherDtl.getActualQtyBasicUnit();
                if (actualQtyBasicUnit > 0){
                    JSONArray storageInfoArray = JSONArray.parseArray(otherDtl.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, ADD);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 办公领用冲销Z08、样品领用冲销Z10、生活领用冲销Z12、不可抗力出库冲销Z14、检测领用冲销Z18、仓库工具领用冲销Z22、生产领用(原料及包材)冲销Z30、生产领用(燃料及动力)冲销Z42、
                             * 生产领用(备品备件)冲销Z44、建安固定资产冲销Z58、生产领用（机物料消耗)-冲销Z62、生产领用（生产耗材）-冲销Z66、车辆使用（生产）-冲销Z68、车辆维修领用（非生产）-冲销Z70、
                             * 车辆燃油领用（非生产）-冲销Z72、劳保领用-冲销Z74、生产发电领用冲销Z80 **/
                            //领用出库冲销17种移动类型，增加库存：M_Z08, M_Z10, M_Z12, M_Z14, M_Z18, M_Z22, M_Z30, M_Z42, M_Z44, M_Z58, M_Z62, M_Z66, M_Z68, M_Z70, M_Z72, M_Z74, M_Z80
                            String comments = M_Z08.equals(movementType) ? "办公领用冲销" : M_Z10.equals(movementType) ? "样品领用冲销" : M_Z12.equals(movementType) ? "生活领用冲销" :
                                    M_Z14.equals(movementType) ? "不可抗力出库冲销" : M_Z18.equals(movementType) ? "检测领用冲销" : M_Z22.equals(movementType) ? "仓库工具领用冲销" :
                                    M_Z30.equals(movementType) ? "生产领用(原料及包材)冲销" : M_Z42.equals(movementType) ? "生产领用(燃料及动力)冲销" : M_Z44.equals(movementType) ? "生产领用(备品备件)冲销" :
                                    M_Z58.equals(movementType) ? "建安固定资产冲销" : M_Z62.equals(movementType) ? "生产领用（机物料消耗)-冲销" : M_Z66.equals(movementType) ? "生产领用（生产耗材）-冲销" :
                                    M_Z68.equals(movementType) ? "车辆使用（生产）-冲销" : M_Z70.equals(movementType) ? "车辆维修领用（非生产）-冲销" : M_Z72.equals(movementType) ? "车辆燃油领用（非生产）-冲销" :
                                    M_Z82.equals(movementType) ? "行政：安防领用-冲销" : M_Z86.equals(movementType) ? "生产领用(工量刃器具)-冲销" :
                                    M_Z74.equals(movementType) ? "劳保领用-冲销" : M_Z80.equals(movementType) ? "生产发电领用冲销" : M_Z90.equals(movementType) ? "仓库叉车燃油领用冲销" : 
                                    M_Z92.equals(movementType) ? "仓库叉车维修领用冲销" : M_Z94.equals(movementType) ? "仓库工具（托盘&绑带）领冲销" : M_Z96.equals(movementType) ? "仓库其他工具领用冲销" :
                                    M_552.equals(movementType) ? "报废出库冲销": M_Z04.equals(movementType) ? "促销物料领用冲销": M_Z24.equals(movementType) ? "其他公司领用冲销": "其它入库";
                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE2, uuid, comments, userId, "海外仓其他出入库", werks, whsLocationCode, movementType, item);
                        }
                    }
                }
            }
        }
        if (M_309.equals(movementType)){
            for (OverseaOtherDtl otherDtl : otherDtlList){
                String materialNo = otherDtl.getMaterialNo();
                String item = otherDtl.getItem();
                double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnit() == null ? 0 : otherDtl.getActualQtyBasicUnit();
                if (actualQtyBasicUnit > 0){
                    JSONArray storageInfoArray = JSONArray.parseArray(otherDtl.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, SUB);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 报废出库551;零价格出库Z55;零价格入库Z56;收货多收Z16;串货调整309;不可抗力出库Z13;IT专用出库Z47;期初库存增加561;期初库存减少562;建安固定资产领用Z57;建安固定资产领用撤销Z58; **/
                            String comments = "串货调整出库";
                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE3, uuid, comments, userId, "海外仓其他出入库", werks, whsLocationCode, movementType, item);
                        }
                    }
                }
                String materialNoAdjusted = otherDtl.getMaterialNoAdjusted();
                double actualQtyBasicUnitAdjusted = otherDtl.getActualQtyBasicUnitAdjusted() == null ? 0 : otherDtl.getActualQtyBasicUnitAdjusted();
                if (actualQtyBasicUnitAdjusted > 0){
                    JSONArray storageInfoArrayAdjusted = JSONArray.parseArray(otherDtl.getStorageInfoAdjusted());
                    for (int i = 0; i < storageInfoArrayAdjusted.size(); i ++){
                        JSONObject storageInfoObj = storageInfoArrayAdjusted.getJSONObject(i);
                        String storageUuidAdjusted = storageInfoObj.getString("storageUuid");
                        double qty = storageInfoObj.getDoubleValue("qty");
                        if (qty > 0){
                            ResponseResult updateInventory = iWhsStorageInventoryService.updateWhsStorageInventory(storageUuidAdjusted, materialNoAdjusted, qty, ADD);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            String comments = "串货调整入库";
                            iWhsOperateLogService.insertWhsOperateLog(storageUuidAdjusted, materialNoAdjusted, qty, OPERATION_TYPE2, uuid, comments, userId, "海外仓其他出入库", werks, whsLocationCode, movementType, item);
                        }
                    }
                }
            }
        }
        return ResponseResult.success();
    }

    int updateOverseaOtherTask(OverseaOtherUpdateDTO overseaOtherUpdateDTO){
        OverseaOtherTask overseaOtherTask = new OverseaOtherTask();
        String uuid = overseaOtherUpdateDTO.getUuid();
        QueryWrapper<OverseaOtherTask> queryWrapper = new QueryWrapper<OverseaOtherTask>().eq("UUID", uuid);
        overseaOtherTask.setOperateTitle(overseaOtherUpdateDTO.getOperateTitle());
        overseaOtherTask.setSpmsStatus(overseaOtherUpdateDTO.getSpmsStatus());
        overseaOtherTask.setCostCenter(overseaOtherUpdateDTO.getCostCenter());
        overseaOtherTask.setRemarks(StringUtils.isEmpty(overseaOtherUpdateDTO.getRemarks()) ? "-" : overseaOtherUpdateDTO.getRemarks());
        overseaOtherTask.setComments(StringUtils.isEmpty(overseaOtherTask.getComments()) ? "-" : overseaOtherTask.getComments());
        overseaOtherTask.setMovementType(overseaOtherUpdateDTO.getMovementType());
        overseaOtherTask.setFactoryType(overseaOtherUpdateDTO.getFactoryType());
        overseaOtherTask.setPdaSN(StringUtils.isNotEmpty(overseaOtherUpdateDTO.getPdaSN()) ? overseaOtherUpdateDTO.getPdaSN() : "");
        overseaOtherTask.setPdaTime(StringUtils.isNotEmpty(overseaOtherUpdateDTO.getPdaTime()) ? overseaOtherUpdateDTO.getPdaTime() : "");
        return this.baseMapper.update(overseaOtherTask, queryWrapper);
    }

    int updateOverseaOtherDtl(OverseaOtherUpdateDTO overseaOtherUpdateDTO){
        String uuid = overseaOtherUpdateDTO.getUuid();
        String costCenter = overseaOtherUpdateDTO.getCostCenter();
        List<OverseaOtherDtl> otherDtlList = overseaOtherUpdateDTO.getOtherDtlList();
        int i = 0;
        for (OverseaOtherDtl otherDtl : otherDtlList){
            OverseaOtherDtl overseaOtherDtl = new OverseaOtherDtl();
            String item = otherDtl.getItem();
            QueryWrapper<OverseaOtherDtl> queryWrapper = new QueryWrapper<OverseaOtherDtl>().eq("UUID", uuid).eq("ITEM", item);
            overseaOtherDtl.setActualQtyBasicUnit(otherDtl.getActualQtyBasicUnit());
            overseaOtherDtl.setStorageInfo(otherDtl.getStorageInfo());
            overseaOtherDtl.setCostCenter(costCenter);
            overseaOtherDtl.setMaterialNoAdjusted(otherDtl.getMaterialNoAdjusted());
            overseaOtherDtl.setActualQtyBasicUnitAdjusted(otherDtl.getActualQtyBasicUnitAdjusted());
            overseaOtherDtl.setStorageInfoAdjusted(otherDtl.getStorageInfoAdjusted());
            overseaOtherDtl.setSupplierNo(otherDtl.getSupplierNo());
            overseaOtherDtl.setSapDeliveryNoteItem(otherDtl.getSapDeliveryNoteItem());
            overseaOtherDtl.setRemarks(StringUtils.isEmpty(otherDtl.getRemarks()) ? "-" : otherDtl.getRemarks());
            overseaOtherDtl.setComments(StringUtils.isEmpty(otherDtl.getComments()) ? "-" : otherDtl.getComments());
            overseaOtherDtl.setActualQtyDeliveryUnit(otherDtl.getActualQtyDeliveryUnit());
            overseaOtherDtl.setDeliveryUnit(otherDtl.getDeliveryUnit());

            overseaOtherDtl.setInternalOrderNumber(otherDtl.getInternalOrderNumber());
            // 零价格出入库金额默认0.01 2022-12-03 xzp add
            if (M_Z55.equals(overseaOtherUpdateDTO.getMovementType()) || M_Z56.equals(overseaOtherUpdateDTO.getMovementType())) {
            	overseaOtherDtl.setLocalCurrency(0.01);
            } else {
            	overseaOtherDtl.setLocalCurrency(otherDtl.getLocalCurrency());
            }
            if (iOverseaOtherDtlService.update(overseaOtherDtl, queryWrapper)){
                i ++;
            }
        }
        return i;
    }

    /***
     1-1；保存修改
     1-2；提交审批：更新单据状态备注等信息，更新明细数量储位备注等信息；—— 出库操作需检查库存是否够扣
     2-4；审批通过：更新单据状态，按行扣减/增加仓库库存；—— 出库操作需检查库存是否够扣
     出库 551, Z13, Z47, Z55, 562, Z57
     入库 Z56, Z16, 561
     有出有入 309
     */
    ResponseResult checkUpdate(OverseaOtherUpdateDTO overseaOtherUpdateDTO){
        if (overseaOtherUpdateDTO == null){
            return ResponseResult.error("请求参数错误");
        }
        String targetStatus = overseaOtherUpdateDTO.getSpmsStatus();
        if (StringUtils.isEmpty(targetStatus)){
            return ResponseResult.error("请求参数目标状态错误");
        }
        String uuid = overseaOtherUpdateDTO.getUuid();
        if (StringUtils.isEmpty(uuid)){
            return ResponseResult.error("请求其他出入库任务参数uuid不能为空");
        }
        OverseaOtherTask overseaOtherTask = getOtherTask(uuid);
        if (!overseaOtherTask.getDataVersion().equals(overseaOtherUpdateDTO.getDataVersion())){
            return ResponseResult.error("其他出入库任务信息已更新请刷新后重试");
        }
        String spmsId = overseaOtherTask.getSpmsId();
        String currentStatus = overseaOtherTask.getSpmsStatus();
        String movementType = overseaOtherTask.getMovementType();
        List<OverseaOtherDtl> otherDtlList = overseaOtherUpdateDTO.getOtherDtlList();
        if (!OTHER_SAVE.getCode().equals(currentStatus) && !OTHER_SUBMITTED.getCode().equals(currentStatus)
                && !OTHER_REJECT.getCode().equals(currentStatus)){
            return ResponseResult.error("其他出入库任务当前状态禁止此操作");
        }
        if (OTHER_SAVE.getCode().equals(targetStatus)){

        } else if (OTHER_SUBMITTED.getCode().equals(targetStatus) || OTHER_APPROVED.getCode().equals(targetStatus)){
            if (M_551.equals(movementType) || M_Z13.equals(movementType) || M_Z47.equals(movementType) ||
                    M_Z55.equals(movementType) || M_562.equals(movementType) || M_Z57.equals(movementType) ||
                    M_309.equals(movementType) || M_Z49.equals(movementType) || M_Z15.equals(movementType) ||
                    M_Z53.equals(movementType) || MoveOut311.equals(movementType)){
                //提交审批 1-2，或 审批通过 2-4，有库存扣减的操作，需要检查单据明细行每行物料库存是否够扣减；
                for (OverseaOtherDtl otherDtl : otherDtlList){
                    String item = otherDtl.getItem();
                    String materialNo = otherDtl.getMaterialNo();
                    String storageInfo = otherDtl.getStorageInfo();
                    double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnit();
                    if (actualQtyBasicUnit > 0){
                        if (StringUtils.isEmpty(storageInfo)){
                            return ResponseResult.error(spmsId + "实出数量大于0的行:" + item + "，料号:" + materialNo + "储位信息无效");
                        }
                        //storageInfoArray 结构参考：[{"storageUuid":"cbd9576a4e53461fe0530101007f3e24","qty":5,"storageNo":"A010101","unitValue":5}]
                        JSONArray storageInfoArray = JSONArray.parseArray(storageInfo);
                        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 + "可用库存不足");
                                }
                            }
                        }
                    }
                }
            }
        } else {
            return ResponseResult.error("其他出入库任务请求目标状态错误");
        }
        return ResponseResult.success();
    }

    /** 新增明细行 */
    @Override
    public synchronized ResponseResult updateOtherDtlListI(List<OverseaOtherDtl> otherDtlList, String userId) {
        if (otherDtlList == null || otherDtlList.size() == 0){
            return ResponseResult.error("请求参数错误");
        }
        String uuid = otherDtlList.get(0).getUuid();
        OverseaOtherTask overseaOtherTask = getOtherTask(uuid);
        if (overseaOtherTask == null){
            return ResponseResult.error("请求其他出入库任务不存在");
        }
        Integer maxItemNumber = this.baseMapper.getOtherTaskMaxItemNumber(uuid);
        for (int i = 0; i < otherDtlList.size(); i ++){
            OverseaOtherDtl otherDtl = otherDtlList.get(i);
            otherDtl.setUuid(uuid);
            otherDtl.setItem(String.valueOf((i + 1) * 10 + maxItemNumber));
            otherDtl.setWerks(overseaOtherTask.getWerks());
            otherDtl.setWhsLocationCode(overseaOtherTask.getWhsLocationCode());
            otherDtl.setWorkshopCode(overseaOtherTask.getWorkshopCode());
            otherDtl.setCostCenter(overseaOtherTask.getCostCenter());
            iOverseaOtherDtlService.save(otherDtl);
        }
        iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_UPDATE.getDescZh(), OTHER_UPDATE.getDescEn(), "", OTHER_UPDATE.getDescRu());
        return ResponseResult.success("其他出入库任务明细更新成功").add("otherDtlList", getOtherDtlList(uuid));
    }

    /** 删除明细行 */
    @Override
    public synchronized ResponseResult updateOtherDtlListD(List<OverseaOtherDtl> otherDtlList, String userId) {
        if (otherDtlList == null || otherDtlList.size() == 0){
            return ResponseResult.error("请求参数错误");
        }
        String uuid = "";
        for (OverseaOtherDtl otherDtl : otherDtlList){
            uuid = otherDtl.getUuid();
            String item = otherDtl.getItem();
            if (StringUtils.isNotEmpty(uuid) && StringUtils.isNotEmpty(item)){
                QueryWrapper<OverseaOtherDtl> queryWrapper = new QueryWrapper<OverseaOtherDtl>().eq("UUID", uuid).eq("ITEM", item);
                iOverseaOtherDtlService.remove(queryWrapper);
            }
        }
        iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_UPDATE.getDescZh(), OTHER_UPDATE.getDescEn(), "", OTHER_UPDATE.getDescRu());
        return ResponseResult.success("其他出入库任务明细更新成功").add("otherDtlList", getOtherDtlList(uuid));
    }

    /** 提交SAP；4-5/6、5-5/6 */
    @SuppressWarnings("unchecked")
	@Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult submitOtherTaskSap(String uuid, String costCenter, String postingDate, Integer dataVersion, String userId)throws Exception  {
//        try {
            ResponseResult checkResult = checkToSap(uuid, costCenter, postingDate, dataVersion);
            if (checkResult.getCode() != SUCCESS){
                return checkResult;
            }
            QueryWrapper<OverseaOtherTask> queryWrapper = new QueryWrapper<OverseaOtherTask>().eq("UUID", uuid);
            OverseaOtherTask overseaOtherTask = getOtherTask(uuid);

            Map<String, Object> otherTaskHead = this.baseMapper.otherTaskHead(uuid, postingDate);
            List<Map<String, Object>> otherDtlItem = this.baseMapper.otherDtlItem(uuid, StringUtils.isEmpty(costCenter) || "null".equals(costCenter.trim()) ? "" : costCenter);
            if (otherTaskHead == null || otherDtlItem == null || otherDtlItem.size() == 0){
                return ResponseResult.error("查询无可提交SAP项目");
            }
            if("02".equals(overseaOtherTask.getDocumentType())){//旧件物料
                overseaOtherTask.setPostingDate(postingDate);
                if (StringUtils.isNotEmpty(costCenter) && !"null".equals(costCenter.trim())){
                    overseaOtherTask.setCostCenter(costCenter);
                }
                overseaOtherTask.setSpmsStatus(OTHER_SUBMIT_SAP.getCode());
                this.baseMapper.update(overseaOtherTask, queryWrapper);

                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_SUBMIT_SAP.getDescZh(),
                        OTHER_SUBMIT_SAP.getDescEn(), sapLog, "", "", "其他出入库提交过账成功", OTHER_SUBMIT_SAP.getDescRu());
                return ResponseResult.success("其他出入库提交过账成功").add("otherTask", getOtherTaskInfo(uuid));
            }
            if (MoveIn311.equals(overseaOtherTask.getMovementType())) {
            	otherTaskHead.put("BWART", "311");
            	for (int i = 0; i < otherDtlItem.size(); i++) {
            		Map<String, Object> map = otherDtlItem.get(i);
            		map.put("LGORT", overseaOtherTask.getOtherWhsLocationCode());
            	}
            }
            if (MoveOut311.equals(overseaOtherTask.getMovementType())) {
            	otherTaskHead.put("BWART", "311");
            	otherTaskHead.put("LGORT", overseaOtherTask.getOtherWhsLocationCode());
            	for (int i = 0; i < otherDtlItem.size(); i++) {
            		Map<String, Object> map = otherDtlItem.get(i);
            		map.put("LGORT", overseaOtherTask.getWhsLocationCode());
            	}
            }
            JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(otherTaskHead, otherDtlItem, "Z_SPMS_ANOMALY_POST", "ANOMALY_POST");
            // 根据工厂查询对应的SAP Clinet
            List<ZSapOrgClient> selectList = zSapOrgClientMapper.selectList(new QueryWrapper<ZSapOrgClient>().eq("WERKS", otherTaskHead.get("WERKS")));
            if (CollectionUtils.isNotEmpty(selectList)) {
                JSONObject obj = dataToSap.getJSONObject("REQUEST").getJSONObject("ESB_ATTRS");
                obj.put("Target_ID", "SAP-"+selectList.get(0).getZmandt());
            } else {
                return ResponseResult.error("工厂："+otherTaskHead.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_Undercharged = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
            if (SAP_SUCCESS.equals(RETURN_DATA_Undercharged.getString("O_TYPE"))) {
                String sapVoucherNumber = RETURN_DATA_Undercharged.getString("O_MBLNR").trim();
                String sapVoucherYear = RETURN_DATA_Undercharged.getString("O_MJAHR").trim();
                overseaOtherTask.setPostingDate(postingDate);
                if (StringUtils.isNotEmpty(costCenter) && !"null".equals(costCenter.trim())){
                    overseaOtherTask.setCostCenter(costCenter);
                }
                overseaOtherTask.setSapVoucherNumber(sapVoucherNumber);
                overseaOtherTask.setSapVoucherYear(sapVoucherYear);
                overseaOtherTask.setSpmsStatus(OTHER_SUBMIT_SAP.getCode());
                this.baseMapper.update(overseaOtherTask, queryWrapper);

                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_SUBMIT_SAP.getDescZh() + ":" + sapVoucherNumber,
                        OTHER_SUBMIT_SAP.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "其他出入库提交SAP成功", OTHER_SUBMIT_SAP.getDescRu());
                try {
                	JSONArray costArray = RETURN_DATA_Undercharged.getJSONArray("IT_COST");
                	if (costArray != null && costArray.size() > 0) {
                		List<OverseaOtherDtl> itemList = new ArrayList<OverseaOtherDtl>();
                		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) {
                				OverseaOtherDtl dtl = new OverseaOtherDtl();
                				String zeile = (String) map.get("ZEILE1");
                				String zeileRepla = zeile.replaceAll("^(0+)", "");
                				dtl.setUuid(uuid);
                				dtl.setItem(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<OverseaOtherDtl>> partition = Lists.partition(itemList, 1000);
                				for (List<OverseaOtherDtl> pa : partition) {
                					this.baseMapper.updateBatchDtl(pa);
                				}
                			} else {
                				this.baseMapper.updateBatchDtl(itemList);
                			}
                		}
                	}
                } catch (Exception e) {
                }
                
                return ResponseResult.success("其他出入库任务提交SAP成功").add("otherTask", getOtherTaskInfo(uuid));
            } else {
                overseaOtherTask.setPostingDate(postingDate);
                overseaOtherTask.setCostCenter(costCenter);
                overseaOtherTask.setSpmsStatus(OTHER_SUBMIT_SAP_ERROR.getCode());
                this.baseMapper.update(overseaOtherTask, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_SUBMIT_SAP_ERROR.getDescZh(),
                        OTHER_SUBMIT_SAP_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "其他出入库提交SAP失败", OTHER_SUBMIT_SAP_ERROR.getDescRu());
                return ResponseResult.error("其他出入库任务提交SAP失败")
                        .add("sapReturnedMessage", message)
                        .add("dataToSap", dataToSap)
                        .add("otherTask", getOtherTaskInfo(uuid));
            }
//        }catch (FeignException feignException){
//            feignException.printStackTrace();
//            return ResponseResult.error("请求SAP失败 FeignException").add("error", feignException.getMessage());
//        }catch (Exception e){
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error("其他出入库任务更新单据或提交SAP失败 Exception").add("error", e.getMessage());
//        }
    }

    /**
     movementType：报废出库551;零价格出库Z55;零价格入库Z56;收货多收Z16;串货调整309;不可抗力出库Z13;IT专用出库Z47;期初库存增加561;期初库存减少562;建安固定资产领用Z57;建安固定资产领用撤销Z58;
     出库 551, Z13, Z47, Z55, 562, Z57; 入库 Z56, Z16, 561; 有出有入 309;
     561, 562 提交SAP不需要成本中心；

     */
    ResponseResult checkToSap(String uuid, String costCenter, String postingDate, Integer dataVersion){
        if (StringUtils.isEmpty(uuid) || StringUtils.isEmpty(postingDate) || dataVersion == null){
            return ResponseResult.error("请求参数错误");
        }
        OverseaOtherTask overseaOtherTask = getOtherTask(uuid);
        if (overseaOtherTask == null){
            return ResponseResult.error("请求其他出入库任务不存在");
        }
        if (!dataVersion.equals(overseaOtherTask.getDataVersion())){
            return ResponseResult.error("请求其他出入库任务已更新请刷新重试");
        }
        String spmsStatus = overseaOtherTask.getSpmsStatus();
        if (!OTHER_APPROVED.getCode().equals(spmsStatus) && !OTHER_SUBMIT_SAP_ERROR.getCode().equals(spmsStatus)){
            return ResponseResult.error("请求其他出入库任务当前状态禁止此操作");
        }
        String movementType = overseaOtherTask.getMovementType();
        if (M_551.equals(movementType) || M_Z13.equals(movementType) || M_Z47.equals(movementType) || M_Z55.equals(movementType)
                || M_Z56.equals(movementType) || M_Z16.equals(movementType) || M_309.equals(movementType)
                || M_Z49.equals(movementType) || M_Z54.equals(movementType) || M_Z15.equals(movementType) || M_Z53.equals(movementType)){
            if (StringUtils.isEmpty(costCenter)){
                return ResponseResult.error("成本中心不允许为空");
            }
        }
        return ResponseResult.success();
    }

    /** 任务回撤；2-3(审批不通过)、6-4、4/5-1(库存操作)
     * spmsStatus：SPMS状态(0已删除;1保存;2提交/待审批;3审批不通过;4审批通过;5提交SAP失败;6提交SAP成功;)*/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult cancelOtherTask(String uuid, String cancelPostingDate, Integer dataVersion, String userId)throws Exception  {
//        try {
            ResponseResult checkResult = checkCancel(uuid, cancelPostingDate, dataVersion);
            if (checkResult.getCode() != SUCCESS){
                return checkResult;
            }
            QueryWrapper<OverseaOtherTask> queryWrapper = new QueryWrapper<OverseaOtherTask>().eq("UUID", uuid);
            OverseaOtherTask overseaOtherTask = getOtherTask(uuid);
            String spmsStatus = overseaOtherTask.getSpmsStatus();
            if (OTHER_SUBMITTED.getCode().equals(spmsStatus)){
                overseaOtherTask.setSpmsStatus(OTHER_REJECT.getCode());
                this.baseMapper.update(overseaOtherTask, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_REJECT.getDescZh(), OTHER_REJECT.getDescEn(), "", OTHER_REJECT.getDescRu());
                return ResponseResult.success("其他出入库任务审批不通过").add("otherTask", getOtherTaskInfo(uuid));
            }else if (OTHER_SUBMIT_SAP.getCode().equals(spmsStatus)){
                Map<String, Object> dataHeadCancel = this.baseMapper.dataHeadCancel(uuid, cancelPostingDate);
                if (dataHeadCancel == null){
                    return ResponseResult.error("查询无可提交SAP项目");
                }
                if("02".equals(overseaOtherTask.getDocumentType())){//旧件物料
                    overseaOtherTask.setCancelPostingDate(cancelPostingDate);
                    overseaOtherTask.setSpmsStatus(OTHER_APPROVED.getCode());
                    this.baseMapper.update(overseaOtherTask, queryWrapper);

                    iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_SUBMIT_SAP.getDescZh(),
                            OTHER_SUBMIT_SAP.getDescEn(), sapLog, "", "", "其他出入库撤销提交过账成功", OTHER_SUBMIT_SAP.getDescRu());
                    return ResponseResult.success("其他出入库撤销提交过账成功").add("otherTask", getOtherTaskInfo(uuid));
                }
                JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(dataHeadCancel, null, "Z_SPMS_CANCEL", "SPMS_CANCEL");
                // 根据工厂查询对应的SAP Clinet
                List<ZSapOrgClient> clinetList = zSapOrgClientMapper.selectList(new QueryWrapper<ZSapOrgClient>().eq("WERKS", overseaOtherTask.getWerks()));
                if (!CollectionUtils.isEmpty(clinetList)) {
                	JSONObject esbObj = dataToSap.getJSONObject("REQUEST").getJSONObject("ESB_ATTRS");
                	esbObj.put("Target_ID", "SAP-"+clinetList.get(0).getZmandt());
                } else {
                	return ResponseResult.error("工厂："+overseaOtherTask.getWerks()+"未找到对应的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 cancelVoucherNumber = RETURN_DATA.getString("0_MBLNR");
                    overseaOtherTask.setCancelPostingDate(cancelPostingDate);
                    overseaOtherTask.setCancelVoucherNumber(cancelVoucherNumber);
                    overseaOtherTask.setSpmsStatus(OTHER_APPROVED.getCode());
                    this.baseMapper.update(overseaOtherTask, queryWrapper);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_CANCEL_TO_APPROVED.getDescZh() + ":" + cancelVoucherNumber,
                            OTHER_CANCEL_TO_APPROVED.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "其他出入库任务撤销提交SAP", OTHER_CANCEL_TO_APPROVED.getDescRu());
                    return ResponseResult.success("其他出入库任务撤销提交SAP成功").add("otherTask", getOtherTaskInfo(uuid));
                } else {
                    overseaOtherTask.setCancelPostingDate(cancelPostingDate);
                    this.baseMapper.update(overseaOtherTask, queryWrapper);
                    iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_CANCEL_ERROR.getDescZh(),
                            OTHER_CANCEL_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "其他出入库任务撤销提交SAP", OTHER_CANCEL_ERROR.getDescRu());
                    return ResponseResult.error("其他出入库任务撤销提交SAP失败")
                            .add("sapReturnedMessage", message)
                            .add("dataToSap", dataToSap)
                            .add("otherTask", getOtherTaskInfo(uuid));
                }
            } else if (OTHER_APPROVED.getCode().equals(spmsStatus) || OTHER_SUBMIT_SAP_ERROR.getCode().equals(spmsStatus)){
                ResponseResult updateStorageInventory = cancelUpdateWhsStorageInventory(overseaOtherTask, userId);
                if (updateStorageInventory.getCode() != SUCCESS){
                    log.info("=======RuntimeException=========\n" + updateStorageInventory.getMsg());
                    throw new RuntimeException("储位库存更新错误\n" + updateStorageInventory.getMsg());
                }
                overseaOtherTask.setSpmsStatus(OTHER_CANCEL_TO_SAVE.getCode());
                this.baseMapper.update(overseaOtherTask, queryWrapper);
                iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, OTHER_CANCEL_TO_SAVE.getDescZh(), OTHER_CANCEL_TO_SAVE.getDescEn(), "", OTHER_CANCEL_TO_SAVE.getDescRu());
                return ResponseResult.success("其他出入库任务撤回成功").add("otherTask", getOtherTaskInfo(uuid));
            } else {
                return ResponseResult.error("其他出入库任务当前状态禁止此操作");
            }
//        }catch (FeignException feignException){
//            feignException.printStackTrace();
//            return ResponseResult.error("请求SAP失败 FeignException").add("error", feignException.getMessage());
//        }catch (Exception e){
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error("其他出入库任务更新单据或提交SAP失败 Exception").add("error", e.getMessage());
//        }
    }

    /***
     SPMS状态(0已删除;1保存;2提交/待审批;3审批不通过;4审批通过;5提交SAP失败;6提交SAP成功;)
     2-3(审批不通过)
     6-4；撤回SAP凭证；
     4/5-1；撤回到审批通过之前，原入库类型(Z56, Z16, 309)需检查出库库存是否足够扣减；
     出库 551, Z13, Z47, Z55, 562, Z57
     入库 Z56, Z16, 561
     有出有入 309

     561, 562, Z57 禁止回撤；

     领用出库冲销17种移动类型，增加库存的操作，禁止回撤：
     M_Z08, M_Z10, M_Z12, M_Z14, M_Z18, M_Z22, M_Z30, M_Z42, M_Z44, M_Z58, M_Z62, M_Z66, M_Z68, M_Z70, M_Z72, M_Z74, M_Z80
     */
    ResponseResult checkCancel(String uuid, String cancelPostingDate, Integer dataVersion){
        if (StringUtils.isEmpty(uuid) || dataVersion == null){
            return ResponseResult.error("请求参数错误");
        }
        OverseaOtherTask overseaOtherTask = getOtherTask(uuid);
        if (overseaOtherTask == null){
            return ResponseResult.error("请求其他出入库任务不存在");
        }
        if (!dataVersion.equals(overseaOtherTask.getDataVersion())){
            return ResponseResult.error("请求其他出入库任务已更新请刷新重试");
        }
        String movementType = overseaOtherTask.getMovementType();
        String spmsStatus = overseaOtherTask.getSpmsStatus();
        if (!OTHER_SUBMITTED.getCode().equals(spmsStatus) && !OTHER_APPROVED.getCode().equals(spmsStatus)
                && !OTHER_SUBMIT_SAP_ERROR.getCode().equals(spmsStatus) && !OTHER_SUBMIT_SAP.getCode().equals(spmsStatus)){
            return ResponseResult.error("请求其他出入库任务当前状态禁止此操作");
        }
        if (OTHER_SUBMIT_SAP.getCode().equals(spmsStatus)){
        	// 吴尧钦：提交SAP成功状态下进行撤销不根据移动类型来控制 2022-09-05 xzp update
//            if (M_561.equals(movementType) || M_562.equals(movementType)){
//                return ResponseResult.error("期初数据禁止此操作");
//            }
//            if (M_Z57.equals(movementType)){
//                return ResponseResult.error("建安固定资产领用禁止此操作");
//            }
//            if (M_Z08.equals(movementType) || M_Z10.equals(movementType) || M_Z12.equals(movementType) || M_Z14.equals(movementType) || M_Z18.equals(movementType)
//                    || M_Z22.equals(movementType) || M_Z30.equals(movementType) || M_Z42.equals(movementType) || M_Z44.equals(movementType) || M_Z58.equals(movementType)
//                    || M_Z62.equals(movementType) || M_Z66.equals(movementType) || M_Z68.equals(movementType) || M_Z70.equals(movementType) || M_Z72.equals(movementType)
//                    || M_Z74.equals(movementType) || M_Z80.equals(movementType)){
//                return ResponseResult.error("领用出库冲销数据禁止此操作");
//            }
            if (StringUtils.isEmpty(cancelPostingDate)){
                return ResponseResult.error("撤销SAP凭证过账日期不能为空");
            }
            if (StringUtils.isEmpty(overseaOtherTask.getSapVoucherNumber())){
                return ResponseResult.error("撤销SAP凭证不存在");
            }
        }
        if (OTHER_APPROVED.getCode().equals(spmsStatus) || OTHER_SUBMIT_SAP_ERROR.getCode().equals(spmsStatus)){
//            if (M_561.equals(movementType) || M_562.equals(movementType)){
//                return ResponseResult.error("期初数据禁止此操作");
//            }
            String spmsId = overseaOtherTask.getSpmsId();
            if (M_Z56.equals(movementType) || M_Z16.equals(movementType)|| M_Z54.equals(movementType) || M_561.equals(movementType) || 
            		MoveIn311.equals(movementType)){
                List<OverseaOtherDtl> otherDtlList = iOverseaOtherDtlService.getOverseaOtherDtlList(uuid);
                for (OverseaOtherDtl otherDtl : otherDtlList){
                    String item = otherDtl.getItem();
                    String materialNo = otherDtl.getMaterialNo();
                    String storageInfo = otherDtl.getStorageInfo();
                    double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnit();
                    if (actualQtyBasicUnit > 0){
                        if (StringUtils.isEmpty(storageInfo)){
                            return ResponseResult.error(spmsId + "实出数量大于0的行:" + item + "，料号:" + materialNo + "储位信息无效");
                        }
                        //storageInfoArray 结构参考：[{"storageUuid":"cbd9576a4e53461fe0530101007f3e24","qty":5,"storageNo":"A010101","unitValue":5}]
                        JSONArray storageInfoArray = JSONArray.parseArray(storageInfo);
                        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 + "可用库存不足");
                                }
                            }
                        }
                    }
                }
            }
            if (M_Z08.equals(movementType) || M_Z10.equals(movementType) || M_Z12.equals(movementType) || M_Z14.equals(movementType) || M_Z18.equals(movementType)
                    || M_Z22.equals(movementType) || M_Z30.equals(movementType) || M_Z42.equals(movementType) || M_Z44.equals(movementType) || M_Z58.equals(movementType)
                    || M_Z62.equals(movementType) || M_Z66.equals(movementType) || M_Z68.equals(movementType) || M_Z70.equals(movementType) || M_Z72.equals(movementType)
                    || M_Z74.equals(movementType) || M_Z80.equals(movementType) || M_Z90.equals(movementType) || M_Z92.equals(movementType) || M_Z94.equals(movementType)
                    || M_Z96.equals(movementType) || M_552.equals(movementType) || M_Z04.equals(movementType) || M_Z24.equals(movementType) || M_Z86.equals(movementType)) {
            	List<OverseaOtherDtl> otherDtlList = iOverseaOtherDtlService.getOverseaOtherDtlList(uuid);
                for (OverseaOtherDtl otherDtl : otherDtlList){
                    String item = otherDtl.getItem();
                    String materialNo = otherDtl.getMaterialNo();
                    String storageInfo = otherDtl.getStorageInfo();
                    double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnit();
                    if (actualQtyBasicUnit > 0){
                        if (StringUtils.isEmpty(storageInfo)){
                            return ResponseResult.error(spmsId + "实出数量大于0的行:" + item + "，料号:" + materialNo + "储位信息无效");
                        }
                        //storageInfoArray 结构参考：[{"storageUuid":"cbd9576a4e53461fe0530101007f3e24","qty":5,"storageNo":"A010101","unitValue":5}]
                        JSONArray storageInfoArray = JSONArray.parseArray(storageInfo);
                        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 + "可用库存不足");
                                }
                            }
                        }
                    }
                }
            }
            if (M_309.equals(movementType)){
                List<OverseaOtherDtl> otherDtlList = iOverseaOtherDtlService.getOverseaOtherDtlList(uuid);
                for (OverseaOtherDtl otherDtl : otherDtlList){
                    String item = otherDtl.getItem();
                    String materialNo = otherDtl.getMaterialNoAdjusted();
                    String storageInfo = otherDtl.getStorageInfoAdjusted();
                    double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnitAdjusted();
                    if (actualQtyBasicUnit > 0){
                        if (StringUtils.isEmpty(storageInfo)){
                            return ResponseResult.error(spmsId + "调整数量大于0的行:" + item + "，料号:" + materialNo + "储位信息无效");
                        }
                        //storageInfoArray 结构参考：[{"storageUuid":"cbd9576a4e53461fe0530101007f3e24","qty":5,"storageNo":"A010101","unitValue":5}]
                        JSONArray storageInfoArray = JSONArray.parseArray(storageInfo);
                        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("串货调整行号" + item + "物料号" + materialNo + "在储位" + storageNo + "无可用库存");
                                }
                                if (qty > whsStorageInventory.getAvailableQty()){
                                    return ResponseResult.error("串货调整行号" + item + "物料号" + materialNo + "在储位" + storageNo + "可用库存不足");
                                }
                            }
                        }
                    }
                }
            }
        }
        return ResponseResult.success();
    }

    synchronized ResponseResult cancelUpdateWhsStorageInventory(OverseaOtherTask otherTask, String userId){
        String uuid = otherTask.getUuid();
        String werks = otherTask.getWerks();
        String whsLocationCode = otherTask.getWhsLocationCode();
        String movementType = otherTask.getMovementType();
        List<OverseaOtherDtl> otherDtlList = iOverseaOtherDtlService.getOverseaOtherDtlList(uuid);
        if (M_551.equals(movementType) || M_Z13.equals(movementType) || M_Z47.equals(movementType) || 
        		M_Z55.equals(movementType) || M_Z57.equals(movementType) || M_Z49.equals(movementType) ||
                M_Z81.equals(movementType) || M_Z85.equals(movementType) ||
        		M_562.equals(movementType) || M_Z15.equals(movementType) || M_Z53.equals(movementType) || 
        		MoveOut311.equals(movementType)){
            for (OverseaOtherDtl otherDtl : otherDtlList){
                String materialNo = otherDtl.getMaterialNo();
                String item = otherDtl.getItem();
                double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnit() == null ? 0 : otherDtl.getActualQtyBasicUnit();
                if (actualQtyBasicUnit > 0){
                    JSONArray storageInfoArray = JSONArray.parseArray(otherDtl.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, ADD);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 报废出库551;零价格出库Z55;零价格入库Z56;收货多收Z16;串货调整309;不可抗力出库Z13;IT专用出库Z47;期初库存增加561;期初库存减少562; 建安固定资产领用Z57;建安固定资产领用撤销Z58;**/
                            String comments = M_551.equals(movementType) ? "报废出库撤销" :  M_Z13.equals(movementType) ? "不可抗力出库撤销" :
                                    M_Z47.equals(movementType) ? "IT专用出库撤销" : M_Z55.equals(movementType) ? "零价格出库撤销" : 
                                    	M_Z57.equals(movementType) ? "建安固定资产领用撤销" : M_Z49.equals(movementType) ? "报废出库(生产)撤销" :
                                        M_Z81.equals(movementType) ? "行政：安防领用撤销" : M_Z85.equals(movementType) ? "生产领用(工量刃器具)撤销" :
                                    		M_Z15.equals(movementType) ? "收货少收(贸易)撤销" : M_Z53.equals(movementType) ? "收货少收(生产)撤销" : MoveOut311.equals(movementType) ? "其他移出撤销" : "其它出库撤销";

                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE2, uuid, comments, userId, "海外仓其他出入库撤销", werks, whsLocationCode, movementType, item);
                        }
                    }
                }
            }
        }
        if (M_Z56.equals(movementType) || M_Z16.equals(movementType) || M_Z54.equals(movementType) || M_561.equals(movementType)
                || M_Z551.equals(movementType) || MoveIn311.equals(movementType)){
            for (OverseaOtherDtl otherDtl : otherDtlList){
                String materialNo = otherDtl.getMaterialNo();
                String item = otherDtl.getItem();
                double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnit() == null ? 0 : otherDtl.getActualQtyBasicUnit();
                if (actualQtyBasicUnit > 0){
                    JSONArray storageInfoArray = JSONArray.parseArray(otherDtl.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, SUB);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 报废出库551;零价格出库Z55;零价格入库Z56;收货多收Z16;串货调整309;不可抗力出库Z13;IT专用出库Z47;期初库存增加561;期初库存减少562; 建安固定资产领用Z57;建安固定资产领用撤销Z58;**/
                            String comments = M_Z56.equals(movementType) ? "零价格入库撤销" :  M_Z16.equals(movementType) ? "收货多收撤销" :
                                    M_Z551.equals(movementType) ? "旧件入库" : M_Z54.equals(movementType) ? "收货多收(生产)撤销" : MoveIn311.equals(movementType) ? "其他移入撤销" : "其它入库撤销";

                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE3, uuid, comments, userId, "海外仓其他出入库撤销", werks, whsLocationCode, movementType, item);
                        }
                    }
                }
            }
        }
        if (M_Z08.equals(movementType) || M_Z10.equals(movementType) || M_Z12.equals(movementType) || M_Z14.equals(movementType) || M_Z18.equals(movementType)
                || M_Z22.equals(movementType) || M_Z30.equals(movementType) || M_Z42.equals(movementType) || M_Z44.equals(movementType) || M_Z58.equals(movementType)
                || M_Z62.equals(movementType) || M_Z66.equals(movementType) || M_Z68.equals(movementType) || M_Z70.equals(movementType) || M_Z72.equals(movementType)
                || M_Z82.equals(movementType) || M_Z86.equals(movementType)
                || M_Z74.equals(movementType) || M_Z80.equals(movementType) || M_Z90.equals(movementType) || M_Z92.equals(movementType) || M_Z94.equals(movementType)
                || M_Z96.equals(movementType) || M_552.equals(movementType) || M_Z04.equals(movementType) || M_Z24.equals(movementType)){
            for (OverseaOtherDtl otherDtl : otherDtlList){
                String materialNo = otherDtl.getMaterialNo();
                String item = otherDtl.getItem();
                double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnit() == null ? 0 : otherDtl.getActualQtyBasicUnit();
                if (actualQtyBasicUnit > 0){
                    JSONArray storageInfoArray = JSONArray.parseArray(otherDtl.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, SUB);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 办公领用冲销Z08、样品领用冲销Z10、生活领用冲销Z12、不可抗力出库冲销Z14、检测领用冲销Z18、仓库工具领用冲销Z22、生产领用(原料及包材)冲销Z30、生产领用(燃料及动力)冲销Z42、
                             * 生产领用(备品备件)冲销Z44、建安固定资产冲销Z58、生产领用（机物料消耗)-冲销Z62、生产领用（生产耗材）-冲销Z66、车辆使用（生产）-冲销Z68、车辆维修领用（非生产）-冲销Z70、
                             * 车辆燃油领用（非生产）-冲销Z72、劳保领用-冲销Z74、生产发电领用冲销Z80 **/
                            //领用出库冲销17种移动类型，增加库存：M_Z08, M_Z10, M_Z12, M_Z14, M_Z18, M_Z22, M_Z30, M_Z42, M_Z44, M_Z58, M_Z62, M_Z66, M_Z68, M_Z70, M_Z72, M_Z74, M_Z80
                            String comments = M_Z08.equals(movementType) ? "办公领用冲销撤销" : M_Z10.equals(movementType) ? "样品领用冲销撤销" : M_Z12.equals(movementType) ? "生活领用冲销撤销" :
                                    M_Z14.equals(movementType) ? "不可抗力出库冲销撤销撤销" : M_Z18.equals(movementType) ? "检测领用冲销撤销" : M_Z22.equals(movementType) ? "仓库工具领用冲销撤销" :
                                    M_Z30.equals(movementType) ? "生产领用(原料及包材)冲销撤销" : M_Z42.equals(movementType) ? "生产领用(燃料及动力)冲销撤销" : M_Z44.equals(movementType) ? "生产领用(备品备件)冲销撤销" :
                                    M_Z58.equals(movementType) ? "建安固定资产冲销撤销" : M_Z62.equals(movementType) ? "生产领用（机物料消耗)-冲销撤销" : M_Z66.equals(movementType) ? "生产领用（生产耗材）-冲销撤销" :
                                    M_Z68.equals(movementType) ? "车辆使用（生产）-冲销撤销" : M_Z70.equals(movementType) ? "车辆维修领用（非生产）-冲销撤销" : M_Z72.equals(movementType) ? "车辆燃油领用（非生产）-冲销撤销" :
                                    M_Z82.equals(movementType) ? "行政：安防领用-冲销" : M_Z86.equals(movementType) ? "生产领用(工量刃器具)-冲销" :
                                    M_Z74.equals(movementType) ? "劳保领用-冲销撤销" : M_Z80.equals(movementType) ? "生产发电领用冲销撤销" : M_Z90.equals(movementType) ? "仓库叉车燃油领用冲销撤销" :
                                    M_Z92.equals(movementType) ? "仓库叉车维修领用冲销撤销": M_Z94.equals(movementType) ? "仓库工具（托盘&绑带）领用冲销撤销": M_Z96.equals(movementType) ? "仓库其他工具领用冲销撤销":
                                    M_552.equals(movementType) ? "报废出库冲销撤销": M_Z04.equals(movementType) ? "促销物料领用冲销撤销": M_Z24.equals(movementType) ? "其他公司领用冲销撤销": "其它入库撤销";
                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE3, uuid, comments, userId, "海外仓其他出入库撤销", werks, whsLocationCode, movementType, item);
                        }
                    }
                }
            }
        }
        if (M_309.equals(movementType)){
            for (OverseaOtherDtl otherDtl : otherDtlList){
                String materialNo = otherDtl.getMaterialNo();
                String item = otherDtl.getItem();
                double actualQtyBasicUnit = otherDtl.getActualQtyBasicUnit() == null ? 0 : otherDtl.getActualQtyBasicUnit();
                if (actualQtyBasicUnit > 0){
                    JSONArray storageInfoArray = JSONArray.parseArray(otherDtl.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, ADD);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            /** 报废出库551;零价格出库Z55;零价格入库Z56;收货多收Z16;串货调整309;不可抗力出库Z13;IT专用出库Z47;期初库存增加561;期初库存减少562; 建安固定资产领用Z57;建安固定资产领用撤销Z58;**/
                            String comments = "串货调整出库撤销";
                            iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, OPERATION_TYPE2, uuid, comments, userId, "海外仓其他出入库撤销", werks, whsLocationCode, movementType, item);
                        }
                    }
                }
                String materialNoAdjusted = otherDtl.getMaterialNoAdjusted();
                double actualQtyBasicUnitAdjusted = otherDtl.getActualQtyBasicUnitAdjusted() == null ? 0 : otherDtl.getActualQtyBasicUnitAdjusted();
                if (actualQtyBasicUnitAdjusted > 0){
                    JSONArray storageInfoArrayAdjusted = JSONArray.parseArray(otherDtl.getStorageInfoAdjusted());
                    for (int i = 0; i < storageInfoArrayAdjusted.size(); i ++){
                        JSONObject storageInfoObj = storageInfoArrayAdjusted.getJSONObject(i);
                        String storageUuidAdjusted = storageInfoObj.getString("storageUuid");
                        double qty = storageInfoObj.getDoubleValue("qty");
                        if (qty > 0){
                            ResponseResult updateInventory = iWhsStorageInventoryService.updateWhsStorageInventory(storageUuidAdjusted, materialNoAdjusted, qty, SUB);
                            if (updateInventory.getCode() != SUCCESS){
                                return updateInventory;
                            }
                            String comments = "串货调整入库撤销";
                            iWhsOperateLogService.insertWhsOperateLog(storageUuidAdjusted, materialNoAdjusted, qty, OPERATION_TYPE3, uuid, comments, userId, "海外仓其他出入库撤销", werks, whsLocationCode, movementType, item);
                        }
                    }
                }
            }
        }
        return ResponseResult.success();
    }

	@Override
	public ResponseResult getOverseaOtherTaskHead(String spmsId) {
		if (StringUtils.isEmpty(spmsId)) {
			ResponseResult.error("SPMS单号为空，请求失败");
		}
		// 查询其他出入库头信息
		OverseaOtherTask headVO = this.baseMapper.selectOne(new QueryWrapper<OverseaOtherTask>().eq("SPMS_ID", spmsId));
		// 查询其他出入库行项目信息
		List<Map<String, Object>> otherDtlList = iOverseaOtherDtlService.getOtherDtlList(headVO != null ? headVO.getUuid() : "");
		return ResponseResult.success().add("headVO", headVO).add("itemList", otherDtlList);
	}


    @Override
    public List<OverseaOtherTask> findListByRecord(String relateDocument) {
        if (StringUtils.isEmpty(relateDocument)){
            return null;
        }
        QueryWrapper<OverseaOtherTask> queryWrapper = new QueryWrapper<OverseaOtherTask>().eq("RELATE_DOCUMENT", relateDocument);
        return this.baseMapper.selectList(queryWrapper);
    }

    /** 更新退库申请每一行实际移动类型，然后根据类型的不同拆分其他出入库任务； */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult generateOverseaOtherTask(OverseaOtherTaskGenerateDTO overseaOtherTaskGenerateDTO, String userId) throws Exception {
        ResponseResult checkResult = checkGenerateOverseaOtherTask(overseaOtherTaskGenerateDTO);
        if (checkResult.getCode() != SUCCESS){
            return checkResult;
        }
        String uuidRequisition = overseaOtherTaskGenerateDTO.getUuidRequisition();

        QueryWrapper<EamReturnSku> overseaRequisitionQueryWrapper = new QueryWrapper<EamReturnSku>().eq("UUID_REQUISITION", uuidRequisition);
        EamReturnSku oRequisition = new EamReturnSku();
        oRequisition.setCostCenter(overseaOtherTaskGenerateDTO.getCostCenter());
        oRequisition.setCostCenterName(overseaOtherTaskGenerateDTO.getCostCenterName());
        iEamReturnSkuService.update(oRequisition, overseaRequisitionQueryWrapper);

        List<EamReturnSkuDtlDTO> overseaRequisitionDtlDTOList = overseaOtherTaskGenerateDTO.getEamReturnSkuDtlDTOList();
        for (EamReturnSkuDtlDTO dto : overseaRequisitionDtlDTOList){
            String actualMovementType = dto.getActualMovementType();
            Integer item = dto.getItem();
            QueryWrapper<EamReturnSkuDtl> queryWrapper = new QueryWrapper<EamReturnSkuDtl>()
                    .eq("UUID_REQUISITION", uuidRequisition).eq("ITEM", item);
            EamReturnSkuDtl overseaRequisitionDtl = new EamReturnSkuDtl();
            overseaRequisitionDtl.setActualMovementType(actualMovementType);
            iEamReturnSkuDtlService.update(overseaRequisitionDtl, queryWrapper);
        }

        String createDate = overseaOtherTaskGenerateDTO.getCreateDate();
        EamReturnSku eamReturnSku = iEamReturnSkuService.getEamReturnSku(uuidRequisition);
        String relateDocument = eamReturnSku.getSpmsId();
        List<EamReturnSkuDtl> overseaRequisitionDtlList = iEamReturnSkuDtlService.getEamReturnSkuDtls(uuidRequisition);

        Set<String> set = new HashSet<>();
        for (EamReturnSkuDtl overseaRequisitionDtl : overseaRequisitionDtlList){
            double actualBasicUnit = overseaRequisitionDtl.getActualQtyBasicUnit();
            if (actualBasicUnit > 0){
                set.add(overseaRequisitionDtl.getActualMovementType());
            }
        }
        for (String movementType : set){
            String uuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
            createOverseaOtherTaskByEam(uuid, eamReturnSku, userId,movementType);
            int i = 0;
            for (EamReturnSkuDtl eamReturnSkuDtl : overseaRequisitionDtlList){
                String actualMovementType = eamReturnSkuDtl.getActualMovementType();
                double actualBasicUnit = eamReturnSkuDtl.getActualQtyBasicUnit();
                if (movementType.equals(actualMovementType) && actualBasicUnit > 0){
                    Integer item = (i + 1) * 10;
                    createOtherDtlByEam(uuid, item,eamReturnSkuDtl,movementType,eamReturnSku.getCostCenter());
                    i ++;
                }
            }
            iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, "新建入库任务", "Create a repository task", "", "Новые задачи складирования");
        }

        updateEamReturnSku(eamReturnSku, "1");//已生成入库单
        iOverseaOperateLogService.addOverseaOperateLog(userId, eamReturnSku.getUuidRequisition(), "已生成其他出入库", "Other repositories have been generated", "", "Созданы другие хранилища");

        QueryWrapper<OverseaOtherTask> queryWrapper = new QueryWrapper<OverseaOtherTask>()
                .eq("RELATE_DOCUMENT", relateDocument).orderByAsc("SPMS_ID");

        if(eamReturnSku!=null && StringUtils.isNotEmpty(eamReturnSku.getRequestnum())){//退库单是EAM创建的
            List<OverseaOtherTask> outs = this.baseMapper.selectList(queryWrapper);
            if(outs!=null && outs.size()>0){
                String outIds = "";
                for (OverseaOtherTask out : outs){
                    outIds = outIds+out.getSpmsId()+",";
                }
                if(outIds.length()>0){
                    outIds = outIds.substring(0,outIds.length()-1 );
                }
                JSONObject dataToSap = formatDataToSap(eamReturnSku.getRelateDocument(),"0",outIds);
                JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
                JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
                if (!"10000".equals(RETURN_DATA.getString("code"))) {
                    throw new Exception("出库推送EAM接口异常！");
                }
            }
        }
        return ResponseResult.success()
                .add("whsOutList", this.baseMapper.selectList(queryWrapper))
                .add("eamReturnSku", iEamReturnSkuService.getEamReturnSku(uuidRequisition))
                .add("overseaRequisitionDtlList", iEamReturnSkuDtlService.getEamReturnSkuDtls(uuidRequisition));
    }

    ResponseResult checkGenerateOverseaOtherTask(OverseaOtherTaskGenerateDTO overseaOtherTaskGenerateDTO){
        if (overseaOtherTaskGenerateDTO == null){
            return ResponseResult.error("请求参数错误");
        }
        String uuidRequisition = overseaOtherTaskGenerateDTO.getUuidRequisition();
        String createDate = overseaOtherTaskGenerateDTO.getCreateDate();
        Integer dataVersion = overseaOtherTaskGenerateDTO.getDataVersion();
        if (StringUtils.isEmpty(uuidRequisition) || StringUtils.isEmpty(createDate) || INVALID_DATE.equals(createDate)){
            return ResponseResult.error("请求参数错误");
        }
        EamReturnSku eamReturnSku = iEamReturnSkuService.getEamReturnSku(uuidRequisition);
        if (eamReturnSku == null){
            return ResponseResult.error("退库申请查询不存在");
        }
        if (!dataVersion.equals(eamReturnSku.getDataVersion())){
            return ResponseResult.error("数据已刷新请刷新后重试");
        }
        if (!eamReturnSku.getSpmsStatus().equals(REQUISITION_APPROVED.getCode())){
            return ResponseResult.error("退库申请当前状态禁止此操作");
        }
        List<EamReturnSkuDtlDTO> overseaRequisitionDtlDTOList = overseaOtherTaskGenerateDTO.getEamReturnSkuDtlDTOList();
        if (overseaRequisitionDtlDTOList == null || overseaRequisitionDtlDTOList.size() == 0){
            return ResponseResult.error("请求参数明细行数据为空");
        }
        for (EamReturnSkuDtlDTO dto : overseaRequisitionDtlDTOList){
            String actualMovementType = dto.getActualMovementType();
            if (StringUtils.isEmpty(actualMovementType)){
                return ResponseResult.error("退库申请明细行" + dto.getItem() + "实际移动类型为空");
            }
        }
        return ResponseResult.success();
    }


    /** 更新退库申请每一行实际移动类型，然后根据类型的不同拆分其他出入库任务； */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult generateFormerOtherTask(OverseaOtherTaskGenerateFormerDTO overseaOtherTaskGenerateDTO, String userId) throws Exception {
        ResponseResult checkResult = checkGenerateFormerOtherTask(overseaOtherTaskGenerateDTO);
        if (checkResult.getCode() != SUCCESS){
            return checkResult;
        }
        String uuidRequisition = overseaOtherTaskGenerateDTO.getUuidRequisition();

        QueryWrapper<EamFormerSku> overseaRequisitionQueryWrapper = new QueryWrapper<EamFormerSku>().eq("UUID_REQUISITION", uuidRequisition);
        EamFormerSku oRequisition = new EamFormerSku();
        oRequisition.setCostCenter(overseaOtherTaskGenerateDTO.getCostCenter());
        oRequisition.setCostCenterName(overseaOtherTaskGenerateDTO.getCostCenterName());
        iEamFormerSkuService.update(oRequisition, overseaRequisitionQueryWrapper);

        List<EamFormerSkuDtlDTO> overseaRequisitionDtlDTOList = overseaOtherTaskGenerateDTO.getEamReturnSkuDtlDTOList();
        for (EamFormerSkuDtlDTO dto : overseaRequisitionDtlDTOList){
            String actualMovementType = dto.getActualMovementType();
            Integer item = dto.getItem();
            QueryWrapper<EamFormerSkuDtl> queryWrapper = new QueryWrapper<EamFormerSkuDtl>()
                    .eq("UUID_REQUISITION", uuidRequisition).eq("ITEM", item);
            EamFormerSkuDtl overseaRequisitionDtl = new EamFormerSkuDtl();
            overseaRequisitionDtl.setActualMovementType(actualMovementType);
            iEamFormerSkuDtlService.update(overseaRequisitionDtl, queryWrapper);
        }

        String createDate = overseaOtherTaskGenerateDTO.getCreateDate();
        EamFormerSku eamFormerSku = iEamFormerSkuService.getEamFormerSku(uuidRequisition);
        String relateDocument = eamFormerSku.getSpmsId();
        List<EamFormerSkuDtl> overseaRequisitionDtlList = iEamFormerSkuDtlService.getEamFormerSkuDtls(uuidRequisition);

        Set<String> set = new HashSet<>();
        for (EamFormerSkuDtl overseaRequisitionDtl : overseaRequisitionDtlList){
            double actualBasicUnit = overseaRequisitionDtl.getActualQtyBasicUnit();
            if (actualBasicUnit > 0){
                set.add(overseaRequisitionDtl.getActualMovementType());
            }
        }
        for (String movementType : set){
            String uuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
            createOverseaOtherTaskByEamFormer(uuid, eamFormerSku, userId,movementType);
            int i = 0;
            for (EamFormerSkuDtl eamFormerSkuDtl : overseaRequisitionDtlList){
                String actualMovementType = eamFormerSkuDtl.getActualMovementType();
                double actualBasicUnit = eamFormerSkuDtl.getActualQtyBasicUnit();
                if (movementType.equals(actualMovementType) && actualBasicUnit > 0){
                    Integer item = (i + 1) * 10;
                    createOtherDtlByEamFormer(uuid, item,eamFormerSkuDtl,movementType,eamFormerSku.getCostCenter());
                    i ++;
                }
            }
            iOverseaOperateLogService.addOverseaOperateLog(userId, uuid, "新建入库任务", "Create a repository task", "", "Новые задачи складирования");
        }

        updateEamFormerSku(eamFormerSku, "1");//已生成入库单
        iOverseaOperateLogService.addOverseaOperateLog(userId, eamFormerSku.getUuidRequisition(), "已生成其他出入库", "Other repositories have been generated", "", "Созданы другие хранилища");

        QueryWrapper<OverseaOtherTask> queryWrapper = new QueryWrapper<OverseaOtherTask>()
                .eq("RELATE_DOCUMENT", relateDocument).orderByAsc("SPMS_ID");

        List<OverseaOtherTask> outs = this.baseMapper.selectList(queryWrapper);
        if(outs!=null && outs.size()>0){
            String outIds = "";
            for (OverseaOtherTask out : outs){
                outIds = outIds+out.getSpmsId()+",";
            }
            if(outIds.length()>0){
                outIds = outIds.substring(0,outIds.length()-1 );
            }
            JSONObject dataToSap = formatFormerDataToSap(eamFormerSku.getRelateDocument(),"0",outIds);
            JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
            JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
            if (!"10000".equals(RETURN_DATA.getString("code"))) {
                throw new Exception("出库推送EAM接口异常！");
            }
        }
        return ResponseResult.success()
                .add("whsOutList", this.baseMapper.selectList(queryWrapper))
                .add("eamFormerSku", iEamFormerSkuService.getEamFormerSku(uuidRequisition))
                .add("overseaRequisitionDtlList", iEamFormerSkuDtlService.getEamFormerSkuDtls(uuidRequisition));
    }

    ResponseResult checkGenerateFormerOtherTask(OverseaOtherTaskGenerateFormerDTO overseaOtherTaskGenerateDTO){
        if (overseaOtherTaskGenerateDTO == null){
            return ResponseResult.error("请求参数错误");
        }
        String uuidRequisition = overseaOtherTaskGenerateDTO.getUuidRequisition();
        String createDate = overseaOtherTaskGenerateDTO.getCreateDate();
        Integer dataVersion = overseaOtherTaskGenerateDTO.getDataVersion();
        if (StringUtils.isEmpty(uuidRequisition) || StringUtils.isEmpty(createDate) || INVALID_DATE.equals(createDate)){
            return ResponseResult.error("请求参数错误");
        }
        EamFormerSku eamReturnSku = iEamFormerSkuService.getEamFormerSku(uuidRequisition);
        if (eamReturnSku == null){
            return ResponseResult.error("旧件申请查询不存在");
        }
        if (!dataVersion.equals(eamReturnSku.getDataVersion())){
            return ResponseResult.error("数据已刷新请刷新后重试");
        }
        if (!eamReturnSku.getSpmsStatus().equals("0")){
            return ResponseResult.error("旧件申请当前状态禁止此操作");
        }
        List<EamFormerSkuDtlDTO> overseaRequisitionDtlDTOList = overseaOtherTaskGenerateDTO.getEamReturnSkuDtlDTOList();
        if (overseaRequisitionDtlDTOList == null || overseaRequisitionDtlDTOList.size() == 0){
            return ResponseResult.error("请求参数明细行数据为空");
        }
        for (EamFormerSkuDtlDTO dto : overseaRequisitionDtlDTOList){
            String actualMovementType = dto.getActualMovementType();
            if (StringUtils.isEmpty(actualMovementType)){
                return ResponseResult.error("旧件申请明细行" + dto.getItem() + "实际移动类型为空");
            }
        }
        return ResponseResult.success();
    }



    private JSONObject formatDataToSap(String overseaRequisitionNum,String state,String outNum) {
        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", outNum);//入库单号
        data.put("STATE", state);//状态（0=已完成，1=已撤回）
        head.put("OVDATA", data);
        REQUEST_DATA.put("SendData", head);
        REQUEST_DATA.put("Operation", "Z_SPMS_RETURN_SKU_TO_EAM");
        REQUEST_DATA.put("Type", "RETURN_SKU_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;
    }



    private JSONObject formatFormerDataToSap(String overseaRequisitionNum,String state,String outNum) {
        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", outNum);//入库单号
        data.put("STATE", state);//状态（0=已完成，1=已撤回）
        head.put("OVDATA", data);
        REQUEST_DATA.put("SendData", head);
        REQUEST_DATA.put("Operation", "Z_SPMS_FORMER_SKU_TO_EAM");
        REQUEST_DATA.put("Type", "FORMER_SKU_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;
    }

    boolean updateEamReturnSku(EamReturnSku eamReturnSku, String spmsStatus){
        eamReturnSku.setSpmsStatus(spmsStatus);
        return iEamReturnSkuService.update(eamReturnSku, new QueryWrapper<EamReturnSku>().eq("UUID_REQUISITION", eamReturnSku.getUuidRequisition()));
    }

    boolean updateEamFormerSku(EamFormerSku eamFormerSku, String spmsStatus){
        eamFormerSku.setSpmsStatus(spmsStatus);
        return iEamFormerSkuService.update(eamFormerSku, new QueryWrapper<EamFormerSku>().eq("UUID_REQUISITION", eamFormerSku.getUuidRequisition()));
    }


    int createOverseaOtherTaskByEam(String uuid, EamReturnSku eamReturnSku, String userId,String movementType){
        OverseaOtherTask overseaOtherTask = new OverseaOtherTask();
        overseaOtherTask.setUuid(uuid);
        overseaOtherTask.setOperateTitle(eamReturnSku.getComments());
        overseaOtherTask.setMovementType(movementType);
        overseaOtherTask.setSpmsStatus(eamReturnSku.getSpmsStatus());
        overseaOtherTask.setWerks(eamReturnSku.getWerks());
        overseaOtherTask.setWorkshopCode(eamReturnSku.getWorkshopCode());
        overseaOtherTask.setWhsLocationCode(eamReturnSku.getWhsLocationCode());
        overseaOtherTask.setCreateDate(eamReturnSku.getCreateDate());
        //overseaOtherTask.setSapDeliveryNote(eamReturnSku.getSapDeliveryNote());
        overseaOtherTask.setCreateUserid(userId);
        overseaOtherTask.setCostCenter(eamReturnSku.getCostCenter());
        overseaOtherTask.setRemarks(eamReturnSku.getRemarks());
        overseaOtherTask.setComments(eamReturnSku.getComments());
        overseaOtherTask.setRelateDocument(eamReturnSku.getSpmsId());
        //overseaOtherTask.setFactoryType(eamReturnSku.getFactoryType());
        return this.baseMapper.insert(overseaOtherTask);
    }

    int createOtherDtlByEam(String uuid,Integer item, EamReturnSkuDtl otherDtl,String movementType,String costCenter){
        String werks = otherDtl.getWerks();
        String workshopCode = otherDtl.getWorkshopCode();
        String whsLocationCode = otherDtl.getWhsLocationCode();
        //String costCenter = otherDtl.getCostCenter();
        //String sapDeliveryNote = eamReturnSkuDtl.getSapDeliveryNote();
        int i = 0;
        OverseaOtherDtl overseaOtherDtl = new OverseaOtherDtl();
        overseaOtherDtl.setUuid(uuid);
        overseaOtherDtl.setItem(item+"");
        overseaOtherDtl.setWerks(werks);
        overseaOtherDtl.setWorkshopCode(workshopCode);
        overseaOtherDtl.setWhsLocationCode(whsLocationCode);
        overseaOtherDtl.setMaterialNo(otherDtl.getMaterialNo());
        overseaOtherDtl.setActualQtyBasicUnit(otherDtl.getActualQtyBasicUnit());
        overseaOtherDtl.setStorageInfo(otherDtl.getStorageInfo());
        overseaOtherDtl.setBasicUnit(otherDtl.getBasicUnit());
        overseaOtherDtl.setCostCenter(costCenter);
        //overseaOtherDtl.setMaterialNoAdjusted(otherDtl.getMaterialNoAdjusted());
        //overseaOtherDtl.setActualQtyBasicUnitAdjusted(otherDtl.getActualQtyBasicUnitAdjusted());
       // overseaOtherDtl.setStorageInfoAdjusted(otherDtl.getStorageInfo());
        //overseaOtherDtl.setSupplierNo(otherDtl.getSupplierNo());
        //overseaOtherDtl.setSapDeliveryNote(sapDeliveryNote);
        //overseaOtherDtl.setSapDeliveryNoteItem(otherDtl.getSapDeliveryNoteItem());
        overseaOtherDtl.setRemarks(otherDtl.getRemarks());
        overseaOtherDtl.setComments(otherDtl.getRemarks());

        //overseaOtherDtl.setActualQtyDeliveryUnit(otherDtl.getActualQtyDeliveryUnit());
        //overseaOtherDtl.setDeliveryUnit(otherDtl.getDeliveryUnit());

        overseaOtherDtl.setInternalOrderNumber(otherDtl.getProjectOaNumber());
        // 零价格出入库金额默认为空 2022-12-03 xzp add
//        if (M_Z55.equals(movementType) || M_Z56.equals(movementType)) {
//            overseaOtherDtl.setLocalCurrency(null);
//        } else {
//            overseaOtherDtl.setLocalCurrency(otherDtl.getLocalCurrency());
//        }
        if (iOverseaOtherDtlService.save(overseaOtherDtl)){
            i ++;
        }
        return i;
    }

    int createOverseaOtherTaskByEamFormer(String uuid, EamFormerSku eamSku, String userId,String movementType){
        OverseaOtherTask overseaOtherTask = new OverseaOtherTask();
        overseaOtherTask.setUuid(uuid);
        overseaOtherTask.setOperateTitle(eamSku.getComments());
        overseaOtherTask.setMovementType(movementType);
        overseaOtherTask.setSpmsStatus("1");//保存状态
        overseaOtherTask.setWerks(eamSku.getWerks());
        overseaOtherTask.setWorkshopCode(eamSku.getWorkshopCode());
        overseaOtherTask.setWhsLocationCode(eamSku.getWhsLocationCode());
        overseaOtherTask.setCreateDate(eamSku.getCreateDate());
        //overseaOtherTask.setSapDeliveryNote(eamSku.getSapDeliveryNote());
        overseaOtherTask.setCreateUserid(userId);
        overseaOtherTask.setCostCenter(eamSku.getCostCenter());
        overseaOtherTask.setRemarks(eamSku.getRemarks());
        overseaOtherTask.setComments(eamSku.getComments());
        overseaOtherTask.setRelateDocument(eamSku.getSpmsId());
        overseaOtherTask.setDocumentType("02");//旧件物料入库
        //overseaOtherTask.setFactoryType(eamSku.getFactoryType());
        return this.baseMapper.insert(overseaOtherTask);
    }

    int createOtherDtlByEamFormer(String uuid,Integer item, EamFormerSkuDtl otherDtl,String movementType,String costCenter){
        String werks = otherDtl.getWerks();
        String workshopCode = otherDtl.getWorkshopCode();
        String whsLocationCode = otherDtl.getWhsLocationCode();
        //String costCenter = otherDtl.getCostCenter();
        //String sapDeliveryNote = eamReturnSkuDtl.getSapDeliveryNote();
        int i = 0;
        OverseaOtherDtl overseaOtherDtl = new OverseaOtherDtl();
        overseaOtherDtl.setUuid(uuid);
        overseaOtherDtl.setItem(item+"");
        overseaOtherDtl.setWerks(werks);
        overseaOtherDtl.setWorkshopCode(workshopCode);
        overseaOtherDtl.setWhsLocationCode(whsLocationCode);
        overseaOtherDtl.setMaterialNo(otherDtl.getMaterialNo());
        overseaOtherDtl.setActualQtyBasicUnit(otherDtl.getActualQtyBasicUnit());
        overseaOtherDtl.setStorageInfo(otherDtl.getStorageInfo());
        overseaOtherDtl.setBasicUnit(otherDtl.getBasicUnit());
        overseaOtherDtl.setCostCenter(costCenter);
        //overseaOtherDtl.setMaterialNoAdjusted(otherDtl.getMaterialNoAdjusted());
        //overseaOtherDtl.setActualQtyBasicUnitAdjusted(otherDtl.getActualQtyBasicUnitAdjusted());
        // overseaOtherDtl.setStorageInfoAdjusted(otherDtl.getStorageInfo());
        //overseaOtherDtl.setSupplierNo(otherDtl.getSupplierNo());
        //overseaOtherDtl.setSapDeliveryNote(sapDeliveryNote);
        //overseaOtherDtl.setSapDeliveryNoteItem(otherDtl.getSapDeliveryNoteItem());
        overseaOtherDtl.setRemarks(otherDtl.getRemarks());
        overseaOtherDtl.setComments(otherDtl.getRemarks());

        //overseaOtherDtl.setActualQtyDeliveryUnit(otherDtl.getActualQtyDeliveryUnit());
        //overseaOtherDtl.setDeliveryUnit(otherDtl.getDeliveryUnit());

        overseaOtherDtl.setInternalOrderNumber(otherDtl.getProjectOaNumber());
        // 零价格出入库金额默认为空 2022-12-03 xzp add
//        if (M_Z55.equals(movementType) || M_Z56.equals(movementType)) {
//            overseaOtherDtl.setLocalCurrency(null);
//        } else {
//            overseaOtherDtl.setLocalCurrency(otherDtl.getLocalCurrency());
//        }
        if (iOverseaOtherDtlService.save(overseaOtherDtl)){
            i ++;
        }
        return i;
    }

}


