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

Header Area in Web UI

$
0
0

Objective: To understand and enhance header area of Web UI.

 

Header area in  CRM Web UI is defined by the layout component. To identify the different components which comprise the header, we can have a look at the Layout component.

Path - IMG > Customer Relationship management > UI Framework > Technical Role Definition > Define Layout Profile.

Screen Shot 2016-04-08 at 11.28.13 AM.png

The Layout Profile would have all the layout components which comprises the Web UI page. This includes Logo Area, Header area and other layout components.

To further get the detailing of the layout component, drill down into the layout component WORKAREA_HEADER.

Path - IMG > Customer Relationship management > UI Framework > Technical Role Definition > Define Layout components.

This will contain the application ID or the Web UI component ID. In this case, component is CRM_WORKAREAHDR.

 

Screen Shot 2016-04-08 at 11.29.52 AM.png

 

Component: CRM_WORKAREAHDR

This component contains the header area views and configuration. This component contains views UI_COMPONENT_1, UI_COMPONENT_2, UI_COMPONENT_3.

This UI component can also be used to align and position header elements such as working context, saved search etc.

 

The positioning, realignment and declaration of this elements is done in UI Configuration of the Component CRM_WORKAREAHDR.

For ex, To display Central Search on right hand side of header area i.e, UI_COMPONENT_3, declare as

 

UI_COMPONENT_3:Window=CRM_ALLSEARCHES.CRM_ALLSEARCHES/LauncherWindow;horizontalAlignment=right;

 

We can also provide other header area functionalities, width etc through this method.

 

 

 


WEBCUIF EhP4 SP02 - Release Notes

$
0
0

These Release Notes focus on new features and enhancements delivered as part of the Web Client UI Framework EhP4 Support Package 02.

 

The WEBCUIF development team members are doing their best to provide those new developments on older releases. So if you are interested in a specific feature, verify its availability by checking the corresponding SAP Note.

 

New Features and Enhancements

 

Integration with the SAP Theme Designer

 

It is now possible to style the Web Client UI Framework using the SAP Theme Designer. See the How-To Guide for more details.

 

theme_designer.png

 

See SAP Note: 2232580

 

 

New Progress Indicator THTMLB Tag

 

A new THTMLB Tag, thtmlb:progressIndicator, allows you to easily display a percentage value or any kind of progress and enhance the user experience on your form. You can also use a new P-GETTER attribute in order to any inputfield into a progress indicator on a Configurable Form.

 

progress_bar.png

 

See SAP Note: 2174100 and 2239586

 

 

Floating Pager for the Table

 

 

It is now possible to have the table pager float. The floating pager will appear for tables that are partially in the viewport, thus the pager is always accessible and it is not required to scroll to the complete bottom of the table to navigate to another page of records. When floating, the pager will be semi-transparent; on hover, the semi-transparency will be removed.

 

floating_pager.png

 

See SAP Note: 2268797

 

 

Highlighting of Mandatory Fields

 

Mandatory fields are highlighted consistently in all skins. All mandatory fields have a border to emphasize their importance on a given form. The border color matches the color of the mandatory star.

 

highlight_field.png

 

See SAP Note: 2283068

 

 

If you missed them, check out the WEBCUIF EhP4 SP01 - Release Notes.

Triggering Server side validation by pressing TAB (Enter is not required)

$
0
0

Overview:


Many times in our project we have requirement to trigger server side validation by Pressing TAB key (keyboard). Typically this is a demand from Customer who are usually new to SAP world. I myself had faced similar situation and convinced customer that it is required in SAP CRM to press "Enter" to get the error message aka validating the data.


In this blog I would explain how can we trigger Validation by pressing TAB key in SAP CRM Web UI.

Yes it is clear that we can also attach JavaScript (Attaching Java Script to a field in Table of SAP CRM Web UI) but complex validation logic (through BOL) is not possible or really complex.



Details:


By pressing Tab key on Web UI, it is actually fires client side event "Clientblur". We need to capture trigger event handler through JavaScript for the event Clientblur, and trigger server side event through BSP element <bsp: htmlbEvent>.

 

 

Step 1:

 

Copy CL_UIF_BP_SAMPLE_ITERATOR  class to Z Iterator class. In method "IF_HTMLB_TABLEVIEW_ITERATOR~RENDER_CELL_START" (is used for new column) we need to capture "Clientblur". Below is sample code:

 

DATA: lr_input TYPE REF TO cl_thtmlb_inputfield.

 

   CASE p_tableview_id.

     WHEN OTHERS.

       CASE p_column_key.

         WHEN 'ZZTEST'.     "CRM Web UI Field Name

*         Onclient functionality

           TRY .

               lr_input ?= p_replacement_bee.

               lr_input->onclientblur = 'return Testclientblur()'.

               p_replacement_bee ?= lr_input.

             CATCH cx_root.

               p_replacement_bee ?= p_replacement_bee.

           ENDTRY.

       ENDCASE.

   ENDCASE.


Step 2:

 

In .HTM page need to create an instance of created Iterator class:


DATA: gr_iterator TYPE REF TO ZCL_TEST_ITERATOR.

CREATE OBJECT gr_iterator.

 

In Tableview or Tablecellartor, need to use the before created custom Iterator class. Below sample code:

 

       iterator = "<%= gr_iterator %>"

 

Step 3:


In .HTM page after Tableview / Tablecellartor code declaration, need to declare BSP Element for event firing and JavaScript event handler method.


<bsp:htmlbEvent name = "DO_VALIDATE_INPUT"

                 id   = "DO_VALIDATE_INPUT" />

 

* Here DO_VALIDATE_INPUT is the name of method to handle the event in View Implementation class

* I have used standard method DO_VALIDATE_INPUT for testing purpose and can be best place to write validation for multipurpose uses.

 

Step 4:


In .HTM page after Tableview / Tablecellartor code and  BSP Event Element declaration, JavaScript event handler method should be written.


<script type="text/javascript">

 

function Testclientblur() {

 

DO_VALIDATE_INPUT();

 

}

</script>

 

* Here Testclientblur is the event handler for client side event "Clientblur", which we have declared in Step 1. In this event handler, it is calling Server Side Event and Event handler "Do handle event".

 

 

Test:


I have used for testing and Date field and by pressing the Tab key on Date field pops out error message "Date sdsd is invalid"

 

