package nc.bs.wa.paydata.devMethod;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.framework.common.NCLocator;
import nc.impl.pubapp.pattern.database.IDExQueryBuilder;
import nc.itf.pubdev.pubtool.BDTool.IBDDatasGainTool;
import nc.itf.uap.pf.IPFBusiAction;
import nc.jdbc.framework.processor.BeanListProcessor;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.vo.arap.pay.AggPayBillVO;
import nc.vo.arap.pay.PayBillItemVO;
import nc.vo.arap.pay.PayBillVO;
import nc.vo.arap.pub.BillActionConstant;
import nc.vo.bd.defdoc.DefdocVO;
import nc.vo.bd.inoutbusiclass.InoutBusiClassVO;
import nc.vo.hrwa.dev.DevWaDataVO;
import nc.vo.hrwa.dev.DevWaQueryDTO;
import nc.vo.org.DeptVO;
import nc.vo.pmpub.project.ProjectHeadVO;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.VOStatus;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.pub.PubAppTool;
import nc.vo.wa.category.WaClassVO;
import nc.vo.wa.item.WaItemVO;
import nccloud.commons.collections.CollectionUtils;
import nccloud.pubitf.arap.arappub.IArapBillPubUtilService;

public class PushPayBillMethod {
	
	

	public String checkSendStatus(String pk_org, String pk_wa_class,  String cyear, String cperiod, boolean ispushyear) {
		String mesage = "";
		String curcyear =cyear;
		String curperiod =cperiod;
		//检查取的是否为当前月
		 String newperiod = checkiscuryearperiod( pk_org,  pk_wa_class,   cyear,  cperiod);
		 curcyear = newperiod.substring(0,4);
		 curperiod =  newperiod.substring(4,6);
		//检查是否推送过了
		checkispushed(pk_org,curcyear,curperiod,ispushyear);
		//1.根据组织及期间，判断当前是否有工资及研发费，并且是已发放状态 ，否则报错
		HashMap<String, List<DevWaQueryDTO>> waclassmap = (HashMap<String, List<DevWaQueryDTO>>) getSendDataStatus(pk_org,curcyear,curperiod);
		DevWaQueryDTO[] results = waclassmap.values().stream().flatMap(list->list.stream()).toArray(DevWaQueryDTO[]::new);
		  for (DevWaQueryDTO result : results) {
				 boolean ispayed = result.getPayoffflag().booleanValue();
				 if(!ispayed) {
					 String watype = result.getWatype();
					 mesage = mesage+"薪资期间【"+curcyear+curperiod+"】【"+watype+"】未发放!";
				 }
			}
		return mesage;
	}

