分类 K3Cloud 下的文章

本文介绍了成本对象类型表、维度表、信息表等表之间的关联关系及生成时机,提供了相关的SQL查询脚本。同时,还阐述了如何查询成本计算结果表的表结构关联关系,并说明了如何查询历史期间数据和期间字段。此外,还提及了费用分配相关表结构和查询方法。

有用

反馈

持续更新......

---------------------------------------------------------------------------------------------------------


1、成本对象类型表、维度表、信息表关联关系,生成的时机

关联关系参考脚本:

select * from T_CB_PROORDERTYPE type1

       inner join T_BD_MATERIAL mat on mat.FMATERIALID=type1.FPRODUCTID

       inner join T_CB_PROORDERDIME dime1 on type1.FPROORDERTYPE=dime1.FPROORDERTYPE and type1.FCOSTCENTERID=dime1.FCOSTCENTERID

       and mat.FMASTERID=dime1.FPRODUCTID and type1.FNUMBER=dime1.FPRODUCTNO and type1.FSEQ=dime1.FBILLSEQ

       inner join T_CB_PROORDERINFO info on info.FPRODUCTDIMEID= dime1.FPRODUCTDIMEID  


生成时机:

T_CB_PROORDERTYPE   普通生产下达,委外生产下达,简单生产入库,重复生产入库;(同理:投入产量归集表T_CB_INPUTQTYENTRY )

T_CB_PROORDERDIME   费用分配之前,根据投入信息,入库信息获取工单信息;

T_CB_PROORDERINFO   期初和期末标识, 期初是结账的时候,期末是成本计算后写的。


关于许多小伙伴咨询数据字典的问题,请参考帖子答复的方法1下载数据字典:

https://vip.kingdee.com/questions/333685685569759744/answers/333813294701778688?productLineId=1


需注意此版数据字典是星空7.6版本的,后续版本若有添加新字段,数据字典中是没有的。

例如T_CB_PROORDERTYPE,在8.0版本添加了FMASTERID(物料FMASTERID内码) 和 FSUPPLIERID(供应商内码)

图片.png

FNUMBER:生产、委外订单的单据编号;简单生产手工录入的生产编号(前提是勾选了生产编号影响成本)

FSEQ:生产、委外订单分录行号,简单生产和重复生产都是0

FDATE:生产、委外订单的下达日期或简单生产入库单的单据日期

FPROORDERTYPE :业务类型,枚举值如下

PO:普通生产,生产订单

SPO:简单生产

OUTSRC:委外生产,委外订单

TSO:费用追踪至出库单 // 销售出库,费用追踪至产品,费用归集单录入的销售费用

TSR:费用追踪至退货单 //销售退货单

TP:费用追踪至产品

REM:重复生产


T_CB_PROORDERDIME

图片.png

FPRODUCTID:物料表的FMASTERID

FPRODUCTTYPE:1 主产品 2 联产品 3 副产品



2、成本计算结果表的表结构

关联关系参考脚本:

select * from T_CB_PROORDERTYPE type1

       inner join T_BD_MATERIAL mat on mat.FMATERIALID=type1.FPRODUCTID

       inner join T_CB_PROORDERDIME dime1 on type1.FPROORDERTYPE=dime1.FPROORDERTYPE and type1.FCOSTCENTERID=dime1.FCOSTCENTERID

       and mat.FMASTERID=dime1.FPRODUCTID and type1.FNUMBER=dime1.FPRODUCTNO and type1.FSEQ=dime1.FBILLSEQ

       inner join T_CB_PROORDERINFO info on info.FPRODUCTDIMEID= dime1.FPRODUCTDIMEID

       inner join T_CB_COSTCALEXPENSE exp1 on exp1.FID=info.FID

       inner join T_CB_COSTCALEXPENSEDETAIL exp1detail on exp1.FENTRYID=exp1detail.FENTRYID


若查询历史期间的数据,则是T_CB_PROORDERINFO_H、T_CB_COSTCALEXPENSE_H、T_CB_COSTCALEXPENSE_H

同理:T_CB_COSTMATTERIAL  T_CB_COSTMATTERIALDETAIL


如何查询期间字段

-- T_CB_PROORDERINFO(本期)或T_CB_PROORDERINFO_H(历史期间)的期间字段FACCTGID

-- FACCTGID  核算组织+核算体系+会计政策+期间

select syst.FNUMBER,org.FNUMBER,po.FNUMBER,U0.FYEAR,U0.FPERIOD,U0.FID as FACCTGID,U1.FDIMENSIONID

from T_HS_OUTACCTG U0

INNER JOIN T_HS_CALDIMENSIONS U1 ON U0.FDIMENSIONID = U1.FDIMENSIONID

inner join T_ORG_ACCOUNTSYSTEM syst on syst.FACCTSYSTEMID=U1.FACCTSYSTEMID --and syst.FNUMBER=''--核算体系编码

inner join T_ORG_ORGANIZATIONS org on  org.FORGID=U1.FFINORGID --and org.FNUMBER=''--组织编码

inner join T_FA_ACCTPOLICY po on po.FACCTPOLICYID=U1.FACCTPOLICYID --and po.FNUMBER=''--会计政策编码

--where U0.FYEAR = 2021 AND U0.FPERIOD = 7--期间

order by syst.FNUMBER,org.FNUMBER,po.FNUMBER,U0.FYEAR,U0.FPERIOD;


费用分配相关表结构:

--费用分配明细表

select * from T_CB_EXPALLORESULTSEND a inner join T_CB_EXPENSECOLLENTRY b on a.FBILLENTRYID=b.fentryid and a.FSRCBIILLFORMID='CB_EXPENSECOLLECTION' --费用分配结果发送方