testerror.png

 

Summary:


I hope it would solve many business case problem where validation error by pressing Enter or Save button is too late. Please use the logic and if you have questions and / or comment, please add. Enjoy

 

Reference: CRM WebClient UI - Talking with Java Script - CRM - SCN Wiki

Check logged in Business Role & derive authorizations

$
0
0

Objective : Change View settings such as showing certain buttons like EDIT based on current logged in Business role.

 

 

Current logged in Business role can be obtained using method GET_PROFILE of Class CL_CRM_UI_PROFILE. We can derive view changes based on Business roles as well.

 

For eg, If the need is to restrict the user to EDIT view only in a certain Business role. this can be achieved by adding the logic in the placeholder wherein the buttons are configured & a simple code snippet like below can derive that logic.

 

Sample code -

 

Data :  lr_profile type ref to CL_CRM_UI_PROFILE,

            lv_role type string.

 

lr_profile ?= CL_CRM_UI_PROFILE=>get_instance().

 

call method lr_profile->if_crm_ui_profile~get_profile

RECEIVING

     rv_result = lv_role.

 

If lv_role NE '<Z-Business role name>'.

         Delete  gt_button where on_click = 'EDIT'.

endif.

Keeping up with the Webclient UI Framework

$
0
0

The Webclient UI Framework (a.k.a. WEBCUIF) is a large and complex product, always evolving thanks to the customers and the community feedback. Here are some resources that can help you stay ahead of the game:

 

Do you use other channels or sources? Do you have other ideas for collaboration? Don't hesitate to start a discussion in the comments below.

HP LoadRunner Scripts For WebUI

$
0
0

Story: Recently I was busy with writing some HP LoadRunner scripts for WebUI. Having no practical experience and being actually a dummy in HP LR in general, I trained myself based on the multiple videos available on YouTube. However, when doing scripts for WebUI I experienced some problems, which are not described well enough somewhere. Therefore, I decided to share my experience here…

1.    Manual Correlation

The thing what you need to do with your script, you need to correlate your script parameters. This means that we need to identify the source for the values and using this source we need to populate our variables.

The process of identifying a proper source for the variable looks like described below.

For instance, you noticed down you are missing a variable REF_ID at line 114. Variable HOST is a defined constant.

p1.png

We can assume that the variable is coming from the previously executed request or requests. First you need to step over the previously executed request, at the line 77. Then select a tab “Snapshot” – “Recording”. Next, navigate to “Response” area and click CTRL+F.

p2.png

Copy the value (e.g. bD1lbiZjPTEwMCZkPW1pbg==) from your Excel file and search for all the occurrences of it.

p3.png

Double-click on the first occurrence in the list.

p4.png

You are navigated to the place of occurrence.

p5.png

What do we get from this? It was a redirected GET request, data is located in the response header, within the following line: location: /sap(bD1lbiZjPTEwMCZkPW1pbg==)/bc/bsp/sap/crm_ui_start/default.htm?sap-sessioncmd=open , in between: “()”. And it’s already enough to get this data in runtime, by using the function web_reg_save_param_ex.

We need to place the following code into the lines right BEFORE our request. So lines 59 – 74 should look like below.

   
      /*    Correlation   comment - Do not change! 
          Original   value='bD1lbiZjPTEwMCZkPW1pbg=='
          Name   ='REF_ID'
          Type   ='ResponseBased'
          Response   Header: location:   /sap(bD1lbiZjPTEwMCZkPW1pbg==)/bc/bsp/sap/crm_ui_start/default.htm?sap-sessioncmd=open
       */   
      web_reg_save_param_ex(
          "ParamName=REF_ID",
          "LB=sap(",
          "RB=)/",
          "Notfound=warning",
          SEARCH_FILTERS,
          "Scope=Headers",
          "IgnoreRedirections=No",
          "RequestUrl=*/crm_ui_start/default.htm*",
          LAST);

 

You can find more details regarding this function here: http://lrhelp.saas.hp.com/en/latest/help/function_reference/Content/web/lrFr_web_reg_save_param_ex.htm

Similar procedures must be performedfor all the variables you defined.

We will consider some common cases that can be relevant for all WebUI HP LR Scripts.

1.1.                    Getting Referrer ID

Referrer ID is required across complete script, from the login page until log-out.

    /*    Correlation comment - Do not   change! 
          Original value='bD1lbiZjPTEwMCZkPW1pbg=='
 
        Name ='REF_ID'
 
        Type ='ResponseBased'
 
        Response Header:   location:   /sap(bD1lbiZjPTEwMCZkPW1pbg==)/bc/bsp/sap/crm_ui_start/default.htm?sap-sessioncmd=open
 
     */   
     
web_reg_save_param_ex(
         
"ParamName=REF_ID",
         
"LB=sap(",
         
"RB=)/",
         
"Notfound=warning",
         
SEARCH_FILTERS,
         
"Scope=Headers",
         
"IgnoreRedirections=No",
         
"RequestUrl=*/crm_ui_start/default.htm*",
         
LAST);
 
     
     
