实体服务规则如何条件地设置单据体字段汇总到单据头字段原创
金蝶云社区-文安根
文安根
25人赞赏了该文章 4,856次浏览 未经作者许可,禁止转载编辑于2022年01月20日 15:12:00

    以销售订单为例,假设客户在销售订单单据头上二开一个名称为'F_ora_QtySum'数量字段(在基本信息页签中),如下图1-1所示:

image.png

    图1-1


    标准功能中销售订单单据体上已有一个FQty字段,那如何设置将单据体中所有单位为kg的物料的数量汇总到单据头二开的字段‘F_ora_QtySum’上呢?此时可以在单据头基本信息的实体服务规则中再添加一个类型为‘计算定义公式的值并填写到指定列’的服务,前提条件可设置为:FQty <> null AND FQty <> 0 AND FMaterialId <> null  ,如下图1-2所示:image.png

图1-2


    注意:虽然是在单据头基本信息上写的实体服务规则,且在写前提条件中可选择的字段只有基本信息页签中的字段和一些函数,但是还是可以自行输入单据体中的字段作为前提条件表达式。‘计算定义公式的值并填写到指定列’中的表达式为:F_ORA_QTYSUM = sum(map(lambda x : (x.FQty if(x. FUnitID<>null and x.FUnitID.FNumber.__eq__('kg')) else 0), FSaleOrderEntry))

如下图1-3所示: 

图1-3


    这里说明一下,如果需求是要在更新'销售数量'时就条件汇总到二开的'F_ora_QtySum'字段中,那图1-2的前置条件表达式就要包含FQty且要在BOSIDE中勾选FQty字段的'即时触发更新事件',另外,如果图1-3的'计算定义公式的值并填写到指定列’是复合条件,比如说限制销售单位必须为kg且仓库必须是X仓才汇总二开字段,那么最好也要在前置条件中包含单位和仓库,这样就能达到更新仓库或单位时重新计算汇总值,同理真实环境最好也要在图1-3中勾选'行删除',因为删除行时一般也是要重新计算汇总值,论坛地址‘ https://vip.kingdee.com/article/87214388838194432  ’ 中的这个表达式是错误的,它没有按python语句写,如下图1-4所示:

image.png

图1-4


    针对上面的表达式,如果是写在订单明细单据体中的实体服务规则,则会报‘BOSDynamicRow is not iterable’异常,猜测是BOS平台在解析订单明细单据体的实体服务规则时会把FSaleOrderEntry当作一个单独的对象BOSDynamicRow,而在单据头中解析实体服务规则时会把FSaleOrderEntry当成一个列表对象传给python。而python的函数map(function, iterate)中的第二个参数是需要对象列表的,所以这种情况必须写在基本信息单据头而不是订单明细单体的实体服务规则中。另外,在上面的图1-4所示的表达式中,如果写了ToString()方法(此方法只是C#的写法,python是str()),这个也不会有报错提示,个人猜测是在python语法中,map函数调用lambda表达式抛出的异常信息(原始信息由lambda抛出)被sum函数容错处理了,导致sum函数返回0,有点像数据库SUM聚合函数,从不汇总null值,就像python一样,不汇总有异常的数据。但如果修改sum为len函数,则异常信息就比较明显了,这可能是len函数不容错异常,直接抛出来了,如下图1-5所示:

image.png

图1-5

    另外,上面图1-3中的类似的读取单据体FSaleOrderEntry的表达式如果写在后端保存插件中也是可行的,此时不会抛BOSDynamicRow is not iterable’异常,参看:https://vip.kingdee.com/article/141900810463701760


赞 25