package com.sunda.spmswms.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.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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.spmswms.entity.WhsInventoryInfo;
import com.sunda.spmswms.entity.WhsMove;
import com.sunda.spmswms.entity.WhsMoveDtl;
import com.sunda.spmswms.entity.WhsStorageInventory;
import com.sunda.spmswms.mapper.WhsMoveMapper;
import com.sunda.spmswms.service.*;

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.text.SimpleDateFormat;
import java.util.*;

import static com.sunda.spmscommon.Constans.*;

/**
 * <p>
 * 移仓任务表头 服务实现类
 * </p>
 *
 * @author Wayne
 * @since 2021-05-31
 */
@Service
public class WhsMoveServiceImpl extends ServiceImpl<WhsMoveMapper, WhsMove> implements IWhsMoveService {

    @Autowired
    IWhsMoveDtlService iWhsMoveDtlService;

    @Autowired
    ISapDeliveryNoteLogService iSapDeliveryNoteLogService;

    @Autowired
    IWhsStorageInventoryService iWhsStorageInventoryService;

    @Autowired
    IWhsInventoryInfoService iWhsInventoryInfoService;

    @Autowired
    IWhsOperateLogService iWhsOperateLogService;

    @Autowired
    IFeignServiceCommon iFeignServiceCommon;
    @Autowired
    ZSapOrgClientMapper zSapOrgClientMapper;

    @Override
    public List<WhsMove> whsMoveList() {
        return this.baseMapper.selectList(null);
    }

    /**
     {
     "whsMoveNo": "CN01-20210531-001",
     "moveType": "123",
     "goodsType": "X",
     "werksMoveOut": "CN01",
     "whsLocationCodeMoveOut": "1061",
     "werksMoveIn": "CN01",
     "whsLocationCodeMoveIn": "1011",
     "beginDate": "2021-05-31",
     "endDate": "2021-05-31",
     "spmsStatus": "1,2",
     "pageNo": 1,
     "pageSize": 20
     }
     * @param doc
     * @return
     */
    @Override
    public Page<Map<String, Object>> getWhsMoveList(JSONObject doc) {
        int pageNo = !doc.containsKey("pageNo") || doc.get("pageNo") == null || "".equals(doc.get("pageNo")) ? 1 : Integer.parseInt(doc.get("pageNo").toString());
        int pageSize = !doc.containsKey("pageSize") || doc.get("pageSize") == null || "".equals(doc.get("pageSize")) ? 20 : Integer.parseInt(doc.get("pageSize").toString());

        String whsMoveNo = !doc.containsKey("whsMoveNo") || doc.get("whsMoveNo") == null || "".equals(doc.get("whsMoveNo")) ? null : doc.getString("whsMoveNo");
        String moveType = !doc.containsKey("moveType") || doc.get("moveType") == null || "".equals(doc.get("moveType")) ? null : doc.getString("moveType");
        String goodsType = !doc.containsKey("goodsType") || doc.get("goodsType") == null || "".equals(doc.get("goodsType")) ? null : doc.getString("goodsType");
        String werksMoveOut = !doc.containsKey("werksMoveOut") || doc.get("werksMoveOut") == null || "".equals(doc.get("werksMoveOut")) ? null : doc.getString("werksMoveOut");
        String whsLocationCodeMoveOut = !doc.containsKey("whsLocationCodeMoveOut") || doc.get("whsLocationCodeMoveOut") == null || "".equals(doc.get("whsLocationCodeMoveOut")) ? null : doc.getString("whsLocationCodeMoveOut");
        String werksMoveIn = !doc.containsKey("werksMoveIn") || doc.get("werksMoveIn") == null || "".equals(doc.get("werksMoveIn")) ? null : doc.getString("werksMoveIn");
        String whsLocationCodeMoveIn = !doc.containsKey("whsLocationCodeMoveIn") || doc.get("whsLocationCodeMoveIn") == null || "".equals(doc.get("whsLocationCodeMoveIn")) ? null : doc.getString("whsLocationCodeMoveIn");
        String beginDate = !doc.containsKey("beginDate") || doc.get("beginDate") == null || "".equals(doc.get("beginDate")) ? null : doc.getString("beginDate");
        String endDate = !doc.containsKey("endDate") || doc.get("endDate") == null || "".equals(doc.get("endDate")) ? null : doc.getString("endDate");
        String materialNo = !doc.containsKey("materialNo") || doc.get("materialNo") == null || "".equals(doc.get("materialNo")) ? null : doc.getString("materialNo");
        List<String> spmsStatisList = !doc.containsKey("spmsStatus") || doc.get("spmsStatus") == null || "".equals(doc.get("spmsStatus")) ?
                null : Arrays.asList(doc.getString("spmsStatus").split(","));

        Page<Map<String, Object>> pages = new Page<>(pageNo, pageSize);
        List<Map<String, Object>> pageWMData = this.baseMapper.pageWMDataMap(pages, whsMoveNo, moveType, goodsType, werksMoveOut,
                whsLocationCodeMoveOut, werksMoveIn, whsLocationCodeMoveIn, beginDate, endDate, spmsStatisList, materialNo);
        pages.setRecords(pageWMData);
        return pages;
    }

