How to set multi-level categorization – CRM orders: Recently, I’ve had the requirement to set the multi-level categorization on a CRM service request/order. After going ten rounds with it, I think it worth writing a blog post describing the trials and tribulations and the best approach that can be used. It should save someone out there a lot of wasted effort and frustration to know the principal of how to set these fields.

Some of the information out there is not exactly helpful, especially for programmers looking for BAPI/API calls that can be made to set the categorization.  It may even be suggested that one should the use the BOL programming model ( see https://scn.sap.com/thread/1434317 ) – this is not so easily accomplished, especially in the absence of documentation.

So how do you do it? (Spoiler at the end of this paragraph!). Very quickly one might find that the values are stored on tables CRMD_SRV_OSSET and CRMD_SRV_SUBJECT, can be read via function CRM_ORDER_READ (they come back in the SUBJECT table) and that there are many tantalizing low-level functions in package CRM_ERMS_CATEGORIZATION. But, if you were to debug how the web gui sets a categorization on an order you would find that the standard code does this by calling function CRM_ORDER_MAINTAIN. And that is how you do it – by calling that function in the same way, with the same parameters as the standard code does. There are several pages on SCN where such a call is described, but bear in mind that the example code given on these pages (and at the end of this post) are specific to someone else’s system and not your own.

So, the general principle is to call function CRM_ORDER_MAINTAIN. This is easier said than done. If you debug, you’ll find that two tables provided to this function are critical -it_service_os and ct_input_fields. Within the service_os table there is an “osset” table and within each row of this table there is a “subject” table that holds the lowest tier of the multi-level categorization that is being set. At each of these levels, the entity is referred to either by it’s GUID or by a handle (if the entity is still being created). Since in my particular case this is for a pre-existing order to which we are adding categorization then a GUID is used and not a handle. But where do you get the GUIDs from? In my case they are obtained as follows:

– The order GUID (as per table CRMD_ODERADM_H) should be set on the service_os table and input_fields tables.

– The “osset” table GUID can be obtained by calling function CRM_SERVICE_OS

– The lowest level “subject” table GUID is generated yourself (for example by calling function CRM_GUID_CREATE).

A DISCLAIMER is due here: this information was all obtained through trial and error and debugging, it seems that there isn’t an officially supported way to do what is probably quite a common requirement. Our lives would be a lot simpler if there was an official way and documentation, and I would love to be proven wrong and have someone point out that these exist.

One more thing, it is not enough to simply call CRM_ORDER_MAINTAIN. CRM_ORDER_SAVE also needs to be called to save changes to the database. I’ve also found through experience that these functions may need to be called in a seperate process to the work process that creates the order. (For instance, by scheduling a background job using functions JOB_OPEN etc; scheduling a function to run in update task didn’t seem to be suitable for this problem either.)

I’m loath to offer my code here (that I used to solve my particular problem) as people may be inclined to simply paste it onto their systems and expect it to run immediately. However, an example is a good aid too, so it is being offered below. Bear in mind that things will need to be changed in this code. Your profile type fields, and mode values may be different. So first and foremost debug and see how CRM_ORDER_MAINTAIN is being called and adjust this code accordingly:

function zcrm_add_categorization. *"---------------------------------------------------------------------- *"*"Local Interface: *"  IMPORTING *"     VALUE(IV_CATEGORY) TYPE  STRING *"     VALUE(IV_ACTIVITY_GUID) TYPE  GUID_32 *"     VALUE(IV_ACTIVITY_OBJECT_ID) TYPE  CRMT_OBJECT_ID *"---------------------------------------------------------------------- * Add a categorization to an existing service request ("activity") * * IV_ACTIVITY_GUID is the order GUID, as per table CRMD_ORDERADM_H * IV_ACTIVITY_OBJECT_ID is the order number * IV_CATEGORY is the cat id as per table CRMD_SRV_SUBJECT *LOCAL   include crm_object_names_con.   include crm_object_kinds_con.   data lr_aspect             type ref to if_crm_erms_catego_aspect.   data lr_categoryif         type ref to if_crm_erms_catego_category.   data lr_category           type ref to cl_crm_erms_catego_ca_default.   data lv_cat                type crmt_erms_cat_ca_buf.   data ls_conc               type zcrmt_erms_cat_code_trip.   data lv_obj_guid           type crmc_erms_cat_ln-obj_guid.   data lv_obj_extkey         type crmc_erms_cat_ok-obj_extkey.   data lv_process_type       type crmt_process_type.   data ls_service_h          type crmc_service_h.   data ls_crmt_srv_osset_wrk type crmt_srv_osset_wrk.   data ls_temp_osset         type crmt_srv_osset_wrk1.   data lv_osset_guid         like ls_temp_osset-guid.   data lv_cat_id             type crm_erms_cat_ca_id.   data lt_subject            type crmt_srv_subject_comt.   data ls_subject            type line of crmt_srv_subject_comt.   data ls_osset              type crmt_srv_osset_com1.   data lt_service_os         type crmt_srv_osset_comt.   data ls_service_os         like line of lt_service_os.   data lt_input_fields       type crmt_input_field_tab.   data ls_input_fields       like line of lt_input_fields.   data ls_input_field        like line of lt_input_fields.   data ls_input_field_names  like line of ls_input_field-field_names.   data lt_objects            type crmt_object_guid_tab.   data lv_service_guid       type crmt_object_guid.   data ls_log                type zcrm_erms_sr_log. *  field-symbols  like line of it_activities.   constants cv_link_type type char8              value 'IS_CODE'.   constants cv_asp_id    type crm_erms_cat_as_id value 'Z_YOUR_CAT_SCHEMA'. *Need the external key, so that we know the code group, etc. *...determine cat guid   lv_cat_id = iv_category.   cl_crm_erms_catego_ma_default=>if_crm_erms_catego_manager~get_aspect(     exporting iv_asp_id = cv_asp_id               iv_asp_state  = if_crm_erms_catego_const=>gc_as_state_executable     importing ev_instance = lr_aspect ).   call method lr_aspect->get_cat     exporting       iv_cat_id   = lv_cat_id     importing       ev_instance = lr_categoryif.   lr_category ?= lr_categoryif.   call method lr_category->if_crm_erms_catego_category~get_details     importing       ev_cat = lv_cat. *...with the cat guid we can now determine the external key   select single obj_guid     from crmc_erms_cat_ln     into lv_obj_guid     where cat_guid = lv_cat-cat_guid     and   lnk_type = cv_link_type.   if sy-subrc = 0.     select single obj_extkey       from crmc_erms_cat_ok       into lv_obj_extkey       where obj_guid = lv_obj_guid.     if sy-subrc = 0.       ls_conc = lv_obj_extkey.     endif.   endif. *...call functions to get the guids we're going to need to put in the service_os table   select single process_type     from crmd_orderadm_h     into lv_process_type     where guid = iv_activity_guid.   check sy-subrc = 0.   call function 'CRM_ORDER_SERVICE_H_SELECT_CB'     exporting       iv_process_type = lv_process_type     importing       es_service_h    = ls_service_h     exceptions       entry_not_found = 1       others          = 2.   if sy-subrc <> 0.     clear ls_service_h.   endif.   lv_service_guid = iv_activity_guid.   call function 'CRM_SERVICE_OS_READ_OB'     exporting       iv_ref_guid          = lv_service_guid       iv_ref_kind          = 'A'     importing       es_srv_osset_wrk     = ls_crmt_srv_osset_wrk     exceptions       entry_does_not_exist = 1       error_occured        = 2       parameter_error      = 3       others               = 4.   check sy-subrc = 0. *...subject table   ls_subject-katalogart   = ls_conc-code_cat.   ls_subject-codegruppe   = ls_conc-code_grp.   ls_subject-code         = ls_conc-code_id.   ls_subject-asp_id       = cv_asp_id.   ls_subject-cat_id       = lv_cat_id.   ls_subject-katalog_type = 'D'.   ls_subject-mode         = 'B'.   call function 'CRM_GUID_CREATE'     importing       ev_guid = ls_subject-ref_guid.   insert ls_subject into table lt_subject . *...osset, contains the subject table   clear ls_osset.   ls_osset-subject         = lt_subject.   ls_osset-ref_guid        = lv_osset_guid.   ls_osset-subject_profile = ls_service_h-subject_profile. ".'         '   ls_osset-profile_type    = ls_temp_osset-profile_type.".'A' *...service os data, constains osset   clear ls_service_os.   append ls_osset to ls_service_os-osset.   ls_service_os-ref_guid = iv_activity_guid.   ls_service_os-ref_kind = 'A'.   refresh lt_service_os.   append ls_service_os to lt_service_os. *...input fields   clear ls_input_field.   refresh lt_input_fields.   ls_input_field-ref_guid    = iv_activity_guid.   ls_input_field-ref_kind    = gc_object_kind-orderadm_h.   ls_input_field-objectname  = gc_object_name-service_os.   ls_input_field_names-fieldname = 'ASP_ID'.   insert ls_input_field_names into table ls_input_field-field_names.   ls_input_field_names-fieldname = 'CAT_ID'.   insert ls_input_field_names into table ls_input_field-field_names.   ls_input_field_names-fieldname = 'CODE'.   insert ls_input_field_names into table ls_input_field-field_names.   ls_input_field_names-fieldname = 'CODEGRUPPE'.   insert ls_input_field_names into table ls_input_field-field_names.   ls_input_field_names-fieldname = 'KATALOGART'.   insert ls_input_field_names into table ls_input_field-field_names.   ls_input_field_names-fieldname = 'MODE'.   insert ls_input_field_names into table ls_input_field-field_names.   ls_input_field_names-fieldname = 'REF_GUID'.   insert ls_input_field_names into table ls_input_field-field_names.   insert ls_input_field  into table  lt_input_fields. *Effect change by calling functions to maintain and save CRM order   call function 'CRM_ORDER_MAINTAIN'     exporting       it_service_os     = lt_service_os     changing       ct_input_fields   = lt_input_fields     exceptions       error_occurred    = 1       document_locked   = 2       no_change_allowed = 3       no_authority      = 4       others            = 5.   ls_log-subrc1 = sy-subrc.   check sy-subrc = 0.   refresh lt_objects.   append iv_activity_guid to lt_objects.   call function 'CRM_ORDER_SAVE'     exporting       it_objects_to_save = lt_objects     exceptions       document_not_saved = 1       others             = 2. endfunction.

New NetWeaver Information at SAP.com

Very Helpfull

 

 

User Rating: Be the first one !