Validate partner types / Restrict partner functions to specific partner types only

In ChaRM and ITSM we are using several partner functions. These partner functions can hold contact partners (external business partners, e.g. Requester), employees (internal end-users, e.g. Developer) and organizational units resp. groups (of internal organizational model, e.g. Support Team).

We want to validate that for partner functions which should hold a organizational unit only organizational units can be maintained/selected. We also want to ensure that employees are always business partners with a valid SAP user id assigned. A contact partner should always be a business partner with the role „Contact Partner“.

However this validation cannot be done in SAP CRM standard, because SAP CRM standard is not supporting the check „Organizational Unit only“.

Solution:

Please create your own partner function types using view cluster COMV_PARTNER_PFT (SM34). Note that „0005 Emloyee“ and „0007 Contact Person“ can be used as it is. But „0008 Person Responsible“, „0016 Support Team“ and „0034 Organization Responsible“ needs to be copied in customer namespace 9XXX and corrected. Please ensure following flags:

  • 0005: Not unique at Doc./Item Level, Central Person
  • 0007: Not unique at Doc./Item Level, Contact Person
  • 9008: Unique at Doc./Item Level, Central Person
  • 9016: Not unique at Doc./Item Level, Central Person + Central Person or Org.Unit
  • 9034: Unique at Doc./Item Level, Central Person + Central Person or Org.Unit

Please adjust definition of partner functions in view COMV_PARTNER_FCT (SM30) and exchange partner function type by our (new) types. Note that you are not allowed to do this for SAP standard partner functions.

Please note that it can happen that you have to adjust mapping configuration in view AIC_PARTNER_FCT + CRMV_ORLALL_BTIL as well in case you are changing partner function types. This is specific to ITSM/ChaRM only.

Please note that it can happen that you have to configure business partner relationship assignment or that you have to adjust partner determination based on business partner relationship. (Only needed if you are changing partner function type. If you are in parallel changing business partner relationship. If you are using partner determination based on business partner relationship.)

Depending on you changes, it can also happen that you have to run report CRM_INDEX_REBUILD (if order index fields get changed because of partner function type change).

Please modify function module COM_PARTNER_CHECK_MASTER_DATA:

  • Check for Central Person: Perform check only if check for „Central Person“ is activated and check for „Central Person or Org.Unit“ is deactivated.
  • Check for Central Person or Org.Unit: Perform check only if check for „Central Person“ is deactivated and check for „Central Person or Org.Unit“ is activated.
  • Check for Org.Unit (new check): Perform check only if check for „Central Person“ is activated and check for „Central Person or Org.Unit“ is activated. Here check for object type „O“ using function module BP_BUPA_GET_HROBJECT.

If you want, you can use SAP CRM Web UI message replacement feature to replace error messages COM_PARTNER-135 and COM_PARTNER-136:

  • Replace “Partner &1 (&2) is neither an employee nor an organizational unit” by “Partner &1 cannot be a &2. Please select a group.”
  • Replace “Partner &1 (&2) is not an emloyee” by “Partner &1 cannot be a &2. Please select a person.”

Remark: You can define and use your own partner function types. The given types were just examples.

Remark: This solution is not able to validate a partner function agains a business partner role „Developer“, „Tester“, „Change Manager“ etc. It is not able to validate against corresponding PFCG roles. Therefore this improvement is just a simple but very helpful improvement.

Sorting on calculated (virtual) fields in Web UI

Assignment blocks usually contain tables. The content of these tables can be sorted by clicking the header column and selecting ascending or descending. This sorting feature is supported out of the box and managed by the Web UI framework.

However, this feature is supported only for attributes which are part of the business object layer (BOL entity level). It is not working for calculated (virtual) attributes which are implemented at the context node level only.

To support real and virtual attributes you have to implement a solution similar to

SAP CRM WebUI : Sorting custom columns (custom attributes)

  1. Use a callback method to perform the comparison.
  2. Use a method cl_crm_uiu_bp_tools=>is_a_greater_b, cl_crm_uiu_bp_tools=>is_date_a_greater_b or similar to perform the comparison on context node level instead of BOL entity level.

Automated creation of follow-up transactions. How to use and enhance COPY_DOCUMENT?

To create follow-up documents automatically from a business transaction we can use a ppf action with method COPY_DOCUMENT.

We have to use the parameter „process_typ“ to specify to transaction type.

