二开-自定义BOS单据表头下推老单表体选单关系设计原创
金蝶云社区-Robby
Robby
13人赞赏了该文章 674次浏览 未经作者许可,禁止转载编辑于2023年09月01日 10:25:48

案例:自定义bos下推产品入库单,并实现勾稽

自定义bos单如下

image.png

下面将分解开发过程:

创建选单关系:请不要再bos设计器里添加新单推老单的选单关系,该工具对老单支持不够;只能通过再数据库中插入数据来实现功能;

查找下游单据(老单)的模板ID;select  FID,FTemplateID,* from ICTransactionType where FName = '产品入库',

image.png

FID=2,FTemplateID='A02'

再ictemplateentry中查找表体字段

image.png

查找上游单据bos单据的单据类型:

FID=200000013,表头物理表FTableName='t_bos200000013',主键FPrimaryKey ='FID'

image.png

bos单的模型Fkey字段标记,ffieldname字段物理表字段名

image.png

第一步:创建选单关系:

INSERT INTO ICClassLink(FSourClassTypeID,FDestClassTypeID,FSourBillShowIndex,FAllowCopy,FAllowCheck,FAllowForceCheck,FFlowControl,FDeCondition,FCondition,FDeHCondition,FDeBCondition,FSourBillFID,FSourBillFEntryID,FSourBillFBillNo,FObjectName,FObjectType,FObjectID,FIsUsed,FUsePage,FDefaultPage,FSRCIDKey,FSRCEntryIDKey,FSRCBillNoKey,FSRCClassIDKey,FISUserDefine,FDestTranTypeID,FSourTranTypeID,FSelectListID,FMustSelected,FSystemReserved,FROB,FFieldName,FRemark,FUseSpec,FSrcDestPage,FSrcPage,FToRed,FSourTypeID,FDestTypeID,FLookUpConditionUp,FLookUpConditionDown,FDefault,FUnControl,FParaValue) VALUES (200000013,-2,0,0,1,0,0,'','FQTY>FQTY1','','','FID','','FBillNo','',0,0,2,',1,',',1,','FSourceInterID','FSourceEntryID','FSourceBillNo','FSourceTranType',1,2,200000013,200000013,0,0,0,'200000013','<FAction=,CanMultiSelBill;/>',-1,0,0,0,0,0,'','',0,6,0) 

GO

image.png

image.png

FSourClassTypeID 填写上游bos单据的类型200000013

FDestClassTypeID 填写下游老单的类型ID -2;老单需要再FID前加上负号(-)

FAllowcopy:复制关系

FAllowCheck:勾稽

FAllowForceCheck:强制勾稽

开发时使用勾稽即可;FAllowCheck=1,其它=0

FCondition:FQty>FQty1(bos单中FQty,FQty1分别对应生产数量、累计入库数量);指必须符合这个条件时才可以下推;

FSourBillFID:FID 上游单据主键

FSourbillFEntryID:空 (表头推表体,这里可以不用填)

FSourcBillFBillNo:FBillNo 上游单据的单据编号字段

--可以通过脚本select FKey,* from ICClassTableInfo where FClassTypeID = 200000013来查询字段的Key

FISused:2启用

FUsePage:,1, 仅表头

FDefualtPage:,1, 仅表头

FSrcIDKey:下游单据的物理表字段用于存上游单据内码

FSRCEntryIDKey:'FSourceEntryID',下游单据的物理表字段用于存上游单据分录ID

FSRCBillNoKey:'FSourceBillNo'下游单据的物理表字段用于存上游单据编号

FSRCClassIDKey:'FSourceTranType'下游单据的物理表字段用于存上游单据类型

FDestTranTypeID:产品入库的FID(查产品入库单模板时查出来的FID值)

FSourTranTypeID:上游bos单单据类型id

FSelectListID:上游bos单单据类型id

FFieldName:icclasslink中定义的ffieldname,建议使用200000013与bos单的单据类一致

FRemark:'<FAction=,CanMultiSelBill;/>'固定值,表示可同时选多个单一起下推

当你完成上面的操作后,再200000013序时簿上就会出现 下推-产品入库 这个菜单了;

image.png

第二步:添加下推的值映射关系:

比如将bos单表头的物料携带到产品入库表体的物料字段上:

当下游单据是老单时,在下游单据加载上游数据的数据包时,拼接Sql时需要用到ICTableRelation,ICSelbills;

ICTableRelation用于拼接这个sql的from部分

ICSelbills用于拼接这个sql的select部分


insert into ICTableRelation(FTypeID,FInterID,FTableName,FTableNameAlias,FFieldName,FTableName11,FTableNameAlias11,FFieldName11,FLogic,FBillID,FFieldID,FMode,FIndex,FCondition,FLeftParentheses,FRightParentheses,FLogicOperator,FISConst,FConstType,FSubFilter)

