martedì 12 marzo 2013

How to create a link to a rapid application into navigation bar

Follow the below tree in SPRO and select "Define Navigation Bar Profile":



In first folder "Define Logical Links" you should already have links to your own rapid application (created by the standard wizard for rapid applications).




Now you can create a new direct link group by choosing folder "Define Direct Link Groups" and than create e new entry as shown in selected record on the right.



Next you have to assign required logical link to your own direct link group by choosing folder "Assign Links To Direct Link Group" (with required direct link group selected). Add entries and put the position as shown below.



Now go back to spro and follow below tree than select "Define Business Role"




Search and select your business role and go to folder "Adjust Direct Link Groups"



Search and select you direct link group and go to folder "Adjust Direct Links"



Now you can choose which links has to be visible by check the related check-box.



Go to your Web UI and choose the business role used in the steps above, you should have new links on the navigation bar:



mercoledì 25 luglio 2012

Create a Custom BOL from ZTable for BP

  1. Extend object Model for Business Partner

ref. to this link and consider the example implemented on the system


Follow the following step in SPRO and select "Extend Object Model for Business Partner":

Use ZALLINEA_SISTEMI as external object name and ZCL_ALLINEA_SISTEMI as implementation class. 
Insert the object definition for this new ZALLINEA_SISTEMI object using structure ZALLINEA_SIS_STRUCT and the structure key is ZALL_SIS_KEY:


In model definition insert a new entry ZALL_SIS_REL with cadinality 1 : 0..n (similar to ZCOD_SOR_REL):


The structure ZALLINEA_SIS_STRUCT must be created with the following fields:

Componente
Cl. Tipizzazione
Tipo componente
Tipo dati
Lunghezza
CRM_OBJECT
TYPE
ZCRM_OBJECT
CHAR
10
GUID
TYPE
CRMT_OBJECT_GUID
RAW
16
CRM_ITEM
TYPE
ZCRM_ITEM
CHAR
8
SYS_CODE
TYPE
ZED_SYS_CODE
CHAR
3
TYPE
TYPE
CHAR2
CHAR
2
OUTCOME
TYPE
ZOUTCOME
CHAR
2
ERR_CODE
TYPE
ZCODICE_ERRORE
CHAR
4
ERR_DESC
TYPE
ZDESCR_ERRORE
CHAR
255
ACTION
TYPE
CHAR01
CHAR
1
MESSAGE
TYPE
CRMT_BSP_MKTSC_MESSAGE
CHAR
255
UPD_TIMESTAMP
TYPE
COMT_CHANGED_AT_USR
DEC
15

The structure ZALL_SIS_KEY must be created with the following fields:

Componente
Cl. Tipizzazione
Tipo componente
Tipo dati
Lunghezza
CRM_OBJECT
TYPE
ZCRM_OBJECT
CHAR
10
GUID
TYPE
CRMT_OBJECT_GUID
RAW
16
CRM_ITEM
TYPE
ZCRM_ITEM
CHAR
8
SYS_CODE
TYPE
ZED_SYS_CODE
CHAR
3

In this case we must use two custom tables (ZCA_PTB_SYS_SYNC and ZCA_PTB_ERR_COD) to retrieve records: those tables are already in the system, hence you don’t need to create them. Logic to retrieve records from those two tables will be detailed in next chapter.

Now you can create the custom class as described in page 8 of pdf document (linked at the beginning of this how to). Class name will be ZCL_ALLINEA_SISTEMI: it's important to set the superclass with CL_BUIL_ABSTR.

2 Logic to retrieve records