The title of the ppf action will be taken over as description of the follow-up transaction. There is no way to deactivate this feature except the title will be left empty. Then it depends on the copy control what will happen.

The long text of the ppf action can be transferred to a text type of the follow-up document. If we want to do this, we just need to configure and use a text determination access sequences using function module CRM_REFERENCE_TEXT_GET (ref object and ref text type can be left empty in customizing).

If we want to set some more values (i.e. priority, category, …), we have to put these static values in the ppf action container like parameter process_type. We also have to enhance method copy_document of class cl_action_execute to transfer these data to the follow-up document. There is currently no standard solution to default/transfer some data to the follow-up document.

If we want to set a partner for a specific partner function we should do it using partner determination or BRF+ based on a field which is already defaulted using solution mentioned above (i.e. category). We should never try to default a partner by the follow-up creation routine itself because the partner number will be different in different systems and the assignment rule might change very often.

The copy control is per default active for the follow-up creation, which means that data can be overtaken from the current transaction to the follow-up transaction.

Unfortunately there is currently no way to create a follow-up based on a template transaction. Only SAP CRM Service is using such a feature for Service Plans (we can have a look at ppf action method CREATE_ORDER_SRVPLAN and transaction CRMD_SERV_CYCLE). However, this solution is specific for this use case only and cannot be used for other use cases as well.

For a lot of use cases COPY_DOCUMENT (with the mentioned extensions) will be sufficient to implement the requirements. However there exist some other ppf action methods which handles items and document flow in a different way. If we want to use/copy items we should try COPY_DEF_ITEMS (create follow-up and copy items), COPY_ITEM_LOCAL (create/copy items in a transaction locally) and COPY_ITEM_TO_TASK (create follow-up transaction with current item as predecessor).

How to work with timestamp attributes in SAP Web Client UI?

It happens very often, that we want to use additional TIMESTAMPs in context of Business Transaction Management.

If we are introducing additional date types (appointments) via configuration, the SAP CRM standard is managing the display, storage and data conversion. We just need to add context nodes for it to our UI components. We should have a look at already existing date/time context nodes and reuse the context node classes used here to ensure standard-like behaviour (virtual fields, value helps, data conversion, …).

If we decide to create a field enhancement using Application Enhancement Tool (AET), we dont need an additional context node since we are using context node BTAdminH or BTCustomerH. However, we will now face the challenge, that there is no proper value help available for timestamps. Therefore we need to create two additional virtual attributes for DATE and TIME which are referring to the TIMESTAMP attribute.

(Der Quellcode wird später hier noch ergänzt….)

How to calculate virtual fields for table enhancements created with AET?

All tables, structures, function modules and classes will be generated automatically, if you create a table enhancement using Application Enhancement Tool (AET). However, sometimes you might want to calculate some fields instead of storing it in database.

The AET is not supporting such virtual fields. Therefore you have to implement it manually.

Solution 1: Create an additional attribute in the context node of the generated UI component and place a calculation in the getter method. Deactivate coding of setter and i-getter method.

Solution 2: Enhance structures ?_WORK, ?_ATTR and ?_BOL_ATTR by an additional attribute. Place your calculation at the end of method GET_DETAIL of class CL_AXT_TABLES_API (define and use a table name dependent BADI for high quality solution). Add a value attribute with the same name to context node of the generated UI component. Don’t change the generated code here since it will read the data from BOL/GenIL as wanted.

Conclusion 1: Development should be restricted to a minimum. Whenever source code can be avoided, it should be avoided. Therefore solution 1 is preferred from a supportability perspective, if there are only few virtual fields required.

Conclusion 2: Business logic should be placed in API or BOL/GenIL layer instead of UI layer to be reused UI independently. Therefore solution 2 is preferred from an architecture perspective, if several virtual fields are required or if a high quality and high flexible solution is requested.

Such- und Wertehilfen im SAP Web Client UI

Das SAP Web Client UI ist ein mächtiges und flexibles Framework zur Entwicklung nutzerfreundlicher User Interfaces. Doch manchmal hat SAP SE die Lösung nicht zuende gedacht. Als Beispiel sei hier der üblicherweise ungerechtfertigt hohe Entwicklungsaufwand zur Implementierung Feldprüfungen bei Eingabe, Feldaufbereitungen bei Ausgabe und Such- bzw. Wertehilfen genannt.