web_custom_request("default.htm_2",
         
"URL={HOST}/sap/bc/bsp/sap/crm_ui_start/default.htm?sap-sessioncmd=open",
         
"Method=POST",
         
….

 

1.2.                    Getting Session ID

Session ID is required across complete script, from the login page until log-out.

    /*    Correlation comment - Do not   change! 
          Original   value='ZT1VMGhCVWxOSVFWUkxTVTVmTXpGZk1UYzJBRkJXbGhZOEh1YUdvTWo2N3Q4QWhRPT0='
          Name   ='ESID' Type ='ResponseBased'
       */
      web_reg_save_param_ex(
          "ParamName=ESID",
          "LB=(",

        "RB=)",
          "Notfound=error",
          SEARCH_FILTERS,
          "Scope=Body",
          LAST);
 
 
      web_submit_data("uif_callback",
          "Action={HOST}/sap/webcuif/uif_callback?sap-client=100&sap-language=EN&sap-domainRelax=min&crm_handler=CL_CRM_UI_SESSION_MANAGER",
          "Method=POST",
          "RecContentType=text/plain",
          "Referer={HOST}/sap({REF_ID})/bc/bsp/sap/crm_ui_start/default.htm",
          "Snapshot=t7.inf",
          "Mode=HTML",
          ITEMDATA,
          "Name=cmd","Value=get_esid",ENDITEM,
          LAST);

 

1.3.                    Getting WCF Request Ticket

WCF Request Ticket is required across complete script, from the login page until log-out.

/*    Correlation   comment - Do not change! 
      Original   value='AF5073FD82AC118ADB0067CA7B4E52A7'
      Name   ='WCF_REQUEST_TICKET'
      Type ='ResponseBased'
  */
      web_reg_save_param_ex(
          "ParamName=WCF_REQUEST_TICKET",
           "LB=name\=\"wcf-secure-id\"   value\=\"",
          "RB=\"",
          "Notfound=error",
          "Ordinal=LAST",
          SEARCH_FILTERS,
          "Scope=Body",
          LAST);

 

    web_url("main.htm",
          "URL={HOST}/sap({ESID})/bc/bsp/sap/crm_ui_frame/main.htm?sap-client=100&sap-language=EN&sap-domainRelax=min&saprole=SALESPRO",
          "Resource=0",

 

Hint: Symbol \ (back-slash) before the character means that this character should be considered as part of the text string, and not as a “special character”.

Hint: Sometimes you get several values for the same criteria. Therefore while testing and debugging you can set up Ordinal=All to get a clear vision on which value you need. In this case, we wanted the LAST occurrence only.

1.4.                    Getting Referrer ID (2)

Referrer ID is required across complete script, from the login page until log-out.

/*    Correlation   comment - Do not change! 
      Original value='bD1FTiZjPTEwMCZpPTEmZT1VMGhCVWxOSVFWUkxTVTVmTXpGZk1UYzJBRkJXbGhZOEh1YUdvTWo2N3Q4QWhRJTNkJTNk'
      Name ='REF_ID_2'
      Type ='ResponseBased'
      Response Header: location: varthtmlbMangling =   "bD1FTiZjPTEwMCZpPTEmZT1VMGhCVWxOSVFWUkxTVTVmTXpGZk1UYzJBRkJXbGhZOEh1YUdvTWo2N3Q4QWhRJTNkJTNk";
  */
      web_reg_save_param_ex(
          "ParamName=REF_ID_2",
          "LB=varthtmlbMangling\= \"",
          "RB=\";",
          "Ordinal=LAST",
          SEARCH_FILTERS,
          "Scope=Body",
          LAST);

 

    web_url("main.htm",
          "URL={HOST}/sap({ESID})/bc/bsp/sap/crm_ui_frame/main.htm?sap-client=100&sap-language=EN&sap-domainRelax=min&saprole=SALESPRO",
          "Resource=0",

 

Hint: Sometimes you get several values for the same criteria. Therefore while testing and debugging you can set up Ordinal=All to get a clear vision on which value you need. In this case, we wanted the LAST occurrence only.

1.5.                    Getting WCF Request Ticket (2)

Referrer ID is required across complete script, from the login page until log-out.

    /*     Correlation comment - Do   not change! 
           Original   value='09AFA03946E7BD32CD3109628855703D'
          Name   ='WCF_REQUEST_TICKET_6'
          Type   ='ResponseBased'

  */
      web_reg_save_param_ex(
          "ParamName=WCF_REQUEST_TICKET_6",
          "LB=wcf-request-ticket\=",
          "RB=\r\n",
          SEARCH_FILTERS,
          "Scope=Headers",
          "RequestUrl=*/bspwdapplication.do*",
          LAST);

 

Hint: Symbols “\r\n” from the above script mean NEW LINE.

1.6.                    Adding Thinking Time

Often you need to add thinking time in seconds into your script. It can be done using the command lr_think_time()as shown below.

    lr_think_time(5);

 

You can also influence thinking time by respective runtime settings of your script.

p6.png

 

 

 

2.    Hints

When you test your script you will probably get several errors when processing a logon step or at the very beginning of your script. Next possible issues are related to processing of the popups, especially when they are appearing sequentially one after another. In this case you may not even get any errors in VUGen, but the script execution won’t be successful. This chapter will describe some known cases and the ways to overcome the issues.

The following table contains some common errors and solutions.

          
ErrorReasonSolution

HTTP Status Code 400

(Session Timed-Out)


Most probably, your session id ESID or referrer session id REF_ID(n) are not correct.Check the correlation of ESID and REF_ID parameters. See hint 5.

HTTP Status Code 403

(Unauthorized Request)


Most probably, your wcf-request-ticket is   not correct.Check correlation of WCF_REQUEST_TICKET(n)   parameter. See hints 5 and 6.

VUGen does not give you any error, but popups are not working.


Most probably you have problems with wcf-request-ticket   or referrer session id REF_ID(n).


Check the correlation of REF_ID(n) and   WCF_REQUEST_TICKET(n). See hints 5, 6, 7 and 8.


Hint 1: Always back-up your script.

Hint 2: Never displace the parameters you cannot correlate by other parameters that you think you correlated correctly.

Hint 3: Try to correlate all parameters. If not possible, try to use constants.

Hint 4: Snapshots can be truncated. Use HTTP tracers instead.

Hint 5: Sometimes in VUGen you get several parameters, even though you can see only one in the Snapshot or in HTTPWatch. In this case use option Ordinal = All to get all the variables (VAR_n) and chose the appropriate one later: Ordinal = 1, 2, N, or LAST.

Hint 6: If the right border (parameter RB) for certain variable is NEXT LINE, you need to use “RB=\r\n” in respective web_reg_save_param_ex call.

Hint 7: VUGen does not give you any error, but popups are not working. You should pay attention to referrer ids and wcf-request-tickets, especially for callbackFlashIslands and callbackSilverlightIslands.

 

"Action={HOST}/sap({REF_ID_2})/bc/bsp/sap/crm_ui_frame/bspwdapplication.do?id=1&wcf-request-ticket={WCF_REQUEST_TICKET_6}",

 

"Name=wcf-secure-id","Value={WCF_REQUEST_TICKET}",ENDITEM,

 

"Name=callbackFlashIslands","Value=/sap({REF_ID_2})/webcuif/uif_callback?crm_handler=CL_THTMLBX_FLASH_ISLAND&wcf-request-ticket={WCF_REQUEST_TICKET}",ENDITEM,
          "Name=callbackSilverlightIslands","Value=/sap({REF_ID_2})/webcuif/uif_callback?crm_handler=CL_THTMLBX_SILVERLIGHT_ISLAND&wcf-request-ticket={WCF_REQUEST_TICKET}",ENDITEM,
         

 

Most probably your have displaced the variables manually (see Hint 2.), or simply the performed correlation does not work (Hints 5 and 6).

Hint 8: For the above (Hint 7) described scenario, you could probably see */logon_error.html call within statistical records, transaction STAD.

Hint 9: Always include logoff and browser closure steps into the script.

Hint 10: To identify if your script is executed successfully or not, do not rely on VUGen. Define functional exit criteria and check them on the back-end. For instance if you create 1Order documents, check if they are being created in the table CRMD_ORDERADM_H.

p7.png

 

P.S. If you have some interesting case, issue or error, feel free to add it here.

BR, Dima

 

SAP CRM WEB UI Accessibility

$
0
0

Disclaimer:

          This blog is intended to share the accessibility project experience.


Important:

          Term ‘Users’ in this blog refer to visually challenged users, who have up to 90% visual challenge.

 

Background: As part of my previous projects, I got an opportunity to work for accessibility requirements for visually impaired users. This was an unique project experience working on different set of requirements. I had to first understand the business requirements from a different angle( interpret disability of user) and provide appropriate solution. As part of requirement gathering process, Identify the business processes, SAP CRM WEB UI screens navigated by user. Solution should simplify the WEB UI screens with less cluttered information for smooth navigation and uninterrupted process execution. On one project I worked with IS Utilities customer service adviser user, accepting inbound calls, making outbound calls and successfully making sales. On another project I worked with Grantor Funding officer working in back office reviewing customer applications and approving funds.

Users navigated through SAP CRM WEB UI screens using keyboard short cuts and with help of screen reading software.

 

WEB UI Navigation:

  • Configure shortcuts for keyboard navigation
  • Making sure each UI element can be navigated by using ‘TAB’ key
  • Each UI element has appropriate text and can be read by the screen reading software
  • Making sure all the required information for the user is present on the same WEB UI screen, preventing forward and back navigation.

 

Screen reading software:

  • Every screen reading software has it own pros and cons, based on the application and OS they are used with
  • Internet Browser compatibility of screen reading software
  • There are some scripts written for JAWS software, which will be triggered as user starts using the software. Its a local deployment.

 

Custom Development/Changes:

  • Simplified UI screens, with only required information
  • Default the information wherever possible
  • Remove the hyper links

 

Challenges:

  • SAP CRM WEB UI Tables and table line navigation
  • Hyper links
  • Transaction launchers
  • Custom developed UI elements
  • UI Screen in display and edit mode
  • Attachments to SAP CRM Objects
  • Data loss pop ups
  • Screen reader software does not indicate the current position of the cursor
  • Forward/backward Screen navigation from hyperlinks
  • Un-necessary Messages (Error, Warning, Information)
  • Flickering of UI screen as soon as the screen reader software is activated

 

High Contrast Screens: High contract UI, typical combinations

  • White background and black text
  • Yellow background and black text
  • Pink background and black text
  • Blue background and black text

New high contract skins were developed

 

Fonts: Large fonts

 

Multi lingual: Other than English

 

Links for additional reading

SAP CRM BP Address Types: Choosing the correct address

$
0
0

Disclaimer: This blog is part of series


Background: As part of a project i got an opportunity to work on BP addresses. Address is very critical element while communicating with customers, across industry. SAP system should be configured to suit the business requirement while fully utilizing the capability provided by SAP. Address management is one of the efficiently designed features of SAP. I would like to share the behavior of address types based on configuration.

 

Business Requirement:  A customer can have multiple addresses based on context of business process and appropriate selection of address for correspondence is the key.

For Example to name a few:

Main Address - using which customer was registered or was acquired.

Correspondence address - To receive correspondences

Billing Address - To receive bills/invoices for services

Forwarding Address - To receive correspondence once customer has switched to new supplier

 

Standard SAP provides address type XXDEFAULT and you can configure custom address types under IMG path shown below in Figure 1 and Figure 2.

 

Figure. 1

IMG Define Address Type.jpg

Figure. 2

TB009.jpg

 

Marked Check box 'Several uses' for an address type enables business to enter multiple addresses. However, only one will be valid for correspondence at any point of time and end user will have the ability to switch between the addresses based on customer's request. Example shown below in Figure 3:

 

Figure. 3

Several Use flag.jpg

Whereas, the address type where several use flag is not marked, then there can be only one address at any point of time. If end user enters another address for the same address type latest becomes the standard and valid for use. Though the previous address will be still exists, but without an address type association. Example shown below Figure 4.

 

Figure. 4

Several Use flag not.jpg

Now, how to identify standard/default address. As shown below there will not be a dustbin icon with standard address type (XXDEFAULT). This is the standard SAP feature.

 

Figure. 5

Standard default address.jpg

If end user enters another address with XXDEFAULT address type, automatically previous address will be marked with an end date system date - 1 and new address will have a start date of system date and end date as 31.12.9999. This can be seen screen shot given above Figure 5 and below Figure 6.


Figure. 6

Standard Address SAP GUI.jpg

Business processes should always look for the address type, standard flag and end date to pick correct address.


How to replace the standard message

$
0
0

You work on the CRM WebUI, and a standard message is displayed after you perform an action, but the message text does not meet your requirement, and you want to replace the existing standard message with your own message.

 

CRM has the functionality that you can replace the existing message with your own messages that are created in your namespace. You can replace the existing message text with your own message text. The customizing path is:

SPRO -> Customer Relationship Management -> UI Framework -> UI Framework Definition -> Define Messages to Be Replaced


If this cann't fullfill your requirement, you may try BADI WCF_ALTER_UI_MESSAGES.

AET Table Enhancement

$
0
0

Application Enhancement Tool can be used for both Field and Table Enhancement. Recently We had a requirement in my project to enable AET for a Table .This blog would explain on how AET can be used for Table Enhancement.

 

Field Enhancement : AET Tool can be used to create,update and delete fields in the table that does not belong to standard Delivery.

Table Enhancement : AET Can be used to create,update and delete tables that does not belong to standard delivery , the same table can be linked with an existing table via Parent ID . This table can be made available in the CRM WEB UI as an Assignment Block or in Form View.

 

 

Requirement :

There is a Relationship Table which maintains the relationship between the entities .For example we have a Case and Person as two entities and the different relationships can be created between these two entities .For Example : Person can be related as Suspect to a case , or as an Victim.

 

The requirement was to enable AET for this relationship Table , so that customer can maintain there own fields in a new table and link with this relationship Table.

Customer should be able to create , update and delete entries in this new table from UI .

 

 

1) Enabling AET for a Table

 

  Call transaction AXTREG and create the Table Enhancement Place and also mention the required details like Application Group and the Parent ID .

Parent ID Data Element will be same as the Key field in the Parent Table.

 

 

Capture.PNG

 

Next step is to mention the Parent Business Object under which Extension BO will be created .

In the Transaction AXTREG , under Enhanced Business Objects select the Enhanced Business Object and the the part of Enhanced BO  under which Enhancement place will be included

 

Untitled.png

Specify the Table Enhancement Place which was created in first step and also Select New Extensions allowed .

 

 

2) Creation of Extension Tables From UI

 

Steps to make Configuration Active

 

First Enable the Configuration from Personalize settings from the Web UI

 

Untitled.png

 

Now go to the page from where Enhanced BO will be called ( For  which Table Enhancement Place is added  ) and select configuration from left Upper corner as shown below.

 

 

Untitled.png

Then Select the particular Block and Display the enhancements .

 

Capture.PNG

 

From here , you can create a table and this will generate all the Extension BO's with the structure of Table mentioned by the user.

 

Capture.PNG

 

Table Created is as show below

 

Capture.PNG

Once we Create Table from UI , this will also generate the View under the  UI Component which is mentioned   while creating.

View will have Context node referring the Extension BO Object .

 

Capture.PNG

 

 

3) Enhance the Genil Class to show the Extension Bo's in BOL Model Brower.

 