	public void processer(String pk_org, String pk_wa_class,  String cyear, String cperiod, boolean ispushyear) throws BusinessException {
		// TODO Auto-generated method stub
		String curcyear =cyear;
		String curperiod =cperiod;
		//检查取的是否为当前月
		 String newperiod = checkiscuryearperiod( pk_org,  pk_wa_class,   cyear,  cperiod);
		 curcyear = newperiod.substring(0,4);
		 curperiod =  newperiod.substring(4,6);
//		//检查是否推送过了
//		checkispushed(pk_org,curcyear,curperiod);
		//1.根据组织及期间，判断当前是否有工资及研发费，并且是已发放状态 ，否则报错
		HashMap<String, List<DevWaQueryDTO>> waclassmap = (HashMap<String, List<DevWaQueryDTO>>) getSendDataStatus(pk_org,curcyear,curperiod);
		
		//2.查询工资数据及研发费数据
	    HashMap<String,List<DevWaDataVO>> wadataMap  = getWaDatas(waclassmap.values().stream().flatMap(list->list.stream()).toArray(DevWaQueryDTO[]::new));
	    
	    //3.根据对照表获取表体计算逻辑
	     //薪酬项目-业务类型对照
	     List<DefdocVO> FK004 = BdGainserver.GainDefDocByListcode("XZFK004", " and doc.pk_org ='"+pk_org+"' ");
	     
	     //薪酬项目-研发费项目对照
	     List<DefdocVO> FK005 = BdGainserver.GainDefDocByListcode("XZFK005", " and doc.pk_org ='"+pk_org+"' ");
	     
	     //社保、公积金、年金项目-业务对照
	     List<DefdocVO> FK006 = BdGainserver.GainDefDocByListcode("XZFK006", " and doc.pk_org ='"+pk_org+"' ");
	     //社保、公积金、年金项目-研发费用对照
	     List<DefdocVO> FK007 = BdGainserver.GainDefDocByListcode("XZFK007", " and doc.pk_org ='"+pk_org+"' ");
	     if(waclassmap.containsKey("研发费用")) {
	    	 if(ispushyear) {
	    		 
	    		 if(CollectionUtils.isEmpty(FK006)||CollectionUtils.isEmpty(FK007))
	    			 ExceptionUtils.wrappBusinessException("请先维护当前公司对照表【社保、公积金对照表】、【社保、公积金_年金项目-研发费业务类型对照表】");
	    	 }else {
	    		 if(CollectionUtils.isEmpty(FK004)||CollectionUtils.isEmpty(FK005))
	    			 ExceptionUtils.wrappBusinessException("请先维护当前公司对照表【薪资项目对照表】、【薪酬研发费对照表】");
	    		 
	    	 }
	     }else {
	    	 if(ispushyear) {
	    		 if(CollectionUtils.isEmpty(FK006))
	    			 ExceptionUtils.wrappBusinessException("请先维护当前公司对照表【社保、公积金对照表】");
	    		 
	    	 }else {
	    		 
	    		 if(CollectionUtils.isEmpty(FK004))
	    			 ExceptionUtils.wrappBusinessException("请先维护当前公司对照表【薪资项目对照表】");
	    	 }
	     }
	      //薪资项目
	     HashMap<String,UFDouble> salarymap = new HashMap<String,UFDouble>();
	     //研发费用-对应部门 
	     HashMap<String,UFDouble> rdmap = new HashMap<String,UFDouble>();
	     //研发费用-无部门 
	     HashMap<String,UFDouble> rdnodeptmap = new HashMap<String,UFDouble>();
	     //项目对照
	     HashMap<String,String> projectmap = new HashMap<String,String>();
	     for (String watype : wadataMap.keySet()) {
			if(waclassmap.containsKey("研发费用")&&waclassmap.get("研发费用").get(0).getPk_wa_class().equals(watype)) {
				//计算研发费用 
				CalRDMap(wadataMap.get(watype),rdmap,projectmap,FK005,FK007,ispushyear);
			}else {
				//计算非研发费
				CalSalaryMap(wadataMap.get(watype),salarymap,FK004,FK006,ispushyear);
			}
		}
	     
	     //处理研发费
	     for (String rdkey : rdmap.keySet()) {
			 //研发费key及普通费key 按收支项目+部门进行扣减
	    	 String[] comkeys  =rdkey.split("#");
	    	 String comkey =comkeys[0]+"#"+comkeys[1]; 
	    	 //根据计算逻辑 ，普通费用要减去研发费的值 
	    	 if(salarymap.containsKey(comkey)) {
	    		 if(salarymap.get(comkey).abs().doubleValue()>0) {
	    			 salarymap.put(comkey, salarymap.get(comkey).sub(rdmap.get(rdkey)));
	    			 
	    		 }
	    	 }
	    	 //rebuild new rdmap 第二个为部门，去掉
	    	 String[] keys = rdkey.split("#");
	    	 keys[1] = null;
	    	 String newcomkeys ="";
	    	 for (int i = 0;i<keys.length;i++) {
	    		 if(i==0) {
	    			 newcomkeys = keys[i];
	    		 }else { 
	    			 newcomkeys = newcomkeys+"#"+keys[i];
	    		 }
			}
	    	 if(rdnodeptmap.containsKey(newcomkeys)) {
	    		 rdnodeptmap.put(newcomkeys, rdnodeptmap.get(newcomkeys).add(rdmap.get(rdkey)));
	    	 }else {
	    		 rdnodeptmap.put(newcomkeys, rdmap.get(rdkey));
	    	 }
	    	 
	    	 
		}
	    if(ispushyear) {
	    	//构造年金付款单数据并保存	
	    	buildPayBill(pk_org,curcyear,curperiod,salarymap,rdnodeptmap,projectmap,FK004,FK005,FK006,FK007,"F3-Cxx-003");
	    }else {
	    	//构造薪酬付款单数据并保存
	    	buildPayBill(pk_org,curcyear,curperiod,salarymap,rdnodeptmap,projectmap,FK004,FK005,FK006,FK007,"F3-Cxx-002");
	    	
	    }
		
	}

	private String checkiscuryearperiod(String pk_org, String pk_wa_class, String cyear, String cperiod) {
		// TODO Auto-generated method stub
		String qsql = "select * from  wa_waclass where  pk_wa_class = '"+pk_wa_class+"' and def1 in ( '本月工资','研发费用','上月工资' )  ";
		List<WaClassVO> waclassvos = null;
		 try {
			 waclassvos = (List<WaClassVO>)getBaseDAO().executeQuery( qsql, new BeanListProcessor(WaClassVO.class));
		} catch (DAOException e) {
			// TODO Auto-generated catch block
			ExceptionUtils.wrappBusinessException("查询薪资方案出错："+e.getMessage());
		}
		 
		 if(CollectionUtils.isEmpty(waclassvos))
			 ExceptionUtils.wrappBusinessException("当前选择的薪资方案不属于【本月工资】,【研发费用】,【上月工资】这三类，请检查！");
		 
		  String watype = waclassvos.get(0).getDef1();
		  if("上月工资".equals(watype)) {
			   return getnextperiod(cyear, cperiod);
			  
		  }
		return cyear+cperiod;
	}

	private void checkispushed(String pk_org, String cyear, String cperiod, boolean ispushyear) {
		// TODO Auto-generated method stub
		if(ispushyear) {
			
			String qsql = "select count(1) exsistrow from ap_paybill where nvl(dr,0)=0 and pk_tradetype in('F3-Cxx-003') and def30 = 'Y' and def31 = '"+cyear+cperiod+"'";
			try {
				Integer exsistrow = (Integer) getBaseDAO().executeQuery(qsql, new ColumnProcessor("exsistrow"));
				if(exsistrow>0)
					ExceptionUtils.wrappBusinessException("期间【"+cyear+cperiod+"】数据已经推送到【社保、公积金、年金缴款单】，请先删除对应的下游单据！");
				
			} catch (DAOException e) {
				// TODO 自动生成的 catch 块
				ExceptionUtils.wrappBusinessException("构造查询存在数据出错！"+e.getMessage());
			}
		}else {
			
			String qsql = "select count(1) exsistrow from ap_paybill where nvl(dr,0)=0 and pk_tradetype in('F3-Cxx-002') and def30 = 'Y' and def31 = '"+cyear+cperiod+"'";
			try {
				Integer exsistrow = (Integer) getBaseDAO().executeQuery(qsql, new ColumnProcessor("exsistrow"));
				if(exsistrow>0)
					ExceptionUtils.wrappBusinessException("期间【"+cyear+cperiod+"】数据已经推送到【薪酬付款单】，请先删除对应的下游单据！");
				
			} catch (DAOException e) {
				// TODO 自动生成的 catch 块
				ExceptionUtils.wrappBusinessException("构造查询存在数据出错！"+e.getMessage());
			}
		}
	}