Folgende Lösungen stehen zur Verfügung:

  • Die genannten Logiken sind in den Kontextknoten implementiert. Wird also ein Kontextknoten benutzt, der in einer anderen UI-Komponente bereits existiert, sollte geprüft werden, ob der Kontextknotenkontroller wiederverwendet werden kann. Nachdem die Super-Klasse des eigenen Kontextknoten durch die Standard-Kontextknotenkontrollerklasse ausgetauscht wird, stehen in der Regel sämtliche vom Standard gewohnte Prüfungen und Aufbereitungen zur Verfügung.
  • Bei Nutzung des Design Layers können dem Feld Dictionary-Suchhilfen zugeordnet werden. Diese werden dann automatisch gezogen.
  • Für Felderweiterungen mittels Application Enhancement Toolset (AET) werden automatisch die Dictionary-Suchhilfen bzw. -Wertehilfen genutzt. Ohne Programmieraufwand.
  • Im Artikel SAP CRM & SAP Solution Manager Business Transaction Search Enhancement habe ich beschrieben, wie die AET-Automatik auch für SAP-Standard-Felder oder manuell ergänzte Kundenfelder aktiviert werden kann. Dieser Weg wird jedoch von SAP SE nicht supportet.
  • Wenn alle anderen Wege versagen, dann muss am Ende doch klassich die V-Getter-Methode im Kontextknotenkontroller ausprogrammiert werden. Für einfache Dropdown-Listen gibt es jedoch bereits eine Hilfsklasse cl_crm_uiu_ddlb die uns die meiste Arbeit abnimmt:
method GET_V_NAME_OF_THE_ATTRIBUTE.

DATA:
lr_valuehelp_pldescr TYPE REF TO cl_crm_uiu_ddlb.

*Create Value Help Descriptor
CREATE OBJECT lr_valuehelp_pldescr
EXPORTING
iv_source_type = if_bsp_wd_valuehelp_pldescr=>source_type_table.

*Build up dropdown list based on data element.
CALL METHOD lr_valuehelp_pldescr->set_data_element
EXPORTING
iv_data_element      = 'NAME_OF_THE_DATA_ELEMENT'
* iv_add_initial_entry =
.

*Return value help descriptor
rv_valuehelp_descriptor ?= lr_valuehelp_pldescr.

endmethod.

Message Check on Save

Identify Message Class and Number
You can activate extended message tracking by setting user parameter BSPWD_USER_LEVEL (and CRM_USER_LEVEL) to value 9 in transaction SU3 resp. SU01. Now you will see the wanted details on mouse hover of the message in Web UI.

Correct Error Flag
Sometimes it happen, that a Business Transaction contains no error messages but is still flagged as erroneous.

This inconsistency can be solved using report CRM_MESSAGES_CHECK like mentioned in SAP Note „1971092 – Wrong System Status ‚Contain Errors'“. However this report is not able to identify all issues: If a business transaction has no message log but is flagged as erroneous, it will not be identified. But if the message log exists and is empty it will be identified.

Error Message Replacement
Sometimes an error message shown in SAP Web Client UI might be too technical. In this case it is possible to replace it by a user-friendly one. The SAP Web Client UI standard feature “Message Replacement” can be used here.

  1. (Activate business function UI_FRW_1 and UI_FRW_1_DOCU in transaction SFW5.)
  2. Assigning function profile MSG_REPLACE to your business role.
  3. Create own message classes and messages using transaction SE91.
  4. Configure all wanted message replacements SPRO -> CRM -> UI Framework -> UI Framework Definition -> Define Messages to Be Replaced.

Mandatory Field Check on Save
Sometimes fields are configured as mandatory in SAP Web Client UI. In case of empty mandatory fields end-users will get an error message. It is still possible to save. To avoid saving you can activate the “SAP Web Client UI Mandatory Field Check on Save” feature.

  1. Configure your Web UI and mark fields as mandatory.
  2. Maintain parameter CRMORDER-NO_SAVE_MAND_FIELDS in configuration table SMOFPARSFA.

More details:

  • SAP Note „1353553 – Opportunity: Behavior of mandatory fields in Web UI“
  • http://scn.sap.com/message/14553524