Next step is to Enhance the Genil Class to show the Extension Bo's which will be created under this root Object.

 

 

Below Code can be put in the Get_model Method of Genil class of Parent Object

TRY.

      CALL METHOD cl_axt_extensibility_access=>get_extension_tables

        EXPORTING

          iv_appl_group = 'ICM'

          iv_ext_tplace = 'ICM_RELATION'

        IMPORTING

          et_model_il   = lt_model_id.

    CATCH cx_axt_runtime.

  ENDTRY.

 

  LOOP AT lt_model_id ASSIGNING <fs_model_id>.

    MOVE-CORRESPONDING <fs_model_id> TO ls_relation_det.

    INSERT ls_relation_det INTO TABLE rt_relation_det.

  ENDLOOP.

 

This will add all the extension BO's to the Model as shown below.

 

 

Capture.PNG

 

4) Create new Genil Class for Handling CRUD Operation on the new Extension BO's

 

Create New Genil Class for the New relation which is created and Read , Modify and Save Methods to handle CRUD operation on the new table.

 

API's of Standard class CL_AXT_TABLES_API ( Create,Change,Delete and Save Methods ) can be used for CRUD operations.

 

Adjust the Genil Class of Parent Object in such a way that New Genil Class will be called for CRUD operation on the new Table.

 

 