Redefine method READ and add code as below: 
  DATA: lv_obj   TYPE REF TO if_genil_container_object.
  DATA: lv_obj_new   TYPE REF TO if_genil_container_object.
  DATA: lv_parent   TYPE REF TO if_genil_container_object.
  DATA: lwa_key TYPE  ZALL_SIS_KEY .
  DATA: lv_bp_guid TYPE crmt_genil_object_guid,
        lt_ptb_sys TYPE TABLE OF zca_ptb_sys_sync,
        ls_ptb_sys TYPE zca_ptb_sys_sync,
        ls_ptb_err TYPE zca_ptb_err_cod.

  DATA lw_sistemi TYPE LINE OF t_bol.
  DATA lt_obj1 TYPE t_bol.
  DATA lwa_global_bol_data TYPE LINE OF t_bol.
  DATA lwa_bol_data TYPE ZALLINEA_SIS_STRUCT .
  DATA lt_bol_data TYPE STANDARD TABLE OF ZALLINEA_SIS_STRUCT.


*  Assign importing data to object.
  TRY.
      lv_obj ?= iv_ref.
    CATCH: cx_sy_assign_cast_error.
*     else exit: should never happen
      EXIT.
  ENDTRY.

*Check if attributes were requested. If not, then exit.
  CHECK lv_obj->check_attr_requested( ) = abap_true.

*Get key of current object
  lv_obj->get_key( IMPORTING es_key = lwa_key ).

*Fetch key for current BOL entity
  IF lwa_key IS INITIAL"if no current object is instatiated
    lv_parent = lv_obj->get_parent( ).
    CALL METHOD lv_parent->get_key
      IMPORTING
        es_key = lv_bp_guid.

    IF lv_bp_guid IS NOT INITIAL.

      SELECT * FROM zca_ptb_sys_sync
            INTO TABLE lt_ptb_sys
            WHERE guid = lv_bp_guid .

      LOOP AT lt_ptb_sys INTO ls_ptb_sys.

        MOVE: lv_bp_guid            TO lw_sistemi-guid,
              ls_ptb_sys-crm_item      TO lw_sistemi-crm_item,
              ls_ptb_sys-sys_code      TO lw_sistemi-SYS_CODE,
              ls_ptb_sys-outcome       TO lw_sistemi-SYS_CODE,
              ls_ptb_sys-message       TO lw_sistemi-message,
              ls_ptb_sys-upd_timestamp TO lw_sistemi-upd_timestamp.

        SELECT SINGLE * FROM zca_ptb_err_cod
                        INTO ls_ptb_err
                       WHERE err_code = ls_ptb_sys-err_code.

        IF sy-subrc = 0.
          MOVE: ls_ptb_err-err_code TO lw_sistemi-err_code.
        ENDIF.
        MOVE-CORRESPONDING lw_sistemi TO lwa_key.
        MOVE-CORRESPONDING lw_sistemi TO lwa_global_bol_data.
        MOVE-CORRESPONDING lw_sistemi TO lwa_bol_data.

        TRY.
            lv_obj->set_key( lwa_key ).
            lv_obj->set_attributes( lwa_bol_data ).
            me->set_attr_properties( lv_obj ).
          CATCH cx_crm_genil_model_error.               "#EC NO_HANDLER
          CATCH cx_crm_cic_duplicate_entry.             "#EC NO_HANDLER
        ENDTRY.
      endloop.
    ENDIF.

  ENDIF.

Redefine method MODIFY:
  DATA: lv_obj   TYPE REF TO if_genil_container_object.
  DATA: lv_obj_new   TYPE REF TO if_genil_container_object.
  DATA: lv_parent   TYPE REF TO if_genil_container_object.
  DATA: lwa_key TYPE  zaddon_bp_key.
  DATA: lv_bp_guid TYPE crmt_genil_object_guid.
  DATA lwa_obj1 TYPE LINE OF t_bol.
  DATA lwa_global_bol_data TYPE LINE OF t_bol.
  DATA lwa_bol_data TYPE zaddon_bp_struct.

*  Assign importing data to object.
  TRY.
      lv_obj ?= iv_ref.
    CATCH: cx_sy_assign_cast_error.
*     else exit: should never happen
      EXIT.
  ENDTRY.

*Get key of current object
  lv_obj->get_key( IMPORTING es_key = lwa_key ).