left join T_CB_EXPALLORESULTREC c on a.FSENDID=c.FSENDID left join T_CB_PROORDERDIME dime on dime.FPRODUCTDIMEID=c.FPRODUCTDIMEID --费用分配结果接收方

where a.FOUTACCTGID=100001 -- FACCTGID


--材料费用分配明细表

select * from T_CB_COSTALLORESULTSEND a  --材料费用分配结果发送方

left join T_CB_COSTALLORESULTREC c on a.FSENDID=c.FSENDID left join T_CB_PROORDERDIME dime on dime.FPRODUCTDIMEID=c.FPRODUCTDIMEID --材料费用分配结果接收方

where a.FOUTACCTGID=100001 -- FACCTGID


若查询历史期间的数据,则是T_CB_EXPALLORESULTSEND_H、T_CB_EXPALLORESULTREC_H、T_CB_COSTALLORESULTSEND_H、T_CB_COSTALLORESULTREC_H



select * from  T_HS_OUTACCTG;

image.png

SELECT * FROM T_CB_PROORDERINFO;  历史数据在 T_CB_PROORDERINFO_H

image.png


SELECT * FROM T_CB_PROORDERDIME;

image.png


以下四个表都有历史表,存储在_H 中


  • SELECT * FROM T_CB_CostMatterial  ;--FEXPTYPE 0直接费用、1间接费用、2其他费用

image.png

  • SELECT * FROM T_CB_CostMatterialDetail ;--费用

image.png

  • SELECT * FROM T_CB_CostCalExpense;

    image.png

  • SELECT * FROM T_CB_CostCalExpenseDetail;--成本

image.png


作者:拿了你的糖

来源:金蝶云社区

原文链接:https://vip.kingdee.com/article/456499268162143232?productLineId=1&lang=zh-CN

著作权归作者所有。未经允许禁止转载,如需转载请联系作者获得授权。


本文包含两个SQL查询语句。第一个语句用于跟踪销售订单到生产订单的每种成本项目的汇总金额,包括直接材料、直接材料钢材、拆卸费、差旅费和直接人工等成本项目的投入金额,并关联了销售订单、工单及其明细、成本计算等表。第二个语句用于显示工单的材料明细,即获取成本计算后的材料分配结果,包括材料编码、材料名称及本期投入金额,同样涉及生产订单、成本计算及材料表等。两个查询均从当前和历史数据中获取信息。

有用

反馈

一、按销售订单跟踪生产订单的每种成本项目的汇总金额

image.png

select T.订单编号,T.订单日期,T.客户名称,T.订单行号,T.产品编码,T.产品名称,T.订单数量,T.计量单位,T.工单号 ,T.工单行号
	,sum(case when t.成本项目='直接材料' then t.投入金额 else 0 end) as 直接材料
	,sum(case when t.成本项目='直接材料钢材' then t.投入金额 else 0 end) as 直接材料钢材
	,sum(case when t.成本项目='拆卸费' then t.投入金额 else 0 end) as 拆卸费
	,sum(case when t.成本项目='差旅费' then t.投入金额 else 0 end) as 差旅费
	,sum(case when t.成本项目='直接人工' then t.投入金额 else 0 end) as 直接人工From
	(		select 
		tm.FBILLNO as 订单编号,tm.FDATE as 订单日期,tbc.FNAME as 客户名称,td.fseq  as 订单行号,tbm.FNUMBER as 产品编码,tbml.FNAME as 产品名称,td.FQTY as 订单数量,tbul.FNAME as 计量单位
		,tmo.FBILLNO as 工单号 ,tmod.FSEQ as 工单行号,s.fcostname as 成本项目,s.FCURRINPUTAMOUNT as 投入金额		from T_SAL_ORDER tm--销售订单
		inner join T_SAL_ORDERentry td on tm.fid=td.fid		inner join T_BD_CUSTOMER_L tbc on tm.FCUSTID=tbc.FCUSTID--客户
		inner join T_BD_MATERIAL tbm on td.FMATERIALID=tbm.FMATERIALID--物料
		inner join T_BD_MATERIAL_L tbml on tbm.FMATERIALID=tbml.FMATERIALID--物料描述
		inner join T_BD_UNIT_L tbul on td.FUNITID=tbul.FUNITID--计量单位
		left join T_PRD_MOENTRY tmod on tmod.FSALEORDERID=td.FID and tmod.FSALEORDERENTRYID=td.FENTRYID--工单明细
		left join T_PRD_MO tmo on tmod.FID=tmo.FID--工单
		left join
		--select s.FPRODUCTNO as MONumbere,s.FBILLSEQ as MOSeq,s.fcostname,sum(FSumCurrInputAmount) as MOInAmount
		(				--成本计算后数据获取--当期
			select d.FPRODUCTNO,d.FBILLSEQ,d.FPROORDERTYPE				--订单行数据
				,ce.FSumCurrInputAmount --本期总投入
				,ce.FCurrInputAmount ---本期投入
				--成本项目明细行
				,ced.FCOSTITEMID ,tb1.fname  as fcostname --成本项目
			from T_CB_PROORDERINFO p 			inner join T_CB_PROORDERDIME d on p.FPRODUCTDIMEID=d.FPRODUCTDIMEID --生产订单维度信息表
			--成本计算结果费用表:成本项目,费用项目
			inner join T_CB_COSTCALEXPENSE ce on ce.FID=p.FID  --费用分配总表
			inner join T_CB_COSTCALEXPENSEDETAIL ced on ced.FENTRYID=ce.FENTRYID--费用分配细表
			inner join T_HS_COSTITEM_L tb1 on ced.FCOSTITEMID=tb1.fcostitemid--成本项目
			inner join T_CB_COSTCENTER_L tb2 on d.fcostcenterid=tb2.FCostcenterid--成本中心
			--成本计算结果材料表:若需要获取子项物料则关联以下两个表
			--inner join T_CB_COSTMATTERIAL cm on cm.FID=p.FID
			--inner join T_CB_COSTMATTERIALDETAIL cmd on cmd.FENTRYID=cm.FENTRYID
			where   p.FENDINITKEY='1'   -- 1-期末数据,0-期初数据
			and		d.FPROORDERTYPE='PO'	

			--and d.FPRODUCTNO='MO000004' and d.FBILLSEQ=1  --订单编号行号
			--and p.FACCTGID=100002   --核算内码,由核算体系组织年期唯一确定,获取时一定要加核算范围

			union all  --历史订单信息
			--成本计算后数据获取--历史期间
			select d.FPRODUCTNO,d.FBILLSEQ,d.FPROORDERTYPE				--订单行数据
				,ce.FSumCurrInputAmount --本期总投入
				,ce.FCurrInputAmount ---本期投入
				--成本项目明细行
				,ced.FCOSTITEMID ,tb1.fname  as fcostname --成本项目
			from T_CB_PROORDERINFO_H p 			inner join T_CB_PROORDERDIME d on p.FPRODUCTDIMEID=d.FPRODUCTDIMEID --生产订单维度信息表
			--成本计算结果费用表:成本项目,费用项目
			inner join T_CB_COSTCALEXPENSE_H ce on ce.FID=p.FID  --费用分配总表
			inner join T_CB_COSTCALEXPENSEDETAIL_H ced on ced.FENTRYID=ce.FENTRYID--费用分配细表
			inner join T_HS_COSTITEM_L tb1 on ced.FCOSTITEMID=tb1.fcostitemid--成本项目
			inner join T_CB_COSTCENTER_L tb2 on d.fcostcenterid=tb2.FCostcenterid--成本中心
			--成本计算结果材料表:若需要获取子项物料则关联以下两个表
			--inner join T_CB_COSTMATTERIAL cm on cm.FID=p.FID
			--inner join T_CB_COSTMATTERIALDETAIL cmd on cmd.FENTRYID=cm.FENTRYID
			where   p.FENDINITKEY='1'   -- 1-期末数据,0-期初数据
			and		d.FPROORDERTYPE='PO'	

			--and d.FPRODUCTNO='MO000004' and d.FBILLSEQ=1  --订单编号行号
			--and p.FACCTGID=100002   --核算内码,由核算体系组织年期唯一确定,获取时一定要加核算范围
		)s on s.FPRODUCTNO=tmo.FBILLNO and s.FBILLSEQ=tmod.FSEQ		--where  s.FPRODUCTNO='MO000008'
		--group by s.FPRODUCTNO,s.FBILLSEQ ,s.fcostname
	)T 	group by  T.订单编号,T.订单日期,T.客户名称,T.订单行号,T.产品编码,T.产品名称,T.订单数量,T.计量单位,T.工单号 ,T.工单行号


