Quantcast
Channel: SCN : Document List - SAP CRM: Webclient UI - Framework
Viewing all 189 articles
Browse latest View live

The Curious case of no response from Search in Agent Inbox

$
0
0

This document is based on my personal experience and

you are most welcome to comment and provide feedback about the scenario and solution.

 

We were getting complains that the agent inbox search takes a lot of time to show the results and sometimes it times out without showing any results.

Here's the approach for root cause analysis and the solution that we did.

 

I believe the Step 1 of the following analysis applies to all the reporting framework and the standard queries which are provided by SAP.

Step 1: To start analysing all the slow search response issues , first is to put an external breakpoint in the method

 

                    CL_CRM_REPORT_ACC_DYNAMIC -> DATABASE_ACCESS

db_Access.JPG

 

 

This method exactly tells the select query which hits the database tables to get the list of guids. We can get to know the joins , number of rows and the where clauses used for the database hit from here. Based on the system in your case there could be a problem due an non-indexed column , a z table or too much data.

I noticed that the number of rows was being set as 5199 in our case , even when the max hits was set to 200.

 

On debugging I noticed that the system adds 5000 rows to the guid list and the search is getting fired using a combination of system status and the user status.

The following method does this

 

               CL_CRM_QUERYAUI_RUN_BTIL -> READ_BUSINESS_TRANSACTIONSadding_5000.JPG

 

 

Root Cause of Problem: I noticed that the issued lied partly in our customizing , partly in SAP standard customizing and partly in the above logic. The logic in the above method was not supporting the customizing done for implementation.It was adding 5000 rows to the count of guids and after fetching so many guids the transactions were being read and further filtering was being done.


Background of customizing in the system: We had maintained status profiles for the Z transactions and some of the user statuses were not mapped to a system status (that was a business requirement and hence like that).

 

We had also maintained customizing in the following view to make sure the user status maintained by us are used while searching the inbox status.

 

SAP standard provides customizing in the view CRMC_IC_AUI_MAP_STA where user status can be mapped to the various status shown in the agent Inbox , there is a flag to mark which all status are allowed to be fetched for the "Not Completed" status in the agent inbox.

 

 

Contents of the view CRMC_IC_AUI_MAP_STA


cust.JPG

So , now we knew the problem was because the system was getting hit with combinations of system status and user status when search was done for "Not completed" status in the agent inbox. When there was a combination , the logic would add 5000 to the guid list and hence slow down or time out the end result.

 

One proposal to resolve the problem was the badi implementation for CRM_IC_INBOX_BADI to forcefully set the max hits to 200. This was not a solution for us as the filtering was happening later on and the actual results would have been lesser than 200.

 

Solution : We had already enhanced the inbox search view for customer specific fields and other enhancements. We had already provided a Z class in place of the standard class CL_CRM_AUI_QUERY_SERVICE to cater to additional customer specific requirements. For resolving the issue , the method MAP_PARAM_1O was updated in the Z class by us to remove the system status from the lt_status_tab for our specific transaction types.

 

Hope this analysis and solution helps someone. Please feel free to comment.

Regards, Parveen Kumar


Create Default Empl relationship while creating BP

$
0
0

Hi ,

This document will help us to keep the default values while creating BP . Here I am keeping the Default relationship of employee responsible Of username.

 

 

1. Implement the BADI     :-  BADI_CRM_BP_UIU_DEFAULTS

2. Write the code in method  IF_UIU_BP_DEFAULTS~GET_DEFAULT_VALUES.

 

Copy and paste the below code .

DATAlr_typed_context TYPE REF TO cl_bsp_wd_context,

          lr_coll_wrapper TYPE REF TO cl_bsp_wd_collection_wrapper,

          lr_node TYPE REF TO cl_bsp_wd_context_node,

          lr_current TYPE REF TO cl_bsp_wd_value_node,

          lr_entity TYPE REF TO cl_crm_bol_entity,

          lr_collection TYPE REF TO if_bol_entity_col,

          lr_relation TYPE REF TO cl_crm_bol_entity,

          ls_relation TYPE crmt_bupa_il_relation,

          lv_bp_type TYPE string,

          lv_bp_number TYPE string,

          lv_emp_res   TYPE bu_partner.

 

   FIELD-SYMBOLS: <typed_context>  TYPE any,

                   <context_node> TYPE any.

 

   ASSIGN cr_me->('TYPED_CONTEXT') TO <typed_context>.

   IF sy-subrc = 0.

     lr_typed_context ?= <typed_context>.

     IF lr_typed_context IS BOUND.

       ASSIGN lr_typed_context->('HEADER') TO <context_node>.

       IF sy-subrc = 0.

         TRY.

             lr_node ?= <context_node>.

           CATCH cx_sy_move_cast_error.

         ENDTRY.

         IF lr_node IS BOUND.

           lr_coll_wrapper ?= lr_node->collection_wrapper.

           IF lr_coll_wrapper IS BOUND.

             TRY.

                 lr_entity ?= lr_coll_wrapper->get_current( ).

                 CHECK lr_entity IS BOUND.

                 lr_entity->get_property_as_value( EXPORTING iv_attr_name = 'BP_CATEGORY'

                                                 IMPORTING ev_result = lv_bp_type ).

 

                 lr_entity->get_property_as_value( EXPORTING iv_attr_name = 'BP_NUMBER'

                                                 IMPORTING ev_result = lv_bp_number ).

                 lr_collection  = lr_entity->get_related_entities( iv_relation_name ='BuilRelationshipRel').

                 IF lr_collection  IS BOUND AND lr_collection->size( ) = 0 AND lv_bp_type = '1'.

 

                   lr_relation = lr_entity->create_related_entity( iv_relation_name ='BuilRelationshipRel' ).

                   CALL FUNCTION 'CRM_ERMS_FIND_BP_FOR_USER'

                     EXPORTING

                       iv_user_id = sy-uname

                     IMPORTING

                       ev_bupa_no = lv_emp_res.

                   ls_relation-partner1 = lv_bp_number.

                   ls_relation-partner2 = lv_emp_res.

                   ls_relation-relationshipcategory = 'BUR011'.

                   lr_relation->set_properties( EXPORTING is_attributes = ls_relation ).

                 ENDIF.

               CATCH cx_sy_move_cast_error.

               CATCH cx_crm_cic_parameter_error.

             ENDTRY.

           ENDIF.

         ENDIF.

       ENDIF.

     ENDIF.

   ENDIF.

Update the business transaction document created through ERMS workflow

$
0
0

This document help us to update the business transaction document (Ex: Service Ticket) created through ERMS.

Email response management system will create a document based on the spro settings. The ERMS settings can be found from the path

SPRO->Customer Relationship Management->Email Response Management System->Service Manager->Define Service Manager Profile.

 

Here i would like to explain with example, I will consider the service ticket as business document created out of the ERMS.

The Service ticket created based on the erms workflow as a background process. Suppose if we want to update the document with some custom field data we can do this by two process.

1: We can create a EC function module to trigger while saving ( This will be triggered while manual creation of document also but some cases not required to update the custom data automatically in manual creation ) 

2: We can maintain a custom service ID and can assign this service ID to service manager profile.( This process also can be used to fill some prerequisites for ERMS flow, something like BP check and if it is not valid we can use a dummy BP id before creating the document)

 

Customizing the service id and Service manager profile is not a difficult task. We need to create a custom service ID and should be mapped to service manager profile.

The custom service ID should be assigned with a custom class where in we have to write the logic to update the document.


Creation of Service ID

SPRO->Customer Relationship Management->Email Response Management System->Service Manager->Define Services.

Here we can create a custom service id entry and can be assign custom class to the service ID.

 

Assign the service ID to service manager Profile

SPRO->Customer Relationship Management->Email Response Management System->Service Manager->Define Service Manger Profile->Directly Called Services.

Here we can assign the custom service ID, the same sequence as mentioned here will be executed while executing the workflow.

 

The custom class (SE24) should be created with interface IF_CRM_ERMS_SERVICE, the interface method "Execute" should be used to write the custom logic. This method will have parameter of type CL_CRM_ERMS_SERVICE_MANAGER can be used to retrieve all the data related to ERMS.

 

I hope this document would little bit helpful. Please give comments and suggestions to improve the document.

Upload excel from CRM web UI and displaying result using Dynamic Table (valid only for xlsx. and xls. extention)

$
0
0

Hi,

 

I had a requirement where in user wanted to upload excel in CRM .

 

I can easily develop an se38 report where we provide the functionality of uploading excel and subsequent activity.

 

But this is an approach we have actually implemented many times and since CRM is all about web UI, I wanted to accommodate the requirement from Web UI.

 

Here for fulfilling I did some research and came across following link :

 

http://wiki.scn.sap.com/wiki/display/CRM/CRM+Web+UI+-+Uploading+data+from+Excel+files

 

I must appreciate author for this link.

 

But here whole code is done using Java script and some more concepts.

 

I personally did not wanted to follow the approach and hence after exploring I came up with new solution.

 

Please follow below specified procedure and hope your requirement gets covered.

 

For accommodating requirement I developed Z component.

 

1.jpg

 

Step 1:Create Z component ZEXCEL_UPLOAD, with View 1 for upload bar.

 

For Upload bar we have standard BSP component available GS_FILE_UPLOAD which we can use same.(By component usage functionality) in your Z component.

 

Or you can create a new view and just copy the .htm , EH_ONUPLOAD code from View GS_FILE_UPLOAD/VFileUpload .

 

I actually copied the code in Z view so that I can put my text as per requirement without enhancing standard component. (You can follow any approach)

 

If you are copying the view don’t forget to accommodate the code for Upload button

 

So now your View 1 is ready.

 

Step 2:  Create view 2 for displaying the data from excel in table view

 

Here a beautiful approach is followed . Dynamically we are actually generating the attributes in context node of your result list. Because we wanted to make a generic component.

 

Here suppose you have 5 columns in your excel automatically 5 columns with the same label of your excel would be available as result.

 

Hence you can use same component at multiple places

 

Since we want an list of attributes dynamically we won’t add attributes in context node.

 

But without any attribute in context note your system won’t allow you to create context node and also will throw exception when you will run the component as no config would be available.

 

Hence just add one attribute which is available by default like sr. no. later on by code we will replace same by our list of attributes.

 

Step 3: Reading excel data into an internal table.

 

I personally prefer using Class-method approach for my development.

 

Hence I developed a Z class ZCL_MK_GLOBAL and a static method with public visibility EXCEL_FILE_UPLOAD with importing

parameters filename and content.

 

In EH_ONUPLOAD method of view 1 (Copied code from GS_FILE_UPLOAD component )

 

We have two variable LV_FILE_NAME and LV_FILE_CONTENT_XSTRING.

 

At end of the code of EH_ONUPLOAD method, Call your method EXCEL_FILE_UPLOAD of class ZCL_MK_GLOBAL and

pass LV_FILE_NAME and LV_FILE_CONTENT_XSTRING in it.

 

1.jpg

 

Declare attribute in ZCL_MK_GLOBAL class.(As shown in below image)

 

1.jpg

 

Now we will code in EXCEL_FILE_UPLOAD method.

 

1.jpg

 

 

1.jpg

 

 

 

   METHOD EXCEL_FILE_UPLOAD.  DATA: LO_DOC_SPREADSHEET TYPE REF TO CL_FDT_XL_SPREADSHEET,        LS_MESSAGE         TYPE        IF_FDT_TYPES=>S_MESSAGE,        LV_WS_NAME         TYPE                   STRING,        LT_MESSAGE         TYPE        IF_FDT_TYPES=>T_MESSAGE,        LT_WS_NAME         TYPE STANDARD TABLE OF STRING,        ER_DATA            TYPE REF TO DATA.  TRY .      CREATE OBJECT LO_DOC_SPREADSHEET        EXPORTING          DOCUMENT_NAME = IV_FILENAME          XDOCUMENT     = IV_CONTENT.    CATCH CX_FDT_EXCEL_CORE.      MESSAGE E004(FDT_EXCEL_API) INTO LS_MESSAGE-TEXT.      LS_MESSAGE-MSGTY = 'E'.      "'Unable to parse the excel content.'.      APPEND LS_MESSAGE TO LT_MESSAGE.      RAISE EXCEPTION TYPE CX_FDT_EXCEL        EXPORTING          MT_MESSAGE = LT_MESSAGE.  ENDTRY.
