package nc.bs.pub.workflownote;

import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.framework.common.ITimeService;
import nc.bs.framework.common.InvocationInfo;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Logger;
import nc.bs.pf.pub.PfDataCache;
import nc.bs.pub.pf.PfMailAndSMSUtil;
import nc.bs.pub.pf.PfMessageUtil;
import nc.bs.pub.pf.tx.TxCompletionChecker;
import nc.bs.pub.taskmanager.workitem.PushableMsgErmDistributor;
import nc.bs.wfengine.engine.EngineService;
import nc.bs.wfengine.engine.ext.TaskTopicResolver;
import nc.itf.uap.rbac.IUserManageQuery;
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.BaseProcessor;
import nc.jdbc.framework.processor.BeanListProcessor;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.message.util.IDefaultMsgConst;
import nc.message.vo.NCMessage;
import nc.ui.pf.multilang.PfMultiLangUtil;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.ml.MultiLangUtil;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.pf.change.PfUtilBaseTools;
import nc.vo.pf.msg.MessageMetaType;
import nc.vo.pf.msg.MessageMetaVO;
import nc.vo.pf.pub.IDapType;
import nc.vo.pf.pub.util.UserUtil;
import nc.vo.pf.term.ApproveTermConfig;
import nc.vo.pf.term.IApproveTerm;
import nc.vo.pub.BusinessException;
import nc.vo.pub.billtype.BilltypeVO;
import nc.vo.pub.compiler.PfParameterVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pub.mobile.MobileMsg;
import nc.vo.pub.msg.AbstractMsgL10NCallback;
import nc.vo.pub.msg.CommonMessageVO;
import nc.vo.pub.msg.EmailMsg;
import nc.vo.pub.msg.IMsgL10NCallback;
import nc.vo.pub.msg.UserNameObject;
import nc.vo.pub.pfworkflow.IWorkFlowConst;
import nc.vo.pub.workflownote.WorkflownoteVO;
import nc.vo.sm.UserVO;
import nc.vo.trade.sqlutil.IInSqlBatchCallBack;
import nc.vo.trade.sqlutil.InSqlBatchCaller;
import nc.vo.uap.pf.PFRuntimeException;
import nc.vo.wfengine.core.workflow.BasicWorkflowProcess;
import nc.vo.wfengine.core.workflow.MailModal;
import nc.vo.wfengine.core.workflow.MobileModal;
import nc.vo.wfengine.core.workflow.WorkflowProcess;
import nc.vo.wfengine.definition.WorkflowTypeEnum;
import nc.vo.wfengine.pub.WFTask;
import nc.vo.wfengine.pub.WfTaskOrInstanceStatus;
import nc.vo.wfengine.pub.WfTaskType;
import nc.vo.wfengine.pub.WorkitemMsgContext;
import nccloud.impl.platform.common.util.StringUtils;

/**
 * 审批任务项的管理类 <li>从WorkflownoteBO重构而来,要尽量减少BO类的数量
 * 
 * @author 雷军 created on 2005-3-31
 */
public class WorknoteManager {

	public WorknoteManager() {
		super();
	}
	
	/**
	 * 根据Task创建一个制单默认工作项
	 * 
	 * @param task
	 * @return 制单环节提交人PK
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public static WorkflownoteVO createBillMakerNoteVO(WFTask task) throws BusinessException {
		if(task == null || task.getTaskPK()==null){
			return null;
		}
		String suffix = MultiLangUtil.getCurrentLangSeqSuffix();
		String mlFiledName = "user_name" + suffix;
//		String sql = "select billcommiter as checkman, a.startts as senddate,a.startts as dealdate, b."+mlFiledName+" as checknameml "
//				+" from pub_wf_instance a,sm_user b "
//				+" where a.billcommiter = b.cuserid and (pk_wf_instance in(select pk_wf_instance from pub_wf_task  where pk_wf_task =?))";
		BaseDAO dao = new BaseDAO();
//		SQLParameter paras = new SQLParameter();
//		paras.addParam(task.getTaskPK());
		List<WorkflownoteVO> noteList  = null;
		//noteList = (List<WorkflownoteVO>) dao.executeQuery(sql, paras, new BeanListProcessor(WorkflownoteVO.class));
		//兼容升级前的数据处理
		//if(noteList ==null || noteList.size() ==0){	
			//61-63-65 升级后没走完的审批流审批报错问题，主要是以前版本billcommiter字段为null引起的
			String wfProcessInstancePK= task.getWfProcessInstancePK();
			String str = "select billmaker as checkman, a.startts as senddate,a.startts as dealdate, b."+mlFiledName+" as checknameml "
					+" from pub_wf_instance a,sm_user b "
					+" where a.billmaker = b.cuserid and pk_wf_instance =?";
			SQLParameter par = new SQLParameter();
			par.addParam(wfProcessInstancePK);
			noteList = (List<WorkflownoteVO>) dao.executeQuery(str, par, new BeanListProcessor(WorkflownoteVO.class));
		//}	
		WorkflownoteVO noteVO = noteList.get(0);
		fillOtherNoteProp(noteVO,task);
		return noteVO;
	}

	private static void fillOtherNoteProp(WorkflownoteVO worknote,WFTask task) {
		String checkman = worknote.getCheckman();
		worknote.setApproveresult(UFBoolean.TRUE.toString());
		worknote.setBillid(task.getBillID());
		worknote.setBillVersionPK(task.getBillversionPK());
		worknote.setBillno(task.getBillNO());
		worknote.setCheckname(worknote.getChecknameml());
		worknote.setChecknote(ApproveTermConfig.getInstance().getText(IApproveTerm.PASS));
		worknote.setPk_billtype(task.getBillType());
		
		worknote.setPk_group(InvocationInfoProxy.getInstance().getGroupId());
		worknote.setPk_org(task.getPk_org());
		worknote.setSenderman(checkman);
		worknote.setIscheck("Y");
		worknote.setPk_wf_task(task.getTaskPK());
		worknote.setApprovestatus(WfTaskOrInstanceStatus.Finished.getIntValue());

		WorkitemMsgContext msgContext = new WorkitemMsgContext();
		msgContext.setSender(worknote.getSenderman());
		msgContext.setBillno(worknote.getBillno());
		msgContext.setBillType(worknote.getPk_billtype());
		msgContext.setBillid(worknote.getBillid());
		msgContext.setResult(worknote.getApproveresult());
		msgContext.setActionType(worknote.getActiontype());
		msgContext.setCheckNote(worknote.getChecknote());
		
		NCMessage ncmsg = TaskTopicResolver.constructNCMsg(msgContext);
		String messageNote = ncmsg.getMessage().getSubject();

		worknote.setMessagenote(messageNote);
		worknote.setWorkflow_type(Integer.valueOf(WorkflowTypeEnum.Approveflow.getIntValue()));
		worknote.setActiontype(WorkflownoteVO.WORKITEM_TYPE_APPROVE);
		worknote.setIsmsgbind("N");
	}

	/**
	 * 拼接工作项的工作流类型属性条件 <li>工作流中由于可以嵌入审批子流程，所以需要查询审批子流程 <li>
	 * 
	 * @param iWfType
	 *            主流程类型，见<code>WorkflowTypeEnum.Approveflow</code>和
	 *            <code>WorkflowTypeEnum.Workflow</code>
	 * @return
	 */
	private String getWorkflowTypeAndWhere(int iWfType) {

		String strWfTypeSql = " and workflow_type in"
				+ WorkflowTypeEnum.getInstanceTypeInSql(iWfType);

		return strWfTypeSql;
	}

