Skip to Content

Some things are just so essential that there must be hundreds of people fighting the same or similar problem at the same time. If all these went to SDN and tell the other about their findings and “lessons learnt”, world would be much brighter and people would be happier and less overworked. One of these things are HR Qualifications.

Well, maybe they`re not THAT essential as I think, but I have been fighting them often over the years. That`s why I decided to write this blog. To create some knowledge available for everybody so the effort that is wasted because everybody has to reinvent his or her wheel. I also mentioned that several times before but let me say it once again: I use SDN blogs to persist my own knowledge, which I cannot exercise every week or every month and have to reinvent some parts of the wheel over time too.

Side note: if you`re interested in this article, you might be interested in another one about HR-PD on Apraisal BADIs too. Check it here: Challenge yourself (HR-PD Appraisal BADIs).

Development notes and shortcuts

  • OOQA operations: you`re looking for the code which is handling different OK_CODEs (different buttons and other objects on the screen). The popup screen displaying the qualification details is screen number 2100 in function group RHPE (you will see RHPE prefix in some useful function modules` names too). Flow logic MODULE RHPE_USER_COMMAND on line 43 (in my version) is the right spot to place you break point if you need to learn more about how this transaction works.
  • There one can learn that the function module used for creating the qualifications is RHPE_QUALI_CREATE and the one for qualification groups is RHPE_Q_CLASS_CREATE. You can either debug the call in the standard to learn about input and output parameters or check the example coding for mass Q and QK upload from Excel (one could make it more round and shiny, but with my example coding for a jump start every ABAPer should be able to adapt the code to his/her needs in 20 minutes).
  • What some people do and value is the option not to use the scale texts inheritance (then you say yes, the scale will have 6 grades, but no, text won`t be inherited from the “parent”, but will be specific for this one qualification or a group). That`s an important feature of the coding below and the purpose of the checkbox and text field on the middle tab of the qualification popup in OOQA. You can either provide the texts when creating a group or a qualification (see example coding below, look for 1048 keyword, make sure you say INHERITED <> ‘X’ if you want to push your own texts) or you can add texts later using function module RHPS_INFTY_1048_WRITE  (for reading the same there is RHPS_INFTY_1048_READ_SINGLE function).
  • You might need to read a scale. Then use function module called RHPG_SCALE_READ.
  • When you have qualifications created, you might want to assign them to your HR objects. For that use function module RH_RELATION_MAINTAIN. For example you maintain the relationship between objects P and Q or C and Q (so you assign a qualification to a person or to a job for example). To learn more about objects and relationships I suggest you go to SE11 and learn about tables HRP1000 and HRP1001.
  • I am not copying any calls here or even explain the parameters of the calls, just use where used list to get a rough idea or place there a break point and run the transaction which uses the function module.
  • Important tables: HRP1000 and 1001 as mentioned above for qualifications. For scale related data look for T77* tables. Example: T77TP for Proficiency texts. But unless you program something huge (for huge data processing), calling function modules should be enough. Since you know the function modules (above), you can check tables used in their source codes and get other tables from there.

Useful transactions

  • OOQA – Qualification catalog: create qualifications and organize them into “folders” (qualification groups; these groups are important because you maintain qualification scale on the group level).
  • OOQM – Qualification profile mass maintenance
  • PPPM – Change profile for object (assign a selected object a qualification, let`s say to a Job type object (object “code” or OTYPE “C”), and evaluate this qualification to “Insufficient” for the object).
  • PEPM – when you have your qualifications assigned and evaluated for objects, you might want to compare profiles to get answers for questions like “Who is qualified for a position” etc.

Useful tricks

In OOQA menu: View > Additional data on (CTRL+F6) displays the scale ID and scale description text next to every qualification group in the catalog.

Mass qualification catalog operation: Upload from Excel file

My program below is not the only option. That would be funny, wouldn’t it.