*gets the first worksheet and then getting the data in a internal table  LO_DOC_SPREADSHEET->IF_FDT_DOC_SPREADSHEET~GET_WORKSHEET_NAMES( IMPORTING WORKSHEET_NAMES = LT_WS_NAME  ).
*  Get the first worksheet  READ TABLE LT_WS_NAME INDEX 1 INTO LV_WS_NAME.  IF LV_WS_NAME IS INITIAL.    MESSAGE E005(FDT_EXCEL_API) INTO LS_MESSAGE-TEXT.    LS_MESSAGE-MSGTY = 'E'.    "'No worksheet exists in the excel content.'.    APPEND LS_MESSAGE TO LT_MESSAGE.    RAISE EXCEPTION TYPE CX_FDT_EXCEL      EXPORTING        MT_MESSAGE = LT_MESSAGE.  ENDIF.  ER_DATA = LO_DOC_SPREADSHEET->IF_FDT_DOC_SPREADSHEET~GET_ITAB_FROM_WORKSHEET( LV_WS_NAME ).  GV_CTXT_DATA = ER_DATA.
ENDMETHOD.

Step 4: We will create attributes (by reading the header of the excel) for the result list in view 2.

 

Here we know that in GET_TABLE_LINE_SAMPLE  method, code for attributes of a context node (Table Columns) is done.

 

Hence we will code in this method.

 

1.jpg

 

If you have noticed in above steps we took the data in GV_CTXT_DATA.

 

1.jpg

(If above image is not clear please click on same you would able to see in full screen else please find same code below)

 

 

 

   METHOD GET_TABLE_LINE_SAMPLE.  TYPES: BEGIN OF LINE.
**  TYPES NO TYPE CHAR2. "Added by wizard  TYPES:    SRNO TYPE CHAR2,        END OF LINE.  FIELD-SYMBOLS: <LS_TABLE_LINE> TYPE STANDARD TABLE.  FIELD-SYMBOLS: <FS_IS_FINAL>  TYPE ANY."TABLE.  DATA: LS_TABLE_HEADER TYPE REF TO DATA.  FIELD-SYMBOLS: <GS_TABLE_LINE> TYPE STANDARD TABLE.  FIELD-SYMBOLS: <LS_COMP> TYPE ANY.  DATA: IT_FCAT TYPE LVC_T_FCAT.  FIELD-SYMBOLS: <WA_FCAT> TYPE LVC_S_FCAT.  DATA: LV_TABLINE TYPE REF TO DATA.  ASSIGN ZCL_MK_GLOBAL=>GV_CTXT_DATA->* TO <LS_TABLE_LINE> .  CREATE DATA RV_SAMPLE TYPE LINE. " standard  CHECK <LS_TABLE_LINE> IS ASSIGNED.  READ TABLE <LS_TABLE_LINE> ASSIGNING <FS_IS_FINAL> INDEX 1.  CHECK <FS_IS_FINAL> IS ASSIGNED.  CREATE DATA LV_TABLINE LIKE LINE OF <LS_TABLE_LINE>.  DATA : IT_DETAIL TYPE ABAP_COMPDESCR_TAB,         WA_COMP   TYPE ABAP_COMPDESCR,         LV_COUNT TYPE CHAR20.  DATA : LR_REF_DESCR TYPE REF TO CL_ABAP_STRUCTDESCR.  DATA :GT_DYNA_TABLE  TYPE REF TO  DATA.  DATA: LV_INDEX TYPE SY-INDEX.  DATA : LV_SY_SUBRC TYPE SY-SUBRC VALUE 0.  LR_REF_DESCR ?= CL_ABAP_TYPEDESCR=>DESCRIBE_BY_DATA_REF( LV_TABLINE ).  IT_DETAIL     = LR_REF_DESCR->COMPONENTS .  IF IT_DETAIL IS NOT INITIAL.    DESCRIBE TABLE IT_DETAIL LINES LV_COUNT.
*    LOOP AT IT_DETAIL INTO WA_COMP.
*      WRITE:/ WA_COMP-NAME .
*    ENDLOOP.    DO LV_COUNT TIMES.
*    WHILE LV_SY_SUBRC = 0.      ASSIGN COMPONENT  SY-INDEX OF STRUCTURE <FS_IS_FINAL> TO <LS_COMP>.
*      IF SY-SUBRC = 0.      APPEND INITIAL LINE TO IT_FCAT ASSIGNING <WA_FCAT>.      LV_INDEX = SY-INDEX.      <WA_FCAT>-COL_POS   = LV_INDEX.      <WA_FCAT>-FIELDNAME = <LS_COMP>.      <WA_FCAT>-COLTEXT   = <LS_COMP>.      <WA_FCAT>-DATATYPE  = 'C'.      <WA_FCAT>-INTTYPE   = 'C'.      <WA_FCAT>-INTLEN    = '30' .
*      LV_SY_SUBRC = 0.
*      ELSE.
*        LV_SY_SUBRC = 1.
*      ENDIF.
*    ENDWHILE.    ENDDO.    CALL METHOD CL_ALV_TABLE_CREATE=>CREATE_DYNAMIC_TABLE      EXPORTING        IT_FIELDCATALOG = IT_FCAT      IMPORTING        EP_TABLE        = GT_DYNA_TABLE.    ASSIGN GT_DYNA_TABLE->* TO <LS_TABLE_LINE>.  ENDIF.  CHECK <LS_TABLE_LINE> IS ASSIGNED.  CREATE DATA RV_SAMPLE LIKE LINE OF <LS_TABLE_LINE>.
ENDMETHOD.

 

And congratulation you are done with it Your data is uploaded from excel to grid…Now play with it in whatever way you want

 

Please take care of following points

 

·      1)   If your excel header line contain special character than this solution wont work

·      2)   If length of header is less than 3 character it will not work

·      3)   If length of header increases 15 character it wont work.

 

But being a developer we can definitely handle this by our coding skills or we can ask user to take care on specified points.

 

Note:   CL_FDT_XL_SPREADSHEET specified class is available in CRM 7.0 EHP1 onwards only.

CRM WebClient UI & Netweaver Enterprise Portal Integration

$
0
0

The document covers internal and external Portal & CRM integration, along with some tips, interesting SAP Notes and things to consider when opening an OSS incident/message. The examples within this document are based on CRM EhP 2 with Enterprise Portal 7.20.

View Document

Almost Everything About Transaction Launcher - Part II

$
0
0

This document has been long overdue and I apologize for the delay. The issues that I have been seeing lately are a little bit more complex, or let's say out of the ordinary. Since the configuration, troubleshooting and debugging were already covered in Part I, and you are all experts in that area, in this document I will summarize some of the issues that I have seen with Launch Transactions and their solutions. The format may be similar to an FAQ, but I don't think it qualifies as one. The scenario(s) you face may be different then what is covered here, but my goal is to at least point you in the right direction.

View Document

Hide And Unhide Work-centers in the Navigation Bar Profile Dynamically

$
0
0

Hi,

 

Sometime there are requirements like where we need to Hide some work-center from the Navigation Bar profile based on some condition at run-time.

We all know that this can be done by creating two Business Roles with different Navigation Bar Profiles assigned to them.

 

Now suppose business do not want to use different business roles for this purpose and they want to go with only one business role Or

there might be requirement like Suppose in Interaction Center we need to Hide some Work centers from the Nav Bar Profile until the account will not get confirmed and Once the account gets confirmed the  Work Center should be available on UI.

 

So here I will take simple example lets say  we need to Hide the Work Center ‘Interaction Record’ from the Navigation Bar in IC Agent Role.

In this document I will be explaining how can we Hide Work center 'Interaction Record' from the Nav Bar Profile in IC Agent role if the account is not confirmed and once the account gets confirmed then we will make the 'Interaction Record' work center available in the Nav Bar Profile.

 

Step 1: Put the external debugger in the ‘MainNavigationLinks.htm’ page of the view ‘CRMCMP_NAVBAR/MainNavigationLinks’ under BSP component ‘CRMCMP_NAVBAR/MainNavigationLinks’ .

Now open your business Role in UI . The debugger will stop and just check the entries in ‘CONTROLLER->MENU_ITEMS’ .

 

 

As you can see in the Screen shot it contains all the Work-center Ids which we have made available in the Nav Bar Profile in the Configuration of Business Role and Navigation Bar Profile . Just note down the Work center details( that you want to Hide) from this Table . In our case its ‘Interaction Record’ as shown below:


 

Step 2. We need to Enhance the component ‘CRMCMP_NAVBAR’ and then the view ‘CRMCMP_NAVBAR/MainNavigationLinks’.

Now we are ready to make changes in the ‘MainNavigationLinks.htm’ page for our requirement.

 

Step 3:  Put the below Code in the .htm page . It can be modified according to the Requirement. Please see added Comments in different sections of below code for better understanding.

 

<%@page language="abap" %>
<%@extension name="htmlb" prefix="htmlb" %>
<%@extension name="xhtmlb" prefix="xhtmlb" %>
<%@extension name="crm_bsp_ic" prefix="crmic" %>
<%@extension name="bsp" prefix="bsp" %>
<%@extension name="thtmlb" prefix="thtmlb" %>
<%
data: lv_new type string.
lv_new
= 'X'.
DATA: lr_object TYPE REF TO IF_CRM_UI_PROFILE,
rv_result
TYPE        STRING,
rv_result1
TYPE        STRING.
**Here we are checking the Business Role So that it will be applicable only **for our business role i.e. IC_AGENT
  lr_object = cl_crm_ui_profile=>get_instance( ).
CALL METHOD lr_object->GET_PROFILE
RECEIVING
RV_RESULT
= rv_result.


if RV_RESULT eq 'IC_AGENT'.
Datalr_gdc TYPE REF TO if_crm_ui_data_context,
lr_bo_prop
TYPE REF TO cl_crm_bol_entity,
lr_menu   
TYPE CRMT_THTMLB_MENU_ITEM,
ls_menu   
LIKE LINE OF lr_menu.

lr_gdc
= cl_crm_ui_data_context_srv=>get_instance( ).
CHECK lr_gdc IS BOUND.
lr_bo_prop ?= lr_gdc
->get_entity( name = 'CURRENTCUSTOMER' ).

***Here we are checking whether account is confirmed or not in UI
    if lr_bo_prop is INITIAL.

lr_menu[]
controller->menu_items[].
refresh: controller->menu_items.

***Delete the entry from the table with ID ‘IC_BT_INR’ Interaction Record
      delete lr_menu where ID eq ‘IC_BT_INR'.
controller
->menu_items[] = lr_menu[].
else.
lr_menu[]
controller->menu_items[].
refresh: controller->menu_items.
read TABLE lr_menu INTO ls_menu with key link_id = 'IC_BT_INR'.


if sy-subrc ne 0.

***Adding the Interaction Record Entry back to table which we have copied in ***step 1
         ls_menu-item_level = '0000'.
ls_menu
-ID         = 'IC_BT_INR'.
ls_menu
-text      = 'Interaction Record'.
ls_menu
-link_id   = 'IC_BT_INR'.
ls_menu
-tooltip   = 'Interaction Record'.

APPEND ls_menu TO lr_menu.
controller
->menu_items[] = lr_menu[].
ELSE.
controller
->menu_items[] = lr_menu[].
endif .
ENDIF.
ENDIF.
if lv_new is initial.
%>
<thtmlb:menu menuItems=
"<%= controller->menu_items %>" />
<%
else.
%>
<thtmlb:menuII
id        = "mainmenu"
menuItems =
"<%= controller->menu_items %>" />
<%
endif.
%>

 

 

Hope it helps .

 

Thanks

Kumar Gaurav

Debugging Techniques in SAP CRM Web UI.

$
0
0

Hi Folks,

 

As we already know ABAP Debug tool is the most efficient toll for all our ABAP programmers . Here I would like to share few things about debugging what I know and which are going to be useful while debugging. By using below techniques we can debug more efficiently the source code.Please find the below points.

 

 

1) How to Debug from CRM to ECC?

 

We already know by doing many ways we can trigger debug mode in SAP system , like by selecting BP in application tool bar or by entering /h or /hs in command tool bar or by entering keyword with our user name break idadmin.But if we want to trigger from CRM server to ECC server or vicee versa we have to follow below method.

 

As both system different the only one way to connect is RFC user with this user name name only different SAP system's will communicate.So first of all we have to identify RFC user name in ECC and then we have to change in debugger user name with RFC user name.Please find the below screen shots for more details.

 

Settings.GIF

we can collect RFC user name from transaction code SM59 and then we have to replace that user name in USER parameter.

 

debugging.GIF

 

Note : After debugging we have to replace our user name other wise from ECC side with our user name BP won't trigger .

 

 

2) How to debug form SAP CRM Web UI in different ways?

 

A) Consider a situation we have logged on Web UI with end user credentials but that particular person doesn't have SAP GUI credentials by that time if we want to debug then we have to change name in the following path Utilities->Settings->ABAP Editor -> ABAP Debugging -> User .Please find the above screen shot for details

 

B) If we want to debug from  Web UI then we have to keep Secession Break Point and this is going to be validate for next 2 hours and we can keep maximum 32 secession break points .

 

 

 

 