5) Enhance the Existing UI with the View Created for Table

 

Creation of a Table would have generated the new view as mentioned in the step 2 . This view can be used in the Existing View for enabling CRUD operation from UI by a User.

 

 

This completes the End to End Implementation of AET Enhancement for Table.

 

Hope this Blog helps the people dealing with AET.

 

 

Thank You,

 

Jayashree

How WebUI passes table selected row information to ABAP backend

$
0
0

I have been working as a Fiori application developer in SAP for almost two years, which means now I use Chrome development tool in my daily work for trouble shooting instead of ABAP debugger when I was working using CRM WebUI.

 

Yesterday I was assigned with an incident about CRM Lead application in WebUI, and I am glad to figure out that Chrome development tool can also do me a great favor for my trouble shooting in WebUI issue. I share with my experience learned in this blog.

 

Issue description

 

The incident complains that when a given row in Products assignment block is selected and Delete button in toolbar is clicked, nothing occurs.

clipboard1.png

My issue analysis process

 

I located the event handler of this delete button in toolbar:

clipboard2.png

And I find out that get_marked in line 21 return an empty BOL entity collection.

clipboard3.png

I debugged into get_marked, this method will only return those BOL entities as marked whose SELECTED equals to true.

For Lead application, all the BOL entities which represent table entries in assignment block has SELECTED as false, as a result no BOL entity is returned - so nothing to be deleted.

3.jpeg

However I have checked Opportunity application, the deletion works. The attribute for BOL entity is set as abap_true as expected.

clipboard1.png

What is the reason of this different behavior?

 

Research how WebUI passes table selected row information to ABAP backend via Chrome development tool

 

In WebUI I selected first row in table and click delete button in toolbar, then I observe this selected information is passed to ABAP backend via field name as C34_W111_V113_V120_prodtable_selectedRows and value as 1.

clipboard2.png

And in ABAP backend, all these http form fields passed from frontend UI are received and stored in variable lt_fields in line 25.

clipboard2.png

I download the content of lt_fields as excel and highlight the field for selected row index:


clipboard3.png

Then in ABAP backend, it is expected to populate the string "C34_W111_V113_V120_prodtable_selectedRows" to get the index by field name. From the code below we get: "C34_W111_V113_V120_prodtable"

clipboard5.png

The left string fragment "selectedRows" comes from constant gc_selected_rows. Now the selected row index is get by field name in line 14.

clipboard6.png

The original issue is: although we have table id "prodtable",

clipboard7.png

however a wrong default id "Table" is passed in via iv_id and thus wrong field name is generated, so based on this wrong field name, no selected index could be queried:

clipboard8.png

The issue is already fixed via SAP note 2331513.

 

The naming convention of capital characters in lv_name:

 

  • C: component
  • W: window
  • V: view

 

You can also find such id in generated html source code via Chrome development tool in Element tab: first click the small icon highlighted below and then click the UI area you would like to inspect:

clipboard9.png


Then in Elements tab, the html source code of the selected UI area will be displayed for you:

clipboard10.png

Further reading

Replication of Price Agreement from CRM to ERP

$
0
0

Overview:

 

In this blog posting I would cover scenario of replicating price agreement from SAP CRM to ERP. Price Agreement is very vital of Sales Contract, which influence the further documents in ERP including Sales Order and Billing.

 

