在SAP
HCM实施项目中,在某些特殊的情况下,SAP提供的标准函数(Function)和操作(Operation)无法满足客户的特定需求,顾问可能需要增强开发客户自定义的函数和操作,虽然以我的项目经验来看,虽然这是极少发生的事例,但也不是不可能发生。
本文以工资计算函数和操作为例,介绍开发用户自定义函数和操作的步骤和注意事项。
一、定义步骤
步骤一:运行TCODE
PE04,输入自定义函数或者操作的名字,然后选择对象类别(工资计算用或者考勤核算用)和对象类型(函数或者操作),点击创建(Create)按钮后进入下一屏幕。
步骤二:选择对应的FORM子例程名字,建议使用系统默认生成的标准名字,也可以使用自定义的FORM子例程名字,然后选择使用该函数或者操作的国家分组,如果是考勤核算使用的函数或者操作,选择所有国家分组,然后选择参数格式、参数和参数值,最后保存并激活定义的函数或者操作;
步骤三:使用TCODE SE38 显示程序 HCNCALC0,
找到Include
程序PCBURZCN0,这个Include是SAP预留给客户写自己定义的函数和操作代码的地方,但也需要修改对象的Access
Key,Access Key可以通过SAP的客户支持平台申请;
步骤四:
在程序PCBURZCN0中的紧急修改模式下,定义Operation或者Function对应的FORM,FORM的名字为:如果是函数,在Function的名字前加前缀FU,如果是操作,在Operation的名字前加前缀OP。这时候可以先不写任何的实现代码,保存后激活程序PCBURZCN0。
步骤五:使用工具程序RPUCT700或者RPUCT300生成包含自定义函数和操作的 Turbo
Case过程选择Include程序PCBO1CN0和PCOIPCN0等,RPUCT700也是调用的RPUCT300,两个程序无本质区别,均可以使用;在输出日志里或者生成的PCOIPCN0可以看到自己的定义的函数或者操作包括在Turbo
Case中,才算生成成功。
步骤六:再次使用TCODE
PE04编辑自定义的Function或者Operation,点击源代码按钮,这时候系统自动跳转到 程序PCBURZCN0中
对应的子例程FORM,这时候就可以写FORM子例程的代码逻辑了。
二、注意事项:
1)一般情况,尽量使用标准的函数和操作及参数组合以满足客户的需求,不到万不得已不建议自己开发客户自己定义的函数和操作。
2)在自己写的代码中尽量不要修改工资核算程序使用的标准内表如WPBP、APER等,也不要改变其中记录的顺序,除非自己有充分的把握。如果确实需要对标准内表做排序或者临时修改其内容,可以先存在一个局部内表中,在结束函数或者操作的代码的时候恢复系统标准的内表。
3)对IT表和VAR表可以增加新的记录,但一般不要删除表中已经存在的记录。
4)客户自定义的函数和操作的命名要遵从SAP预留给客户的命名空间,不要使用SAP标准函数和操作对象的命名范围。使用工具程序RDDKOR54可以查询SAP预留给客户自定义函数和操作对象的命名空间,输入表名为T52A0,可以的命名空间如下图所示。
5)
用于考勤核算的客户自定义的函数和操作的代码存放在哪个INCLUDE,尚不清楚,SAP有没有预留INCLUDE需要进一步确认。
三、例子代码
需要定义一个OPERATION,用于读取和汇总员工2017年1-7月和工人2017年1-8月的奖金计提额(工资项1090),然后存放在VAR表的变量2018中备用。下面是一个计算和往
VAR中插入变量的程序例子,该变量可以在该操作被调用后使用 。
1) 在工资计算规则中调用自定义的OPERATION
-------------+---------+---------+---------+---------+---------+---------+
D CMPER
JJ18 "YEAR 2018
<
ERROR
=
D AMT?0
= *
= >
ADDWT *
ADDWT 4010_1090
AMT=& 2018SUBWT 4010NEXTR
A
= >
A AMT=L 4009SUBWT 4010SUBWT
4009
>
D AMT?0
> *
> >
ADDWT
* ADDWT 4010AMT=L 4009SUBWT
4010SUBWT 4009
其中
_1090就是自定义的Operation,它完成读取员工2017年1到7月或者8月的工资项1090,累加后存放在变量表VAR中的变量2018的AMT字段,供后面的Operation
AMT使用.
2)程序代码
*----------------------------------------------------------------------*
* INCLUDE PCBURZCN0 *
* Customer functions and operations *
* Use this include to create customer *
* specific functions and operations *
* Attention: Never change or transport this include in SAP systems *
*----------------------------------------------------------------------*
*{ INSERT DEVK905020 1
form op_1090.
data: gt_rgdir type table of pc261,
gs_rgdir type pc261,
gt_rgdir_final type table of pc261,
gv_relid type relid_pcl,
gv_molga type molga,
gv_type type t52relid-typename,
gv_id type i,
ref_payresult type ref to data,
gs_wpbp type pc205,
gs_rt type pc207,
gv_date_begin like sy-datum,
gv_date_end like sy-datum,
gv_yifa type i.
data: l_1090 type pc207-betrg.
field-symbols: type any,
type hrpay99_rt.
refresh gt_rgdir.
call function 'CU_READ_RGDIR'
exporting
persnr = pernr-pernr
tables
in_rgdir = gt_rgdir
exceptions
no_record_found = 1
others = 2.
if sy-subrc = 0.
clear: gv_relid,gv_molga.
call function 'PYXX_GET_RELID_FROM_PERNR'
exporting
employee = pernr-pernr
importing
relid = gv_relid
molga = gv_molga
exceptions
error_reading_infotype_0001 = 1
error_reading_molga = 2
error_reading_relid = 3
others = 4.
if sy-subrc = 0.
select single typename
from t52relid
into gv_type
where relid eq gv_relid
and tabname = 'PCL2'.
if sy-subrc ne 0.
gv_relid = 'CN'.
gv_type = 'PAYCN_RESULT'.
endif.
create data ref_payresult type (gv_type).
assign ref_payresult->* to .
endif.
endif.
delete gt_rgdir where srtza ne 'A'.
refresh gt_rgdir_final.
clear gs_rgdir.
read table p0001 index 1.
if p0001-abkrs = 'A1'.
“办公室员工
gv_date_begin = '20170101'.
gv_date_end = '20170731'.
else.
“现场工人
gv_date_begin = '20170101'.
gv_date_end = '20170831'.
endif.
loop at gt_rgdir into gs_rgdir where payty = ''
and fpbeg ge gv_date_begin
and fpend le gv_date_end.
append gs_rgdir to gt_rgdir_final.
clear gs_rgdir.
endloop.
sort gt_rgdir_final by seqnr.
clear gs_rgdir.
loop at gt_rgdir_final into gs_rgdir.
call function 'PYXX_READ_PAYROLL_RESULT'
exporting
clusterid = gv_relid
employeenumber = pernr-pernr
sequencenumber = gs_rgdir-seqnr
changing
payroll_result =
exceptions
illegal_isocode_or_clusterid = 1
error_generating_import = 2
import_mismatch_error = 3
subpool_dir_full = 4
no_read_authority = 5
no_record_found = 6
versions_do_not_match = 7
error_reading_archive = 8
error_reading_relid = 9
others = 10.
if sy-subrc eq 0.
assign component 'INTER-RT' of structure to .
if gs_rgdir-abkrs = 'A1'.
loop at into gs_rt.
case gs_rt-lgart.
when '1090'.
l_1090 = l_1090 + gs_rt-betrg.
exit.
when others.
continue.
endcase.
clear gs_rt.
endloop.
elseif ( gs_rgdir-abkrs = 'A2' or gs_rgdir-abkrs = 'A3' ).
loop at into gs_rt.
case gs_rt-lgart.
when '1000'.
l_1090 = l_1090 + gs_rt-betrg * 150 / 1200 .
exit.
when others.
continue.
endcase.
clear gs_rt.
endloop.
endif.
else.
endif.
endloop.
var-lgart = '2018'.
var-betrg = l_1090.
var-amt_curr = 'CNY'.
collect var
endform.