Secession BP.GIF

 

 

 

 

 

3) How to reprocess the same code in debugging mode ?

 

Consider we are in debugging mode and we have run one condition but we want to run same condition again with out executing the total transaction code.For this we have keep our cursor in the line where exactly we want to run the same code again and need to select Debugger tab in menu bar then have to press go to statement  or else we have to press SHIFT+F12 short cut key .

 

Line Number 18.GIF

we have to keep our cursor from where exactly we want to run the code again and need to click on Go to statement.

 

Goto Statement.GIF

 

then we can re debug the code one more time .

 

4) To Identify Flow stack and to know Global Variable's Memory.

 

A)To Identify the the Below :- When we are debugging in CRM , we have to know flow or Screen Stack of debugging ,that means after current executing method/FM which FM/method is going to triggered to next or which FM/Method trigger earlier . This total flow is available at New Debugger tool in DESKTOP2 .Please find the attached screen shot for more details.

Screen Stack.GIF

 

 

B) To Know Global Variable Memory Details.

 

Consider we are creating a SalesOrder In ECC and we want to validate to order details before saving data in master tables .By that time we have to Global tab in SAP NEW ABAP Debug tool.Generally the names of internal tables will like this CVBAP,CVBAK.

 

Please guide me with your suggestions.....

 

 

Thanks & Regards,

Siva Krishna Boddapati


Step by step to create value help

$
0
0

This document could be used for beginners for Webclient UI development who wants to know how to implement value help.

 

 

Example:

 

When clicking F4 on BusinessPartner ID,

clipboard1.png


a new window pops up as value help, you can click search button to get a list of business partners and choose one of them:

clipboard2.png

Once you mark the first search result, both ID and name would be automatically written back to your host page.

clipboard3.png

Step1: Implement GET_P method for field "BusinessPartner ID":

clipboard4.png

 

CASE iv_property.

     WHEN if_bsp_wd_model_setter_getter=>fp_fieldtype.

       rv_value = cl_bsp_dlc_view_descriptor=>field_type_input.

  ENDCASE.

 

 

 

Implement GET_V method:

 

 create object rv_valuehelp_descriptor type cl_bsp_wd_valuehelp_navdescr       exporting          iv_outbound_plug = 'OP_PARTNER_SEARCH'.


Step2: Create a new outbound plug OP_PARTNER_SEARCH: ( the name must equal to the value passed to exporting parameter in GET_V method )

clipboard6.png

define a private attribute mv_popup with TYPE REF TO if_bsp_wd_popup in your view controller.

 

Implement the following code:

 

 

 

DATA: lv_node  TYPE REF TO cl_bsp_wd_context_node.

DATA: lv_title TYPE string.

lv_title = cl_wd_utilities=>get_otr_text_by_alias( 'CRM_UIU_PROD_CUST/SEARCH_CUSTOMER' ).

mv_popup = comp_controller->window_manager->create_popup(

             iv_interface_view_name = 'SearchHelpWindow'

             iv_usage_name          = 'BPSearch'

             iv_title               = lv_title ).

mv_popup->set_display_mode( if_bsp_wd_popup=>c_display_mode_surrounded ).

mv_popup->set_on_close_event( iv_view = me iv_event_name = 'CLOSEPOPUP' ).

mv_popup->open( 'CLEAR_ALL' ).


Step3: in step2 we try to open the popup window defined in component usage BPSearch, so we have to define that usage in runtime repository:

clipboard7.png

in code it is defined when value help window is closed, event CLOSEPOPUP will be triggered. So we create this event handler and implement it:

In the event handler, we get the selected BP information from context node PARTNER of component BP_HEAD_SEARCH and

set the content into our own field "BusinessPartner ID" and "Employee Name":

method EH_ONCLOSEPOPUP.

 

DATA: lv_target_node TYPE REF TO cl_bsp_wd_context_node.

  DATA: lr_node      TYPE REF TO cl_bsp_wd_context_node,

             lr_entity    TYPE REF TO if_bol_bo_property_access,

             lr_entity_bp TYPE REF TO if_bol_bo_property_access,

             lv_fullname TYPE BU_DESCRIP,

             lv_bp_id    TYPE bu_partner.

  lr_entity ?= me->typed_context->bpinfo->collection_wrapper->get_current( ).

  ASSERT lr_entity IS NOT INITIAL.

  lr_node = mv_popup->get_context_node( 'PARTNER' ).

  CHECK lr_node IS BOUND.

  lr_entity_bp = lr_node->collection_wrapper->get_current( ).

  CHECK lr_entity IS BOUND AND lr_entity_bp IS BOUND.

  lv_bp_id = lr_entity_bp->get_property_as_string( 'BP_NUMBER' ).

  CHECK lv_bp_id IS NOT INITIAL.

  lr_entity->set_property( iv_attr_name = 'BP_ID' iv_value     = lv_bp_id ).

  CALL FUNCTION 'CRM_BUPA_DESCRIPTION_READ'

      EXPORTING

         iv_partner          = lv_bp_id

      IMPORTING

         ev_description_name = lv_fullname

      EXCEPTIONS

         no_partner_specified  = 1

         no_valid_record_found = 2

         OTHERS                = 3.

   lr_entity->set_property( iv_attr_name = 'BP_NAME' iv_value     = lv_fullname ).

Note: when you create the outbound plug OP_PARTNER_SEARCH in step2, the method is created with Protected by default. You should change the visibility manually to Public:

clipboard9.png

or else you will meet with CX_BSP_WD_INCORRECT_IMPLEMENT exception, since in the runtime the framework would expect to call it as public method as below:

clipboard10.png

Custom GENIL used in Guided Page Activity BSP View

$
0
0

TaskUI_header.jpg

 

Applies to:

SAP CRM 7.0, EHP1 and EHP2

 

Summary

This particular document illustrates step by step procedure to create guided page activity (Popularly  known as Task type UI View in SAP CRM terminology).  This document also provides procedure to create the ZBOL and custom GENIL class in order to do data handling and then will be using the same in BSP workbench as guided page activity view.

 

Author(s): Rajwin Singh Sood

Company: Atos

Created on: 25th Feb 2014

 

Author Bio

Author_pic.jpgRajwin Singh Sood is currently working as Team lead/Solution Architect at Atos. He has got experience of about 9  years in SAP ABAP and SAP CRM web UI. He is also a SAP CRM EHP2 Certified associated consultant. Prior to working with Atos he had worked with SAP India(SAP Global Delivery), Capgemini , Accenture and Infosys. He worked in SAP CRM Web Ui in areas like BSP enhancements, transaction launchers, BOL Programming, BRFPlus .

 

 

Custom Table & Structure Creation for BOL Objects

We’ll be using two custom tables in order to illustrate the task type UI the tables snapshots are given below:-

 

pic1.jpg

 

This particular table will be saving the data with respect to the employee personal data where the emp_no will be primary key. Structure for the same is also created the snapshot is given below:-

 

pic2.jpg

 

And the other table which is dependent table is used to save employee information table the snap shot is given below :-

 

pic3.jpg

 

The structure for the BOL is also created and the snap shot is given below:-

 

pic4.jpg

 

GENIL Component Creation & SPRO Settings

You have to make entries in the SPRO for Genil component and component set. While creating a new entry for the Genil component, you need to specify Genil class, description, model table and object table.

Object table will contain the list of BOL objects and their structure types and model table will contain relationship between those BOL objects and cardinality.

CRM->CRM Cross application components->Generic interaction layer->Basic Settings

 

 

pic5.jpg

 

Create a new entry for your custom Genil component, its description, implementation class, object table and model table.

 

pic6.jpg

 

Create a new component set.

 

pic7.jpg

 

Assign your component to component set.

pic8.jpg

 

Object Table & Model Table Creation

The object table and model table are the one where the whole business logic of the BOL lies as the GENIL class is always dependent on these to talk to the data base tables. The object table ZEMP_DET_OBJ is created for the same

 

 

pic9.jpg

 

The entries in the table are for root object which corresponds to the Employee personal table which is the root table and the access object which corresponds to the employee official table which will be used together in the Task type UI.

 

 

pic10.jpg

 

pic11.jpg

 

The model table is used to show the cardinality between the root and access object by this we mean that between the employee personal information and employee official data we have the cardinality defined as 1 to 1. This is just for illustration you can change the cardinality accordingly.

 

pic12.jpg

 

pic13.jpg

 

Here cardinality A corresponds to the relationship of object A(employee personal information) where entry C corresponds to 1 and the CARD B corresponds to the relationship of object(employee  official information) which means  there could either 0 or more than 1 entry.

 

Genil Class Creation

Genil class is the one which will be containing the business logic to database handling.

Create the class using transaction se 24 change the super class to CL_CRM_GENIL_ABSTR_COMPONENT

Which is the standard SAP class containing all the necessary methods to deal with the data base handling.

 

Pic15.jpg

 

The methods which we need to redefine are:-

IF_GENIL_APPL_INTLAY~CREATE_OBJECTS: this method is required to be redefined as this method is always called whenever new record for Employee personal information is created. The code snippet is given below:-

 

 

METHOD if_genil_appl_intlay~create_objects.

  DATA:

    ls_create_root  TYPE zemp_pers_data,

    lv_err          TYPE string,

    lt_request_obj  TYPE crmt_request_obj_tab,

    ls_request_obj LIKE LINE OF lt_request_obj,

    lt_bapireturn   TYPE bapiret2_tab.

 

  CALL METHOD super->if_genil_appl_intlay~create_objects

    EXPORTING

      iv_object_name = iv_object_name

      iv_number      = iv_number

      it_parameters  = it_parameters

      iv_root_list   = iv_root_list.

 

  CHECK iv_object_name = 'ZEMP_Details'.

 

* get create parameters:

  CALL METHOD cl_crm_genil_abstr_component=>fill_struct_from_nvp_tab

    EXPORTING

      it_parameters = it_parameters

    CHANGING

      cs_parameter  = ls_create_root.

 

****create new employee in the system

  CALL METHOD me->create_new_emp

    EXPORTING

      i_new_emp         = ls_create_root

    RECEIVING

      e_err_during_save = lv_err.

 

*  IF lv_err IS INITIAL AND ls_create_root IS NOT INITIAL.

  iv_root_list->add_object( iv_object_name = 'ZEMP_Details' "#EC NOTEXT

                            is_object_key =  ls_create_root-emp_no ).

*  ENDIF.

* read the attributes:

  me->if_genil_appl_intlay~get_objects(

                               it_request_objects = lt_request_obj

                               iv_root_list       = iv_root_list   ).

 

ENDMETHOD.

 

IF_GENIL_APPL_INTLAY~GET_OBJECTS: This particular method picks up the entries from the object table. To understand that same please paste the below code snippet and put a break point on the statement and then run the transaction GEINL_MODEL_BROWSER. The code snippet is given below:-

 

METHOD if_genil_appl_intlay~get_objects.

  CALL METHOD super->if_genil_appl_intlay~get_objects

    EXPORTING

      it_request_objects = it_request_objects

      iv_root_list       = iv_root_list.

** Local Objects

  DATA: lo_object TYPE REF TO if_genil_container_object,

        lo_msg_cont TYPE REF TO cl_crm_genil_global_mess_cont,

        lo_attr_props TYPE REF TO if_genil_obj_attr_properties.

 

  DATA: ls_emp_per TYPE zemp_pers_data,

        ls_emp_off TYPE zemp_off_data.

  DATA: lv_key  TYPE zemp_no,

        lv_selected_val TYPE zemp_no,

        lv_name TYPE crmt_ext_obj_name.

 

  lo_object = iv_root_list->get_first( ).

  WHILE lo_object IS BOUND.

    lv_name = lo_object->get_name( ).

    CASE lv_name.

      WHEN 'ZEMP_Details'.

        IF lo_object->check_attr_requested( ) = abap_true.

          CALL METHOD lo_object->get_key

            IMPORTING

              es_key = lv_key.

          lv_selected_val = lv_key.

          SELECT SINGLE * FROM zemp_pers_data INTO CORRESPONDING FIELDS OF ls_emp_per WHERE emp_no =  lv_selected_val.

          lo_object->set_attributes( ls_emp_per ).

          lo_attr_props = lo_object->get_attr_props_obj( ).

          lo_attr_props->set_all_properties( if_genil_obj_attr_properties=>changeable ).

        ENDIF.

      WHEN 'Zemp_off_data'.

        IF lo_object->check_attr_requested( ) = abap_true.

          CALL METHOD lo_object->get_key

            IMPORTING

              es_key = lv_key.

          lv_selected_val = lv_key.

          SELECT SINGLE * FROM zemp_off_data INTO CORRESPONDING FIELDS OF ls_emp_off WHERE emp_no =  lv_selected_val.

          lo_object->set_attributes( ls_emp_per ).

          lo_attr_props = lo_object->get_attr_props_obj( ).

          lo_attr_props->set_all_properties( if_genil_obj_attr_properties=>changeable ).

        ENDIF.

      WHEN OTHERS.

    ENDCASE.

    lo_object = iv_root_list->get_next( ).

  ENDWHILE.

 

 

  1. ENDMETHOD.

 

