package com.cim.idm.service.Impl;

import com.alibaba.fastjson.JSONArray;
import com.cim.idm.dao.MaterialReversalDao;
import com.cim.idm.exception.GlobalException;
import com.cim.idm.framework.IDMFrameServiceProxy;
import com.cim.idm.framework.data.EventInfo;
import com.cim.idm.service.IMaterialUndoService;
import com.cim.idm.service.impl.ToSAPServiceImpl;
import com.cim.idm.utils.AjaxResult;
import com.cim.idm.utils.EventInfoUtil;
import com.cim.idm.wmspackage.materialpacking.MaterialPackingServiceProxy;
import com.cim.idm.wmspackage.materialpacking.management.data.MaterialPacking;
import com.cim.idm.wmspackage.materialpacking.management.data.MaterialPackingKey;
import com.cim.idm.wmspackage.materialpacking.management.info.RemoveInfo;
import com.cim.idm.wmspackage.materialpacking.management.info.SetEventInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("MaterialUndo")
public class MaterialUndoServiceImpl implements IMaterialUndoService {

	@Autowired
	private ToSAPServiceImpl toSAPService;

	@Autowired
	private MaterialReversalDao materialReversalDao;
	/**
	 * 入库冲销
	 * @param undoId
	 * @param user
	 */
	@Transactional
	public void rkUndo (String undoId, String user) throws Exception {

		String billCode = toSAPService.cancelShipInter(undoId, user);
		if (billCode == null) {
			throw new GlobalException("报送ERP失败,请联系IT处理！");
		}

		EventInfo makeEventInfo = new EventInfoUtil().makeEventInfo("MakeUndo", user, "MakeUndo");
		String  condition="WHERE UNDOID =? ";
		String[] bindSet={undoId};
		//根据物料凭证找到所有的待冲销数据，更新库存状态为创建
		List<MaterialPacking> list = MaterialPackingServiceProxy.getMaterialPackingService().select(condition, bindSet);
		Map<String, Object> hashMap = new HashMap<String, Object> ();
		hashMap.put("stockState", "Created");
		SetEventInfo setEventInfo = new SetEventInfo();
		setEventInfo.setUserColumns(hashMap);
		for (MaterialPacking materialPacking : list) {
			MaterialPackingKey key = materialPacking.getKey();
			MaterialPackingServiceProxy.getMaterialPackingService().setEvent(key, makeEventInfo, setEventInfo);
		}

//		String sql = "UPDATE BS_MATERIALPACKINGUNDOINFO b SET b.FLAG = 'Y' WHERE b.UNDOID = :UNDOID";
//		Map<String, Object> hashMap2 = new HashMap<String, Object> ();
//		hashMap2.put("UNDOID", undoId);
//		IDMFrameServiceProxy.getSqlTemplate().update(sql, hashMap2);
		// 更新凭证冲销状态
		MaterialReversalDao.updateReversalUnDoId(undoId);
	}

