/*HSxxRIFQ+8j1Z0CxDy9Wh8q2/m1lLemdbyabwEn07iAs031dRalbxGC7uHn1bRpmhRA2hxP9v7uM
GfRxh0n51w==*/
package nc.impl.sscpfa.pfareport.service;

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

import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Logger;
import nc.bs.sscrp.tools.SqlUtils;
import nc.impl.sscpfa.pfareport.util.GetDatabaseUtil;
import nc.impl.sscpfa.pfareport.util.SSCReportStatisticUtil;
import nc.impl.sscpfa.pfareport.util.TimestampUtils;
import nc.itf.cmp.settlement.ISettlementQueryForSscService;
import nc.itf.sscpfa.pfareport.ISSCTaskQueryService;
import nc.jdbc.framework.JdbcSession;
import nc.jdbc.framework.PersistenceManager;
import nc.jdbc.framework.SQLParameter;
import nc.jdbc.framework.exception.DbException;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.jdbc.framework.util.DBConsts;
import nc.pub.smart.context.SmartContext;
import nc.vo.ml.MultiLangUtil;
import nc.vo.pub.BusinessException;
import nc.vo.pub.BusinessRuntimeException;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.sscpfa.pfareport.report.ReportQueryConditionVO;
import nc.vo.ssctp.sscbd.constant.SSCWorkFlowConst;
import nc.vo.ssctp.sscbd.enumeration.ActionType;
import nc.vo.ssctp.sscbd.enumeration.TaskStatus;
import nccloud.commons.lang.StringUtils;
import nccloud.pubitf.sscpub.module.enable.ISCCGroupAndModuleCheck;

public class TaskDetailQueryService {
	
	BaseDAO dao = new BaseDAO();
	private int period = 1;
	private String suffix = "";
	
	public void queryAndUpdateBills(ReportQueryConditionVO reportQueryConditionVO,SmartContext context,String tableName){
		
		suffix = MultiLangUtil.getCurrentLangSeqSuffix();
		
		try {
			if(reportQueryConditionVO.getReportType_src() == null){
				String startdate = reportQueryConditionVO.getCur_startdate();
				String enddate = reportQueryConditionVO.getCur_enddate();
				//统计提交后的数据
				queryCommitBills(reportQueryConditionVO,tableName,startdate,enddate);
				//影像扫描
				queryImageBills(reportQueryConditionVO,tableName,startdate,enddate);
				//本地流程
				queryLocalBills(reportQueryConditionVO,tableName,startdate,enddate);
				//共享初审
				queryFirstExamBills(reportQueryConditionVO,tableName,startdate,enddate);
				//共享复审
				queryReExamBills(reportQueryConditionVO,tableName,startdate,enddate);
				//签字、结算
				querySignAndSettleBills(reportQueryConditionVO,tableName);
			}else{
				String reporttype = reportQueryConditionVO.getReportType();
				reportQueryConditionVO.setReportType(reportQueryConditionVO.getReportType_src());
				ISSCTaskQueryService service = (ISSCTaskQueryService)NCLocator.getInstance().lookup(ISSCTaskQueryService.class);
				service.queryData(reportQueryConditionVO, context);
				String startdate = reportQueryConditionVO.getStartdate();
				String enddate = reportQueryConditionVO.getEnddate();
				//统计提交后的数据
				queryCommitBillsForLink(reportQueryConditionVO,tableName,startdate,enddate);
				if(reportQueryConditionVO.getReportType_src().equals("imagescan")||reportQueryConditionVO.getReportType_src().equals("fullprocess")){
					//影像扫描
					queryImageBillsForLink(reportQueryConditionVO,tableName,startdate,enddate);
				}
				if(reportQueryConditionVO.getReportType_src().equals("localprocess")||reportQueryConditionVO.getReportType_src().equals("fullprocess")){
					//本地流程
					queryLocalBillsForLink(reportQueryConditionVO,tableName,startdate,enddate);
				}
				if(reportQueryConditionVO.getReportType_src().equals("firstexam")||reportQueryConditionVO.getReportType_src().equals("reviewexam")||reportQueryConditionVO.getReportType_src().equals("sscapprove")
						||reportQueryConditionVO.getReportType_src().equals("sscprocess")||reportQueryConditionVO.getReportType_src().equals("fullprocess")){
					//共享初审
					queryFirstExamBillsForLink(reportQueryConditionVO,tableName,startdate,enddate);
					//共享复审
					queryReExamBillsForLink(reportQueryConditionVO,tableName,startdate,enddate);
				}
				if(reportQueryConditionVO.getReportType_src().equals("sscprocess")||reportQueryConditionVO.getReportType_src().equals("fullprocess")
						||reportQueryConditionVO.getReportType_src().equals("sign")||reportQueryConditionVO.getReportType_src().equals("settle")||reportQueryConditionVO.getReportType_src().equals("payment")){
					//签字、结算
					querySignAndSettleBillsForLink(reportQueryConditionVO,tableName);
				}			
				reportQueryConditionVO.setReportType(reporttype);
			}
			//
		} catch (BusinessException e) {
			throw new BusinessRuntimeException(e.getMessage(), e);
		}
		
	}
	
	public void queryCommitBills(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName, String starttime, String endtime) throws BusinessException{
		
		
		String pk_sscunit = reportQueryConditionVO.getPk_sscunit();
		String pk_org = reportQueryConditionVO.getPk_org();
		String pk_transtype = reportQueryConditionVO.getPk_transtype();//多选，逗号隔开
		UFBoolean includeAutoApprove =  reportQueryConditionVO.getIncludeAutoApprove();

		//2022/04/19 邵丹 add start
  		String billno = reportQueryConditionVO.getBillno();//单据编号
        	String pre_creationtime = reportQueryConditionVO.getPre_creationtime();//单据提交开始时间
        	String end_creationtime = reportQueryConditionVO.getEnd_creationtime();//单据提交结束时间
        	String billmaker = reportQueryConditionVO.getBillmaker();//报账人
		//2022/04/19 邵丹 add end
		StringBuilder sb = new StringBuilder("insert into " + tableName + " (billid,billno,pk_group,pk_org,pk_org_name,pk_billtypecode,pk_tradetype,tradetypecode,tradetypename,committime,amount,pk_currtype,billdate,billmaker,pay_mny,paycomfirm_time) ");
		
		//2022/04/19 邵丹 update
		//sb.append(" SELECT TASK.BUSIID BILLID,                                       ");
		sb.append(" SELECT distinct TASK.BUSIID BILLID,                                       ");
		//2022/04/19 邵丹 update
		
		sb.append("        TASK.BILLNO,                                              ");
		sb.append("        TASK.PK_GROUP,                                            ");
		sb.append("        TASK.PK_ORG,                                              ");
		sb.append("        '' PK_ORG_NAME,                                           ");
		sb.append("        '' PK_BILLTYPECODE,                                       ");
		sb.append("        TASK.PK_TRADETYPE PK_TRADETYPE,                           ");
		sb.append("        '' TRADETYPECODE,                                         ");
		sb.append("        '' TRADETYPENAME,                                         ");
		sb.append("        TASK.CREATIONTIME COMMITTIME,                             ");//当前任务的创建时间就是单据的提交时间
		sb.append("        isnull(TASK.AMOUNT, 0) AMOUNT,                            ");
		sb.append("        TASK.PK_CURRTYPE PK_CURRTYPE,                             ");
		sb.append("        TASK.BILLDATE,                                            ");
		sb.append("        SM_USER.USER_NAME BILLMAKER,                              ");
				
		//2022/04/08 mrcopy add
//		sb.append("        bx.zfbbje pay_mny			                         ");
		sb.append("case when TASK.billtypecode = '264X' then bx.zfbbje else jk.zfbbje  end pay_mny, ");

		sb.append("        ebank_b.paydate paycomfirm_time			                       ");
		//2022/04/08 mrcopy add
		
		sb.append("   FROM SSCTP_CURRENTTASK TASK LEFT JOIN SM_USER 				 ");
		sb.append("     ON TASK.BILLMAKER = SM_USER.CUSERID                          ");
		
		
		//2022/04/08 mrcopy add start
		sb.append("  LEFT JOIN ebank_confirmpay_h ebank_h   						  ");
		sb.append("  	on ebank_h.sourcebillno = TASK.billno 			  			  ");
		sb.append("  LEFT JOIN ebank_confirmpay_b ebank_b   						  ");
		sb.append("  	on ebank_h.pk_confirmpay_h = ebank_b.pk_confirmpay_h 			  ");
		sb.append("  left join er_bxzb bx												");
		sb.append("  	on bx.pk_jkbx = TASK.BUSIID 									");
		sb.append("  left join er_jkzb jk");
		sb.append("  	on jk.pk_jkbx = TASK.BUSIID 									");
		//2022/04/08 mrcopy add end
		
		//add by sdan srart
		sb.append("  LEFT JOIN ssctp_flowpath flowpath   						  ");
		sb.append("  on flowpath.pk_currenttask = TASK.pk_currenttask 			  ");
		//add by sdan end
		
		sb.append("   WHERE 1=1 ");

		if(StringUtils.isNotEmpty(pk_sscunit)){
			sb.append(" AND TASK.PK_SSCUNIT = '" + pk_sscunit + "'                      ");
		}
		if(StringUtils.isNotEmpty(pk_org)){
			sb.append(" AND " + SqlUtils.getInStr("TASK.PK_ORG", pk_org.split(","),true));
		}
		if(StringUtils.isNotEmpty(pk_transtype)){
			sb.append(" AND " + SqlUtils.getInStr("TASK.PK_TRADETYPE", pk_transtype.split(","),true));
		}

		
		  //add by sdan 20220416 start
   		 if (StringUtils.isNotEmpty(billno)) {
        	 sb.append(" AND TASK.BILLNO like '%"  +billno+"%' ");
     		  }
    
	     if(StringUtils.isNotEmpty(pre_creationtime) && StringUtils.isNotEmpty(end_creationtime)) {
	    	    sb.append(" AND flowpath.OPERATETIME BETWEEN '" + TimestampUtils.getFormatDate(pre_creationtime) + "' AND  ");
	    	     sb.append(" '" + TimestampUtils.getFormatDate(end_creationtime) + "'                              "); 
	  	  }
       
	     if (StringUtils.isNotEmpty(billmaker)) {
	         sb.append(" AND " + SqlUtils.getInStr("SM_USER.user_name", billmaker.split(","), true));
	       }
	       // add by sdan end

		if(includeAutoApprove == null || !includeAutoApprove.booleanValue()){
			sb.append(" AND TASK.ISAUTOAPPROVE = 'N'                      ");
		}
		sb.append(" AND TASK.BILLDATE BETWEEN '" +TimestampUtils.getFormatDate(starttime) + "' AND ");
		sb.append(" '" + TimestampUtils.getFormatDate(endtime)+ "'                              ");
		
		new BaseDAO().executeUpdate(sb.toString());
	}
	
