package com.sunda.spmsoversea.service.impl;

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.OverseaBatchReceiptSearchDto;
import com.sunda.spmsoversea.entity.OverseaDnDtl;
import com.sunda.spmsoversea.entity.OverseaOtherBatchReceipt;
import com.sunda.spmsoversea.entity.OverseaOtherBatchReceiptDtl;
import com.sunda.spmsoversea.enums.OverseaBatchReceiptEnum;
import com.sunda.spmsoversea.mapper.OverseaOtherBatchReceiptMapper;
import com.sunda.spmsoversea.service.IFormatDataToSapService;
import com.sunda.spmsoversea.service.IOverseaDnDtlService;
import com.sunda.spmsoversea.service.IOverseaOperateLogService;
import com.sunda.spmsoversea.service.IOverseaOtherBatchReceiptDtlService;
import com.sunda.spmsoversea.service.IOverseaOtherBatchReceiptService;
import com.sunda.spmsoversea.service.IWhsOperateLogService;
import com.sunda.spmsoversea.service.IWhsStorageInventoryService;
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.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;

import static com.sunda.spmsoversea.constant.CommonConstant.SUCCESS;
import static com.sunda.spmsoversea.constant.CommonConstant.sapLog;
import static com.sunda.spmsoversea.constant.CommonConstant.spmsLog;
import static com.sunda.spmsoversea.constant.SapConstant.SAP_SUCCESS;
import static com.sunda.spmsoversea.constant.WhsStorageInventoryConstant.OPERATION_TYPE2;
import static com.sunda.spmsoversea.constant.WhsStorageInventoryConstant.OPERATION_TYPE3;
import static com.sunda.spmsoversea.constant.WhsStorageInventoryConstant.WHS_OPERATE_LOG_ADD;
import static com.sunda.spmsoversea.constant.WhsStorageInventoryConstant.WHS_OPERATE_LOG_SUB;
import static com.sunda.spmsoversea.constant.WhsStorageInventoryConstant.ADD;
import static com.sunda.spmsoversea.constant.WhsStorageInventoryConstant.SUB;
import static com.sunda.spmsoversea.constant.MovementTypeConstant.M643;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;

/**
 * <p>
 * 其他收货分批收货表头 服务实现类
 * </p>
 *
 * @author Wayne
 * @since 2023-02-10
 */
@Service
public class OverseaOtherBatchReceiptServiceImpl extends ServiceImpl<OverseaOtherBatchReceiptMapper, OverseaOtherBatchReceipt> implements IOverseaOtherBatchReceiptService {
	
	@Autowired
	IOverseaOtherBatchReceiptDtlService iOverseaOtherBatchReceiptDtlService;
	
	@Autowired
	IFormatDataToSapService iFormatDataToSapService;
	
	@Autowired
	IFeignServiceCommon iFeignServiceCommon;
	
	@Autowired
	IOverseaOperateLogService iOverseaOperateLogService;
	
	@Autowired
	IWhsStorageInventoryService iWhsStorageInventoryService;
	
	@Autowired
	IWhsOperateLogService iWhsOperateLogService;
	
	@Autowired
	IOverseaDnDtlService iOverseaDnDtlService;
	
	@Autowired
	ZSapOrgClientMapper zSapOrgClientMapper;
	
	@Value("${zxd.sap.client}")
    private String zxdSapClient;
	
	@Override
	public List<Map<String, Object>> selectList(OverseaBatchReceiptSearchDto overseaDnSearchDTO) {
		return this.baseMapper.selectBatchReceiptList(overseaDnSearchDTO);
	}