One might use other ways like LSMW or the transactions OODT/ OOMV. But sometimes you don`t have the necessary skills to use the tools or there are others reasons not to use them.

The program expects two input files: first one for qualifications or qualification groups (depends on the PARAMETER on the selection screen), the second one for scale texts, if you want to override the existing (so DO NOT want the inheritance).

Input files formats

Format of the file one:

  • Name (HRP1000-STEXT),
  • Short description (HRP1000-SHORT),
  • Superior object (qualification group HRP1000-OBJID).
  • For qualification groups you can specify SCALE_ID in the fourth column but for qualifications that makes no sense.
  • Fifth column must be empty (because the structure`s fifth column is a table type for those curious why), but from sixth column onwards you can put notes there. You can also use the coloring in the Excel, which also comes handy sometimes.

Format of the file two:

  • Name (HRP1000-STEXT) – this name must be the same as in the file one so the program can understand these new scale texts belong to qualification or q. group with this name. I needed it this way to make it easy to use for my users, but you can easily change this behavior.
  • Second column is for SCALE proficiency.
  • Third is for the texts. If you want multiple lines of text for the proficiency description, you just give them the same proficiency number and the system will put them together.

Note: second file can be empty, then no texts are changed and objects are created with INHERITED = ‘X’, since there is nothing to use for replacement.

I hope this will give the newcomers a rough idea about the topic and the coding can cut your own effort into half, hopefully even less. Share your hints and knowledge on “basic problems” too, remember that 99% of the customer will not use HANA or mobile in the next year, but they`re using ERP for years. So that`s the scalable way of helping people. If you help one to cope with the “typical problem” and that problem is typical for hundreds of people, than the benefit is some hundreds multiplied by an hour… wow, that would make me happy. Cheers Otto

REPORT  zquali_tree.
PARAMETERS: p_plvar TYPE plvar DEFAULT '01'.
PARAMETERS: p_qk RADIOBUTTON GROUP rad1,              "upload q. groups
            p_q  RADIOBUTTON GROUP rad1 DEFAULT 'X'.  "qualifications
TYPES: BEGIN OF tt_class,
    stext TYPE hrp1000-stext,
    short TYPE hrp1000-short,
    vobjid TYPE hrp1000-objid,
    scale_id TYPE t77sk-scale_id,
    values TYPE hap_t_pt1048,
  END OF tt_class.
DATA lt_classes TYPE TABLE OF tt_class.
TYPES: BEGIN OF tt_rating,
    stext TYPE hrp1000-stext,
    rating TYPE rating,
    tline    TYPE hrline79,
  END OF tt_rating.
DATA lt_ratings TYPE TABLE OF tt_rating.
TYPE-POOLS: truxs.
*************************************************************
*************************************************************
DATA lt_filetable TYPE filetable.
DATA ls_file LIKE LINE OF lt_filetable.
DATA lt_raw_data TYPE truxs_t_text_data.
DATA lv_file TYPE rlgrap-filename.
DATA lv_rc TYPE i.
DEFINE upload_file.
  clear: lt_filetable[], lv_rc, lv_file.
  call method cl_gui_frontend_services=>file_open_dialog
    changing
      file_table              = lt_filetable
      rc                      = lv_rc
    exceptions
      file_open_dialog_failed = 1
      cntl_error              = 2
      error_no_gui            = 3
      not_supported_by_gui    = 4
      others                  = 5.
  if sy-subrc <> 0.
    message id sy-msgid type sy-msgty number sy-msgno
               with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  endif.
  read table lt_filetable into ls_file index 1.
  if sy-subrc ne 0.
    message 'Cancelled by the user' type 'S'.
    exit.
  endif.
  lv_file = ls_file-filename.
  call function 'TEXT_CONVERT_XLS_TO_SAP'
    exporting
      i_tab_raw_data       = lt_raw_data
      i_filename           = lv_file
    tables
      i_tab_converted_data = &1
    exceptions
      conversion_failed    = 1
      others               = 2.
  if sy-subrc <> 0.
    message id sy-msgid type sy-msgty number sy-msgno
            with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  endif.