	public void queryCommitBillsForLink(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName, String starttime, String endtime) throws BusinessException{
		
		//String flowpathsql = getFlowPathSql(reportQueryConditionVO,starttime,endtime);
		
		if(reportQueryConditionVO.getIsCurrentPeriod().equals("N")){
			period = 0;
		}
		
		StringBuilder sb = new StringBuilder("insert into " + tableName + " (billid,billno,pk_group,pk_org,pk_org_name,pk_billtypecode,pk_tradetype,tradetypecode,tradetypename,committime,amount,pk_currtype,billdate,billmaker) ");
		
		sb.append(" select distinct * from ( ");
		sb.append(" select flow.busiid billid,flow.billno,flow.pk_group,flow.pk_org,isnull(o.name"+suffix+",o.name) pk_org_name,b2.pk_billtypecode pk_billtypecode,b.pk_billtypeid pk_tradetype,b.pk_billtypecode tradetypecode, ");
		sb.append(" isnull(b.billtypename"+suffix+",b.billtypename) tradetypename,flow.operatetime committime,flow.amount amount,flow.pk_currtype pk_currtype,flow.billdate billdate,isnull(sm_user.user_name"+suffix+",sm_user.user_name) billmaker ");
		sb.append(" from ");
		
		sb.append(" (select busiid,billno,pk_group,pk_org,creationtime as operatetime,pk_tradetype,pk_billtype,amount,pk_currtype,billdate,billmaker ");
		sb.append(" from ssctp_task where busiid in (select pk_bill from "+reportQueryConditionVO.getTableName()+" where period = "+period+" and iseffectivebill = 1) and pk_sscnode = '"+SSCWorkFlowConst.MakeBillPK+"') flow ");
		
//		sb.append(" (select * from ssctp_flowpath where busiid in (select pk_bill from "+reportQueryConditionVO.getTableName()+" where iseffectivebill = 1) and actiontype = '"+ActionType.makebill.getValue()+"' and pk_sscnode = '"+SSCWorkFlowConst.MakeBillPK+"' ");
//		sb.append(" and operatetime in (select min(operatetime) from ssctp_flowpath where busiid in (select pk_bill from "+reportQueryConditionVO.getTableName()+" where period = "+period+" and iseffectivebill = 1) and actiontype = '"+ActionType.makebill.getValue()+"' group by busiid)) flow ");
		
		sb.append(" left join bd_billtype b on flow.pk_tradetype = b.pk_billtypeid ");
		sb.append(" left join bd_billtype b2 on flow.pk_billtype = b2.pk_billtypeid ");
		sb.append(" left join org_orgs o on flow.pk_org = o.pk_org ");
		
		/*sb.append(" left join ( select amount,billdate,billmaker,busiid from sscrp_bill where to_date(billdate, 'yyyy-mm-dd hh24:mi:ss')  ");
		sb.append(" between to_date('" + starttime + "','yyyy-mm-dd hh24:mi:ss') and to_date('" + endtime + "','yyyy-mm-dd hh24:mi:ss') ");
		sb.append(" union all select amount,billdate,billmaker,busiid from sscrp_bill_done where to_date(billdate, 'yyyy-mm-dd hh24:mi:ss') ");
		sb.append(" between to_date('" + starttime + "','yyyy-mm-dd hh24:mi:ss') and to_date('" + endtime + "','yyyy-mm-dd hh24:mi:ss') ");
		sb.append(" ) rp on rp.busiid = flow.busiid ");*/
		
//		sb.append(" left join (select amount,pk_currtype,billdate,billmaker,busiid from sscrp_bill where busiid in (select pk_bill from "+ reportQueryConditionVO.getTableName() +") ");
//		sb.append(" union all select amount,pk_currtype,billdate,billmaker,busiid from sscrp_bill_done where busiid in (select pk_bill from "+ reportQueryConditionVO.getTableName() +") ) rp");
//		sb.append(" on flow.busiid = rp.busiid ");
		sb.append(" left join sm_user on flow.billmaker = sm_user.cuserid ");
		
		sb.append(" ) d ");
		
		/*sb.append("where to_date(d.billdate, 'yyyy-mm-dd hh24:mi:ss') ");
		sb.append("between to_date('" + starttime + "','yyyy-mm-dd hh24:mi:ss') ");
		sb.append("and to_date('" + endtime + "','yyyy-mm-dd hh24:mi:ss')");*/
		
		new BaseDAO().executeUpdate(sb.toString());
	}
	
	
	public void queryLocalBills(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName, String starttime, String endtime) throws BusinessException{
		
		StringBuilder sb = new StringBuilder();
		sb.append(" select flow.busiid, sum(isnull(flow.statisticaltime, 0)) consumetime ");
		sb.append("   from ssctp_flowpath flow ");
		sb.append("  where (flow.pk_sscnode in ('0001ZG10000000NODE03', ");
		sb.append("                            '0001ZG10000000NODE05', ");
		sb.append("                            '0001ZG10000000NODE04') ");
		sb.append("         or (flow.pk_sscnode in ('0001ZG10000000NODE01','0001ZG10000000NODE02') and actiontype = 'busiapprove')) ");
		sb.append("			and flow.busiid in (select billid from "+tableName+") ");
		sb.append("  group by flow.busiid ");

		StringBuilder sql = new StringBuilder();
		if(GetDatabaseUtil.getDatabaseType() == DBConsts.POSTGRESQL ) {
			sql.append("update "+tableName+"  ");
			sql.append(" set "+tableName+".bdlc_costtime = B.consumetime ");
			sql.append("from ("+ sb.toString()+ ") B ");
			sql.append("where ("+tableName+".billid = B.busiid)");
		}else {
			sql.append(" merge into "+tableName+" A ");
			sql.append(" using (" + sb.toString() +" ) B ");
			sql.append(" on (A.billid = B.busiid ) ");
			sql.append(" when matched then  ");
			sql.append(" update ");
			sql.append(" set A.bdlc_costtime = B.consumetime ");
			sql.append(SSCReportStatisticUtil.getMergeTail());
		}
		
		new BaseDAO().executeUpdate(sql.toString());
	}
	
	public void queryLocalBillsForLink(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName, String starttime, String endtime) throws BusinessException{
		
		StringBuilder sb_starttime = new StringBuilder();
		sb_starttime.append(" select min(operatetime) ssc_starttime, busiid billid ");
		sb_starttime.append(" 	from ssctp_flowpath ");
		sb_starttime.append("  where actiontype = 'busiapprove' ");
		sb_starttime.append(" 	 and pk_currenttask in ");
		sb_starttime.append(" 		 (select pk_currenttask ");
		sb_starttime.append(" 			from ssctp_currenttask ");
		sb_starttime.append(" 		   where pk_sscnode in ");
		sb_starttime.append(" 				 ('0001ZG10000000NODE01', '0001ZG10000000NODE02') ");
		sb_starttime.append("			 and busiid in (select pk_bill from "+reportQueryConditionVO.getTableName()+"  ");
		sb_starttime.append("										  where period = "+period+" ");
		sb_starttime.append(" 										    and iseffectivebill = 1)) ");
		sb_starttime.append(" 	group by busiid; ");
		
		List<Map<String, Object>> ssc_starttime = (List<Map<String, Object>>) dao.executeQuery(sb_starttime.toString(), new MapListProcessor());
		String sql_start = " update "+tableName+" set ssc_starttime = ? where billid = ? ";
		List<SQLParameter> parameterList_start = new ArrayList<SQLParameter>();
		for(Map map : ssc_starttime){
			SQLParameter param = new SQLParameter();
			param.addParam(map.get("ssc_starttime") !=null?map.get("ssc_starttime"):"");
			param.addParam(map.get("billid"));
			parameterList_start.add(param);
		}
		batchUpdate(sql_start, parameterList_start);
		
		if(reportQueryConditionVO.getIsCurrentPeriod().equals("N")){
			period = 0;
		}
		
		StringBuilder sb = new StringBuilder();
		sb.append(" select flow.busiid, sum(isnull(flow.statisticaltime, 0)) consumetime ");
		sb.append("   from ssctp_flowpath flow ");
		sb.append("  where flow.pk_sscnode in ('0001ZG10000000NODE03', ");
		sb.append("                            '0001ZG10000000NODE05', ");
		sb.append("                            '0001ZG10000000NODE04') ");
		sb.append("    and flow.busiid in (select pk_bill from "+reportQueryConditionVO.getTableName()+" where period = "+period+" and iseffectivebill = 1) ");
		sb.append("  group by flow.busiid ");

		List<Map<String, Object>> local = (List<Map<String, Object>>) dao.executeQuery(sb.toString(), new MapListProcessor());
		
		String sql = " update "+tableName+" set bdlc_costtime = ? where billid = ? ";
		List<SQLParameter> parameterList = new ArrayList<SQLParameter>();
		for(Map map : local){
			SQLParameter param = new SQLParameter();
			param.addParam(map.get("consumetime") !=null?map.get("consumetime"):0);
			param.addParam(map.get("busiid"));
			parameterList.add(param);
		}
		batchUpdate(sql, parameterList);
	}
	