二、按工单显示材料明细-取值材料分配结果

image.png

	select s.FPRODUCTNO as 工单编号,s.FBILLSEQ as 工单行号,s.clnumber as 材料编码,s.clname as 材料名称,s.FCURRINPUTAMOUNT 本期投入金额--此金额是投入明细,没有按工单汇总
	from
	(		--成本计算后数据获取--当期
		select d.FPRODUCTNO,d.FBILLSEQ,d.FPROORDERTYPE			--订单行数据
			,tbb.FNUMBER as clnumber,tbbl.fname as clname
			,cm.FCurrInputAmount --本期投入金额

		from T_CB_PROORDERINFO p 		inner join T_CB_PROORDERDIME d on p.FPRODUCTDIMEID=d.FPRODUCTDIMEID --生产订单维度信息表
		--成本计算结果费用表:成本项目,费用项目
		--inner join T_CB_COSTCALEXPENSE ce on ce.FID=p.FID  --费用分配总表
		--inner join T_CB_COSTCALEXPENSEDETAIL ced on ced.FENTRYID=ce.FENTRYID--费用分配细表
		--inner join T_HS_COSTITEM_L tb1 on ced.FCOSTITEMID=tb1.fcostitemid--成本项目
		--inner join T_CB_COSTCENTER_L tb2 on d.fcostcenterid=tb2.FCostcenterid--成本中心
		--成本计算结果材料表:若需要获取子项物料则关联以下两个表
		inner join T_CB_COSTMATTERIAL cm on cm.FID=p.FID--材料分配明细表
		--inner join T_CB_COSTMATTERIALDETAIL cmd on cmd.FENTRYID=cm.FENTRYID
		inner join T_BD_MATERIAL tbb on cm.FMATERIALID=tbb.FMATERIALID		inner join T_BD_MATERIAL_L  tbbl on tbb.FMATERIALID=tbbl.FMATERIALID		where   p.FENDINITKEY='1'   -- 1-期末数据,0-期初数据
		and		d.FPROORDERTYPE='PO'	

		--and d.FPRODUCTNO='MO000004' and d.FBILLSEQ=1  --订单编号行号
		--and p.FACCTGID=100002   --核算内码,由核算体系组织年期唯一确定,获取时一定要加核算范围


		union all--历史期间
			--成本计算后数据获取--档期
		select d.FPRODUCTNO,d.FBILLSEQ,d.FPROORDERTYPE			--订单行数据
			,tbb.FNUMBER as clnumber,tbbl.fname as clname
			,cm.FCurrInputAmount --本期投入金额

		from T_CB_PROORDERINFO_H p 		inner join T_CB_PROORDERDIME d on p.FPRODUCTDIMEID=d.FPRODUCTDIMEID --生产订单维度信息表
		--成本计算结果费用表:成本项目,费用项目
		--inner join T_CB_COSTCALEXPENSE ce on ce.FID=p.FID  --费用分配总表
		--inner join T_CB_COSTCALEXPENSEDETAIL ced on ced.FENTRYID=ce.FENTRYID--费用分配细表
		--inner join T_HS_COSTITEM_L tb1 on ced.FCOSTITEMID=tb1.fcostitemid--成本项目
		--inner join T_CB_COSTCENTER_L tb2 on d.fcostcenterid=tb2.FCostcenterid--成本中心
		--成本计算结果材料表:若需要获取子项物料则关联以下两个表
		inner join T_CB_COSTMATTERIAL_H cm on cm.FID=p.FID--材料分配明细表
		--inner join T_CB_COSTMATTERIALDETAIL cmd on cmd.FENTRYID=cm.FENTRYID
		inner join T_BD_MATERIAL tbb on cm.FMATERIALID=tbb.FMATERIALID		inner join T_BD_MATERIAL_L  tbbl on tbb.FMATERIALID=tbbl.FMATERIALID		where   p.FENDINITKEY='1'   -- 1-期末数据,0-期初数据
		and		d.FPROORDERTYPE='PO'	

		--and d.FPRODUCTNO='MO000004' and d.FBILLSEQ=1  --订单编号行号
		--and p.FACCTGID=100002   --核算内码,由核算体系组织年期唯一确定,获取时一定要加核算范围)s