	/**
	 * 根据单据Id查询相关的工作项VO <li>获取所有 或已经处理过的
	 * 
	 * @modifier zhouzhenga 需查出消息节点产生的工作项
	 * 
	 * @param billId
	 *            单据ID
	 * @param billType
	 *            单据类型PK
	 * @param iStatus
	 *            0-获取所有；1-获取已处理的 kejl修改 2获取的是未完成的
	 * @param iWorkflowOrApproveflow
	 *            主流程类型，见<code>WorkflowTypeEnum.Approveflow</code>和
	 *            <code>WorkflowTypeEnum.Workflow</code>
	 * @throws DbException
	 */
	public WorkflownoteVO[] queryAllByBillId(String billId, String billType,
			int iStatus, int iWorkflowOrApproveflow) throws DbException {

		String suffix = MultiLangUtil.getCurrentLangSeqSuffix();
		String mlFiledName = "user_name" + suffix;
		String sql = "select pk_checkflow,pk_wf_task,pk_billtype,billno,actiontype,senderman,"
				+ "checkman,ischeck,checknote,senddate,dealdate,messagenote,receivedeleteflag,observer,c.ts,"
				+ "c.pk_org,billid,billversionpk,a.user_name as sendername,a."
				+ mlFiledName
				+ " as sendernameml,b.user_name as checkname,b."
				+ mlFiledName
				+ " as checknameml,"
				+ "approvestatus,approveresult,c.pk_group,c.workflow_type from pub_workflownote c,sm_user a,sm_user b "
				+ "where c.senderman=a.cuserid and c.checkman=b.cuserid and c.approvestatus !=5 "//去掉补偿弃审
				+ "and (billversionpk=? or billid =? ) and actiontype<>'"
				+ WorkflownoteVO.WORKITEM_TYPE_BIZ
				+ "' "
				// + "and actiontype<>'" + WorkflownoteVO.WORKITEM_TYPE_CHECKMSG
				// + "' "
				+ (billType == null ? "" : "and pk_billtype=?");
				if(iWorkflowOrApproveflow==0){
					
				}else{
					sql = sql+ getWorkflowTypeAndWhere(iWorkflowOrApproveflow);
				}
				

		String tempSql = "";
		if (iStatus == 1){
			tempSql = " and approveresult is not null";
			}else if(iStatus == 2){
				tempSql = " and approveresult is null and  approvestatus = 0 ";
			}
		
		sql += tempSql + " order by c.senddate, c.dealdate asc,c.dealtimemillis asc";

		PersistenceManager persist = null;
		try {
			persist = PersistenceManager.getInstance();
			JdbcSession jdbc = persist.getJdbcSession();
			SQLParameter para = new SQLParameter();
			para.addParam(billId);
			para.addParam(billId);
			if (billType != null)
				para.addParam(billType);
			@SuppressWarnings({ "unchecked"})
			List<WorkflownoteVO> noteList = (List<WorkflownoteVO>) jdbc.executeQuery(sql, para,
					new BeanListProcessor(WorkflownoteVO.class));
			return (WorkflownoteVO[]) noteList
					.toArray(new WorkflownoteVO[noteList.size()]);
		} finally {
			if (persist != null)
				persist.release();
		}
	}
	
	
	
	/**
	 * 批量查询
	 * @param billId
	 * @param billType
	 * @param iStatus
	 * @param iWorkflowOrApproveflow
	 * @return
	 * @throws DbException
	 */
	public WorkflownoteVO[] queryAllByBillIdBatch(String[] billId, String[] billType,
			int iStatus, int iWorkflowOrApproveflow) throws DbException {
		 
	//	String[] dd = new String[] {"111"};
		String billidcon = buildsql(billId);
		String billTypecon = buildsql(billType);
		
	
		
		String suffix = MultiLangUtil.getCurrentLangSeqSuffix();
		String mlFiledName = "user_name" + suffix;
		String sql = "select pk_checkflow,pk_wf_task,pk_billtype,billno,actiontype,senderman,"
				+ "checkman,ischeck,checknote,senddate,dealdate,messagenote,receivedeleteflag,observer,c.ts,"
				+ "c.pk_org,billid,billversionpk,a.user_name as sendername,a."
				+ mlFiledName
				+ " as sendernameml,b.user_name as checkname,b."
				+ mlFiledName
				+ " as checknameml,"
				+ "approvestatus,approveresult,c.pk_group,c.workflow_type from pub_workflownote c,sm_user a,sm_user b "
				+ "where c.senderman=a.cuserid and c.checkman=b.cuserid and c.approvestatus !=5 "//去掉补偿弃审
				+ "and (billversionpk in ("+billidcon+") or billid in ("+billidcon+") ) and actiontype<>'"
				+ WorkflownoteVO.WORKITEM_TYPE_BIZ
				+ "' "
				// + "and actiontype<>'" + WorkflownoteVO.WORKITEM_TYPE_CHECKMSG
				// + "' "
				+ (billType == null ? "" : "and pk_billtype in ("+billTypecon+")");
				if(iWorkflowOrApproveflow==0){
					
				}else{
					sql = sql+ getWorkflowTypeAndWhere(iWorkflowOrApproveflow);
				}
				

		String tempSql = "";
		if (iStatus == 1){
			tempSql = " and approveresult is not null";
			}else if(iStatus == 2){
				tempSql = " and approveresult is null and  approvestatus = 0 ";
			}
		
		sql += tempSql + " order by c.senddate, c.dealdate asc,c.dealtimemillis asc";

		PersistenceManager persist = null;
		try {
			persist = PersistenceManager.getInstance();
			JdbcSession jdbc = persist.getJdbcSession();
//			SQLParameter para = new SQLParameter();
//			para.addParam(billidcon);
//			para.addParam(billidcon);
//			if (billType != null)
//				para.addParam(billTypecon);
			@SuppressWarnings({ "unchecked"})
			List<WorkflownoteVO> noteList = (List<WorkflownoteVO>) jdbc.executeQuery(sql, null,
					new BeanListProcessor(WorkflownoteVO.class));
			return (WorkflownoteVO[]) noteList
					.toArray(new WorkflownoteVO[noteList.size()]);
		} finally {
			if (persist != null)
				persist.release();
		}
	}
	
	

	/**
	 * 查询出某单据的所有已经完成的工作项
	 * 
	 * @param billId
	 * @param billType
	 * @return
	 * @throws BusinessException
	 */
	public WorkflownoteVO[] queryAllMessageChecked(String billId,
			String billType) throws BusinessException {
		String cond = "billversionpk=? and pk_billtype=? and approvestatus="
				+ WfTaskOrInstanceStatus.Finished.getIntValue()
				+ " and approveresult is not null";
		SQLParameter para = new SQLParameter();
		para.addParam(billId);
		para.addParam(billType);
		@SuppressWarnings("unchecked")
		Collection<WorkflownoteVO> coRet = new BaseDAO().retrieveByClause(
				WorkflownoteVO.class, cond, para);

		return coRet.toArray(new WorkflownoteVO[coRet.size()]);
	}

