欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

用友uap nc65开发-单据联查相关开发

程序员文章站 2022-03-07 23:40:38
...
用友uap nc65开发-单据联查相关开发
1.单据联查:针对有上下游数据单据,通过单据联查使用图形化界面显示该单据上下游。本教程分两部分,上游和下游。
2.前期配置:xml配置对应的按钮,这里指定当前节点的单据类型,id,编码。
<!--======= 动作:[newActions] [联查单据] ===========-->
	<bean id="linkQueryAction" class="nc.ui.pr.pub.linkquery.LinkQueryAction">
		<property name="model"><ref bean="bmModel"/></property>
		<property name="billtype" value="H351"/>
		<property name="billid" value="pk_head"/>
		<property name="billcode" value="vbillno"/>
		<property name="exceptionHandler"><ref bean="exceptionHandler" /></property>
	</bean>
LinkQueryAction支持类如下:
package nc.ui.pr.pub.linkquery;

import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.Action;
import javax.swing.KeyStroke;

import nc.md.data.access.NCObject;
import nc.ui.ml.NCLangRes;
import nc.ui.pubapp.billgraph.RowLinkQueryUtil;
import nc.ui.trade.billgraph.billflow.control.DefaultBillGraphListener;
import nc.ui.trade.billgraph.billflow.control.IBillGraphListener;
import nc.ui.trade.billgraph.billflow.view.BillLinkFlowDlg;
import nc.ui.trade.billgraph.billflow.view.SourceBillFlowDlg;
import nc.ui.uif2.NCAction;
import nc.ui.uif2.ShowStatusBarMsgUtil;
import nc.ui.uif2.UIState;
import nc.ui.uif2.editor.BillForm;
import nc.ui.uif2.editor.BillListView;
import nc.ui.uif2.model.AbstractUIAppModel;
import nc.uif2.annoations.MethodType;
import nc.uif2.annoations.ModelMethod;
import nc.uif2.annoations.ModelType;
import nc.vo.uap.busibean.exception.BusiBeanException;

/**
 * 单据联查Action
 * 
 * @author zenglong
 * 
 */
public class LinkQueryAction extends NCAction {
	
	private static final long serialVersionUID = -604785789980468531L;

	private static final String BILL_FINDER_CLASSNAME = "nc.vo.pr.pub.linkquery.BillTypeSetBillFinder";

	private String billType;

	private BillForm editor;

	private BillListView view;

	private String rowNoKey;

	private AbstractUIAppModel model;

	private IBillGraphListener billGraphListener = null;

	private SourceBillFlowDlg sourceBillFlowDlg = null;
	
	private String billtype;
	private String billid;
	private String billcode;

	public LinkQueryAction() {
		this.setCode("BillLinkQuery");
		// 增加默认监听
		this.billGraphListener = new DefaultBillGraphListener();
		this.setBtnName();
	}

	@Override
	public void doAction(ActionEvent e) throws Exception {
		initUI();
		Object selectedData = LinkQueryAction.this.getModel().getSelectedData();
		NCObject ncObject = NCObject.newInstance(selectedData);
		if(ncObject.getAttributeValue(billid)==null){
			throw new BusiBeanException(billid+"指定的不对,请检查");
		}
		if(ncObject.getAttributeValue(billcode)==null){
			throw new BusiBeanException(billcode+"指定的不对,请检查");
		}
		// 设置参数
		this.sourceBillFlowDlg.setBillType(billtype);
		this.sourceBillFlowDlg.setBillID(ncObject.getAttributeValue(billid).toString());
		this.sourceBillFlowDlg.setBillNO(ncObject.getAttributeValue(billcode).toString());
		this.sourceBillFlowDlg.setNodeCode(getModel().getContext().getNodeCode());

		// 设置监听器
		this.sourceBillFlowDlg.setBillGraphListener(this.billGraphListener);

		// 打开对话框
		if (this.sourceBillFlowDlg.showModal() == -1) {
			ShowStatusBarMsgUtil.showStatusBarMsg(
					NCLangRes.getInstance().getStrByID("uif2",
							"SourceBillFlowDlg-0006")/* 未找到单据联查信息! */, this
							.getModel().getContext());
		}
	}