*Fetch key for current BOL entity
  IF lwa_key IS INITIAL"if no current object is instatiated
    lv_parent = lv_obj->get_parent( ).
    CALL METHOD lv_parent->get_key
      IMPORTING
        es_key = lv_bp_guid.

*take the business partner number from guid
    SELECT SINGLE partner FROM but000 INTO lwa_key-partner WHERE partner_guid = lv_bp_guid.

    CHECK lwa_key-partner IS NOT INITIAL.

  ENDIF.
*end of READ Method

  DATA: lv_delta TYPE crmt_delta.
  DATA lv_msg TYPE REF TO if_genil_message_container.
  DATA lwa_bol_data_chg TYPE LINE OF t_bol.
  DATA : lt_return TYPE bapiret2_t.
  DATA : ls_return TYPE bapiret2.
DATA: lr_obj_prop TYPE REF TO if_genil_obj_attr_properties,
        lt_changed_fields TYPE crmt_attr_name_tab,
        lwa_changed_fields TYPE LINE OF crmt_attr_name_tab.
  FIELD-SYMBOLS <new_data> TYPE any.
  FIELD-SYMBOLS <old_data> TYPE any.


  lv_delta = lv_obj->get_delta_flag( ).
  IF NOT lv_delta IS INITIAL.
* Delete messages for entity
    lv_msg ?= lv_obj->get_message_container( ).
    lv_msg->delete_messages( iv_object_name = me->object_name ).
  ENDIF.

***Creating new Data
  IF lv_delta EQ if_genil_cont_simple_object=>delta_created.
* Set the key structure
   CLEAR: lwa_global_bol_data, gt_global_bol_data.
  MOVE-CORRESPONDING  lwa_key to lwa_global_bol_data.

    TRY.
        CALL METHOD lv_obj->set_key
          EXPORTING
            is_object_key = lwa_key.
      CATCH cx_crm_genil_duplicate_key.                 "#EC NO_HANDLER
    ENDTRY.
* Store data into global internal table
    lv_obj->get_attributes( IMPORTING es_attributes = lwa_bol_data ).
    lv_obj->get_attributes( IMPORTING es_attributes = lwa_bol_data_chg ).
    lr_obj_prop = lv_obj->get_attr_props_obj( ).
    CALL METHOD lr_obj_prop->get_name_tab_4_property
      EXPORTING
        iv_property = if_genil_obj_attr_properties=>modified
      IMPORTING
        et_names    = lt_changed_fields.

    LOOP AT lt_changed_fields INTO lwa_changed_fields.
        ASSIGN COMPONENT lwa_changed_fields OF STRUCTURE lwa_bol_data_chg TO <new_data>.
        ASSIGN COMPONENT lwa_changed_fields OF STRUCTURE lwa_global_bol_data TO <old_data>.
        <old_data> = <new_data>.
      ENDLOOP.

    APPEND lwa_global_bol_data TO gt_global_bol_data.
  ENDIF.

***Modifing existing data
  IF lv_delta EQ if_genil_cont_simple_object=>delta_changed.
    lv_obj->get_attributes( IMPORTING es_attributes = lwa_bol_data_chg ).
    lr_obj_prop = lv_obj->get_attr_props_obj( ).
    CALL METHOD lr_obj_prop->get_name_tab_4_property
      EXPORTING
        iv_property = if_genil_obj_attr_properties=>modified
      IMPORTING
        et_names    = lt_changed_fields.
    CLEAR lwa_global_bol_data.
    READ TABLE gt_global_bol_data INTO lwa_global_bol_data WITH KEY partner = lwa_key-partner.
    IF sy-subrc EQ 0.
      LOOP AT lt_changed_fields INTO lwa_changed_fields.
        ASSIGN COMPONENT lwa_changed_fields OF STRUCTURE lwa_bol_data_chg TO <new_data>.
        ASSIGN COMPONENT lwa_changed_fields OF STRUCTURE lwa_global_bol_data TO <old_data>.
        <old_data> = <new_data>.
      ENDLOOP.
      MODIFY gt_global_bol_data FROM lwa_global_bol_data INDEX 1.
    ELSE.
      ls_return-type = 'E'.
      ls_return-id   = '00'.
      ls_return-number = '001'.
      ls_return-message_v1 = 'Impossibile salvare dati AddonBP'.
      ls_return-message_v2 = 'Impossibile determinare numero BP'.
    ENDIF.
  ENDIF.


  DATA: lwa_obj_inst TYPE crmt_genil_obj_instance.
  me->register_save_handler( lv_obj ).
  lwa_obj_inst-object_name = me->object_name.
  lwa_obj_inst-object_id = cl_crm_genil_container_tools=>build_object_id( lwa_key ).
  APPEND lwa_obj_inst TO ct_changed_objects.

  CALL METHOD cl_crm_buil_services=>bol_add_messages
    EXPORTING
      iv_cont_obj      = lv_obj
      iv_object_name   = me->object_name
      it_bapi_messages = lt_return. 