summary-icon摘要

由AI智能服务提供

本文回顾了Python插件开发的前几篇内容,并重点介绍了单据转换插件的开发。单据转换是业务流程中的重要环节,通过插件可以控制单据的转换过程,调整生成的下游数据包。文章详细阐述了单据转换的两种类型(下推和选单)及其实现逻辑,并介绍了单据转换插件的注册、事件处理流程以及常用事件的处理方法。通过示例代码展示了如何在Python中实现单据转换插件,并提供了应用案例和事件处理示例。最后,感谢读者的关注与支持,并预告了下一篇关于插件常用工具类的分享。

有用

反馈

往期回顾:

【Python插件入门】第1篇:Python插件入门讲解

【Python插件入门】第2篇:基本开发过程介绍

【Python插件入门】第3篇:插件中如何进行数据操作

【Python插件入门】第4篇:单据表单插件

【Python插件入门】第5篇:单据列表插件

【Python插件入门】第6篇:操作服务插件

【Python插件入门】第7篇:简单账表服务插件

【Python插件入门】第8篇:账表表单插件

      

        前面的篇章讲解了各种类型的插件,这些插件都是在单个业务对象中触发使用,我们同时也了解了对单据数据的操作方法,是不是对这个系统的功能背后的实现逻辑有了更深的理解呢,当不同的业务对象"串联起来"就构成了系统中各种丰富的功能,形成了系统的业务流程,在"串联"各种单据的过程中,必不可少的就是"单据转换",他是业务流程连接过程中的一个重要枢纽,对于单据转换的过程 ,系统也支持了通过插件对这个过程进行干预,今天我们就来看一看如何用Python开发单据转换插件。

一、单据转换概述

  • 单据转换,是指把上游所选单据,按照转换规则,自动生成下游单据数据包的过程;不对下游单据进行保存、提交、审核等处理。

  • 单据转换插件,能够介入到单据转换的各个关键时刻,对转换行为进行控制,从而调整所生成的下游数据包;

  • 单据转换按照发起方不同,可分为下推、选单;

    下推是指在上游单据列表,把所选单据,生成下游单据数据包,并展示出来;

    选单是指在下游单据新增界面,弹出上游单据列表,选择源单返回,然后根据转换规则把源单数据填写到下游单据新增界面上;

  • 选单实际上分为两个独立的过程,一个是选单前过程,根据转换规则,生成源单数据筛选条件,传给源单列表。因此源单列表上显示的,都是允许下推的数据;另外一个就是选单过程,把用户选择返回的源单数据,迁移到目标单据上;

  • 下推与选单,采用相同单据转换规则,进行数据迁移;也采用相同的单据转换插件,但触发的事件略有差异,编写单据转换插件时,需要兼顾这些差异; 

二、单据转换规则简介

以下知识结构截图摘取自@eris 老师分享的学习资料,在此感谢老师的用心制作!

也强烈推荐大家看看老师的讲解文章和课程!金蝶云星空BOS专题中级课-业务流程

    单据转换的核心是单据转换规则基于单据转换规则才会有单据转换插件。单据转换规则配置可以实现我们常见的单据流转需求,我们先来简单回顾一下单据转换规则。

  • 单据关联配置:要实现关键关联,需要先在下游单据中设置单据关联配置

image.png


  • 单据转换规则说明

image.png

  • 单据转换规则策略要点

image.png

  • 可以触发单据转换规则的操作

image.png

三、单据转换插件介绍

    C#开发时,单据转换插件的基类是AbstractConvertPlugIn。Python插件在单据转换规则-插件策略中注册即可。

    单据转换插件开始支持Python插件的版本是PT-146836 [7.5.1.202005],高于此版本,应该都是可以使用的。

    单据转换插件是依赖于单据转换规则来触发的,单据转换从选择单据、指定单据类型、分组合并、过滤携带数据等整个转换过程都提供了插件干预方法,应对一些复杂的单据转换场景需求。所以只要触发了单据转换规则,就可以触发单据转换插件执行过程。

  • 单据下推执行过程

image.png

image.png

  • 单据选单执行过程

image.png

  • 单据转换插件一览图(含事件执行顺序)

image.png


  • 选单时,单据转换插件事件执行顺序:与下推有小部分差异

image.png