Message Check on Save
Sometimes business transactions contains error messages. Usually end-users can still save. In most cases this is acceptable because status change to next status is not allowed in case of errors. In some cases saving is needed, because some activities are performed on save which might resolve the error together with the error message. However, in some seldom cases save shall be blocked for certain error messages.

One example is COM_PARTNER 145 „Business Partner is not a valid business partner.“

In SAP standard there exist no feature to disallow saving dependent on an certain error message. Therefore you have to develop it by creating a configuration table containing fields CLIENT, OBJECT_NAME, MSGTY, MSGID, MSGNO, LANGU and TEXT and by implementing BADI ORDER_SAVE (method CHECK_BEFORE_SAVE).

  1. Check if dialog mode is active using function module COM_PARTNER_DIALOG_MODE_CHECK (Check should only be performed in case of online/foreground processing)
  2. Check if SAP Web Client UI is active using method cl_thtmlb_util=>get_business_role_name (Check should only be performed in case of online/foreground processing)
  3. Select all configured messages using view /GLB/MECOS_R.
  4. Get all messages for current business transaction using function module CRM_MESSAGES_SEARCH.
  5. Get details for all messages using function module CRM_MESSAGES_GET_MSG_INFO.
  6. Check whether business transaction contains configured messages. Check on Object Name, Message Type, Message Class and Message Number. All fields can be left empty in configuration which means “all”.
  7. Cancel save by raising exception DO_NOT_SAVE. If an error message is configured transfer this customer specific error message.
METHOD if_ex_order_save~check_before_save.

DATA:
lv_profile    TYPE crmt_ui_profile,
lt_message    TYPE TABLE OF /glb/mecos_r,
* ls_msg_idno TYPE bal_s_idno,
* lt_msg_idno TYPE bal_r_idno,
lt_msg_handle TYPE bal_t_msgh,
ls_msg_info   TYPE crmt_msg_info,
ls_msg        TYPE bal_s_msg.

FIELD-SYMBOLS:
<fs_message>    LIKE LINE OF lt_message,
<fs_msg_handle> LIKE LINE OF lt_msg_handle.

*-------------------------------------------------------------------------

*Get dialog mode state.
CALL FUNCTION 'COM_PARTNER_DIALOG_MODE_CHECK'
EXCEPTIONS
no_dialog = 1
OTHERS    = 2.

*We are in dialog mode (online/foreground processing).
CHECK sy-subrc = 0.

*Get Business Role
CALL METHOD cl_thtmlb_util=>get_business_role_name
RECEIVING
rv_role = lv_profile.

*We are in SAP Web Client UI (online/foreground processing).
CHECK lv_profile IS NOT INITIAL.

*Alle registrierten Fehlermeldungen lesen.
SELECT *
INTO TABLE lt_message[]
FROM /glb/mecos_r.

*There are some messages configured.
CHECK lt_message[] IS NOT INITIAL.

**Build search conditions.
* REFRESH lt_msg_idno[].
* LOOP AT lt_message ASSIGNING <fs_message>.
*
* ls_msg_idno-low-msgid = <fs_message>-msgid.
* ls_msg_idno-low-msgno = <fs_message>-msgno.
* CLEAR ls_msg_idno-high.
* ls_msg_idno-sign = 'I'.
* ls_msg_idno-option = 'EQ'.
* APPEND ls_msg_idno TO lt_msg_idno.
*
* ENDLOOP.

*Search for matching messages.
CALL FUNCTION 'CRM_MESSAGES_SEARCH'
EXPORTING
* it_r_msgidno = lt_msg_idno[]
iv_ref_object   = iv_guid
iv_ref_kind     = 'A'
* IV_CALLER_NAME =
* IT_LOGICAL_KEYS =
* IV_PROBCLASS =
* IV_DETLEVEL =
IMPORTING
et_msg_handle   = lt_msg_handle
EXCEPTIONS
appl_log_error  = 1
error_occurred  = 2
OTHERS          = 3.

*There should never occur an error here.
*We found some messages.
CHECK sy-subrc = 0 AND lt_msg_handle[] IS NOT INITIAL.

LOOP AT lt_msg_handle ASSIGNING <fs_msg_handle>.

*Get message details.
CALL FUNCTION 'CRM_MESSAGES_GET_MSG_INFO'
EXPORTING
is_msg_handle           = <fs_msg_handle>
* IV_GET_CALLER_NAME = TRUE
IMPORTING
es_info                 = ls_msg_info
es_msg                  = ls_msg
EXCEPTIONS
not_found               = 1
wrong_context_structure = 2
data_error              = 3
OTHERS                  = 4.

