具体包含如下内容
1、采购审批的基本配置
2、采购审批策略的常见问题
3、采购审批策略不生效或者错误的主要原因和解决思路
4、采购订单的修改与重新审批
5、采购订单的修改(重新审批)与采购订单输出
6、S4变化点
7、如何设置修改其他字段(如交货日期)也触发采购订单的重新审批。
1、采购审批的基本配置
参见“SAP专业咨询”公众号上的三篇文章。
SAP 采购订单审批策略实例详解(一)
SAP 采购订单审批策略实例详解(二)
SAP采购审批策略常用表以及出口增强
2、采购审批策略的常见问题
问题1:哪些字段可以用来确定采购订单审批的策略
可直接用来进行采购订单审批的字段在表CEKKO中,包含公司代码、采购组、采购组织、采购订单类型、采购订单不含税总金额、供应商、国际贸易条款、工厂、物料组、采购版本号等字段。
可以通过增强进一步增加字段。
问题2:如果使用采购订单的行项目字段,有何注意点。
采购订单的下达是基于抬头层面,行项目级别的字段(如工厂、物料组)可以汇总到抬头中,具体方式如下:
以工厂为例,如果采购订单的所有行项目的工厂是一样的,则系统将会使用该工厂代码,如果行项目中有二个工厂,系统将给工厂赋予一个空值'',此时就根据空白值去查找审批策略。
从这个逻辑触发,大部分情况下还是应该使用采购订单的抬头字段,确保每张采购订单有唯一性。
问题3:如果使用成本中心、物料编码、版本号码、项目类别作为审批条件,是否可以,有何注意点
核心注意点是需要使用数据库表中的值。
其中对于成本中心、物料编码、版本号码、供应商等字段来说,可能需要增加前导零(leadingzeros),因为成本中心、版本号这些字段在后台数据库中往往是 0打头的,在前台显示是系统去除了前导零.
对于项目类别,需要使用内部编号。如委外业务的项目类别为L,其在后台的数据库中是数字3.
3、采购审批策略不生效或者错误的主要原因和解决思路
首先通过事务代码CL20N查看审批策略的分类,是否分类与后台的配置一致,或者根据事务代码CL30N反查分配的类是否正确,是否一致。
如下图所示,使用事务代码CL30N检查,首先输入采购审批的分类,然后输入相应的值,查看是否可以查找到正确且唯一的审批策略。
其次是确保审批策略分类用到的特征值输入准确,是否存在上文的一些注意点,如应该输入前导零。
在少部分情况下,需要通过程序删除已有的配置(分类),具体程序为RCCLZUOB,输入类032,对象:KSSK,其中字段“删除”,不输入代表仅仅检查,输入X,则删除已有的配置。
备注:涉及删除操作,请谨慎处理。
4、采购订单的修改与重新审批
采购订单已经审批后,采购订单是否可以修改、修改后是否重新触发审批,这是一个业务问题,在SAP中,如下图所示,系统通过可变性(Changeability)这一参数来控制相应的逻辑,具体分为三个层次
-
第一个层次是:是否可以对已经审批的采购订单进行修改?
-
第二个层次是:假设层次1的结论是允许修改,那么是否触发审批?
-
第三个层次是:基于层次2,如果修改触发审批,那么具体在什么场景下将会重新触发审批(需要再次审批),场景又可以进一步细分为三种情况
场景1:采购订单的修改导致的采购订单总金额变化(Valuechange),此时是否重新触发审批,具体示例如下:
系统标准逻辑对采购订单的进行修改造成整张采购订单金额变大时,系统将会触发重新审批。
注意只有金额变大才会重新触发审批,其他情况(金额变小或者单价变化等,修改交货日期等)都不会触发重新审批。
同时系统可以设置比例,如定义“值更改”为10%,此时假设已经审批的采购订单总金额为10000元,则修改后的采购订单中总金额大于11000时,就会重新触发审批。
场景2:采购订单的修改导致新的审批策略(newstrategy),此时重新触发审批,具体示例如下:
假设采购组影响采购审批策略,其中采购组A1、A2的审批代码为Z1,采购组B1、B2的审批代码为Z2,审批代码Z1和Z2分布代表不同的采购审批角色,如果将采购订单的采购组从A1改成A2,由于二个采购组确定的是相同的审批代码Z1,也就是审批策略保持不变,那么此时不会触发重新审批,采购订单的状态将仍然是批准状态。但如果采购订单的采购组从A1改成B1,由于审批代码需要从Z1改成Z2,所以采购订单的状态将会重新设置(Reset),状态变成未审批状态。
场景3是一个特殊的场景,是指采购订单已经输出(Output)的情况下,输出在SAP中是指通过打印或者EDI的输出形式发给供应商,这个场景我们在下一部分介绍。
具体如下图所示,可变性存在6个选项
-
可变性的值为1:当PO为批准状态,不可以对PO进行任何修改。
-
可变性的值为2:当PO为批准状态,可以对PO的修改,任何的修改将不会触发重新审批,也就是PO仍然是批准状态。
-
可变性的值为3:当PO为批准状态,可以对PO进行各种字段的修改,当某个字段的修改影响新的审批策略,则将会触发重新审批,状态变成未审批的状态。其他字段的修改不会导致重新审批。
-
可变性的值为4:当PO为批准状态,可以对PO进行各种字段的修改,当某个字段的修改影响新的审批策略或者导致采购订单金额变大,则将会触发重新审批,状态变成未审批的状态。其他字段的修改不会导致重新审批。
-
可变性的值为5:与策略3类似,差异在于采购订单已经输出(Output)这一特殊场景的影响,具体差异在下文中描述
-
可变性的值为6:与策略4类似,差异在于采购订单已经输出(Output)这一特殊场景的影响,具体差异在下文中描述
5、采购订单的修改(重新审批)与采购订单输出
采购订单的成功输出是一个非常关键的业务操作,代表采购订单目前正在发送给供应商或者已经发送给供应商,甚至供应商已经将物资发出。当采购订单是成功输出状态,对采购订单的修改、审批都有直接的影响,需要有不同的处理流程。
备注:采购订单输出的形式多样,可能是打印、或者电子邮件,或者通过EDI直接与供应商系统连接,假设采用系统标准的输出功能,如下图所示,状态为绿色,代表采购订单已经成功输出。
如果上文中的采购审批策略中的可变性选择3或者4,将会产生二个结果
-
无法取消审批
采购单如果已经成功输出(如打印),则系统不允许取消审批,具体如下图所示,在ME29N中,直接点击取消,系统将报错,提示采购订单已经输出,消息号为ME175。
-
不会触发新的审批
采购订单打印后,可以修改采购订单,如增加金额或者修改采购组,但此时系统不会重新触发采购审批,也就是审批状态始终为已审批状态。
如果我们希望采购订单成功输出后,还可以重新触发审批的,则有如下几种方式
-
一种方式是不采用系统标准的输出功能,采用自定义的输出
-
另外一种方式是将可变性修改为5或者6,此时当修改采购订单,导致采购金额变大或者导致新的审批策略,就可以重新触发采购订单的审批。
-
还有一种方式是从执行层面进行操作,通过修改采购订单的输出让系统认为当前采购订单处于未成功输出的状态,具体操作方式可以是事务代码ME22N或者ME9F,以ME22N为例,点击到采购订单输出界面,选择成功输出的行,然后点击重复输出,系统会复制一个新的输出,颜色为黄色(未处理)然后保存。
此时由于存在一个没有成功输出的消息,就可以使用ME28/ME29N撤消采购订单的审批,同时当修改采购订单的字段(如采购组或者单价变大),也可以触发新的采购审批策略。
6、S4变化点
在S4中,系统提供了另外一种基于BRF的采购订单审批方式。
如下图所示,勾选如下配置,则代表采用新方式,原有的配置方式不再生效。在大部分项目中,还是采用原有的ECC的采购审批策略。
备注:具体的配置路径未“物料管理>采购>采购订单>采购订单的下达过程>激活采购订单的灵活工作流”
7、如何设置修改其他字段(如交货日期)也触发采购订单的重新审批。
标准功能无法实现,下图示例是通过增强的方式,灵活实现通过配置的方式触发采购订单的重新审批。
如根据特定项目(客户)的需求,配置采购订单的交货日期、付款条款发生变化,则触发采购订单的审批。
三个基本知识:
知识点1:BAPI“BAPI_PO_RESET_RELEASE”可用来设置采购订单的状态为未审批,输入参数为采购订单号码和审批代码。
知识点2:增强“ME_PURCHDOC_POSTED”中有采购订单修改前的数据和采购订单修改后的数据,因此可以用来判断采购订单的哪些字段被修改了。
知识点3:调用“BAPI_PO_RESET_RELEASE”设置采购订单的状态为未审批,需要这张采购订单本身可以在前台取消审批,如通过ME29N可以取消审批状态。
完整示例代码与步骤如下
1、建立表ZPO_CHANGE
表中包含三个参数:采购订单类型、表和字段,通过这个表设置根据采购订单类型配置当采购订单的哪个字段修改,可以触发采购订单新的审批。
强烈建议
项目实施过程中,将hardcode的代码变成可维护的表,这一步非常关键,当系统实现方式从硬代码变成数据(表),这样可以灵活的适应企业的业务发展与变化。
如下图所示,本例中,针对采购订单类型NB设置采购订单抬头的二个字段(付款条款EKKO-ZTERM和汇总号)和行项目的二个字段(数量和库存地点)发生变化时,需要重新触发审批。
2、在增强ME_PURCHDOC_POSTED中根据上一步骤的Z表,判断是否需要重新触发采购订单的审批,具体代码如下
METHOD if_ex_me_purchdoc_posted~posted.
DATA:zekpo_change TYPE char1,
zekko_change TYPE char1.
DATA:lt_fields TYPE TABLE OF zpo_change.
FIELD-SYMBOLS:<fs_fields> LIKE LINE OF lt_fields,
<fs_ekpo_new> TYPE uekpo,
<fs_ekpo_old> TYPE uekpo,
<fs_new_i> TYPE any,
<fs_old_i> TYPE any,
<fs_new_h> TYPE any,
<fs_old_h> TYPE any.
CLEAR zekpo_change.
CLEAR zekko_change.
*判断PO抬头的更改,是否需要重新触发审批
SELECT *
FROM zpo_change
INTO TABLE lt_fields
WHERE tabname = 'EKKO' AND bsart = im_ekko-bsart.
CHECK sy-subrc = 0.
LOOP AT lt_fields ASSIGNING <fs_fields>.
IF zekko_change IS INITIAL.
ASSIGN COMPONENT <fs_fields>-fieldname OF STRUCTURE im_ekko_old TO <fs_old_h>.
CHECK <fs_old_h> IS ASSIGNED.
ASSIGN COMPONENT <fs_fields>-fieldname OF STRUCTURE im_ekko TO <fs_new_h>.
CHECK <fs_new_h> IS ASSIGNED.
IF <fs_old_h> <> <fs_new_h>.
zekko_change='X'.
ENDIF.
UNASSIGN:<fs_old_h>, <fs_new_h>.
ENDIF.
ENDLOOP.
CLEAR lt_fields.
REFRESH lt_fields.
*判断PO行项目的更改,是否需要重新触发审批
SELECT *
FROM zpo_change
INTO TABLE lt_fields
WHERE tabname = 'EKPO' AND bsart = im_ekko-bsart.
CHECK sy-subrc = 0.
LOOP AT lt_fields ASSIGNING <fs_fields>.
CHECK zekpo_change IS INITIAL.
LOOP AT im_ekpo ASSIGNING <fs_ekpo_new> .
READ TABLE im_ekpo_old ASSIGNING <fs_ekpo_old>
WITH KEY ebelp = <fs_ekpo_new>-ebelp.
IF sy-subrc <> 0.
zekpo_change='X'.
ELSE.
IF zekpo_change IS INITIAL.
ASSIGN COMPONENT <fs_fields>-fieldname OF STRUCTURE <fs_ekpo_old> TO <fs_old_i>.
CHECK <fs_old_i> IS ASSIGNED.
ASSIGN COMPONENT <fs_fields>-fieldname OF STRUCTURE <fs_ekpo_new> TO <fs_new_i>.
CHECK <fs_new_i> IS ASSIGNED.
IF <fs_old_i> <> <fs_new_i>.
zekpo_change='X'.
ENDIF.
UNASSIGN:<fs_old_i>, <fs_new_i>.
ENDIF.
ENDIF.
ENDLOOP.
ENDLOOP.
CLEAR lt_fields.
REFRESH lt_fields.
IF zekko_change ='X'OR zekpo_change ='X'.
CALL FUNCTION 'ZMM_PO_RESET_RELEASE'
EXPORTING
purchaseorder = im_ekko-ebeln.
ENDIF.
ENDMETHOD.
3、在增强ME_PURCHDOC_POSTED设置,如果需要触发重新审批,则调用BAPI“BAPI_PO_RESET_RELEASE”,取消采购订单的审批状态。
为了程序可读性更加高和通用性更加强,首先额外创建一个函数ZMM_PO_RESET_RELEASE,相比标准BAPI,这个函数中传入的参数更加简单变成只有一个参数:采购订单编号(PURCHASEORDER),也就是通过这个函数只需要传入采购订单就可以取消审批,具体代码如下:
FUNCTION zmm_po_reset_release.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" VALUE(IV_PO_ORDER) TYPE EBELN
*"----------------------------------------------------------------------
FIELD-SYMBOLS:<lf_rel_code> TYPE bapimmpara-rel_code.
DATA: rel_status_new TYPE bapimmpara-rel_status,
rel_indicator_new TYPE bapimmpara-po_rel_ind,
return TYPE TABLE OF bapireturn.
DATA:ls_return TYPE bapireturn,
lt_bapireturn TYPE TABLE OF bapireturn,
ls_release_info TYPE bapirlgnpo,
ls_release_posted TYPE bapirlcopo,
lf_comp_num TYPE i,
lf_string TYPE string,
lf_error TYPE flag.
CALL FUNCTION 'BAPI_PO_GETRELINFO'
EXPORTING
purchaseorder = iv_po_order
IMPORTING
general_release_info = ls_release_info
release_already_posted = ls_release_posted
TABLES
return = lt_bapireturn.
lf_comp_num = 2.
DO 1 TIMES. "几级审批,测试场景只有1级审批,因此循环1次,根据需要可以循环N次,采购审批层次可以支持8个层次。
ASSIGN COMPONENT lf_comp_num OF STRUCTURE ls_release_posted TO <lf_rel_code>.
IF <lf_rel_code> IS NOT INITIAL.
CALL FUNCTION 'BAPI_PO_RESET_RELEASE'
EXPORTING
purchaseorder = iv_po_order
po_rel_code = <lf_rel_code>
use_exceptions = space
IMPORTING
rel_status_new = rel_status_new
rel_indicator_new = rel_indicator_new
TABLES
return = return.
LOOP AT return INTO ls_return WHERE type = 'E' OR type = 'A' .
EXIT.
ENDLOOP.
IF sy-subrc NE 0 .
WAIT UP TO 3 SECONDS.
ENDIF.
ENDIF.
lf_comp_num = lf_comp_num + 1.
ENDDO.
IF zekko_change ='X'OR zekpo_change ='X'.
CALL FUNCTION 'ZMM_PO_RESET_RELEASE'
EXPORTING
purchaseorder = im_ekko-ebeln.
ENDIF.
ENDFUNCTION.