	/**
	 * 采购入库冲销
	 * @param undoId
	 * @param user
	 */
	@Transactional
	public void cgrkUndo (String undoId, String user) throws Exception {
		String billCode = "";
		billCode = toSAPService.cancelShipInter(undoId, user);
		if (billCode == null) {
			throw new GlobalException("报送ERP失败,请联系IT处理！");
		}

		EventInfo makeEventInfo = new EventInfoUtil ().makeEventInfo("采购入库冲销", user, "采购入库冲销");
		String  condition="SELECT MATERIALPACKINGNAME FROM MATERIALPACKING WHERE UNDOID = :UNDOID ";
//		String[] bindSet={undoId};
		Map<String, Object> hashMap = new HashMap<String, Object> ();
		hashMap.put("UNDOID", undoId);
		//根据物料凭证找到所有的待冲销数据，更新库存状态为创建
		List<Map<String, Object>> MPlIST = IDMFrameServiceProxy.getSqlTemplate().queryForList(condition, hashMap);
		SetEventInfo setEventInfo = new SetEventInfo();
		setEventInfo.setUserColumns(hashMap);
		RemoveInfo removeInfo = new RemoveInfo();
		for (Map<String, Object> MP : MPlIST) {
			//根据当前的数据跟新完工报告且删除入库表的数据
			String sql = "SELECT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME\r\n" +
					"UNION \r\n" +
					"SELECT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME";
			String MATERIALPACKINGNAME = MP.get("MATERIALPACKINGNAME").toString();
			hashMap.put("MATERIALPACKINGNAME", MATERIALPACKINGNAME);
			List<Map<String, Object>> queryForList = IDMFrameServiceProxy.getSqlTemplate().queryForList(sql, hashMap);
			for (int i = 0; i < queryForList.size(); i++) {
				String dh = queryForList.get(i).get("RECEIVEREQUESTNAME").toString();
				hashMap.put("RECEIVEREQUESTNAME", dh);
				String hh = queryForList.get(i).get("RECEIVEREQUESTDETAILNAME").toString();
				hashMap.put("RECEIVEREQUESTDETAILNAME", hh);
//				String sl = queryForList.get(i).get("QTY").toString();
				String updateSql = "UPDATE MATERIALRECEIVEREQUESTDETAIL T  \r\n" +
						"SET T.RECEIVEDQUANTITY = T.RECEIVEDQUANTITY - (  \r\n" +
						"    SELECT NVL(SUM(M.QTY),0)  \r\n" +
						"    FROM MATERIALPACKINGSUB M  \r\n" +
						"    WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME  \r\n" +
						"      AND M.RECEIVEREQUESTNAME = T.RECEIVEREQUESTNAME  \r\n" +
						"      AND M.RECEIVEREQUESTDETAILNAME = T.RECEIVEREQUESTDETAILNAME  \r\n" +
						")  \r\n" +
						"WHERE T.RECEIVEREQUESTNAME = :RECEIVEREQUESTNAME  \r\n" +
						"  AND T.RECEIVEREQUESTDETAILNAME = :RECEIVEREQUESTDETAILNAME";
				IDMFrameServiceProxy.getSqlTemplate().update(updateSql, hashMap);


				String updateSql2 = "UPDATE MATERIALRECEIVEREQUESTDETAIL T  \r\n" +
						"SET T.RECEIVEDQUANTITY = T.RECEIVEDQUANTITY - (  \r\n" +
						"    SELECT NVL(SUM(M.QTY),0)  \r\n" +
						"    FROM MATERIALPACKINGSUBHISTORY M  \r\n" +
						"    WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME  \r\n" +
						"      AND M.RECEIVEREQUESTNAME = T.RECEIVEREQUESTNAME  \r\n" +
						"      AND M.RECEIVEREQUESTDETAILNAME = T.RECEIVEREQUESTDETAILNAME  \r\n" +
						")  \r\n" +
						"WHERE T.RECEIVEREQUESTNAME = :RECEIVEREQUESTNAME  \r\n" +
						"  AND T.RECEIVEREQUESTDETAILNAME = :RECEIVEREQUESTDETAILNAME";
				IDMFrameServiceProxy.getSqlTemplate().update(updateSql2, hashMap);

				String deleteSql = " DELETE FROM MATERIALPACKINGSUB T WHERE T.RECEIVEREQUESTNAME = :RECEIVEREQUESTNAME AND "
						+ "T.RECEIVEREQUESTDETAILNAME = :RECEIVEREQUESTDETAILNAME AND T.MATERIALPACKINGNAME = :MATERIALPACKINGNAME";
				IDMFrameServiceProxy.getSqlTemplate().update(deleteSql, hashMap);

			}
			MaterialPackingServiceProxy.getMaterialPackingService().remove(new MaterialPackingKey("SDK", MATERIALPACKINGNAME), makeEventInfo, removeInfo);
		}

		// 更新凭证冲销状态
		MaterialReversalDao.updateReversalUnDoId(undoId);
	}
	