*There should never occur an error here.
CHECK sy-subrc = 0.

*Check all details.
LOOP AT lt_message
ASSIGNING <fs_message>
WHERE ( object_name = ls_msg_info-object_name OR object_name IS INITIAL ) AND
( msgty       = ls_msg-msgty            OR msgty       IS INITIAL ) AND
( msgid       = ls_msg-msgid            OR msgid       IS INITIAL ) AND
( msgno       = ls_msg-msgno            OR msgno       IS INITIAL ).

*Check IV_CALLER_NAME.

*All details are correct.
CHECK sy-subrc = 0.

*Prepare own error message for save abort.
IF <fs_message>-text IS NOT INITIAL.

cv_own_message = abap_true.
MESSAGE <fs_message>-text TYPE 'A' RAISING do_not_save.

ELSE.

*Abort save now (using standard error message).
RAISE do_not_save.

ENDIF.

ENDLOOP.

ENDLOOP.

ENDMETHOD.

Display and Search Business Partner Names in SAP Web UI

Issue
If a business partner is displayed in SAP Web Client UI, you will see „Firstname Lastname“ for natural persons or „Name1“ (address data maintained) or „Name 1 Name2“ (no address data maintained) for organizational units. The search is only working for „Lastname“, „Firstname Lastname“ and „Lastname, Firstname“ resp. „Name1“ „Name2 Name1“ and „Name1, Name2“.

Challenge
If you want to change this logic (especially to resolve the mismatch between display and search), you have to implement BADI BUPA_DESCRIPTION_GET which is used by function module BUPA_DESCRIPTION_GET, BUP_PARTNER_DESCRIPTION_GET and CRM_BUPA_DESCRIPTION_READ.

In SAP CRM standard (and therefore in some cases of SAP Solution Manager as well), the first address line determined by function module ADDRESS_INTO_PRINTFORM is used if the business partner has valid address data (please have a look at method method MOD_ATTR_DATA of class CL_CRM_PARTNER_RUN_BTIL). To change the building logic of the address lines, you have to create and register an own address layout key (900..999) in customizing view V_T005_BAS. You have to implement user exit SZAD0001. BADI BUPA_DESCRIPTION_GET or ADDR_PRINTFORM_SHORT cannot be used here. However in SAP CRM this additional implementation is needed but in SAP Solution Manager you can assume, that mostly BADI BUPA_DESCRIPTION_GET will work, if you have implemented SAP note „2157087 – Partner function „Support team“ only show Name1 in display mode„.

The search logic is located in function module COM_PARTNER_IDENTIFY which is called by method identify_partner of class cl_crm_uiu_bt_partner. (Please search for call of form fill_matchcode_fields). There is no BADI available, therefore you have to use modification or implicit enhancement techniques. Please ensure that SAP note „1713745 – Search of Org. Unit by name is not working“ is implemented, because this note changes the search logic for organizational units.

*"----------------------------------------------------------------------
*"Methoden Signatur:
*"  Importing
*"     VALUE(IS_BUT000) TYPE BUT000
*"     VALUE(IV_ADDRNUMBER) TYPE AD_ADDRNUM
*"     VALUE(IV_VALDT) TYPE BAPIBUS1006_VALIDITY-VALID_DATE
*"     VALUE(IV_BAPI_ENVIROMENT) TYPE FLAG
*"  Changing
*"     VALUE(EV_DESCRIPTION) TYPE BU_DESCRIP
*"     VALUE(EV_DESCRIPTION_NAME) TYPE BU_DESCRIP
*"     VALUE(EV_DESCRIP_NAME_LONG) TYPE BU_DESCRIP_NAME_LONG
*"     VALUE(EV_DESCRIPTION_LONG) TYPE BUS000FLDS-DESCRIP_LONG
*"----------------------------------------------------------------------

METHOD if_ex_bupa_description_get~modify.

  DATA:
    lv_ext_id TYPE string.

  CASE is_but000-type.

*- Person ------------------------------------------------------------------------
    WHEN 1.

*Return Full Name
      ev_description_long = is_but000-name1_text.

*If Full Name is empty, return first and last name.
      IF ev_description_long IS INITIAL.
        ev_description_long = condense( is_but000-name_first && ` ` && is_but000-name_last ).
      ENDIF.