values(0,0,'t_BOS200000013','v1','FBASE','t_ICItem','t4','FItemID','*=','A02','200000013',0,0,'','','','=',0,0,'')


image.png

FTableName,上游单据的表头物理表字段

FTableNameAlias : v1 上游单据物理表别称,一般使用v1

FFieldName,FBASE上游单据物料字段的物理表字段名称

FTableName11 : t_icitem 关联表(物料基础资料)物理表

FTableName11:t_icitem  别称 t4 ,可以随意命名

FFieldName11:fitemid 物料的主键

flogic:*= 表示left join

FBillID:产品入库单的模板ID

FFieldID:icclasslink中定义的ffieldname,建议使用200000013与bos单的单据类一致

FLogicOperator:=


这种配置再拼sql的where部分会是这样

from t_BOS200000013 v1

left join t_icitem t4 on v1.FBASE = t4.fitemid 


接下来是select部分:

不管选单时要携带任意字段,这2条记录是必须插入的

Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited)

values('A02',200000013,'',-200,-1,'FInterID','FID','t_BOS200000013','v1','',0,0)

Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited)

values('A02',200000013,'',-1,-1,'FBillNo','FBillNo','t_BOS200000013','v1','',0,0)


FID, 产品入库单的模板ID

FFieldName:icclasslink中定义的ffieldname,建议使用200000013与bos单的单据类一致

这2条记录比较特殊需要单据说明

第一条记录 标记选单关系中上游单据的主键

FSelType:-200 bos单的主键定义

FDK:-1 固定-1

FColName:数据包的字段别名必须是FInterID

FName:bos单主键物理表字段

FTableName:t_BOS200000013字段来源物理表

FTableAlias:v1 与ICTableRelation定义的别名要保持一致

第二条记录 标记选单关系上游单据的单据编号字段

FSelType -1 固定

FDK:-1 固定-1

FColName:数据包的字段别名必须是FBillNo

FName:bos单单据编号物理表字段

FTableName:t_BOS200000013字段来源物理表

FTableAlias:v1 与ICTableRelation定义的别名要保持一致

接下来配置物料携带:

Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited)

values('A02',200000013,'FItemID',0,0,'FItemID','FITEMID','t_ICItem','t4','',0,0)

Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited)

values('A02',200000013,'FItemID',0,0,'FItemNUMBER','FNUMBER','t_ICItem','t4','',0,0)

Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited)

values('A02',200000013,'FItemID',0,0,'FItemNAME','FNAME','t_ICItem','t4','',0,0)


FDstCtlField:FItemID 下游单据物料字段,因为物料是基础资料类型字段,所以不能只携带内码到下游,还需要再数据包中配置名称和编码来

FDK 1 编码 2名称

FTableName:字段来源t_ICItem

FTableAlias : t4 ICTableRelation定义的别名要保持一致


再拼凑select脚本时就会是这样

v1.FID as FInterID,v1.FbillNo as fbillno,t4.FITEMID as FItemID ,t4.FNUMBERas FItemNUMBER,t4.FNAME as FItemNAME


 执行完上述脚本之后,点击下推看看效果;

打开sqlserver跟踪器,会看到这样一条脚本

image.png

t4.FUnitGroupID这个是系统自动添加的,只要转换关系中存在t_icitem,就会自动创建这个字段的输出,供携带单位使用

下推后的效果

image.png

已同样的方法我们把单位插入进来(开发可以先自己配置一次,再往下看,检验一下是否已经掌握携带关系配置)

...

...

确定单位物理表select * from t_ItemClass 查询结果t_MeasureUnit


insert into ICTableRelation(FTypeID,FInterID,FTableName,FTableNameAlias,FFieldName,FTableName11,FTableNameAlias11,FFieldName11,FLogic,FBillID,FFieldID,FMode,FIndex,FCondition,FLeftParentheses,FRightParentheses,FLogicOperator,FISConst,FConstType,FSubFilter) values(0,1,'t_BOS200000013','v1','FBase1','t_MeasureUnit','t7','FMeasureUnitID','*=','A02','200000013',0,0,'','','','=',0,0,'')

--单位也是基础资料因此也需要插3条记录

Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited) values('A02',200000013,'FUnitID',0,0,'FUnitID','FMeasureUnitID','t_MeasureUnit','t7','',0,0) Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited) values('A02',200000013,'FUnitID',0,0,'FUnitNUMBER','FNUMBER','t_MeasureUnit','t7','',0,0) Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited) values('A02',200000013,'FUnitID',0,0,'FUnitNAME','FNAME','t_MeasureUnit','t7','',0,0)