	@Override
	public List<Map<String, Object>> selectDtlList(OverseaBatchReceiptSearchDto overseaDnSearchDTO) {
		return this.baseMapper.selectBatchReceiptDtlList(overseaDnSearchDTO);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResponseResult saveOverseaBatchReceipt(JSONObject obj, String userId) throws Exception {
		JSONObject headObj = obj.containsKey("batchReceiptHead") ? obj.getJSONObject("batchReceiptHead") : null;
        JSONArray itemsObj = obj.containsKey("batchReceiptDtl") ? obj.getJSONArray("batchReceiptDtl") : null;
        if (headObj == null || itemsObj == null) {
        	return ResponseResult.error("Error, batchReceiptHead or batchReceiptDtl missed from the parameters, please double check");
        }
        OverseaOtherBatchReceipt head = headObj.toJavaObject(OverseaOtherBatchReceipt.class);
        // 检验数据
        this.checkHeadData(head);
        if (StringUtils.isBlank(head.getUuid())) {
        	// 新建
        	String uuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
        	head.setUuid(uuid);
        	head.setSpmsStatus(OverseaBatchReceiptEnum.SAVE.getCode());
        	head.setCreateUserid(userId);
        	head.setCreateTime(new Date());
        	this.baseMapper.insert(head);
        } else {
        	head.setUpdateTime(new Date());
        	head.setUpdateUserid(userId);
        	this.baseMapper.updateById(head);
        }
        QueryWrapper<OverseaOtherBatchReceipt> query = new QueryWrapper<OverseaOtherBatchReceipt>().eq("UUID", head.getUuid());
    	OverseaOtherBatchReceipt selectHead = this.baseMapper.selectOne(query);
        List<OverseaOtherBatchReceiptDtl> itemList = new ArrayList<OverseaOtherBatchReceiptDtl>();
    	int itemNum = 10;
    	for (int i = 0; i < itemsObj.size(); i++) {
			OverseaOtherBatchReceiptDtl item = itemsObj.getObject(i, OverseaOtherBatchReceiptDtl.class);
			if (StringUtils.isBlank(item.getItemRelation())) {
				return ResponseResult.error("行项目中关联的原始行号不能为空");
			}
			if (StringUtils.isBlank(item.getSapPurchaseOrderItem())) {
				return ResponseResult.error("行项目中关联的采购凭证PO行号不能为空");
			}
			if (StringUtils.isBlank(item.getSapPurchaseOrder())) {
				return ResponseResult.error("行项目中关联的采购凭证PO号不能为空");
			}
			if (StringUtils.isBlank(item.getStorageInfo()) || JSONArray.parseArray(item.getStorageInfo(), Map.class).size() == 0) {
				return ResponseResult.error("行项目中储位信息不能为空");
			}
			String itemUuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
			item.setUuid(itemUuid);
			item.setSpmsId(selectHead.getSpmsId());
			item.setSapDeliveryNoteRelation(head.getSapDeliveryNoteRelation());
			item.setCreateTime(new Date());
			item.setCreateUserid(userId);
			item.setUpdateTime(new Date());
			item.setUpdateUserid(userId);
			item.setItemNumber(itemNum+"");
			itemList.add(item);
			itemNum += 10;
		}
    	// 先删除
    	QueryWrapper<OverseaOtherBatchReceiptDtl> dtlQuery = new QueryWrapper<OverseaOtherBatchReceiptDtl>().eq("SPMS_ID", selectHead.getSpmsId());
    	iOverseaOtherBatchReceiptDtlService.remove(dtlQuery);
    	// 再保存
    	iOverseaOtherBatchReceiptDtlService.saveBatch(itemList);
    	
    	iOverseaOperateLogService.addOverseaOperateLog(userId, selectHead.getSpmsId(), OverseaBatchReceiptEnum.SAVE.getDescZh(),
        		OverseaBatchReceiptEnum.SAVE.getDescEn(), spmsLog, JSON.toJSONString(obj), null, "分批收货保存", OverseaBatchReceiptEnum.SAVE.getDescRu());
		return ResponseResult.success().add("batchReceiptHead", selectHead).add("batchReceiptDtl", itemList);
	}

	ResponseResult checkHeadData(OverseaOtherBatchReceipt head) throws Exception {
		if (StringUtils.isBlank(head.getWerks())) {
			return ResponseResult.error("工厂代码不能为空");
		}
		if (StringUtils.isBlank(head.getWhsLocationCode())) {
			return ResponseResult.error("仓库代码不能为空");
		}
		if (StringUtils.isBlank(head.getSapDeliveryNoteRelation())) {
			return ResponseResult.error("关联的SAP交货单号不能为空");
		}
		if (StringUtils.isBlank(head.getSapPurchaseOrder())) {
			return ResponseResult.error("关联的采购凭证PO号不能为空");
		}
		return ResponseResult.success();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResponseResult submitOverseaBatchReceipt(JSONObject obj, String userId) throws Exception {
		JSONObject headObj = obj.containsKey("batchReceiptHead") ? obj.getJSONObject("batchReceiptHead") : null;
        JSONArray itemsObj = obj.containsKey("batchReceiptDtl") ? obj.getJSONArray("batchReceiptDtl") : null;
        if (headObj == null || itemsObj == null) {
        	return ResponseResult.error("Error, batchReceiptHead or batchReceiptDtl missed from the parameters, please double check");
        }
        OverseaOtherBatchReceipt head = headObj.toJavaObject(OverseaOtherBatchReceipt.class);
        // 检验数据
        ResponseResult checkHeadData = this.checkHeadData(head);
        if (checkHeadData.getCode() != SUCCESS){
            return checkHeadData;
        }
        head.setSpmsStatus(OverseaBatchReceiptEnum.SUBMITTED.getCode());
        QueryWrapper<OverseaOtherBatchReceipt> query;
        if (StringUtils.isBlank(head.getUuid())) {
        	// 新建
        	String uuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
        	head.setUuid(uuid);
        	head.setCreateUserid(userId);
        	head.setCreateTime(new Date());
        	this.baseMapper.insert(head);
        	query = new QueryWrapper<OverseaOtherBatchReceipt>().eq("UUID", uuid);
        } else {
        	query = new QueryWrapper<OverseaOtherBatchReceipt>().eq("UUID", head.getUuid());
        	OverseaOtherBatchReceipt selectHead = this.baseMapper.selectOne(query);
        	if (OverseaBatchReceiptEnum.SUBMITTED.getCode().equals(selectHead.getSpmsStatus()) || OverseaBatchReceiptEnum.SUBMIT_SAP_SUCCESS.getCode().equals(selectHead.getSpmsStatus())
        			|| OverseaBatchReceiptEnum.SUBMIT_SAP_ERROR.getCode().equals(selectHead.getSpmsStatus()) || OverseaBatchReceiptEnum.SUBMITTED_SAP.getCode().equals(selectHead.getSpmsStatus())) {
        		return ResponseResult.error("状态已更新，请刷新后再试");
        	}
        	head.setUpdateTime(new Date());
        	head.setUpdateUserid(userId);
        	this.baseMapper.updateById(head);
        }
        OverseaOtherBatchReceipt selectHead = this.baseMapper.selectOne(query);
        List<OverseaOtherBatchReceiptDtl> itemList = new ArrayList<OverseaOtherBatchReceiptDtl>();
    	int itemNum = 10;
    	for (int i = 0; i < itemsObj.size(); i++) {
			OverseaOtherBatchReceiptDtl item = itemsObj.getObject(i, OverseaOtherBatchReceiptDtl.class);
			if (StringUtils.isBlank(item.getItemRelation())) {
				return ResponseResult.error("行项目中关联的原始行号不能为空");
			}
			if (StringUtils.isBlank(item.getSapPurchaseOrderItem())) {
				return ResponseResult.error("行项目中关联的采购凭证PO行号不能为空");
			}
			if (StringUtils.isBlank(item.getSapPurchaseOrder())) {
				return ResponseResult.error("行项目中关联的采购凭证PO号不能为空");
			}
			if (StringUtils.isBlank(item.getStorageInfo())) {
				return ResponseResult.error("行项目中储位信息不能为空");
			}
			if (item.getActualQuantity() == null || item.getActualQuantity() == 0) {
				return ResponseResult.error("行项目中实收数量不能为空或0");
			}
			String itemUuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
			item.setUuid(itemUuid);
			item.setSpmsId(selectHead.getSpmsId());
			item.setSapDeliveryNoteRelation(head.getSapDeliveryNoteRelation());
			item.setCreateTime(new Date());
			item.setCreateUserid(userId);
			item.setUpdateTime(new Date());
			item.setUpdateUserid(userId);
			item.setItemNumber(itemNum+"");
			itemList.add(item);
			itemNum += 10;
		}
    	// 先删除
    	QueryWrapper<OverseaOtherBatchReceiptDtl> dtlQuery = new QueryWrapper<OverseaOtherBatchReceiptDtl>().eq("SPMS_ID", selectHead.getSpmsId());
    	iOverseaOtherBatchReceiptDtlService.remove(dtlQuery);
    	// 再保存
    	iOverseaOtherBatchReceiptDtlService.saveBatch(itemList);
    	iOverseaOperateLogService.addOverseaOperateLog(userId, selectHead.getSpmsId(), OverseaBatchReceiptEnum.SUBMITTED.getDescZh(),
        		OverseaBatchReceiptEnum.SUBMITTED.getDescEn(), spmsLog, JSON.toJSONString(obj), null, "分批收货提交", OverseaBatchReceiptEnum.SUBMITTED.getDescRu());
		return ResponseResult.success().add("batchReceiptHead", selectHead).add("batchReceiptDtl", itemList);
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional(rollbackFor = Exception.class)
	public synchronized ResponseResult submitToSap(JSONObject obj, String userId) throws Exception {
		JSONObject headObj = obj.containsKey("batchReceiptHead") ? obj.getJSONObject("batchReceiptHead") : null;
        if (headObj == null) {
        	return ResponseResult.error("Error, batchReceiptHead missed from the parameters, please double check");
        }
        OverseaOtherBatchReceipt head = headObj.toJavaObject(OverseaOtherBatchReceipt.class);
		ResponseResult checkResult = checkUpdate(head);
        if (checkResult.getCode() != SUCCESS){
            return checkResult;
        }
        QueryWrapper<OverseaOtherBatchReceipt> query = new QueryWrapper<OverseaOtherBatchReceipt>().eq("SPMS_ID", head.getSpmsId());
    	OverseaOtherBatchReceipt selectHead = this.baseMapper.selectOne(query);
		// 调用接口同步SAP
        Map<String, Object> dataHead = this.baseMapper.dataHead(head.getSpmsId(), head.getPostingDate(), userId);
        List<Map<String, Object>> dataItems = this.baseMapper.actualDataItems(head.getSpmsId());
        if (dataHead != null && dataItems != null && dataItems.size() > 0){
        	if(dataItems.get(0).get("WERKS")!=null){
                // 根据工厂查询对应的SAP Clinet
                List<ZSapOrgClient> selectList = zSapOrgClientMapper.selectList(new QueryWrapper<ZSapOrgClient>().eq("WERKS", dataItems.get(0).get("WERKS")));
                if (!CollectionUtils.isEmpty(selectList)) {
                	dataHead.put("MANDT_PO", selectList.get(0).getZmandt());
                	dataHead.put("MANDT_DN", selectList.get(0).getZmandt());
                } else {
                    throw new RuntimeException("工厂："+dataItems.get(0).get("werks")+"未找到对应的SAP Clinet");
                }
            }
        	JSONObject dataToSap = iFormatDataToSapService.formatDataToSap(dataHead, dataItems, "ZZXD_IF_SPMS_04", "ZZXD_IF_SPMS_04");
        	JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
        	JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
        	if (SAP_SUCCESS.equals(RETURN_DATA.getJSONArray("T_R_HEAD").getJSONObject(0).getString("TYPE"))) {
//                    String sapVoucherNumber = RETURN_DATA.getJSONArray("IT_MSG").getJSONObject(0).getString("MBLNR");
//                    String sapVoucherYear = RETURN_DATA.getJSONArray("IT_MSG").getJSONObject(0).getString("MJAHR");

				String sapVoucherNumber = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getJSONArray("T_R_HEAD").getJSONObject(0).getString("MBLNR");
				String sapVoucherYear = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getJSONArray("T_R_HEAD").getJSONObject(0).getString("MJAHR");
                // 增加库存数量
                ResponseResult updateInventory = updateWhsStorageInventory(selectHead, ADD, userId, OPERATION_TYPE2, "其他收货分批收货提交SAP");
                if (updateInventory.getCode() != SUCCESS){
                	return ResponseResult.error("储位库存更新错误："+ updateInventory.getMsg());
                }
                selectHead.setSpmsStatus(OverseaBatchReceiptEnum.SUBMIT_SAP_SUCCESS.getCode());
                selectHead.setPostingDate(head.getPostingDate());
                selectHead.setSapVoucherNumber(sapVoucherNumber);
                selectHead.setSapVoucherYear(sapVoucherYear);
                selectHead.setUpdateTime(new Date());
                selectHead.setUpdateUserid(userId);
                this.baseMapper.updateById(selectHead);
                iOverseaOperateLogService.addOverseaOperateLog(userId, selectHead.getSpmsId(), OverseaBatchReceiptEnum.SUBMIT_SAP_SUCCESS.getDescZh(),
                		OverseaBatchReceiptEnum.SUBMIT_SAP_SUCCESS.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "分批收货提交SAP成功", OverseaBatchReceiptEnum.SUBMIT_SAP_SUCCESS.getDescRu());
                try {
					JSONArray costJson =  message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getJSONArray("T_R_ITEM");
	                //JSONArray costJson = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA").getJSONArray("IT_COST");
	                if (costJson != null && costJson.size() > 0) {
                		List<OverseaOtherBatchReceiptDtl> itemList = new ArrayList<OverseaOtherBatchReceiptDtl>();
                		for (int i = 0; i < costJson.size(); i++) {
                			Map<String, Object> map = (Map<String, Object>) costJson.get(i);
                			if (map.get("ZEILE") != null && map.get("DMBTR") != null) {
                				OverseaOtherBatchReceiptDtl dtl = new OverseaOtherBatchReceiptDtl();
                				String zeile = (String) map.get("ZEILE");
                				String zeileRepla = zeile.replaceAll("^(0+)", "");
                				dtl.setSpmsId(head.getSpmsId());
                				dtl.setItemRelation(zeileRepla);
                				dtl.setDmbtr(map.get("DMBTR").toString());
                				dtl.setWaers(map.get("WAERS") != null ? map.get("WAERS").toString() : "");
                				itemList.add(dtl);
                			}
                		}
                		if (!CollectionUtils.isEmpty(itemList)) {
                			if (itemList.size() > 1000) {
                				List<List<OverseaOtherBatchReceiptDtl>> partition = Lists.partition(itemList, 1000);
                				for (List<OverseaOtherBatchReceiptDtl> pa : partition) {
                					this.baseMapper.updateBatchDtl(pa);
                				}
                			} else {
                				this.baseMapper.updateBatchDtl(itemList);
                			}
                		}
                	}
                } catch (Exception e) {
                }
                OverseaBatchReceiptSearchDto dto = new OverseaBatchReceiptSearchDto();
                dto.setSpmsId(head.getSpmsId());
                List<Map<String, Object>> itemMapList = this.baseMapper.selectBatchReceiptDtlList(dto);
                // 将分批收货的实收数量回写到其他收货行项目中的实收数量字段上
                List<OverseaDnDtl> updateList = new ArrayList<OverseaDnDtl>();
                for (Map<String, Object> itemMap : itemMapList) {
                	String actualQuantity = itemMap.get("actualQuantity").toString();
                	String storageInfo = itemMap.get("storageInfo").toString();
                	OverseaDnDtl dnDtl = iOverseaDnDtlService.getDnDtl(itemMap.get("sapDeliveryNoteRelation").toString(), itemMap.get("itemRelation").toString());
                	if (dnDtl == null) {
                		continue;
                	}
                	if (dnDtl.getActualQtyBasicUnit() == null) {
                		dnDtl.setActualQtyBasicUnit(Double.valueOf(actualQuantity));
                	} else {
                		dnDtl.setActualQtyBasicUnit(dnDtl.getActualQtyBasicUnit()+Double.valueOf(actualQuantity));
                	}
                	if (dnDtl.getActualQtyUnitSales() == null) {
                		dnDtl.setActualQtyUnitSales(Double.valueOf(actualQuantity));
                	} else {
                		dnDtl.setActualQtyUnitSales(dnDtl.getActualQtyUnitSales()+Double.valueOf(actualQuantity));
                	}
                	if (StringUtils.isBlank(dnDtl.getStorageInfo())) {
                		dnDtl.setStorageInfo(storageInfo);
                	} else {
                		// 其他收货的储位信息
                		JSONArray dnArray = JSONArray.parseArray(dnDtl.getStorageInfo());
                		// 分批收货的储位信息
                		JSONArray receiptArray = JSONArray.parseArray(storageInfo);
                		for (int i = 0; i < receiptArray.size(); i++) {
                			JSONObject rcobj = receiptArray.getJSONObject(i);
                			rcobj.put("spmsId", head.getSpmsId());
                			rcobj.put("itemNumber", itemMap.get("itemNumber").toString());
                			dnArray.add(rcobj);
                		}
                		dnDtl.setStorageInfo(dnArray.toJSONString());
                	}
                	updateList.add(dnDtl);
                }
                if (!CollectionUtils.isEmpty(updateList)) {
                	iOverseaDnDtlService.saveOrUpdateBatch(updateList);
                }
                return ResponseResult.success("分批收货提交SAP成功").add("batchReceiptHead", this.baseMapper.selectOne(query)).add("batchReceiptDtl", itemMapList);
            } else {
            	throw new Exception("提交SAP失败："+JSON.toJSONString(message));
//            	selectHead.setSpmsStatus(OverseaBatchReceiptEnum.SUBMIT_SAP_ERROR.getCode());
//            	selectHead.setPostingDate(head.getPostingDate());
//            	selectHead.setUpdateTime(new Date());
//            	selectHead.setUpdateUserid(userId);
//                this.baseMapper.updateById(selectHead);
//                iOverseaOperateLogService.addOverseaOperateLog(userId, selectHead.getSpmsId(), OverseaBatchReceiptEnum.SUBMIT_SAP_ERROR.getDescZh(),
//                		OverseaBatchReceiptEnum.SUBMIT_SAP_ERROR.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "分批收货提交SAP失败");
//                OverseaBatchReceiptSearchDto dto = new OverseaBatchReceiptSearchDto();
//                dto.setSpmsId(head.getSpmsId());
//                return ResponseResult.error("分批收货提交SAP错误")
//                        .add("sapReturnedMessage", message)
//                        .add("dataToSap", dataToSap)
//                        .add("batchReceiptHead", selectHead)
//                        .add("batchReceiptDtl", this.baseMapper.selectBatchReceiptDtlList(dto));
            }
        }
		return ResponseResult.error("分批收货提交SAP错误");
	}

	synchronized ResponseResult updateWhsStorageInventory(OverseaOtherBatchReceipt head, String operateType, String userId, String logType, String remark) {
		QueryWrapper<OverseaOtherBatchReceiptDtl> query = new QueryWrapper<OverseaOtherBatchReceiptDtl>().eq("SPMS_ID", head.getSpmsId());
		List<OverseaOtherBatchReceiptDtl> list = iOverseaOtherBatchReceiptDtlService.list(query);
		if (CollectionUtils.isEmpty(list)) {
			return ResponseResult.error("分批收货明细查询不存在");
		}
		for (OverseaOtherBatchReceiptDtl overseaDnDtl : list){
            String materialNo = overseaDnDtl.getMaterialNo();
            String itemNumber = overseaDnDtl.getItemNumber();
            double actualQtyBasicUnit = overseaDnDtl.getActualQuantity() == null ? 0 : overseaDnDtl.getActualQuantity();
            if (actualQtyBasicUnit > 0){
                //storageInfoArray 结构参考：[{"storageUuid":"f17e13b4d9ad4d39ba55548eff544391","qty":100,"storageNo":"C010101"}]
                JSONArray storageInfoArray = JSONArray.parseArray(overseaDnDtl.getStorageInfo());
                for (int i = 0; i < storageInfoArray.size(); i ++){
                    JSONObject storageInfoObj = storageInfoArray.getJSONObject(i);
                    String storageUuid = storageInfoObj.getString("storageUuid");
                    double qty = storageInfoObj.getDoubleValue("qty");
                    if (qty > 0){
                        ResponseResult updateInventory = iWhsStorageInventoryService.updateWhsStorageInventory(storageUuid, materialNo, qty, operateType);
                        if (updateInventory.getCode() != SUCCESS){
                            return updateInventory;
                        }
                        String comments = operateType.equals(ADD) ? WHS_OPERATE_LOG_ADD : WHS_OPERATE_LOG_SUB;
                        iWhsOperateLogService.insertWhsOperateLog(storageUuid, materialNo, qty, logType, head.getSapDeliveryNoteRelation(), comments, userId, remark, head.getWerks(), head.getWhsLocationCode(), M643, itemNumber);
                    }
                }
            }
        }
        return ResponseResult.success();
	}

	private ResponseResult checkUpdate(OverseaOtherBatchReceipt head) {
		if (StringUtils.isBlank(head.getPostingDate())) {
			return ResponseResult.error("过账日期不能为空");
		}
		QueryWrapper<OverseaOtherBatchReceipt> query = new QueryWrapper<OverseaOtherBatchReceipt>().eq("SPMS_ID", head.getSpmsId());
    	OverseaOtherBatchReceipt selectHead = this.baseMapper.selectOne(query);
    	if (selectHead == null) {
    		return ResponseResult.error("分批收货任务不存在，请检查数据！");
    	}
    	if (!OverseaBatchReceiptEnum.SUBMITTED.getCode().equals(selectHead.getSpmsStatus()) && !OverseaBatchReceiptEnum.SUBMIT_SAP_ERROR.getCode().equals(selectHead.getSpmsStatus())) {
    		return ResponseResult.error("单据当前状态禁止此操作");
    	}
		return ResponseResult.success();
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional(rollbackFor = Exception.class)
	public synchronized ResponseResult cancelDn(JSONObject obj, String userId) throws Exception {
		JSONObject headObj = obj.containsKey("batchReceiptHead") ? obj.getJSONObject("batchReceiptHead") : null;
        if (headObj == null) {
        	return ResponseResult.error("Error, batchReceiptHead missed from the parameters, please double check");
        }
        OverseaOtherBatchReceipt head = headObj.toJavaObject(OverseaOtherBatchReceipt.class);
		QueryWrapper<OverseaOtherBatchReceipt> query = new QueryWrapper<OverseaOtherBatchReceipt>().eq("SPMS_ID", head.getSpmsId());
    	OverseaOtherBatchReceipt selectHead = this.baseMapper.selectOne(query);
    	if (selectHead == null) {
    		return ResponseResult.error("分批收货任务不存在，请检查数据！");
    	}
    	if (StringUtils.isBlank(head.getCancelPostingDate()) && OverseaBatchReceiptEnum.SUBMIT_SAP_SUCCESS.getCode().equals(selectHead.getSpmsStatus())) {
    		return ResponseResult.error("撤销日期不能为空");
    	}
    	if (!OverseaBatchReceiptEnum.SUBMITTED.getCode().equals(selectHead.getSpmsStatus()) && !OverseaBatchReceiptEnum.SUBMIT_SAP_SUCCESS.getCode().equals(selectHead.getSpmsStatus()) && !OverseaBatchReceiptEnum.SUBMIT_SAP_ERROR.getCode().equals(selectHead.getSpmsStatus())) {
    		return ResponseResult.error("单据当前状态禁止此操作");
    	}
    	selectHead.setUpdateTime(new Date());
    	selectHead.setUpdateUserid(userId);
    	OverseaBatchReceiptSearchDto dto = new OverseaBatchReceiptSearchDto();
        dto.setSpmsId(head.getSpmsId());
        if (OverseaBatchReceiptEnum.SUBMITTED.getCode().equals(selectHead.getSpmsStatus()) || OverseaBatchReceiptEnum.SUBMIT_SAP_ERROR.getCode().equals(selectHead.getSpmsStatus())) {
        	// 从提交状态撤回为保存状态
        	selectHead.setSpmsStatus(OverseaBatchReceiptEnum.SAVE.getCode());
        	this.baseMapper.updateById(selectHead);
        	iOverseaOperateLogService.addOverseaOperateLog(userId, selectHead.getSpmsId(), OverseaBatchReceiptEnum.CANCEL_TO_SAVE.getDescZh(), OverseaBatchReceiptEnum.CANCEL_TO_SAVE.getDescEn(), "", OverseaBatchReceiptEnum.CANCEL_TO_SAVE.getDescRu());
            return ResponseResult.success("撤销成功").add("batchReceiptHead", selectHead).add("batchReceiptDtl", this.baseMapper.selectBatchReceiptDtlList(dto));
        } else if (OverseaBatchReceiptEnum.SUBMIT_SAP_SUCCESS.getCode().equals(selectHead.getSpmsStatus())) {
        	// 调用接口同步SAP
        	Map<String, Object> dataHead = this.baseMapper.dataHeadCancelMigo(head.getSpmsId(), head.getCancelPostingDate());
        	if (dataHead != null){
        		dataHead.put("SHLX", "A");
        		dataHead.put("VBELN", selectHead.getSapDeliveryNoteRelation());
                // 根据工厂查询SAP Clinet
                String sapClinet2 = "";
                List<ZSapOrgClient> selectList2 = zSapOrgClientMapper.selectList(new QueryWrapper<ZSapOrgClient>().eq("WERKS", selectHead.getWerks()));
                if (!CollectionUtils.isEmpty(selectList2)) {
                	sapClinet2 = selectList2.get(0).getZmandt();
                } else {
                	return ResponseResult.error("工厂："+selectHead.getWerks()+"未找到对应的SAP Clinet");
                }
                if (dataHead.get("CLIENT") == null) {
                	dataHead.put("CLIENT", sapClinet2);
                }
                dataHead.put("DN_MANDT", sapClinet2);
        		JSONObject dataToSap = this.setToSapData(dataHead);
        		JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
        		JSONObject RETURN_DATA = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
        		JSONObject E_DATA2 = RETURN_DATA.getJSONObject("E_DATA");
        		if (E_DATA2 != null && SAP_SUCCESS.equals(E_DATA2.getString("TYPE"))) {
        			String cancelVoucherNumber = E_DATA2.getString("MBLNR");
        			selectHead.setCancelPostingDate(head.getCancelPostingDate());
        			selectHead.setCancelVoucherNumber(cancelVoucherNumber);
        			selectHead.setSpmsStatus(OverseaBatchReceiptEnum.SUBMITTED.getCode());
        			// 减库存数量
        			ResponseResult updateInventory = updateWhsStorageInventory(selectHead, SUB, userId, OPERATION_TYPE3, "其他收货分批收货撤销提交SAP");
        			if (updateInventory.getCode() != SUCCESS){
        				return ResponseResult.error("储位库存更新错误:" +updateInventory.getMsg());
        			}
        			this.baseMapper.updateById(selectHead);
        			iOverseaOperateLogService.addOverseaOperateLog(userId, selectHead.getSpmsId(), OverseaBatchReceiptEnum.CANCEL_TO_SUBMITTED.getDescZh(),
        					OverseaBatchReceiptEnum.CANCEL_TO_SUBMITTED.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "分批收货撤销提交SAP", OverseaBatchReceiptEnum.CANCEL_TO_SUBMITTED.getDescRu());
        			// 扣减关联的其他收货行项目中的实收数量
        			OverseaBatchReceiptSearchDto dtoDtl = new OverseaBatchReceiptSearchDto();
        			dtoDtl.setSpmsId(head.getSpmsId());
                    List<Map<String, Object>> itemMapList = this.baseMapper.selectBatchReceiptDtlList(dtoDtl);
                    // 将分批收货的实收数量回写到其他收货行项目中的实收数量字段上
                    List<OverseaDnDtl> updateList = new ArrayList<OverseaDnDtl>();
                    for (Map<String, Object> itemMap : itemMapList) {
                    	String actualQuantity = itemMap.get("actualQuantity").toString();
//                        	String storageInfo = itemMap.get("storageInfo").toString();
                    	OverseaDnDtl dnDtl = iOverseaDnDtlService.getDnDtl(itemMap.get("sapDeliveryNoteRelation").toString(), itemMap.get("itemRelation").toString());
                    	if (dnDtl == null) {
                    		continue;
                    	}
                    	if (dnDtl.getActualQtyBasicUnit() != null) {
                    		dnDtl.setActualQtyBasicUnit(dnDtl.getActualQtyBasicUnit()-Double.valueOf(actualQuantity));
                    	}
                    	if (dnDtl.getActualQtyUnitSales() != null) {
                    		dnDtl.setActualQtyUnitSales(dnDtl.getActualQtyUnitSales()-Double.valueOf(actualQuantity));
                    	}
                    	if (StringUtils.isNotBlank(dnDtl.getStorageInfo())) {
                    		// 其他收货的储位信息
                    		JSONArray dnArray = JSONArray.parseArray(dnDtl.getStorageInfo());
                    		// 分批收货的储位信息
//                        		JSONArray receiptArray = JSONArray.parseArray(storageInfo);
                    		Iterator<Object> it = dnArray.iterator();
                    		while(it.hasNext()) {
                    			Map<String, Object> dnMap = (Map<String, Object>) it.next();
                    			if (dnMap.get("spmsId") != null && dnMap.get("itemNumber") != null && head.getSpmsId().equals(dnMap.get("spmsId").toString()) && itemMap.get("itemNumber").toString().equals(dnMap.get("itemNumber").toString())) {
                    				it.remove();
                    			}
//                        			for (int j = 0; j < receiptArray.size(); j++) {
//                        				JSONObject rcobj = receiptArray.getJSONObject(j);
//                        			}
                    		}
                    		dnDtl.setStorageInfo(dnArray.toJSONString());
                    	}
                    	updateList.add(dnDtl);
                    }
                    if (!CollectionUtils.isEmpty(updateList)) {
                    	iOverseaDnDtlService.saveOrUpdateBatch(updateList);
                    }
        			return ResponseResult.success("分批收货撤销成功").add("batchReceiptHead", selectHead);
        		} else {
        			throw new Exception("撤销失败："+JSON.toJSONString(message));
//        			selectHead.setCancelPostingDate(head.getCancelPostingDate());
//        			this.baseMapper.updateById(selectHead);
//        			iOverseaOperateLogService.addOverseaOperateLog(userId, selectHead.getSpmsId(), OverseaBatchReceiptEnum.CANCEL_TO_SUBMITTED.getDescZh(),
//        					OverseaBatchReceiptEnum.CANCEL_TO_SUBMITTED.getDescEn(), sapLog, dataToSap.toJSONString(), message.toJSONString(), "分批收货撤销提交SAP失败");
//        			return ResponseResult.error("分批收货撤销提交SAP错误")
//        					.add("sapReturnedMessage", message)
//        					.add("dataToSap", dataToSap)
//        					.add("batchReceiptHead", selectHead)
//        					.add("batchReceiptDtl", this.baseMapper.selectBatchReceiptDtlList(dto));
        		}
        	}
        }
		return ResponseResult.error("分批收货提交SAP错误");
	}

	private JSONObject setToSapData(Map<String, Object> dataHead) {
		JSONObject doc = new JSONObject();
        JSONObject request = new JSONObject();
        JSONObject esbAttrs = new JSONObject();
        JSONObject requestData = new JSONObject();
        esbAttrs.put("App_ID", "SPMS");
        esbAttrs.put("Target_ID", zxdSapClient);
        esbAttrs.put("Application_ID", "00020000000002");
        esbAttrs.put("Transaction_ID", UUID.randomUUID().toString());
        Map<String, Object> fileds = new HashMap<>();
        requestData.put("fileds", fileds);
        Map<String, Object> structures = new HashMap<>();
//        SimpleDateFormat simp = new SimpleDateFormat("yyyy:MM:ddHH:mm:ss:SS");//月日时分秒 毫秒
//        String serialNumber=simp.format(new Date()).replace(":","" );
//        dataHead.put("SPMID", "SPMS"+serialNumber);
        structures.put("I_DATA", dataHead);
        requestData.put("structures", structures);
        Map<String, Object> tables = new HashMap<>();
        requestData.put("tables", tables);
        requestData.put("Operation", "ZZXD_IF_SPMS_05");
        requestData.put("Type", "ZZXD_IF_SPMS_05");
        request.put("ESB_ATTRS", esbAttrs);
        request.put("REQUEST_DATA", requestData);
        doc.put("REQUEST", request);
        return doc;
	}

	@Override
	public ResponseResult deleteReceipt(JSONObject obj, String userId) {
		try {
			JSONObject headObj = obj.containsKey("batchReceiptHead") ? obj.getJSONObject("batchReceiptHead") : null;
            if (headObj == null) {
            	return ResponseResult.error("Error, batchReceiptHead missed from the parameters, please double check");
            }
            OverseaOtherBatchReceipt head = headObj.toJavaObject(OverseaOtherBatchReceipt.class);
    		QueryWrapper<OverseaOtherBatchReceipt> query = new QueryWrapper<OverseaOtherBatchReceipt>().eq("SPMS_ID", head.getSpmsId());
        	OverseaOtherBatchReceipt selectHead = this.baseMapper.selectOne(query);
        	if (selectHead == null) {
        		return ResponseResult.error("分批收货任务不存在，请检查数据！");
        	}
        	if (!OverseaBatchReceiptEnum.SAVE.getCode().equals(selectHead.getSpmsStatus())) {
        		return ResponseResult.error("单据当前状态禁止此操作");
        	}
        	selectHead.setUpdateTime(new Date());
        	selectHead.setUpdateUserid(userId);
        	selectHead.setSpmsStatus(OverseaBatchReceiptEnum.DELETE.getCode());
        	iOverseaOperateLogService.addOverseaOperateLog(userId, selectHead.getSpmsId(), OverseaBatchReceiptEnum.DELETE.getDescZh(),
            		OverseaBatchReceiptEnum.DELETE.getDescEn(), spmsLog, null, null, "分批收货删除", OverseaBatchReceiptEnum.DELETE.getDescRu());
			this.baseMapper.updateById(selectHead);
			OverseaBatchReceiptSearchDto dto = new OverseaBatchReceiptSearchDto();
            dto.setSpmsId(head.getSpmsId());
			return ResponseResult.success("删除成功").add("batchReceiptHead", selectHead).add("batchReceiptDtl", this.baseMapper.selectBatchReceiptDtlList(dto));
		} catch (Exception e){
            e.printStackTrace();
            return ResponseResult.error().add("error", e.getMessage());
        }
	}

}