    @Override
    public List<Map<String, Object>> getWhsMoveDtls(String whsMoveUuid) {
        return this.baseMapper.getWhsMoveDtls(whsMoveUuid);
    }

    /**
     {
     "whsMove": {
     "whsMoveUuid": "icyuhbjifgygvvhujhhhjjhjhjhhuhvbhj",
     "werksMoveOut": "CN01",
     "whsLocationCodeMoveOut": "1061",
     "moveOutRemark": "1061贸易货移仓移出",
     "werksMoveIn": "CN01",
     "whsLocationCodeMoveIn": "1011",
     "remark": null,
     "moveType": "123",
     "goodsType": "M",
     "moveInRemark": "1011贸易货移仓移入",
     "currentStatus": "1",
     "targetStatus":"1",
     "createDate": "2021-05-31"
     },
     "whsMoveDtl": [{
     "actualOutQty": null,
     "moveOutStorage": null,
     "moveOutRemark": null,
     "materialNo": null,
     "costCenter": null,
     "moveInStorage": null,
     "supplierNo": null,
     "whsMoveUuid": "test001",
     "remark": null,
     "itemNo": 10,
     "basicUnit": null,
     "moveInRemark": null,
     "boxNote": "YC-test001-0101",
     "materialZhDesc": null,
     "materialEnDesc": null,
     "plannedOutQty": 1,
     "plannedOutStorage": null,
     "actualInQty": null
     }]
     }

     0删除; 1草稿; 2移出可执行; 3移出提交(移入可执行); 4移入提交(待上传SAP); 5提交SAP成功; 6完成(计算库存);
     先检查能否执行成功，如果能则提交SAP；提交SAP成功则更新SPMS库存，失败则忽略更新；
     * @param doc
     * @param userId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult addWhsMove(JSONObject doc, String userId)throws Exception  {
        ResponseResult checkResult = checkDataValidate(doc);
        if (checkResult.getCode() != 200){
            return checkResult;
        }
//        try {
            JSONObject whsMoveObj = doc.getJSONObject("whsMove");
            JSONArray whsMoveDtlArray = doc.getJSONArray("whsMoveDtl");
            String whsMoveUuid = whsMoveObj.getString("whsMoveUuid");
            if (StringUtils.isEmpty(whsMoveUuid)){
                /** 新建移仓任务表头和行项目 */
                String uuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
                int createWhsMove = createWhsMove(uuid, whsMoveObj, userId);
                if (createWhsMove < 0){
                    throw new Exception("创建移仓任务失败");
                }
                iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(uuid, userId, WHS_MOVE_INIT);
                int createWhsMoveDtl = createWhsMoveDtls(uuid, whsMoveDtlArray);
                if (createWhsMoveDtl < 0){
                    throw new Exception("创建移仓任务明细失败");
                }
                return ResponseResult.success()
                        .add("whsMove", this.baseMapper.selectOne(new QueryWrapper<WhsMove>().eq("WHS_MOVE_UUID", uuid)))
                        .add("getWhsMoveDtls", getWhsMoveDtls(uuid));
            }
            /** 已存在移仓任务uuid，则更新移仓任务表头及明细 */
            int uWhsMove = updateWhsMove(whsMoveObj, userId);
            if (uWhsMove < 0){
                throw new Exception("更新移仓任务失败");
            }
            iSapDeliveryNoteLogService.insertSapDeliveryNoteLogM(whsMoveUuid, userId, WHS_MOVE_UPDATE);
            int uWhsMoveDtl = updateWhsMoveDtl(whsMoveDtlArray);
            if (uWhsMoveDtl < 0){
                throw new Exception("更新移仓任务失败");
            }
            return ResponseResult.success()
                    .add("whsMove", this.baseMapper.selectOne(new QueryWrapper<WhsMove>().eq("WHS_MOVE_UUID", whsMoveUuid)))
                    .add("getWhsMoveDtls", getWhsMoveDtls(whsMoveUuid));