	public void queryImageBills(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName, String starttime, String endtime) throws BusinessException{
		
		StringBuilder sb = new StringBuilder();
		sb.append(" select zgsm_starttime, ");
		sb.append("        ssctp_task.operatetime zgsm_endtime, ");
		sb.append("        isnull(sm_user.user_name"+suffix+",sm_user.user_name)      zgsm_user, ");
		sb.append("        zgsm_costtime, ");
		sb.append("        ssctp_task.busiid ");
		sb.append("   from ssctp_task ");
		sb.append("   left join (select busiid, ");
		sb.append("                     min(beigntime) zgsm_starttime, ");
		sb.append("                     sum(statisticaltime) zgsm_costtime ");
		sb.append("                from ssctp_flowpath ");
		sb.append("               where pk_sscnode = '0001ZG10000000NODE04' and  beginstate = '" + TaskStatus.waitingscan + "'  ");
		sb.append("               group by ssctp_flowpath.busiid) flow ");
		sb.append("     on ssctp_task.busiid = flow.busiid ");
		sb.append("   left join sm_user ");
		sb.append("     on ssctp_task.operator = sm_user.cuserid ");
		sb.append("  where pk_sscnode = '0001ZG10000000NODE04' ");
		sb.append(" 	  and billdate between '"+TimestampUtils.getFormatDate(starttime)+"' and '"+TimestampUtils.getFormatDate(endtime)+"' ");
		
		StringBuilder sql = new StringBuilder();
		if(GetDatabaseUtil.getDatabaseType() == DBConsts.POSTGRESQL ) {
			sql.append("update "+tableName+"  ");
			sql.append(" set "+tableName+".zgsm_starttime = B.zgsm_starttime,");
			sql.append(" "+tableName+".zgsm_endtime = B.zgsm_endtime,");
			sql.append(" "+tableName+".zgsm_costtime = B.zgsm_costtime,");
			sql.append(" "+tableName+".zgsm_user = B.zgsm_user ");
			sql.append("from ("+ sb.toString()+ ") B ");
			sql.append("where ("+tableName+".billid = B.busiid) ");
		}else {
			sql.append(" merge into "+tableName+" A ");
			sql.append(" using (" + sb.toString() +" ) B ");
			sql.append(" on (A.billid = B.busiid ) ");
			sql.append(" when matched then  ");
			sql.append(" update ");
			sql.append(" set A.zgsm_starttime = B.zgsm_starttime,");
			sql.append(" A.zgsm_endtime = B.zgsm_endtime,");
			sql.append(" A.zgsm_costtime = B.zgsm_costtime,");
			sql.append(" A.zgsm_user = B.zgsm_user ");
			sql.append(SSCReportStatisticUtil.getMergeTail());
		}
		
		new BaseDAO().executeUpdate(sql.toString());
		
	}
	