这里要说明的是,下推、选单前、选单过程,采用的插件是同一个。 从事件的覆盖度来看,下推过程触发的事件是最全面的,针对下推过程编写的插件,选单过程被自动覆盖。也就是说通常情况下,在不对选单界面做特殊干预的情况下,按照下推的运行过程来开发一个单据转换插件,对选单操作也是通用的。

四、单据转换插件常用事件

        前面的截图中已经将单据转换插件执行过程讲得比较清晰了,总的来说单据转换插件也是按照一条"流水线"执行的,我们只需要在需要干预的环节,去实现对应的事件,加入我们的代码逻辑就可以了。

  • 我们再整体看一下下推运行时序

image.png

  • 新建一个单据转换插件,以采购申请下推采购订单为例

image.png

  • 下面看看单据转换插件中的一些常用事件

#解析字段映射关系,并构建查询参数。
#这里可以加入你想要的额外的字段
def OnQueryBuilderParemeter(e):
    #插件常用全局属性,顺带介绍一下,不一定在此事件中使用  #*************************************************************************************************************
    #this.OperationNumber;#操作编码,如下推,选单操作等,值分别为Push,Draw,
    #paraDIC=this.Option.GetVariables();#获取自定义参数集,字典类型,例如是否整单下推、是否需要校验下游单据新增权限、WebAPI调下推时传入的自定义参数等等
    #if(paraDIC.ContainsKey("参数标识")==True):#判断是否含有某个参数
    #    paraValue=paraDIC["参数标识"];#取出参数标识
    #***********************************************************************************************************
    #e.SourceBusinessInfo;#上游单据的元数据信息,可从这里获取一些上游单据的关键信息
    # secFormId=e.SourceBusinessInfo.GetForm().Id;#上游单据FormId
     billNo=SelectorItemInfo("FBillNo");#加入单据转化规则中没有配置的,但需要额外加载的字段
     e.SelectItems.Add(billNo);

#解析过滤策略中配置的条件,可以在这里加自定义的下推过滤条件
#此事件开始前,刚完成选单条件策略中的过滤条件的解析
#e.FilterPolicySQL来自于:【选单条件策略中设置的过滤条件(JsonSetting)】+【选单条件策略中的附加条件(CustFilter)】+【按目标组织基础资料属性过滤的条件(TargetOrgBDFilterList)】
#此事件结束后,e.FilterPolicySQL将使用AND操作符合并到QueryBuilderParemeter.FilterClauseWihtKey,后续作用于选单列表取数
def OnParseFilter(e):
    filterStr=" FBillNo LIKE 'CGSQ%' "
    e.FilterPolicySQL=StringUtils.JoinFilterString(e.FilterPolicySQL,filterStr);#追加过滤条件,默认用AND连接
    e.PlugFilterDesc = "单据编号必须包含【CGSQ】";#过滤条件描述信息,下推不满足时,会提示出来。

#选单时才有,解析字段映射关系中配置的过滤选项:过滤/仅追加
#此事件开始前,刚完成用于选单列表取数的QueryBuilderParemeter的构建,e.FilterOptionsSQL来自于QueryBuilderParemeter.FilterClauseWihtKey
def OnParseFilterOptions(e):
    #e.TargetData;#目标单的数据包
    #e.SourceBusinessInfo;#源单元数据信息
    #e.TargetBusinessInfo;#目标单元数据信息
    filterStr=" FReqQty > 10 ";
    e.FilterOptionsSQL = StringUtils.JoinFilterString(e.FilterOptionsSQL,filterStr);#追加选单过滤条件

#获取到源单数据之后触发,(下推执行)
#可以在此事件中修改源单下推的数据包,不会真实修改源单,只会影响下推的携带值
#例如,可以动态修改源单分单依据字段的值,以此实现动态分单策略
def OnGetSourceData(e):
    #e.SourceBusinessInfo;#源单元数据信息
    srcData=e.SourceData;#源单数据,本次下推的所有数据行,DynamicObjectCollection类型
    #可循环从数据包集合中取数,只能取到参与转换规则中配置的字段和OnQueryBuilderParemeter额外加入的字段
    for row in srcData:
        srcId=row["Id"];#源单Id
        srcEntryId=str(dr["FEntity_FEntryID"]);#源单分录内码:单据体标识_FEntryId

#获取到源单数据之后触发,(选单执行)
#与OnGetSourceData类似,只不过一个是在下推执行,一个是选单执行
def OnGetDrawSourceData(e):
    #e.SourceBusinessInfo;#源单元数据信息
    srcData=e.SourceData;#源单数据,本次下推的所有数据行,DynamicObjectCollection类型
    #可循环从数据包集合中取数,只能取到参与转换规则中配置的字段和OnQueryBuilderParemeter额外加入的字段
    for row in srcData:
        srcId=row["Id"];#源单Id
        srcEntryId=str(dr["FEntity_FEntryID"]);#源单分录内码:单据体标识_FEntryId

#执行分组前触发,可以在此增加自定义的分组字段
def OnBeforeGroupBy(e):
    srcData= e.SourceData;#源单数据
    HeadGroupKey = e.HeadGroupKey;#分单依据
    e.HeadGroupKey =("{0},{1}").format(e.HeadGroupKey,"FXXX");#追加分组字段
    EntryGroupKey=e.EntryGroupKey;#单据体分组合并字段
    e.EntryGroupKey =("{0},{1}").format(e.EntryGroupKey,"FEXXX");#追加单据体分组合并字段
    SubEntryGroupKey=e.SubEntryGroupKey;#子单据体分组字段
    e.SubEntryGroupKey =("{0},{1}").format(e.SubEntryGroupKey,"FEXXX");#追加单据体分组字段