	/**
	 * 单据审批通过\审批不通过后给某些人发送的通知工作项.
	 * 
	 * @param workFlow
	 * @param checkers
	 * @param pkCorp
	 * @return keys 工作项的主键数组
	 * @throws BusinessException 
	 * @throws DbException
	 */
	@SuppressWarnings("rawtypes")
	public String[] insertInfoWorkitem(IMsgL10NCallback msg, WorkflownoteVO workFlow,
			ArrayList checkers, String pkCorp) throws BusinessException {
		
		List<WorkflownoteVO> noteList = new ArrayList<WorkflownoteVO>();
		
		for (Iterator it = checkers.iterator(); it.hasNext(); ) {
			String checker = (String) it.next();
			
			WorkflownoteVO note = (WorkflownoteVO) workFlow.clone();
			note.setCheckman(checker);
			
			
			//测试代码
		/*	msg = ((AbstractMsgL10NCallback)msg).appendAfter(new AbstractMsgL10NCallback() {
				
				@Override
				public String getMessage() throws BusinessException {
					return "1";
				}
			}).appendAfter(new AbstractMsgL10NCallback() {
				
				@Override
				public String getMessage() throws BusinessException {
					return "2";
				}
			}).appendBefore(new AbstractMsgL10NCallback() {
				
				@Override
				public String getMessage() throws BusinessException {
					return "-1";
				}
			}).appendBefore(new AbstractMsgL10NCallback() {
				
				@Override
				public String getMessage() throws BusinessException {
					return "-2";
				}
			});*/
			
			note.setMessagenote(msg.getLocalizedMsg(checker));
			
			noteList.add(note);
		}
		
		return new BaseDAO().insertVOList(noteList);
	}

	/**
	 * 根据SQL语句查询对应的数据,使用Vector返回 <li>处理大数据量查询(只返回前5000行数)
	 * 
	 * @param strSQL
	 *            String 传入的SQL语句
	 * @param intCols
	 *            int 被返回的查询字段个数
	 * @param fieldType
	 *            int[] 被返回的查询字段类型,必须为IDapType中的常量
	 */
	public Vector queryDataBySQL(String strSQL, final int intCols,
			final int[] fieldType) throws DbException {

		PersistenceManager persist = null;
		try {
			persist = PersistenceManager.getInstance();
			JdbcSession jdbc = persist.getJdbcSession();
			Vector vResult = (Vector) jdbc.executeQuery(strSQL,
					new BaseProcessor() {
						public Object processResultSet(ResultSet rs)
								throws SQLException {
							Vector retVec = new Vector();

							int lineCount = 0;
							int intRow = 1;
							while (rs.next()) {
								// 只返回前5000行数据
								if (lineCount++ >= IWorkFlowConst.MAX_QUERY_ROW_COUNT) {
									Logger.warn(">>WorknoteManager.queryDataBySQL():查询数据量太大,只返回前面5000数据");
									break;
								}

								Vector v = new Vector();
								v.addElement(Integer.valueOf(intRow++));
								for (int i = 1; i <= intCols; i++) {
									switch (fieldType[i - 1]) {
									case IDapType.INTEGER: {
										int tmpInt = rs.getInt(i);
										v.addElement(Integer.valueOf(tmpInt));
										break;
									}
									case IDapType.UFDOUBLE: {
										BigDecimal tmpDbl = (BigDecimal) rs
												.getObject(i);
										v.addElement(tmpDbl == null ? null
												: new UFDouble(tmpDbl));
										break;
									}
									case IDapType.STRING: {
										v.addElement(rs.getString(i));
										break;
									}
									default: {
										v.addElement(rs.getString(i));
										break;
									}
									}
								}
								retVec.addElement(v);
							}
							return retVec;
						}
					});
			return vResult;
		} finally {
			if (persist != null)
				persist.release();
		}
	}

	/**
	 * 查询有效的审批人，不包括制单人
	 * 
	 * @param billId
	 * @param billType
	 * @return
	 * @throws DbException
	 */
	public UserVO[] queryValidCheckers(String billId, String billType)
			throws DbException {
		String sql = "select a.cuserid,a.user_code,a.user_name from pub_workflownote c,sm_user a "
				+ "where c.checkman=a.cuserid and billversionpk=? and pk_billtype=? and actiontype not in('"
				+ WorkflownoteVO.WORKITEM_TYPE_BIZ
				+ "','"
				+ WorkflownoteVO.WORKITEM_TYPE_MAKEBILL + "') ";

		String tempSql = " and approveresult is not null and approvestatus<>"
				+ WfTaskOrInstanceStatus.Inefficient.getIntValue();
		sql += tempSql + " order by c.senddate";

		PersistenceManager persist = null;
		try {
			persist = PersistenceManager.getInstance();
			JdbcSession jdbc = persist.getJdbcSession();
			SQLParameter para = new SQLParameter();
			para.addParam(billId);
			para.addParam(billType);
			List lResult = (List) jdbc.executeQuery(sql, para,
					new BaseProcessor() {
						@Override
						public Object processResultSet(ResultSet rs)
								throws SQLException {
							ArrayList alRet = new ArrayList();
							while (rs.next()) {
								UserVO userVO = new UserVO();
								userVO.setPrimaryKey(rs.getString(1));
								userVO.setUser_code(rs.getString(2));
								userVO.setUser_name(rs.getString(3));
								alRet.add(userVO);
							}
							return alRet;
						}
					});
			return (UserVO[]) lResult.toArray(new UserVO[lResult.size()]);
		} finally {
			if (persist != null)
				persist.release();
		}
	}

	/**
	 * 审批流结束-不通过，给制单人发送消息，并 发送邮件或短信
	 * 
	 * @param message
	 * @param paraVo
	 */
	public void sendMessageAfterNoPass(IMsgL10NCallback message, PfParameterVO paraVo) {
		String checkNote = null;
		if (paraVo.m_workFlow != null)
			checkNote = paraVo.m_workFlow.getChecknote();
		// Object[] retObjs = sendAllPersonMessage(message, checkNote,
		// paraVo.m_billId, paraVo.m_billType, paraVo.m_operator);
		Object[] retObjs = sendAllPersonMessage(message, paraVo);
		if (retObjs == null)
			return;

		IMsgL10NCallback mailMsg = (IMsgL10NCallback) retObjs[0];
		String[] userIds = (String[]) ((ArrayList) retObjs[1])
				.toArray(new String[0]);

		// mail or mobile
		mailOrSmsToMakerAfterFinished(userIds, paraVo, mailMsg,
				paraVo.m_operator);

	}

