用友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中,校验相关信息,后面联查需要。



用友NC65是什么架构 用友nc65教学课程_用友NC65是什么架构



3.下游:如图所示:



用友NC65是什么架构 用友nc65教学课程_java_02




找下游单据需要字段


主键 公司 单据编号 类型 交易类型pk(随便) 来源单据(子表)


在按钮类的doAction中


用友NC65是什么架构 用友nc65教学课程_数据_03


进入nc.ui.trade.billgraph.billflow.view.SourceBillFlowDlg类(单据联查和行联查对话框 )

进入initData方法中。

用友NC65是什么架构 用友nc65教学课程_用友NC65是什么架构_04


进入nc.ui.trade.billgraph.billflow.view.BillLinkFlowDlg类中

用友NC65是什么架构 用友nc65教学课程_ide_05


进入nc.ui.trade.billgraph.billflow.view.SourceBillFlowDlg类的querySourceBillVO方法。


用友NC65是什么架构 用友nc65教学课程_java_06


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]));
		}
	}


用友NC65是什么架构 用友nc65教学课程_ide_07


进入到该类的searchForwardBillsByLayer方法中,如图所示:

用友NC65是什么架构 用友nc65教学课程_数据_08



获得下游单据类型,如果在此处无法获得,需要在单据类型管理设置下游,


用友NC65是什么架构 用友nc65教学课程_ide_09


用友NC65是什么架构 用友nc65教学课程_java_10


在此通过获得的下游单据类型,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方法找收费清单的上游。如此递归。


如图所示:


用友NC65是什么架构 用友nc65教学课程_java_11


问题总结:


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

用友NC65是什么架构 用友nc65教学课程_用友NC65是什么架构_12

原因是在联查上游的时候,对应的单据类型没有设置进去,需要对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方法