	protected void initUI() {
		if (this.sourceBillFlowDlg == null) {
			// 初始化对话框
			if (Thread.currentThread().getContextClassLoader() == null)
				Thread.currentThread().setContextClassLoader(
						LinkQueryAction.class.getClassLoader());
			this.sourceBillFlowDlg = new BillLinkFlowDlg(this.model.getContext()
					.getEntranceUI());
			this.sourceBillFlowDlg
			.setBillFinderClassname(LinkQueryAction.BILL_FINDER_CLASSNAME);
		}
	}


	public SourceBillFlowDlg getSourceBillFlowDlg() {
		return sourceBillFlowDlg;
	}

	public String getBillType() {
		return this.billType;
	}

	@ModelMethod(modelType = ModelType.AbstractAppModel, methodType = MethodType.GETTER)
	public AbstractUIAppModel getModel() {
		return this.model;
	}


	public void setBillType(String billType) {
		this.billType = billType;
	}

	@ModelMethod(modelType = ModelType.AbstractAppModel, methodType = MethodType.SETTER)
	public void setModel(AbstractUIAppModel model) {
		this.model = model;
		model.addAppEventListener(this);
	}

	public void setOpenMode(int openMode) {
		// 设置是否权限模式
		if (this.billGraphListener != null
				&& this.billGraphListener instanceof DefaultBillGraphListener) {
			((DefaultBillGraphListener) this.billGraphListener)
					.setOpenMode(openMode);
		}
		this.setBtnName();
	}

	public int getOpenMode() {
		if (this.billGraphListener != null
				&& this.billGraphListener instanceof DefaultBillGraphListener) {
			return ((DefaultBillGraphListener) this.billGraphListener)
					.getOpenMode();
		} else {
			return -1;
		}
	}

	public void setBillGraphListeners(final IBillGraphListener listener) {
		this.billGraphListener = listener;
	}

	public String getRowNoKey() {

		if (rowNoKey == null) {
			rowNoKey = RowLinkQueryUtil.getRowNoKey(getEditor());
		}
		return rowNoKey;
	}

	public void setRowNoKey(String rowNoKey) {
		this.rowNoKey = rowNoKey;
	}

	public BillForm getEditor() {
		return editor;
	}

	public void setEditor(BillForm editor) {
		
		this.editor = editor;
		this.editor.addHeadMouseClicked(this);
	}

	public BillListView getView() {
		return view;
	}