	/**
	 * 支持附件
	 * 
	 * @param message
	 * @param paraVO
	 * @return
	 */
	public Object[] sendAllPersonMessage(IMsgL10NCallback message, PfParameterVO paraVO) {
		try {
			// 查询该单据的所有审批记录
			WorkflownoteVO[] workflowVOs = queryAllMessageChecked(
					paraVO.m_billVersionPK, paraVO.m_billType);

			if (workflowVOs == null || workflowVOs.length == 0)
				return null;

			Set<String> checkerSet = new HashSet<String>();

			final String senderman = paraVO.m_operator;
			final String billno = paraVO.m_billNo;
			
			message = new AbstractMsgL10NCallback() {
				
				@Override
				public String getMessage() throws BusinessException {
					UserVO userVo = NCLocator.getInstance().lookup(IUserManageQuery.class).getUser(senderman);
					String senderName = senderman;
					if (userVo != null) {
						senderName = PfMultiLangUtil.getSuperVONameOfCurrentLang(userVo, UserVO.USER_NAME);
					}
					return senderName + "{UPPpfworkflow-000347}<"/**
					 	* @res *
					 	*      "通知单据"
					 	*/
						+ billno + ">";
				}
			}.appendAfter(message);

			WorkflownoteVO worknoteVO = new WorkflownoteVO();
			// sendWorkflow.setBillType(MessageVO.NOT_BUSINESS_MSG);
			worknoteVO.setPk_billtype(paraVO.m_billType);
			worknoteVO.setIscheck("N");
			worknoteVO.setSenderman(senderman);
			worknoteVO.setPk_org(workflowVOs[0].getPk_org());
			worknoteVO.setPk_group(workflowVOs[0].getPk_group());
			worknoteVO.setBillid(workflowVOs[0].getBillid());
			worknoteVO.setBillVersionPK(workflowVOs[0].getBillVersionPK());
			worknoteVO.setBillno(workflowVOs[0].getBillno());
			worknoteVO.setActiontype(WorkflownoteVO.WORKITEM_TYPE_BIZ);
			// yanke1 此处不设置message
			// 后面为各个人生成工作项时再设置
//			worknoteVO.setMessagenote(message);
			worknoteVO.setChecknote(paraVO.m_workFlow == null ? ""
					: paraVO.m_workFlow.getChecknote());
			worknoteVO.setSenddate(NCLocator.getInstance().lookup(ITimeService.class).getUFDateTime());
			worknoteVO.setApprovestatus(WfTaskOrInstanceStatus.Started
					.getIntValue());
			String checker = null;
			String sender = null;
			for (int i = 0; i < workflowVOs.length; i++) {
				checker = workflowVOs[i].getCheckman();
				if (checker != null) {
					// yanke1 2012-9-27
					// 在审批通过的情况下，即使最后审批人与制单人为同一人，也会给制单人发消息
					// 所以 这里不再判断最后审批人与接收人是否相同，从而保持行为与审批通过情况一致
					checkerSet.add(checker);
					
//					if (!checker.equals(senderman)) {
//						checkerSet.add(checker);
//					} else if (checker.equals(paraVO.m_makeBillOperator)) {
//						// 如果接收人与最后审批人为同一人
//						// 且接收人为制单人
//						// 那么依然发给它
//						
//					} else {
//						// 接收人与最后审批人为同一人
//					}
				}
				sender = workflowVOs[i].getSenderman();
				if (sender != null && !sender.equals(senderman)) {
					checkerSet.add(sender);
				}
			}
			
			if (checkerSet.size() == 0) {
				return null;
			}
			
			ArrayList<String> checkerList = new ArrayList<String>();
			checkerList.addAll(checkerSet);
			
			String[] pks = insertInfoWorkitem(message, worknoteVO, checkerList,
					worknoteVO.getPk_org());

			// yanke1 2012-10-10 工作任务的附件不再发到消息里
			WorkflownoteVO[] notes = queryWorkitemArrayByPKs(pks);
			
			// 审批结束且不通过，发送消息给参与者
			PfMessageUtil.sendMessageOfWorknoteBatch(notes);

			return new Object[] { message, checkerList };
		} catch (Exception e) {
			Logger.warn(e.getMessage(), e);
			// XXX:即使发送失败，也不向外抛出异常
			// yanke1 2012-10-10 为什么不抛异常？太不合理
			throw new PFRuntimeException(e.getMessage(), e);
		}
	}

	/**
	 * 给所有参与该流程实例的人发送非业务消息
	 * 
	 * @param message
	 * @param checkNote
	 * @param billid
	 * @param billType
	 * @param senderman
	 */
	public Object[] sendAllPersonMessage(IMsgL10NCallback message, String checkNote,
			String billid, String billType, final String senderman) {
		try {
			// 查询该单据的所有审批记录
			WorkflownoteVO[] workflowVOs = queryAllMessageChecked(billid,
					billType);

			if (workflowVOs == null || workflowVOs.length == 0)
				return null;

			ArrayList alCheckers = new ArrayList();
			
			final String billno = workflowVOs[0].getBillno();
			
			message = new AbstractMsgL10NCallback() {
				
				@Override
				public String getMessage() throws BusinessException {
					UserVO userVo = NCLocator.getInstance().lookup(IUserManageQuery.class).getUser(senderman);
					String senderName = senderman;
					if (userVo != null) {
						senderName = PfMultiLangUtil.getSuperVONameOfCurrentLang(userVo, UserVO.USER_NAME);
					}
					return senderName + "{UPPpfworkflow-000347}<"/* @res "通知单据" */
										+ billno + ">";
				}
			}.appendAfter(message);
			// 查找操作人的姓名


			WorkflownoteVO worknoteVO = new WorkflownoteVO();
			// sendWorkflow.setBillType(MessageVO.NOT_BUSINESS_MSG);
			worknoteVO.setPk_billtype(billType);
			worknoteVO.setIscheck("N");
			worknoteVO.setSenderman(senderman);
			worknoteVO.setPk_org(workflowVOs[0].getPk_org());			
			worknoteVO.setPk_group(workflowVOs[0].getPk_group());
			worknoteVO.setBillid(workflowVOs[0].getBillid());
			worknoteVO.setBillVersionPK(workflowVOs[0].getBillVersionPK());
			worknoteVO.setBillno(workflowVOs[0].getBillno());
			worknoteVO.setActiontype(WorkflownoteVO.WORKITEM_TYPE_BIZ);
			worknoteVO.setChecknote(checkNote);
			worknoteVO.setSenddate(NCLocator.getInstance().lookup(ITimeService.class).getUFDateTime());
			worknoteVO.setApprovestatus(WfTaskOrInstanceStatus.Started
					.getIntValue());
			String checker = null;
			String sender = null;
			for (int i = 0; i < workflowVOs.length; i++) {
				checker = workflowVOs[i].getCheckman();
				if (checker != null && !checker.equals(senderman)) {
					if (!alCheckers.contains(checker)) {
						alCheckers.add(checker);
					}
				}
				sender = workflowVOs[i].getSenderman();
				if (sender != null && !sender.equals(senderman)) {
					if (!alCheckers.contains(sender)) {
						alCheckers.add(sender);
					}
				}
			}
			String[] pks = insertInfoWorkitem(message, worknoteVO, alCheckers,
					worknoteVO.getPk_org());
			// 审批结束且不通过，发送消息给参与者
			PfMessageUtil.sendMessageOfWorknoteBatch(queryWorkitemArrayByPKs(pks));

			return new Object[] { message, alCheckers };
		} catch (Exception e) {
			Logger.warn(e.getMessage(), e);
			// XXX:即使发送失败，也不向外抛出异常
			// yanke1 2012-10-10 为什么不抛异常？太不合理
			throw new PFRuntimeException(e.getMessage(), e);
		}
	}