	/**
	 * 成品入库冲销
	 * @param undoId
	 * @param user
	 */
	@Transactional
	public void cprkUndo (String undoId, String user) throws Exception {
//		sap过账
//		String billCode = toSAPService.cancelShipInter(undoId, user);
//		if (billCode == null) {
//			throw new GlobalException("报送ERP失败,请联系IT处理！");
//		}
		EventInfo makeEventInfo = new EventInfoUtil ().makeEventInfo("成品入库冲销", user, "成品入库冲销");
		String  condition="SELECT MATERIALPACKINGNAME FROM MATERIALPACKING WHERE UNDOID = :UNDOID ";
//		String[] bindSet={undoId};
		Map<String, Object> hashMap = new HashMap<String, Object> ();
		hashMap.put("UNDOID", undoId);
		//根据物料凭证找到所有的待冲销数据，更新库存状态为创建
		List<Map<String, Object>> MPlIST = IDMFrameServiceProxy.getSqlTemplate().queryForList(condition, hashMap);
		SetEventInfo setEventInfo = new SetEventInfo();
		setEventInfo.setUserColumns(hashMap);
		RemoveInfo removeInfo = new RemoveInfo();
		for (Map<String, Object> MP : MPlIST) {
			//根据当前的数据跟新完工报告且删除入库表的数据
			String sql = "SELECT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME\r\n" + 
					"UNION \r\n" + 
					"SELECT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME";
			String MATERIALPACKINGNAME = MP.get("MATERIALPACKINGNAME").toString();
			hashMap.put("MATERIALPACKINGNAME", MATERIALPACKINGNAME);
			List<Map<String, Object>> queryForList = IDMFrameServiceProxy.getSqlTemplate().queryForList(sql, hashMap);
			for (int i = 0; i < queryForList.size(); i++) {
				String dh = queryForList.get(i).get("RECEIVEREQUESTNAME").toString();
				hashMap.put("RECEIVEREQUESTNAME", dh);
				String hh = queryForList.get(i).get("RECEIVEREQUESTDETAILNAME").toString();
				hashMap.put("RECEIVEREQUESTDETAILNAME", hh);
//				String sl = queryForList.get(i).get("QTY").toString();
				String updateSql = "UPDATE MATERIALRECEIVEREQUESTDETAIL T  \r\n" + 
						"SET T.RECEIVEDQUANTITY = T.RECEIVEDQUANTITY - (  \r\n" + 
						"    SELECT NVL(SUM(M.QTY),0)  \r\n" + 
						"    FROM MATERIALPACKINGSUB M  \r\n" + 
						"    WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME  \r\n" + 
						"      AND M.RECEIVEREQUESTNAME = T.RECEIVEREQUESTNAME  \r\n" + 
						"      AND M.RECEIVEREQUESTDETAILNAME = T.RECEIVEREQUESTDETAILNAME  \r\n" + 
						")  \r\n" + 
						"WHERE T.RECEIVEREQUESTNAME = :RECEIVEREQUESTNAME  \r\n" + 
						"  AND T.RECEIVEREQUESTDETAILNAME = :RECEIVEREQUESTDETAILNAME";
				IDMFrameServiceProxy.getSqlTemplate().update(updateSql, hashMap);
				
				
				String updateSql2 = "UPDATE MATERIALRECEIVEREQUESTDETAIL T  \r\n" + 
						"SET T.RECEIVEDQUANTITY = T.RECEIVEDQUANTITY - (  \r\n" + 
						"    SELECT NVL(SUM(M.QTY),0)  \r\n" + 
						"    FROM MATERIALPACKINGSUBHISTORY M  \r\n" + 
						"    WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME  \r\n" + 
						"      AND M.RECEIVEREQUESTNAME = T.RECEIVEREQUESTNAME  \r\n" + 
						"      AND M.RECEIVEREQUESTDETAILNAME = T.RECEIVEREQUESTDETAILNAME  \r\n" + 
						")  \r\n" + 
						"WHERE T.RECEIVEREQUESTNAME = :RECEIVEREQUESTNAME  \r\n" + 
						"  AND T.RECEIVEREQUESTDETAILNAME = :RECEIVEREQUESTDETAILNAME";
				IDMFrameServiceProxy.getSqlTemplate().update(updateSql2, hashMap);
				
				String deleteSql = " DELETE FROM MATERIALPACKINGSUB T WHERE T.RECEIVEREQUESTNAME = :RECEIVEREQUESTNAME AND "
						+ "T.RECEIVEREQUESTDETAILNAME = :RECEIVEREQUESTDETAILNAME AND T.MATERIALPACKINGNAME = :MATERIALPACKINGNAME";
				IDMFrameServiceProxy.getSqlTemplate().update(deleteSql, hashMap);
				
				String MESsQL = " UPDATE BS_MES_SHIPPED T SET T.RECEIVE_FLAG = 'N' WHERE T.LOTNAME = :MATERIALPACKINGNAME ";
				IDMFrameServiceProxy.getSqlTemplate().update(MESsQL, hashMap);
			}
			MaterialPackingServiceProxy.getMaterialPackingService().remove(new MaterialPackingKey("SDK", MATERIALPACKINGNAME), makeEventInfo, removeInfo);
		}
		
//		String sql = "UPDATE IF_ERPUNDO T SET T.FLAG = 'Y' WHERE  T.UNDOID = :UNDOID ";
//		Map<String, Object> hashMap2 = new HashMap<String, Object> ();
//		hashMap2.put("UNDOID", undoId);
//		IDMFrameServiceProxy.getSqlTemplate().update(sql, hashMap2);
		// 更新凭证冲销状态
		MaterialReversalDao.updateReversalUnDoId(undoId);
	}