#下推执行,根据分组策略创建目标单,此时还没根据字段映射赋值目标单的字段,这个事件用得不多
#也没有创建关联数据包,接近一个"空白"的下游单据,当然有默认值的字段还是有值
def OnCreateTarget(e):
    headEntity=e.TargetExtendedDataEntities.FindByEntityKey("FBillHead");#分组之后创建的所有目标单集合
    for entity in headEntity:
        billObj=entity.DataEntity;#下游单据的完整数据包,可以通过实体数据包操作方式处理下游单据字段

#选单执行,与OnCreateTarget类似,此时获取到了选单返回的数据,但是还没赋值到下游单据的字段上
def OnCreateDrawTarget(e):
    headEntity=e.TargetExtendedDataEntities.FindByEntityKey("FBillHead");#获取根据分组创建好的目标单

#目标单赋值之前触发,主要用启动字段赋值事件OnFieldMapping,用于监听字段映射赋值过程,用得很少
def OnBeforeFieldMapping(e):
    e.FireFieldMappingEvent=True;#启动字段赋值
    
#字段赋值事件,每个数据包,每个字段都会触发,易影响性能,慎用!
def OnFieldMapping(e):
    headEntity=e.TargetExtendedDataEntities.FindByEntityKey("FBillHead");#下游单据数据集
    fldKey=e.TargetField.Key.ToUpperInvariant();#赋值字段标识大写

#字段映射所有字段赋值完成之后触发,用得很少    
def OnAfterFieldMapping(e):
    headEntity=e.TargetExtendedDataEntities.FindByEntityKey("FBillHead");#下游单据数据集

#创建关联关系之前触发,可以取消创建,用得很少
def OnCreateLink(e):
    headEntity=e.TargetExtendedDataEntities.FindByEntityKey("FBillHead");#下游单据数据集
    #e.Cancel=True;#取消创建

#单据关联关系创建之后触发,表单服务策略执行之前
#如果需要干预下游单据,再执行表单服务策略,可以在此事件中对下游单据进行处理
#例如,要通过插件修改采购订单单价,之后系统自动执行表单服务策略计算金额
def OnAfterCreateLink(e):
    headEntity = e.Result.FindByEntityKey("FBillHead");#由于可能分单,所以可能有多个下游单据,是一个集合
    for entity in headEntity:#循环处理
        billObj=entity.DataEntity;#下游单据的完整数据包,可以通过实体数据包操作方式处理下游单据字段

#获取到服务策略之前触发,可在此事件中加入自定义的表单服务或者移除服务,用得少
def OnGetConvertBusinessService(e):
    FormSvcList=e.FormBusinessServices;#表单服务集合
    
#单据转换执行完成之后执行,在表单服务策略执行完成之后
#可以获取到下推完成之后,还未保存的下游单据,对下游单据数据包做最后的处理
#应用案例:单据转换插件提示消息
def AfterConvert(e):
    #整个单据转换执行完毕后的下游单据数据集合,相当于用户看到的推出来的下游单据,但是还没保存
    headEntity = e.Result.FindByEntityKey("FBillHead");#由于可能分单,所以可能有多个下游单据,是一个集合
    for entity in headEntity:#循环处理
        billObj=entity.DataEntity;


  • 相关应用案例参考推荐:

单据转换之多选基础资料下推携带

单据转换之多选辅助资料下推携带

单据转换插件提示消息

显示单据转换操作页面事件OnShowConvertOpForm

单据转换插件,动态表单插件,表单插件,服务插件,多单据体应用

案例四:AfterConvert事件

二开案例.单据转换插件.设置选单条件

单据转换实现多单据体到目标单的携带和关联

单据转换插件之携带子单据体

Python单据转换插件示例-自定义单据下推付款单

......

==========================本篇正文结束=====================================

截止到这一篇,Python插件开发各插件类型,已经介绍完了,感谢大家一如既往的关注与支持!

插件示例代码已经上传附件,老规矩,大家按需下载!

大家持续关注,点赞、评论、收藏,您的点赞、评论就是我前进的动力。

下一篇:【Python插件入门】第10篇(完结篇):插件常用工具类分享


Python单据转换插件示例.rar(3.12KB)


summary-icon摘要

由AI智能服务提供

本文是对“Python插件入门”系列中的一篇关于“简单账表服务插件”的扩展,主要介绍了账表表单插件的概念、应用场景、新建方法及常用事件。账表表单插件通过继承AbstractDynamicFormPlugIn基类实现,用于丰富报表界面功能,如设置数据颜色、修改报表单元格数据、单据关联查询等。文中提供了账表表单插件的详细开发步骤和代码示例,包括初始化、加载、数据绑定、按钮点击等事件的处理方法,展示了如何通过Python代码对报表进行自定义和扩展。

有用

反馈

往期回顾:

【Python插件入门】第1篇:Python插件入门讲解

【Python插件入门】第2篇:基本开发过程介绍

【Python插件入门】第3篇:插件中如何进行数据操作

【Python插件入门】第4篇:单据表单插件

【Python插件入门】第5篇:单据列表插件

【Python插件入门】第6篇:操作服务插件

【Python插件入门】第7篇:简单账表服务插件


    接上一篇,简单账表服务插件主要是完成了报表查询数据的构建,已经完成了简单账表查询功能的开发,那么对于查询界面在做一些"锦上添花"的功能,会让报表功能更加丰富,或者基于报表查询结果,再做一些单据联查、穿透查询等功能,可以通过账表表单插件来完成。