	protected void setBtnName() {
		// 根据权限判断走哪种模式,单据联查还是单据追溯
		if (getOpenMode() == 1) {
			this.setBtnName(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
					.getStrByID("pubapp_0", "0pubapp-0361")/* @res "单据追溯" */);
			this.putValue(Action.SHORT_DESCRIPTION, nc.vo.ml.NCLangRes4VoTransl
					.getNCLangRes().getStrByID("pubapp_0", "0pubapp-0363")/*													 */);
			this.putValue(Action.ACCELERATOR_KEY,
					KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
		} else {
			this.setBtnName(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
					.getStrByID("pubapp_0", "0pubapp-0130")/* @res "联查单据" */);
			this.putValue(Action.SHORT_DESCRIPTION, nc.vo.ml.NCLangRes4VoTransl
					.getNCLangRes().getStrByID("pubapp_0", "0pubapp-0131")/*			 */);
			this.putValue(Action.ACCELERATOR_KEY,
					KeyStroke.getKeyStroke(KeyEvent.VK_K, InputEvent.CTRL_MASK));
		}
	}

	@Override
	protected boolean isActionEnable() {
		return this.model.getUiState() == UIState.NOT_EDIT
				&& this.model.getSelectedData() != null;
	}

	public void setView(BillListView view) {
		this.view = view;
		this.view.addHeadMouseClicked(this);
	}

	public String getBilltype() {
		return billtype;
	}

	public void setBilltype(String billtype) {
		this.billtype = billtype;
	}

	public String getBillid() {
		return billid;
	}

	public void setBillid(String billid) {
		this.billid = billid;
	}

	public String getBillcode() {
		return billcode;
	}

	public void setBillcode(String billcode) {
		this.billcode = billcode;
	}
}
首先指定private static final String BILL_FINDER_CLASSNAME = "nc.vo.pr.pub.linkquery.BillTypeSetBillFinder"; 此类主要是在联查上下游单据做的相关处理。
在doaction中,校验相关信息,后面联查需要。
用友uap nc65开发-单据联查相关开发
3.下游:如图所示:
用友uap nc65开发-单据联查相关开发
找下游单据需要字段
主键 公司 单据编号 类型 交易类型pk(随便) 来源单据(子表)
在按钮类的doAction中
用友uap nc65开发-单据联查相关开发
进入nc.ui.trade.billgraph.billflow.view.SourceBillFlowDlg类(单据联查和行联查对话框 )
进入initData方法中。
用友uap nc65开发-单据联查相关开发
进入
nc.ui.trade.billgraph.billflow.view.BillLinkFlowDlg类中
用友uap nc65开发-单据联查相关开发
进入nc.ui.trade.billgraph.billflow.view.SourceBillFlowDlg类的querySourceBillVO方法。
用友uap nc65开发-单据联查相关开发
this.getBillFinderClassname()方法,在该类定义为全局变量
private String billFinderClassname = "nc.bs.trade.billsource.DefaultBillFinder";
进入nc.bs.trade.billsource.DefaultBillFinder这个类中的findForwardBillsForBillByLayer方法,递归函数,为当前VO合并查找后继单据VO
protected void findForwardBillsForBillByLayer(LightBillVO... bills)
			throws Exception {
		// 查找本层的单据
		Map<String, Map<String, LightBillVO>> billByType = new HashMap<String, Map<String, LightBillVO>>();
		for (LightBillVO billVO : bills) {
			// 设置单据类型和交易类型Name
			this.setBillProperties(billVO);

			if (StringUtils.isEmpty(billVO.getType())
					|| StringUtils.isEmpty(billVO.getID())) {
				continue;
			}

			if (billByType.containsKey(billVO.getType())) {
				billByType.get(billVO.getType()).put(billVO.getID(), billVO);
			} else {
				Map<String, LightBillVO> billsSameType = new HashMap<String, LightBillVO>();
				billsSameType.put(billVO.getID(), billVO);
				billByType.put(billVO.getType(), billsSameType);
			}

		}

		// 获得单据的驱动单据,并且获得单据的单据号
		this.searchForwardBillsByLayer(billByType, null);

		List<LightBillVO> forwardBills = new ArrayList<LightBillVO>();
		for (LightBillVO billVO : bills) {
			LightBillVO[] forwards = billVO.getForwardBillVOs();
			if (forwards != null) {
				for (LightBillVO vo : forwards) {
					forwardBills.add(vo);
				}
			}
		}

		if (forwardBills.size() > 0) {
			findForwardBillsForBillByLayer(forwardBills
					.toArray(new LightBillVO[1]));
		}
	}
用友uap nc65开发-单据联查相关开发
进入到该类的searchForwardBillsByLayer方法中,如图所示:
用友uap nc65开发-单据联查相关开发
获得下游单据类型,如果在此处无法获得,需要在单据类型管理设置下游,
用友uap nc65开发-单据联查相关开发
用友uap nc65开发-单据联查相关开发
在此通过获得的下游单据类型,IBillDataFinder finder = getBillDataFinder(types[i]);找到
/**
	 * 返回具体的单据数据查找器。 该处返回默认的数据查找器。 创建日期:(2004-6-21 20:02:15)
	 * 
	 * @return nc.bs.trade.billsource.IBillDataFinder
	 * @exception java.lang.Exception
	 *                异常说明。
	 */
	private IBillDataFinder getBillDataFinder(String billType) throws Exception {
		if (!this.finderMap.containsKey(billType))
			this.finderMap.put(billType, createBillDataFinder(billType));

		return this.finderMap.get(billType);
	}
这里的createBillDataFinder(billType)方法调用我们在action中设置的BillTypeSetBillFinder类中的createBillDataFinder方法
在重写的BillTypeSetBillFinder类中,我们重写了其中几个需要的节点。
package nc.vo.pr.pub.linkquery;

import nc.bs.pf.pub.PfDataCache;
import nc.bs.trade.billsource.DefaultBillFinder;
import nc.bs.trade.billsource.DefaultDataFinder;
import nc.bs.trade.billsource.IBillDataFinder;
import nc.bs.trade.billsource.NullDataFinder;
import nc.vo.pf.change.PfUtilBaseTools;
import nc.vo.pub.billtype.BilltypeVO;

public class BillTypeSetBillFinder extends DefaultBillFinder {