	/**
	 * 流程结束后，发送邮件或短信给制单人
	 * 
	 * @param paraVo
	 * 
	 */
	private void mailOrSmsToMakerAfterFinished(String[] userIds,
			PfParameterVO paraVo, final IMsgL10NCallback topic, String currentCheckman) {
		try {

			WFTask currentTask = paraVo.m_workFlow.getTaskInfo().getTask();
			
			MessageMetaVO meta = PfMessageUtil.createMessageMeta(paraVo.m_workFlow, currentTask, null);
			meta.setSenddate(new UFDateTime());
			
			String txMark = TxCompletionChecker.getInstance().generateTxMark();
			
			// 查询审批流定义
			EngineService wfQry = new EngineService();
			// WorkflowProcess wp =
			// wfQry.findParsedWfProcessByDefPK(currentTask.getWfProcessDefPK());
			BasicWorkflowProcess bwp = wfQry
					.findParsedMainWfProcessByInstancePK(currentTask
							.getWfProcessInstancePK());

			@SuppressWarnings("deprecation")
			String ptId = bwp.getMailPrintTemplet().getTempletid();
			MailModal mailModal = bwp.getMailModal();
			MobileModal mobileModal = bwp.getMobileModal();
			if (mailModal.getValue() != MailModal.NO_MAIL_INT) {
				
				meta.setMessage_type(MessageMetaType.EMAIL_NOTICE);
				Map<String, MessageMetaVO> userMetaMap = new HashMap<String, MessageMetaVO>();
				
				for (String userid : userIds) {
					MessageMetaVO cloned = (MessageMetaVO) meta.clone();
					
					cloned.setReceiver(userid);
					userMetaMap.put(userid, cloned);
				}
				
				
				Logger.debug(">>>发送邮件开始");
				// 不论流程定义了邮件审批还是邮件通知，给制单人的邮件都不可审批
				EmailMsg em = new EmailMsg();
				em.setMailModal(mailModal);
				em.setUserIds(userIds);
				em.setBillId(paraVo.m_billVersionPK);
				em.setBillNo(paraVo.m_billNo);
				em.setBillType(paraVo.m_billType);
				em.setPrintTempletId(ptId);
				em.setTopicCallback(topic);
				em.setSenderman(currentCheckman);
				// XXX:leijun 2009-5 需要如下赋值
				em.setTasktype(WfTaskType.Makebill.getIntValue());
				em.setLangCode(InvocationInfoProxy.getInstance().getLangCode());
				em.setDatasource(InvocationInfoProxy.getInstance()
						.getUserDataSource());
				em.setInvocationInfo(getInvocationInfo());
				em.setUserMetaMap(userMetaMap);
				em.setTxMark(txMark);
				
				// 异步发送邮件
				PfMailAndSMSUtil.sendEMS(em);
			}
			if (mobileModal.getValue() != MobileModal.NO_MOBILE_INT) {
				Logger.debug(">>>发送短信开始");
				// 不论流程定义了短信审批还是短信通知，给制单人的邮件都不可审批
				String[] targetPhones = PfMailAndSMSUtil
						.fetchPhonesByUserId(userIds);
				if (targetPhones == null || targetPhones.length == 0) {
					Logger.warn(NCLangRes4VoTransl.getNCLangRes().getStrByID(
							"pfworkflow", "WorknoteManager-0001")/*
																 * >>找不到手机号，无法发送短信
																 * ，返回
																 */);
					return;
				}
				
				
				
				IMsgL10NCallback fullTopic = new AbstractMsgL10NCallback() {
					
					@Override
					public String getMessage() throws BusinessException {
						return NCLangRes4VoTransl.getNCLangRes().getStrByID(
								"pfworkflow", "WorknoteManager-0002", null,
								new String[] { topic.getLocalizedMsg(getCurrentCuserid()) })/* {0}(注:不可回复) */;
					}
				};
				
				meta.setMessage_type(MessageMetaType.SMS_NOTICE);
				Map<String, MessageMetaVO> userMetaMap = new HashMap<String, MessageMetaVO>();
				
				for (String userid : userIds) {
					MessageMetaVO cloned = (MessageMetaVO) meta.clone();
					
					cloned.setReceiver(userid);
					userMetaMap.put(userid, cloned);
				}
				
				MobileMsg mm = new MobileMsg();
				mm.setTargetPhones(targetPhones);
				mm.setMsgCallback(fullTopic);
				mm.setUserMetaMap(userMetaMap);
				mm.setTxMark(txMark);
				// 异步发送短信
				PfMailAndSMSUtil.sendSMS(mm);
			}
		} catch (Exception e) {
			Logger.warn(e.getMessage(), e);
			// WARN::即使发送失败，也不向外抛出异常
		}
	}
	
	private InvocationInfo getInvocationInfo() {
		InvocationInfo info = new InvocationInfo();

		info.setBizDateTime(InvocationInfoProxy.getInstance().getBizDateTime());
		info.setGroupId(InvocationInfoProxy.getInstance().getGroupId());
		info.setGroupNumber(InvocationInfoProxy.getInstance().getGroupNumber());
		info.setLangCode(InvocationInfoProxy.getInstance().getLangCode());
		info.setUserDataSource(InvocationInfoProxy.getInstance().getUserDataSource());
		info.setUserId(InvocationInfoProxy.getInstance().getUserId());

		return info;
	}

	/**
	 * 单据审批通过后,给制单人发送非业务消息
	 * 
	 * @param message
	 * @param paraVo
	 */
	public void sendMessageToBillMaker(IMsgL10NCallback message, PfParameterVO paraVo) {
		sendMessage(message, paraVo, paraVo.m_makeBillOperator);
	}