	public void queryImageBillsForLink(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName, String starttime, String endtime) throws BusinessException{
		
		if(reportQueryConditionVO.getIsCurrentPeriod().equals("N")){
			period = 0;
		}
		
		StringBuilder sb = new StringBuilder();
		sb.append(" select zgsm_starttime, ");
		sb.append("        ssctp_task.operatetime zgsm_endtime, ");
		sb.append("        isnull(sm_user.user_name"+suffix+",sm_user.user_name)      zgsm_user, ");
		sb.append("        zgsm_costtime, ");
		sb.append("        ssctp_task.busiid ");
		sb.append("   from ssctp_task ");
		sb.append("   left join (select busiid, ");
		sb.append("                     min(beigntime) zgsm_starttime, ");
		sb.append("                     sum(statisticaltime) zgsm_costtime ");
		sb.append("                from ssctp_flowpath ");
		sb.append("               where pk_sscnode = '0001ZG10000000NODE04' and beginstate = '" + TaskStatus.waitingscan + "' ");
		sb.append("               group by ssctp_flowpath.busiid) flow ");
		sb.append("     on ssctp_task.busiid = flow.busiid ");
		sb.append("   left join sm_user ");
		sb.append("     on ssctp_task.operator = sm_user.cuserid ");
		sb.append("  where pk_sscnode = '0001ZG10000000NODE04' ");
		sb.append(" and ssctp_task.busiid in (select pk_bill from "+reportQueryConditionVO.getTableName()+" where period = "+period+" and iseffectivebill = 1)  ");
		
		List<Map<String, Object>> zgsm = (List<Map<String, Object>>) dao.executeQuery(sb.toString(), new MapListProcessor());
		
		String sql = " update "+tableName+" set zgsm_starttime = ?,zgsm_endtime = ?,zgsm_costtime = ?,zgsm_user = ? where billid = ? ";
		List<SQLParameter> parameterList = new ArrayList<SQLParameter>();
		for(Map map : zgsm){
			SQLParameter param = new SQLParameter();
			param.addParam(map.get("zgsm_starttime") !=null?map.get("zgsm_starttime"):"");
			param.addParam(map.get("zgsm_endtime") !=null?map.get("zgsm_endtime"):"");
			param.addParam(map.get("zgsm_costtime") !=null?map.get("zgsm_costtime"):"");
			param.addParam(map.get("zgsm_user") !=null?map.get("zgsm_user"):"");
			param.addParam(map.get("busiid"));
			parameterList.add(param);
		}
		batchUpdate(sql, parameterList);
		/*StringBuilder sb2 = new StringBuilder();
		sb2.append(" select count(statisticaltime) from ssctp_flowpath where pk_sscnode = '"+SSCWorkFlowConst.ImagePK+"' and actiontype in ('"+ActionType.afterAccount.getValue()+"','"+ActionType.beforeImage.getValue()+"') group by busiid  ");*/
		
	}
	
	
	//TODO mrcopy 2022/04/14  审核开始时间  未对DBConsts.POSTGRESQL 支持  
	public void queryFirstExamBills(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName, String starttime, String endtime) throws BusinessException{
		
		StringBuilder sb_starttime = new StringBuilder();
		
		//20222/04/08 mrcopy update
//		sb_starttime.append(" select min(operatetime) ssc_starttime, busiid ");
//		sb_starttime.append(" 	from ssctp_flowpath ");
//		sb_starttime.append("  where actiontype = 'busiapprove' ");
//		sb_starttime.append(" 		 and pk_sscnode in ('0001ZG10000000NODE01', '0001ZG10000000NODE02') ");
//		sb_starttime.append(" 		 and busiid in (select billid from "+tableName+") ");
//		sb_starttime.append(" 	group by busiid ");
		//20222/04/08 mrcopy update
		
		//20222/04/08 mrcopy add
		sb_starttime.append("select case when max(ssctp_flowpath2.operatetime)   is not null then max(ssctp_flowpath2.operatetime) else max(ssctp_flowpath.operatetime)  end  ssc_starttime, ssctp_flowpath.busiid  	");
		sb_starttime.append(" from ssctp_flowpath ");
		sb_starttime.append(" left join ssctp_flowpath ssctp_flowpath2 ");
		sb_starttime.append(" on ssctp_flowpath2.busiid = ssctp_flowpath.busiid and ssctp_flowpath2.actiontype in ('fetchback','forcefetchback') ");
		sb_starttime.append(" where ssctp_flowpath.actiontype in ('busiapprove','fetchback','forcefetchback')	 and ssctp_flowpath.pk_sscnode in ('0001ZG10000000NODE01', '0001ZG10000000NODE02') ");
		sb_starttime.append(" and ssctp_flowpath.busiid in (select billid from "+tableName+") ");
		sb_starttime.append( " group by ssctp_flowpath.busiid    " );
		//20222/04/08 mrcopy add
		
		
		
		StringBuilder sql = new StringBuilder();
		if(GetDatabaseUtil.getDatabaseType() == DBConsts.POSTGRESQL ) {
			sql.append("update "+tableName+"  ");
			sql.append(" set "+tableName+".ssc_starttime = B.ssc_starttime ");
			sql.append("from ("+ sb_starttime.toString()+ ") B ");
			sql.append("where ("+tableName+".billid = B.busiid)");
		}else {
			sql.append(" merge into "+tableName+" A ");
			sql.append(" using (" + sb_starttime.toString() +" ) B ");
			sql.append(" on (A.billid = B.busiid ) ");
			sql.append(" when matched then  ");
			sql.append(" update ");
			sql.append(" set A.ssc_starttime = B.ssc_starttime ");
			sql.append(SSCReportStatisticUtil.getMergeTail());
		}
		
		new BaseDAO().executeUpdate(sql.toString());
		
		
		
		//20222/04/17 mrcopy add
		StringBuilder sb_getbill_time = new StringBuilder();
		//3.增加“单据到手时间”（操作记录为提取、智能派单、分配、强制分配、取消审核的最新一次操作时间，多次到手按最新一次覆盖）
		sb_getbill_time.append(" select max(operatetime) getbill_time,busiid ");
		sb_getbill_time.append(" from ssctp_flowpath where ");
		sb_getbill_time.append(" actiontype in ('take','intelliDispatch','distribute','forcedistribute','un-sscapprove') ");
		sb_getbill_time.append(" and ssctp_flowpath.pk_sscnode in ('0001ZG10000000NODE01', '0001ZG10000000NODE02') ");
		sb_getbill_time.append("  and ssctp_flowpath.busiid in (select billid from "+ tableName +")   ");
		sb_getbill_time.append(" group by busiid ");
		
		
		StringBuilder sql_getbill_time = new StringBuilder();
		if(GetDatabaseUtil.getDatabaseType() == DBConsts.POSTGRESQL ) {
			sql_getbill_time.append("update "+tableName+"  ");
			sql_getbill_time.append(" set "+tableName+".getbill_time = B.getbill_time ");
			sql_getbill_time.append("from ("+ sb_getbill_time.toString()+ ") B ");
			sql_getbill_time.append("where ("+tableName+".billid = B.busiid)");
		}else {
			sql_getbill_time.append(" merge into "+tableName+" A ");
			sql_getbill_time.append(" using (" + sb_getbill_time.toString() +" ) B ");
			sql_getbill_time.append(" on (A.billid = B.busiid ) ");
			sql_getbill_time.append(" when matched then  ");
			sql_getbill_time.append(" update  ");
			sql_getbill_time.append(" set A.getbill_time = B.getbill_time ");
			
			sql_getbill_time.append(SSCReportStatisticUtil.getMergeTail());
		}
		new BaseDAO().executeUpdate(sql_getbill_time.toString());

		
//		select * from pub_workflownote note join 
//		(select distinct billid,FIRST_VALUE(pk_checkflow) over (partition by billid order by senddate ) pk_checkflow from pub_workflownote workflownote  join (
//		 select max(beigntime) beigntime,busiid from ssctp_flowpath where busiid='1001Q710000000T7J8Q8' and actiontype = 'sscapprove' group by busiid
//		 ) flowpath on workflownote.billid = flowpath.busiid and workflownote.senddate >= flowpath.beigntime and actiontype <> 'BIZ'
//		) checkflow on note.pk_checkflow = checkflow.pk_checkflow
		
		
		//TODO 不支持非oracle 数据库
		StringBuilder sb_recbill_data = new StringBuilder();
		//3.增加“单据到手时间”（操作记录为提取、智能派单、分配、强制分配、取消审核的最新一次操作时间，多次到手按最新一次覆盖）


		sb_recbill_data.append(" select  ");
		sb_recbill_data.append(" note.billid, note.dealdate recbill_time , sm_user.user_name recbill_user, operatetime  flowpath_sscapprove");
		sb_recbill_data.append(" from pub_workflownote note join ");
		sb_recbill_data.append(" (select distinct billid, flowpath.operatetime,FIRST_VALUE(pk_checkflow) over (partition by billid order by senddate ) pk_checkflow ");
		sb_recbill_data.append(" 		from pub_workflownote workflownote  join ( ");
		sb_recbill_data.append("  select max(beigntime) beigntime,max(operatetime) operatetime, busiid from ssctp_flowpath where busiid in (select billid from "+ tableName +")  and actiontype = 'sscapprove' group by busiid ");
//		sb_recbill_data.append("   ) flowpath on workflownote.billid = flowpath.busiid and workflownote.dealdate >= flowpath.beigntime and actiontype <> 'BIZ' ");
		sb_recbill_data.append("   ) flowpath on workflownote.billid = flowpath.busiid and workflownote.dealdate > flowpath.operatetime and actiontype <> 'BIZ'  and workflownote.approveresult='Y' and ischeck !='X' ");
		sb_recbill_data.append("  ) checkflow on note.pk_checkflow = checkflow.pk_checkflow  ");
		sb_recbill_data.append(" join sm_user on note.checkman = sm_user.cuserid ");
		sb_recbill_data.append(" where  (select pk_org from org_orgs where pk_org = sm_user.user_code) is null ");
		
		
		StringBuilder sql_recbill_data = new StringBuilder();
		if(GetDatabaseUtil.getDatabaseType() == DBConsts.POSTGRESQL ) {
			sql_recbill_data.append("update "+tableName+" set ");
//			sql_recbill_data.append("  "+tableName+".getbill_time = B.getbill_time ");
			sql_recbill_data.append("from ("+ sb_recbill_data.toString()+ ") B ");
			sql_recbill_data.append("where ("+tableName+".billid = B.busiid)");
		}else {
			sql_recbill_data.append(" merge into "+tableName+" A ");
			sql_recbill_data.append(" using (" + sb_recbill_data.toString() +" ) B ");
			sql_recbill_data.append(" on (A.billid = B.billid ) ");
			sql_recbill_data.append(" when matched then  ");
			sql_recbill_data.append(" update set ");
			sql_recbill_data.append("  A.recbill_time = B.recbill_time ,");
			sql_recbill_data.append("  A.recbill_user = B.recbill_user, ");
			sql_recbill_data.append("  A.flowpath_sscapprove = B.flowpath_sscapprove ");
			
			
			sql_recbill_data.append(SSCReportStatisticUtil.getMergeTail());
		}
		new BaseDAO().executeUpdate(sql_recbill_data.toString());
		
		
		
		
		//20222/04/17 mrcopy add
		
		
		StringBuilder sb = new StringBuilder();
		sb.append("	select task.busiid, ");
		sb.append("		   task.operatetime gxsh_endtime, ");
		//mrcopy 2020/04/14 add
		sb.append("		   task.creationtime gxsh_starttime, ");
		//mrcopy 2020/04/14 add
		sb.append("		   sum(isnull(flow2.statisticaltime, 0)) gxsh_costtime, ");
		sb.append("		   isnull(u.user_name"+suffix+", u.user_name) gxsh_user ");
		sb.append("	  from (select pk_sscuser, pk_sscnode, busiid, operatetime,creationtime  ");
//		sb.append("	  from (select pk_sscuser, pk_sscnode, busiid, operatetime  ");
		sb.append("			  from ssctp_task ");
		sb.append("			 where pk_sscnode = '0001ZG10000000NODE01' ");
		sb.append("			   and busiid in (select billid from "+tableName+") ");
		sb.append("			   and taskstatus = 'sscapprove') task ");
		sb.append("	  left join ssctp_flowpath flow2 ");
		sb.append("	    on flow2.busiid = task.busiid ");
		sb.append("	   and flow2.pk_sscnode = task.pk_sscnode ");
		sb.append("	   and flow2.beginstate in ('taken', 'notake', 'adjust') ");
		sb.append("	  left join sm_user u ");
		sb.append("	    on u.cuserid = task.pk_sscuser ");
		sb.append("	 group by task.busiid, task.operatetime, task.creationtime, isnull(u.user_name"+suffix+", u.user_name) ");
//		sb.append("	 group by task.busiid, task.operatetime, isnull(u.user_name"+suffix+", u.user_name) ");
		
		sql = new StringBuilder();
		if(GetDatabaseUtil.getDatabaseType() == DBConsts.POSTGRESQL ) {
			sql.append("update "+tableName+"  ");
			sql.append(" set "+tableName+".gxsh_endtime = B.gxsh_endtime,");
			sql.append(" "+tableName+".gxsh_costtime = B.gxsh_costtime,");
			sql.append(" "+tableName+".gxsh_user = B.gxsh_user ");
			sql.append("from ("+ sb.toString()+ ") B ");
			sql.append("where ("+tableName+".billid = B.busiid) ");
		}else {
			sql.append(" /*+ gather_plan_statistics */ merge into "+tableName+" A ");
			sql.append(" using (" + sb.toString() +" ) B ");
			sql.append(" on (A.billid = B.busiid ) ");
			sql.append(" when matched then  ");
			sql.append(" update ");
			sql.append(" set A.gxsh_endtime = B.gxsh_endtime,");
			
			
			//mrcopy 2022/04/14 add
			sql.append(" A.gxsh_starttime = B.gxsh_starttime,");
			//mrcopy 2022/04/14 add
			
			sql.append(" A.gxsh_costtime = B.gxsh_costtime,");
			sql.append(" A.gxsh_user = B.gxsh_user ");
			sql.append(SSCReportStatisticUtil.getMergeTail());
		}
		
		new BaseDAO().executeUpdate(sql.toString());
		
		
		StringBuilder sb2 = new StringBuilder();
		sb2.append(" update "+tableName+"  set gxsp_costtime = 'Y' where billid in (select busiid from ssctp_currenttask t where t.busiid = "+tableName+".billid and t.taskstatus = 'sscapprove')  ");
		dao.executeUpdate(sb2.toString());
		
	}
	
