on 12-14-2007 2:19 PM
When I read the SAP-Press Book "mySAP HR: Technical Principles and Programming"
(actually it was the german edition "Technische Grundlagen und Programmierung")
I came across Chapter 9.1.3 "Using BAPIs", in which some sample code is provided
for updating the email-adress in infotype 0105 "communication".
I just thought: "OK, that could be easily (and better !) done with PERL and SAPNWRFC".
My PERL-script should do the following:
1) Read subtypes 0001 and 0010 from IT 0105 via RFC
2) Compare that data against our LDAP-Server
3) call the approbiate BAPIs for updating IT 0105 via RFC
OK, here's the ABAP-code which accomplishes task #1:
[code]
Z_EMAIL_TAB is a customer-defined structure with 3 components:
component component-type
MY_PERNR PERNR_D
MY_NICKN SYSID
MY_EMAIL COMM_ID_LONG
FUNCTION z_read_email.
*"----
""Lokale Schnittstelle:
*" IMPORTING
*" VALUE(MY_DATE) TYPE ENDDA OPTIONAL
*" TABLES
*" Z_EMAIL STRUCTURE Z_EMAIL_TAB
*"----
DATA: sql_date TYPE begda,
sql_mandt type mandt.
DATA: BEGIN OF wa_ldap_out,
pernr TYPE pernr_d,
nickn TYPE sysid,
email TYPE comm_id_long,
END OF wa_ldap_out.
DATA: exc_ref TYPE REF TO cx_sy_native_sql_error,
error_text TYPE string.
IF my_date IS INITIAL.
MOVE sy-datum TO sql_date.
ELSE.
MOVE date TO sql_date.
ENDIF.
we use native SQL (Oracle), so we have to specify the mandant
exclude-values for PERSK refer to pensionists etc
move sy-mandt to sql_mandt.
EXEC SQL.
open dbcur for
SELECT DISTINCT
pa0001.pernr,
pa0105_0001.usrid,
pa0105_0010.USRID_LONG
FROM pa0000 pa0000,
pa0001 pa0001,
pa0105 pa0105_0001,
pa0105 pa0105_0010
WHERE
pa0000.pernr = pa0001.pernr and
pa0000.begda <= :sql_date AND
pa0000.endda >= :sql_date AND
pa0001.begda <= :sql_date AND
pa0001.endda >= :sql_date AND
pa0001.persk NOT IN ('12' ,'13' ,'17' ,'18') AND
pa0000.stat2 = '3' and
(pa0001.mandt = pa0105_0001.mandt() and pa0001.pernr = pa0105_0001.pernr() and pa0105_0001.usrty() = '0001' and pa0105_0001.begda() <= :sql_date and pa0105_0001.endda(+) >= :sql_date) and
(pa0001.mandt = pa0105_0010.mandt() and pa0001.pernr = pa0105_0010.pernr() and pa0105_0010.usrty() = '0010' and pa0105_0010.begda() <= :sql_date and pa0105_0010.endda(+) >= :sql_date) and
pa0000.mandt = pa0001.mandt and
pa0000.mandt = :sql_mandt
ENDEXEC.
DO.
EXEC SQL.
FETCH NEXT dbcur into :wa_ldap_out
ENDEXEC.
IF sy-subrc <> 0.
EXIT.
ELSE.
APPEND wa_ldap_out to z_email.
ENDIF.
ENDDO.
EXEC SQL.
close dbcur
ENDEXEC.
ENDFUNCTION.
[/code]
Using Native-SQL (we have an Oracle-Backend) saves us from looping through IT0105 twice.
(I don't like ABAP's Open-SQL, it's too limited)
Now we have a nice little table with all our employees pernr, userid and email-adress.
Let's stay on the ABAP-side and have a look at the update-function (task #3):
[code]
FUNCTION z_upd_smtp .
*"----
""Lokale Schnittstelle:
*" IMPORTING
*" VALUE(MY_PERNR) TYPE PERNR_D
*" VALUE(MY_EMAIL) TYPE AD_SMTPADR
*" VALUE(MY_DATE) TYPE BEGDA OPTIONAL
*" TABLES
*" BAPIRETURN STRUCTURE BAPIRETURN1
*"----
DATA: wa_bapireturn TYPE bapireturn1.
IF my_date IS INITIAL.
MOVE sy-datum TO my_date.
ENDIF.
CALL FUNCTION 'BAPI_EMPLOYEET_ENQUEUE'
EXPORTING
number = my_pernr
validitybegin = my_date
IMPORTING
return = wa_bapireturn.
IF wa_bapireturn-type NE 'E'.
CLEAR wa_bapireturn.
CALL FUNCTION 'BAPI_EMPLCOMM_CREATE'
EXPORTING
employeenumber = my_pernr
subtype = '0010'
validitybegin = my_date
validityend = '99991231'
communicationid = my_email
NOCOMMIT =
IMPORTING
return = wa_bapireturn
EMPLOYEENUMBER =
SUBTYPE =
OBJECTID =
LOCKINDICATOR =
VALIDITYBEGIN =
VALIDITYEND =
RECORDNUMBER =
.
APPEND wa_bapireturn TO bapireturn.
CALL FUNCTION 'BAPI_EMPLOYEET_DEQUEUE'
EXPORTING
number = my_persnr
validitybegin = my_datum
IMPORTING
return = wa_bapireturn.
APPEND wa_bapireturn TO bapireturn.
ELSE.
APPEND wa_bapireturn TO bapireturn.
ENDIF.
ENDFUNCTION.
[/code]
And finally the PERL-Script (task #2):
[code]
##### Connect to LDAP-server #################################################
use Net::LDAP;
use Net::LDAP::Control;
use Net::LDAP::Constant qw(LDAP_CONTROL_PAGED);
$pagec = Net::LDAP::Control->new( LDAP_CONTROL_PAGED,
size => 1000);
--- replace with your company-specific values ------------------------------ #
$ldap = Net::LDAP->new( 'your-ldap-server' ) or die "$@";
$mesg = $ldap->bind( 'CN=your-ldap-user,CN=aaaa,DC=bbbb,DC=dd,DC=eeeeeee,DC=fff',
password => 'your-password'
);
use SAPNWRFC;
--- Connection to SAP ----------------------------------------------------- #
SAPNW::Rfc->load_config("your-config-file");
$sap_conn = SAPNW::Rfc->rfc_connect;
--- SAP RFCs --------------------------------------------------------------- #
SAP_RFCs();
--- read all Email-adresses from IT0105 ------------------------------------ #
$rd_handle_eml = $rd_eml->create_function_call;
$rd_handle_eml->invoke();
foreach $row_hashref_eml (@{$rd_handle_eml->Z_EMAIL}) {
$MY_PERNR = $row_hashref_eml->{MY_PERNR};
$MY_NICKN = $row_hashref_eml->;
$MY_EMAIL = $row_hashref_eml->;
$MY_NICKN =~ s/ //g;
$MY_EMAIL =~ s/ //g;
if ($MY_NICKN ne '') {
$strMail_LDAP = nick2email(lc($MY_NICKN));
if (lc($MY_EMAIL) ne lc($strMail_LDAP) && $strMail_LDAP ne '') {
updIT0105("$MY_PERNR","$strMail_LDAP");
print "SUCCESS = $i_uit_success, $MY_PERNR $strMail_LDAP\n";
}
}
else {
do some error-processing here
}
$sap_conn->disconnect();
exit;
############################################################################ #
sub SAP_RFCs {
--- Read E-Mail-Adress from IT0105 ----------------------------------------- #
$rd_eml = $sap_conn->function_lookup("Z_READ_EMAIL");
--- Update E-Mail-Adress in IT0105 ----------------------------------------- #
$rd_uit = $sap_conn->function_lookup("Z_UPD_SMTP");
}
########################################################################### #
sub nick2email {
$strNickn = $_[0];
$strEMail = '';
--- our userid is stored in LDAP-item "mailnickname", just change filter to your needs #
$filter = qq {
(& (mailnickname=$strNickn)
(givenName=*)
(| (objectCategory=person)
(objectClass=person)
)
)
};
while (defined ($search = $ldap->search(
base => "OU=your-base-OU,DC=bbbb,DC=dd,DC=eeeeeee,DC=fff",
filter => $filter,
attrs => ['mailNickname','mail','whenChanged'],
control => [ $pagec ]
) ) ) {
foreach $entry ($search->entries) {
$strEMail = $entry->get_value('mail') ;
}
($resp) = $search->control( LDAP_CONTROL_PAGED );
last unless ref $resp && $pagec->cookie($resp->cookie);
}
return $strEMail;
};
########################################################################### #
sub updIT0105 {
$rd_handle_uit = $rd_uit->create_function_call;
$rd_handle_uit->MY_PERNR($_[0]);
$rd_handle_uit->MY_EMAIL($_[1]);
$rd_handle_uit->invoke();
$i_uit_success = 1;
foreach $row_hashref_uit (@{$rd_handle_uit->BAPIRETURN}) {
if ($row_hashref_uit->{TYPE} ne 'S' && $row_hashref_uit-> ne ' ') {
$i_uit_success = 0;
}
}
};
[/code]
I run this script every Friday on a virtual Windows XP machine (VMWare) scheduled with the AT-Command
and it works really fine, enjoy !!!
P.S.: I hope there aren't any typos in the code, but please check
P.P.S: Thanks again to Piers for SAPNWRC, fantastic.
Hi,
I am very interested in your solution. Can you send me the scripts?
Greeting Jan
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.