一、账表表单插件简介

    C#开发时,账表表单插件的基类是AbstractSysReportPlugIn与单据的表单插件基类不同,C#开始时要注意一下!Python插件开发的话,了解就行了,他也是AbstractDynamicFormPlugIn的派生类,和单据表单插件算是"兄弟"关系。账表表单插件是依赖于账表界面触发的,也属于界面类插件,既然都是继承于AbstractDynamicFormPlugIn,所以很多表单插件中的事件方法也是可以使用的。

    账表表单插件中的一些重要属性和成员这里就不单独介绍了,下面的常用事件讲解中会做介绍,继续往下看!

  • 账表表单插件常见应用场景

    ①账表查询界面设置数据颜色。

    ②修改报表单元格数据:转换百分数、千分号分隔符、修改底部合计结算逻辑等。

    ③单据关联查询。

    ④报表穿透查询,关联弹出其他账表。

    ⑤关闭表头排序功能

    ⑥报表表头字段赋值

    ⑦...

二、新建一个账表表单插件

  • 注意:这里提供一个引用比较全的账表表单插件示例模板,在附件中下载示例代码,复制到BOS里面注册!

  • Python账表表单插件注册方法:如下图所示,以上一篇测试示例报表为例,其他账表类似。

image.png


三、账表表单插件常用事件介绍

    这里做了表单插件的示例,对报表界面做了一些丰富,测试效果图如下:

    image.png

  • 下面看下账表表单插件中常用事件介绍:

#初始化
def OnInitialize(e):
    openPara=this.View.OpenParameter;#获取打开报表时传入的参数
    myPara=openPara.GetCustomParameter("参数标识");#根据参数标识获取某个打开参数
    if(myPara<>None):#若参数不为空
        myParaStr=("{0}").format(myPara);#将参数转换为字符串
        #将参数传递给过滤框,可在过滤框注册表单插件获取此参数
        param=SysReportShowParameter();
        param.CustomParams.Add("参数标识",myParaStr);
#账表页面加载完毕
def OnLoad(e):
    return;#这里示例不执行后面的代码
    #若报表没有显示表头字段,可通过如下代码隐藏表头部分,以免显示一块空白区域,影响用户体验
    sp=this.View.GetControl[SplitContainer]("FSpliteContainer");
    sp.HideFirstPanel(True);#折叠分割容器上面部分