In this scenario we worked was one of difficult scenarios as condition types were created in ERP but Price Agreement (Condition Record) was created in CRM Sales Contract. In following sections I would write down necessary required steps.

 

 

Maintain Structure:

 

Append the structure CND_MAPT_ACS_REM_CUST with the Custom fields (Z) and the standard field which are not available in CRM field catalog. Here remember the field name and data element name should be same with ECC. Please check condition table, field names before appending.

 

Maintain Field Catalog

Maintain the added fields in field catalog, following is the path:

Capture.JPG

Maintain Custom Key Fields

 

Maintain all the Custom (Z field) field which are part of key combination of condition table, which is assigned to condition type. Following is the menu:

Capture1.JPG

Here maintaining CRM_ITEM_GUID to an external field (fictitious) is must as ECC does not understand GUID. For example:

Conversion DirectionLocal FieldExternal FieldConversion
B - LocalCRM_ITEM_GUIDZZTESTPOSNRB-Convesio Routine

 


Initial Download of Condition Type:

 

Through transaction R3AS and objects DNL_CUST_CND, DNL_CUST_CNDALL all relevant customizing and condition types were loaded in CRM

 

 

Impement BADI:

 

  1. Implement BADI "/SAPCND/ROLLNAME" and put e_excuted to 'X' for following methods a. FIELD_CHECK b. ATTRIBUTE_CONVERSION c. F4_HELP

         It is required to give provision for the condition type to create Price Agreement in SAP CRM

 

    2. Implement BADI "CND_MAP_CNV_FIELD" with filter CRM_ITEM_GUID. In this implementation (Conversion Method) Item GUID must be properly divided to Document and Item Number combination, because in ECC GUID does not exist.

 

       Like as :  CONCATENATE lg_vbeln lg_posnr INTO ev_target_value.

 

Maintain Condition Types to Allow Price Agreement replication (ECC):

 

Maintain the relevant condition types in customizing which are used in Price Agreements. This customizing is done to allow the price agreement to be replicated into relevant ECC condition tables. With this entries ECC understand that data is coming from CRM and not created in ECC. Following is the path:

Capture.JPG

 

Summary:

 

After all the steps are performed, create a price agreement with an Item of released status. Check the BDOC is green and there is no error. Check the relevant condition table in CRM for example CNCCRMPRCUS780 and correspoding ECC Table A780 for entries.

 

Also check Sales Contract Item in ECC that price agreement is displayed. If not, please check the check box "condition index" at condition type customizing.

Setting priority for incoming e-mails

$
0
0

Hi All,

 

One of the interesting requirement I recently had was to set the priority of incoming e-mails based on different conditions. Conditions were, if user has marked the email as 'High importance' or the email subject contains some words like 'Urgent', 'Last reminder' etc. As usual the first place for getting something for this requirement was SCN. Though I didn't get a complete solution, I got something from one of the threads.

 

First I checked whether it's possible to set the priority like this. Yes..It's possible manually via transaction code SWI1 and changing the priority. Now how to automate this.

 

For debugging an incoming email, we can set the debugging parameter in the following path,

SPRO->Customer Relationship Management->E-mail response management system->Define Repository or transaction CRMC_ERMS_REPOSITORY. For context ERMS, insert a property 'DEBUG' and value as 'X'. This is a SAP hard-coded break that stops the routing and waits for you in sm50 to debug. Now you can debug in SM50.

 

Following are the steps I found after some debugging and analysis.

 

1. Go to tcode SWO1 and create a sub object for ERMSSUPRT2.


 

2. Redefine the method RuleExecution in the Z-object.

 

 

3. Now this method is the place where you have to make the code changes.

In our case, we created a custom table where we can store the words which needs to be considered as high priority. This allows if in case tomorrow we need some extra words also to be considered.

 

Insert following code here,

 

*   Get specific words from customizing table     SELECT *       FROM ZPRIORITY_WORDS       INTO TABLE lt_prio_key.     IF sy-subrc = 0.
 *     Loop to check if subject contains any string from the table maintained values.       LOOP AT lt_prio_key INTO ls_prio_key.         TRANSLATE ls_prio_key-key_string TO UPPER CASE.         lv_sub_upper = sub .         TRANSLATE lv_sub_upper TO UPPER CASE.         IF lv_sub_upper CS ls_prio_key-key_string.           lv_wi_text_import = 1.           EXIT.         ENDIF.       ENDLOOP.   ENDIF.    

Now we got whether there are any words which is to be set to high. We need to check whether the email was sent with high priority also. Hence, add the following code.

 

      lt_factbase =  service_manager->factbase.
 *     Get priority email setting       CALL METHOD lt_factbase->get_by_xpath         EXPORTING           id_xpath  = '/parts/EMAIL/PRIORITY/text()'         RECEIVING           rd_result = lv_prio.

Considering the values found from above, we have to set the priority of email. Hence, use the FM "SAP_WAPI_CHANGE_WORKITEM_PRIO" for setting the priority.

 

IF lv_wi_text_import EQ 1 OR lv_prio EQ 1.
 *       Change priority         CALL FUNCTION 'SAP_WAPI_CHANGE_WORKITEM_PRIO'           EXPORTING             workitem_id = flowitemid             priority    = '4'             language    = sy-langu.       ENDIF.     ENDIF.

4. We are done with coding part now. The next is to set the z-bject type is released.

 

 

5. And the last step is making the z-object as the delegated type for ERMSSUPRT2. This is to be done in SWO6 transaction.

 

 

Now go to your inbox and see whether the email with 'High importance' has come with priority 'High'.

 

 

Please let me know if you have any queries.

 

Thanks,

Faisal

Configuration Steps in IDOC

$
0
0

IDOC or Intermediate Documents are commonly used in case of data migration between SAP systems or between SAP and legacy system or vice versa.This blog details the steps involved in configuring a new IDOC and also list's down the various transactions that are used while working with IDOCs.

IDOCs can be classified into two . Inbound IDOCs and Outbound IDOCs.

 

Inbound IDOC   : These are IDOCs which get the data into SAP system from external source i.e PI system  or any other external system.

Outbound IDOC: These are IDOCs which are sent out from SAP system to any other system. i.e PI system or any other external system.

 

Step 1 : We need to check the RFC connections to the target system , it can be PI system or any external system. If it is to a PI system then we need to check the connection under ABAP connections in SM59 transaction and for external system under HTTP Connections to External System.

 