接下来是把应收数量、实收数量携带下来,这2个字段直接来源于bos单表头物理表字段,所以只需要各插入一行记录即可,也不需要额外再ICTableRelation添加记录,只需要插入ICSelbills记录即可;

Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited) values('A02',200000013,'FAuxQtyMust',0,0,'FAuxQtyMust','FQty','t_BOS200000013','v1','',0,0) Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited) values('A02',200000013,'FAuxQty',0,0,'FAuxQty','FQty','t_BOS200000013','v1','',0,0)

先不考虑勾稽这种场景,仅考虑把值携带下去,后面会讲如何扣减;

下推单据,后保存一下数据;

image.png

看看后台的记录,下游单据是否记录了上游单据的内码ID

image.png

发现并没有把上游单据ID记录下来;如果没有这些记录是无法做到反写勾稽扣减的;

删掉单据,改进选单关系,把上游的单据内码,单据类型,单据编号携带下来;脚本与数量类似;

Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited) values('A02',200000013,'fsourcetrantype',0,0,'fsourcetrantype','FClassTypeID','t_BOS200000013','v1','',0,0) Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited) values('A02',200000013,'fsourceinterid',0,0,'fsourceinterid','FID','t_BOS200000013','v1','',0,0) Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited) values('A02',200000013,'fsourcebillno',0,0,'fsourcebillno','FBillNo','t_BOS200000013','v1','',0,0)

这里必须要解释一下,因为最开始我们已经插入过单据编号和内码的记录了,但是那是作为选单标识添加的;这里是作为携带字段

FSelType 0表示字段携带到下游的表体字段;

FColName不要用fbillno和finterid,因为FColName字段不能重复,可以随意命名,建议使用跟下游字段一样的字段名;


重新下推单据保存之后image.png

这个时候,已经可以再单据t_200000013的序时簿上下查能够查到刚才保存的单据了;


第三步:勾稽实现:

首先bos单上需要有一个字段来存已下推的数量;在本例中,用累计入库数量来表示;完成了第一步和第二步配置之后,并下推保存了一张单据(如上图);

看看上游单据的累计入库数量是否发生了变化?

为了方便演示,再叙事上配置一个关联信息配置,再一个页面内同时看到上下游单据;image.png

累计入库数量并没有发生变化;

此处尤其复杂,需要好好理解

--反写到累计入库数量,以及关闭标志自动更新;

效果如下:

image.png

insert into ICWriteBackTemplate(FSrcTranType,FDestTranType,FExecuteIndex,FSrcField,FSrcCommitField,FSrcAuxCommitField,FSrcUnitIDField,FDestField,FSrcBillKey,FSrcEntryKey,FDestBillKey,FDestEntryKey,FSrcKeyWord,FDestKeyWord,FOperator,FSaveCheckAction,FUpdateStatusField,FSourceInterIDField,FSourceEntryIDField,FSrcEntryTable) values(200000013,2,10,'[HEAD].FQty','FQty1','','FBase1','[Entry].FAuxQty','FID','','FInterID','FEntryID','FBASE','FItemID','+','','[HEAD].FInteger','FSourceInterID','','t_BOS200000013')

(本例子的场景是表头对表体,反写是写到表头,本文不介绍表体到表体的选单)

FSrcTranType:上游单据类型id

FDestTranType:下游单据类型id

FExecuteIndex:10随便填,如果有多个反写则会按FExecuteIndex从小到大顺序执行

FSrcField:FQty,上游表头数量源头字段,需要用[HEAD]前缀,用于后面反写关闭标记;

FSrcCommitField:FQty1 上游单据的累计下推数量在本例用是累计入库数量;

FSrcAuxCommitField:空;(大多数客户开发bos单据的时候不会再bos单上给每个数量字段对应的基本单位数量;这就要求客户自己再使用的过程中下推后不要改单位;避免出现反写时数据异常,因此本例按无基本单位数量的情况来说明)

FSrcUnitIDField:上游单据单位字段

FDestField:下游数量字段[Entry].FAuxQty,因为是表头推表体,下游的数量再表体,因此要用[Entry]前缀,FAuxQty是常用单位数量,(界面上显示的数量值),为什么不用fqty(基本单位入库数量),因为咱们2开很少使用基本单位数量,扣减上游数量都是用常用单位来弄的,实际上这是一种不规范的开发行为;

FSrcBillKey:FID 上游单据主键字段

FSrcEntryKey:空 (表头对表体不需要使用到上游单据的表体)

FDestBillKey:下游单据的主键

FSrcEntryKey:下游单据的分录号字段

FSrcKeyWord:上游单据关键字,本例中是物料(必填字段)

FDestKeyWord:下游单据表体物料字段

FOperator:+号,固定值

FUpdateStatusField:上游单据关闭字段[HEAD].FInteger,表头字段需要用[HEAD]标记