	/**
	 * 出库冲销
	 * @param undoId
	 * @param user
	 */
	@Transactional
	public void ckUndo (String undoId, String user) throws Exception {

		String billCode = toSAPService.cancelShipInter(undoId, user);
		if (billCode == null) {
			throw new GlobalException("报送ERP失败,请联系IT处理！");
		}

		EventInfo makeEventInfo = new EventInfoUtil ().makeEventInfo("MakeUndo", user, "MakeUndo");
		String  condition="WHERE UNDOID =? ";
		String[] bindSet={undoId};
		//根据物料凭证找到所有的待冲销数据，更新库存状态为创建
		List<MaterialPacking> list = MaterialPackingServiceProxy.getMaterialPackingService().select(condition, bindSet);
		Map<String, Object> hashMap = new HashMap<String, Object> ();
		hashMap.put("stockState", "Stocked");
		hashMap.put("shipRequestName", "");
		SetEventInfo setEventInfo = new SetEventInfo();
		for (MaterialPacking materialPacking : list) {
			MaterialPackingKey key = materialPacking.getKey();
			//获取实际发货数量
			Double materialQuantity = materialPacking.getMaterialQuantity();
			Double materialQuantity2 = materialPacking.getMaterialQuantity2();
			String shipRequestName = materialPacking.getShipRequestName();
			//判断批次现在的库存状态，如果是已出库说明Box已被该单据完全出库，从出库明细表获取信息更新数量，如果状态还是在库更新数量为原有基础上增加
			String pcSql = "MERGE INTO MATERIALPACKING T USING (SELECT MATERIALPACKINGNAME,SUM(QTY) QTY FROM \n" +
					"(SELECT DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME\n" +
					"UNION \n" +
					"SELECT  DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME)\n" +
					"GROUP BY MATERIALPACKINGNAME) M ON (T.MATERIALPACKINGNAME = M.MATERIALPACKINGNAME )\n" +
					"WHEN MATCHED THEN UPDATE SET T.MATERIALQUANTITY = T.MATERIALQUANTITY + M.QTY";
			if ("Stocked".equals(materialPacking.getStockState())) {
				pcSql = "MERGE INTO MATERIALPACKING T USING (SELECT MATERIALPACKINGNAME,SUM(QTY) QTY FROM \n" +
						"(SELECT DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME\n" +
						"UNION \n" +
						"SELECT  DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME)\n" +
						"GROUP BY MATERIALPACKINGNAME) M ON (T.MATERIALPACKINGNAME = M.MATERIALPACKINGNAME )\n" +
						"WHEN MATCHED THEN UPDATE SET T.MATERIALQUANTITY = T.MATERIALQUANTITY + M.QTY,T.MATERIALQUANTITY2 = 0 ";
			} else if ("StockOut".equals(materialPacking.getStockState())) {
				pcSql = "MERGE INTO MATERIALPACKING T USING (SELECT MATERIALPACKINGNAME,SUM(QTY) QTY FROM \n" +
						"(SELECT DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME\n" +
						"UNION \n" +
						"SELECT  DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME)\n" +
						"GROUP BY MATERIALPACKINGNAME) M ON (T.MATERIALPACKINGNAME = M.MATERIALPACKINGNAME )\n" +
						"WHEN MATCHED THEN UPDATE SET T.MATERIALQUANTITY =  M.QTY,T.MATERIALQUANTITY2 = 0 ";
			}
//			BigDecimal fmaterialQuantity = new BigDecimal(materialQuantity);
//			BigDecimal fmaterialQuantity2 = new BigDecimal(materialQuantity2);
//			if (fmaterialQuantity.compareTo(fmaterialQuantity2) == 0) {
//				fmaterialQuantity = BigDecimal.ZERO;
//			}
//			hashMap.put("materialQuantity", fmaterialQuantity);
//			hashMap.put("materialQuantity2", 0);
			setEventInfo.setUserColumns(hashMap);
			MaterialPackingServiceProxy.getMaterialPackingService().setEvent(key, makeEventInfo, setEventInfo);
			
			String cxSql = "MERGE INTO MATERIALSHIPREQUESTDETAIL T USING (SELECT RECEIVEREQUESTNAME,RECEIVEREQUESTDETAILNAME,SUM(QTY) QTY FROM \r\n" + 
					"(SELECT DISTINCT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME\r\n" +
					"UNION \r\n" + 
					"SELECT DISTINCT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME)\r\n" +
					"GROUP BY RECEIVEREQUESTNAME,RECEIVEREQUESTDETAILNAME) M ON (T.SHIPREQUESTNAME = M.RECEIVEREQUESTNAME AND T.SHIPREQUESTDETAILNAME = M.RECEIVEREQUESTDETAILNAME)\r\n" + 
					"WHEN MATCHED THEN UPDATE SET T.ASSIGNEDQUANTITY = T.ASSIGNEDQUANTITY - M.QTY,T.SALEOUTQUANTITY = T.SALEOUTQUANTITY - M.QTY";

			//根据当前的出库数量更新saleQty
//			String sql = "SELECT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME\r\n" + 
//					"UNION \r\n" + 
//					"SELECT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME";
			String MATERIALPACKINGNAME = materialPacking.getMaterialPackingName().toString();
			hashMap.put("MATERIALPACKINGNAME", MATERIALPACKINGNAME);
			hashMap.put("SHIPREQUESTNAME", shipRequestName);
			IDMFrameServiceProxy.getSqlTemplate().update(pcSql, hashMap);
			IDMFrameServiceProxy.getSqlTemplate().update(cxSql, hashMap);
		}

		// 更新凭证冲销状态
		MaterialReversalDao.updateReversalUnDoId(undoId);
	}

