具体的可以参照红皮书,以下只是根据我平时项目遇到的着重做一下总结。
一、开发:
利用前台插件开发的:
1、注册:pfxx\auxiregister\jzpub.xml
<?xml version="1.0" encoding='gb2312'?>
<auxiregister>
<billtype editable="Yes" id="H550">
</billtype>
</auxiregister>
\pfxx\businessprocessor\jzpub.xml
<?xml version="1.0" encoding='gb2312'?>
<businessprocessors>
<businessprocessor baseclassname="" billtype="H550" classname="nc.bs.pfxx.plugins.PrPayPlanPlugin" locklevel="3" metadataid="e8bcfb91-8bfa-4a76-b11f-08e22db60fe9" name="H550">
</businessprocessor>
</businessprocessors>
2、定义字段规则:pfxx\billdefine\jzpub\H550_MY.xml
3、定义报文规范:H550.xml
4、编写代码:modules\jzpub\META-INF\classes\nc\bs\pfxx\plugins\PrPayPlanPlugin.java
package nc.bs.pfxx.plugins;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Logger;
import nc.itf.jzpm.jzpr8005.IPrPayPlanMaintain;
import nc.itf.jzpm.jzpr8005.IPrPayPlanQuery;
import nc.itf.uap.pf.IPFBusiAction;
import nc.itf.uap.pfxx.IPFxxEJBService;
import nc.pubitf.cmp.changebill.ICmpChangeBillPubService;
import nc.pubitf.cmp.paybill.ICmpPayBillPubService;
import nc.pubitf.cmp.recbill.ICmpRecBillPubService;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.pfxx.util.FileUtils;
import nc.vo.pfxx.util.PfxxPluginUtils;
import nc.bs.pfxx.ISwapContext;
import nc.vo.pfxx.auxiliary.AggxsysregisterVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.ISuperVO;
import nc.vo.pub.SuperVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.cmp.bill.BillAggVO;
import nc.vo.cmp.bill.ChangeBillAggVO;
import nc.vo.cmp.bill.RecBillAggVO;
import nc.vo.jzpm.jzpr8005.AggPrPayPlanVO;
import nc.vo.jzpm.jzpr8005.PrPayPlanAccVO;
import nc.vo.jzpm.jzpr8005.PrPayPlanOthVO;
import nc.vo.jzpm.jzpr8005.PrPayPlanPettyVO;
import nc.vo.jzpm.jzpr8005.PrPayPlanSettleVO;
import nc.vo.jzpm.jzpr8005.PrPayPlanVO;
/**
* <b> 在此处简要描述此类的功能 </b>
*
* <p>
* 在此处添加此类的描述信息
* </p>
*
* @author xueyl
* @version Your Project V60
*/
public class PrPayPlanPlugin extends nc.bs.pfxx.plugin.AbstractPfxxPlugin {
/**
* 将由XML转换过来的VO导入NC系统。业务插件实现此方法即可。<br>
* 请注意,业务方法的校验一定要充分
* 仅限表体零星费用。其他表体没测试
* @param vo
* 转换后的vo数据,在NC系统中可能为ValueObject,SuperVO,AggregatedValueObject,IExAggVO等。
* @param swapContext
* 各种交换参数,组织,接受方,发送方,帐套等等
* @param aggxsysvo
* 辅助信息vo
* @return
* @throws BusinessException
*/
protected Object processBill(Object vo, ISwapContext swapContext, AggxsysregisterVO aggxsysvo) throws BusinessException {
//1.得到转换后的VO数据,取决于向导第一步注册的VO信息
AggPrPayPlanVO resvo = (AggPrPayPlanVO)vo;
Map<String, SuperVO[]> map = resvo.getAllChildrenMap();
if(null != map ){
PrPayPlanPettyVO[] pettys=null;
PrPayPlanOthVO[] oths=null;
PrPayPlanSettleVO[] settles=null;
PrPayPlanAccVO[] accs=null;
List<String> pklist=new ArrayList<String>();
for (String key : map.keySet()) {
pklist.add(key);
}
Map<String,PrPayPlanAccVO> accmap=new HashMap<String,PrPayPlanAccVO>();
if(pklist.contains("pk_payplan_acc")){
if(0<map.get("pk_payplan_acc").length){
accs=(PrPayPlanAccVO[]) map.get("pk_payplan_acc");
for (PrPayPlanAccVO accvo : accs) {
accmap.put(accvo.getVbdef1(), accvo);
}
}
}
if(pklist.contains("pk_payplan_petty")){
if(0<map.get("pk_payplan_petty").length){
pettys=(PrPayPlanPettyVO[]) map.get("pk_payplan_petty");
for (PrPayPlanPettyVO petty : pettys) {
for (String key : accmap.keySet()) {
if(key.equals(petty.getVbdef1())){
petty.setBisnewline(UFBoolean.TRUE);
petty.setGrandsonVO(new PrPayPlanAccVO[]{accmap.get(key)});
}
}
}
}
resvo.setChildren(PrPayPlanPettyVO.class, pettys);
}else{
resvo.setChildren(PrPayPlanPettyVO.class, new PrPayPlanPettyVO[]{});
}
if(pklist.contains("pk_payplan_settle")){
if(0<map.get("pk_payplan_settle").length){
settles=(PrPayPlanSettleVO[]) map.get("pk_payplan_settle");
resvo.setChildren(PrPayPlanSettleVO.class, settles);
}
}else{
resvo.setChildren(PrPayPlanSettleVO.class, new PrPayPlanSettleVO[]{});
}
if(pklist.contains("pk_payplan_oth")){
if(0<map.get("pk_payplan_oth").length){
oths=(PrPayPlanOthVO[]) map.get("pk_payplan_oth");
resvo.setChildren(PrPayPlanOthVO.class, oths);
}
}else{
resvo.setChildren(PrPayPlanOthVO.class, new PrPayPlanOthVO[]{});
}
}
resvo.setChildren( PrPayPlanAccVO.class,new PrPayPlanAccVO[]{});
resvo.getAllChildrenMap().clear();
//2.查询此单据是否已经被导入过,有两个方法,具体使用哪一个请参考方法说明javadoc
String vopk = PfxxPluginUtils.queryBillPKBeforeSaveOrUpdate(swapContext.getBilltype(), swapContext.getDocID());
//3. 如果单据设置有辅助信息,aggxsysvo为用户配置的具体辅助信息
//4.如果此单据没有导入过,那么准备保存新单据,保存单据前请进行必要的数据检查,并给出明确的业务异常...
IPrPayPlanQuery lookup = NCLocator.getInstance().lookup(IPrPayPlanQuery.class);
if (vopk != null) {
Logger.info("如果单据已经导入过则进行单据更新...");
if (swapContext.getReplace().equalsIgnoreCase("N")) {
throw new BusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("3607mng_0", "03607mng-0359"));
}
AggPrPayPlanVO[] oldaggvo = lookup.queryBillByPK(new String[]{vopk});
PrPayPlanPettyVO[] oldpettys = (PrPayPlanPettyVO[]) oldaggvo[0].getChildren(PrPayPlanPettyVO.class);
PrPayPlanAccVO[] oldaccs= (PrPayPlanAccVO[]) oldaggvo[0].getChildren(PrPayPlanAccVO.class);
Map<String,PrPayPlanAccVO> oldaccmap=new HashMap<String,PrPayPlanAccVO>();
for (PrPayPlanAccVO oldacc : oldaccs) {
oldaccmap.put(oldacc.getVbdef1(), oldacc);
}
for (PrPayPlanPettyVO oldpetty : oldpettys) {
for (String key : oldaccmap.keySet()) {
if(key.equals(oldpetty.getVbdef1())){
oldpetty.setGrandsonVO(new PrPayPlanAccVO[]{oldaccmap.get(key)});
}
}
}
//根据老数据为新的数据赋值-------start---------
resvo.getParentVO().setBhasbeyondrecord(UFBoolean.FALSE);
resvo.getParentVO().setStatus(1);
resvo.getParentVO().setPk_payplan(oldaggvo[0].getParentVO().getPk_payplan());
resvo.getParentVO().setVbillcode(oldaggvo[0].getParentVO().getVbillcode());
PrPayPlanPettyVO[] newpettys = (PrPayPlanPettyVO[]) resvo.getChildren(PrPayPlanPettyVO.class);
List<PrPayPlanAccVO> acclist=new ArrayList<PrPayPlanAccVO>();
for (PrPayPlanPettyVO newpetty : newpettys) {
newpetty.setStatus(1);
newpetty.setBisnewline(UFBoolean.FALSE);
newpetty.setTs(new UFDateTime());
newpetty.setPk_payplan(oldaggvo[0].getParentVO().getPk_payplan());
for (String key : oldaccmap.keySet()) {
if(key.equals(newpetty.getVbdef1())){
PrPayPlanAccVO oldacc = oldaccmap.get(key);
newpetty.setPk_payplan_petty(oldacc.getPk_payplan_b());
PrPayPlanAccVO[] newaccs = (PrPayPlanAccVO[])newpetty.getGrandsonVO();
for (PrPayPlanAccVO prPayPlanAccVO : newaccs) {
prPayPlanAccVO.setPk_payplan(oldacc.getPk_payplan());
prPayPlanAccVO.setPk_payplan_b(oldacc.getPk_payplan_b());
prPayPlanAccVO.setPk_payplan_acc(oldacc.getPk_payplan_acc());
prPayPlanAccVO.setTs(new UFDateTime());
prPayPlanAccVO.setStatus(0);
}
}
}
PrPayPlanAccVO[] newaccs = (PrPayPlanAccVO[]) newpetty.getGrandsonVO();
for (PrPayPlanAccVO prPayPlanAccVO : newaccs) {
acclist.add(prPayPlanAccVO);
}
}
//根据老数据为新的数据赋值-------end---------
PrPayPlanAccVO[] array = new PrPayPlanAccVO[acclist.size()];
for (int i = 0; i < acclist.size(); i++) {
array[i]=acclist.get(i);
}
resvo.setChildren(PrPayPlanAccVO.class,array);
AggPrPayPlanVO[] vos = ((IPrPayPlanMaintain)NCLocator.getInstance().lookup(IPrPayPlanMaintain.class)).update(new AggPrPayPlanVO[] { resvo},oldaggvo);
vopk = vos[0].getPrimaryKey();
// throw new BusinessException("目前此单据不支持更新");
} else {
Logger.info("如果此单据没有导入过,保存新单据...");
PrPayPlanVO parentVO = resvo.getParentVO();
AggPrPayPlanVO[] vos = ((IPrPayPlanMaintain)NCLocator.getInstance().lookup(IPrPayPlanMaintain.class)).insert(new AggPrPayPlanVO[] { resvo});
vopk = vos[0].getPrimaryKey();
//提交并启动审批流
AggPrPayPlanVO[] newaggvo = lookup.queryBillByPK(new String[]{vopk});
IPFBusiAction ipf = (IPFBusiAction)NCLocator.getInstance().lookup(IPFBusiAction.class);
AggPrPayPlanVO[] processAction = (AggPrPayPlanVO[]) ipf.processAction("SAVE", "H550", null,newaggvo[0], null, null);//动作,单据类型,null,vo,null,null
//6.如果希望单据将来可以更新,请调用下列接口插入文档流水号与生成PK的对照关系
// 第2步查询对照关系相对应,也有两个个方法,具体请看javadoc
//1)PfxxPluginUtils.addDocIDVsPKContrast(swapContext.getBilltype(),swapContext.getDocID(),pk);
//2)PfxxPluginUtils.addDocIDVsPKContrast(swapContext.getBilltype(),swapContext.getDocID(),swapContext.getOrgPk(),pk);
PfxxPluginUtils.addDocIDVsPKContrast(swapContext.getBilltype(), swapContext.getDocID(), vopk);
}
//7.准备返回值,此函数的返回值,最终会以字符串的形式返回给外系统,
// 对于普通单据可以返回NC系统生成的PK值,对于凭证可能返回凭证号,具体视单据而定
// 对于查询插件要求返回org.w3c.dom.Node[]数组 或者org.w3c.dom.Node
return vopk;
}
}
二、联调测试:
涉及的类:
nc.bs.cmp.pfxx.CMPPlugin
nc.bs.bd.pfxx.translator.AccessorTranslator
nc.vo.pfxx.util.PfxxPluginUtils
报文说明:
<?xml version="1.0" encoding='UTF-8'?>
<!-- billtype属性,单据类型 isexchange属性是否使用信息交换平台提供的翻译转换和校验功能
replace属性表示该文档已经正确的受到过并正确 处理过时是否进行覆盖处理
operator属性指定当前发送方对应的nc操作员pk sender属性外系统编码,4位长 -->
<ufinterface billtype="supplier" isexchange="Y" replace="Y" proc="delete" sender="001" operator="1001B110000000000016">
<!--id 数据唯一值,第一次新增,第二次可更新,字符或数字,不能超过30位-->
<bill id="113123">
<billhead>
<!--供应商编号,最大长度为40,类型为:String-->
<code>113123</code>
<!--供应商名称,最大长度为200,类型为:String-->
<name>224123</name>
<!--纳税人识别号,最大长度为20,类型为:String-->
<taxpayerid>22222123</taxpayerid>
<!--供应商基本分类,最大长度为20,类型为:String-->
<pk_supplierclass>0101</pk_supplierclass>
</billhead>
</bill>
</ufinterface>
涉及的表:
//辅助信息详细信息
select * from NC65ZS.XX_AUXIREGISTER;
//基础数据对照
select * from NC65ZS.XX_BDCONTRA;
//基础数据详细对照
select * FROM NC65ZS.XX_BDCONTRA_B;
//外部 系统信息
select * from NC65ZS.XX_EXSYSTEM;
//基础档案翻译器信息
select * from NC65ZS.XX_EXSYSTEMDOC;
//id对照表
select * from NC65ZS.XX_IDCONTRAST;
//翻译器
select * from NC65ZS.XX_TRANSLATOR where XX_TRANSLATOR.PK_TRANSLATOR='1001Z01000000000R5MN';
//详细日志
select * from NC65ZS.XX_XLOG;
//辅助信息基本信息
select * from NC65ZS.XX_XSYSREGISTER;