IF_GENIL_APPL_INTLAY~MODIFY_OBJECTS

The modify method is called whenever we make any changes in the employee data. So when ever we tried to create new employee official information at that point of time this method will be called from GENIL. The code snippet is given below:-

 

 

METHOD if_genil_appl_intlay~modify_objects.

  CALL METHOD super->if_genil_appl_intlay~modify_objects

    EXPORTING

      iv_root_list        = iv_root_list

      iv_return_root_list = iv_return_root_list

    IMPORTING

      et_changed_objects  = et_changed_objects.

 

  DATA:

    ls_create_root  TYPE zemp_pers_data,

    lv_err          TYPE string,

    lt_request_obj  TYPE crmt_request_obj_tab,

    ls_request_obj LIKE LINE OF lt_request_obj,

    lt_bapireturn   TYPE bapiret2_tab.

 

  DATA:

    lr_root_object      TYPE REF TO if_genil_cont_root_object,

    lt_changed_objects  TYPE crmt_genil_obj_instance_tab,

    ls_changed_object   TYPE crmt_genil_obj_instance,

    ls_emp_off          TYPE zemp_off_data,

    lr_emp_offical_det  TYPE REF TO if_genil_container_objectlist,

    lr_emp_object       TYPE REF TO if_genil_container_object,

    lv_err_msg          TYPE string,

    lv_objname          TYPE crmt_ext_obj_name.

 

 

  CLEAR:

    et_changed_objects.

 

* start the modify process

  lr_root_object = iv_root_list->get_first( ).

*read the employee personal data from which we'll retrieve the employee offcial data and then update it accordingly.

  WHILE lr_root_object IS BOUND.

 

* get the name of the root object:

    lv_objname = lr_root_object->get_name( ).

    CASE lv_objname.

      WHEN 'ZEMP_Details'.

****update the root object before checking out the children of the root node

        CALL METHOD lr_root_object->if_genil_cont_simple_object~get_attributes

          IMPORTING

            es_attributes = ls_create_root.

***create new employee in the system

        CALL METHOD me->create_new_emp

          EXPORTING

            i_new_emp         = ls_create_root

          RECEIVING

            e_err_during_save = lv_err.

        IF lv_err IS INITIAL.

          ls_changed_object-object_name = 'ZEMP_Details'.

          ls_changed_object-object_id   = ls_create_root-emp_no.

          APPEND ls_changed_object TO et_changed_objects.

        ENDIF.

****get the children of the root node which is nothing but the data containing employee

        CALL METHOD lr_root_object->if_genil_container_object~get_children

          EXPORTING

            iv_as_copy = abap_false

          RECEIVING

            rv_result  = lr_emp_offical_det.

 

      WHEN OTHERS.

    ENDCASE.

    lr_root_object = iv_root_list->get_next( ).

  ENDWHILE.

****after getting the children modify the offical data of employee by calling the modify method

  IF lr_emp_offical_det IS BOUND.

    lr_emp_object = lr_emp_offical_det->get_first( ).

    IF lr_emp_object IS BOUND.

      CALL METHOD lr_emp_object->if_genil_cont_simple_object~get_attributes

        IMPORTING

          es_attributes = ls_emp_off.

      IF ls_emp_off IS NOT INITIAL.

        CALL METHOD me->modify_emp_off_data

          EXPORTING

            i_off_data        = ls_emp_off

          RECEIVING

            e_err_during_save = lv_err_msg.

        IF lv_err_msg IS INITIAL.

          ls_changed_object-object_name = 'Zemp_off_data'.

          ls_changed_object-object_id   = ls_emp_off-emp_no.

          APPEND ls_changed_object TO et_changed_objects.

        ENDIF.

      ENDIF.

    ENDIF.

  ENDIF.

  1. ENDMETHOD.

 

IF_GENIL_APPL_MODEL~GET_MODEL

This particular method will picking up the cardinalities between the objects from the model table which we had created in previous section.

ETHOD if_genil_appl_model~get_model.

  CALL METHOD super->if_genil_appl_model~get_model

    RECEIVING

      rt_relation_det = rt_relation_det.

 

  DATA:

    ls_relation_detail   TYPE crmt_relation_detail.

  DATA: lt_emp_rel TYPE STANDARD TABLE OF zemp_det_mod,

        ls_emp_rel TYPE zemp_det_mod.

 

  SELECT * FROM zemp_det_mod INTO TABLE lt_emp_rel.

  IF sy-subrc IS INITIAL.

    LOOP AT lt_emp_rel INTO ls_emp_rel.

      MOVE-CORRESPONDING ls_emp_rel TO ls_relation_detail.

      APPEND ls_relation_detail TO rt_relation_det.

    ENDLOOP.

  ENDIF.

  1. ENDMETHOD.

 

IF_GENIL_APPL_MODEL~GET_OBJECT_PROPS

this particular method is used pick up the object properties like the key fields of the table, the fields which should appear on screen while creating new entries and so on.

 

METHOD if_genil_appl_model~get_object_props.

  CALL METHOD super->if_genil_appl_model~get_object_props

    RECEIVING

      rt_obj_props = rt_obj_props.

  DATA: ls_obj_properties   TYPE  crmt_obj_properties,

        lt_emp  TYPE STANDARD TABLE OF zemp_det_obj,

        ls_emp TYPE zemp_det_obj.

  SELECT * FROM zemp_det_obj INTO TABLE lt_emp.

  IF sy-subrc IS INITIAL.

    LOOP AT lt_emp INTO ls_emp.

      ls_obj_properties-object_name   = ls_emp-object_ext.

      ls_obj_properties-attr_struct   = ls_emp-attr_structure.

      ls_obj_properties-create_struct = ls_emp-attr_structure.

      ls_obj_properties-key_struct    = 'CRMT_PRIL_OBJEXT'.

      MOVE-CORRESPONDING ls_emp TO ls_obj_properties.

      APPEND ls_obj_properties TO rt_obj_props.

    ENDLOOP.

  ENDIF.

 

  1. ENDMETHOD.

 

CREATE_NEW_EMP

This particular method is used to update data with respect to employee personal information and will be called while creating the data in GENIL class:-

 

METHOD create_new_emp.

  IF i_new_emp IS NOT INITIAL.

    i_new_emp-mandt = sy-mandt.

    CALL FUNCTION 'ENQUEUE_EZEMP_DEMO_LOCK'

      EXPORTING

        mandt          = sy-mandt

        emp_no         = i_new_emp-emp_no

*       X_EMP_NO       = ' '

      EXCEPTIONS

        foreign_lock   = 1

        system_failure = 2

        OTHERS         = 3.

    IF sy-subrc <> 0.

* Implement suitable error handling here

      CONCATENATE : 'Employee data with employee number '

                      i_new_emp-emp_no

                     ' already locked' INTO e_err_during_save SEPARATED BY space.

    ELSE.

      MODIFY zemp_pers_data FROM i_new_emp.

      IF sy-subrc IS NOT INITIAL.

        CONCATENATE : 'Data for employee '

                      i_new_emp-emp_name

                     'cant be saved due to system issue' INTO e_err_during_save SEPARATED BY space.

      ELSE.

        CALL FUNCTION 'DEQUEUE_EZEMP_DEMO_LOCK'

          EXPORTING

            mandt    = sy-mandt

            emp_no   = i_new_emp-emp_no

*           X_EMP_NO = ' '

          .

 

      ENDIF.

    ENDIF.

 

  ENDIF.

  1. ENDMETHOD.

 

MODIFY_EMP_OFF_DATA

This particular method is used whenever we are trying to create/update the employee official data.

METHOD modify_emp_off_data.

  IF i_off_data IS NOT INITIAL.

    i_off_data-mandt = sy-mandt.

    CALL FUNCTION 'ENQUEUE_EZEMP_OFF_LOCK'

      EXPORTING

        mandt          = sy-mandt

        emp_no         = i_off_data-emp_no

*       X_EMP_NO       = ' '

      EXCEPTIONS

        foreign_lock   = 1

        system_failure = 2

        OTHERS         = 3.

    IF sy-subrc <> 0.

* Implement suitable error handling here

      CONCATENATE : 'Employee data with employee number '

                      i_off_data-emp_no

                     ' already locked' INTO e_err_during_save SEPARATED BY space.

    ELSE.

      MODIFY zemp_off_data FROM i_off_data.

      IF sy-subrc IS NOT INITIAL.

        CONCATENATE : 'Data for employee number '

                      i_off_data-emp_no

                     'cant be saved due to system issue' INTO e_err_during_save SEPARATED BY space.

      ELSE.

        CALL FUNCTION 'DEQUEUE_EZEMP_OFF_LOCK'

          EXPORTING

            mandt    = sy-mandt

            emp_no   = i_off_data-emp_no

*           X_EMP_NO = ' '

          .

 

      ENDIF.

    ENDIF.

 

  ENDIF.

ENDMETHOD.

Guided Page Activity/ Task type UI component creation

Now we need to create a BSP component using workbench transaction BSP_WD_CMPWB.

 

pic16.jpg

 

After the component is create go to run time repository editor and in that click one edit (pencil  Icon) and right mouse click the model to add the model which is the component set which we create in SPRO  ZEMP_DEMO

 

pic17.jpg

 

After this we need to create the views which we need in the TASKTYPE UI the views created are EmployeeOffDetail and EmployeePerDetails with the BOL models as Zemp_off_data and ZEmp_details.

 

pic18.jpg

 

pic19.jpg

 

In the view employee per Detail we need to make changes in do_init_context so that when ever the taskui start it should have the screen with employee personal information in editable mode for the user to enter data

 

METHOD do_init_context.

  CALL METHOD super->do_init_context

    .

  DATA: lo_core TYPE REF TO cl_crm_bol_core,

        lo_order TYPE REF TO cl_crm_bol_entity,

        lo_temp TYPE REF TO if_bol_bo_property_access,

        lt_params TYPE crmt_name_value_pair_tab,

        ls_params TYPE crmt_name_value_pair,

        lo_factory TYPE REF TO cl_crm_bol_entity_factory.

  CLEAR: ls_params, lt_params, lo_order.

  FREE: lo_core,

        lo_order.

 

  lo_core = cl_crm_bol_core=>get_instance( ).

  lo_factory = lo_core->get_entity_factory( 'ZEMP_Details' ).

 

  ls_params-name = 'EMP_NO'.                                "#EC NOTEXT

  ls_params-value = ' '.

  APPEND ls_params TO lt_params.

 

  ls_params-name = 'EMP_NAME'.                              "#EC NOTEXT

  ls_params-value = ' '.

  APPEND ls_params TO lt_params.

 

  ls_params-name = 'EMP_LNAME'.                             "#EC NOTEXT

  ls_params-value = ' '.

  APPEND ls_params TO lt_params.

 

  lo_order = lo_factory->create( lt_params ).

 

  lo_temp ?= lo_order.

 

  me->typed_context->empper->collection_wrapper->add(

  iv_entity = lo_temp

 

  iv_set_focus = abap_true ).

 

  1. ENDMETHOD.

 

Now we create the task type UI

 

pic20.jpg

 

pic21.jpg

 

pic22.jpg

In the configuration of the taskUi view add the views which you need in steps as in step1 screen for employee personal information will appear and then second one will be employee official data

 

We need to handle the event next so whenever the next button is clicked we need to create the blank screen for employee official information.

For that first we need to redefine the handle event method in the controller class of the task ui view

 

IF_BSP_CONTROLLER~HANDLE_EVENT

 

ETHOD if_bsp_controller~handle_event.

  CALL METHOD super->if_bsp_controller~handle_event

    EXPORTING

      event           = event

      htmlb_event     = htmlb_event

      htmlb_event_ex  = htmlb_event_ex

      global_messages = global_messages

    RECEIVING

      global_event    = global_event.

 

  IF event EQ 'frwdbutton'.

    eh_onnextroadmapitem( ).

  ENDIF.

 

  1. ENDMETHOD.

EH_ONNEXTROADMAPITEM

 