	public void queryFirstExamBillsForLink(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName, String starttime, String endtime) throws BusinessException{
		
		StringBuilder sb_starttime = new StringBuilder();
		sb_starttime.append(" select min(operatetime) ssc_starttime, busiid billid ");
		sb_starttime.append(" 	from ssctp_flowpath ");
		sb_starttime.append("  where actiontype = 'busiapprove' ");
		sb_starttime.append(" 	 and pk_currenttask in ");
		sb_starttime.append(" 		 (select pk_currenttask ");
		sb_starttime.append(" 			from ssctp_currenttask ");
		sb_starttime.append(" 		   where pk_sscnode in ");
		sb_starttime.append(" 				 ('0001ZG10000000NODE01', '0001ZG10000000NODE02') ");
		sb_starttime.append("			 and busiid in (select pk_bill from "+reportQueryConditionVO.getTableName()+"  ");
		sb_starttime.append("										  where period = "+period+" ");
		sb_starttime.append(" 										    and iseffectivebill = 1)) ");
		sb_starttime.append(" 	group by busiid; ");
		
		List<Map<String, Object>> ssc_starttime = (List<Map<String, Object>>) dao.executeQuery(sb_starttime.toString(), new MapListProcessor());
		String sql_start = " update "+tableName+" set ssc_starttime = ? where billid = ? ";
		List<SQLParameter> parameterList_start = new ArrayList<SQLParameter>();
		for(Map map : ssc_starttime){
			SQLParameter param = new SQLParameter();
			param.addParam(map.get("ssc_starttime") !=null?map.get("ssc_starttime"):"");
			param.addParam(map.get("billid"));
			parameterList_start.add(param);
		}
		batchUpdate(sql_start, parameterList_start);
		
		if(reportQueryConditionVO.getIsCurrentPeriod().equals("N")){
			period = 0;
		}
		
		StringBuilder sb = new StringBuilder();
		/*sb.append(" select distinct * from ( ");
		sb.append(" select flow1.busiid billid,flow1.operatetime ssc_starttime,flow2.operatetime gxsh_endtime,flow3.gxsh_costtime,u.user_name gxsh_user ");
		sb.append(" from ");
		sb.append(" (select * from ssctp_flowpath where actiontype = '"+ActionType.busiapprove.getValue()+"' and ");
		sb.append(" operatetime in (select max(operatetime) from ssctp_flowpath where actiontype = '"+ActionType.busiapprove.getValue()+"' group by busiid)) flow1 ");
		sb.append(" left join ssctp_flowpath flow2 on flow1.busiid = flow2.busiid and flow2.pk_sscnode = '"+SSCWorkFlowConst.FIRSTPK+"' and flow2.actiontype = '"+ActionType.sscapprove.getValue()+"' ");
		sb.append(" and flow2.operatetime in (select max(operatetime) from ssctp_flowpath where pk_sscnode = '"+SSCWorkFlowConst.FIRSTPK+"' and actiontype = '"+ActionType.sscapprove.getValue()+"' group by busiid) ");
		sb.append(" left join (select sum(statisticaltime) gxsh_costtime,busiid from ssctp_flowpath where pk_sscnode = '"+SSCWorkFlowConst.FIRSTPK+"' and  ");
		sb.append(" actiontype in('sscapprove','handon','adjust','forcefetchback','distribute','forcedistribute','redistribute','take') group by busiid) flow3 on flow1.busiid = flow3.busiid  ");
		sb.append(" left join sm_user u on u.cuserid = flow2.operater ");
		
		sb.append(" ) A ");
		sb.append(" where A.billid in (select pk_bill from "+reportQueryConditionVO.getTableName()+" where period = "+period+" and iseffectivebill = 1)  ");*/
		
		/*sb.append("	select flow1.busiid billid, ");
		sb.append("		   flow1.ssc_starttime, ");
		sb.append("		   flow1.gxsh_endtime, ");
		sb.append("		   sum(isnull(flow2.statisticaltime, 0)) gxsh_costtime, ");
		sb.append("		   isnull(u.user_name"+suffix+",u.user_name) gxsh_user ");
		sb.append("		from (select min(operatetime) ssc_starttime, ");
		sb.append("					 max(operatetime) gxsh_endtime, ");
		sb.append("					 busiid, ");
		sb.append("					 pk_sscnode, ");
		sb.append("					 operater  ");
		sb.append("				from ssctp_flowpath ");
		sb.append("				where pk_sscnode = '0001ZG10000000NODE01' ");
		sb.append("					  and busiid in (select pk_bill ");
		sb.append("					  					from "+reportQueryConditionVO.getTableName()+" ");
		sb.append("											where period = "+period+" ");
		sb.append("												  and iseffectivebill = 1) ");
		sb.append("					 group by busiid,pk_sscnode,operater) flow1 ");
		sb.append("	left join ssctp_flowpath flow2 ");
		sb.append("		on flow2.busiid = flow1.busiid ");
		sb.append("		and flow1.pk_sscnode = flow2.pk_sscnode ");
		sb.append("		and flow2.beginstate in ('taken', 'notake', 'adjust') ");
		sb.append("	left join sm_user u ");
		sb.append("		on u.cuserid = flow1.operater ");
		sb.append("	group by flow1.busiid,flow1.ssc_starttime,flow1.gxsh_endtime,isnull(u.user_name"+suffix+",u.user_name) ");*/
		
		sb.append("	select task.busiid billid, ");
		//sb.append("		   min(flow1.operatetime) ssc_starttime, ");
		sb.append("		   task.operatetime gxsh_endtime, ");
		sb.append("		   sum(isnull(flow2.statisticaltime, 0)) gxsh_costtime, ");
		sb.append("		   isnull(u.user_name"+suffix+", u.user_name) gxsh_user ");
		sb.append("	  from (select pk_sscuser, pk_sscnode, busiid, operatetime ");
		sb.append("			  from ssctp_task ");
		sb.append("			 where pk_sscnode = '0001ZG10000000NODE01' ");
		sb.append("			   and busiid in (select pk_bill from "+reportQueryConditionVO.getTableName()+"  ");
		sb.append("											 where period = "+period+" ");
		sb.append(" 										   and iseffectivebill = 1) ");
		sb.append("			   and taskstatus = 'sscapprove') task ");
		/*sb.append("	  left join ssctp_flowpath flow1 ");
		sb.append("	    on flow1.busiid = task.busiid ");
		sb.append("	   and flow1.pk_sscnode = task.pk_sscnode ");
		sb.append("	   and flow1.actiontype = 'busiapprove' ");*/
		sb.append("	  left join ssctp_flowpath flow2 ");
		sb.append("	    on flow2.busiid = task.busiid ");
		sb.append("	   and flow2.pk_sscnode = task.pk_sscnode ");
		sb.append("	   and flow2.beginstate in ('taken', 'notake', 'adjust') ");
		sb.append("	  left join sm_user u ");
		sb.append("	    on u.cuserid = task.pk_sscuser ");
		sb.append("	 group by task.busiid, task.operatetime, isnull(u.user_name"+suffix+", u.user_name) ");
		
		
		List<Map<String, Object>> gxsh = (List<Map<String, Object>>) dao.executeQuery(sb.toString(), new MapListProcessor());
		String sql = " update "+tableName+" set gxsh_endtime = ?,gxsh_costtime = ?,gxsh_user = ? where billid = ? ";
		List<SQLParameter> parameterList = new ArrayList<SQLParameter>();
		for(Map map : gxsh){
			SQLParameter param = new SQLParameter();
			//param.addParam(map.get("ssc_starttime") !=null?map.get("ssc_starttime"):"");
			param.addParam(map.get("gxsh_endtime") !=null?map.get("gxsh_endtime"):"");
			param.addParam(map.get("gxsh_costtime") !=null?map.get("gxsh_costtime"):"");
			param.addParam(map.get("gxsh_user") !=null?map.get("gxsh_user"):"");
			param.addParam(map.get("billid"));
			parameterList.add(param);
		}
		batchUpdate(sql, parameterList);
		
		StringBuilder sb2 = new StringBuilder();
		sb2.append(" update "+tableName+"  set gxsp_costtime = 'Y' where billid in (select busiid from ssctp_currenttask t where t.busiid = "+tableName+".billid and t.taskstatus = 'sscapprove')  ");
		dao.executeUpdate(sb2.toString());
		
	}
	