	private void buildPayBill(String pk_org, String cyear, String cperiod, HashMap<String, UFDouble> salarymap, HashMap<String, UFDouble> rdmap, HashMap<String, String> projectmap, List<DefdocVO> fK004, List<DefdocVO> fK005, List<DefdocVO> fK006, List<DefdocVO> fK007, String transtype) throws BusinessException {
		// TODO Auto-generated method stub
	     
	   //4.构造付款单
		AggPayBillVO paybill = new AggPayBillVO();
		PayBillVO head = new PayBillVO();
		head.setPk_group(AppContext.getInstance().getPkGroup());	
		head.setBillclass("fk");
		head.setBilldate(new UFDate());
		head.setBillstatus(-1);
		head.setApprovestatus(-1);
		head.setBillyear(cyear);
		head.setBillperiod(cperiod);
		head.setCreationtime(new UFDateTime());
		head.setCreator(AppContext.getInstance().getPkUser());
		head.setPk_billtype("F3");
		head.setPk_currtype("1002Z0100000000001K1");
		head.setScomment(cyear+"年"+cperiod+"月工资");
		head.setSrc_syscode(1);
		head.setSyscode(1);
		head.setBillmaker(AppContext.getInstance().getPkUser());
		head.setTaxcountryid("0001Z010000000079UJJ");
		head.setStatus(VOStatus.NEW);
		head.setPk_tradetype(transtype);
		head.setPk_org(pk_org);
		head.setPk_fiorg(pk_org);
		head.setSett_org(pk_org);
		head.setRate(UFDouble.ZERO_DBL);
		head.setPk_balatype("0001Z0100000000000Y5");
		head.setDef30("Y");
		head.setDef31(cyear+cperiod);
		try {
			String qtradesql = "select pk_billtypeid from bd_billtype where nvl(dr,0)=0 and pk_billtypecode = '"+transtype+"'"; 
			String pk_billtypeid = (String) getBaseDAO().executeQuery(qtradesql, new ColumnProcessor("pk_billtypeid"));
		    if(!PubAppTool.isNull(pk_billtypeid))
		    	head.setPk_tradetypeid(pk_billtypeid);
		    String qorgsql = " select pk_vid from org_orgs_v where nvl(dr,0)=0 and pk_org = '"+pk_org+"'";
		    String pk_vid = (String) getBaseDAO().executeQuery(qorgsql, new ColumnProcessor("pk_vid"));
		    if(!PubAppTool.isNull(pk_vid)) {
		    	head.setPk_org_v(pk_vid);
		    	head.setPk_fiorg_v(pk_vid);
		    	head.setSett_org_v(pk_vid);
		    }
		    
		  //组织默认银行账户
			 String qbanksql = "SELECT pk_bankaccsub FROM v_bankacc WHERE v_bankacc.pk_org = '"+pk_org+"'";
			 String pk_bankaccsub = (String) getBaseDAO().executeQuery(qbanksql, new ColumnProcessor("pk_bankaccsub"));
			 head.setPayaccount(pk_bankaccsub);
		} catch (DAOException e) {
			// TODO Auto-generated catch block
			ExceptionUtils.wrappBusinessException("查询数据失败"+e.getMessage());
		}
		//构造表体
		//薪酬收支项目
		 List<String> xclist = fK004.stream().map(DefdocVO::getDef1).collect(Collectors.toList());
		 if(CollectionUtils.isNotEmpty(fK005)) {
			 xclist.addAll(fK005.stream().map(DefdocVO::getDef1).collect(Collectors.toList())) ;
		 }
		 //年金收支项目
		 List<String> njlist = fK006.stream().map(DefdocVO::getDef1).collect(Collectors.toList());
		 if(CollectionUtils.isNotEmpty(fK007)) {
			 njlist.addAll(fK007.stream().map(DefdocVO::getDef1).collect(Collectors.toList())) ;
		 }
		 List<String> templist = new ArrayList<String>();
		 templist.addAll(xclist);
		 templist.addAll(njlist);
		 String qinoutsql = "select * from bd_inoutbusiclass where nvl(dr,0)=0 and  " 
				 +new IDExQueryBuilder("pk_inoutbusiclass").buildSQL("pk_inoutbusiclass", templist.stream().toArray(String[]::new));
		 List<InoutBusiClassVO> results = (List<InoutBusiClassVO>)getBaseDAO().executeQuery( qinoutsql, new BeanListProcessor(InoutBusiClassVO.class));
		 
		 Map<String, InoutBusiClassVO> inoutMap= results.stream().collect(Collectors.toMap(InoutBusiClassVO::getPk_inoutbusiclass,InoutBusiClassVO->InoutBusiClassVO,(ovalue,nvalue)->nvalue));
		 //获取公司研发中心
		 DeptVO yfdept = null;
		 String qdeptsql = " select * from org_dept where nvl(dr,0)=0 and shortname = '技术研发中心' and pk_org = '"+pk_org+"'";
		 List<DeptVO> deptlist = (List<DeptVO>)getBaseDAO().executeQuery( qdeptsql, new BeanListProcessor(DeptVO.class));
		 if(CollectionUtils.isNotEmpty(deptlist))
			 yfdept = deptlist.get(0);
		 
		 
		 List<PayBillItemVO> bodylist = new ArrayList<PayBillItemVO>();
		 if ("F3-Cxx-002".equals(transtype)) {
				for (String key : salarymap.keySet()) {
					String[] paras = key.split("#");
					if (xclist.contains(paras[0])) {
						PayBillItemVO body = new PayBillItemVO();
						body.setMoney_de(salarymap.get(key));
						body.setLocal_money_de(salarymap.get(key));
						// 设置收支相关数据字段
						InoutBusiClassVO inout = inoutMap.get(paras[0]);
						body.setPk_subjcode(inout.getPk_inoutbusiclass());
						body.setCashitem(inout.getDef1());
						body.setBankrollprojet(inout.getDef2());
						body.setScomment(cyear+"年"+cperiod+"月"+inout.getName());
						body.setPk_deptid(paras[1]);
						String qdeptvsql = "select * from org_dept where nvl(dr,0)=0 and pk_dept = '"+paras[1]+"'"; 
						List<DeptVO> curdeptlist = (List<DeptVO>)getBaseDAO().executeQuery(qdeptvsql, new BeanListProcessor(DeptVO.class));
						
						if(CollectionUtils.isNotEmpty(curdeptlist)) {
							body.setPk_deptid_v(curdeptlist.get(0).getPk_vid());
							if(body.getMoney_de().doubleValue()>0) {
								body.setScomment("支付"+curdeptlist.get(0).getName()+inout.getName()+"费用");
							}else {
								body.setScomment("抵扣"+curdeptlist.get(0).getName()+inout.getName()+"费用");
							}
						}
						body.setPk_recpaytype(paras[2]);
						bodylist.add(body);
					}

				}
				//研发费
				for (String key : rdmap.keySet()) {
					String[] paras = key.split("#");
					if (xclist.contains(paras[0])) {
						PayBillItemVO body = new PayBillItemVO();
						body.setMoney_de(rdmap.get(key));
						body.setLocal_money_de(rdmap.get(key));
						// 设置收支相关数据字段
						InoutBusiClassVO inout = inoutMap.get(paras[0]);
						body.setPk_subjcode(inout.getPk_inoutbusiclass());
						body.setCashitem(inout.getDef1());
						body.setBankrollprojet(inout.getDef2());
						body.setProject(projectmap.get(paras[paras.length-1]) );
						body.setScomment(cyear+"年"+cperiod+"月"+inout.getName());
						body.setPk_recpaytype(paras[2]);
						if(null!=yfdept) {
							
							body.setPk_deptid(yfdept.getPk_dept());
							body.setPk_deptid_v(yfdept.getPk_vid());

							if (body.getMoney_de().doubleValue() > 0) {
								body.setScomment("支付" + yfdept.getName() + inout.getName() + "费用");
							} else {
								body.setScomment("抵扣" + yfdept.getName() + inout.getName() + "费用");
							}
						}else {
							ExceptionUtils.wrappBusinessException("未能找到简称为【技术研发中心】的部门，请检查！");
							
						}
							
						bodylist.add(body);
					}
					
				}
				
				
				
		 	}else {
				for (String key : salarymap.keySet()) {
					String[] paras = key.split("#");
					if (njlist.contains(paras[0])) {
						PayBillItemVO body = new PayBillItemVO();
						body.setMoney_de(salarymap.get(key));
						body.setLocal_money_de(salarymap.get(key));
						// 设置收支相关数据字段
						InoutBusiClassVO inout = inoutMap.get(paras[0]);
						body.setPk_subjcode(inout.getPk_inoutbusiclass());
						body.setCashitem(inout.getDef1());
						body.setBankrollprojet(inout.getDef2());
						body.setScomment(cyear+"年"+cperiod+"月"+inout.getName());
						body.setPk_deptid(paras[1]);
						String qdeptvsql = "select * from org_dept where nvl(dr,0)=0 and pk_dept = '"+paras[1]+"'"; 
						List<DeptVO> curdeptlist = (List<DeptVO>)getBaseDAO().executeQuery(qdeptvsql, new BeanListProcessor(DeptVO.class));
						if(CollectionUtils.isNotEmpty(curdeptlist)) {
							body.setPk_deptid_v(curdeptlist.get(0).getPk_vid());
							if(body.getMoney_de().doubleValue()>0) {
								body.setScomment("支付"+curdeptlist.get(0).getName()+inout.getName()+"费用");
							}else {
								body.setScomment("抵扣"+curdeptlist.get(0).getName()+inout.getName()+"费用");
							}
						}
						body.setPk_recpaytype(paras[2]);
						bodylist.add(body);
					}

				}
				
				for (String key : rdmap.keySet()) {
					String[] paras = key.split("#");
					if (njlist.contains(paras[0])) {
						PayBillItemVO body = new PayBillItemVO();
						body.setMoney_de(rdmap.get(key));
						body.setLocal_money_de(rdmap.get(key));
						// 设置收支相关数据字段
						InoutBusiClassVO inout = inoutMap.get(paras[0]);
						body.setPk_subjcode(inout.getPk_inoutbusiclass());
						body.setCashitem(inout.getDef1());
						body.setBankrollprojet(inout.getDef2());
						body.setProject(projectmap.get(paras[paras.length-1]) );
						body.setScomment(cyear+"年"+cperiod+"月"+inout.getName());
						body.setPk_recpaytype(paras[2]);
						if(null!=yfdept) {
							
							body.setPk_deptid(yfdept.getPk_dept());
							body.setPk_deptid_v(yfdept.getPk_vid());

							if (body.getMoney_de().doubleValue() > 0) {
								body.setScomment("支付" + yfdept.getName() + inout.getName() + "费用");
							} else {
								body.setScomment("抵扣" + yfdept.getName() + inout.getName() + "费用");
							}
							
						}else {
							
							ExceptionUtils.wrappBusinessException("未能找到【技术研发中心】部门，请检查！");
						}
						bodylist.add(body);
					}
					
				}
				
				
				
		 	}
		 
         UFDouble totalmny = UFDouble.ZERO_DBL;
	     //表头数据需要设置到表体
		  for (PayBillItemVO body : bodylist) {
			  body.setPk_group(head.getPk_group());	
				body.setBillclass(head.getBillclass());
				body.setBilldate(head.getBilldate());
				body.setPk_billtype(head.getPk_billtype());
				body.setPk_currtype(head.getPk_currtype());
				body.setStatus(VOStatus.NEW);
				body.setPk_tradetype(transtype);
				body.setPk_org(pk_org);
				body.setPk_fiorg(pk_org);
				body.setSett_org(pk_org);
				body.setRate(UFDouble.ZERO_DBL);
				body.setPk_tradetypeid(head.getPk_tradetypeid());
				body.setPayaccount(head.getPayaccount());
				body.setPk_org_v(head.getPk_org_v());
		    	body.setPk_fiorg_v(head.getPk_fiorg_v());
		    	body.setSett_org_v(head.getSett_org_v());
		    	body.setObjtype(2);
		    	body.setPk_balatype("0001Z0100000000000Y5");
		    	totalmny = totalmny.add(null==body.getMoney_de()?UFDouble.ZERO_DBL:body.getMoney_de());
			
		}
		
		
		head.setLocal_money(totalmny);
		head.setMoney(totalmny);
		PayBillItemVO[] bodys= bodylist.stream().filter(vo->null!=vo.getMoney_de()&&vo.getMoney_de().doubleValue()!=0).toArray(PayBillItemVO[]::new);
            
	     //5.保存付款单
			paybill.setParentVO(head);
			paybill.setChildrenVO(bodys );
			AggregatedValueObject[] aggbillvo = new AggregatedValueObject[] { paybill };
			((IArapBillPubUtilService) NCLocator.getInstance().lookup(IArapBillPubUtilService.class)).interceptorVaildator(aggbillvo, BillActionConstant.SAVE);
			IPFBusiAction baService = NCLocator.getInstance().lookup(IPFBusiAction.class);
			HashMap eap = new HashMap();
			eap.put("notechecked", "notechecked");
			eap.put("NCCLOUD_ENTRY", "true");
			eap.put("IS_RELOADBILL", "true");
			eap.put("nolockandconsist", "Y");
			try {
				baService.processAction("SAVE", "F3", null, aggbillvo[0], null, eap);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				String billname = "社保、公积金、年金缴款单";
						
				if ("F3-Cxx-002".equals(transtype)) {
					billname = "薪酬付款单";
				}
				ExceptionUtils.wrappBusinessException("保存【"+billname+"】失败："+e.getMessage());
			}		
	}