END-OF-DEFINITION.
*************************************************************
*************************************************************
upload_file lt_classes.
upload_file lt_ratings.
*************************************************************
*************************************************************
DATA lv_error TYPE c.
FIELD-SYMBOLS <fs_stup> LIKE LINE OF lt_ratings.
FIELD-SYMBOLS <fs_cls> LIKE LINE OF lt_classes.
LOOP AT lt_ratings ASSIGNING <fs_stup>.
  READ TABLE lt_classes ASSIGNING <fs_cls> WITH KEY stext = <fs_stup>-stext.
  IF sy-subrc NE 0.
    lv_error = 'X'.
    RETURN.
  ELSE.
*** we can put the information into the VALUES tab
    DATA ls_line LIKE LINE OF <fs_cls>-values.
    ls_line-tline = <fs_stup>-tline.
    ls_line-rating = <fs_stup>-rating.
    APPEND ls_line TO <fs_cls>-values.
  ENDIF.
ENDLOOP.
IF lv_error EQ 'X'.
  MESSAGE 'Error in input data, correct it and try again' TYPE 'I'.
  EXIT.
ENDIF.
*************************************************************
*************************************************************
DATA lv_objid TYPE hrp1000-objid.
FIELD-SYMBOLS <fs_class> LIKE LINE OF lt_classes.
LOOP AT lt_classes ASSIGNING <fs_class>.
  IF p_qk IS NOT INITIAL.
    DATA lv_inherited TYPE char1.
*** if there are texts in the input file, use them to override
*** the existing ones, so do not use the inheritance
    IF <fs_class>-values[] IS INITIAL.
      lv_inherited = 'X'.
    ELSE.
      lv_inherited = ''.
    ENDIF.
    CALL FUNCTION 'RHPE_Q_CLASS_CREATE'
      EXPORTING
        plvar                = p_plvar
        short                = <fs_class>-short
        stext                = <fs_class>-stext
        vobjid               = <fs_class>-vobjid
        scale_id             = <fs_class>-scale_id
        inherited_1048       = lv_inherited
      IMPORTING
        objid                = lv_objid
      TABLES
        descr_pt1048         = <fs_class>-values
      EXCEPTIONS
        no_authorization     = 1
        error_during_insert  = 2
        begda_greater_endda  = 3
        wrong_destination    = 4
        wrong_date_format    = 5
        scale_required       = 6
        description_required = 7
        time_not_valid       = 8
        error_ext_number     = 9
        undefined            = 10
        OTHERS               = 11.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ELSE.
      WRITE: / 'QK ', <fs_class>-stext, ' created ', lv_objid.
    ENDIF.
  ELSE.
    IF <fs_class>-values[] IS INITIAL.
      lv_inherited = 'X'.
    ELSE.
      lv_inherited = ''.
    ENDIF.
    CALL FUNCTION 'RHPE_QUALI_CREATE'
      EXPORTING
        plvar                = '01'
        short                = <fs_class>-short
        stext                = <fs_class>-stext
        votype               = 'QK'
        vobjid               = <fs_class>-vobjid
        nyears               = 0
        nmonths              = 0
        inherited_1048       = lv_inherited
      IMPORTING
        objid                = lv_objid
      TABLES
        descr_pt1048         = <fs_class>-values
      EXCEPTIONS
        no_authorization     = 1
        error_during_insert  = 2
        begda_greater_endda  = 3
        object_not_found     = 4
        wrong_otype          = 5
        wrong_destination    = 6
        wrong_date_format    = 7
        scale_required       = 8
        description_required = 9
        time_not_valid       = 10
        error_ext_number     = 11
        undefined            = 12
        OTHERS               = 13.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ELSE.
      WRITE: / 'Q ', <fs_class>-stext, ' created ', lv_objid.
    ENDIF.
  ENDIF.
ENDLOOP.
To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

  1. Alex Tcherniak

    Thanks for taking the time to create this, Otto! 

    As a side note…. I was just thinking that SAP itself should have built and shared a library of similar content “All you need to know about XYZ” for every SAP module and submodule by now!  It will probably comprise a 100 or so topics.  Possibly more…  I suppose not everything needs to be covered. Maybe just the core areas of every module.  The point I am trying to get across is that this would be very valuable knowledge for ABAPers to get a hold of… and none exists yet (that I am aware of).

    Thanks,

    Alex

    (0) 

Leave a Reply