	/**
	 * 转库
	 * @param undoId
	 * @param user
	 */
	@Transactional
	public void zkUndo (String undoId, String user) throws Exception {

		String billCode = toSAPService.cancelShipInter(undoId, user);
		if (billCode == null) {
			throw new GlobalException("报送ERP失败,请联系IT处理！");
		}

		EventInfo makeEventInfo = new EventInfoUtil().makeEventInfo("MakeUndo", user, "MakeUndo");
		String  condition="WHERE UNDOID =? ";
		String[] bindSet={undoId};
		//根据物料凭证找到所有的待冲销数据，更新库存状态为创建
		List<MaterialPacking> list = MaterialPackingServiceProxy.getMaterialPackingService().select(condition, bindSet);

		for (MaterialPacking materialPacking : list) {
			Map<String, Object> hashMap = new HashMap<String, Object> ();
			hashMap.put("erpLocation", materialPacking.getPreErpLocation());
			hashMap.put("locationName", materialPacking.getPreLocationName());
			hashMap.put("preErpLocation", materialPacking.getErpLocation());
			hashMap.put("preLocationName", materialPacking.getLocationName());
			SetEventInfo setEventInfo = new SetEventInfo();
			setEventInfo.setUserColumns(hashMap);
			MaterialPackingKey key = materialPacking.getKey();
			MaterialPackingServiceProxy.getMaterialPackingService().setEvent(key, makeEventInfo, setEventInfo);
		}

		// 更新凭证冲销状态
		MaterialReversalDao.updateReversalUnDoId(undoId);
	}