	public void queryReExamBills(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName, String starttime, String endtime) throws BusinessException{
		
		StringBuilder sb = new StringBuilder();
		sb.append("	select task.busiid, ");
		sb.append("		   task.operatetime gxfh_endtime, ");
		sb.append("		   sum(isnull(flow2.statisticaltime, 0)) gxfh_costtime, ");
		sb.append("		   isnull(u.user_name"+suffix+", u.user_name) gxfh_user ");
		sb.append("	  from (select pk_sscuser, pk_sscnode, busiid, operatetime ");
		sb.append("			  from ssctp_task ");
		sb.append("			 where pk_sscnode = '0001ZG10000000NODE02' ");
		sb.append("			   and busiid in (select billid from "+tableName+") ");
		sb.append("			   and taskstatus = 'sscapprove') task ");
		sb.append("	  left join ssctp_flowpath flow2 ");
		sb.append("	    on flow2.busiid = task.busiid ");
		sb.append("	   and flow2.pk_sscnode = task.pk_sscnode ");
		sb.append("	   and flow2.beginstate in ('taken', 'notake', 'adjust') ");
		sb.append("	  left join sm_user u ");
		sb.append("	    on u.cuserid = task.pk_sscuser ");
		sb.append("	 group by task.busiid, task.operatetime, isnull(u.user_name"+suffix+", u.user_name) ");
		
		StringBuilder sql = new StringBuilder();
		if(GetDatabaseUtil.getDatabaseType() == DBConsts.POSTGRESQL ) {
			sql.append("update "+tableName+"  ");
			sql.append(" set "+tableName+".gxfh_endtime = B.gxfh_endtime,");
			sql.append(" "+tableName+".gxfh_costtime = B.gxfh_costtime,");
			sql.append(" "+tableName+".gxfh_user = B.gxfh_user ");
			sql.append("from ("+ sb.toString()+ ") B ");
			sql.append("where ("+tableName+".billid = B.busiid) ");
		}else {
			sql.append(" merge into "+tableName+" A ");
			sql.append(" using (" + sb.toString() +" ) B ");
			sql.append(" on (A.billid = B.busiid ) ");
			sql.append(" when matched then  ");
			sql.append(" update ");
			sql.append(" set A.gxfh_endtime = B.gxfh_endtime,");
			sql.append(" A.gxfh_costtime = B.gxfh_costtime,");
			sql.append(" A.gxfh_user = B.gxfh_user ");
			sql.append(SSCReportStatisticUtil.getMergeTail());
		}
		
		new BaseDAO().executeUpdate(sql.toString());
		
		StringBuilder sb2 = new StringBuilder();
		sb2.append(" update "+tableName+"  set gxsp_costtime = 'Y' where billid in (select busiid from ssctp_currenttask t where t.busiid = "+tableName+".billid and t.taskstatus = 'sscapprove')  ");
		dao.executeUpdate(sb2.toString());
		
	}
	
	public void queryReExamBillsForLink(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName, String starttime, String endtime) throws BusinessException{
		
		if(reportQueryConditionVO.getIsCurrentPeriod().equals("N")){
			period = 0;
		}
		
		StringBuilder sb = new StringBuilder();
		/*sb.append(" select distinct * from ( ");
		sb.append(" select operatetime gxfh_endtime,gxfh_costtime,u.user_name gxfh_user,flow1.busiid billid ");
		sb.append(" from ");
		sb.append(" (select operatetime,operater,busiid from ssctp_flowpath  where pk_sscnode = '"+SSCWorkFlowConst.REPK+"' and actiontype = '"+ActionType.sscapprove.getValue()+"' ");
		sb.append(" and operatetime in (select max(operatetime) from ssctp_flowpath where pk_sscnode = '"+SSCWorkFlowConst.REPK+"' and actiontype = '"+ActionType.sscapprove.getValue()+"' group by busiid) ) flow1 ");
		sb.append(" left join (select sum(statisticaltime) gxfh_costtime,busiid from ssctp_flowpath where pk_sscnode = '"+SSCWorkFlowConst.REPK+"' and ");
		sb.append(" actiontype in('sscapprove','handon','adjust','forcefetchback','distribute','forcedistribute','redistribute','take') group by busiid) flow2 on flow1.busiid = flow2.busiid  ");
		sb.append(" left join sm_user u on u.cuserid = flow1.operater ");
		
		sb.append(" ) A ");
		sb.append(" where A.billid in (select pk_bill from "+reportQueryConditionVO.getTableName()+" where period = "+period+" and iseffectivebill = 1)  ");*/
		
		/*sb.append("	select flow1.busiid billid, ");
		sb.append("		   flow1.gxfh_endtime, ");
		sb.append("		   sum(isnull(flow2.statisticaltime, 0)) gxfh_costtime, ");
		sb.append("		   isnull(u.user_name"+suffix+",u.user_name) gxfh_user ");
		sb.append("		from (select  ");
		sb.append("					 max(operatetime) gxfh_endtime, ");
		sb.append("					 busiid, ");
		sb.append("					 pk_sscnode, ");
		sb.append("					 operater  ");
		sb.append("				from ssctp_flowpath ");
		sb.append("				where pk_sscnode = '0001ZG10000000NODE02' ");
		sb.append("					  and busiid in (select pk_bill ");
		sb.append("					  					from "+reportQueryConditionVO.getTableName()+" ");
		sb.append("											where period = "+period+" ");
		sb.append("												  and iseffectivebill = 1) ");
		sb.append("					 group by busiid,pk_sscnode,operater) flow1 ");
		sb.append("	left join ssctp_flowpath flow2 ");
		sb.append("		on flow2.busiid = flow1.busiid ");
		sb.append("		and flow1.pk_sscnode = flow2.pk_sscnode ");
		sb.append("		and flow2.beginstate in ('taken', 'notake', 'adjust') ");
		sb.append("	left join sm_user u ");
		sb.append("		on u.cuserid = flow1.operater ");
		sb.append("	group by flow1.busiid,flow1.gxfh_endtime,isnull(u.user_name"+suffix+",u.user_name) ");*/
		
		sb.append("	select task.busiid billid, ");
		sb.append("		   task.operatetime gxfh_endtime, ");
		sb.append("		   sum(isnull(flow.statisticaltime, 0)) gxfh_costtime, ");
		sb.append("		   isnull(u.user_name"+suffix+", u.user_name) gxfh_user ");
		sb.append("	  from (select pk_sscuser, pk_sscnode, busiid, operatetime ");
		sb.append("			  from ssctp_task ");
		sb.append("			 where pk_sscnode = '0001ZG10000000NODE02' ");
		sb.append("			   and busiid in (select pk_bill from "+reportQueryConditionVO.getTableName()+"  ");
		sb.append("											 where period = "+period+" ");
		sb.append(" 										   and iseffectivebill = 1) ");
		sb.append("			   and taskstatus = 'sscapprove') task ");
		sb.append("	  left join ssctp_flowpath flow ");
		sb.append("	    on flow.busiid = task.busiid ");
		sb.append("	   and flow.pk_sscnode = task.pk_sscnode ");
		sb.append("	   and flow.beginstate in ('taken', 'notake', 'adjust') ");
		sb.append("	  left join sm_user u ");
		sb.append("	    on u.cuserid = task.pk_sscuser ");
		sb.append("	 group by task.busiid, task.operatetime, isnull(u.user_name"+suffix+", u.user_name) ");
		
		
		List<Map<String, Object>> gxfh = (List<Map<String, Object>>) dao.executeQuery(sb.toString(), new MapListProcessor());
		String sql = " update "+tableName+" set gxfh_endtime = ?,gxfh_costtime = ?,gxfh_user = ? where billid = ? ";
		List<SQLParameter> parameterList = new ArrayList<SQLParameter>();
		for(Map map : gxfh){
			SQLParameter param = new SQLParameter();
			param.addParam(map.get("gxfh_endtime") !=null?map.get("gxfh_endtime"):"");
			param.addParam(map.get("gxfh_costtime") !=null?map.get("gxfh_costtime"):"");
			param.addParam(map.get("gxfh_user") !=null?map.get("gxfh_user"):"");
			param.addParam(map.get("billid"));
			parameterList.add(param);
		}
		batchUpdate(sql, parameterList);
		StringBuilder sb2 = new StringBuilder();
		sb2.append(" update "+tableName+"  set gxsp_costtime = 'Y' where billid in (select busiid from ssctp_currenttask t where t.busiid = "+tableName+".billid and t.taskstatus = 'sscapprove')  ");
		dao.executeUpdate(sb2.toString());
		
	}
	
	/**
	 * 明细直接查询
	 * @param reportQueryConditionVO
	 * @param tableName
	 * @throws BusinessException
	 */
	public void querySignAndSettleBills(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName) throws BusinessException{
		SSCReportStatisticUtil.getInstance();
		String cmpTempTableName = SSCReportStatisticUtil.getInstance().getSSCPfaReportCmpTable();
		String[] cmpTempTableFields = SSCReportStatisticUtil.SSCPFA_REPORT_CMP_FIELDS;
		reportQueryConditionVO.setCmp_tableName(cmpTempTableName);
		
		String whereSql = "select billid from "+ tableName;
		
		ISCCGroupAndModuleCheck groupAndModuleCheck = NCLocator.getInstance().lookup(ISCCGroupAndModuleCheck.class);
		if(groupAndModuleCheck.isProductModuleInstalled(ISCCGroupAndModuleCheck.CMP_PRODUCT_CODE)) {
			ISettlementQueryForSscService settlementQueryService = NCLocator.getInstance().lookup(ISettlementQueryForSscService.class);
			settlementQueryService.queryBusiBillSettlementInfo(null, null, null, null, 
					whereSql, cmpTempTableName, cmpTempTableFields, period);
		}
		
		StringBuilder sb = new StringBuilder();
		if(GetDatabaseUtil.getDatabaseType() == DBConsts.POSTGRESQL ) {
			sb.append("update "+tableName+"  ");
			sb.append(" set "+tableName+".qz_endtime = B.signdate,");
			sb.append(" "+tableName+".qz_user = B.signer,");
			sb.append(" "+tableName+".qz_costtime = B.signtime, "+tableName+".js_endtime = B.settledate, "+tableName+".js_user = B.settler,");
			sb.append(" "+tableName+".js_costtime = B.settletime,");
			sb.append(" "+tableName+".busi_auditdate = B.busi_auditdate ");
			sb.append("from ("+ getSignSettleInfo(reportQueryConditionVO)+ ") B ");
			sb.append("where ("+tableName+".billid = B.pk_bill)");
		}else {
			sb.append(" merge into "+tableName+" A ");
			sb.append(" using (" + getSignSettleInfo(reportQueryConditionVO) +" ) B ");
			sb.append(" on (A.billid = B.pk_bill ) ");
			sb.append(" when matched then  ");
			sb.append(" update ");
			sb.append(" set A.qz_endtime = B.signdate,");
			sb.append(" A.qz_user = B.signer,");
			sb.append(" A.qz_costtime = B.signtime, A.js_endtime = B.settledate, A.js_user = B.settler,");
			sb.append(" A.js_costtime = B.settletime,");
			sb.append(" A.busi_auditdate = B.busi_auditdate ");
			sb.append(" ,A.flow_cancelledtime = B.flow_cancelledtime ");
			
			sb.append(SSCReportStatisticUtil.getMergeTail());
		}
			
		dao.executeUpdate(sb.toString());
		
	}
	