	private void CalRDMap(List<DevWaDataVO> rdlist, HashMap<String, UFDouble> rdmap, HashMap<String, String> projectmap, List<DefdocVO> fK005, List<DefdocVO> fK007, boolean ispushyear) {
		// TODO Auto-generated method stub
		if(CollectionUtils.isEmpty(rdlist))
			return;
		//统一计算
		List<DefdocVO> inoutList = new ArrayList<DefdocVO>();
		if(ispushyear) {
			
			inoutList.addAll(fK007);
		}else {
			
			inoutList.addAll(fK005);
		}
		//获取研发项目
		HashMap<String,String> projectkeymap =null;
		String qprojectkeysql = "select * from wa_item where nvl(dr,0)=0 and code like 'YFXM%'";
		try {
			List<WaItemVO> results = (List<WaItemVO>)getBaseDAO().executeQuery( qprojectkeysql, new BeanListProcessor(WaItemVO.class));
		    if(CollectionUtils.isNotEmpty(results))
		    	projectkeymap = (HashMap<String, String>) results.stream().collect(Collectors.toMap(WaItemVO::getName, WaItemVO::getItemkey));
		} catch (DAOException e) {
			// TODO Auto-generated catch block
			ExceptionUtils.wrappBusinessException("查询研发项目字段定义失败："+e.getMessage());
		}
		if(null==projectkeymap) {
			ExceptionUtils.wrappBusinessException("未找到定义的项目字段【YFXM...】");
		}
		//获取研发项目
		HashMap<String,String> keyitemmap =null;
		String qkeysql = "select * from wa_item where nvl(dr,0)=0 ";
		try {
			List<WaItemVO> results = (List<WaItemVO>)getBaseDAO().executeQuery( qkeysql, new BeanListProcessor(WaItemVO.class));
			if(CollectionUtils.isNotEmpty(results))
				keyitemmap = (HashMap<String, String>) results.stream().collect(Collectors.toMap(WaItemVO::getItemkey , WaItemVO::getName));
		} catch (DAOException e) {
			// TODO Auto-generated catch block
			ExceptionUtils.wrappBusinessException("查询字段定义失败："+e.getMessage());
		}
		
		List<String> undefindkeyList = new ArrayList<String>();
		//遍历工资数据
		List<String> projectlist = new ArrayList<String>();
	     for (DevWaDataVO DevWaDataVO : rdlist) {
	    	 String pk_dept = DevWaDataVO.getPk_financedept();
	    	 String cyearperiod =DevWaDataVO.getCyearperiod();
	    	 //遍历项目获取数据
	    	 for(String prokeyname:projectkeymap.keySet()) {
	    		 Object project = DevWaDataVO.getAttributeValue(projectkeymap.get(prokeyname));
	    		 if(null!=project&&!PubAppTool.isNull(project.toString())) {
	    			 //记录project名称
	    			 if(!projectlist.contains(project.toString()))
	    				 projectlist.add(project.toString());
	    			 String pkpro = project.toString();
	    			 for (DefdocVO defvo : inoutList) {
	    				 String pk_inout = defvo.getDef1();
	    				 String pk_paytype = defvo.getDef3();
	    				 //计算方向 
	    				 String caldir = defvo.getDef4();
	    				 UFDouble caldirnum = UFDouble.ONE_DBL;
	    				 if(!PubAppTool.isNull(caldir)&&caldir.equals("-"))
	    					 caldirnum = caldirnum.multiply(-1);
	    				 String key = pk_inout+"#"+pk_dept+"#"+pk_paytype+"#null#"+pkpro;
	    				 if(PubAppTool.isNull(defvo.getDef2()))
	    					 ExceptionUtils.wrappBusinessException("研发费对照表配置不全，请检查！！");
	    				 String[] itemkeys = defvo.getDef2().split("\\+");
	    				 
	    				 UFDouble calmny = UFDouble.ZERO_DBL;
	    				 for (String item : itemkeys) {
	    					 if(keyitemmap.containsKey(item)) {
		    					 if(keyitemmap.get(item).startsWith(prokeyname)) {
		    						 Object itemvalue = DevWaDataVO.getAttributeValue(item);
		    						 if(null!=itemvalue) {
		    							 calmny= calmny.add(new UFDouble(itemvalue.toString())).multiply(caldirnum);
		    						 }
		    					 }
	    					 }else {
	    						 if(!undefindkeyList.contains(item))
	    							 undefindkeyList.add(item);
	    					 }
	    				 }
	    				 if(calmny.doubleValue()!=0) {
	    					 
	    					 //记录数据按收支项目+部门+项目
	    					 if(rdmap.containsKey(key)) {
	    						 rdmap.put(key, rdmap.get(key).add(calmny));
	    					 }else {
	    						 rdmap.put(key, calmny);
	    					 }
	    				 }
	    			 }
	    			 
	    		 }
	    		 
	    	 }
	    	 
	     }
	     
	     if(CollectionUtils.isNotEmpty(undefindkeyList)) {
	    	 ExceptionUtils.wrappBusinessException("以下字段未在【公式薪资项目-集团】中定义，请检查itemkey为【"+undefindkeyList.stream().collect(Collectors.joining("】,【"))+"】的数据");
	     }
	     String pk_org = rdlist.get(0).getPk_org();
	     //处理判断是否所有项目都 有对应 
	     if(CollectionUtils.isNotEmpty(projectlist)) {
	    	 String qprojectsql = "select * from bd_project where nvl(dr,0)= 0 and pk_org = '"+pk_org+"' and " + new IDExQueryBuilder("project_name").buildSQL("project_name", projectlist.stream().toArray(String[]::new)) ;
	    	 try {
				List<ProjectHeadVO> results = (List<ProjectHeadVO>)getBaseDAO().executeQuery( qprojectsql, new BeanListProcessor(ProjectHeadVO.class));
				projectmap.putAll((HashMap<String, String>) results.stream().collect(Collectors.toMap(ProjectHeadVO::getProject_name, ProjectHeadVO::getPk_project))); 
	    	 } catch (DAOException e) {
				// TODO Auto-generated catch block
				ExceptionUtils.wrappBusinessException("查询项目失败："+e.getMessage());
			}
	     
	     }
	     Map filtermap = projectmap;
	     String unfindproject = projectlist.stream().filter(proname->!filtermap.containsKey(proname)).collect(Collectors.joining("】,【"));
	     if(!PubAppTool.isNull(unfindproject))
	    	 ExceptionUtils.wrappBusinessException("未能在项目档案找到以下档案，请检查【"+unfindproject+"】");
	}

	
	private void CalSalaryMap(List<DevWaDataVO> salaryList, HashMap<String, UFDouble> salarymap, List<DefdocVO> fK004, List<DefdocVO> fK006, boolean ispushyear) throws BusinessException {
		// TODO Auto-generated method stub
		if(CollectionUtils.isEmpty(salaryList))
			return;
	     //遍历工资数据
	     for (DevWaDataVO DevWaDataVO : salaryList) {
	    	 String pk_dept = DevWaDataVO.getPk_financedept();
	    	 String cyearperiod =DevWaDataVO.getCyearperiod();
	    	 String pk_gwlb =  PubAppTool.isNull(DevWaDataVO.getPk_gwlb())?"gwlb": DevWaDataVO.getPk_gwlb();
	    	 if(!ispushyear&&CollectionUtils.isNotEmpty(fK004)) {
	    		 
	    		 //处理工资数据
	    		 for (DefdocVO defvo : fK004) {
	    			 String pk_inout = defvo.getDef1();
	    			 String pk_paytype = defvo.getDef3();
	    	         String gwlb =  PubAppTool.isNull(defvo.getDef5())?"gwlb": defvo.getDef5() ;
	    	         UFBoolean ischeckgwlb = PubAppTool.isNull(defvo.getDef6())?UFBoolean.FALSE:new UFBoolean(defvo.getDef6());
	    	         //校验岗位类型且一致，不做计算
	    	         if(ischeckgwlb.booleanValue()&& !pk_gwlb.equals(gwlb))
	    	        	 continue;
	    			 //计算方向 
	    			 String caldir = defvo.getDef4();
	    			 UFDouble caldirnum = UFDouble.ONE_DBL;
	    			 if(!PubAppTool.isNull(caldir)&&caldir.equals("-"))
	    				 caldirnum = caldirnum.multiply(-1);
	    			 
	    			 String key = pk_inout+"#"+pk_dept+"#"+pk_paytype+"#"+pk_gwlb;
	    			 if(PubAppTool.isNull(defvo.getDef2()))
	    				 ExceptionUtils.wrappBusinessException("工资对照表配置不全，请检查！！");
	    			 String[] itemkeys = defvo.getDef2().split("\\+");
	    			 UFDouble calmny = UFDouble.ZERO_DBL;
	    			 for (String item : itemkeys) {
	    				 Object itemvalue = DevWaDataVO.getAttributeValue(item);
	    				 if(null!=itemvalue) {
	    					 calmny=calmny.add(new UFDouble(itemvalue.toString())).multiply(caldirnum);
	    				 }
	    			 }
	    			 if(calmny.doubleValue()!=0) {
	    				 
	    				 //记录数据按收支项目+部门
	    				 if(salarymap.containsKey(key)) {
	    					 salarymap.put(key, salarymap.get(key).add(calmny));
	    				 }else {
	    					 salarymap.put(key, calmny);
	    				 }
	    			 }
	    		 }
	    	 }
	    	 
	    	 if(ispushyear&&CollectionUtils.isNotEmpty(fK006)) {
	    		 
	    		 //处理年金数据
	    		 for (DefdocVO defvo : fK006) {
	    			 String pk_inout = defvo.getDef1();
	    			 String pk_paytype = defvo.getDef3();
	    			 String gwlb =  PubAppTool.isNull(defvo.getDef5())?"gwlb": defvo.getDef5() ;
	    	         UFBoolean ischeckgwlb = PubAppTool.isNull(defvo.getDef6())?UFBoolean.FALSE:new UFBoolean(defvo.getDef6());
	    	         //校验岗位类型且一致，不做计算
	    	         if(ischeckgwlb.booleanValue()&& !pk_gwlb.equals(gwlb))
	    	        	 continue;
	    			 String key = pk_inout+"#"+pk_dept+"#"+pk_paytype+"#"+pk_gwlb;
	    			 if(PubAppTool.isNull(defvo.getDef2()))
	    				 ExceptionUtils.wrappBusinessException("年金对照表配置不全，请检查！！");
	    			 String[] itemkeys = defvo.getDef2().split("\\+");
	    			 UFDouble calmny = UFDouble.ZERO_DBL;
	    			 for (String item : itemkeys) {
	    				 Object itemvalue = DevWaDataVO.getAttributeValue(item);
	    				 if(null!=itemvalue) {
	    					 calmny=calmny.add(new UFDouble(itemvalue.toString()));
	    				 }
	    			 }
	    			 if(calmny.doubleValue()!=0) {
	    				 
	    				 //记录数据按收支项目+部门
	    				 if(salarymap.containsKey(key)) {
	    					 salarymap.put(key, salarymap.get(key).add(calmny));
	    				 }else {
	    					 salarymap.put(key, calmny);
	    				 }
	    			 }
	    		 }
	    	 }
		}
		
	}