#报表页面数据加载完毕
def AfterBindData(e):
    listGrid=this.View.GetControl("FList");
    listGrid.SetCustomPropertyValue("AllowSorting"False);#关闭表头的排序功能
    reportModel=this.Model;#SysReportModel类型,报表数据模型
    billObj=reportModel.DataObject;#报表页面实体数据包
    reportView=this.View;#SysReportView类型,报表界面View
    titles=reportModel.ReportTitles;#获取账表服务插件中构建的报表表头字段集
    msg="";
    for title in titles:
        fldKey=title.TitleKey;#表头字段标识
        fldValue=title.TitleValue;#表头字段值
        fldCtl=reportView.GetControl(title.TitleKey);#获取表头字段控件
        #fldCtl.Enabled=True;#默认是锁定的,可通过此代码放开表头字段,允许编辑
        #fldCtl.Visible=False;#隐藏表头字段
    customFilterObj=reportModel.FilterParameter.CustomFilter;#报表过滤框快捷过滤实体数据包
    orgObj=customFilterObj["F_BPW_OrgId"];#获取组织过滤字段
    orgId=orgObj["Id"if(orgObj<>Noneelse "0";#获取组织Id
    this.Model.SetItemValueByID("F_BPW_OrgId",orgId,0);#给表头组织字段赋值成基础资料
    #this.View.ShowMessage(msg);

#按钮点击事件
def ButtonClick(e):
    key=e.Key.ToUpperInvariant();#按钮标识大写
    if(key=="F_BPW_TestBtn".ToUpperInvariant()):
        this.Model.SetItemValueByID("F_BPW_OrgId",0,0);
        reportModel=this.Model;#SysReportModel类型,报表数据模型
        customFilterObj=reportModel.FilterParameter.CustomFilter;#报表过滤框快捷过滤实体数据包
        customFilterObj["F_BPW_OrgId"]=None;#清空过滤数据包中的组织字段
        customFilterObj["F_BPW_OrgId_Id"]=0;
        this.View.Refresh();#清空组织后刷新,获取所有组织数据
        
#表头菜单点击事件
def BarItemClick(e):
    key=e.BarItemKey.ToUpperInvariant();#菜单标识大写
    if(key=="F_BPW_MyBtn".ToUpperInvariant()):
        reportModel=this.Model;#SysReportModel类型,报表数据模型
        rowCount=reportModel.GetRowCount();#报表数据总行数
        tab=reportModel.DataSource;#账表数据源DataTable,报表所有行数据
        x=rowCount;
        mytab=reportModel.GetData(0,x);#获取报表0-x行数据,返回DataTable对象
        tempTabName=tab.TableName;#账表临时表名称,每一次查询报表都会不一样
        msg=("表头菜单{0}点击啦!").format(key);
        this.View.ShowMessage(msg);

#格式化行数据,每一行会运行一次 
#在此事件中可以设置报表数据的颜色
def OnFormatRowConditions(args):
    if(args.DataRow.ColumnContains("orgName")==True):#根据字段标识判断是否显示了该字段
        ss= ("{0}").format(args.DataRow["orgName"]);    #获取字段值,这里是取组织名称
        if("蓝海" in ss):#组织名称包含"蓝海"
            fc=FormatCondition();
            fc.BackColor="#ccffff";#背景色
            fc.ForeColor = "#FF0000";#前景色
            #fc.ColorField = "orgName";#颜色字段
            #fc.ApplayRow = False;#适用整行,默认值为True,设置ColorField时,才会单独对字段设置颜色,否则应用整行
            args.FormatConditions.Add(fc);
    reportModel=this.Model;
    tab=reportModel.DataSource;
    allFlds=tab.Columns;#报表所有字段
    #循环对动态列进行判断,数量不为0显示颜色
    for fld in allFlds:
        fldKey=fld.ColumnName;
        if("_" not in fldKey or fldKey.StartsWith("F")==False):#非数量动态列,不做处理
            continue;#自定义的动态列名规则,我示例报表动态数量列名是F开头且包含下划线,其他字段均不满足此条件
        if(args.DataRow.ColumnContains(fldKey)==True):
            qty= float(args.DataRow[fldKey]);
            if(qty<>0):
                fc=FormatCondition();
                fc.BackColor="#CCCCCC";#背景色
                fc.ForeColor ="#FF0000";#前景色
                fc.ColorField = fldKey;#颜色字段
                fc.ApplayRow = False;
                args.FormatConditions.Add(fc);

#去除尾0,自定义方法供参考
def remove_exponent(i):
    t=str(i);
    return t.rstrip('0').strip('.'if '.' in t else t;
#单元数据格式化
#在这个事件里面可以对报表原输出的单元格内容做修改
def FormatCellValue(args):
    fldkey=args.Header.Key;#字段标识
    if(fldkey=="F2018_1_4" ):
        dr=args.DataRow;#获取当前行的数据
        valueStr= ("{0}").format(args.FormateValue);#获取该字段原输出值
        args.FormateValue=("{0}%").format(round(float(valueStr)*100,2));#转换成百分数
    elif(fldkey=="orgName"):
        dr=args.DataRow;#获取当前行的数据
        valueStr= ("{0}").format(args.FormateValue);#获取该字段原输出值
        args.FormateValue=valueStr.Replace("蓝海","***");#将组织名称中的"蓝海"替换成***
    elif("_" in fldkey and fldkey.StartsWith("F")==True):
        args.FormateValue=remove_exponent(args.FormateValue);#去除尾0
        #oldValue=Decimal.Parse(args.FormateValue);#转换成Decimal
        #args.FormateValue =oldValue.ToString("N");#设置千分位分隔符
    cellTye=int(args.CellType);#单元格类型,0:普通,1:合计,2:小计
    if(cellTye==1 and fldkey=="F2018_1_6"):#判断底部合计行,可对底部合计行做自定义计算修改
        #这里演示将F2018_1_6底部合计修改成:F2018_1_4+F2018_1_5
        newSumValue=float(args.DataRow["F2018_1_4"])+float(args.DataRow["F2018_1_5"]);
        args.FormateValue=("{0}").format(newSumValue);

#单元格超链接点击事件
def EntryButtonCellClick(e):
    row=e.Row;#点击超链接所在序号,从1开始
    fldKey=e.FieldKey.ToUpperInvariant();#点击单元格字段标识大写
    msg=("点击了第{0}行的[{1}]").format(row,fldKey);
    this.View.ShowMessage(msg);
    #e.Cancel=True;#取消点击事件
    #获取当前单元格的值
    reportModel=this.Model;
    tab=reportModel.DataSource;
    value=("{0}").format(tab.Rows[row-1][e.FieldKey]);

#单元格双击事件
#简单账表 表单不会触发EntityRowDoubleClick事件,用此事件代替
def CellDbClick(Args):
    #Args.Cancel=True;#取消事件,若二开标准报表,可以此取消标准功能自带的双击事件
    row=Args.CellRowIndex;#双击序号,从1开始
    fldKey=Args.Header.FieldName;#双击单元格的字段名
    #获取当前单元格的值
    reportModel=this.Model;
    tab=reportModel.DataSource;
    value=("{0}").format(tab.Rows[row-1][fldKey]);#也可以传其他字段名,即可获取其他字段值
    msg=("点击了第{0}行的[{1}],{1}值={2}").format(row,fldKey,value);
    this.View.ShowMessage(msg);

#行点击事件
def EntityRowClick(e):
    row=e.Row;#点击的行序号,从1开始
    #msg=("点击了第{0}行!").format(row);
    #this.View.ShowMessage(msg);
    reportView=this.View;
    selectedDataRows=reportView.SelectedDataRows;#获取选中行,若启用了允许多选,则可获取到所有选中行
    if(selectedDataRows==None or selectedDataRows.Length==0):#无选中行数据
        return;
    #下面实现选中行合计功能
    dt=selectedDataRows[0].Table;
    allFlds=dt.Columns;#报表所有字段
    jsonArr=JSONArray();
    DIC={};
    DIC["F2018_1_4"]="2018-1-4";#添加需要合计的字段标识和字段标题的字典
    DIC["F2018_1_5"]="2018-1-5";
    for fldKey in DIC.keys():
        columnIndex=allFlds.IndexOf(fldKey);
        sumValue=0;
        for selectRow in selectedDataRows:
            fldValue=float(selectRow.ItemArray[columnIndex]);#取出选中行对应字段的值
            sumValue=sumValue+fldValue;
        jsonObj=JSONObject();
        jsonObj.Put("Value",remove_exponent(sumValue));
        jsonObj.Put("Caption",("{0}:").format(DIC[fldKey]));
        jsonArr.Add(jsonObj);
    listGrid=this.View.GetControl("FList");
    listGrid.SetSelectRowsTips(jsonArr);#输出到前端,按下alt键并把鼠标放到选中行的区域,即可看到效果

四、经典实践案例参考

    有了账表表单插件确实可以丰富很多功能,以下是整理的各位大佬分享的一些账表表单插件的常用案例。

    大多是C#插件示例,但是结合上面常用事件介绍中的Python示例,使用Python插件实现也不是难事。


==========================本篇正文结束=====================================

用2篇文章把Python账表开发的核心介绍完了,应该能满足95%以上的报表需求了。

示例代码已经上传附件,老规矩,大家按需下载!

感谢大家持续关注,点赞、评论、收藏,您的点赞、评论就是我前进的动力。


下一篇:【Python插件入门】第9篇-单据转换插件

简单账表-表单插件示例(全).rar(3.86KB)