低代码单据适配生成凭证及凭证联查
声明:本文章转载ncc论坛如有账号直接访问 谢谢 原文章链接
1、元数据及代码定制
元数据特性需要勾选单据特性、审批流特性,以便代码定制时可以勾选审批流的功能特性。元数据可以根据其他需求添加字段并勾选其他特性。
代码定制需要勾选审批流插件填写单据类型,以便生成代码时会预置单据类型,同时方便后续生成凭证时的适配。其他功能插件可以根据需要勾选即可。
2、开发适配
2.1 应用注册模块支持发送会计平台
找到小应用所属模块层级,即编码为4位的层级。需要设置发送会计平台为“是”。
2.2 单据类型
找到自己的单据类型,修改是否发送会计平台设置为“是”并保存。如下图所示。
2.3 平台设置
点击对应单据类型,系统会自动注册对应集团级数据。对应表为fip_config。(一般需要往数据库表里面注册pk_group为GLOBLE00000000000000的数据,不注册也不影响后续流程)
默认生成总账凭证。平台配置是按单据类型或交易类型进行配置,只有选取了具体的单据类型或者交易类型后,才能进行配置操作。
支持对单据类型和交易类型进行设置,如果没有交易类型,将适用单据类型设置,如果有交易类型且进行了设置,则适用该交易类型设置,单据类型的设置不再适用(明
细优先的原则)。
2.4 元数据过滤管理
登录系统管理员,打开节点【元数据过滤管理】节点,业务场景选择会计平台,对应表为md_attr_power。左侧元数据选中自己的元数据实体。右侧需要哪些属性需要与需求进行沟通。这里勾选的属性在配置转换模板元数据属性页签下显示相应属性,例如如果需要利润中心的编码、名称则应该勾选保存,在对应公式编辑器可以选择利润中心的编码名称。
2.5 单据项目
打开单据项目节点,左侧选择自己的单据类型,然后点击右上角自动注册按钮,如要改单据基础名称,点击修改即可。这里注册的单据项目,会影响转换模板配置时公式编辑器单据项目页签。对应表为fip_billitem。
2.6 影响因素定义
影响因素定义是定义各业务模块在入账设置和分类定义中引用的影响因素。按业务模块设置影响因素及其对应的基础档案类型。对应表名:表名fip_factor
2.7 分类定义
业务系统的单据生成总账凭证、成本凭证、责任凭证时,由于单据是描述原始业务的发生情况,并不按照会计要求记录科目或责任要素信息,此时就需要做转换,即根据会计科目或核算要素的核算内容,找出单据上字段的对应关系,并作为对照表记录下来,在生成凭证时根据单据上的相应字段内容按对应关系找到适配的会计科目或核算要素。凡是在由业务单据生成凭证时可能用到的入账科目或要素,均应该归类,并在这里进行定义。对应的表名:fip_classdefine
2.8 转换模板配置
转换模板定义的是凭证模版,它是对应到单据和业务处理过程的会计描述,是单据及业务处理生成凭证的依据和出发点。凭证模板通过指定单据项与凭证字段之间的对应关系完成凭证分录结构的描述。所以能否正确生成凭证关键点就在于转换模板的配置。
2.9 单据类型服务注册
需要往FIP_BILLREGISTER插入一条数据,需要在billreflectclass注册单据查询类,该类需要实现nc.pubitf.fip.external.IBillReflectorService;previewvoucherclass对应凭证预览处理类,这个在后面联查预览凭证时需要用到。linksrcbillclass参考4.2.1 小节凭证联查单据。
FIP_BILLREGISTER示例:
INSERT INTO FIP_BILLREGISTER (BILLDRAWCLASS, BILLREFLECTCLASS, BILLSUMCLASS, CLASS_ENTITY_ID, CTRLORGFINDCLASS, DEFDOC1, DEFDOC2, DEFDOC3, DEFQUERYCLASS, DESBILLSERVCLASS, DESBILLSUMCLASS, DESCTRLRULECLASS, DESSUMRULECLASS, DESSUMRULEENTITY, DESSUMRULEREF, DISPLAYCLASS, DR, DRAWQUERYCLASS, DRAWQUERYPANEL, EDITCLASS, LINKQUERYCLASS, LINKSRCBILLCLASS, MODULECODE, ORG_CTRL_ENTITY1, ORG_CTRL_ENTITY2, ORG_ENTITY_ID, PK_BILLREGISTER, PK_BILLTYPE, PK_GROUP, PK_ORG, PREVIEWVOUCHERCLASS, QUERYCONDITIONCLASS, TS, VOUCHERDATAPROCESSCLASS, WEBCOMPONENT) VALUES (null, 'nc.impl.arap.promotion_fee.promotion_feemaster.TGFYTReflectorServiceImpl', null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0, null, null, null, null, null, 'arap', null, null, null, '0000AA00000000000009', 'TGFYT', null, null, 'nc.impl.arap.promotion_fee.promotion_feemaster.BillLinkVoucharQuery', null, '2022-07-22 23:26:33', null, null);
其中TGFYTReflectorServiceImpl.java示例代码:
package nc.impl.arap.promotion_fee.promotion_feemaster;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import nc.bs.framework.common.NCLocator;
import nc.itf.arap.promotion_fee.promotion_feemaster.IPromotion_feeMasterVOService;
import nc.pubitf.fip.external.IBillReflectorService;
import nc.vo.arap.promotion_fee.AggPromotion_feeMasterVO;
import nc.vo.fip.external.FipExtendAggVO;
import nc.vo.fip.service.FipRelationInfoVO;
import nc.vo.pub.BusinessException;
/**
* 会计平台 查询推广费预提单据
*/
public class TGFYTReflectorServiceImpl implements IBillReflectorService {
@Override
public Collection<FipExtendAggVO> queryBillByRelations(Collection<FipRelationInfoVO> relationvos)
throws BusinessException {
List<String> pks = relationvos.stream().map(item -> item.getRelationID()).collect(Collectors.toList());
if (pks.size() == 0) {
throw new BusinessException("目标单据不存在!");
}
AggPromotion_feeMasterVO[] billVos = NCLocator.getInstance().lookup(IPromotion_feeMasterVOService.class)
.listAggPromotion_feeMasterVOByPk(pks.toArray(new String[0]));
if (billVos == null || billVos.length == 0) {
throw new BusinessException("目标单据不存在!");
}
List<FipExtendAggVO> ret = new ArrayList<FipExtendAggVO>();
for (AggPromotion_feeMasterVO vo : billVos) {
FipExtendAggVO fipExt = new FipExtendAggVO();
fipExt.setBillVO(vo);
fipExt.setRelationID(vo.getPrimaryKey());
ret.add(fipExt);
}
return ret;
}
}
2.10 调用接口自动生成凭证
在审批通过后调用IFipMessageService向会计平台推送消息生成凭证。如果是审批通过则设置messagetype为FipMessageVO.MESSAGETYPE_ADD标识生成动作,如果取消审批时messagetype为FipMessageVO.MESSAGETYPE_DEL标识删除生成的凭证。如下为向会计平台推送消息代码。
private void generateVoucher(List<AggPromotion_feeMasterVO> vos,int messagetype) throws nc.vo.pub.BusinessException {
if(vos==null ||vos.size()==0) {
return;
}
List<FipMessageVO> sendList = new ArrayList<>();
for(AggPromotion_feeMasterVO aggvo:vos) {
Promotion_feeMasterVO headvo = aggvo.getParentVO();
FipRelationInfoVO reVO = new FipRelationInfoVO();
reVO.setPk_group(headvo.getPk_group());// 集团
reVO.setPk_org(headvo.getPk_org());// 组织
reVO.setRelationID(headvo.getPrimaryKey());// 关联号,和单据之间的唯一关联,通过该字段唯一对应一个传入的聚合VO
reVO.setPk_system("AR");// 系统类型
reVO.setBusidate(headvo.getBusidate());// 业务日期,业务生效的日期,不一定是单据日期
reVO.setPk_billtype(headvo.getBilltype());// 单据类型或交易类型PK
reVO.setPk_operator(InvocationInfoProxy.getInstance().getUserId());// 操作员PK,指的是发送会计平台的那个人,不是单据的制单人
reVO.setFreedef1(headvo.getCode());//billcode,单据号
reVO.setFreedef2(headvo.getDigest());// 说明/摘要
reVO.setFreedef3(headvo.getPromotionmoney().toString());//费用金额
FipMessageVO messageVO = new FipMessageVO();
messageVO.setBillVO(aggvo);
messageVO.setMessagetype(messagetype);
messageVO.setMessageinfo(reVO);
sendList.add(messageVO);
}
// 发送到会计平台
NCLocator.getInstance().lookup(IFipMessageService.class).sendMessages(sendList.toArray(new FipMessageVO[0]));
}
在生成的XXXMasterVOServiceImpl类找到callbackAPPROVE和callbackUNAPPROVE方法,修改如下:
@Override
public AggPromotion_feeMasterVO[] callbackAPPROVE(AggPromotion_feeMasterVO...vos) throws BusinessException{
if(ArrayUtils.isEmpty(vos)) {
return null;
}
List<AggPromotion_feeMasterVO> approved = Arrays.stream(vos)
.filter(agg->agg.getParentVO().getApprovestatus()==BillStatusEnum.APPROVED.toIntValue())
.collect(Collectors.toList());
generateVoucher(approved,FipMessageVO.MESSAGETYPE_ADD);
return this.saveAggPromotion_feeMasterVO(vos);
}
@Override
public AggPromotion_feeMasterVO[] callbackUNAPPROVE(AggPromotion_feeMasterVO...vos) throws BusinessException{
if(ArrayUtils.isEmpty(vos)) {
return null;
}
generateVoucher(Arrays.asList(vos),FipMessageVO.MESSAGETYPE_DEL);
return this.saveAggPromotion_feeMasterVO(vos);
}
2.11 验证生成凭证
做完以上适配步骤后,到会计平台的日志追踪节点,可以验证是否已经记录日志。如果有对应单据类型日志说明以上适配步骤已经生效。
在凭证及单据生成节点可以查看所有单据生成的凭证及凭证处理状态。如下图所示:
3 制单
转换模板配置如果设置的产生临时凭证,则审批通过后先产生临时凭证,然后通过制单功能人工干预,再生成正式凭证。制单功能需要注册按钮并实现按钮相应功能。到应用注册找到自己注册的模板,注册制单按钮,按钮区域为common。
在前端onBtnClickHead按钮点击处理,添加制单时的处理代码。
onBtnClickHead = (props, btnCode, param = {}) => {
switch (btnCode) {
………//省略部分代码
case ACTIONS.MAKEBILL:
this.makeBill();
break;
default:
break;
}
}
如下是makeBill处理代码,其中需要用到缓存工具cacheTools 引入方式:import { cacheTools } from ‘nc-lightapp-front’;
/** 制单处理 */
makeBill=()=>{
// 获取选中行
let checkedDatas = this.getCheckedDatas();
if (!checkedDatas) { // 无选中行
toast({color: 'warning', content: '请选择操作数据!'});
return;
}
let appcode = this.props.getSearchParam("c");
let pk = checkedDatas[0].values[FIELDS.PRIMARYKEY].value;
ajax({
url: '/nccloud/arap/promotion_fee/MakBillAction.do',
data: {pk},
success: (res) => {
if (!res||!res.success) {
return ;
}
//打开结算制单节点
cacheTools.set(appcode + res.data.cachekey, res.data.pklist);
this.props.openTo(res.data.url,
{
status: 'edit',
n: '凭证生成',
appcode: res.data.appcode,
pagecode: res.data.pagecode,
scene: appcode + res.data.cachekey
});
}
});
}
后台需要新增MakBillAction,同时添加action.xml、鉴权配置。
package nccloud.web.arap.promotion_fee.promotion_feemaster.action;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.container.IRequest;
import nccloud.web.codeplatform.framework.action.base.BaseAction;
import nccloud.web.codeplatform.framework.action.base.RequestDTO;
import nccloud.web.codeplatform.framework.action.base.RequstParamWapper;
import nccloud.web.codeplatform.framework.action.base.VOTransform;
import java.util.Map;
import nc.itf.fip.opreatinglog.IGenerateBillService;
import nccloud.commons.lang.StringUtils;
public class MakBillAction extends BaseAction{
@Override
public Object doAction(IRequest request, RequstParamWapper paramWapper) throws Throwable {
RequestDTO param = VOTransform.toVO(paramWapper.requestString,RequestDTO.class);
String pk = param.getPk();
if(StringUtils.isEmpty(pk)) {
return null;
}
String[][] data = { {"TGFYT",pk} };
Map<String, Object> map = ServiceLocator.find(IGenerateBillService.class).getAppInfoMap(data);
return map;
}
}
做完以上适配后,当点击制单功能时会跳转到凭证维护,用户根据需要进行调整保存生成正式凭证。
4 凭证联查及预览适配
4.1 单据联查凭证
到应用注册单据模板注册按钮:按钮编码linkvoucher,父按钮编码BillTrack_Group,按钮区域common。
前端适配onBtnClickHead添加按钮处理,如下所示:
onBtnClickHead = (props, btnCode, param = {}) => {
switch (btnCode) {
………//省略部分代码
case ACTIONS.LINKVOUCHER: //联查凭证
this.linkVoucher();
break;
default:
break;
}
}
如下是linkVoucher处理代码,其中需要用到缓存工具cacheTools 引入方式:import { cacheTools } from ‘nc-lightapp-front’; 如果返回"_LinkVouchar2019"标识走联查场景,如果返回"_Preview2019"表示当前业务单据还未生成凭证,不能联查,走预览场景(注意:如果单据的业务逻辑不支持凭证预览,当返回的src值为"_Preview2019"时,需要自行给出错误提示)
linkVoucher=()=>{
// 获取选中行
let checkedDatas = this.getCheckedDatas();
if (!checkedDatas) { // 无选中行
toast({color: 'warning', content: '请选择操作数据!'});
return;
}
let appcode = this.props.getSearchParam("c");
let pk = checkedDatas[0].values[FIELDS.PRIMARYKEY].value;
let pk_org = checkedDatas[0].values[FIELDS.PK_ORG].value;
let pk_group = checkedDatas[0].values['pk_group'].value;
let busidate = checkedDatas[0].values['busidate'].value;
let transtype = checkedDatas[0].values[FIELDS.TRANSTYPE].value;
//拼接预览数据
let viewData = {
messagevo: [
{
pk_system: 'AR', //系统编码
relationid: pk, //单据主键
busidate: busidate, //单据日期
pk_org: pk_org, //组织主键
pk_group: pk_group, //集团主键
pk_billtype: !transtype ? 'TGFYT' : transtype//交易类型或单据类型
}
], //支持多笔预览
desbilltype: ['C0'], //目标单据类型,C0为总账凭证
srcbilltype: !transtype ? 'TGFYT' : transtype //业务组交易类型
};
ajax({
url: '/nccloud/arap/promotion_fee/BillLinkVoucherAction.do',
data: {pk},
success: (res) => {
if(!res||!res.success){
return ;
}
let srcCode = res.data.src;
if ('_LinkVouchar2019' == srcCode) {
//走联查
if (res.data.des) {
//跳转到凭证界面
if (res.data.pklist) {
if (res.data.pklist.length == 1) {
//单笔联查
this.props.openTo(res.data.url, {
status: 'browse',
appcode: res.data.appcode,
pagecode: res.data.pagecode,
id: res.data.pklist[0],
n: '联查凭证',
backflag: 'noback'
});
return;
} else {
//多笔联查
cacheTools.set(res.data.cachekey, res.data.pklist);
this.props.openTo(res.data.url, {
status: 'browse',
appcode: res.data.appcode,
pagecode: res.data.pagecode,
scene: appcode + srcCode,
n: '联查凭证'
});
return;
}
}
} else {
//跳转到会计平台
cacheTools.set(appcode + srcCode, res.data.pklist);
}
} else if ('_Preview2019' == srcCode) {
//走预览
cacheTools.set(appcode + srcCode, viewData);
}
//打开凭证节点
this.props.openTo(res.data.url, {
status: 'browse',
appcode: res.data.appcode,
pagecode: res.data.pagecode,
scene: appcode + srcCode,
n: '凭证预览'// '凭证预览' 凭证使用这个参数,会计平台不用
});
}
});
}
后台需要添加BillLinkVoucherAction,配置action、鉴权。代码如下所示:
package nccloud.web.arap.promotion_fee.promotion_feemaster.action;
import java.util.Map;
import nc.itf.arap.promotion_fee.promotion_feemaster.IPromotion_feeMasterVOService;
import nc.pubitf.fip.service.IFipBillQueryService;
import nc.vo.arap.promotion_fee.AggPromotion_feeMasterVO;
import nc.vo.arap.promotion_fee.Promotion_feeMasterVO;
import nc.vo.fip.service.FipRelationInfoVO;
import nccloud.commons.lang.StringUtils;
import nccloud.framework.core.exception.BusinessException;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.container.IRequest;
import nccloud.web.codeplatform.framework.action.base.BaseAction;
import nccloud.web.codeplatform.framework.action.base.RequestDTO;
import nccloud.web.codeplatform.framework.action.base.RequstParamWapper;
import nccloud.web.codeplatform.framework.action.base.VOTransform;
public class BillLinkVoucherAction extends BaseAction {
@Override
public Object doAction(IRequest request, RequstParamWapper paramWapper) throws Throwable {
RequestDTO param = VOTransform.toVO(paramWapper.requestString, RequestDTO.class);
String pk = param.getPk();
if (StringUtils.isEmpty(pk)) {
return null;
}
IPromotion_feeMasterVOService service = ServiceLocator.find(IPromotion_feeMasterVOService.class);
AggPromotion_feeMasterVO aggvo = service.findAggPromotion_feeMasterVOByPk(pk);
if (aggvo == null) {
throw new BusinessException("没有查到对应的数据,请重试");
}
Promotion_feeMasterVO headvo = aggvo.getParentVO();
// 构造FipRelationInfoVO
FipRelationInfoVO infoVo = new FipRelationInfoVO();
infoVo.setPk_group(headvo.getPk_group());// pk_group
infoVo.setPk_org(headvo.getPk_org());// pk_org
infoVo.setRelationID(headvo.getPrimaryKey());// 关联id
infoVo.setPk_billtype(headvo.getBilltype());// 单据类型或交易类型
IFipBillQueryService fipService = ServiceLocator.find(IFipBillQueryService.class);
Map<String, Object> info = fipService.queryDesAppInfoBySrc(new FipRelationInfoVO[] { infoVo });
return info;
}
}
4.2 凭证联查单据
会计平台联查单据分注册类方式和自定义扩展场景两种方式,两种方式均可配置,优先级:注册类>自定义扩展场景。
4.2.1 注册类方式配置
由于部分业务单据存在一种单据类型注册多个小应用的情况,因此提供以下方案用来查找业务组小应用url,如果业务组一种单据类型只对应一个小应用,可以忽略此方案.
第一步: 编写联查处理类,该处理类需要实现会计平台的接口nc.pubitf.fip.external.ILinkSrcBillService, 并实现方法queryUrlByconditions;具体实现可以参考标准产品nccloud.pubitf.ia.fip.service.FipLinkSrcBillService
接口入参: Map<String, Object>类型,示例如下
{ billtype: "D1",//单据类型或交易类型
relationIds:["1001H110000000001Z7Z","1001H110000000001Z7Y","1001H110000000001Z7X"]//业务单据pk,支持批量
}
接口返回数据格式:Map<String, String>类型,示例如下
{
url: "/nccloud/resources/arap/receivablebill/recbill/list/index.html",//小应用url
appcode: "10001231",//小应用编码
pagecode: "10001231_list"//页面编码
}
第二步: 将第一步编写的实现类注册到数据库表fip_billregister的LINKSRCBILLCLASS字段里,注意注册到自己对应的单据类型的那条数据.
4.2.2 自定义扩展场景方式配置
第一步单据类型管理找到自己的单据类型,页签“单据类型子表”注册一条记录,扩展类型选择NCC自定义扩展场景,扩展名nccloud.pubimpl.fip.generate.FIPExtendSence,这个类是会计平台提供。标识符填写fip。然后重启后台服务。
第二步重启完成后,页签切到关联小应用,添加一条记录关联小应用的应用编码与默认小应用相同即可,联查时会跳转到主应用,场景选择会计平台。低代码平台生成的单据卡片页面编码为空即可。具体如下图
4.2.3 单据适配
低代码生成的单据当所有资源加载完毕会走入pageReady方法,这里我们需要在pageReady方法处理联查时的场景。将需要显示的单据显示出来并在卡片显示。
pageReady = () => {
.....//省略部分代码
//处理凭证联查start
let scene = this.props.getUrlParam("scene"); //src修改为scene
if ("fip" == scene) {
this.voucherLinkBill();
return;
}
//处理凭证联查end
let linkId = this.props.getUrlParam("id");
if (linkId) {
.....//省略部分代码
}else{
this.updateBtnStatus(); // 更新按钮状态
}
}
voucherLinkBill处理如下所示
voucherLinkBill = () => {
//缓存中的key为'checkedData',
//对应的值格式如下:checkedData:[{pk_operating:"0001Z310000000044YOP","groupid":"000001"}]
//其中pk_operating为会计平台fip_relation主键,groupid为分组信息(若没有分组,则无groupid字段)
let checkedData = cacheTools.get("checkedData");
// 获取卡片区域编码
let area = this.getCardAreaCode();
ajax({
url: '/nccloud/arap/promotion_fee/VoucherLinkBillAction.do',
data: {
pageCode: this.config.pagecode,
userJson: { checkedData },
...area
},
success: (res) => {
// 设置页面模式为卡片浏览态
this.state.showmode = SHOWMODE_CARD;
this.state.editmode = EDITMODE_BROWSE;
// 设置显示标题栏返回按钮
this.state.head.initShowBackBtn = true;
this.setState(this.state, () => {
// 获取卡片区域编码
let area = this.getCardAreaCode();
// 设置卡片主表单为浏览态
this.props.form.setFormStatus(area.formId, EDITMODE_BROWSE);
// 设置卡片子表表格为浏览态
area.tableId.forEach(id => {
this.props.cardTable.setStatus(id, EDITMODE_BROWSE);
});
// 清空卡片数据
this.clearCardData();
res.data?this.fillCardData(res.data) : this.clearCardData();
// 更新按钮状态
this.updateBtnStatus();
});
}
});
}
后台添加VoucherLinkBillAction,配置相应的action及鉴权,代码如下所示
package nccloud.web.arap.promotion_fee.promotion_feemaster.action;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import nc.itf.fip.opreatinglog.GenerateRelatedBillService;
import nc.vo.arap.promotion_fee.AggPromotion_feeMasterVO;
import nc.web.arap.link.info.OperatingLogInfo;
import nccloud.framework.core.exception.ExceptionUtils;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.container.IRequest;
import nccloud.web.codeplatform.framework.action.base.BaseAction;
import nccloud.web.codeplatform.framework.action.base.RequestDTO;
import nccloud.web.codeplatform.framework.action.base.RequstParamWapper;
import nccloud.web.codeplatform.framework.action.base.VOTransform;
public class VoucherLinkBillAction extends BaseAction{
@Override
public Object doAction(IRequest request, RequstParamWapper paramWapper) throws Throwable {
RequestDTO param = VOTransform.toVO(paramWapper.requestString,RequestDTO.class);
List<OperatingLogInfo> loginfos = this.convertOperatingLogInfo(param);
GenerateRelatedBillService relatedBillService = ServiceLocator.find(GenerateRelatedBillService.class);
Object[] vos = relatedBillService.queryBill(loginfos.toArray(new OperatingLogInfo[0]), "src");
if (vos == null || vos.length == 0) {
ExceptionUtils.wrapBusinessException("没有联查到数据,请核实后再查!");
}
if(vos[0] instanceof AggPromotion_feeMasterVO) {
return buildResult(param,true,null,vos[0]);
}
return null;
}
private List<OperatingLogInfo> convertOperatingLogInfo(RequestDTO param){
Map<String,Object> userJson = param.getUserJson();
if(userJson==null||userJson.get("checkedData")==null) {
ExceptionUtils.wrapBusinessException("参数错误,请核实后再查!");
}
List<Map<String,String>> checkedData = (List<Map<String, String>>) userJson.get("checkedData");
List<OperatingLogInfo> ret= checkedData.stream().map(item->{
OperatingLogInfo logInfo = new OperatingLogInfo();
logInfo.setPk_operatinglog(item.get("pk_operatinglog"));
logInfo.setSrc_billtype(item.get("src_billtype"));
return logInfo;
}).collect(Collectors.toList());
return ret;
}
}
生成凭证后在凭证卡片界面更多->附属功能->联查单据即可验证能否跳转到单据界面。