//        }catch (Exception e){
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error();
//        }
    }

    /**  targetStatus: 1草稿; 2移出可执行; 3移出提交(移入可执行); 4移入提交(待上传SAP); 5提交SAP成功; 6完成(计算库存); */
    ResponseResult checkDataValidate(JSONObject doc){
        try {
            if (!doc.containsKey("whsMove") || !doc.containsKey("whsMoveDtl")){
                return ResponseResult.error("请求参数错误");
            }
            JSONObject whsMoveObj = doc.getJSONObject("whsMove");
            JSONArray whsMoveDtlArray = doc.getJSONArray("whsMoveDtl");
            if (StringUtils.isEmpty(whsMoveObj.getString("targetStatus"))){
                return ResponseResult.error("请求参数错误");
            }
            if (whsMoveObj.getString("whsMoveUuid") == null || "".equals(whsMoveObj.getString("whsMoveUuid"))){
                /** 新建移仓任务表头和行项目 */
                if (StringUtils.isEmpty(whsMoveObj.getString("werksMoveOut")) || StringUtils.isEmpty(whsMoveObj.getString("createDate"))){
                    return ResponseResult.error("请求参数错误");
                }
            }else {
                /** 已存在移仓任务uuid，则该任务当前状态必须与传入参数的当前状态保持一致，否则不予操作。 */
                WhsMove whsMove = this.baseMapper.selectOne(new QueryWrapper<WhsMove>().eq("WHS_MOVE_UUID", whsMoveObj.getString("whsMoveUuid")));
                if (whsMove == null){
                    return ResponseResult.error("该 whsMoveUuid 对应移仓任务不存在");
                }
                if (!whsMoveObj.getString("currentStatus").equals(whsMove.getSpmsStatus())){
                    return ResponseResult.error("移仓任务已更新请刷新后重试");
                }
            }
            if ("2".equals(whsMoveObj.getString("targetStatus")) && whsMoveDtlArray.size() == 0){
                return ResponseResult.error("创建移仓任务行项目必须有值");
            }
            return ResponseResult.success();
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.error();
        }
    }

    int createWhsMove(String uuid, JSONObject whsMoveObj, String userId){
        try {
            WhsMove whsMove = new WhsMove();
            whsMove.setWhsMoveUuid(uuid);
            whsMove.setMoveType(whsMoveObj.getString("moveType"));
            whsMove.setGoodsType(whsMoveObj.getString("goodsType"));
            whsMove.setWerksMoveOut(whsMoveObj.getString("werksMoveOut"));
            whsMove.setWhsLocationCodeMoveOut(whsMoveObj.getString("whsLocationCodeMoveOut"));
            whsMove.setMoveOutRemark(whsMoveObj.getString("moveOutRemark"));
            whsMove.setWerksMoveIn(whsMoveObj.getString("werksMoveIn"));
            whsMove.setWhsLocationCodeMoveIn(whsMoveObj.getString("whsLocationCodeMoveIn"));
            whsMove.setCreateDate(whsMoveObj.getString("createDate"));
            whsMove.setCreateUserid(userId);
            whsMove.setSpmsStatus(whsMoveObj.getString("targetStatus"));
            return this.baseMapper.insert(whsMove);
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }
    }

    int createWhsMoveDtls(String uuid, JSONArray whsMoveDtlArray){
        try {
            if (whsMoveDtlArray.size() > 0){
                for (int i = 0; i < whsMoveDtlArray.size(); i++){
                    JSONObject whsMoveDtlObj = whsMoveDtlArray.getJSONObject(i);
                    WhsMoveDtl whsMoveDtl = new WhsMoveDtl();
                    whsMoveDtl.setWhsMoveUuid(uuid);
                    whsMoveDtl.setItemNo((i + 1) * 10);
                    whsMoveDtl.setMaterialNo(whsMoveDtlObj.getString("materialNo"));
                    whsMoveDtl.setBoxNote(whsMoveDtlObj.getString("boxNote"));
                    whsMoveDtl.setPlannedOutQty(StringUtils.isEmpty(whsMoveDtlObj.getString("plannedOutQty")) ? null : whsMoveDtlObj.getDoubleValue("plannedOutQty"));
                    whsMoveDtl.setPlannedOutStorage(null==whsMoveDtlObj.getJSONArray("plannedOutStorage")?null:whsMoveDtlObj.getJSONArray("plannedOutStorage").toJSONString());
                    whsMoveDtl.setActualOutQty(StringUtils.isEmpty(whsMoveDtlObj.getString("actualOutQty")) ? null : whsMoveDtlObj.getDoubleValue("actualOutQty"));
                    whsMoveDtl.setMoveOutStorage(null==whsMoveDtlObj.getJSONArray("moveOutStorage")?null:whsMoveDtlObj.getJSONArray("moveOutStorage").toJSONString());
                    whsMoveDtl.setMoveOutRemark(whsMoveDtlObj.getString("moveOutRemark"));
                    whsMoveDtl.setActualInQty(StringUtils.isEmpty(whsMoveDtlObj.getString("actualInQty")) ? null : whsMoveDtlObj.getDoubleValue("actualInQty"));
                    whsMoveDtl.setMoveInStorage(null==whsMoveDtlObj.getJSONArray("moveInStorage")?null:whsMoveDtlObj.getJSONArray("moveInStorage").toJSONString());
                    whsMoveDtl.setMoveInRemark(whsMoveDtlObj.getString("moveInRemark"));
                    whsMoveDtl.setSupplierNo(whsMoveDtlObj.getString("supplierNo"));
                    whsMoveDtl.setCostCenter(whsMoveDtlObj.getString("costCenter"));
                    whsMoveDtl.setRemark(whsMoveDtlObj.getString("remark"));
                    iWhsMoveDtlService.addWhsMoveDtl(whsMoveDtl);
                }
            }
            return 1;
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }
    }

    int updateWhsMove(JSONObject whsMoveObj, String userId){
        try {
            QueryWrapper<WhsMove> queryWrapper = new QueryWrapper<WhsMove>().eq("WHS_MOVE_UUID", whsMoveObj.getString("whsMoveUuid"));
            WhsMove whsMove = this.baseMapper.selectOne(queryWrapper);
            whsMove.setMoveType(whsMoveObj.getString("moveType"));
            whsMove.setGoodsType(whsMoveObj.getString("goodsType"));
            whsMove.setWerksMoveOut(whsMoveObj.getString("werksMoveOut"));
            whsMove.setWhsLocationCodeMoveOut(whsMoveObj.getString("whsLocationCodeMoveOut"));
            whsMove.setMoveOutRemark(whsMoveObj.getString("moveOutRemark"));
            whsMove.setWerksMoveIn(whsMoveObj.getString("werksMoveIn"));
            whsMove.setWhsLocationCodeMoveIn(whsMoveObj.getString("whsLocationCodeMoveIn"));
            whsMove.setMoveInRemark(whsMoveObj.getString("moveInRemark"));
            whsMove.setCreateDate(whsMoveObj.getString("createDate"));
            whsMove.setMoveOutUserid(whsMoveObj.getString("moveOutUserid"));
            whsMove.setMoveInUserid(whsMoveObj.getString("moveInUserid"));
            whsMove.setSpmsStatus(whsMoveObj.getString("targetStatus"));
            whsMove.setRemark(whsMoveObj.getString("remark"));
            return this.baseMapper.update(whsMove, queryWrapper);
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }
    }

    int updateWhsMoveDtl(JSONArray whsMoveDtlArray){
        try {
            for (int i = 0; i < whsMoveDtlArray.size(); i++){
                JSONObject whsMoveDtlObj = whsMoveDtlArray.getJSONObject(i);
                int autoId = whsMoveDtlObj.getInteger("autoId");
                /** 更新时不允许增删行数，仅允许修改行内信息，故按照主键 AUTO_ID 来更新行项目 */
                QueryWrapper<WhsMoveDtl> queryWrapper = new QueryWrapper<WhsMoveDtl>().eq("AUTO_ID", autoId);
                WhsMoveDtl whsMoveDtl = iWhsMoveDtlService.getByAutoId(autoId);
                whsMoveDtl.setItemNo(whsMoveDtlObj.getInteger("itemNo"));
                whsMoveDtl.setMaterialNo(whsMoveDtlObj.getString("materialNo"));
                whsMoveDtl.setBoxNote(whsMoveDtlObj.getString("boxNote"));
                whsMoveDtl.setPlannedOutQty(StringUtils.isEmpty(whsMoveDtlObj.getString("plannedOutQty")) ? null : whsMoveDtlObj.getDoubleValue("plannedOutQty"));
                whsMoveDtl.setPlannedOutStorage(null==whsMoveDtlObj.getJSONArray("plannedOutStorage")?null:whsMoveDtlObj.getJSONArray("plannedOutStorage").toJSONString());
                whsMoveDtl.setActualOutQty(StringUtils.isEmpty(whsMoveDtlObj.getString("actualOutQty")) ? null : whsMoveDtlObj.getDoubleValue("actualOutQty"));
                whsMoveDtl.setMoveOutStorage(null==whsMoveDtlObj.getJSONArray("moveOutStorage")?null:whsMoveDtlObj.getJSONArray("moveOutStorage").toJSONString());
                whsMoveDtl.setMoveOutRemark(whsMoveDtlObj.getString("moveOutRemark"));
                whsMoveDtl.setActualInQty(StringUtils.isEmpty(whsMoveDtlObj.getString("actualInQty")) ? null : whsMoveDtlObj.getDoubleValue("actualInQty"));
                whsMoveDtl.setMoveInStorage(null==whsMoveDtlObj.getJSONArray("moveInStorage")?null:whsMoveDtlObj.getJSONArray("moveInStorage").toJSONString());
                whsMoveDtl.setMoveInRemark(whsMoveDtlObj.getString("moveInRemark"));
                whsMoveDtl.setSupplierNo(whsMoveDtlObj.getString("supplierNo"));
                whsMoveDtl.setCostCenter(whsMoveDtlObj.getString("costCenter"));
                whsMoveDtl.setRemark(whsMoveDtlObj.getString("remark"));
                iWhsMoveDtlService.updateWhsMoveDtl(whsMoveDtl);
            }
            return 1;
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }
    }

    /**
     * 0删除; 1草稿; 2移出可执行; 3移出提交(移入可执行); 4移入提交(待上传SAP); 5提交SAP成功; 6完成(计算库存);
     * 先检查能否执行成功，如果能则提交SAP；提交SAP成功则更新SPMS库存，失败则忽略更新；
     * @param whsMoveUuid
     * @param postingDate
     * @param userId
     * @return
     */
    @SuppressWarnings("unchecked")
	@Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseResult whsMoveToSap(String whsMoveUuid, String postingDate, String userId)throws Exception  {
        QueryWrapper<WhsMove> queryWrapper = new QueryWrapper<WhsMove>().eq("WHS_MOVE_UUID", whsMoveUuid);
        WhsMove whsMove = this.baseMapper.selectOne(queryWrapper);
        ResponseResult cWhsMove = checkWhsMove(whsMove);
        if (cWhsMove.getCode() != 200){
            return cWhsMove;
        }
        List<Map<String, Object>> whsMoveDtls = this.baseMapper.getWhsMoveDtls(whsMoveUuid);
        ResponseResult cWhsMoveDtl = checkWhsMoveDtl(whsMove, whsMoveDtls);
        if (cWhsMoveDtl.getCode() != 200){
            return cWhsMoveDtl;
        }
        JSONObject Head = formatHead(whsMove, postingDate);
        JSONArray Items = new JSONArray();
        /** 备件货移仓结果 上传SAP 需将箱码转换成物料编号 */
        if ("X".equals(whsMove.getGoodsType())){
            List<Map<String, Object>> whsMoveDtlsX = this.baseMapper.getWhsMoveDtlsX(whsMoveUuid);
            Items = formatItemsX(whsMove, whsMoveDtlsX);
        }else {
            Items = formatItemsM(whsMove, whsMoveDtls);
        }
        if (Items.size() == 0){
            return ResponseResult.error("无有效提交SAP数据");
        }
//        try {
            JSONObject dataToSap = formatDataToSap(Head, Items);
            JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon((dataToSap)));

            if (message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").containsKey("O_TYPE")
                    && "S".equals(message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_TYPE"))) {
                String O_MBLNR = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_MBLNR").trim();
                String O_MJAHR = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getString("O_MJAHR").trim();
                try {
	                JSONArray costJson = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getJSONArray("IT_COST");
	                if (costJson != null && costJson.size() > 0) {
                		List<WhsMoveDtl> itemList = new ArrayList<WhsMoveDtl>();
                		for (int i = 0; i < costJson.size(); i++) {
                			Map<String, Object> map = (Map<String, Object>) costJson.get(i);
                			if (map.get("ZEILE1") != null && map.get("DMBTR") != null) {
                				WhsMoveDtl dtl = new WhsMoveDtl();
                				String zeile = (String) map.get("ZEILE1");
                				String zeileRepla = zeile.replaceAll("^(0+)", "");
                				dtl.setWhsMoveUuid(whsMoveUuid);
                				dtl.setItemNo(Integer.valueOf(zeileRepla));
                				dtl.setDmbtr(map.get("DMBTR").toString());
                				dtl.setWaers(map.get("WAERS") != null ? map.get("WAERS").toString() : "");
                				itemList.add(dtl);
                			}
                		}
                		if (CollectionUtils.isNotEmpty(itemList)) {
                			if (itemList.size() > 1000) {
                				List<List<WhsMoveDtl>> partition = Lists.partition(itemList, 1000);
                				for (List<WhsMoveDtl> pa : partition) {
                					this.baseMapper.updateBatchDtl(pa);
                				}
                			} else {
                				this.baseMapper.updateBatchDtl(itemList);
                			}
                		}
                	}
                } catch (Exception e) {
                }
                this.baseMapper.updateWhsMove(whsMoveUuid, postingDate, "5", O_MBLNR, O_MJAHR);
                iSapDeliveryNoteLogService.insertSapRequestRecord(whsMoveUuid, userId, WHS_MOVE_SAP_SUCCESS, message.toJSONString(), dataToSap.toJSONString());
                /** 更新移出移入库存 */
                ResponseResult resp = updateInventory(whsMove, whsMoveDtls, userId);
                if (resp.getCode() != 200){
                    throw new Exception("移位任务提交SAP成功，更新库存失败");
                }
                this.baseMapper.updateWhsMoveStatus(whsMoveUuid, "6");
                iSapDeliveryNoteLogService.insertSapDeliveryNoteLogN(whsMoveUuid, userId, WHS_MOVE_FINISH, "");

                return ResponseResult.success().add("message", message).add("doc", dataToSap)
                        .add("whsMove", this.baseMapper.selectOne(new QueryWrapper<WhsMove>().eq("WHS_MOVE_UUID", whsMoveUuid)))
                        .add("getWhsMoveDtls", getWhsMoveDtls(whsMoveUuid));
            }
            iSapDeliveryNoteLogService.insertSapRequestRecord(whsMoveUuid, userId, WHS_MOVE_SAP_ERROR, message.toJSONString(), dataToSap.toJSONString());
            return ResponseResult.error().add("message", message).add("doc", dataToSap);
//        } catch (Exception e){
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return ResponseResult.error();
//        }
    }

    ResponseResult checkWhsMove(WhsMove whsMove){
        try {
            if (whsMove == null){
                return ResponseResult.error("移仓任务不存在");
            }
            if (!"4".equals(whsMove.getSpmsStatus())){
                return ResponseResult.error("当前状态不可提交");
            }
            return ResponseResult.success();
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.error();
        }
    }

    /** 1.明细行数必须 > 0；
     * 2.贸易货校验每行数据实际移出数量在对应实际移出储位是否够扣；
     * 3.备件货校验每行数据 箱码对应仓库库存是否够扣；
     * 4.备件货每行数据 箱码对应储位库存是否够扣； */
    ResponseResult checkWhsMoveDtl(WhsMove whsMove, List<Map<String, Object>> whsMoveDtls){
        try {
            if (whsMoveDtls == null || whsMoveDtls.size() == 0){
                return ResponseResult.error("移仓任务明细行数不应为 0");
            }
            String goodsType = whsMove.getGoodsType();
            String werksMoveOut = whsMove.getWerksMoveOut();
            String whsLocationCodeMoveOut = whsMove.getWhsLocationCodeMoveOut();
            for (Map<String, Object> whsMoveDtlMap : whsMoveDtls){
                double actualOutQty = whsMoveDtlMap.get("actualOutQty") == null || "".equals(whsMoveDtlMap.get("actualOutQty").toString())
                        ? 0 : Double.parseDouble(whsMoveDtlMap.get("actualOutQty").toString());
                double actualInQty = whsMoveDtlMap.get("actualInQty") == null || "".equals(whsMoveDtlMap.get("actualInQty").toString())
                        ? 0 : Double.parseDouble(whsMoveDtlMap.get("actualInQty").toString());
                if (actualOutQty != actualInQty){
                    return ResponseResult.error("移出移入数量不一致请检查");
                }
                if (actualOutQty > 0){
                    String moveOutStorage = whsMoveDtlMap.get("moveOutStorage") == null || "".equals(whsMoveDtlMap.get("moveOutStorage").toString())
                            ? null : whsMoveDtlMap.get("moveOutStorage").toString();
                    if (moveOutStorage == null){
                        return ResponseResult.error("请求参数错误-移出储位不能为空");
                    }
                    JSONArray moveOutStorageArray = JSON.parseArray(moveOutStorage);
                    if ("M".equals(goodsType)){
                        String materialNo = whsMoveDtlMap.get("materialNo").toString();
                        for (int i = 0; i < moveOutStorageArray.size(); i++){
                            String storageUuid = moveOutStorageArray.getJSONObject(i).getString("storageUuid");
                            double qty = Double.parseDouble(moveOutStorageArray.getJSONObject(i).getString("qty"));
                            String storageNo = moveOutStorageArray.getJSONObject(i).getString("storageNo");
                            WhsStorageInventory whsStorageInventory = iWhsStorageInventoryService.getStorageMaterialNo(storageUuid, materialNo);
                            if (whsStorageInventory == null || qty > whsStorageInventory.getAvailableQty()){
                                return ResponseResult.error("物料 " + materialNo + " 在储位 " + storageNo + "库存不足");
                            }
                        }
                    }
                    if ("X".equals(goodsType)){
                        String boxNote = whsMoveDtlMap.get("boxNote").toString();

                        WhsInventoryInfo whsInventoryInfo = iWhsInventoryInfoService.getWhsInventoryInfoByBoxNote(boxNote, werksMoveOut, whsLocationCodeMoveOut);
                        if (whsInventoryInfo == null || whsInventoryInfo.getQuantity() == 0){
                            return ResponseResult.error("箱码 " + boxNote + " 在仓库 " + werksMoveOut + " " + whsLocationCodeMoveOut + " 可用库存不足");
                        }
                        for (int i = 0; i < moveOutStorageArray.size(); i++){
                            String storageUuid = moveOutStorageArray.getJSONObject(i).getString("storageUuid");
                            double qty = Double.parseDouble(moveOutStorageArray.getJSONObject(i).getString("qty"));
                            String storageNo = moveOutStorageArray.getJSONObject(i).getString("storageNo");
                            WhsStorageInventory whsStorageInventory = iWhsStorageInventoryService.getStorageBoxNote(storageUuid, boxNote);
                            if (whsStorageInventory == null || qty > whsStorageInventory.getAvailableQty()){
                                return ResponseResult.error("箱码 " + boxNote + " 在储位 " + storageNo + " 可用库存不足");
                            }
                        }
                    }
                }
                if (actualInQty > 0){
                    String moveInStorage = whsMoveDtlMap.get("moveInStorage") == null || "".equals(whsMoveDtlMap.get("moveInStorage").toString())
                            ? null : whsMoveDtlMap.get("moveInStorage").toString();
                    if (moveInStorage == null){
                        return ResponseResult.error("请求参数错误-移入储位不能为空");
                    }
                }
            }
            return ResponseResult.success();
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.error();
        }
    }

    JSONObject formatDataToSap(JSONObject Head, JSONArray Items){
        JSONObject object = new JSONObject();
        JSONObject ESB_ATTRS = new JSONObject();
        JSONObject REQUEST_DATA = new JSONObject();
        JSONObject REQUEST = new JSONObject();

        ESB_ATTRS.put("App_ID", "SPMS");
        // 根据工厂查询对应的SAP Clinet
        List<ZSapOrgClient> selectList = zSapOrgClientMapper.selectList(new QueryWrapper<ZSapOrgClient>().eq("WERKS", Head.get("WERKS")));
        if (CollectionUtils.isNotEmpty(selectList)) {
            ESB_ATTRS.put("Target_ID", "SAP-"+selectList.get(0).getZmandt());
        } else {
            throw new RuntimeException("工厂："+Head.get("werks")+"未找到对应的SAP Clinet");
        }
        ESB_ATTRS.put("Application_ID", "00020000000002");
        ESB_ATTRS.put("Transaction_ID", UUID.randomUUID().toString());

        SimpleDateFormat simp = new SimpleDateFormat("yyyy:MM:ddHH:mm:ss:SS");//月日时分秒 毫秒
        String serialNumber=simp.format(new Date()).replace(":","" );
//        Head.put("SPMSID", "SPMS"+serialNumber);

//        REQUEST_DATA.put("Head", Head);
//        REQUEST_DATA.put("Items", Items);
        Map<String, Object> fileds = new HashMap<>();
        fileds.put("SPMSID", "SPMS"+serialNumber);
        REQUEST_DATA.put("fileds", fileds);

        Map<String, Object> structures = new HashMap<>();
        structures.put("I_HEADER", Head);
        REQUEST_DATA.put("structures", structures);

        Map<String, Object> tables = new HashMap<>();
        tables.put("IT_ITME", Items);
        REQUEST_DATA.put("tables", tables);

        REQUEST_DATA.put("Operation", "Z_SPMS_ANOMALY_POST");
        REQUEST_DATA.put("Type", "ANOMALY_POST");

        REQUEST.put("REQUEST_DATA", REQUEST_DATA);
        REQUEST.put("ESB_ATTRS", ESB_ATTRS);
        object.put("REQUEST", REQUEST);
        return object;
    }

    JSONObject formatHead(WhsMove whsMove, String postingDate){
        JSONObject doc = new JSONObject();
        doc.put("LGORT", whsMove.getWhsLocationCodeMoveIn());
        doc.put("BLDAT", whsMove.getCreateDate().replaceAll("-", ""));
        doc.put("BUDAT", postingDate.replaceAll("-", ""));
        doc.put("WERKS", whsMove.getWerksMoveIn());
        doc.put("BWART", whsMove.getMoveType());
        doc.put("BKTXT", whsMove.getWhsMoveNo() + " " + whsMove.getRemark());
//        doc.put("SPMSID", whsMove.getWhsMoveNo());
        doc.put("XBLNR", whsMove.getWhsMoveNo());
        return doc;
    }

    JSONArray formatItemsM(WhsMove whsMove, List<Map<String, Object>> whsMoveDtls){
        JSONArray array = new JSONArray();
        for (int i = 0; i < whsMoveDtls.size(); i ++) {
            Map<String, Object> map = whsMoveDtls.get(i);
            double actualInQty = map.get("actualInQty") == null ? 0 :
                    StringUtils.isEmpty(map.get("actualInQty").toString()) ? 0 :
                            Double.parseDouble(map.get("actualInQty").toString());
            if (actualInQty > 0){
                JSONObject obj = new JSONObject();
                obj.put("ZEILE", map.get("itemNo").toString());
                obj.put("MATNR", map.get("materialNo"));
                obj.put("MENGE", map.get("actualInQty") == null || map.get("actualInQty") == "" ? "0" : map.get("actualInQty").toString());
                obj.put("MEINS", map.get("basicUnit") == null ? "" : map.get("basicUnit").toString());
                obj.put("LIFNR", map.get("supplierNo") == null ? "" : map.get("supplierNo").toString());
                obj.put("KOSTL", map.get("costCenter") == null ? "" : map.get("costCenter").toString());
                obj.put("WERKS", whsMove.getWerksMoveOut());
                obj.put("LGORT", whsMove.getWhsLocationCodeMoveOut());
                obj.put("SGTXT", map.get("remark") == null ? "" : map.get("remark").toString());
                array.add(obj);
            }
        }
        return array;
    }

    JSONArray formatItemsX(WhsMove whsMove, List<Map<String, Object>> whsMoveDtlsX){
        JSONArray array = new JSONArray();
        for (Map<String, Object> map : whsMoveDtlsX){
            double actualInQty = map.get("actualInQty") == null ? 0 :
                    StringUtils.isEmpty(map.get("actualInQty").toString()) ? 0 :
                            Double.parseDouble(map.get("actualInQty").toString());
            if (actualInQty > 0){
                JSONObject obj = new JSONObject();
                obj.put("ZEILE", map.get("itemNo").toString());
                obj.put("MATNR", map.get("materialNo"));
                obj.put("MENGE", map.get("domesticQtyReceived") == null || map.get("domesticQtyReceived") == "" ? "0" : map.get("domesticQtyReceived").toString());
                obj.put("MEINS", map.get("basicUnit") == null ? "" : map.get("basicUnit").toString());
                obj.put("LIFNR", map.get("supplierNo") == null ? "" : map.get("supplierNo").toString());
                obj.put("KOSTL", map.get("costCenter") == null ? "" : map.get("costCenter").toString());
                obj.put("WERKS", whsMove.getWerksMoveOut());
                obj.put("LGORT", whsMove.getWhsLocationCodeMoveOut());
                obj.put("SGTXT", map.get("remark") == null ? "" : map.get("remark").toString());
                array.add(obj);
            }
        }
        return array;
    }

    ResponseResult updateInventory(WhsMove whsMove, List<Map<String, Object>> whsMoveDtls, String userId){
        try {
            String whsMoveUuid = whsMove.getWhsMoveUuid();
            String goodsType = whsMove.getGoodsType();
            String werksMoveOut = whsMove.getWerksMoveOut();
            String whsLocationCodeMoveOut = whsMove.getWhsLocationCodeMoveOut();

            String werksMoveIn = whsMove.getWerksMoveIn();
            String whsLocationCodeMoveIn = whsMove.getWhsLocationCodeMoveIn();

            for (Map<String, Object> whsMoveDtlMap : whsMoveDtls){
                double actualOutQty = whsMoveDtlMap.get("actualOutQty") == null || "".equals(whsMoveDtlMap.get("actualOutQty").toString())
                        ? 0 : Double.parseDouble(whsMoveDtlMap.get("actualOutQty").toString());
                double actualInQty = whsMoveDtlMap.get("actualInQty") == null || "".equals(whsMoveDtlMap.get("actualInQty").toString())
                        ? 0 : Double.parseDouble(whsMoveDtlMap.get("actualInQty").toString());
                if (actualOutQty > 0 && actualInQty > 0){
                    JSONArray moveOutStorage = JSON.parseArray(whsMoveDtlMap.get("moveOutStorage").toString());
                    JSONArray moveInStorage = JSON.parseArray(whsMoveDtlMap.get("moveInStorage").toString());
                    String itemNo = whsMoveDtlMap.get("itemNo").toString(); 
                    if ("M".equals(goodsType)){
                        String materialNo = whsMoveDtlMap.get("materialNo").toString();
                        /** 贸易货移出仓库对应储位扣减库存 */
                        for (int i = 0; i < moveOutStorage.size(); i ++){
                            String storageUuid = moveOutStorage.getJSONObject(i).getString("storageUuid");
                            double qty = Double.parseDouble(moveOutStorage.getJSONObject(i).getString("qty"));
                            iWhsStorageInventoryService.updateWhsStorage(storageUuid, materialNo, qty);
                            //日志单据类型：1自管仓仓库库存日志；2自管仓储位库存日志；3海外仓仓库库存日志；4海外仓储位库存日志；
                            //操作类型: 11移仓(出储位);12移仓(入储位);13移仓(出仓库);14移仓(入仓库)
                            iWhsOperateLogService.insertWhsOperateLog("2", storageUuid, materialNo, "",
                                    qty, "11", whsMoveUuid, GOODS_OUT_STORAGE, userId, "", werksMoveOut, whsLocationCodeMoveOut, itemNo);
                        }
                        /** 贸易货移入仓库对应储位增加库存 */
                        for (int i = 0; i < moveInStorage.size(); i ++){
                            String storageUuid = moveInStorage.getJSONObject(i).getString("storageUuid");
                            double qty = Double.parseDouble(moveInStorage.getJSONObject(i).getString("qty"));
                            iWhsStorageInventoryService.updateWhsStorageInventoryMOld(storageUuid, materialNo, qty);
                            iWhsOperateLogService.insertWhsOperateLog("2", storageUuid, materialNo, "",
                                    qty, "12", whsMoveUuid, TRADE_GOODS_INTO_STORAGE, userId, "", werksMoveIn, whsLocationCodeMoveIn, itemNo);
                        }
                    }
                    if ("X".equals(goodsType)){
                        String boxNote = whsMoveDtlMap.get("boxNote").toString();
                        /** 备件货移出仓库扣减对应箱码 仓库库存、储位库存；箱码唯一，直接做删除处理；*/
                        for (int i = 0; i < moveOutStorage.size(); i ++){
                            String storageUuid = moveOutStorage.getJSONObject(i).getString("storageUuid");
                            double qty = Double.parseDouble(moveOutStorage.getJSONObject(i).getString("qty"));
                            iWhsInventoryInfoService.deleteBoxNoteWhsInventory(werksMoveOut, whsLocationCodeMoveOut, boxNote);
                            iWhsOperateLogService.insertWhsOperateLog("1", "", "", boxNote,
                                    qty, "13", whsMoveUuid, SPARE_PARTS_OUT_WHS, userId, "", werksMoveOut, whsLocationCodeMoveOut, itemNo);

                            iWhsStorageInventoryService.deleteStorageBoxNote(boxNote);
                            iWhsOperateLogService.insertWhsOperateLog("2", storageUuid, "", boxNote,
                                    qty, "11", whsMoveUuid, SPARE_PARTS_OUT_STORAGE, userId, "", werksMoveOut, whsLocationCodeMoveOut, itemNo);
                        }
                        /** 备件货移入仓库增加对应箱码 仓库库存、储位库存；箱码唯一，直接做新增处理；*/
                        for (int i = 0; i < moveInStorage.size(); i ++){
                            String storageUuid = moveInStorage.getJSONObject(i).getString("storageUuid");
                            double qty = Double.parseDouble(moveInStorage.getJSONObject(i).getString("qty"));
                            iWhsInventoryInfoService.addWhsInventory(werksMoveIn, whsLocationCodeMoveIn, boxNote, qty, userId);
                            iWhsOperateLogService.insertWhsOperateLog("1", "", "", boxNote,
                                    qty, "14", whsMoveUuid, SPARE_PARTS_INTO_WHS, userId, "", werksMoveIn, whsLocationCodeMoveIn, itemNo);

                            iWhsStorageInventoryService.insertStorageInventory(storageUuid, "", boxNote);
                            iWhsOperateLogService.insertWhsOperateLog("2", storageUuid, "", boxNote,
                                    qty, "12", whsMoveUuid, SPARE_PARTS_INTO_STORAGE, userId, "", werksMoveIn, whsLocationCodeMoveIn, itemNo);
                        }
                    }
                }
            }
            return ResponseResult.success();
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.error("移仓库存更新异常");
        }
    }


}