	/**
	 * 自动转库
	 * @param undoId
	 * @param user
	 */
	@Transactional
	public void zdZkUndo (String undoId, String user,String preErpLocation,String preLocationName) throws Exception {

		String billCode = toSAPService.cancelShipInter(undoId, user);
		if (billCode == null) {
			throw new GlobalException("报送ERP失败,请联系IT处理！");
		}

		EventInfo makeEventInfo = new EventInfoUtil().makeEventInfo("冲销自动转库", user, "冲销自动转库");
		String  condition="WHERE UNDOID =? ";
		String[] bindSet={undoId};
		//根据物料凭证找到所有的待冲销数据，更新库存状态为创建
		List<MaterialPacking> list = MaterialPackingServiceProxy.getMaterialPackingService().select(condition, bindSet);

		for (MaterialPacking materialPacking : list) {
			Map<String, Object> hashMap = new HashMap<String, Object> ();
			if(preLocationName == null) {
				preLocationName = "";
			}
			if(preErpLocation == null) {
				preErpLocation = "";
			}
			hashMap.put("erpLocation", preErpLocation);
			hashMap.put("locationName", preLocationName);
//			hashMap.put("preErpLocation", materialPacking.getErpLocation());
//			hashMap.put("preLocationName", materialPacking.getLocationName());
			SetEventInfo setEventInfo = new SetEventInfo();
			setEventInfo.setUserColumns(hashMap);
			MaterialPackingKey key = materialPacking.getKey();
			MaterialPackingServiceProxy.getMaterialPackingService().setEvent(key, makeEventInfo, setEventInfo);
		}

		// 更新凭证冲销状态
		MaterialReversalDao.updateReversalUnDoId(undoId);
	}
	/**
	 * 无来源转库
	 * @param undoId
	 * @param user
	 */
	@Transactional
	public void wlyZkUndo (String undoId, String user,String preErpLocation,String preLocationName) throws Exception {

		String billCode = toSAPService.cancelShipInter(undoId, user);
		if (billCode == null || billCode.equals("")) {
			throw new GlobalException("报送ERP失败,请联系IT处理！");
		}

		EventInfo makeEventInfo = new EventInfoUtil().makeEventInfo("冲销无来源转库", user, "冲销无来源转库");
		String  condition="WHERE UNDOID =? ";
		String[] bindSet={undoId};
		//根据物料凭证找到所有的待冲销数据，更新库存状态为创建
		List<MaterialPacking> list = MaterialPackingServiceProxy.getMaterialPackingService().select(condition, bindSet);
		SetEventInfo setEventInfo = new SetEventInfo();

//		新加
		for (MaterialPacking materialPacking : list) {
			Map<String, Object> hashMap = new HashMap<String, Object> ();
			if(preLocationName == null) {
				preLocationName = "";
			}
			if(preErpLocation == null) {
				preErpLocation = "";
			}
			hashMap.put("erpLocation", preErpLocation);
			hashMap.put("locationName", preLocationName);
//			hashMap.put("preErpLocation", materialPacking.getErpLocation());
//			hashMap.put("preLocationName", materialPacking.getLocationName());
			setEventInfo.setUserColumns(hashMap);
			MaterialPackingKey key = materialPacking.getKey();
			MaterialPackingServiceProxy.getMaterialPackingService().setEvent(key, makeEventInfo, setEventInfo);
		}

		for (MaterialPacking materialPackingSplit : list) {

			String MATERIALPACKINGNAME1 = materialPackingSplit.getMaterialPackingName().toString();
			String CHARGE = materialPackingSplit.getCharge();

			Map<String, Object> hashMapsplit = new HashMap<String, Object> ();
			hashMapsplit.put("MATERIALPACKINGNAME", MATERIALPACKINGNAME1);
			// 如果是拆分批次
			if ("Y".equals(materialPackingSplit.getSplit())) {

				// 如果不是辅材出库，则合并批次数量并删除拆分的批次和sub
				if(!CHARGE.isEmpty()) {
					// 拆分的批次数量
					Double spitMaterialQuantity = materialPackingSplit.getMaterialQuantity();
					// 查出非拆分的原批次
					String  NsplitCondition="WHERE charge =? AND split IS NULL";
					String[] NspliBindSet={CHARGE};
					//
					List<MaterialPacking> noSplitList = MaterialPackingServiceProxy.getMaterialPackingService().select(NsplitCondition, NspliBindSet);
					String NoSMaterialPackingName = noSplitList.get(0).getMaterialPackingName();

					// 存在原批次
					if(!NoSMaterialPackingName.isEmpty()) {
						MaterialPackingKey noSKey = noSplitList.get(0).getKey();
						// 原批次数量
						Double NoPMaterialQuantity = noSplitList.get(0).getMaterialQuantity();
						Map<String, Object> hashMapNosplit = new HashMap<String, Object> ();

						//累加数量
						hashMapNosplit.put("materialQuantity", NoPMaterialQuantity + spitMaterialQuantity);
						setEventInfo.setUserColumns(hashMapNosplit);
						MaterialPackingServiceProxy.getMaterialPackingService().setEvent(noSKey, makeEventInfo, setEventInfo);
					}


					String delSplitSql = "DELETE FROM MATERIALPACKING WHERE MATERIALPACKINGNAME = :MATERIALPACKINGNAME";
					// 删除拆分出的批次
					IDMFrameServiceProxy.getSqlTemplate().update(delSplitSql, hashMapsplit);
				}
				//如果是辅材、更新为在库，删除sub，不是辅材 删除sub
				String delSubSql = "DELETE FROM MATERIALPACKINGSUB WHERE MATERIALPACKINGNAME = :MATERIALPACKINGNAME";
				IDMFrameServiceProxy.getSqlTemplate().update(delSubSql, hashMapsplit);

			}
		}

		// 更新凭证冲销状态
		MaterialReversalDao.updateReversalUnDoId(undoId);
	}