	@Override
	public IBillDataFinder createBillDataFinder(String billType)
			throws Exception {

		billType = PfUtilBaseTools.getRealBilltype(billType);

		BilltypeVO type = PfDataCache.getBillType(billType);
		if(type == null)
			return  new NullDataFinder();
		IBillDataFinder finder = null;
		// 收款单汇总
		if ("H351".equalsIgnoreCase(billType)) {
			finder = new BillDataFinderForH351();
		} else if ("H350".equalsIgnoreCase(billType)) {// 收款单
			finder = new BillDataFinderForH350();
		} else if ("H345".equalsIgnoreCase(billType)) {// 收费清单
			finder = new BillDataFinderForH345();
		} else if ("H338".equalsIgnoreCase(billType)) {// 财务应收单
			finder = new BillDataFinderForH338();
		} else if ("H318".equalsIgnoreCase(billType)) {// 财务应收单
			finder = new BillDataFinderForH318();
		} else if ("H313".equalsIgnoreCase(billType)) {//合同临时费用单
			finder = new BillDataFinderForH313();
		} else {
			finder = new DefaultDataFinder();
		}
		return finder;
	}
}
我们以收款单为例,如果下游是收款单,我们重写了收款单的DefaultDataFinder类
package nc.vo.pr.pub.linkquery;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import nc.bs.logging.Logger;
import nc.bs.pf.pub.BillTypeCacheKey;
import nc.bs.pf.pub.PfDataCache;
import nc.bs.trade.billsource.DefaultDataFinder;
import nc.bs.trade.billsource.IBillFlow;
import nc.bs.trade.billsource.DefaultDataFinder.BillTypeInfo;
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.BeanListProcessor;
import nc.jdbc.framework.processor.ResultSetProcessor;
import nc.uif.pub.exception.UifRuntimeException;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.pub.BusinessException;
import nc.vo.pub.billtype.BilltypeVO;
import nc.vo.trade.billsource.LightBillVO;

public class BillDataFinderForH350 extends DefaultDataFinder {
	
	
	/**
	 * 当前单据类型,查询来源单据的sql
	 * vsourcebilltype, vsourcebillid 顺序不能改变
	 * @author zhangqiang
	 */
	@Override
	protected String createSQL(String billType) {
		// TODO 自动生成的方法存根
		//收款单
		if("H350".equalsIgnoreCase(billType)){
			String sql="SELECT DISTINCT  vsourcebilltype as vsourcebilltype, vsourcebillid as vsourcebillid FROM fdc_pr_RevfareBody WHERE pk_head=? and isnull(dr,0)=0";
			return sql;
		}
		return super.createSQL(billType);
	}
	@SuppressWarnings( { "serial", "unchecked" })
	public nc.vo.trade.billsource.LightBillVO[] getSourceBills(
			String curBillType, String curBillID) {
		String sql = createSQL(curBillType);
		if (sql == null)
			return null;
		PersistenceManager sessionManager = null;
		try {
			sessionManager = PersistenceManager.getInstance();
			JdbcSession session = sessionManager.getJdbcSession();
			SQLParameter para = new SQLParameter();
			para.addParam(curBillID);

			ResultSetProcessor p = new ResultSetProcessor() {
				@SuppressWarnings("unchecked")
				public Object handleResultSet(ResultSet rs) throws SQLException {
					ArrayList al = new ArrayList();
					while (rs.next()) {
						String type = rs.getString(1);
						String id = rs.getString(2);
						if (type != null && id != null
								&& type.trim().length() > 0
								&& id.trim().length() > 0) {
							LightBillVO svo = new LightBillVO();
							svo.setType(type);
							svo.setID(id);
							al.add(svo);
						}
					}
					return al;
				}
			};
			ArrayList<LightBillVO> result = (ArrayList<LightBillVO>) session
					.executeQuery(sql, para, p);
			if (result.size() == 0)
				return null;
			// 增补上游单据号
			for (LightBillVO vo : result) {
				BillTypeInfo info = getBillCodeAndCorp_V61(vo.getType(), vo.getID());
				if(info != null)
				{
					vo.setCode(info.getCode());
					vo.setCorp(info.getCorp());
					if(info.getBilltype()!=null){
						vo.setType(info.getBilltype());
					}
					vo.setTranstype(info.getTranstype());
					vo.setTranstypepk(info.getTranstypepk());
				}
			}
			return (nc.vo.trade.billsource.LightBillVO[]) result
					.toArray(new nc.vo.trade.billsource.LightBillVO[result
							.size()]);
		} catch (DbException e) {
 			Logger.error(e.getMessage(), e);
			throw new UifRuntimeException(e.getMessage());
		} finally {
			sessionManager.release();
		}
	}
	