FSourceInterIDField:下游单据表体中存上游单据内码的字段

FSourceEntryIDField:空

FSrcEntryTable:'t_BOS200000013',上游单据表头物理表名称

第四步:如何限制累计入库数量不能大于我上游单据的原始数量

再sqlserver跟踪器中,跟踪下游单据保存脚本发现有这样一条脚本

set nocount on 

declare @fcheck_fail int 

declare @fsrccommitfield_prevalue decimal(28,13) 

declare @fsrccommitfield_endvalue decimal(28,10) 

declare @maxorder int 

 update src set @fsrccommitfield_prevalue= isnull(abs(src.fqty1),0),     @fsrccommitfield_endvalue=@fsrccommitfield_prevalue+dest.fauxqty,     

@fcheck_fail=case when isnull(@maxorder,0)=1 then 0 else (case when (1=1) then @fcheck_fail else -1 end) end,  

src.fqty1= case when src.fqty < 0 then -1 * @fsrccommitfield_endvalue else @fsrccommitfield_endvalue end 

 from t_bos200000013 src 

inner join (

select u1.fsourceinterid as fsourceinterid,u1.fsourcetrantype,u1.fitemid,sum(u1.fauxqty) as fauxqty from  icstockbillentry u1 where u1.finterid=1961 group by u1.fsourceinterid,u1.fsourcetrantype,u1.fitemid

) dest on dest.fsourceinterid = src.fid and dest.fitemid = src.fbase


如果将1=1配置为@fsrccommitfield_endvalue < src.fqty;即累计入库数量>原始单据数量时令@fcheck_fail=-1

将刚才的writebacktemplate脚本进行改造:

delete ICWriteBackTemplate where FSrcTranType = 200000013 insert into ICWriteBackTemplate(FSrcTranType,FDestTranType,FExecuteIndex,FSrcField,FSrcCommitField,FSrcAuxCommitField,FSrcUnitIDField,FDestField,FSrcBillKey,FSrcEntryKey,FDestBillKey,FDestEntryKey,FSrcKeyWord,FDestKeyWord,FOperator,FSaveCheckAction,FUpdateStatusField,FSourceInterIDField,FSourceEntryIDField,FSrcEntryTable,FCheckExpression_Save) values(200000013,2,10,'[HEAD].FQty','FQty1','','FBase1','[Entry].FAuxQty','FID','','FInterID','FEntryID','FBASE','FItemID','+','','[HEAD].FInteger','FSourceInterID','','t_BOS200000013','@fsrccommitfield_endvalue<[srctable].FQty')

插入前记得先删掉之前的writebacktemplate记录,即向FCheckExpression_Save插入@fsrccommitfield_endvalue<[srctable].FQty;

表示符合表达式条件时容许保存,根据反写的脚本可以知道@fsrccommitfield_endvalue表示加上这张单据累计入库数量

[srctable].FQty表示上游单据的原始数量;

[srctable]会再实际脚本中被替换成src

[srcheadtable] 会被替换成srchead

[desttable]会被替换成dest

只接受以上3中[xxx]的输入

改造后效果如下,

这次下推10个(已经累计下推了8个了)那么根据我们预计效果应该是禁止保存,

image.png

第五步:下推时的默认数量配置,

单据已经累计入库8个了,那么下次下推希望默认的应收数量和实收数量为2(即原始数量-累计入库数量);

调整选单关系ICSelbills,再上面的步骤中已经介绍过,这个表是用来存原始数据包构建sql时的select部分;

我们需要改造select xxxxx. FQty as FAuxQty,FQty as FAuxQtyMust.xxxxx

变成select xxxxx. FQty - FQty1 as FAuxQty,FQty - FQty1 as FAuxQtyMust.xxxxx

改造之前的脚本(先删掉对应记录再插入)

Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited) values('A02',200000013,'FAuxQtyMust',0,0,'FAuxQtyMust','FQty','t_BOS200000013','v1','FQty - FQty1',0,0) Insert into ICSelbills(FID,FFieldName,FDstCtlField,FSelType,FDK,FColName,FName,FTableName,FTableAlias,FAction,FROB,FAllowEdited) values('A02',200000013,'FAuxQty',0,0,'FAuxQty','FQty','t_BOS200000013','v1','FQty - FQty1',0,0)

如果FAction不为空,则再拼接select时会用FAction来替换FName,

那么我们只需要将FAction插入FQty - FQty1即可;

再来看效果:

image.png


备注:如果再修改后台数据时,k3并未关闭,那么请在执行完脚本之后再任务管理器中杀掉k3cacheclient.exe进程,保证下次打开单据时是最新的模型;如果之前你再bos设计器建立了选单关系,请自行删掉(清理本文中涉及到的物理表数据),让他还原到一个未配置选单关系的状态;


完;







赞 13