3 New assignment block creation

Component BP_HEAD is already enhanced under enhancement set ZCRMO_ENSET

The wizard will start asking the view name: type ZAllineaSistemi. Use model node and refer to the bol entities as in image below:

Now add all attributes from ZALL_SISTEMI in “Add Model Attributes” step. In step “Select View Type” select table view and set checkboxes as in image below:



Now add the created view in the right Viewset. Expand viewset BP_HEAD/BPHEADOverview and right click in viewarea OverviewPage selecting “Aggiungere view”



From the popup raised up select in field “View” the view revious steps:



Create a binding between ZHEADER  context node and custom controller):


Display hidden blocks in component PRD01OV

Component PRD01OV has several blocks that can be added to the main view (MaterialOV). Although I moved many blocks in displayable part, those blocks are not visible in the configuration:



This is not due to the fact that blocks are hidden, but this issue is related to the relationship types activated in product category. To solve this issue go to transaction COMM_HIERARCHY, select the appropriate hierarchy and category then select tab "Relationship type" and add the relationship you need:

When done you will see in WebUI that all blocks in displayable part will be shown:

Disable + and - buttons in advanced search

This change requires the access key for standard class CL_THTMLB_ADVANCEDSEARCH. The solution suggested below will be applied for all search pages but can be adjusted depending on customer requirements.

Open method IF_BSP_ELEMENT~DO_AT_BEGINNING and comment code from row 738 until row 887.

mercoledì 18 luglio 2012

How to configure WorkProtect Mode popup

When you navigate from a BSP to a portal component i.e. WebDynpro Java without saving, you could have data loss. In order to manage centrally all these situations you may configure the WorkProtect Mode popup.

This is an example of popup

Configuration steps on NetWeaver 7.0x
  • Access to Portal using a user with admin role.

  • Navigate to Service Configuration: System Administration -> System Configuration -> Service Configuration


  • Select application "com.sap.portal.epcf.loader" and open the properties for service "epcfloader"
    Here you can customize following settings:
    • workprotect.mode.default
    • workprotect.mode.personalize
    • workprotect.popup.layout
    • workprotect.window.features


  • Save and restart the service so the changes take effect.

    Right-click on the application node "com.sap.portal.epcf.loader" and then choose "Administrate" in order to open the application console. Restart/Stop links are shown.




Possible values ​​for the properties

"workprotect.mode.default" property
[1] for "Protect unsaved data (open page in a new window)"
[2] for "Discard unsaved data (open page in the same window)"
[3] for "Choose action in popup on unsaved data"

"workprotect.mode.personalize" property
[on] means users may change their values in the portal personalization ("Personalize -> WorkProtect Mode ").
[off] means users cannot changed individually the personalization.

"workprotect.popup.layout" property
[default] for options shown as link
[buttons] for options shown as button

"workprotect.window.features" property
Default value is empty but you can change it to any value accepted by the JavaScript function window.open i.e. toolbar=no,location=no