METHOD eh_onnextroadmapitem.

  DATA: lr_emp_per TYPE REF TO cl_crm_bol_entity,

        lr_cuco TYPE REF TO zl_zemp_dat_bspwdcomponen_impl,

        ls_emp_per_details TYPE zemp_pers_data,

        ls_emp_off_details TYPE zemp_off_data,

        lr_emp_off TYPE REF TO cl_crm_bol_entity.

 

  lr_cuco ?= me->comp_controller.

  CHECK lr_cuco IS BOUND.

  lr_emp_per ?= lr_cuco->typed_context->empper->collection_wrapper->get_current( ).

  lr_emp_off ?= lr_cuco->typed_context->offdetail->collection_wrapper->get_current( ).

  IF lr_emp_per IS BOUND.

    CALL METHOD lr_emp_per->if_bol_bo_property_access~get_properties

      IMPORTING

        es_attributes = ls_emp_per_details.

  ENDIF.

  IF ls_emp_per_details IS NOT INITIAL AND lr_emp_off IS NOT BOUND.

    lr_emp_off = lr_emp_per->create_related_entity( iv_relation_name = 'employee_relation' ).

    IF lr_emp_off IS BOUND.

      lr_emp_off->switch_to_change_mode( ).

      ls_emp_off_details-emp_no = ls_emp_per_details-emp_no.

      CALL METHOD lr_emp_off->if_bol_bo_property_access~set_properties

        EXPORTING

          is_attributes = ls_emp_off_details.

      lr_cuco->typed_context->offdetail->collection_wrapper->add( lr_emp_off ).

 

    ENDIF.

 

  ENDIF.

ENDMETHOD.

 

Testing the working mode of task type ui

After completing the coding to test the application just click on the test button

 

pic23.jpg

 

After which you come to screen

 

pic24.jpg

 

 

Enter the new data to be entered

 

pic25.jpg

 

And click on next button

 

pic26.jpg

 

Enter the bank details and click on finish button

 

pic27.jpg

 

 

Now check the data base tables to see whether the data has flowed in

 

pic28.jpg

 

When you click on execute

 

pic29.jpg

 

 

So employee has been created now pick up the emp_no and check it in employee official information table

 

pic30.jpg

 

pic32.jpg

 

the above was just an illustration or simple example as to how we can use guided page activity, it could be used for more complex scenarios where in we would have cases involving steps to save data for multiple database tables.

Adding new field to the Rapid application

$
0
0

I would like to share my recent findings with rapid application development. As most of us know that rapid application used to maintain entries in database table from web UI screen. Rapid application is quite similar to the table maintenance view in GUI. But using rapid application system will generate BSP component with search, result and detail page views.

There are certain cases where in we want to add a new field to the existing rapid application, this can be done easily with few steps in a quick manner.

 

1. First of all we need to enhance the database table with the new field details.

2. Open the BSP component corresponds to rapid application then navigate to BOL Model Browser section, there you can find the required entity under the root objects, then enhance the structure with new field details. The sturcture name would be names as tablename*attr ( DB table name * attr ) Now we can see the new field in our context node attributes then change the reuired configurations.

 

Rapid app1.png

 

3. We need to enhance the working structure also with new field, we can identify the working structure by searching with table name * work in SE11, you can find the respective structure and then add new field in this structure. If we do not enhance the working structure you will be getting a error message while saving the data from web UI screen.

4. There is final step to update the new field value in database table. If we create a new entry then system will insert the entry in data base table along with new field value but suppose user try to update the existing entry system will not replicate the new field value in database table. To make it work we need to change one standard function module which is used to update or insert the entry into database table.

     We can find the function module by using where used list of the database table and we can modify the function module directly. We need to add the new field in where condition for updating the database table.

5. We can regenerate the table maintenance without disturbing nay existing settings. So that GUI table maintenance and web ui screen will have same set of fields.

Enabling BI reports IN CRM Web UI

$
0
0

1. Prerequisites

The corresponding BW reports should be built on BW system before they can be used as links in CRM Portal.

2. Configuration Rationale

This configuration is required as part of BI report access from the CRM portal. It includes addition of BI report links for respective queries and applicable roles on the CRM portal.

3. Configuration Procedure

3.1 Development of the BI Reports

 

The BI Queries should be already developed using Query Designer

 

3.2 Defining the BI Reports

 

We take the path specified below:

 

1.  CRM-> UI Frame work-> UI Frame work Definition -> Display SAP netweaver BW Reports

 

Click on New entries and maintain the values as shown in figure below:

1.png

2.png

 

3.3 Defining the Logical Links

 

We take the path specified below:

 

CRM-> UI Frame work-> Technical role Definition -> Define Navigation Bar profile.

 

  1. Double click on “Define Logical link” and create logical links for all Queries as shown in below figure:

3.png

 

2.  Go back and click on “Define work center Link Group” link.

 

3.  Select standard link group “ANA-RPT-SR” on left Navigation Pane double click on “Assign Links to work center Link Group”.

4.png

 

4.   Assign the logical links pertaining to BI reports to this work center link group.

 

5.png

5. Select the required Navigation Profile Bar and assign the SLS-REPORT work center link to it as shown below.

6.png

7.png

 

CRM-> UI Frame work-> Business Roles -> Define Business Role

 

  1. Select the required business role and double click on “Adjust work center Group Links” on left pane.
  2. Click on “position” For displaying the Reports related to opportunities enter the following Values

          Work center Id = SLS-REPORT

          Group ID= ANA-RPT-SR

  3.   Once you are in the Overview page check the box “Visible” for all the reports to be displayed in UI as shown in figure below.

 

WEB UI Output:

 

9.png

10.png

 

 

Authors:

Apoorv Dhawan

Neha Manikumar

Drag and Drop in Tree Type BSP View

$
0
0

Drag&drop1.jpg

 

Applies to:

SAP CRM 7.0, EHP1 and EHP2

 

Summary

This particular document illustrates step by step procedure to first create a tree type view in BSP workbench. Then include the Drag & Drop functionality in the same. The drag and drop functionality makes the maintenance easy for the customer wherein user just needs to drag the data from one node of the tree to another node of the tree without any hassles. The inspiration for this document is the complex object which I had worked on wherein I had to introduce the same although the scenario was very complex as the tree was recursive and have n number of children with their children having n number of children and so on(the whole logic of getting the data for the tree was encompassed in LORDS Class). I wasn’t able to reproduce the same scenario in this document but tried to summarize the steps which I had used taking into consideration that in this document I am just having the tree with 1 level of child.

 

Important  point to note: This particular illustration will be valid only when we are trying to drag & drop child node from One parent node to another parent Node. Dragging and dropping the parent node is not possible in this as this is simple step by step illustration.

 

 

Author(s): Rajwin Singh Sood

Company: Atos

Created on: 13th Mar 2014

 

Author Bio

Author_pic.jpgRajwin Singh Sood is currently working as Team lead/Solution Architect at Atos. He has got experience of about 9  years in SAP ABAP and SAP CRM web UI. He is also a SAP CRM EHP2 Certified associate consultant. Prior to working with Atos he had worked with SAP India(SAP Global Delivery), Capgemini , Accenture and Infosys. He worked in SAP CRM Web UI areas like BSP enhancements, transaction launchers, BOL Programming, BRFPlus .

 

 

 

Table definition for the tree type view

We’ll be using a very simple transparent table which will be having the field to capture the parent. Please refer to the below screenshot:-

 

Drag&Drop2.jpg

 

Where the parent ID will be pointing to the parent of that tree. After activating the table please enter the data in the table:-

 

Drag&Drop3.jpg

 

 

View Creation in BSP

This is the first step wherein we’ll be creating a simple view in BSP workbench before converting the same in to Tree type View. Please not that you could create the ZBOL for the same but over here I’ll be incorporating the logic of fetching the data in DO_INIT method of BSP Workbench. For implementing the same into ZBOL you can refer to my previous Blog the link is given below:-

 

http://scn.sap.com/docs/DOC-52830

 

Now go to BSP workbench transaction BSP_WD_CMPWB and create a new BSP Component:-

 

Drag&Drop4.jpg

 

After this create a View with the Value node and in the value node add the structure as ZTREE_PRODUCT so that all the attributes will appear as it is and in the final step of the wizard make the view as table type view and click on the check box of configuration where in finally you’ll get the view as:-

 

Drag&Drop5.jpg

 

After this as mentioned that we’ll incorporating the logic of fetching the data in DO_INIT. We’ll be having the public instance internal table variable which will of type table ZTREE_PRODUCT created in the above step. Please refer to the screenshots given below:-

 

Drag&drop6.jpg

 

And the code snippet is :-

 

Drag&Drop7.jpg

 

Drag&Drop8.jpg

 

Now this global variable will be used wherever we need to retrieve or change data as this has been loaded once the BSP Component is loaded.

 

Steps for converting that View to tree type View

Now as our view is ready we now need to convert the same into tree type view. This particular section you can refer to SCN as there are many blogs written on the same. But I’ll be still covering it up here in order to maintain the consistency of the document. The steps are enumerated below:-

Step1: We need to change the super class of the context node class which was automatically  created in the view creation step to CL_BSP_WD_CONTEXT_NODE_TREE  from CL_BSP_WD_CONTEXT_NODE.

 

Drag&Drop9.jpg

 

Once you do that now once you expand the context node you’ll see it will look like the one given below with the new Method REFRESH in addition to IF_BSP_MODEL~INIT and GET_TABLE_LINE_SAMPLE which were again automatically created while creating the simple view.

Drag&Drop10.jpg

Step2: The refresh method which appeared in the above screenshot needs to be redefined so that it will instantiate the proxy class to get the children of the root node. The important part in converting any view to tree type view is first refresh method and then creation of Proxy class as in refresh method we’ll be first instantiating the proxy class and then the root element(parent) is also added to the view. Please refer to the screenshot as well as the code snippet below:-

 

Drag&Drop11.jpg

 

METHOD refresh.

*CALL METHOD SUPER->REFRESH

*    .

  DATA : lr_iterator TYPE REF TO if_bol_bo_col_iterator,

           lr_entity   TYPE REF TO if_bol_bo_property_access,"cl_crm_bol_entity,

           lr_root     TYPE REF TO if_bsp_wd_tree_node.

 

  TRY.

      lr_iterator = me->collection_wrapper->get_iterator( ).

      lr_entity ?= lr_iterator->get_first( ).

      WHILE lr_entity IS BOUND.

        lr_root = me->node_factory->get_proxy(

                   iv_bo         = lr_entity

                   iv_proxy_type = 'ZCL_PRODUCT_TREE' ).

        lr_root->node_key = add_root_node( lr_root ).

*        exit.

        lr_entity ?= lr_iterator->get_next( ).

      ENDWHILE.

 

    CATCH cx_sy_move_cast_error cx_sy_ref_is_initial.

  ENDTRY.

  1. ENDMETHOD.

Step3: Now  we need to create the Proxy class which we had instantiated in the refresh method as defined in step2 above. Please note it’s the proxy class method GET_CHILDREN which actually picks up the children of the parent node in the view and will be invoked once we try to expand the parent node in the browser. Please refer to the screenshot for the class creation as well as code snippet for the GET_CHILDREN as shown below:-

 

Drag&Drop12.jpg

 

Drag&drop13.jpg

 

METHOD if_bsp_wd_tree_node~get_children.

*CALL METHOD SUPER->IF_BSP_WD_TREE_NODE~GET_CHILDREN

**  EXPORTING

**    is_sort_wish =

*  RECEIVING

*    RT_CHILDREN  =

*    .

  TYPES: BEGIN OF line,

           product_id TYPE zprod_id,

           prod_company TYPE zprod_company,

           prod_type TYPE zprod_root_type,

           parent_id TYPE zprod_id,

         END OF line.

  DATA: lr_child     TYPE REF TO if_bsp_wd_tree_node,

        lv_size_s    TYPE i,

        lv_size_d    TYPE i,

        lr_current   TYPE REF TO if_bol_bo_property_access,

        lr_iterator  TYPE REF TO if_bol_bo_col_iterator,

        lv_parent    TYPE zprod_id,

        ls_prod_tree_par TYPE ztree_product,

        ls_product_tree TYPE ztree_product.

  DATA : lr_valuenode        TYPE REF TO  cl_bsp_wd_value_node,

         lr_col              TYPE REF TO  if_bol_bo_col,

         lr_tabline          TYPE REF TO line,

         ls_tabline          TYPE line.

 

  DATA: lv_entity           TYPE REF TO if_bol_bo_property_access.

 

 

  CREATE OBJECT lr_col TYPE cl_crm_bol_bo_col.

  lr_current ?= me->bo.

  lr_current->get_property_as_value( EXPORTING iv_attr_name = 'PRODUCT_ID'  IMPORTING ev_result = lv_parent ).

  CALL METHOD lr_current->get_properties

    IMPORTING

      es_attributes = ls_prod_tree_par.

  .

  CHECK ls_prod_tree_par-parent_id IS INITIAL.

  APPEND ls_prod_tree_par TO lt_prod_tree.

  IF lv_parent IS NOT INITIAL.

    LOOP AT zl_zbsp_tre_product_impl=>gt_tree_product INTO ls_product_tree WHERE parent_id EQ lv_parent.

      CREATE DATA lr_tabline.

      CREATE OBJECT lr_valuenode

        EXPORTING

          iv_data_ref = lr_tabline.

      CLEAR ls_tabline.

      MOVE-CORRESPONDING ls_product_tree TO ls_tabline.

      lr_valuenode->set_properties( ls_tabline ).

      lr_col->add( lr_valuenode ).

    ENDLOOP.

  ENDIF.

  lv_entity ?= lr_col->get_first( ).

  WHILE lv_entity IS BOUND.

    lr_child = me->node_factory->get_proxy(

           iv_bo = lv_entity

           iv_parent_proxy = me

           iv_proxy_type = 'ZCL_PRODUCT_TREE' ).

    lr_child->is_leaf = abap_false.

    lr_child->expand_node( ).

    APPEND lr_child TO rt_children.

 

    lv_entity ?= lr_col->get_next( ).

  ENDWHILE.

  1. ENDMETHOD.

 