	private Map<String, List<DevWaQueryDTO>> getSendDataStatus(String pk_org, String cyear, String cperiod) {
		// TODO Auto-generated method stub
		String lastmonth = getlastperiod(cyear, cperiod);
		String qsql =   " select ww.pk_org,\n" +
						"       ww.code,\n" + 
						"       ww.name,\n" + 
						"       ww.pk_wa_class,\n" + 
						"       wpi.cyear,\n" + 
						"       wpi.cperiod,\n" + 
						"       wpi.pk_wa_period,\n" + 
						"       nvl(wps.payoffflag,'N') as payoffflag,\n" + 
						"       nvl(ww.def1,'N') as watype\n" + 
						"  from wa_waclass ww\n" + 
						" inner join wa_periodscheme wp\n" + 
						"    on ww.pk_periodscheme = wp.pk_periodscheme\n" + 
						" inner join wa_period wpi\n" + 
						"    on wp.pk_periodscheme = wpi.pk_periodscheme\n" + 
						"     and wpi.cyear||wpi.cperiod<=ww.cyear||ww.cperiod\n" + 
						"  left join wa_periodstate wps\n" + 
						"    on ww.pk_wa_class = wps.pk_wa_class\n" + 
						"   and wpi.pk_wa_period = wps.pk_wa_period\n" + 
						" where nvl(ww.dr, 0) = 0\n" + 
						"   and nvl(wp.dr, 0) = 0\n" + 
						"   and nvl(wpi.dr, 0) = 0 \n"+
						"   and   ww.stopflag ='N' \n"+
						"   and ww.pk_org = '"+pk_org+ "'\n"+
						"   and wpi.cyear = '"+cyear+"' \n"+
						"   and wpi.cperiod = '"+cperiod+"' \n" +
						"   and ww.def1 in ( '本月工资','研发费用' ) \n" +
						" union \n"+
						" select ww.pk_org,\n" +
						"       ww.code,\n" + 
						"       ww.name,\n" + 
						"       ww.pk_wa_class,\n" + 
						"       wpi.cyear,\n" + 
						"       wpi.cperiod,\n" + 
						"       wpi.pk_wa_period,\n" + 
						"       nvl(wps.payoffflag,'N') as payoffflag,\n" + 
						"       nvl(ww.def1,'N') as watype\n" + 
						"  from wa_waclass ww\n" + 
						" inner join wa_periodscheme wp\n" + 
						"    on ww.pk_periodscheme = wp.pk_periodscheme\n" + 
						" inner join wa_period wpi\n" + 
						"    on wp.pk_periodscheme = wpi.pk_periodscheme\n" + 
						"    and wpi.cyear||wpi.cperiod<=ww.cyear||ww.cperiod\n" + 
						"  left join wa_periodstate wps\n" + 
						"    on ww.pk_wa_class = wps.pk_wa_class\n" + 
						"   and wpi.pk_wa_period = wps.pk_wa_period\n" + 
						" where nvl(ww.dr, 0) = 0\n" + 
						"   and nvl(wp.dr, 0) = 0\n" + 
						"   and nvl(wpi.dr, 0) = 0 \n"+
						"   and   ww.stopflag ='N' \n"+
						"   and ww.pk_org = '"+pk_org+ "'\n"+
						"   and wpi.cyear = '"+lastmonth.substring(0, 4)+"' \n"+
						"   and wpi.cperiod = '"+lastmonth.substring(4, 6)+"' \n" +
						"   and ww.def1 in ( '上月工资') \n" ;
		List<DevWaQueryDTO> results = null;
		try {
			results = (List<DevWaQueryDTO>)getBaseDAO().executeQuery( qsql, new BeanListProcessor(DevWaQueryDTO.class));
		} catch (DAOException e) {
			// TODO Auto-generated catch block
			ExceptionUtils.wrappBusinessException("查询薪资方案发放状态失败："+e.getMessage());
		}
		if(CollectionUtils.isEmpty(results)) {
			ExceptionUtils.wrappBusinessException("当前公司薪资期间【"+cyear+cperiod+"】未定义工资方案及研发费方案");
		}
//		for (DevWaQueryDTO result : results) {
//			 boolean ispayed = result.getPayoffflag().booleanValue();
//			 if(!ispayed) {
//				 String watype = result.getWatype();
//				 ExceptionUtils.wrappBusinessException("当前公司薪资期间【"+cyear+cperiod+"】【"+watype+"】未发放,请检查！");
//			 }
//		}
		
		return results.stream().collect(Collectors.groupingBy(DevWaQueryDTO::getWatype ,Collectors.toList()));
	}
	
	
	private HashMap<String, List<DevWaDataVO>> getWaDatas(DevWaQueryDTO[] vos) {
		// TODO Auto-generated method stub
		List<DevWaDataVO> wadatas = new ArrayList<DevWaDataVO>();
		for (DevWaQueryDTO devWaQueryDTO : vos) {
			String sql = " select wa.*,op.glbdef2 pk_gwlb  from wa_data wa "
					+ " left join hi_psnjob job on wa.pk_psnjob = job.pk_psnjob and nvl(job.dr,0) = 0 "
					+ " left join om_post op on  job.pk_post = op.pk_post and nvl(op.dr,0)=0 "
					+ " where nvl(wa.dr,0)=0 "
					+ " and wa.pk_org = '"+devWaQueryDTO.getPk_org()+"'"
					+ " and wa.stopflag = 'N' "
					+" and wa.pk_wa_class ='"+devWaQueryDTO.getPk_wa_class()+"'"
					+" and wa.cyearperiod = '"+devWaQueryDTO.getCyear()+devWaQueryDTO.getCperiod()+"'";
			try {
				List<DevWaDataVO> results = (List<DevWaDataVO>)getBaseDAO().executeQuery( sql, new BeanListProcessor(DevWaDataVO.class));
			    if(null!=results)
			    	wadatas.addAll(results);
			} catch (DAOException e) {
				// TODO Auto-generated catch block
				ExceptionUtils.wrappBusinessException("获取薪资发放数据失败："+e.getMessage());
			}
		}
		return  (HashMap<String, List<DevWaDataVO>>) wadatas.stream().collect(Collectors.groupingBy(DevWaDataVO::getPk_wa_class, Collectors.toList()));
	}
	
