HCM Processes & Forms offers a world of possibilities for automating HR and other employee related processes. However, as the old maps of the uncharted seas would note, “Here there be monsters”. I’ve become familiar with a few of these “monsters” over the past year. If you are not scared of dragons, trolls, ghosts, things-that-go-bump-in-the-night, cryptic error messages and endless short dumps, then pull up a chair, grab some popcorn and spend a little time reading my account of many of the battles I have fought and discoveries I have made with regards to HCM Processes & Forms.
I am just wrapping up a fairly large HCM Processes and Forms project that is actually part of a larger “MSS back-in-the-box” project. Prior to this work, I was vaguely familiar with HCM Process and Forms (HCM P&F) due to researching the “HR Administrator” business package (part of HR Administrative Services…HRAS) for a previous client. They loved what they saw, and I was ready to jump right in and get to it. Sadly, they were only on ECC 5, and HCM P&F along with HRAS was not released until ECC 6. Luckily, my very next project….the one I am finishing now…was ECC 6! This client wanted PCR-ish functionality to replace some custom written MSS Java apps. Upon more reading up on Personnel Change Request (PCRs) however, I discovered that PCRs were being replaced by HCM Processes & Forms (even says so in the SAP documentation!). PCRs are going the way of the dinosaur, so why start my client off already behind the times? This was a great opportunity to get HCM P&F in place!
That being said in my opinion, HCM P&F removes a lot of the limitations PCRs had and also adds loads of functionality. I will start off by saying, I think it is a great framework! However, like a new model of a great sports car, there will be a few hiccups to work out in the beginning. As HCM P&F is new with ECC6, it’s had it’s share as well. Even on our project, our beginning days with the delivered HCM P&F were trying to say the least. Once we upgraded to Enhancement Pack 2 for EA-HR, not only were many of our bugs/errors/etc corrected, but it also added even more functionality to HCM P&F. To that point, I would highly suggest that you at least start from EhP 2 when working with HCM P&F. The ABAP Webdynpro replacement to the older Java Webdynpro applications alone are worth the change!
The following are the main “gotchas”, bugs, oddities and curiosities that I have collected over my past year’s experience with HCM P&F. These are based on ECC6 EhP 2, so possibly some have been corrected (though I haven’t seen mention yet in current and coming enhancement packs). So in no particular order and without further adieu…..
(1) Process Creation Process Name (bug)
This is a little one (especially as you read down the others!), but it is an annoyance nonetheless. When you create a process, you are presented with a pop-up asking you for the process ID and description. Actually, the field called “Process Description” is the “Process Name” which is what appears in the “Start Application” for users to select a process. There is, in fact, another field for a true description (ie. long description) that appears along with the name during process selection.
workaround: Although you enter this during process creation, you can then change the process’ name and description fields in configuration.
(2) Message Mapping through the Design Time workbench (bug)
With Enhancement Pack 2, SAP released the “Design Time for Processes and Forms” which is a workbench-like replacement to all of the previous, individual IMG steps. From the Design Time, you are suppose to be able to accomplish everything that your would have done before by going into each individual node and making configuration changes. However, it seems this does not work in all cases. Through the Design Time workbench if you are doing “Message Mapping” to hide or change the wording of any message (warning, error, etc), you must enter which “Processor Role” for which this config applies. However, the “Processor Role” entry cuts off at 8 characters, but the field is actually 10 characters. This throws an error immediately on our custom entries which are 9 characters long and does not allow you to make configuration entries for those. The exact problem can be seen in function group HRASR00_DT_FORM_SCENARIO, screen 2120.
workaround: You can make your configuration entries/changes using the “old”, individual configuration node under “Configurtion of Forms”.
(3) Multiple Create operations – index only useful with time constraint 3
For the standard SAP_PA service’s operations, SAP provides a field for “Record Index”. This is used in the event that you need to load several records from form fields into the same backend service. For example if you were going to load 3 sets of amount, currency and begin/end date form fields into the same backend infotype, you would simply set the record index for the first set as “1”, the second set as “2” and the third set as “3. You might have something like….
However, because the infotype we select is not configured with a “time constraint” of 3 (“3” means that multiple records can occur even if dates overlap) but is set as time constraint 2 (meaning if records do exist, begin and end dates can not overlap) and even though we took great care to insure for ourselves that the dates do not overlap, we can not configure this as above making use of the “record index” field. We actually have to make 3 separate calls to SAP_PA as shown:
workaround: As shown in the image above, break up operations into multiple calls to SAP_PA with different form field values mapped to the same set of infotype screen structures, but all set to record index 1.
(4) Transfer of field values from one form scenario to another form scenario with multiple form steps (bug)
HCM Processes and Forms configuration allows you to pass form field values from one form (source) to another form scenario (target). In this way, the user’s entries can be passed around from form to form along the process which most likely contains many different forms and form steps. According to SAP’s documentation, “The field values are filled in the target form scenario when the fields become relevant for the first time.” Therefore, as an example, let’s say a user is on step 1 of a form scenario and some form field gets it’s value transferred from another form (i.e. the “source” scenario). The user will see this value as it came from the other form scenario. Now, let’s say the user changes this value and sends the form on it’s way. The next part of our process goes to step 2 within the same form scenario as step 1. The user on step 2 should now pull up the form and see the value for the form field as it was entered in step 1. However, this is not the case as we have seen over and over again in testing. The user in step 2 will actually see the form field value reset again to the value passed over by the “source” scenario. This is not suppose to happen even according to SAP’s help documentation!
workaround: You must split the “taget” scenario into two (or more…depending on the steps) form scenarios. The first one will still have it’s values transferred from the same source scenario. However now, you must transfer the entries from from the original target scenario on to the next “new” scenario (and on and on as the new scenarios require).
(5) Delete operation for subytpe “*” using standard SAP_PA service (bug)
Let’s consider an example where maybe you just need to delete (end date) a whole bunch of subtype for an infotype at once and just want to do it for “whatever is there”. According to SAP documentation, you can do this with the SAP_PA service by setting the infotype ot the infotype of choice, setting the operation to “DELETE” and setting the subtype to “*” (wildcard). Then, it will make the change to all of the subtypes that exist for that infotype. This keeps you from having to list out each one as well as insuring they even exist before trying to “delete”. Sounds great! Sounds simple! Doesn’t work. We set up such an operation and noticed that each and every time, it would only delete (end date) the FIRST subtype in our list. All others would be unaffected. After a day of debugging, I found the following:
First, we have a structure (SERVICE_OPERATIONS) that defines our operations. Here, we are saying we want to do a “delete” on infotype 168, 169 and 170:
Next, we have a structure (SERVICE_DATASETS) that collects all of our form fields that will be used in the operation above:
SERVICE_DATASETS (before bug)
Next, the code goes through and depending on our “wildcards” it creates another structure (STORED_PSKEYS) that “explode” out our wildcards to list which subtypes are actually available. Using our example, this might be:
So, now the code should go through our SERVICE_DATASETS and where it finds an “*” for our subtype, it should create as many entries for each of the actual subtypes in STORED_PSKEYS. However, our results are:
SERVICE_DATASETS (after bug)
This is due to a bug in the coding of class CL_HRASR00_PAITF_MAPPER’s method FILL_SUBTY_AND_OBJS. Around lines 52-55, you will see that is uses a field symbol incorrectly. As the code loops through our SERVICE_DATASET, it is looking for “*” to then replace with all entries from STORED_PSKEYS. So, it changes the first set. But then, as it loops again, because the field symbol changed our “*” to the first entry of STORED_PSKEYS, it no longer finds an “*” again and moves on to the next set of SERVICE_DATASET fields.
workaround: None. For us, this was reported to SAP with all supported details (more than here). Even with all the information, we still had to go the rounds of giving them access, pointing them to an example, and blah blah blah. They have been “looking into it”…..for about 6 weeks now. (haha)
(6) Rules must use fields from service
A nice feature of HCM Process and Forms is that you can define “rules” and then use these “rules” to determine if an entire service will trigger or even if operations within the services will occur. Rules are just simple little “Excel-like” formulas which can use any form field but must evaluate to either true or false. It’s great that they allow them at both levels so you can control if all or some of a service is needed. This gives you some “dynamic” control. However, to my dismay, I found out a bit later that “rules” did not work quite how I had believed. For the longest time, I could not figure out why some of my rules seemed to have no effect. They checkedout fine using the rule checking tool. So what gives? It was only after reading the documentation again for the umpteenth time that I noticed something in the fine print. Per documentation, “If the rule is assigned to an operation of a back-end service, all form fields that are used in the rule must also be assigned to the back-end service.” Fields for rule must be in the service/operation?!?!? What?!?! Are you kidding me?!?!? You would think that there would be several cases where you want to use form fields to decide what services/operations to trigger based off of rules even though the form field is not part of the service itself. But then….there I go “thinking” again. (haha) For example, we have some radio buttons on a form that might determine if the user gets bonus pay or not, so we have a rule to check “IS_BONUS = ‘YES'”. However, when doing an infotype operation from standard service SAP_PA and wanting to use that rule to decide if the user gets the bonus or not, of course, the standard infotype does not have our little “is_bonus” field in it. Therefore, our rule is ignored.
workaround: None. Your only option is to get creative with generic services. For example, we might have a generic service that has the “IS_BONUS” field in it’s field list, but we don’t use it for anything in the service. Then, we can check our rule against the generic service (because it now has this field in it’s interface) and make the other changes to infotype fields we need. Then when we get to SAP_PA, we can either use new rules to check the infotype fields or simply do the operation based on whatever data we changed (if at all). Yes, it’s a hassle, but it works. (haha)
(7) Time Constraint not numeric (bug)
There are several parts of SAP’s standard service SAP_PA code where there are checks on the “time constraint” of an infotype. For example, you will often see “IF zeitb NE 3.”. However, “time constraint” (zeitb) can have all kinds of values like 1,2,3,A,B, etc. If the time constraint on an infotype we wish to use in an operation is not numeric then we get a nice short dump. For example, infotype 0415 might have a time constraint value of “B”. This causes a process to go **BOOM**!
workaround: None. We had to remove those infotypes from the operations or create our own custom enhanced generic services to deal with this until SAP provides a fix.
(8) SAP_PA operations do not allow multiple operations on same infotype/subtype controlled by rules
This one seems like a big oversight. If I have the service SAP_PA defined for my form scenario, and say in my list of operations maybe I want to perform different operations on the same infotype depending on the results of a rule. For instance, maybe in one case I want to change a person’s Main Address (create a new date delimited record), but in another condition, I want to perform a “change without delimit” (maybe they are staying at the same address longer now). This is what you get when trying to do this:
Even if you split your services up and have two different SAP_PA services listed with different operations defined in each, it still will not allow it and throws the same error.
workaround: None. Make use of generic services and rules to try to accomplish what you need either by setting fields as needed for one infotype operation or by making changes outside the SAP_PA service (this gets REAL messy and requires and Enhanced Generic Service).
(9) If you use a form field in many operations for one generic service split in separate calls , the defined fieldgroups get overwritten.
Suppose, we have a configuration for our backend services for a form scenario like this:
Here, we want to call a custom service, Z_PROC to do one operation (GET_ACTION) in it, then call SAP_PA, and then call Z_PROC again using a different operation (GET_REASON). This first call to Z_PROC might be configured as:
Then, we configure the second call to Z_PROC for a different method but using one of the same form fields as the first call:
Now, if you go back to the first service, you will see that the “field group” has been changed!
Why does it do this ?!?! The configuration of one service and operation should have no effect on others.
workaround: To correct this, we have two choices here that I have found work. First, if possible (though not always practical), we can configure our fields for the same service all in a single step. That is, we would have our service listed like:
And then the field would look like:
However, if this does not work, we have a second option. Of course, as in my example, you might actually need to do some operation, then do another like SAP_PA and then use that combined information to call yet another custom service. If so, split generic services into single method/operation. In our example, we would “break up” our Z_PROC service and make it into a single “operation” service and an new service with the other operation. This is not the best situation if you are trying to use services to group together similar operations (like making a “utility” service for date manipulation operations), however, it does work. If you actually look at SAP’s sample generic services, most all of them only have a single operation….and I think I found out why. (haha)
(10) Re-ordering Back-End Services
On the Back-End Services list screen, where it lists all the services assigned to your form scenario and their order, there is a “nice” feature where you can select a service and then click an up/down icon to move it up or down in the list. Sounds great! Ahhh but here’s the rub. For some reason, it will “absorb” all of the fields from any other service it “leaps” over. Then you have to go back into the service and “untangle” the mess that was made. No idea why it does this.
workaround: Your best bet, copy your service info over to Excel. Delete the service from the list. Make an “insert” point at where you wanted your service. Paste back over your service details into the new location.
(11) Standard Workflow Background Task Step
SAP provides several very useful standard Workflow task steps for HCM Processes and Forms. Amongst these is a background task “TS17900110: Import Field Value to WF Container Element” that looks so promising at first glance. It allows you to move Adobe form field values into your workflow container for you to then use for whatever you like within your workflow. You simply bind field/value pairs….like FORM_FIELD_NAME_1=EmployeeName, FORM_FIELD_VALUE_1….FORM_FIELD_NAME_2=EmployeeState, FORM_FIELD_VALUE_2…the task will read the “field” binding and then fill in the “value” binding to pass back. For multiple fields, you just keep incrementing your digit on the end of the “FORM_FIELD_NAME_x” and “FORM_FIELD_VALUE_x” bindings. Yep, just keep on incrementing away….1….2…..3….STOP! You can not pass over more than 3….yes, 3…..fields at a time. What?!?!? Did someone figure out that no one in their right mind would ever need more than 3 fields from a form? “But this one goes to 11…..one betta.” Fight it as much as you like, if you read some of the fine print in the help.sap.com documentation, it clearly states “You can use the task to read the values of a maximum of three fields.”
workaround: Well, your choices are rather slim here. Either you have to place multiple task steps in your workflow to accomplish this (for example, if you need 18 form fields, that means you will have 7 of these task steps in a row!) or you can do as we did and create a custom task step that calls as custom FM we wrote that retrieves all of the form fields for us.
(12) Making database inserts/deletes from a Generic Service
Suppose we have some Generic Service we wrote that will make an entry to some custom table based on some of our form data which we might use later for reporting, auditing or whatever. Our service has some “write_entry” operation in it that we have configured in our list of services. Now, you would expect that our service would fire during the course of the “do_operation” call to our “write_entry” method and make an entry when the form is “sent” (SEND step). Furthermore, you might also think that somehow our service would consider the workflow binding to the SEND_VARIATION (“A” means write to database while a “blank” or “B” means to simply “check” the operations like a test run but do not save). However, all of these assumptions could not be further from the truth. In fact, it is much worse! First off, the SEND_VARIATION does not apply to generic services. Even the SAP help documentation states “The element specifies whether the data is saved in the infotypes in the backend system”. Secondly, keep in mind, our operations get fired in order EACH time an “event” occurs. That means, our operation will trigger when the user does a “check” as well as when they do a “send”. We do not have “step level control” within the task (ie EDIT->CHECK->SEND), so we don’t know “where” we are within the form application to control our operation. We could actually be making at least two entries each time! (more if the user goes back to previous steps or if fields from our operation are tied to user events as well). This is a “good new, bad news” situation. The good news is SAP provides a solution. You must implement an Enhanced Generic Services for a database save. The bad news is that SAP provides no examples of Enhanced Generic Services. The standard SAP_PA service is similar to an enhanced generic service and can be used as reference, but it is way to complicated in much of it’s functionality to be of much use in learning what is needed for an enhanced generic service.
workaround: For any kind of database changes, SAP suggests creating an Enhanced Generic Service. Good luck figuring it out though!
(13) User Events (Enhancement Pack 2 and up)
I saved the “best” for last. Up till now, if the others I listed were “sand in my shorts” or “thorns in my side”, this one can best be described as “flossing your teeth with barbed wire”….sure, it’s possible, but it’s probably going to be painful and really messy!
Prior to Enhancement Pack 2, we only had two real “events” to respond to with our Adobe forms. These were “Initialize” (called when the form is first pulled up) and “Check” (triggered each time the form moves to the next steps). This was something like:
As of Enhancement Pack 2, you can now define “user events” for your forms. Before this, if for instance you wanted to push a button to trigger a search to populate a drop-down (like an input help), you would actually trigger the “check” event for the form and ALL FORM FIELDS would be passed to the backend. With user events however, you can define your own custom event as well as which fields get passed to the backend for your event. In a previous blog, I mentioned how great this was and how much I loved it. Well, I still am glad we have this functionality, it’s just that once I dug into it a bit, it was not implemented quite as expected.
a. Implemented “bass-ackwards”?
In the southern US, we have a saying that in my opinion, perfectly sums up how user events have been implemented. Bass-ackwards! Let’s just say that that means “backwards” to keep this conversation “family friendly”. (haha) At least for my way of thinking, I would imagine that I could define a user event and then define what operation I want to call for it and finally what group of fields to pass to this operation. Fairly cut and dry. However, this could not be further from the truth for HCM P&F user events. Besides defining your own user events, that’s about where the similarities end in my thinking and SAP’s implementation. As mentioned for the first step, you do define a user event. Then you define a “field group”(or groups) and what kind of operation to do (“initialize” or “check”) NOTICE….I did not say you define an operation…just the “kind” of operation. Lastly, you select the form fields for the “field group” to group together all the fields you wish to use for your user event (these fields have limitations discussed in the next section too!). Now, two problems here right off….1. again, we did not define any operations for our field group….2. the “field group” we defined here has absolutely no relationship to any field groups we defined in the “Back-End Services” configuration. So how does it work then? Well, here comes the “fun” part. All you really did was to define a “name” the Adobe form passes as an event. Then the code will simply match your “user event name” to what field groups were linked to it. It then goes through the field groups and collects all the fields to be used. Ready for this? It then will inspect each field and collect all operations that are bound to that field. Your “event” will then “fire” all of those operations as either a “check” (usual) or “initialize” event based on how you defined your field group for the user event. I can kind of see what they were trying to do here. They left user events more open to allow you to “trigger” lots of things in one event. However, I don’t think that’s what people want a custom user event to really do. Even then, if they did, they could control their own event internally to do the same thing. So, your one user event that you wanted to trigger to do one very specific bit of work could possibly “fire” off all of you operations just like the “old”, pre-user events, “check” event. So what is the benefit of the new user event functionality again? (haha)
workaround: Not so much a workaround as a warning….be very careful in your use and implementation of user events. Strange things can and will happen. The external debugger will become your best friend as you try to make sense of it all.
b. Phantom field in field groups
If you remove/delete a form field, it will not automatically be removed from your user events’ field groups that used it. When using the event, you will get an error message referring to the “phantom” field.
workaround: First, add the form field back. Then go in to your user events and remove (uncheck) the field from all field groups that use it. Finally, go back into form fields and safely remove the field again.
c. Friendly SAP adds “effective date” no matter what
During the code which executes your user events in class CL_HRASR00_DISPATCHER method IF_HRASR00_DISPATCHER~EXECUTE_OPERATIONS, line 200 will actually add “Effective Date” to your list of fields in your field group regardless if you do not want it in there. It’s alright for events that use “effective date” because it simply removes the duplicate with a “delete adjacent” call.(At least they got that right!)
(** I love the developers comment that they manually added the field because of course everyone needs it!)
The next the code does is that it looks at every field in your field group to determine which operations the field is bound to. As “effective date” is always part of SAP_PA, this means that at the very least SAP_PA and your own desired service will be executed. Also, since SAP_PA requires MASSN, MASSG and PERNR along with EFFECTIVE_DATE, those fields also get added to your field group and any other services bound to those fields as well will get executed. This can get quite messy and far beyond your original intent of your user event.
In our example, we have a simple search user event. It takes just two simple fields….a search string and then the employee numbers it returns. However, as mentioned, EFFECTIVE_DATE gets added to it as does MASSN, MASSG and PERNR due to SAP_PA. Now, we do have an operation that uses MASSN (to find the possible “action” for a selected employee based on their country) and another operation that uses MASSG (populates “reasons” based on the action from the other). Both of those should not fire for our user event, however, because they have MASSN and MASSG in them, they get added to the list. So now, from our one simple little “search” user event, we actually will have 4 operations firing!!!
workaround: None! Yep…pretty simple until (or if) SAP corrects this. Just keep in mind that for your user event, you will always have at least your intended operation plus SAP_PA being called.
d. User events still are just operations of backend services
workaround: My only suggestion is that you make good use of “rules” so that your operations do not execute except when you need them too (i.e. user event triggered).
Well, I have gone on and on quite long enough (did I break any records? haha). I do not want to give anyone the wrong impression here. I think HCM Processes & Forms is a great framework with lots of potential. (I hope I never do another PCR ever!!!) I just want to make people aware of the obstacles they might face and how to deal with them rather than getting turned off by HCM P&F all together. I hope my experience and the information provided here can help others. I know I spent many times banging my head against a wall trying to figure out a few of these! I have several more blogs about HCM P&F planned and I promise they will be much more positive. In fact, the next one is going to be tips and tricks for a successful HCM Processes & Forms project! Stay tuned and until next time…