	public String[] getForwardBillTypes(LightBillVO vo)	throws BusinessException {
		BilltypeVO billtypevo = PfDataCache.getBillTypeInfo(new BillTypeCacheKey().buildBilltype(vo.getType()));
		if(billtypevo == null)
			return null;
		
		if(billtypevo.getForwardbilltype() == null ){
			return null;
		}
		
		return billtypevo.getForwardbilltype().split(",");
		
	}
	@Override
	@SuppressWarnings( { "unchecked", "serial" })
	public nc.vo.trade.billsource.LightBillVO[] getForwardBills(String srcBillType,
			String curBillType, String... srcBillID) {
		String sql=null;
		if(curBillType.equalsIgnoreCase("H350")){
		 sql= "SELECT DISTINCT  fdc_pr_Revfare.pk_head id, fdc_pr_Revfare.pk_org corp, fdc_pr_Revfare.billno code ,'H350','0001B110000000002H31', B.vsourcebillid sourceID  FROM fdc_pr_Revfare, fdc_pr_RevfareBody B WHERE fdc_pr_Revfare.pk_head=B.pk_head and B.vsourcebillid in('"+srcBillID[0]+"') and fdc_pr_Revfare.dr =0 and B.dr =0";
		}else{
			 sql = createSQL1(curBillType, srcBillID);
		}
		if(sql == null)
			return null;
		
		PersistenceManager sessionManager = null;
		try {
			sessionManager = PersistenceManager.getInstance();
			JdbcSession session = sessionManager.getJdbcSession();
			
			ArrayList result = (ArrayList) session.executeQuery(sql, new BeanListProcessor(LightBillVO.class));
			if (result.size() == 0){
				return null;
			}
			else{
				LightBillVO  lightBillVO  = (LightBillVO) result.get(0); 
				lightBillVO.setType("H350");
				return (LightBillVO[]) result.toArray(new LightBillVO[result.size()]);
			}

		} catch (DbException e) {
			Logger.error(e.getMessage(), e);
			throw new UifRuntimeException("getForwardBills error");
		} finally {
			sessionManager.release();
		}
		
	}
	