	/**
	 * 根据年月获取上一个月，返回如202205这样的值进行拆分
	 * @param cyear
	 * @param cperiod
	 * @return
	 */
	private String getlastperiod(String cyear,String cperiod) {
		LocalDate lastmonthdate= LocalDate.of(Integer.parseInt(cyear),Integer.parseInt(cperiod),1 ).minusMonths(1);
		
		String returnmethod = lastmonthdate.getYear()+(lastmonthdate.getMonthValue()<10?"0"+lastmonthdate.getMonthValue():lastmonthdate.getMonthValue()+"");
		
		return returnmethod;
		
	}
	
	/**
	 * 根据年月获取，返回如202205这样的值进行拆分
	 * @param cyear
	 * @param cperiod
	 * @return
	 */
	private String getnextperiod(String cyear,String cperiod) {
		LocalDate nextmonthdate= LocalDate.of(Integer.parseInt(cyear),Integer.parseInt(cperiod),1 ).plusMonths(1);
		
		String returnmethod = nextmonthdate.getYear()+(nextmonthdate.getMonthValue()<10?"0"+nextmonthdate.getMonthValue():nextmonthdate.getMonthValue()+"");
		
		return returnmethod;
		
	}
	

	private BaseDAO baseDAO;
	
	public BaseDAO getBaseDAO() {
		if (baseDAO == null) {
			baseDAO = new BaseDAO();
		}
		return baseDAO;
	}
	 private IBDDatasGainTool BdGainserver = (IBDDatasGainTool) NCLocator.getInstance().lookup(IBDDatasGainTool.class);

}