	/**
	 * 给某人发送业务通知消息
	 * 
	 * @param message
	 * @param paraVo
	 */
	public void sendMessage(final IMsgL10NCallback message, PfParameterVO paraVo, String userId) {
		try {
			
			
			final String billno = paraVo.m_billNo;
			final String sender = paraVo.m_operator;
			
			AbstractMsgL10NCallback finalMessage = new AbstractMsgL10NCallback() {
				
				@Override
				public String getMessage() throws BusinessException {
					// 查找操作人的姓名
					IUserManageQuery iUserService = (IUserManageQuery) NCLocator
							.getInstance().lookup(IUserManageQuery.class.getName());
					nc.vo.sm.UserVO user = iUserService.getUser(sender);
					String senderName = sender;
					if (user != null) {
						senderName = PfMultiLangUtil.getSuperVONameOfCurrentLang(user, UserVO.USER_NAME);
					}

					return senderName + "{UPPpfworkflow-000347}<" + billno + ">";
				}
				
			};
			
			if (message != null ) {
				finalMessage.appendAfter(message);
			}
			
			WorkflownoteVO worknoteVO = new WorkflownoteVO();

			// sendWorkflow.setBillType(MessageVO.NOT_BUSINESS_MSG);
			worknoteVO.setPk_billtype(paraVo.m_billType);
			worknoteVO.setIscheck("N");
			worknoteVO.setSenderman(paraVo.m_operator);
			worknoteVO.setCheckman(userId);
			worknoteVO.setPk_org(paraVo.m_pkOrg);
			worknoteVO.setPk_group(paraVo.m_pkGroup);
			worknoteVO.setBillid(paraVo.m_billId);
			worknoteVO.setBillVersionPK(paraVo.m_billVersionPK);
			worknoteVO.setBillno(paraVo.m_billNo);
			// worknoteVO.setPk_businesstype(paraVo.m_businessType);
			worknoteVO.setActiontype(WorkflownoteVO.WORKITEM_TYPE_BIZ);
			// sendWorkflow.setSendDate(new UFDateTime(paraVo.m_currentDate));
			worknoteVO.setSenddate(NCLocator.getInstance().lookup(ITimeService.class).getUFDateTime());
			worknoteVO.setApprovestatus(WfTaskOrInstanceStatus.Started
					.getIntValue());
			if (paraVo.m_workFlow != null) {
				if (paraVo.m_workFlow.getChecknote() != null) {
					worknoteVO.setChecknote(paraVo.m_workFlow.getChecknote());
				}
				if (paraVo.m_workFlow.getWorkflow_type() != null) {
					worknoteVO.setWorkflow_type(paraVo.m_workFlow.getWorkflow_type());
				}
			} else {
				worknoteVO.setChecknote("");
			}

			ArrayList checkers = new ArrayList();
			checkers.add(worknoteVO.getCheckman());
			String[] pks = insertInfoWorkitem(finalMessage, worknoteVO, checkers,
					worknoteVO.getPk_org());

			// yanke1 2012-10-10 工作任务的附件不再发到消息中心中
			
			WorkflownoteVO[] worknotes = queryWorkitemArrayByPKs(pks);
			
			//kejl 与nc调用方式分开
			
			List<WorkflownoteVO> ncnotes = new ArrayList<WorkflownoteVO>();
			List<WorkflownoteVO> nccnotes = new ArrayList<WorkflownoteVO>();
			
		//	IBilltypeService billtypeService  =  NCLocator.getInstance().lookup(IBilltypeService.class);
			if(worknotes!=null && worknotes.length>0){
				for(WorkflownoteVO note : worknotes){
					
					BilltypeVO  billtypeVo = null;
					if(StringUtils.isNotEmpty(note.getPk_billtype())){
						billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(note.getPk_billtype()));
					//	billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(ncMsg.getMessage().getDetail().split("@")[1]));
						// billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(task.getBillType()));
					//	  billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(worknote.getPk_billtype()));
					// billtyVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(currentTask.getBillType()));
					}
				//	BilltypeVO billtypeVo = billtypeService.getRealBilltype(note.getPk_billtype());
					
					if(billtypeVo!=null && billtypeVo.getIsLightBill()!=null && billtypeVo.getIsLightBill().booleanValue()){
						
						nccnotes.add(note);
						
					}else{
						ncnotes.add(note);
					}


//					if( billtypeVo.getIsLightBill()!=null && billtypeVo.getIsLightBill().booleanValue())
//						nccloud.bs.pub.pf.PfMessageUtil.sendMessageOfWorknoteBatch("approve",notes);//PfMessageUtil.sendMessageOfWorknoteBatch(notes);
//					else
//						PfMessageUtil.sendMessageOfWorknoteBatch(notes);	
					
					
				}
				
			}
			
			if(ncnotes!=null && ncnotes.size()>0){
				
				PfMessageUtil.sendMessageOfWorknoteBatch(ncnotes.toArray(new WorkflownoteVO[0]));
			}
			
			if(nccnotes!=null && nccnotes.size()>0){
				
				nccloud.bs.pub.pf.PfMessageUtil.sendMessageOfWorknoteBatch("notice",nccnotes.toArray(new WorkflownoteVO[0]));
			}
			
			
			

			// mail or mobile
			String[] userIds = new String[] { userId };
			mailOrSmsToMakerAfterFinished(userIds, paraVo, finalMessage,
					worknoteVO.getCheckman());
			//申请单推送到友报账
//			if(paraVo.m_actionName.equals("SIGNAL") && paraVo.m_billType.startsWith("261")){
//				 new PushableMsgErmDistributor().distributeWorkitem(worknotes);
//			}
			if(paraVo.m_billType.equals("261X-Cxx-004")){
				 new PushableMsgErmDistributor().distributeWorkitem(worknotes);
			}
		} catch (Exception e) {
			Logger.warn(e.getMessage(), e);
			// WARN::即使发送失败，也不向外抛出异常
			// yanke1 2012-10-10 为什么不抛异常？太不合理
			throw new PFRuntimeException(e.getMessage(), e);
		}
	}

	public String getProcessId(PfParameterVO paraVO, int iWorkflowtype) {
		String processId = null;
		String billId = paraVO.m_billVersionPK;
		String billNo = paraVO.m_billNo;
		String billtype = paraVO.m_billType;
		String sql = "select processdefid from pub_wf_instance where billversionpk=? and billtype=? and workflow_type=? and billno=?";
		PersistenceManager persist = null;
		try {
			persist = PersistenceManager.getInstance();
			JdbcSession jdbc = persist.getJdbcSession();
			SQLParameter para = new SQLParameter();
			para.addParam(billId);
			para.addParam(billtype);
			para.addParam(iWorkflowtype);
			para.addParam(billNo);
			processId = (String) jdbc.executeQuery(sql, para,
					new ColumnProcessor(1));
			return processId;
		} catch (DbException e) {
			// TODO Auto-generated catch block
			Logger.error(e.getMessage(), e);
		} finally {
			if (persist != null)
				persist.release();
		}
		return null;
	}

	private String getInstancePk(PfParameterVO paraVO, int iWorkflowtype) {
		String processId = null;
		String billId = paraVO.m_billVersionPK;
		String billNo = paraVO.m_billNo;
		String billtype = paraVO.m_billType;
		String sql = "select pk_wf_instance from pub_wf_instance where billversionpk=? and billtype=? and workflow_type=? and billno=?";
		PersistenceManager persist = null;
		try {
			persist = PersistenceManager.getInstance();
			JdbcSession jdbc = persist.getJdbcSession();
			SQLParameter para = new SQLParameter();
			para.addParam(billId);
			para.addParam(billtype);
			para.addParam(iWorkflowtype);
			para.addParam(billNo);
			processId = (String) jdbc.executeQuery(sql, para,
					new ColumnProcessor(1));
			return processId;
		} catch (DbException e) {
			// TODO Auto-generated catch block
			Logger.error(e.getMessage(), e);
		} finally {
			if (persist != null) {
				persist.release();
			}
		}
		return null;
	}

	/**
	 * 流程状态发生变化时候向制单人发送信息
	 * 
	 * @throws
	 * */
	public void sendMsgWhenWFstateChanged(PfParameterVO paraVO,
			String processId, int note, int iWorkflowtype)
			throws BusinessException {

		if (StringUtil.isEmptyWithTrim(processId)
				|| StringUtil.isEmptyWithTrim(getInstancePk(paraVO,
						iWorkflowtype))) {
			// 没有走工作流或者审批流
			return;
		}
		WorkflowProcess wps = new EngineService().queryWfProcess(processId,
				getInstancePk(paraVO, iWorkflowtype));
		ArrayList<String> supervisors = new ArrayList<String>();
		if(((BasicWorkflowProcess) wps).getSupervisor()!=null && !((BasicWorkflowProcess) wps).getSupervisor().isEmpty())
			supervisors.addAll(((BasicWorkflowProcess) wps).getSupervisor());
		ArrayList<String> sendstates = ((BasicWorkflowProcess) wps)
				.getWorkflowStateChangeInfo();

		CommonMessageVO msgVO = null;

		// @modifier yanke1 2011-4-1 无论是否在流程中配置了流程实例监控条件，流程终止时都要向制单人发送消息
		if (note == WfTaskOrInstanceStatus.Terminated.getIntValue()) {

			// supervisors参数置空会默认向制单人发送消息
			String billmaker = paraVO.m_makeBillOperator;
			// luowk7 处理终止流程消息空指针
			if ((supervisors.size()>0&&!supervisors.toString().contains(billmaker))||supervisors.size()==0) {
				supervisors.add("[U]"+billmaker);
			}
			msgVO = fetchMsgVO(paraVO, supervisors, WfTaskOrInstanceStatus
					.fromIntValue(note).toString().substring(1));
		
//			IBilltypeService billtypeService  =  NCLocator.getInstance().lookup(IBilltypeService.class);
//			
//			BilltypeVO billtypeVo = billtypeService.getRealBilltype(msgVO.getBilltype());
			
			//BilltypeVO[] billtypeVo = new BilltypeDMO().queryAllBillTypes("pk_billtypecode='"+task.getBillType()+"'");
			
//			if(billtypeVo!=null && billtypeVo.length>0){
//				vo = billtypeVo[0];
//			}else{
//			throw new Exception("单据类型不存在");
//			}
			BilltypeVO  billtypeVo = null;
			if(StringUtils.isNotEmpty(msgVO.getBilltype())){
			//	billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(note.getPk_billtype()));
			//	billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(ncMsg.getMessage().getDetail().split("@")[1]));
				// billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(task.getBillType()));
			//	  billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(worknote.getPk_billtype()));
			// billtyVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(currentTask.getBillType()));
				 billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(msgVO.getBilltype()));
			}
			


			if(billtypeVo!=null && billtypeVo.getIsLightBill()!=null && billtypeVo.getIsLightBill().booleanValue())
				nccloud.bs.pub.pf.PfMessageUtil.sendNoticeMessage(msgVO);
				//nccloud.bs.pub.pf.PfMessageUtil.sendMessageOfWorknoteBatch("approve",notes);//PfMessageUtil.sendMessageOfWorknoteBatch(notes);
			else
				PfMessageUtil.sendNoticeMessage(msgVO);
			//	PfMessageUtil.sendMessageOfWorknoteBatch(notes);
			
			
		} else if (sendstates != null
				&& sendstates.contains(String.valueOf(note))) { // 配置了流程实例监控条件、在挂起和恢复操作时将向监控人/制单人发送消息
			String changenote = "";
			if (String.valueOf(note).equals("10")) {
				changenote = NCLangRes4VoTransl.getNCLangRes().getStrByID(
						"pfworkflow", "WorknoteManager-0003")/* 恢复 */;
			} else {
				changenote = WfTaskOrInstanceStatus.fromIntValue(note)
						.toString();
			}
//			IBilltypeService billtypeService  =  NCLocator.getInstance().lookup(IBilltypeService.class);
//			
//			BilltypeVO billtypeVo = billtypeService.getRealBilltype(fetchMsgVO(paraVO, supervisors,
//					changenote).getBilltype());
			
			//BilltypeVO[] billtypeVo = new BilltypeDMO().queryAllBillTypes("pk_billtypecode='"+task.getBillType()+"'");
			
//			if(billtypeVo!=null && billtypeVo.length>0){
//				vo = billtypeVo[0];
//			}else{
//			throw new Exception("单据类型不存在");
//			}
			
			BilltypeVO  billtypeVo = null;
			if(StringUtils.isNotEmpty(fetchMsgVO(paraVO, supervisors,
					changenote).getBilltype())){
			//	billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(note.getPk_billtype()));
			//	billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(ncMsg.getMessage().getDetail().split("@")[1]));
				// billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(task.getBillType()));
			//	  billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(worknote.getPk_billtype()));
			// billtyVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(currentTask.getBillType()));
			//	 billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(msgVO.getBilltype()));
				 billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.
						getRealBilltype(fetchMsgVO(paraVO, supervisors,
								changenote).getBilltype()));
			}
			


			
			if(billtypeVo!=null && billtypeVo.getIsLightBill()!=null && billtypeVo.getIsLightBill().booleanValue())
				nccloud.bs.pub.pf.PfMessageUtil.sendNoticeMessage(fetchMsgVO(paraVO, supervisors,
						changenote));
				//nccloud.bs.pub.pf.PfMessageUtil.sendMessageOfWorknoteBatch("approve",notes);//PfMessageUtil.sendMessageOfWorknoteBatch(notes);
			else
				PfMessageUtil.sendNoticeMessage(fetchMsgVO(paraVO, supervisors,
						changenote));
			//	PfMessageUtil.sendMessageOfWorknoteBatch(notes);
			
			
		
		}
	}

	/**
	 * 构造信息，用PfMessageUtil发送,没有配置监控人的情况下，默认给制单人发送信息
	 * */
	private CommonMessageVO fetchMsgVO(PfParameterVO paraVO,
			ArrayList<String> superisor, String note) throws BusinessException {
		CommonMessageVO message = new CommonMessageVO();
		message.setSender(paraVO.m_operator);
		message.setTitle(NCLangRes4VoTransl.getNCLangRes().getStrByID(
				"pfworkflow", "WorknoteManager-0004")/* 流程状态改变通知消息 */);
		message.setBillid(paraVO.m_billVersionPK);
		message.setBillno(paraVO.m_billNo);
		message.setBilltype(paraVO.m_billType);
		message.setNeedFlowCheck(false);
		UserNameObject[] receivers = null;
		if (superisor == null || superisor.size() == 0) {
			receivers = new UserNameObject[1];
			IUserManageQuery qry = NCLocator.getInstance().lookup(
					IUserManageQuery.class);
			UserVO receiver = qry.getUser(paraVO.m_makeBillOperator);
			receivers[0] = new UserNameObject(receiver.getUser_name());
			receivers[0].setUserCode(receiver.getUser_code());
			receivers[0].setUserPK(receiver.getCuserid());
			receivers[0].setPkcorp(paraVO.m_pkGroup);
		} else {
			receivers = getReceiverVO(superisor, paraVO.m_pkGroup);
		}
		message.setReceiver(receivers);
		message.setSendDataTime(new UFDateTime());
		UserVO sender = NCLocator.getInstance().lookup(IUserManageQuery.class)
				.getUser(paraVO.m_operator);
		message.setMessageContent(sender.getUser_name() + note
				+ paraVO.m_billNo);
		return message;
	}

	private UserNameObject[] getReceiverVO(ArrayList<String> superisor,
			String pk_group) throws BusinessException {
		ArrayList<UserVO> userArr = new ArrayList<UserVO>();
		IUserManageQuery qry = NCLocator.getInstance().lookup(
				IUserManageQuery.class);
		for (String pk : superisor) {
			if (pk.startsWith("[U]")) {
				UserVO receiver = qry.getUser(pk.substring(3));
				userArr.add(receiver);
			} else if (pk.startsWith("[R]")) {
				// 角色分配的所有用户
				UserVO[] reveivers = qry.queryUserByRole(pk.substring(3), null);
				reveivers = UserUtil.filtDisableUsers(reveivers);
				for (int i = 0, end = reveivers == null ? 0 : reveivers.length; i < end; i++) {
					userArr.add(reveivers[i]);
				}
			}
		}
		UserNameObject[] objs = new UserNameObject[userArr.size()];
		for (int i = 0, end = userArr.size(); i < end; i++) {
			objs[i] = new UserNameObject(userArr.get(i).getUser_name());
			objs[i].setUserCode(userArr.get(i).getUser_code());
			objs[i].setUserPK(userArr.get(i).getCuserid());
			objs[i].setPkcorp(pk_group);
		}

		return objs;
	}

	public static WorkflownoteVO queryWorkitemByPK(String pkMsg)
			throws DAOException {
		BaseDAO dao = new BaseDAO();
		return (WorkflownoteVO) dao.retrieveByPK(WorkflownoteVO.class, pkMsg);
	}

	public static WorkflownoteVO[] queryWorkitemArrayByPKs(String[] pk_checkflows)
			throws BusinessException, SQLException {
		if (pk_checkflows == null || pk_checkflows.length == 0)
			return null;
		
		
		final BaseDAO dao = new BaseDAO();
		final List<WorkflownoteVO> noteList = new ArrayList<WorkflownoteVO>();
		
		InSqlBatchCaller caller = new InSqlBatchCaller(pk_checkflows);
		caller.execute(new IInSqlBatchCallBack() {
			
			@Override
			public Object doWithInSql(String inSql) throws BusinessException,
					SQLException {
				Collection<WorkflownoteVO> vos = dao.retrieveByClause(
						WorkflownoteVO.class, "pk_checkflow in " + inSql);
				
				noteList.addAll(vos);
				return null;
			}
		});
		
		return noteList.toArray(new WorkflownoteVO[0]);
	}

	public static void deleteWorknote(WorkflownoteVO noteVO)
			throws BusinessException {
		BaseDAO dao = new BaseDAO();
		dao.deleteVO(noteVO);
		PfMessageUtil.deleteMessagesOfWorknote(new WorkflownoteVO[] { noteVO });
	}

	public static String insertWorknote(WorkflownoteVO noteVO)
			throws BusinessException {
		
//		IBilltypeService billtypeService  =  NCLocator.getInstance().lookup(IBilltypeService.class);
//		
//		BilltypeVO billtypeVo = billtypeService.getRealBilltype(noteVO.getPk_billtype());
		BilltypeVO billtypeVo = PfDataCache.getBillTypeInfo(InvocationInfoProxy.getInstance().getGroupId(),PfUtilBaseTools.getRealBilltype(noteVO.getPk_billtype()));

		BaseDAO dao = new BaseDAO();
		String worknotePK = dao.insertVO(noteVO);
		noteVO.setPk_checkflow(worknotePK);
		//for NCC kejl start 
		if( billtypeVo.getIsLightBill()!=null && billtypeVo.getIsLightBill().booleanValue()){
			String msgSourceType = null;
			String actionType = noteVO.getActiontype();
			WorkflownoteVO[] noteArray =  null;
			if (actionType != null && actionType.startsWith(WorkflownoteVO.WORKITEM_TYPE_BIZ)) {
				// 通知消息发到通知收件箱里
				msgSourceType = WorkflownoteVO.NCMSG_TYPE_PFBIZMSG;
				noteVO.getNcMsg().getMessage().setMsgsourcetype("msgSourceType");
				noteArray = new WorkflownoteVO[1];
				noteArray[0]= noteVO;
				nccloud.bs.pub.pf.PfMessageUtil.sendMessageOfWorknoteBatch("notice",noteArray);//PfMessageUtil.sendMessageOfWorknoteBatch(notes);
			} else {
				// 其它发到工作任务
				msgSourceType = IDefaultMsgConst.WORKLIST;
				noteVO.getNcMsg().getMessage().setMsgsourcetype("worklist");
				noteArray = new WorkflownoteVO[1];
				noteArray[0]= noteVO;
				nccloud.bs.pub.pf.PfMessageUtil.sendMessageOfWorknoteBatch("approve",noteArray);//PfMessageUtil.sendMessageOfWorknoteBatch(notes);
			}
			
			WorkflownoteVO[] workflownotvo = {noteVO};
			
			
		}else{
			PfMessageUtil.sendMessageOfWorknote(noteVO);
		}
		//for NCC kejl end
		return worknotePK;
	}

	public static void insertWorknoteList(List<WorkflownoteVO> noteVOList)
			throws BusinessException {
		BaseDAO dao = new BaseDAO();
		String[] worknotePKs = dao.insertVOList(noteVOList);
		int i = 0;
		for (Iterator iterator = noteVOList.iterator(); iterator.hasNext();) {
			WorkflownoteVO workflownoteVO = (WorkflownoteVO) iterator.next();
			workflownoteVO.setPk_checkflow(worknotePKs[i++]);
		}
		PfMessageUtil.sendMessageOfWorknoteBatch(noteVOList
				.toArray(new WorkflownoteVO[0]));
	}
	
	public static void updateWorknoteBatch(WorkflownoteVO[] worknotes) throws BusinessException{
		BaseDAO dao = new BaseDAO();
		dao.updateVOArray(worknotes);
		PfMessageUtil.deleteMessagesOfWorknote(worknotes);
		PfMessageUtil.sendMessageOfWorknoteBatch(worknotes);
	}
	public static void deleteWorknoteBatch(WorkflownoteVO[] worknotes) throws BusinessException {
		PfMessageUtil.deleteMessagesOfWorknote(worknotes);
		BaseDAO dao = new BaseDAO();
		dao.deleteVOArray(worknotes);
	}

	/**
	 * 判断从数据库中查询所得集合是否是空集
	 * 
	 * @param strs
	 *            集合
	 * @return boolean
	 * */
	private boolean isNullResult(List<String> strs) {
		if (strs == null || strs.size() == 0)
			return true;
		for (String value : strs) {
			if (value != null && value.trim().length() != 0)
				return false;
		}
		return true;
	}

	public WorkflownoteVO[] queryEffectiveWorkitems(String billId,
			String billType, int iStatus, int iWorkflowOrApproveflow)  throws DbException{

		String suffix = MultiLangUtil.getCurrentLangSeqSuffix();
		String mlFiledName = "user_name" + suffix;
		String sql = "select pk_checkflow,pk_wf_task,pk_billtype,billno,actiontype,senderman,"
				+ "checkman,ischeck,checknote,senddate,dealdate,messagenote,receivedeleteflag,observer,c.ts,"
				+ "c.pk_org,billid,billversionpk,a.user_name as sendername,a."
				+ mlFiledName
				+ " as sendernameml,b.user_name as checkname,b."
				+ mlFiledName
				+ " as checknameml,"
				+ "approvestatus,approveresult,c.pk_group,c.workflow_type from pub_workflownote c,sm_user a,sm_user b "
				+ "where c.senderman=a.cuserid and c.checkman=b.cuserid "
				+ "and billversionpk=? and actiontype<>'"
				+ WorkflownoteVO.WORKITEM_TYPE_BIZ
				+ "' "
				// + "and actiontype<>'" + WorkflownoteVO.WORKITEM_TYPE_CHECKMSG
				// + "' "
				+ (billType == null ? "" : "and pk_billtype=?");
				if(iWorkflowOrApproveflow==0){
					
				}else{
					sql = sql+ getWorkflowTypeAndWhere(iWorkflowOrApproveflow);
				}
				
			
		String tempSql = "";
		tempSql = "and approvestatus!=4";
		if (iStatus == 1){
			tempSql = tempSql +" and approveresult is not null";
			}else if(iStatus == 2){
				tempSql =tempSql + " and approveresult is not null and  approvestatus = 1 ";
			}
		
		sql += tempSql + " order by c.senddate, c.dealdate asc,c.dealtimemillis asc";

		PersistenceManager persist = null;
		try {
			persist = PersistenceManager.getInstance();
			JdbcSession jdbc = persist.getJdbcSession();
			SQLParameter para = new SQLParameter();
			para.addParam(billId);
			if (billType != null)
				para.addParam(billType);
			@SuppressWarnings({ "unchecked"})
			List<WorkflownoteVO> noteList = (List<WorkflownoteVO>) jdbc.executeQuery(sql, para,
					new BeanListProcessor(WorkflownoteVO.class));
			return (WorkflownoteVO[]) noteList
					.toArray(new WorkflownoteVO[noteList.size()]);
		} finally {
			if (persist != null)
				persist.release();
		}
	
	}
	
	private String  buildsql(String[] presql) {
		String useridssql = "";
		for(String sql :presql) {
			useridssql = useridssql +"'"+sql+"',";
		}
		useridssql = useridssql.substring(0,useridssql.length()-1);
		return useridssql;
	}


}