	/**
	 * 功能描述:创建查询语句;在该类型的单据中查找某种类型单据的后续单据 
	 * 
	 * 输入参数:String billType,单据类型.
	 * 
	 * 返回值: SQL语句
	 * 
	 * 主表表名、主表主键字段名、主表单据号字段名、子表表名、子表外键字段名、单据来源类型字段名、来源单据ID字段名
	 * @param srcBillID 
	 * 
	 */
	protected String createSQL1(String curBillType, String... srcBillID) {

		IBillFlow billflow = getBillFlow(curBillType);
		if (billflow == null) {
			nc.bs.logging.Logger.error("单据类型:" + curBillType + "没有找到单据流程信息!");
			return null;
		}	
		String hTable = billflow.getMainTableName();
		String hPkField = billflow.getMainTablePrimaryKeyFiled();
		String hPkCorp = billflow.getBillCorp();
		String hBillCodeField = billflow.getBillNOField();
		
		String hBillTypeField = billflow.getBillTypeField();
		String hTransTypeField = billflow.getTransTypeField();
		String hTransTypePkField = billflow.getTransTypePkField();
		
		String bTable = billflow.getSubTableName();
		String bFkField = billflow.getSubTableForeignKeyFiled();
//		String bTableSourceTypeField = billflow.getSourceTypeField();
		String bTableSourceIDField = billflow.getSourceIDField();

		// 如果单据没有来源单据类型字段,则返回空.即如果该类型单据没有标识来源单据
		// 类型,就无法定位它是否是后单据.
		// 通常该情况是:它是某种固定类型单据的后续单据.
		if (bTableSourceIDField == null)
			return null;

		// 在该类型的单据中查找某种类型单据的后续单据
		StringBuffer sb = new StringBuffer("SELECT DISTINCT ");
		sb.append(" ");
		sb.append(hTable + "." + hPkField);
		sb.append(" id, ");
		sb.append(hTable + "." + hPkCorp);
		sb.append(" corp, ");
		sb.append(hTable + "." + hBillCodeField);
		sb.append(" code ");
		
		if(!StringUtil.isEmptyWithTrim(hBillTypeField))
		{
			sb.append( "," + hTable + "." + hBillTypeField);
			sb.append(" type");
		}
		if(!StringUtil.isEmptyWithTrim(hTransTypeField))
		{
			sb.append(", ");
			sb.append(hTable + "." + hTransTypeField);
			sb.append(" transtype ");
		}
		if(!StringUtil.isEmptyWithTrim(hTransTypePkField))
		{
			sb.append(", ");
			sb.append(hTable + "." + hTransTypePkField);
			sb.append(" transtypepk ");
		}
		{
			sb.append(", ");
			if (hTable.equalsIgnoreCase(bTable)) {
				sb.append("B" + "." + bTableSourceIDField);
			} else {
				sb.append(bTable + "." + bTableSourceIDField);
			}
			sb.append(" sourceID ");
		}
		sb.append(" ");
		sb.append("FROM");
		sb.append(" ");
		sb.append(hTable);
		sb.append(", ");
		if (hTable.equalsIgnoreCase(bTable)) {
			sb.append(bTable + " B");
		} else {
			sb.append(bTable);
		}
		sb.append(" ");
		sb.append("WHERE");
		sb.append(" ");
		sb.append(hTable + "." + hPkField);
		sb.append("=");

		if (hTable.equalsIgnoreCase(bTable)) {
			sb.append("B" + "." + bFkField);
		} else {
			sb.append(bTable + "." + bFkField);
		}

		sb.append(" and ");
		if (hTable.equalsIgnoreCase(bTable)) {
			sb.append("B" + "." + bTableSourceIDField);
		} else {
			sb.append(bTable + "." + bTableSourceIDField);
		}
		sb.append(" in(");

	    // 构造来源单据主键参数
	    for (String id : srcBillID) {
	    	sb.append("'");
	    	sb.append(id);
	    	sb.append("'");
	    	sb.append(",");
	    }
	    sb.deleteCharAt(sb.length() - 1);
	    sb.append(")");

//		if (hTableBillTypeField != null) {
//			sb.append(" and ");
//			sb.append(hTable + "." + hTableBillTypeField);
//			sb.append("=?");
//		}

		sb.append(" and ");
		sb.append(hTable + ".dr =0");
		sb.append(" and ");

		if (hTable.equalsIgnoreCase(bTable)) {
			sb.append("B" + ".dr =0");
		} else {
			sb.append(bTable + ".dr =0");
		}
		return sb.toString();
	}
	}
先执行方法public nc.vo.trade.billsource.LightBillVO[] getForwardBills(String srcBillType,String curBillType, String... srcBillID)在这里我们主要重写一句sql
sql= "SELECT DISTINCT  fdc_pr_Revfare.pk_head id, fdc_pr_Revfare.pk_org corp, fdc_pr_Revfare.billno code ,'H350','0001B110000000002H31', B.vsourcebillid sourceID  FROM fdc_pr_Revfare, fdc_pr_RevfareBody B WHERE fdc_pr_Revfare.pk_head=B.pk_head and B.vsourcebillid in('"+srcBillID[0]+"') and fdc_pr_Revfare.dr =0 and B.dr =0";

找下游单据需要字段
主键 公司 单据编号 类型 交易类型pk(随便) 来源单据(子表)
然后执行方法getForwardBillTypes(LightBillVO vo)找收款单下游,如此递归查找。
4.上游:从nc.bs.trade.billsource.DefaultBillFinder类中的findSourceBillsForBill方法开始
/**
	 * 递归函数,为当前VO查找来源单据VO
	 */
	protected void findSourceBillsForBill(LightBillVO bill) throws Exception {
		// 设置单据类型和交易类型Name
		this.setBillProperties(bill);

		// 获得单据的来源单据,并且获得单据的单据号
		this.searchSourceBills(bill, null);

		// 递归调用
		LightBillVO[] sources = bill.getSourceBillVOs();
		for (int i = 0; sources != null && i < sources.length; i++) {
			findSourceBillsForBill(sources[i]);
		}
	}
而后的过程和下游一样,进入DefaultDataFinder类中,先执行createSQL方法,
	/**
	 * 当前单据类型,查询来源单据的sql vsourcebilltype, vsourcebillid 顺序不能改变
	 * 
	 * @author zhangqiang
	 */
	@Override
	protected String createSQL(String billType) {
		// TODO 自动生成的方法存根
		// 收费清单
		if ("H345".equalsIgnoreCase(billType)) {
			String sql = "SELECT DISTINCT  vsourcebilltype as vsourcebilltype, vsourcebillid as vsourcebillid FROM fdc_pr_Bill WHERE pk_head=? and isnull(dr,0)=0";
			return sql;
		}
		return super.createSQL(billType);
	}
然后再掉用getSourceBills方法找收费清单的上游。如此递归。

如图所示:
用友uap nc65开发-单据联查相关开发
问题总结:

1.联查后未带出单据号,如图所示:

用友uap nc65开发-单据联查相关开发

原因是在联查上游的时候,对应的单据类型没有设置进去,需要对BillDataFinderForH350类下的 getSourceBills方法重写下:

@SuppressWarnings({ "serial", "unchecked" })
	public nc.vo.trade.billsource.LightBillVO[] getSourceBills(
			String curBillType, String curBillID) {
		String sql = createSQL(curBillType);
		if (sql == null)
			return null;
		PersistenceManager sessionManager = null;
		try {
			sessionManager = PersistenceManager.getInstance();
			JdbcSession session = sessionManager.getJdbcSession();
			SQLParameter para = new SQLParameter();
			para.addParam(curBillID);

			ResultSetProcessor p = new ResultSetProcessor() {
				@SuppressWarnings("unchecked")
				public Object handleResultSet(ResultSet rs) throws SQLException {
					ArrayList al = new ArrayList();
					while (rs.next()) {
						String type = rs.getString(1);
						String id = rs.getString(2);
						if (type != null && id != null
								&& type.trim().length() > 0
								&& id.trim().length() > 0) {
							LightBillVO svo = new LightBillVO();
							svo.setType(type);
							svo.setID(id);
							al.add(svo);
						}
					}
					return al;
				}
			};
			ArrayList<LightBillVO> result = (ArrayList<LightBillVO>) session
					.executeQuery(sql, para, p);
			if (result.size() == 0)
				return null;
			// 增补上游单据号
			for (LightBillVO vo : result) {
				BillTypeInfo info = getBillCodeAndCorp_V61(vo.getType(),
						vo.getID());
				if (info != null) {
					vo.setCode(info.getCode());
					vo.setCorp(info.getCorp());
					if (info.getBilltype() != null) {
						vo.setType(info.getBilltype());
					}
					vo.setTranstype(info.getTranstype());
					vo.setTranstypepk(info.getTranstypepk());
				}
			}
			return (nc.vo.trade.billsource.LightBillVO[]) result
					.toArray(new nc.vo.trade.billsource.LightBillVO[result
							.size()]);
		} catch (DbException e) {
			Logger.error(e.getMessage(), e);
			throw new UifRuntimeException(e.getMessage());
		} finally {
			sessionManager.release();
		}
	}

2.说明点:

对于收费清单    联查上游的时候会找自己的createSQL方法,联查下游的时候会找下游的getForwardBills方法