*- Organization ------------------------------------------------------------------------
    WHEN 2.

*Try to get external ID.
      lv_ext_id = /glb/9gt_bp_partner_mapping=>map_partner_int_to_ext(
        iv_third_party_guid = /glb/9gt_bp_partner_mapping=>get_default_third_party_guid( )
        iv_process_type     = /glb/9gt_bp_partner_mapping=>get_default_process_type( )
        iv_partner_no       = is_but000-partner ).

*Return external ID
      IF lv_ext_id IS NOT INITIAL.
        ev_description_long = lv_ext_id.
      ELSE.
*Return Name 2 (Full Organization Name)
        ev_description_long = is_but000-name_org2.

*If Name 2 is empty, return Name 1 only (Short Organization Name)
        IF ev_description_long IS INITIAL.
          ev_description_long = is_but000-name_org1.
        ENDIF.
      ENDIF.

*- Group ------------------------------------------------------------------------
    WHEN 3.

*Return Full Name
      ev_description_long = is_but000-name1_text.

*If Full Name is empty, return Name 1 and Name 2.
      IF ev_description_long IS INITIAL.
        ev_description_long = condense( is_but000-name_grp1 && ` ` && is_but000-name_grp2 ).
      ENDIF.

  ENDCASE.

*Return the same value for all returning parameters.
  ev_description = ev_description_name = ev_descrip_name_long = ev_description_long.

ENDMETHOD.

Änderung des Internetbrowsers für SAP CRM Web UI funktioniert nicht mit Single Sign On

  1. Bitte stelle sicher, dass Firefox, Google Chrome, Opera etc. dein Standardbrowser ist. Wie das geht ist hier erklärt: https://support.google.com/chrome/answer/95417?hl=en
  2. Ab jetzt sollten die Transaktionen WUI, CRM_UI und SM_CRM diesen Internet Browser und nicht mehr den Microsoft Internet Explorer (IE) nutzen.
  3. Falls die Transaktionen WUI und CRM_UI funktionieren, SM_CRM aber nicht, dann liegt das am Single Sign On (SSO). Es sieht so aus, also ob bei aktivem Single Sign On automatisch der IE genutzt wird. Konkret verifizieren kannst du das mit der Transaktion START_BSP und der BSP-Anwendung „CRM_UI_START“. Der Folgende Artikel bestätigt, dass bei SSO ein IE-ActiveX-Control verwendet wird, um den Aufruf zu realisieren: https://scn.sap.com/thread/1406302

Lösung:

  1. Bitte erstelle einen SAP Incident. Die Erfolgswahrscheinlichkeit ist allerdings sehr gering, da es sich streng genommen um keinen Bug sondern eine Funktionsverbesserung handelt.
  2. Verwende nicht den SAP GUI. Hinterlege und nutze stattdessen den SAP CRM Web UI Link als Windows-Verknüpfung, Browser-Favorit oder Portallink. Teilweise kannst du Username und Passwort als Klartextparameter der URL mitgeben (Verknüpfung, Favorit). Teilweise wird SSO unterstützt (Portallink).

Get Multi Level Category

*"----------------------------------------------------------------------
*"Methoden Signatur:
*"  Importing
*"    IV_GUID TYPE CRMT_OBJECT_GUID
*"    IV_CATALOG_TYPE TYPE CRMT_CATALOGTYPE
*"  Returning
*"     VALUE(RT_RESULT) TYPE CRMT_ERMS_CAT_CA_LANG_TAB
*"----------------------------------------------------------------------
************************************************************************
* Method GET_CATEGORY                                                  *
* Date   26.01.2015                                                    *
*                                                                      *
*----------------------------------------------------------------------*
* Get Multi Level Category.                                            *
************************************************************************
METHOD get_category.

*Low Level Function for Debugging: CRM_ERMS_CAT_CA_READ + CRM_ERMS_CAT_AS_READ.

  TYPES:
    tt_category TYPE TABLE OF REF TO if_crm_erms_catego_category.

  DATA:
    li_aspect	    TYPE REF TO if_crm_erms_catego_aspect,
    li_category   TYPE REF TO if_crm_erms_catego_category,
    lr_categories TYPE REF TO data,
    ls_cat_lang   TYPE crmt_erms_cat_ca_lang.

  FIELD-SYMBOLS:
    <ft_category> TYPE tt_category,
    <fi_category> LIKE li_category.