Images.bmp.png

Image.png

 

Step 2: Create a port in transaction WE21 which shows the target system’s RFC destination.

 

Image.png

 

Step 3 : In transaction WE20, create a partner profile and mention the message tpe details .In case of Oubound IDOC’s , mention the message types under Outbound Parameters.In case of Inbound IDOC’s , mention the message types under Inbound Parameters. For outbound parameters ,maintain port and IDOC details, because port describes to which system the IDOC has to flow. Whereas in Inbound IDOC,mention the process code details which determines the inbound function module for processing the data.

 

Image.png

 

Step 4 : Message type SYNCH is the default message type for outbound parameters. Choose a particular message type and maintain the below settings. Under the receiver port mention the port created in transaction WE21. In Output mode, choose Transfer IDOC immediately. In IDOC type mention the IDOC associated with the Message Type.


Image.png

Image.png

 

Step 5: For Inbound IDOCs, mention the process code as APL1 and choose option Trigger Immediately under Processing by Function Module.

 

Image.png

 

Step 6 : In transaction BDFG, we can see which ALE function module we need to enhance for our requirement. In case, we are working with Business Partner we can choose the FM as CRMXIF_PARTNER_SAVE and the Business Object Type as ‘BUS1006’. In IDOCs , SAP by standard provides us to exchange the business partner master data details , BP relationships and BP Hierarchies.

 

Image.png

 

Step 7: In case we are working with Business Transactions we can choose the FM as CRMXIF_ORDER_SAVE and the Business Object Type as ‘BUS20001’.

 

Image.png

 

Step 8 : In our example let us work upon Business Partners. Select the FM name and the Business Object type and click enter. By default all standard messages types would be displayed out.Now to create a new message type , click on Create button as shown below. You will get a popu where in you can enter a Z name.

 

Image.png

 

Step 9 : Once the Z message type is created. Release it as shown.

 

Image.png

 

Step 10 : Select  the  Z message type and click on the Display button to view the details.

 

Image.png

 

Step 11 : With Z Message Type , Z FM’s for both Inbound and Outbound gets created.

Image.png

 

Step 12 : In transaction WE30 we can check the IDOC  created.

Image.png

Image.png

 

Step 13 : In transaction WE31 we can check the IDOC  segment .

 

Image.png

 

Step 14 : For Inbound IDOCs in transaction code WE42 , select the process code APL1 and click on display . Assign a Z Fm-ZAPPL_IDOC_INPUTI . Create a copy of the standard FM APPL_IDOC_INPUTI into ZAPPL_IDOC_INPUTI .

 

Image.png

Image.png

Image.png

 

Step 15 : Under Logical Message , mention the Z message type created.

 

im.png

im.png

 

Step 16 :In  transaction WE81 , we can see the message type details.

im.png

 

Step 17 : In  transaction WE82 , we can see the message type and basic type details.

 

im.png

 

Step 18 : For outbound IDOCs in transaction BD64 , create a distribution model. Goto change mode and click on 'Create Model View'. Enter a description and Technical name.

 

im.png

 

Step 19 : Add the message type under the Distribution Model and maintain the sender and receiver system details.

 

im.png

 

Step 20 : In transaction BD82, generate the partner profile for the newly created distribution model.

 

im.png

 

Step 21 : In  transaction SMOEAC , we create the sites and subscriptions.Site is the destination where the data needs to be sent.Subsricption is to identify what is the object to be exchanged. (In case of BP data it will be All Business Partner MESG).Subscriptions are assigned under Sites. Type would vary based on our need.


im.png

im.png

im.png

 

Step 22 : In transaction CRMXIF_C1 , we maintain the message type details against the Site name.

 

im.png

 

Step 23 : We can even restrict an Outbound IDOC flow based on any condition to a particular Site. A times there could be multiple sites in a system , we can control the flow of IDOC here as well.This can be achieved by maintaining an entry in table - SMW3FDCUST, we assign a copy of standard FM - SMW3_OUTBOUNDADP_CALLADAPTERS against BDoc Type BUPA_MAIN,  which is  used to do any further customizations. We can do the same for other IDOC types.In the Z FM ,input parameter HEADER we get the Site ID details , based on that we can control the changing parameter - RECEPIENTS.

 

Step 24 : Apart from the above steps we can use Transaction WE02/WE05 to display any IDOC and WE60 for IDOC Documentation.To reprocess any IDOC use transaction WE19 adn inoput teh IDOC number, a new number gets generated.

 

Step 25 : Any IDOC has 3 records types - Control, Data and Status.Control Records displays the direction of the IDOC, message type/basic type details.

Data record display the data under multiple segments. In Status Record we can check the IDOC status whether it is a success or failure.

 

Tables for these 3 record types are as below.

 

Control Record - EDIDC

Data Records    - EDIDD

Status Record   - EDIDS

Asynchronous Rendering of TAJAX Areas / Table Views

$
0
0

I have already briefly mentioned asynchronous rendering of the tables here:

Parallelization in Web UI - Part 2

Since then I have simplified a solution to a certain extent, but I forgot to make a post about it . A new solution does not require you to use createFastRowsCallbackfunction (which, in fact, should receive a kind of crazy input, that you have to create on your own).

Instead we will build a normal HTML-based response. It can be doe for ANY Tajax area, including the tables.

So, what is the difference?

And the changes are:

1.       When building a view, we start it from our own TAJAX area (<tajax:areaid="myTajaxArea" >).

2.       Moreover, we need to store its name in the controller class (controller->gr_ajax_area = page_context->element_at_top_of_stack( ).).

3.       As a callback function, we are using our own one. (functionUpdateMyTable(reqObj)).

 

<%@page language="abap" %>
 
<%@extension name="thtmlb" prefix="thtmlb" %>
 
<%@extension name="chtmlb" prefix="chtmlb" %>
 
<%@extension name="bsp" prefix="bsp" %>
 
<%@extension name="tajax" prefix="tajax" %>
  <script language=
"javascript" type="text/javascript">
  function UpdateMyTable(reqObj)
  {
  
varresponseText = reqObj.request.responseText;
  
varobj = JSON.parse(responseText);
  
varfnum = obj.TEXT.length;
  
for (vari= 0; i< fnum; i++) {
   
varelem = document.getElementById(obj.TEXT[i].NAME);
     if (elem){
      elem.innerHTML = obj.TEXT[i].VALUE;
     }
   }
  }
  </script>
  <tajax:area id=