After this you can see once expand the context node in BSP workbench it will look like the one in the below screenshot:-

 

Drag&drop14.jpg

 

Step4: the step 4 is the place where we’ll define the configuration in the configuration tab and change the iterator in the HTM code (View Layout) in order to display the view as tree type view in Browser.

First the HTM code screenshot and snippet

 

Drag&Drop15.jpg

 

The HTM code :-

 

<%@page language="abap" %>

<%@extension name="thtmlb" prefix="thtmlb" %>

<%@extension name="chtmlb" prefix="chtmlb" %>

<%@extension name="bsp" prefix="bsp" %>

<%--<thtmlb:toolbar buttons         = "<%= controller->IF_BSP_WD_DYN_BTN_CONTROL~GET_LOCAL_TOOLBAR_BUTTONS( ) %>"

                foreignUse      = "TRUE"

                id              = "tabtoolbar"

                maxButtonNumber = "<%= controller->IF_BSP_WD_DYN_BTN_CONTROL~GET_NO_OF_VISIBLE_TOOLBAR_BTNS( ) %>" />--%>

<%

* Conversion Cnode SelectionMode to Tag

  data: lv_cellerator_selectionmode type string,

  lv_cellerator_editmode  type string,

  lv_cellerator_selectioncolumn type string.

  cl_thtmlb_util=>translate_selection_mode(

  exporting

  iv_selection_mode    = Product->SELECTION_MODE

  iv_all_rows_editable = space

  importing

  ev_selection_mode   = lv_cellerator_selectionmode

  ev_edit_mode        = lv_cellerator_editmode

  ev_selection_column = lv_cellerator_selectioncolumn ).

%>

<%--<chtmlb:configCellerator downloadToExcel       = "TRUE"

                         editMode              = "<%= lv_cellerator_editmode %>"

                         id                    = "ConfCellTable"

                         onRowSelection        = "select"

                         personalizable        = "TRUE"

                         selectedRowIndex      = "<%= Product->SELECTED_INDEX %>"

                         selectedRowIndexTable = "<%= Product->SELECTION_TAB %>"

                         selectionColumn       = "<%= lv_cellerator_selectioncolumn %>"

                         selectionMode         = "<%= lv_cellerator_selectionmode %>"

                         table                 = "//Product/Table"

                         usage                 = "EDITLIST"

                         visibleFirstRow       = "<%= Product->VISIBLE_FIRST_ROW_INDEX %>"

                         visibleRowCount       = "6"

                         width                 = "100%"

                         xml                   = "<%= controller->configuration_descr->get_config_data( ) %>" />--%>

<chtmlb:configTree id                    = "TreeView"

                   nodeTable             = "<%= product->node_tab %>"

                   dragAndDropIterator = "<%= controller->gr_drag_drop %>"

                   nodeTextColumn        = "NODE_ID"

                   onCollapseNode        = "collapse"

                   onExpandNode          = "expand"

                   onRowSelection        = "select"

                   selectionMode         = "NONE"

                   selectedRowIndexTable = "<%= product->SELECTION_TAB %>"

                   selectedRowIndex      = "<%= product->SELECTED_INDEX %>"

<%--                   type                  = "ASSIGNMENTBLOCK"--%>

                   downloadToExcel       = "FALSE"

                   noFrame               = "TRUE"

                   table                 = "//product/Table"

                   personalizable        = "TRUE"

                   visibleRowCount       = "20"

                   actions               = "<%= controller->gt_button %>"

                   xml                   = "<%= controller->configuration_descr->get_config_data( ) %>" />

 

and the configuration add the fields to be displayed on the browser:-

 

Drag&Drop16.jpg

 

Step5: The last step in the TREE type view creation is that we redefine DO_PREPARE_OUTPUT and in that when the view is loaded first time we’ll add only the Parent items from the ZBSP_TREE table into the collection wrapper after which we call the refresh method which will invoke the proxy class GET_CHILDREN to pick up its children.

 

Drag&Drop17.jpg

 

 

TYPES: BEGIN OF ltype_attr_struct,

           product_id TYPE zprod_id,

           prod_company TYPE zprod_company,

           prod_type TYPE zprod_root_type,

           parent_id TYPE zprod_id,

 

           END OF ltype_attr_struct.

 

  DATA: lv_struct_ref TYPE REF TO ltype_attr_struct,

        lv_value_node TYPE REF TO cl_bsp_wd_value_node,

        lv_size_s     TYPE i,

        lv_size_d     TYPE i,

        lv_bo_coll    TYPE REF TO if_bol_bo_col.

 

  DATA: ls_tree_product     TYPE ztree_product,

        ls_tree_product_tmp TYPE ztree_product,

        lt_tree_product     TYPE ztree_product_tt.

 

*  typed_context->product->collection_wrapper->clear_collection( ).

  REFRESH lt_tree_product.

  IF iv_first_time IS NOT INITIAL.

 

    CREATE OBJECT lv_bo_coll TYPE cl_crm_bol_bo_col.

 

    lt_tree_product[] = gt_tree_product[].

 

    DELETE lt_tree_product WHERE parent_id IS NOT INITIAL.

    LOOP AT lt_tree_product INTO ls_tree_product.

      CREATE DATA lv_struct_ref.

      CREATE OBJECT lv_value_node

        EXPORTING

          iv_data_ref = lv_struct_ref.

      CALL METHOD lv_value_node->if_bol_bo_property_access~set_properties

        EXPORTING

          is_attributes = ls_tree_product.

      lv_bo_coll->add( lv_value_node ).

 

    ENDLOOP.

    typed_context->product->collection_wrapper->set_collection( lv_bo_coll ).

    typed_context->product->refresh( ).

  ENDIF.

  CALL METHOD super->do_prepare_output

    EXPORTING

      iv_first_time = iv_first_time.

 

Now when you test this BSP application by clicking on the button you’ll see it will look like the tree in the browser:-

Drag7Drop18.jpg

 

Also create the events collapse and expand (EH_ONCOLLAPSE & EH_ONEXPAND) the code snippet is given below:-

 

METHOD eh_oncollapse.

  DATA: lv_event TYPE REF TO cl_thtmlb_tree.

 

  FIELD-SYMBOLS: <line> TYPE crmt_bsp_treetable_node.

 

  lv_event ?= htmlb_event_ex.

 

  typed_context->product->collapse_node( lv_event->row_key ).

 

ENDMETHOD.

 

METHOD eh_onexpand.

  DATA: lv_event TYPE REF TO cl_thtmlb_tree.

 

  FIELD-SYMBOLS: <line> TYPE crmt_bsp_treetable_node.

 

  lv_event ?= htmlb_event_ex.

 

  typed_context->product->expand_node( lv_event->row_key ).

ENDMETHOD.

 

Drag&Drop19.jpg

 

Steps for Inclusion of Drag And Drop Feature

After we have created the tree type view now we will be discussing the steps in order to include the drag & drop functionality:-

Step1: The first step is that we need to make the changes in the HTM (View Layout) to include the drag and drop iterator for which we again need to create a class containing the method which will set the property of the view as DRAG & DROP. The screenshots are given below:-

 

Drag7Drop20.jpg

 

<chtmlb:configTree id                    = "TreeView"

                   nodeTable             = "<%= product->node_tab %>"

                   dragAndDropIterator = "<%= controller->gr_drag_drop %>"

                   nodeTextColumn        = "NODE_ID"

                   onCollapseNode        = "collapse"

                   onExpandNode          = "expand"

                   onRowSelection        = "select"

                   selectionMode         = "NONE"

                   selectedRowIndexTable = "<%= product->SELECTION_TAB %>"

                   selectedRowIndex      = "<%= product->SELECTED_INDEX %>"

<%--                   type                  = "ASSIGNMENTBLOCK"--%>

                   downloadToExcel       = "FALSE"

                   noFrame               = "TRUE"

                   table                 = "//product/Table"

                   personalizable        = "TRUE"

                   visibleRowCount       = "20"

                   actions               = "<%= controller->gt_button %>"

                   xml                   = "<%= controller->configuration_descr->get_config_data( ) %>" />

 

Drag7drop21.jpg

 

Drag7drop22.jpg

 

 

In this class include the interface IF_THTMLB_DRAG_N_DROP_ITERATOR and there is no super class for this. After you include the interface you’ll get the methods as IF_THTMLB_DRAG_N_DROP_ITERATOR~RENDER_OBJECTS_DND_BEHAVIORS

IF_THTMLB_DRAG_N_DROP_ITERATOR~RENDER_HEADER_DND_BEHAVIORS

We’ll redefining the method IF_THTMLB_DRAG_N_DROP_ITERATOR~RENDER_OBJECTS_DND_BEHAVIORS

The code is given below:-

METHOD if_thtmlb_drag_n_drop_iterator~render_objects_dnd_behaviors.

  DATA: ls_behavior    TYPE           crm_thtmlb_behavior_structure.

 

  ls_behavior-behaviorid = 'B2'.                            "#EC NOTEXT

  ls_behavior-flavor     = cl_bsp_dlc_config_util=>c_dnd_default_flavor. "'F2'.

  ls_behavior-issource  = 'X'.                              "#EC NOTEXT

  ls_behavior-istarget   = 'X'.                             "#EC NOTEXT

  ls_behavior-effect_cross_control     = 'MOVE'.            "#EC NOTEXT

  ls_behavior-effect_inside_control     = 'MOVE'.           "#EC NOTEXT

  APPEND ls_behavior TO ev_behavior.

Also please add the following line of code to instantiate the object of the class in DO_INIT

 

 

Drag7Drop23.jpg

 

 

Step2: the last step to include the functionality is to add the interface IF_THTMLB_DRAG_N_DROP in the implementation class of the view ZL_ZBSP_TRE_PRODUCT_IMPL which will in turn add the methods IF_THTMLB_DRAG_N_DROP~ON_DRAG & IF_THTMLB_DRAG_N_DROP~ON_DROP respectively. As far as logic is concerned there is a table which is already created when you had converted the view to the tree node Context_node->Product->Node_tab which is populated by the GET_CHILDREN method depending upon you logic to populate the children. So in the drag and drop we’ll be basically playing around with this table for instance we are moving child at position 6 to 1 we’ll be just changing the parent_id for 6 with that of 1 and then in do _prepare_out put we’ll be just reinitializing the table after the table is build. The coding as well as the snapshots are given below for more reference:-

 

Drag7Drop24.jpg

 

This is the internal table which we’ll using to refresh the context_node->product->node_tab

 

Drag7Drop25.jpg

METHOD if_thtmlb_drag_n_drop~on_drag.

  CONSTANTS lc_moved TYPE c VALUE 'M'.

  DATA: lr_iterator     TYPE REF TO if_bol_bo_col_iterator,

        lr_entity       TYPE REF TO if_bol_bo_property_access,

        ls_tree         TYPE ztree_product,

        lr_dnd_obj      TYPE REF TO cl_thtmlb_table_dnd_object.

 

  lr_dnd_obj ?= drag_n_drop_object.

 

  CASE effect.

    WHEN 'MOVE'.

      READ TABLE typed_context->product->node_tab[] INTO gs_tree_product INDEX lr_dnd_obj->row.

      IF sy-subrc IS INITIAL.

        DELETE typed_context->product->node_tab[] INDEX lr_dnd_obj->row.

      ENDIF.

    WHEN 'COPY'.

  ENDCASE.

ENDMETHOD.

 

Drag7Drop26.jpg

 

 