*Ensure valid result.
  REFRESH rt_result[].

*Get Assigned Category.
  CALL METHOD cl_crm_ml_category_util=>get_categoryfirst
    EXPORTING
      iv_ref_guid     = iv_guid
      iv_ref_kind     = 'A'
      iv_catalog_type = iv_catalog_type
    IMPORTING
      er_aspect       = li_aspect
      er_category     = li_category.

  CHECK li_aspect IS BOUND AND li_category IS BOUND.

*Get All Parent Nodes.
  CALL METHOD cl_crm_ml_category_util=>get_cat_pars_all
    EXPORTING
      ir_aspect     = li_aspect
      ir_category   = li_category
    IMPORTING
      er_categories = lr_categories.

  CHECK lr_categories IS BOUND.

  ASSIGN lr_categories->* TO <ft_category>.

*Don't forget our assigned Category.
  INSERT li_category INTO <ft_category> INDEX 1.

  LOOP AT <ft_category> ASSIGNING <fi_category>.

*Get Category Details.
    CALL METHOD <fi_category>->get_details
*  EXPORTING
*    iv_auth_check = ' '
       IMPORTING
*        ev_cat        = ls_cat
         ev_cat_lang   = ls_cat_lang.

*Ensure that description is filled.
    IF ls_cat_lang-cat_desc IS INITIAL.
      ls_cat_lang-cat_desc = ls_cat_lang-cat_labl.
    ENDIF.

    IF ls_cat_lang-cat_desc IS INITIAL.
      ls_cat_lang-cat_desc = ls_cat_lang-cat-cat_id.
    ENDIF.

*Transfer Result
    INSERT ls_cat_lang INTO rt_result[] INDEX 1.

  ENDLOOP.

ENDMETHOD.

Get business partner description for a given partner function or user name

*"----------------------------------------------------------------------
*"Methoden Signatur:
*"  Importing
*"    IV_GUID TYPE CRMT_OBJECT_GUID
*"    IV_PARTNER_FCT TYPE CRMT_PARTNER_FCT
*"    IV_PARTNER_PFT TYPE CRMT_PARTNER_PFT
*"  Exporting
*"    EV_NUMBER TYPE BU_PARTNER
*"    EV_DESCRIPTION_NAME TYPE BU_DESCRIP
*"    EV_DESCRIPTION_SHORT TYPE COMT_PARTNER_ADDRESS_WO_STREET
*"    EV_DESCRIPTION_LONG TYPE COMT_PARTNER_ADDRESS_W_STREET
*"----------------------------------------------------------------------
************************************************************************
* Method GET_PARTNER_OF_FCT                                            *
* Date   26.01.2015                                                    *
*                                                                      *
*----------------------------------------------------------------------*
* Get Partner for given Partner Function.                              *
************************************************************************
METHOD GET_PARTNER_OF_FCT.

  DATA:
    ls_partner          TYPE crmt_partner_external_wrk,
    lv_description      TYPE bus000flds-descrip,
    lv_description_name	TYPE bus000flds-descrip,
    lv_description_long	TYPE bus000flds-descrip_long.

  CLEAR:
    ev_number,
    ev_description_name,
    ev_description_short,
    ev_description_long.

*Get partner for a given partner function or partner function type.
  CALL FUNCTION 'CRM_PARTNER_READ_OW'
    EXPORTING
      iv_ref_guid            = iv_guid
      iv_ref_kind            = 'A'
      iv_partner_fct         = iv_partner_fct
      iv_partner_pft         = iv_partner_pft
      iv_mainpartner_only    = 'X'
      iv_get_bp_numbers      = 'X'
*     IV_REFRESH_ADDRESS_REF = ' '
    IMPORTING
      es_partner_wrk         = ls_partner
    EXCEPTIONS
      error_occurred         = 1
      parameter_error        = 2
      entry_does_not_exist   = 3
      OTHERS                 = 4.

*Partner not found.
  CHECK sy-subrc = 0.

*Get Description
  CALL FUNCTION 'BUP_PARTNER_DESCRIPTION_GET'
    EXPORTING
      i_partnerguid      = ls_partner-bp_partner_guid
    IMPORTING
      e_description      = lv_description
      e_description_name = lv_description_name
      e_description_long = lv_description_long
    EXCEPTIONS
      partner_not_found  = 1
      wrong_parameters   = 2
      internal_error     = 3
      OTHERS             = 4.