	/**
	 * 汇总表联查
	 * @param reportQueryConditionVO
	 * @param tableName
	 * @throws BusinessException
	 */
	public void querySignAndSettleBillsForLink(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName) throws BusinessException{
		
		if(reportQueryConditionVO.getIsCurrentPeriod().equals("N")){
			period = 0;
		}
		StringBuilder sb = new StringBuilder();
		if(GetDatabaseUtil.getDatabaseType() == DBConsts.POSTGRESQL ) {
			sb.append(" update "+tableName+" A ");
			sb.append(" set A.qz_endtime = B.signdate,");
			sb.append(" A.qz_user = B.signer,");
			sb.append(" A.qz_costtime = B.signtime, A.js_endtime = B.settledate, A.js_user = B.settler,");
			sb.append(" A.js_costtime = B.settletime,");
			sb.append(" A.busi_auditdate = B.busi_auditdate ");
			//mrcopy 2022/04/16 add
			sb.append(" ,A.flow_cancelledtime = B.flow_cancelledtime ");
			//mrcopy 2022/04/16 add
			sb.append("from ("+ getSignSettleInfo(reportQueryConditionVO)+ ") B ");
			sb.append("where ( A.billid = B.pk_bill and B.period = " + period + ")");
		}else{
			sb.append(" merge into "+tableName+" A ");
			sb.append(" using (" + getSignSettleInfoForLink(reportQueryConditionVO) +" ) B ");
			sb.append(" on (A.billid = B.pk_bill and B.period = " + period + ") ");
			sb.append(" when matched then  ");
			sb.append(" update ");
			sb.append(" set A.qz_endtime = B.signdate, ");
			sb.append(" 	A.qz_user = B.signer, ");
			sb.append(" 	A.qz_costtime = B.signtime, ");
			sb.append("		A.js_endtime = B.settledate, ");
			sb.append("		A.js_user = B.settler, ");
			sb.append(" 	A.js_costtime = B.settletime, ");
			sb.append(" 	A.busi_auditdate = B.busi_auditdate ");
			sb.append(SSCReportStatisticUtil.getMergeTail());
		}
		dao.executeUpdate(sb.toString());
		
	}
	
	/**
	 * 获取签字结算信息，计算签字和结算总耗时，用于明细直接查
	 * 
	 * @param reportQueryConditionVO
	 * @throws BusinessException
	 */
	private String getSignSettleInfo(ReportQueryConditionVO reportQueryConditionVO) throws BusinessException {
		//不包含自动签字
		boolean includeAutoSign = reportQueryConditionVO.getIncludeAutoSign() != null && reportQueryConditionVO.getIncludeAutoSign().booleanValue();
		//不包含自动结算
		boolean includeAutoSettle = reportQueryConditionVO.getIncludeAutoSettle() != null && reportQueryConditionVO.getIncludeAutoSettle().booleanValue();
		
		StringBuilder sb = new StringBuilder("select cmp.*, ");
		sb.append("case when cmp.isautosign = 'N' and flow1.cancelledtime is not null then cmp.signT + flow1.cancelledtime else cmp.signT end signtime, ");
		sb.append("case when cmp.isautosign = 'Y' and flow1.cancelledtime is not null then cmp.settleT + flow1.cancelledtime else cmp.settleT end settletime ");
		sb.append(", flow1.cancelledtime  flow_cancelledtime ");
		sb.append("from (select a.*,");
		sb.append(TimestampUtils.getHourSql("a.signdate", "a.busi_auditdate") + " signT,");
		sb.append(TimestampUtils.getHourSql("a.settledate", "a.signdate") + " settleT ");
		sb.append(" from "+ reportQueryConditionVO.getCmp_tableName() +" a where 1=1 ");
		//不包含自动签字
		if (!includeAutoSign) {
			sb.append("and isautosign = 'N'");
		}
		
		//不包含自动结算
		if (!includeAutoSettle) {
			sb.append(" and" + handSettleSql());
		}
		sb.append(") cmp ");
		
		sb.append("left join(select curtask.busiid pk_bill, isnull(sum(flow.statisticaltime),0) cancelledtime ");
		sb.append("from "+ reportQueryConditionVO.getCmp_tableName() +" report ");
		sb.append("left join ssctp_currenttask curtask on curtask.busiid=report.pk_bill ");
		sb.append("left join ssctp_flowpath flow on curtask.busiid = flow.busiid and curtask.pk_sscnode = flow.pk_sscnode and flow.actiontype = 'un-sscapprove' ");
		sb.append("where 1=1 ");
		sb.append("group by curtask.busiid) flow1 on cmp.pk_bill=flow1.pk_bill ");
		return sb.toString();
	}
	
	
	
	
	
	
	/**
	 * 获取签字结算信息，计算签字和结算总耗时，用于联查
	 * 
	 * @param reportQueryConditionVO
	 * @throws BusinessException
	 */
	private String getSignSettleInfoForLink(ReportQueryConditionVO reportQueryConditionVO) throws BusinessException {
		String reportType = reportQueryConditionVO.getReportType();
		boolean sign = ReportQueryConditionVO.REPORTTYPE_SIGN.equals(reportType);
		boolean settle = ReportQueryConditionVO.REPORTTYPE_SETTLE.equals(reportType);
		boolean payment = ReportQueryConditionVO.REPORTTYPE_PAYMENT.equals(reportType);
		//不包含自动签字
		boolean includeAutoSign = reportQueryConditionVO.getIncludeAutoSign() != null && reportQueryConditionVO.getIncludeAutoSign().booleanValue();
		//不包含自动结算
		boolean includeAutoSettle = reportQueryConditionVO.getIncludeAutoSettle() != null && reportQueryConditionVO.getIncludeAutoSettle().booleanValue();
		
		StringBuilder sb = new StringBuilder("select cmp.*, ");
		sb.append("case when cmp.isautosign = 'N' and flow1.cancelledtime is not null then cmp.signT + flow1.cancelledtime else cmp.signT end signtime, ");
		sb.append("case when cmp.isautosign = 'Y' and flow1.cancelledtime is not null then cmp.settleT + flow1.cancelledtime else cmp.settleT end settletime ");
		sb.append("from (select a.*,");
		sb.append(TimestampUtils.getHourSql("a.signdate", "a.busi_auditdate") + " signT,");
		sb.append(TimestampUtils.getHourSql("a.settledate", "a.signdate") + " settleT ");
		sb.append(" from "+ reportQueryConditionVO.getCmp_tableName() +" a where 1=1 ");
		//自动签字
		if ((sign || payment) && !includeAutoSign) {
			sb.append("and isautosign = 'N'");
		}
		
		//自动结算
		if ((settle || payment) && !includeAutoSettle) {
			sb.append("and" + handSettleSql());
		}
		sb.append(") cmp ");
		
		sb.append("left join(select curtask.busiid pk_bill,report.period, isnull(sum(flow.statisticaltime),0) cancelledtime ");
		sb.append("from "+ reportQueryConditionVO.getCmp_tableName() +" report ");
		sb.append("left join ssctp_currenttask curtask on curtask.busiid=report.pk_bill ");
		sb.append("left join ssctp_flowpath flow on curtask.busiid = flow.busiid and curtask.pk_sscnode = flow.pk_sscnode and flow.actiontype = 'un-sscapprove' ");
		sb.append("group by curtask.busiid,report.period) flow1 on cmp.pk_bill=flow1.pk_bill and cmp.period = flow1.period  ");
		return sb.toString();
	}
	