METHOD if_thtmlb_drag_n_drop~on_drop.

  CONSTANTS lc_moved TYPE c VALUE 'M'.

  DATA: lr_iterator     TYPE REF TO if_bol_bo_col_iterator,

          lr_entity     TYPE REF TO if_bol_bo_property_access,

          ls_tree       TYPE ztree_product,

          ls_tree_par   TYPE ztree_product,

          lv_expand_id  TYPE string,

          lv_row        TYPE i,

          lv_parent     TYPE zprod_id,

          ls_node_tab   TYPE crmt_bsp_treetable_node,

          lv_dnd_obj    TYPE REF TO cl_thtmlb_table_dnd_object.

 

  TRY.

      lv_dnd_obj ?= drag_n_drop_object.

      IF lv_dnd_obj->row EQ 0.

        lv_dnd_obj->row = 1.

      ENDIF.

      IF gs_tree_product IS NOT INITIAL.

        READ TABLE typed_context->product->node_tab[] INTO ls_node_tab INDEX lv_dnd_obj->row.

        IF sy-subrc IS INITIAL.

 

          IF ls_node_tab-parent_key IS NOT INITIAL.

            gs_tree_product-parent_key = ls_node_tab-parent_key.

          ELSE.

            gs_tree_product-parent_key = ls_node_tab-node_key.

          ENDIF.

          INSERT gs_tree_product INTO typed_context->product->node_tab[] INDEX lv_dnd_obj->row.

          gt_node_tab[] = typed_context->product->node_tab[].

        ELSE.

          lv_row = lv_dnd_obj->row - 1.

          READ TABLE typed_context->product->node_tab[] INTO ls_node_tab INDEX lv_row.

          IF sy-subrc IS INITIAL.

            IF ls_node_tab-parent_key IS NOT INITIAL.

              gs_tree_product-parent_key = ls_node_tab-parent_key.

            ELSE.

              gs_tree_product-parent_key = ls_node_tab-node_key.

            ENDIF.

            INSERT gs_tree_product INTO typed_context->product->node_tab[] INDEX lv_row.

            gt_node_tab[] = typed_context->product->node_tab[].

          ELSE.

            lv_row = lv_dnd_obj->row + 1.

            READ TABLE typed_context->product->node_tab[] INTO ls_node_tab INDEX lv_row.

            IF sy-subrc IS INITIAL.

              IF ls_node_tab-parent_key IS NOT INITIAL.

                gs_tree_product-parent_key = ls_node_tab-parent_key.

              ELSE.

                gs_tree_product-parent_key = ls_node_tab-node_key.

              ENDIF.

              INSERT gs_tree_product INTO typed_context->product->node_tab[] INDEX lv_row.

              gt_node_tab[] = typed_context->product->node_tab[].

 

            ENDIF.

          ENDIF.

 

        ENDIF.

 

      ENDIF.

 

    CATCH cx_root.

  ENDTRY.

ENDMETHOD.

 

Testing the working model of Drag & Drop in browser

 

As we are done with the development now we’ll test it in the browser:-

Run the test button

Drag7Drop27.jpg

 

Drag7Drop28.jpg

 

Now drag the product ID 100202 to 100102

 

Drag7drop29.jpg

 

After dragging it looks like

 

Drag7Drop30.jpg

 

So its moved where we had dragged.

Displaying Assignment Blocks in Tabs

$
0
0

We can display assignment blocks in tabs using thtmlb tag element "tabContainer" .

This will be useful where when we need to display assignment blocks in tab instaed of displaying it one by one in Overview page.

 

First step

we need to create Viewset for this and in .htm page use "tabContainer" tag to display tabs

Atributes:tabLinks is used to show the tabs values

               SelectedTabLinkId is used to show the selected tab link

 

Declare attributes TAB_LINK type CRMT_THTMLB_LINK_T and SELECTED_LINK TYPE string in implementation class

 

in .htm page we need this code for tab

 

<thtmlb:tabContainer id                    = "tc1"

                       design                = "TABS"

                       checkContent          = "FALSE"

                       tabLinks              = "<%= controller->TAB_LINK %>"

                       selectedTabLinkId     = "<%= controller->SELECTED_LINK %>"

                       noExcelDownloadButton = "TRUE"

                       noPersonalizeButton   = "TRUE"

                       noTableGraphicsButton = "TRUE" >

    <bsp:call comp_id = "<%= controller->GET_VIEWAREA_CONTENT_ID( 'VIEWA' ) %>"

              url     = "<%= controller->GET_VIEWAREA_CONTENT_URL( 'VIEWA' ) %>" />

  </thtmlb:tabContainer>

 

here we can use vieware "VIEWA' to have all the (assignments blocks) views and we can display the view on select event of the tab

 

Second step:

For this we need to fill TAB_LINK and SELECTED_LINK attributes

fill tab links in DO_INIT_CONTEXT of the View set

 

DATA:

   ls_link TYPE crmt_thtmlb_link.

  REFRESH tab_link.
  CLEAR ls_link.
  ls_link-id      = 'View1.                      "#EC NOTEXT
  ls_link-onclick = 'VIEW1.                     "#EC NOTEXT
  ls_link-text    = 'Tab1'.

APPEND ls_link TO tab_link.

 

  CLEAR ls_link.

  ls_link-id      = 'View2               "#EC NOTEXT
  ls_link-onclick = 'VIEW2'.                 "#EC NOTEXT
  ls_link-text    = 'Tab2'.

  APPEND ls_link TO tab_link.

 

and selected_link = 'View1'. "default tab.

 

Third step:

on tab click event VIEW1 and VIEW2 put code to navigate to the selected view

EH_ONVIEW1.

selected_link = 'VIEW1'.

view_manager->navigate( source_rep_view = rep_view

                            outbound_plug = 'ToView1' ).

 

EH_ONVIEW2

selected_link = 'VIEW2'.

view_manager->navigate( source_rep_view = rep_view

                            outbound_plug = 'ToView2' ).

 

create navigation link ToView1 and ToView2 with target views

 

Tabs.jpg

 

Regards,

Deepika.

Navigation/Event handling with messages in CRM Web-UI

$
0
0

Purpose :

 

To trigger/handle events from messages in CRM Web-UI.

 

Explanation :


In CRM Web-UI, we can enable messages to appear as links, on the click of which a custom event can be triggered. Eg: On the click of a particular message , you can change status of a transaction or navigate to another page etc.


1.png


Steps :

 

1. In the view controller's class in tcode : BSP_WD_CMPWB, add an interface : IF_BSP_WD_MESSAGE_HANDLER ( This interface is responsible for handling message events ).

 

1.png

 

2. We need to subscribe the message's handler class, this can be done in any method in the controller class : I prefer , DO_INIT_CONTEXT.

 

DATA : lr_msg       TYPE REF TO cl_bsp_wd_message_service.

 

   lr_msg ?= cl_bsp_wd_message_service=>get_instance( ).

 

"Subscribe message for handling with the controller class

       lr_msg->subscribe_message(

         EXPORTING

           iv_message_class  'ZCRM_MESSAGES'   " Messages, Message Class

           iv_message_number '006'   " Messages, Message Number

           iv_subscriber     me  " Interface for Error Handler

       ).

     CATCH cx_bsp_wd_dupl_mess_subscr.    " Error: Double Registration for a Message

   ENDTRY.