*Partner not found.
  CHECK sy-subrc = 0.

*Transfer data.
  MOVE:
    ls_partner-partner_no TO ev_number,
    lv_description_name   TO ev_description_name,
    lv_description        TO ev_description_short,
    lv_description_long   TO ev_description_long.

*Alternatively we could use function CRM_PARTNER_TO_DISPLAY_OW.
*But here we get all partners and have to filter/select the wanted partner entry with own coding.
ENDMETHOD.

*"----------------------------------------------------------------------
*"Methoden Signatur:
*"  Importing
*"    IV_UNAME TYPE SYUNAME
*"  Exporting
*"    EV_DESCRIPTION_NAME TYPE BU_DESCRIP
*"    EV_DESCRIPTION_SHORT TYPE COMT_PARTNER_ADDRESS_WO_STREET
*"    EV_DESCRIPTION_LONG TYPE COMT_PARTNER_ADDRESS_W_STREET
*"----------------------------------------------------------------------
************************************************************************
* Method GET_PARTNER_BY_UNAME                                          *
* Date   26.01.2015                                                    *
*                                                                      *
*----------------------------------------------------------------------*
* Get Partner for given User Name.                                     *
************************************************************************
METHOD get_partner_by_uname.

  DATA:
    lv_partner_guid     TYPE bu_partner_guid,
    lv_description      TYPE bus000flds-descrip,
    lv_description_name	TYPE bus000flds-descrip,
    lv_description_long	TYPE bus000flds-descrip_long.

  CLEAR:
    ev_description_name,
    ev_description_short,
    ev_description_long.

*Get Partner for Username
  CALL FUNCTION 'BP_CENTRALPERSON_GET'
    EXPORTING
      iv_username         = iv_uname
    IMPORTING
      ev_bu_partner_guid  = lv_partner_guid
    EXCEPTIONS
      no_central_person   = 1
      no_business_partner = 2
      no_id               = 3
      OTHERS              = 4.

*Partner not found.
  CHECK sy-subrc = 0.

*Get Description
  CALL FUNCTION 'BUP_PARTNER_DESCRIPTION_GET'
    EXPORTING
      i_partnerguid      = lv_partner_guid
    IMPORTING
      e_description      = lv_description
      e_description_name = lv_description_name
      e_description_long = lv_description_long
    EXCEPTIONS
      partner_not_found  = 1
      wrong_parameters   = 2
      internal_error     = 3
      OTHERS             = 4.

*Partner not found.
  CHECK sy-subrc = 0.

*Transfer data.
  MOVE:
    lv_description_name   TO ev_description_name,
    lv_description        TO ev_description_short,
    lv_description_long   TO ev_description_long.

ENDMETHOD.

SAP CRM & SAP Solution Manager PPF Action Condition Enhancement

How to add attributes for PPF action conditions?

The PPF action framework is a powerful framework to trigger actions (= sending smartforms or executing methods) dependent on several events & issues (= schedule and start conditions).
However in SAP standard there is only a small set of business transaction related attributes which can be evaluated. This document explains how to enhance the PPF by additional customer or SAP standard attributes with minimum development effort.

PPF Action Condition Enhancement.pdf (559.8 KiB)

SAP CRM & SAP Solution Manager E-Mail Notification Enhancement

How to send E-Mails to business partners not mentioned in the current business transaction?

We want to send e-mail notifications on certain conditions to certain partners. However some recipients are only valid on the level of predecessor transactions. SAP standard only supports e-mail notifications to partners of the current Business Transaction.
This little solution removes this limitation and opens the way to send notifications to partners of the current and predecessor transaction.

E-Mail Notification Enhancement.pdf (299.9 KiB)

SAP CRM & SAP Solution Manager Business Transaction Search Enhancement

How to implement business transaction search enhancements with minimum development?

There exist several guides in SCN. These guides always explain how to do big developments in context of search enhancement. These big development activities are needed if we need special value helps or if we need to adjust existing selection criteria or result list or if we want to enhance other searches than business transaction search.
In most cases we simply want to add some additional search criteria and result list fields. In these cases, we are able to implement this low effort solution with minimum development.

Business Transaction Search Enhancement.pdf (808.1 KiB)