	/**
	 * 质检结果
	 * @param undoId
	 * @param user
	 */
	@Transactional
	public void zjJgUndo (String undoId, String user) throws Exception {

		String billCode = toSAPService.cancelShipInter(undoId, user);
		if (billCode == null) {
			throw new GlobalException("SAP质检结果冲销失败！");
		}

		// 更新凭证冲销状态
		MaterialReversalDao.updateReversalUnDoId(undoId);
	}

	@Transactional
	public void orderUndo (String undoId, String user, String commitDate) throws Exception {


		List<String> materialPackingKeyList = new ArrayList<>();
		EventInfo makeEventInfo = new EventInfoUtil ().makeEventInfo("单号凭证冲销", user, "单号凭证冲销");
		String  condition="WHERE UNDOID =? ";
		String[] bindSet={undoId};
		//根据物料凭证找到所有的待冲销数据，更新库存状态为创建
		List<MaterialPacking> list = MaterialPackingServiceProxy.getMaterialPackingService().select(condition, bindSet);
		for (int i = 0; i < list.size(); ++ i) {
			String materialPackingName = list.get(i).getMaterialPackingName();
			materialPackingKeyList.add(materialPackingName);
		}

		String billCode = toSAPService.outOrderChancel(undoId, "SKD",user, materialPackingKeyList,commitDate);
		if (billCode == null) {
			throw new GlobalException("报送ERP失败,请联系IT处理！");
		}

		Map<String, Object> hashMap = new HashMap<String, Object> ();
		hashMap.put("stockState", "Stocked");
		hashMap.put("shipRequestName", "");
		SetEventInfo setEventInfo = new SetEventInfo();


		for (MaterialPacking materialPackingSplit : list) {

			String MATERIALPACKINGNAME1 = materialPackingSplit.getMaterialPackingName().toString();
			String CHARGE = materialPackingSplit.getCharge();

			Map<String, Object> hashMapsplit = new HashMap<String, Object> ();
			hashMapsplit.put("MATERIALPACKINGNAME", MATERIALPACKINGNAME1);
			// 如果是拆分批次
			if ("Y".equals(materialPackingSplit.getSplit())) {

				// 如果不是辅材出库，则合并批次数量并删除拆分的批次和sub
				if(!CHARGE.isEmpty()) {
					// 拆分的批次数量
					Double spitMaterialQuantity = materialPackingSplit.getMaterialQuantity();
					// 查出非拆分的原批次
					String  NsplitCondition="WHERE charge =? AND split IS NULL";
					String[] NspliBindSet={CHARGE};
					//
					List<MaterialPacking> noSplitList = MaterialPackingServiceProxy.getMaterialPackingService().select(NsplitCondition, NspliBindSet);
					String NoSMaterialPackingName = noSplitList.get(0).getMaterialPackingName();

					// 存在原批次
					if(!NoSMaterialPackingName.isEmpty()) {
						MaterialPackingKey noSKey = noSplitList.get(0).getKey();
						// 原批次数量
						Double NoPMaterialQuantity = noSplitList.get(0).getMaterialQuantity();
						Map<String, Object> hashMapNosplit = new HashMap<String, Object> ();

						//累加数量
						hashMapNosplit.put("materialQuantity", NoPMaterialQuantity + spitMaterialQuantity);
						setEventInfo.setUserColumns(hashMapNosplit);
						MaterialPackingServiceProxy.getMaterialPackingService().setEvent(noSKey, makeEventInfo, setEventInfo);
					}


					String delSplitSql = "DELETE FROM MATERIALPACKING WHERE MATERIALPACKINGNAME = :MATERIALPACKINGNAME";
					// 删除拆分出的批次
					IDMFrameServiceProxy.getSqlTemplate().update(delSplitSql, hashMapsplit);
				}
				//如果是辅材、更新为在库，删除sub，不是辅材 删除sub
				String delSubSql = "DELETE FROM MATERIALPACKINGSUB WHERE MATERIALPACKINGNAME = :MATERIALPACKINGNAME";
				IDMFrameServiceProxy.getSqlTemplate().update(delSubSql, hashMapsplit);

			}
		}


		for (MaterialPacking materialPacking : list) {
			MaterialPackingKey key = materialPacking.getKey();
			//获取实际发货数量
			Double materialQuantity = materialPacking.getMaterialQuantity();
			Double materialQuantity2 = materialPacking.getMaterialQuantity2();
			String shipRequestName = materialPacking.getShipRequestName();
			//判断批次现在的库存状态，如果是已出库说明Box已被该单据完全出库，从出库明细表获取信息更新数量，如果状态还是在库更新数量为原有基础上增加
			String pcSql = "MERGE INTO MATERIALPACKING T USING (SELECT MATERIALPACKINGNAME,SUM(QTY) QTY FROM \n" +
					"(SELECT DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME\n" +
					"UNION \n" +
					"SELECT  DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME)\n" +
					"GROUP BY MATERIALPACKINGNAME) M ON (T.MATERIALPACKINGNAME = M.MATERIALPACKINGNAME )\n" +
					"WHEN MATCHED THEN UPDATE SET T.MATERIALQUANTITY = T.MATERIALQUANTITY + M.QTY";
			if ("Stocked".equals(materialPacking.getStockState())) {
				pcSql = "MERGE INTO MATERIALPACKING T USING (SELECT MATERIALPACKINGNAME,SUM(QTY) QTY FROM \n" +
						"(SELECT DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME\n" +
						"UNION \n" +
						"SELECT  DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME)\n" +
						"GROUP BY MATERIALPACKINGNAME) M ON (T.MATERIALPACKINGNAME = M.MATERIALPACKINGNAME )\n" +
						"WHEN MATCHED THEN UPDATE SET T.MATERIALQUANTITY = T.MATERIALQUANTITY + M.QTY,T.MATERIALQUANTITY2 = 0 ";
			} else if ("StockOut".equals(materialPacking.getStockState())) {
				pcSql = "MERGE INTO MATERIALPACKING T USING (SELECT MATERIALPACKINGNAME,SUM(QTY) QTY FROM \n" +
						"(SELECT DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME\n" +
						"UNION \n" +
						"SELECT  DISTINCT M.MATERIALPACKINGNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME AND M.RECEIVEREQUESTNAME = :SHIPREQUESTNAME)\n" +
						"GROUP BY MATERIALPACKINGNAME) M ON (T.MATERIALPACKINGNAME = M.MATERIALPACKINGNAME )\n" +
						"WHEN MATCHED THEN UPDATE SET T.MATERIALQUANTITY =  M.QTY,T.MATERIALQUANTITY2 = 0 ";
			}
//			BigDecimal fmaterialQuantity = new BigDecimal(materialQuantity);
//			BigDecimal fmaterialQuantity2 = new BigDecimal(materialQuantity2);
//			if (fmaterialQuantity.compareTo(fmaterialQuantity2) == 0) {
//				fmaterialQuantity = BigDecimal.ZERO;
//			}
//			hashMap.put("materialQuantity", fmaterialQuantity);
//			hashMap.put("materialQuantity2", 0);
			setEventInfo.setUserColumns(hashMap);
			MaterialPackingServiceProxy.getMaterialPackingService().setEvent(key, makeEventInfo, setEventInfo);

			String cxSql = "MERGE INTO MATERIALSHIPREQUESTDETAIL T USING (SELECT RECEIVEREQUESTNAME,RECEIVEREQUESTDETAILNAME,SUM(QTY) QTY FROM \r\n" +
					"(SELECT DISTINCT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME\r\n" +
					"UNION \r\n" +
					"SELECT DISTINCT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME)\r\n" +
					"GROUP BY RECEIVEREQUESTNAME,RECEIVEREQUESTDETAILNAME) M ON (T.SHIPREQUESTNAME = M.RECEIVEREQUESTNAME AND T.SHIPREQUESTDETAILNAME = M.RECEIVEREQUESTDETAILNAME)\r\n" +
					"WHEN MATCHED THEN UPDATE SET T.ASSIGNEDQUANTITY = T.ASSIGNEDQUANTITY - M.QTY,T.SALEOUTQUANTITY = T.SALEOUTQUANTITY - M.QTY";


			//根据当前的出库数量更新saleQty
//			String sql = "SELECT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUB M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME\r\n" +
//					"UNION \r\n" +
//					"SELECT M.RECEIVEREQUESTNAME,M.RECEIVEREQUESTDETAILNAME,M.QTY FROM MATERIALPACKINGSUBHISTORY M WHERE M.MATERIALPACKINGNAME = :MATERIALPACKINGNAME";
			String MATERIALPACKINGNAME = materialPacking.getMaterialPackingName().toString();
			hashMap.put("MATERIALPACKINGNAME", MATERIALPACKINGNAME);
			hashMap.put("SHIPREQUESTNAME", shipRequestName);

			IDMFrameServiceProxy.getSqlTemplate().update(pcSql, hashMap);
			IDMFrameServiceProxy.getSqlTemplate().update(cxSql, hashMap);
		}

		// 更新凭证冲销状态
		MaterialReversalDao.updateReversalUnDoId(undoId);
	}

}