3. In the controller class ( IMPL's ) method : IF_BSP_WD_MESSAGE_HANDLER~HANDLE_MESSAGE , you can handle the message events like this :


method IF_BSP_WD_MESSAGE_HANDLER~HANDLE_MESSAGE.

   if is_message-id = 'ZCRM_MESSAGE' and is_message-number = '006'.

     "logic to handle event

   endif.

endmethod.


How to fetch the Current Business Role selected by User in Web UI.

$
0
0

 

DATA : ls_user_role TYPE string,
           lr_profile_instance
TYPE REF TO if_crm_ui_profile.

 

 

 

 

lr_profile_instance = cl_crm_ui_profile=>get_instance( ).

CALL METHOD lr_profile_instance->get_profile
     RECEIVING
          rv_result
= ls_user_role.

 

 

The variable ls_user_role contains the Business Role selected by the user.

 

                                        (or)

 

DATAlr_profile TYPE REF TO if_crm_ui_profile,
           lv_business_role TYPE string.

* Get the Profile for the Current User


  lr_profile = cl_crm_ui_profile=>get_instance( ).
  lv_business_role = lr_profile->get_profile( ).

 

The variable lv_business_role contains the Business Role selected by the user.


This code is valid for CRM 7.0 onwards.

How to: Export / Download Microsoft Excel, Word, PowerPoint, Generic approach for any file from CRM Web UI

$
0
0
This document explains how to:


Download Excel from CRM Web UI

 

 

  1. Create a BSP Controller "downloadExcel" for Excel.
  2. Create a Controller class "ZCL_CRM_DOWNLOAD_EXCEL" with superclass CL_BSP_CONTROLLER2. Redefine the DO_REQUEST method with the below code.
METHOD do_request.
DATA:
lv_xls          TYPE xstring.
lv_len            TYPE i.
*  Get the excel file here. For more details, you can refer the definition of the following method in How to - Add Custom XML Parts to Microsoft Excel using ABAP
get_xls_download(
      IMPORTING
        ev_xml_xstring_xls = lv_xls
      EXCEPTIONS
        error_occurred    = 1
                            ).
  lv_len = xstrlen( lv_xls ).
*  Export response data
CALL METHOD response->if_http_entity~append_data
    EXPORTING
      data  = lv_xls
      length = lv_len.
*  Set response content-type as Excel
  CALL METHOD response->if_http_entity~set_header_field
    EXPORTING
      name  = 'content-type'                                "#EC NOTEXT
"content-type for XLSX
      value = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'.
"Content types
"Excel (*.xlsx) - 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
"Excel (*.xlsm) - 'application/vnd.ms-excel.sheet.macroenabled.12'

ENDMETHOD.
  3.  Set the contoller class to the BSP Controller. Now you can use this controller to download the file.
BSPControllerExcel.png

Download Word from CRM Web UI

 

 

  1. Create a BSP Controller "downloadWordDoc" for Word.
  2. Create a Controller class "ZCL_CRM_DOWNLOAD_WORDDOC" with superclass CL_BSP_CONTROLLER2. Redefine the DO_REQUEST method with the below code.

 

METHOD do_request.
DATA:
lv_doc          TYPE xstring.
lv_len            TYPE i.
*  Get the word file here. For more details, you can refer the definition of the following method in How to - Add Custom XML Parts to Microsoft Word using ABAP
get_doc_download(
      IMPORTING
        ev_xml_xstring_doc = lv_doc
      EXCEPTIONS
        error_occurred    = 1
                            ).
  lv_len = xstrlen( lv_doc ).
*  Export response data
CALL METHOD response->if_http_entity~append_data
    EXPORTING
      data  = lv_doc
      length = lv_len.
*  Set response content-type as Word
  CALL METHOD response->if_http_entity~set_header_field
    EXPORTING
      name  = 'content-type'                                "#EC NOTEXT
"content-type for DOCX
      value = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'.
"Content types
"Word (*.docx) - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document
"Word (*.docm) - 'application/vnd.ms-word.document.macroenabled.12'

ENDMETHOD.
  3.  Set the contoller class to the BSP Controller. Now you can use this controller to download the file.
BSPControllerWord.png

Download PowerPoint from CRM Web UI



  1. Create a BSP Controller "downloadPowerPoint" for PowerPoint.
  2. Create a Controller class "ZCL_CRM_DOWNLOAD_POWERPOINT" with superclass CL_BSP_CONTROLLER2. Redefine the DO_REQUEST method with the below code.
METHOD do_request.
DATA:
lv_ppt          TYPE xstring.
lv_len            TYPE i.
*  Get the powerpoint file here. For more details, you can refer the definition of the following method in How to - Add Custom XML Parts to Microsoft PowerPoint using ABAP
get_ppt_download(
      IMPORTING
        ev_xml_xstring_ppt = lv_ppt
      EXCEPTIONS
        error_occurred    = 1
                            ).
  lv_len = xstrlen( lv_ppt ).
*  Export response data
CALL METHOD response->if_http_entity~append_data
    EXPORTING
      data  = lv_ppt
      length = lv_len.
*  Set response content-type as PowerPoint
  CALL METHOD response->if_http_entity~set_header_field
    EXPORTING
      name  = 'content-type'                                "#EC NOTEXT
"content-type for PPTX
      value = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'.
"Content types
"PowerPoint (*.pptx) - 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
"PowerPoint (*.pptm) - 'application/vnd.ms-powerpoint.presentation.macroenabled.12'

ENDMETHOD.
  3.  Set the contoller class to the BSP Controller. Now you can use this controller to download the file.
BSPControllerPowerPoint.png

 


Generic Approach: Download a file from CRM Web UI



  1. Create a BSP Controller "downloadFile".
  2. Create a Controller class "ZCL_CRM_DOWNLOAD_FILE" with superclass CL_BSP_CONTROLLER2. Redefine the DO_REQUEST method with the below code.
METHOD do_request.
DATA:
lv_ppt          TYPE xstring.
lv_len            TYPE i.
*  Get the file here.
get_file_download(
      IMPORTING
        ev_xml_xstring_file = lv_file
      EXCEPTIONS
        error_occurred    = 1
                            ).
  lv_len = xstrlen( lv_file ).
*  Export response data
CALL METHOD response->if_http_entity~append_data
    EXPORTING
      data  = lv_file
      length = lv_len.
*  Set response content-type for the file. Get the content-type using API Class method 'cl_mime_repository_api->get( )' while reading the file from the Mime repository
  CALL METHOD response->if_http_entity~set_header_field
    EXPORTING
      name  = 'content-type'                                "#EC NOTEXT
"content-type for file
      value = 'set the content-type here read using the above mentioned API method'.

ENDMETHOD.
  3.  Set the contoller class to the BSP Controller. Now you can use this controller to download the file.
BSPControllerGeneric.png

Why timeout page is always displayed although there is NO TIMEOUT AT ALL

$
0
0

In my blog Timeout page and WebUI freezing issue - Another causethe behavior that a time out page is displayed in UI, although there is no time out at all but instead some exception occurred in ABAP backend. From my point of view this time out page is misleading. In that blog I share one of my example how to find the root cause which causes the ABAP exception in an efficient way.


In this document I will explain to you why the time out page is designed to be rendered after some backend exception occurs.

 

First I need to find a scenario which will trigger an ABAP backend exception. Fortunately I have already one at hand ( I should not say fortunately since this scenario is responsible by my team and I need to fix it anyway):

 

After I click F4 on field Base Category, a popup window is expected to appear.

clipboard1.png


However due to a bug in my code, there is one runtime error in ABAP backend:

clipboard2.png

And then I see error in UI.

clipboard3.png

After I click any place in UI, I see the time out page below.

clipboard4.png

How to find the logic why this time out page is chosen and rendered by UI Framework

 

 

In the beginning I am not clear where to set breakpoint to debug as this timeout page rendering is implemented via UI framework.

 

So I plan to have a try with HTTP Professional.

 

clipboard5.png

I click "Record" button in toolbar to enable trace mode, and reproduce my operation in UI. Immediately I observed there is HTTP 500 error recorded. The log tells me that it tries to get a popup window but failed with result HTTP/1.1 500 Internal Server Error.

clipboard6.png

Right after the 500 error, there is a HTTP 302 redirection and the redirected target is CRM_UI_FRAME/logon_error.htm.

clipboard7.png

Click "Content" tab, it also shows error detail including ABAP callstack.

clipboard8.png

Now we can start trouble shooting in ABAP side. Quickly I notice the text in timeout page is stored in application

->gv_logon_error_message. Again use Where Used function in ABAP workbench and set breakpoint in hit, then reproduce the scenario one again.

clipboard9.png

Breakpoint is triggered as expected. Here due to 500 error, the popup name could not be got, so a session restart is planned as documented in commet 53.

 

 

I just do not understand why my UI framework colleague choose the OTR text TIMEOUT1. IMHO a text like "Some error happened, restart your session" is perhaps better.

 

clipboard10.png


Then the javascript for session restart is filled and redirection is launched as below:

clipboard11.png


Put the mouse on hyperlink and we will see redirection Javascript hint:

clipboard12.png

Almost Everything About Transaction Launcher - Part II

$
0
0

This document has been long overdue and I apologize for the delay. The issues that I have been seeing lately are a little bit more complex, or let's say out of the ordinary. Since the configuration, troubleshooting and debugging were already covered in Part I, and you are all experts in that area, in this document I will summarize some of the issues that I have seen with Launch Transactions and their solutions. The format may be similar to an FAQ, but I don't think it qualifies as one. The scenario(s) you face may be different then what is covered here, but my goal is to at least point you in the right direction.

View this Document

How to maintain multi level category in a transaction

$
0
0

Hi All,

 

I would like to share one of my recent experiences which I hope will make someone else' life easier. My requirement was to maintain the multi level categorization for a transaction. Thus the transaction's value for category was getting changed while the save happens.

 

Untitled picture.png

 

Above is the screenshot of the category which in programming you will get the values in ET_SUBJECT which is the returning parameter for CRM_ORDER_READ function module.

 

You can write the below code in appropriate BADI/program which you think most suitable for your purpose.

 

TYPES:BEGIN OF l_ty_asp_id,

        asp_id TYPE crm_erms_cat_guid,

        val_to TYPE crm_erms_cat_timestamp,

        END OF l_ty_asp_id.

 

* Data declarations

  DATA: l_v_user              TYPE syuname, " User name maintained in static variable

        l_v_bp_guid           TYPE bu_partner_guid, " BP GUID

        l_v_logical_key       TYPE crmt_logical_key,

        l_v_bpid              TYPE personid,        " BP Id

        l_v_catid             TYPE crm_erms_cat_ca_id,  " Category ID

        l_wa_partner_com      TYPE crmt_partner_com, " Partner details

        l_wa_field_names      TYPE crmt_input_field_names, " Input fields

        l_wa_input_fields     TYPE crmt_input_field,            " local work area to store the input fields

        l_i_input_fields      TYPE crmt_input_field_names_tab, " Internal table for input fields

        l_wa_subject_com      TYPE crmt_subject_com,

        l_i_subject_com       TYPE crmt_subject_comt,

        l_is_field_names      TYPE crmt_input_field_names_tab,

        l_is_input_fields     TYPE crmt_input_field_tab,

        l_i_subject           TYPE crmt_subject_wrkt,

        l_i_asp_id            TYPE TABLE OF l_ty_asp_id.

 

* Constants

  CONSTANTS:

            l_c_ref_kind      TYPE crmt_object_kind      VALUE 'A',        " Reference kind as header

            l_c_prof_type TYPE crmt_subject_profile_type VALUE 'A',               " local constant to store the value for profile type

            l_c_mode      TYPE crmt_mode                 VALUE 'A',               " local constant to store the value for mode

            l_c_profile   TYPE crmt_fieldname            VALUE 'SUBJECT_PROFILE', " local constant to store the field name for the field SUBJECT_PROFILE

            l_c_hand      TYPE crmt_fieldname            VALUE 'HANDLE',          " local constant to store the field name for the field HANDLE

            l_c_header    TYPE crmt_fieldname            VALUE 'GUID',            " local constant to store the field name for the field GUID

            l_c_ref_head  TYPE crmt_fieldname            VALUE 'REF_GUID',        " local constant to store the field name for the field REF_GUID

            l_c_kind      TYPE crmt_fieldname            VALUE 'REF_KIND',        " local constant to store the field name for the field REF_KIND

            l_c_prof_typ  TYPE crmt_fieldname            VALUE 'PROFILE_TYPE',    " local constant to store the field name for the field PROFILE_TYPE

            l_c_obj_name  TYPE crmt_object_name          VALUE 'SUBJECT',         " local constant to store the field name for the field SUBJECT

            l_c_asp_id    TYPE crmt_fieldname            VALUE 'ASP_ID',    " local constant to store the field name for the field ASP_ID

            l_c_cat_id    TYPE crmt_fieldname            VALUE 'CAT_ID',    " local constant to store the field name for the field CAT_ID

            l_c_asp_value TYPE crm_erms_cat_as_id        VALUE 'YOUR CATEGORIZATION SCHEMA'.

 

  FIELD-SYMBOLS:<fs_asp_id> TYPE l_ty_asp_id.

 

 

  CLEAR:l_wa_field_names.

 

* Select the corresponding category ID

* First fetch the active ASP ID. For this following things are to be done.

* 1) Fetch the asp_guid from crmc_erms_cat_as which has status R( released)

* 2) Take the val_to which is the highest.

 

  SELECT asp_guid

         val_to

    FROM crmc_erms_cat_as

    INTO TABLE l_i_asp_id

   WHERE asp_id = l_c_asp_value

     AND asp_state = 'R'.

 

  IF sy-subrc = 0.

    SORT l_i_asp_id DESCENDING BY val_to.

    READ TABLE l_i_asp_id ASSIGNING <fs_asp_id> INDEX 1."Reading the highest value.

    IF sy-subrc = 0.   

* Now read the category id for the ASP id.

      SELECT crmc_erms_cat_ca~cat_id UP TO 1 ROWS

        FROM crmc_erms_cat_ca

        JOIN crmc_erms_cat_cd

          ON crmc_erms_cat_ca~cat_guid = crmc_erms_cat_cd~cat_guid

        INTO l_v_catid

       WHERE crmc_erms_cat_cd~cat_label_uc = ca_solution_team

         AND crmc_erms_cat_ca~asp_guid = <fs_asp_id>-asp_id.

      ENDSELECT.

 

      IF sy-subrc = 0.

* Populating the local work area for subject details.

        l_wa_subject_com-ref_guid        = is_orderadm_h_wrk-guid.

        l_wa_subject_com-ref_kind        = l_c_ref_kind.

        l_wa_subject_com-asp_id          = l_c_asp_value.

        l_wa_subject_com-cat_id          = l_v_catid.

        l_wa_subject_com-katalog_type    = 'D'.

 

* Generating a random GUID

        TRY.

            l_wa_subject_com-guid = cl_system_uuid=>create_uuid_x16_static( ).

          CATCH cx_uuid_error.      "Catching an exception

* No need of further processing s required if an exception is caught while generating a

* random GUID, hence raising an exception

        ENDTRY.

 

        l_wa_subject_com-profile_type    = l_c_prof_type.

 

* Check whether the subject is already there. If yes, mode should be change. Otherwise create.

        CALL FUNCTION 'CRM_SUBJECT_READ_OW'

          EXPORTING

            iv_ref_guid     = is_orderadm_h_wrk-guid

            iv_ref_kind     = 'A'

            iv_profile_type = 'A'

          IMPORTING

            et_subject_wrk  = l_i_subject

          EXCEPTIONS

            error_occurred  = 1

            OTHERS          = 2.

        IF sy-subrc <> 0.

* Implement suitable error handling here

        ENDIF.

        IF l_i_subject IS INITIAL.

          l_wa_subject_com-mode            = l_c_mode.

        ELSE.

          l_wa_subject_com-mode            = 'B'.

        ENDIF.

 

        INSERT l_wa_subject_com INTO TABLE l_i_subject_com.

 

** Populating the field names of the fields that are to be updated

        l_wa_field_names-fieldname = l_c_asp_id.

        INSERT l_wa_field_names INTO TABLE l_is_field_names.

        l_wa_field_names-fieldname = l_c_cat_id.

        INSERT l_wa_field_names INTO TABLE l_is_field_names.

        l_wa_field_names-fieldname = l_c_profile.

        INSERT l_wa_field_names INTO TABLE l_is_field_names.

        l_wa_field_names-fieldname = l_c_hand.

        INSERT l_wa_field_names INTO TABLE l_is_field_names.

        l_wa_field_names-fieldname = l_c_header.

        INSERT l_wa_field_names INTO TABLE l_is_field_names.

        l_wa_field_names-fieldname = l_c_ref_head.

        INSERT l_wa_field_names INTO TABLE l_is_field_names.

        l_wa_field_names-fieldname = l_c_kind.

        INSERT l_wa_field_names INTO TABLE l_is_field_names.

        l_wa_field_names-fieldname = l_c_prof_typ.

        INSERT l_wa_field_names INTO TABLE l_is_field_names.

 

        CALL FUNCTION 'CRM_SERVICE_OS_GET_LOG_KEY'

          EXPORTING

            iv_guid           = l_wa_subject_com-guid

            iv_handle         = l_wa_subject_com-handle

          IMPORTING

            ev_logical_key    = l_v_logical_key

          EXCEPTIONS

            parameter_missing = 1

            OTHERS            = 2.

        IF sy-subrc <> 0.

        ENDIF.

 

*Updating hte internal table for input fields.

        l_wa_input_fields-ref_guid    = is_orderadm_h_wrk-guid.

        l_wa_input_fields-ref_kind    = l_c_ref_kind.

        l_wa_input_fields-objectname  = l_c_obj_name .

        l_wa_input_fields-logical_key = l_v_logical_key.

        l_wa_input_fields-field_names = l_is_field_names.

        INSERT l_wa_input_fields INTO TABLE l_is_input_fields.

 

* Maintain the subject values

        CALL FUNCTION 'CRM_SUBJECT_MAINTAIN_OW'

          EXPORTING

            it_subject_com = l_i_subject_com

          CHANGING

            ct_input_field = l_is_input_fields

          EXCEPTIONS

            error_occurred = 1

            OTHERS         = 2.

        IF sy-subrc <> 0.

* Do nothing.

        ENDIF.

      ENDIF.

.

 

 

Now you can check the transaction for the category. It would be maintained with right values.

 

Please let me know if you have any queries.

 

Thanks,

Faisal

Viewing all 189 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>