"myTajaxArea" >
    </br>
    <b>Here the
area begins!</b>
    </br>
   
<%
   
" Save Top AJAX Area Reference
    controller
->gr_ajax_area = page_context->element_at_top_of_stack( ) .
   
   
"
Conversion CnodeSelectionMode to Tag
   
data: lv_cellerator_selectionmodetype string,
    lv_cellerator_editmode  type
string,
    lv_cellerator_selectioncolumn
type string.
    cl_thtmlb_util
=>translate_selection_mode(
   
exporting
    iv_selection_mode   
= SOMEDATA->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).
   
   
   
data: lv_table_beetype ref to cl_chtmlb_config_cellerator.
   
   
ifcontroller->gv_config_tableis initial
   
or 1 = 1.
   
   
" Create Table
   
call method cl_chtmlb_config_cellerator=>factory
   
exporting
   
id                    = controller->gc_table_id
    downloadToExcel      
= 'TRUE'
    editMode             
= 'NONE' "lv_cellerator_editmode
    onRowSelection       
= 'select'
    personalizable       
= 'TRUE'
    selectedRowIndex     
= somedata->selected_index
    selectedRowIndexTable
= somedata->selection_tab
    selectionColumn      
= lv_cellerator_selectioncolumn
    selectionMode        
= lv_cellerator_selectionmode
   
table                 = somedata->table
    _table               
= '//SOMEDATA/Table'
    usage                
= 'EDITLIST'
    visibleFirstRow      
= somedata->visible_first_row_index
    visibleRowCount      
= '6'
    width                
= '100%'
    xml                  
= controller->configuration_descr->get_config_data( )
    receiving
    element      
= lv_table_bee.
   
   
"
Store the link
    controller
->gv_config_table ?= lv_table_bee.
   
   
"   Post AJAX call to update content  %>

      <script type="text/javascript">
          thtmlbAJAXCall.callBackend(
"<%= controller->create_ajax_url( ) %>",UpdateMyTable);
        </script>
   
<%
   
"
    lv_table_bee
->emptytabletext =

                 cl_wd_utilities=>get_otr_text_by_alias('CRM_BSP_UI_FRAME_RECOBJ/LOADING' ).
 
   
endif.
   
   
" Get the link
    lv_table_bee ?= controller
->gv_config_table.
   
   
" Render html element
    lv_table_bee
->if_bsp_bee~render(_m_page_context).
   
%>
    </br>
    <b>Here the
area ends!</b>
    </br>
  </tajax:area>

 

4.       In IF_CRM_WEB_CALLBACK~HANDLE_REQUEST method we are using a new method CREATE_TABLE_VIEW_HTML_NEW, which returns an inner HTML of our TAJAX Area.

method create_table_view_html_new.

 

     " Variables

     data: lv_attribute_path type string,

           lv_model_name     type string.

 

     " Strucures

     data: ls_area_content type crms_tajax_area_content.

 

     " References

     data: lo_page            type ref to cl_bsp_ctrl_adapter,

           lo_view_manager    type ref to cl_bsp_wd_view_manager,

           lo_view_controller type ref to cl_bsp_wd_view_controller,

           lo_model           type ref to if_bsp_model_binding,

           lo_context_node_tv type ref to cl_bsp_wd_context_node_tv.

 

     " Field symbols

     field-symbols: <fs_page>  type bsprtip.

 

     " Create page instance

     read table cl_bsp_context=>c_page_instances

     with key page_name = cl_bsp_wd_appl_controller=>appl_controller_name

     assigning <fs_page>.

 

     " Rendering

     if sy-subrc is initial and <fs_page>-instance is bound.

       lo_page            ?= <fs_page>-instance.

       lo_view_manager    ?= lo_page->m_adaptee.

       lo_view_controller ?= ir_controller.

       lo_view_manager->render( iv_root_view = lo_view_controller ).

     endif.

 

     " Get model

     call method cl_bsp_model=>if_bsp_model_util~split_binding_expression

       exporting

         binding_expression = iv_binding_string

       importing

         attribute_path     = lv_attribute_path

         model_name         = lv_model_name.

     try.

         lo_model ?= ir_controller->get_model( lv_model_name ).

         lo_context_node_tv ?= lo_model.

       catch: cx_root.

         exit.

     endtry.

 

     "Build table

     lo_context_node_tv->build_table( ).

 

     " Get AJAX Area Content By ID

     call method lo_view_controller->retrieve_ajax_area_content

       exporting

         iv_page_id         = ir_controller->component_id

         iv_area_id         = iv_ajax_area_id

       importing

         es_content_info    = ls_area_content

         er_used_controller = lo_view_controller.

 

     ev_html = ls_area_content-area_content.

 

 

   endmethod.



 

5.       We send back this inner HTML code as a part of JSON response. (Here we use a table, as probably several areas or individual fields can be processed in one request).


               
call method create_table_view_html_new
                 
exporting
                    ir_server        
= ir_server
                    ir_controller    
= ir_controller
                    iv_binding_string
= '//SOMEDATA/TABLE'
                    iv_ajax_area_id  
= lr_controller->gr_ajax_area->id
                 
importing
                    ev_html          
= lv_html.
 
               
iflv_htmlis not initial.
                  ls_field_list
-name  =lr_controller->gr_ajax_area->id.
                  ls_field_list
-value= lv_html.
                 
appendls_field_listto lt_field_list.
               
endif.
 
               
"ABAP to JSON
                lr_writer
= cl_sxml_string_writer=>create(type = if_sxml=>co_xt_json ).
               
calltransformation id source text = lt_field_list[] result xml lr_writer.
                lv_json
= lr_writer->get_output( ).
 
 
               
" Set Response
                ir_server
->response->set_data( lv_json).
                ir_server
->response->set_header_field(name  = 'content-type'
                                                      
value = 'text/xml' ).

 

And the picture to prove that this is working.

 

output_nFIVXG.gif

 

Run simple! No crazy concatenated HTML strings!

 

P.S. Sorry, standard SAP's formatting is lost again. Do not know how to keep it.

 

BR, Dima


Viewing all 195 articles
Browse latest View live


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