	/**
	 * 手动结算判断：结算时间大于签字时间即为手动结算
	 * @return
	 */
	private String handSettleSql(){
		StringBuilder sql = new StringBuilder(" To_date( settledate, 'yyyy-mm-dd hh24:mi:ss') > ");
		sql.append("To_date(signdate, 'yyyy-mm-dd hh24:mi:ss') ");
		if(GetDatabaseUtil.getDatabaseType() == DBConsts.SQLSERVER){
			sql = new StringBuilder(" CONVERT(varchar(100),settledate) > ");
			sql.append("CONVERT(varchar(100),signdate) ");
		}
		return sql.toString();
	}
	
	
	public void queryALLFLOWBills(ReportQueryConditionVO reportQueryConditionVO, 
			String tableName, String starttime, String endtime) throws BusinessException{
		
		String flowpathsql = getFlowPathSql(reportQueryConditionVO,starttime,endtime);
		
		StringBuilder sb = new StringBuilder("insert into " + tableName + " ( ");
		
		sb.append(" select f1.busiid billid ,f1.billno,f1.pk_org,o.name pk_org_name,f1.pk_group,f1.pk_tradetype,b1.pk_billtypecode tradetypecode , b.billtypename tradetypename, ");
		sb.append(" f3.operatetime committime, f4.operatetime, f5.operatetime, count(f4.statisticaltime) ");
		sb.append(" from ");
		sb.append(" (select *,ROW_NUMBER() OVER (ORDER BY operatetime desc) as rownum_   ");
		sb.append(" from ssctp_flowpath where "+flowpathsql+" and aciontype = '"+ActionType.beforeImage.getValue()+"' and rownum_ <= 1 ) f1");
		sb.append(" left join (select busiid, sum(statisticaltime) zgsm_costtime ");
		sb.append(" from ssctp_flowpath where "+flowpathsql+" and actiontype = '"+ActionType.afterImage.getValue()+"' group by busiid) f2 ");
		sb.append(" on f1.busiid = f2.busiid ");
		sb.append(" left join (select busiid, operatetime zgsm_endtime, operator zgsm_user,ROW_NUMBER() OVER (ORDER BY operatetime desc) as rownum_ ");
		sb.append(" from ssctp_flowpath where "+flowpathsql+" and actiontype = '"+ActionType.afterImage.getValue()+"' and rownum_ <= 1 group by busiid) f3 ");
		sb.append(" on f1.busiid = f3.busiid ");
		
		sb.append(" left join (select busiid, operatetime ssc_starttime, ROW_NUMBER() OVER (ORDER BY operatetime desc) as rownum_");
		sb.append(" from ssctp_flowpath where "+flowpathsql+" and actiontype = '"+ActionType.busiapprove.getValue()+"' and pk_sscnode = '"+SSCWorkFlowConst.FIRSTPK+"' and rownum_ <= 1 group by busiid) f4 ");
		sb.append(" on f1.busiid = f4.busiid ");
		sb.append(" left join (select busiid, sum(statisticaltime) gxsh_costtime ");
		sb.append(" from ssctp_flowpath where "+flowpathsql+" and actiontype in ('sscapprove','handon','adjust','forcefetchback') and pk_sscnode = '"+SSCWorkFlowConst.FIRSTPK+"' group by busiid) f5 ");
		sb.append(" on f1.busiid = f5.busiid ");
		sb.append(" left join (select busiid, operatetime gxsh_endtime, operator gxsh_user,ROW_NUMBER() OVER (ORDER BY operatetime desc) as rownum_ ");
		sb.append(" from ssctp_flowpath where "+flowpathsql+" and actiontype in ('sscapprove','handon','adjust','forcefetchback','take') and pk_sscnode = '"+SSCWorkFlowConst.FIRSTPK+"' and rownum_ <= 1 group by busiid) f6 ");
		sb.append(" on f1.busiid = f6.busiid ");
		
		sb.append(" left join (select busiid, sum(statisticaltime) gxfh_costtime ");
		sb.append(" from ssctp_flowpath where "+flowpathsql+" and actiontype in ('sscapprove','handon','adjust','forcefetchback','take') and pk_sscnode = '"+SSCWorkFlowConst.REPK+"' group by busiid) f5 ");
		sb.append(" on f1.busiid = f5.busiid ");
		sb.append(" left join (select busiid, operatetime gxfh_endtime, operator gxfh_user,ROW_NUMBER() OVER (ORDER BY operatetime desc) as rownum_ ");
		sb.append(" from ssctp_flowpath where "+flowpathsql+" and actiontype = '"+ActionType.sscapprove.getValue()+"' and pk_sscnode = '"+SSCWorkFlowConst.REPK+"' and rownum_ <= 1 group by busiid) f6 ");
		sb.append(" on f1.busiid = f6.busiid ");
		
		sb.append(" left join (select busiid, sum(statisticaltime) gxsp_costtime ");
		sb.append(" from ssctp_flowpath where "+flowpathsql+"  and pk_sscnode in ('"+SSCWorkFlowConst.FIRSTPK+"','"+SSCWorkFlowConst.REPK+"')  ");
		sb.append(" and beginstate = '"+TaskStatus.taken.getValue()+"' and actiontype in ('sscapprove','handon','adjust','forcefetchback','take') group by busiid) f7");
		sb.append(" on f1.busiid = f7.busiid ");
		
		sb.append(" left join (select busiid, sum(statisticaltime) bdlc_costtime ");
		sb.append(" from ssctp_flowpath where "+flowpathsql+"  and pk_sscnode in ('"+SSCWorkFlowConst.MakeBillPK+"','"+SSCWorkFlowConst.AccountPK+"','"+SSCWorkFlowConst.ImagePK+"')  ");
		sb.append(" and actiontype in ('makebill','afterImage','afterAccount') group by busiid) f8");
		sb.append(" on f1.busiid = f8.busiid ");
		
		sb.append("left join bd_billtype b on f1.pk_tradetype = b.pk_billtypeid ");
		
		sb.append("c");
		
		sb.append(" )");
		
		new BaseDAO().executeUpdate(sb.toString());
	}
	
	private String getFlowPathSql(ReportQueryConditionVO reportQueryConditionVO, String starttime, String endtime){
		String pk_sscunit = reportQueryConditionVO.getPk_sscunit();
		String pk_org = reportQueryConditionVO.getPk_org();
//		String pk_dept = reportQueryConditionVO.getPk_dept();//暂时没用
//		String pk_busiunit = reportQueryConditionVO.getPk_busiunit();//暂时没用
		String pk_transtype = reportQueryConditionVO.getPk_transtype();//多选，逗号隔开
		
		StringBuilder sb = new StringBuilder(" 1 = 1 ");
		//sb.append(" and billno in (select billno from ssctp_flowpath where pk_sscunit = '"+ pk_sscunit + "') ");
		/*if(StringUtils.isNotEmpty(pk_org)){
			sb.append(" and pk_org in ");
			String [] pk_orgs = pk_org.split(",");
			sb.append(getIn(pk_orgs));
		}
		if(StringUtils.isNotEmpty(pk_transtype)){
			sb.append(" and pk_tradetype in ");
			String[] pk_transtypes = pk_transtype.split(",");
			sb.append(getIn(pk_transtypes));
		}*/
		try {
			if(StringUtils.isNotEmpty(pk_org)){
				sb.append(" and ");
				sb.append(SqlUtils.getInStr("pk_org", pk_org.split(","),true));
			}
			if(StringUtils.isNotEmpty(pk_transtype)){
				//sb.append(" and pk_tradetype in ");
				//String[] pk_transtypes = pk_transtype.split(",");
				//sb.append(getIn(pk_transtypes));
				sb.append(" and ");
				sb.append(SqlUtils.getInStr("pk_tradetype", pk_transtype.split(","),true));
			}
		} catch (BusinessException e) {
			Logger.error(e.getMessage(),e);
		}
		/*sb.append("and to_date(operatetime, 'yyyy-mm-dd hh24:mi:ss') ");
		sb.append("between to_date('" + starttime + "','yyyy-mm-dd hh24:mi:ss') ");
		sb.append("and to_date('" + endtime + "','yyyy-mm-dd hh24:mi:ss')");*/
		if(reportQueryConditionVO.getIncludeAutoApprove()==null || (reportQueryConditionVO.getIncludeAutoApprove()!=null&&!reportQueryConditionVO.getIncludeAutoApprove().booleanValue())){
			sb.append(" and pk_currenttask in (select pk_currenttask from ssctp_currenttask c where (c.isautoapprove is null or c.isautoapprove = 'N' ) and c.pk_sscunit = '"+ pk_sscunit + "' ");
			sb.append(" and c.pk_sscnode in ('0001ZG10000000NODE01','0001ZG10000000NODE02') and c.pk_currenttask = t.pk_currenttask) ");
		}
		return sb.toString();
	}
	
	private String getIn(String[] values){
		StringBuilder sb = new StringBuilder("( ");
		for(int i = 0; i < values.length; i++){
			if(i == values.length-1){
				sb.append("'" + values[i] + "')");
			} else {
				sb.append("'" + values[i] + "',");
			}
		}
		return sb.toString();
	}
	
	private int batchUpdate(String sql, List<SQLParameter> parameterList) throws BusinessException {
        PersistenceManager manager = null;
        int value;
        try {
            manager = PersistenceManager.getInstance();
            manager.setMaxRows(100000);
//            manager.setAddTimeStamp(true);
            JdbcSession session = manager.getJdbcSession();
            if(parameterList !=null && parameterList.size() > 0){
            	session.addBatch(sql, parameterList.toArray(new SQLParameter[parameterList.size()]));
            }
            value = session.executeBatch();
        } catch (DbException e) {
            Logger.error(e.getMessage(), e);
            throw new DAOException(e.getMessage());
        } finally {
            if (manager != null)
                manager.release();
        }
        return value;
    }


}

/*HSxxRIFQ+8j1Z0CxDy9Wh8q2/m1lLemdbyabwEn07iAs031dRalbxGC7uHn1bRpmhRA2hxP9v7uM
GfRxh0n51w==*/
