Friday, 24 May 2013

41.BASICS OF BOL PROGRAMMING




SEND AN EMAIL TO CRMWEBCLIENT@GMAIL.COM IF YOU WANT BELOW CODE.

**********************************************
*BOL PROGRAMMING
*SAP CRM WEBCLIENT
*GIVES INTRODUCTION TO * basic activities like search, create, update in the bol
*programming in order to give introduction to the main classes and methods of business object layer.
**********************************************





*used data
DATA: lr_core 
TYPE REF TO cl_crm_bol_core.

*in order to use any service of BOL, we need to start the MODEL (component set) using
* CORE class.

lr_core = cl_crm_bol_core=>get_instance( ).


*once we have the instance, then load the component set.
*here we will be using ONEORDER component set.

*when we are working on web ui, this will be handled by framework. here we are doing it in the report programming so we need to handle it

TRY.
    
CALL METHOD lr_core->load_component_set
      
EXPORTING
        iv_component_set_name = 
'ONEORDER'.
  
CATCH cx_crm_genil_general_error .
ENDTRY.


*component is loaded, so we can use the BOL services. Let us search for a particular
*contract. for that we need to get an instance of dquery service class.

DATA: lr_query 
TYPE REF TO cl_crm_bol_dquery_service,
      lr_result 
TYPE REF TO cl_crm_bol_bo_col.



*****SEARCH OPERATION***********************

"get the instance of dynamic search object,which will be used to search service contracts.
lr_query ?= cl_crm_bol_dquery_service=>get_instance( iv_query_name = 
'BTQSrvCon' ).

"Every dynamic search object will have its own result type object. here BTQSrvcon has BTQRSrvcon as result object.
"so in the result list all objects are type of BTQRSrvcon.

"we got the instance, so we need to set the selection criteria.

"fetching all contracts whose description is 'testing'.
"you can call this method multiple times to add different selection parameters.
lr_query->add_selection_param( iv_attr_name = 
'DESCRIPTION'
                                                iv_sign      = 
'I'
                                                iv_option    = 
'EQ'
                                                iv_low       = 
'testing' ).


"get the list contracts that match the selection criteria in the form of collection.
"collection is nothing but a container that holds records. we can compare it like a internal table
"that holds records.

lr_result ?= lr_query->get_query_result( ).


"Let us print the contract id and description of all records in teh collection.


"cl_crm_bol_entity is used to represent the record in the BUSINESS OBJECT LAYER.
DATA: lr_entity 
TYPE REF TO cl_crm_bol_entity,
      lv_objectid 
TYPE string,
      lv_descr 
TYPE char40.


"read the first record in the collection.

lr_entity ?= lr_result->if_bol_bo_col~get_first( ).


"following while loop mechanism is used to visit each record in the collection.

WHILE lr_entity IS BOUND.


  
"read the contract id.

  
"get property as string will return attribute values in the form of string. so we declared lv_objectid as string.
  lr_entity->get_property_as_string( 
EXPORTING iv_attr_name = 'OBJECT_ID'
 RECEIVING rv_result = lv_objectid  ).

  
"get property as value will return the value as it as.so we declared DESCRIPTION with data element.
  lr_entity->get_property_as_value( 
EXPORTING iv_attr_name = 'DESCRIPTION' IMPORTING ev_result = lv_descr ).


  
WRITE : lv_objectid, lv_descr.

  
WRITE /:.

  
"read the next record in the collection.

  lr_entity ?= lr_result->if_bol_bo_col~get_next( ).

ENDWHILE.









**************UPDATING OPERATION***************************

"Let us change the description of one service contract.

"get the curren entity from the result list.

"Every collection holds one pointer which always points to the current record we visited.We generally call it is a focus
"in the BOL language. so get current returns the object which has focus. so what ever the last object we visited in the
"above loop, will be fetched in the below statement.

lr_entity ?= lr_result->if_bol_bo_col~get_current( ).


IF lr_entity IS BOUND.  "we never work on object references which are initial. this is check is very important in BOL.


  
"can we use the set property as string directly on this lr_entity?.

  
"No, it is dynamic query result object, generally all properties of these type objects are read only.

  
"DESCRIPTION is property of BTAdminH object. we need to get it using the relations. We need to take help from MODEl to see
  
"what are the relations that we need to go through to reach the target object. Transaction GENIL_MODEL_BROWSER

  
"in our scenario, we have BTQRSrvcon as a soruce in the lr_entity variable. This object has a relation 'Association BTADVSSrvCon Child Cardinality 1'
  
"which will give the object BTOrder.

  
"again BTOrder is having a relation 'Composition BTOrderHeader Child Cardinality 1', which will fetch the target object BTAdminH. this object has
  
"an attribute 'DESCRIPTION'.

  
"while looking at the relations, look at the cardinality of relation. if cardinality is 0...1, then relation always fetch one single entity. if is
  
"0...N, then relation will fetch multiple entities.

  
" use the GET RELATED ENTITY when cardinality is 0...1.
  
" use the GET_RELATED_ENTITIES when cardinality is 0...N.

  DATA: lr_order 
TYPE REF TO cl_crm_bol_entity.

  
"read the BTORDER first.
  
" the parameter iv_mode will take another value 'b', which stands for bypassing the buffer.
  
"which means, framework will ignore the values that exist in the bol buffer and read the target
  
"entity values from the database by triggering required APIs. it can decrease the performance. so use only in necessary
  
"situations like when you are reading that particular entity first time..
  TRY.
      
CALL METHOD lr_entity->get_related_entity
        
EXPORTING
          iv_relation_name = 
'BTADVSSrvCon'
          iv_mode          = cl_crm_bol_entity=>bypassing_buffer
        RECEIVING
          rv_result        = lr_order.
    
CATCH cx_crm_genil_model_error .
  ENDTRY.


  
"we got the order, then read the BTAdminH.

  DATA:  lr_header 
TYPE REF TO cl_crm_bol_entity.

  
IF lr_order IS BOUND.

    TRY.
        
CALL METHOD lr_order->get_related_entity
          
EXPORTING
            iv_relation_name = 
'BTOrderHeader'
            iv_mode          = cl_crm_bol_entity=>bypassing_buffer
          RECEIVING
            rv_result        = lr_header.
      
CATCH cx_crm_genil_model_error .
    ENDTRY.


  ENDIF.

  
"we got the BTadminH. change its DESCRIPTION property.
  
IF lr_header IS BOUND.

    
"before changing any property of BOL object, we need to lock it.
    
"this will be accomplished by lock method.



    
IF  lr_header->lock( ) = abap_true.  "if we get the lock, then only continue


      
"we use set_* methods to change the properties of BOL objects.
      lr_header->set_property_as_string( 
EXPORTING iv_attr_name = 'DESCRIPTION'  
      iv_value = 'changed'  ).

    ENDIF.


    
"once change is done, we need to tell about this change to the framework.
    
"we will use core class for this.

    lr_core->modify( ).


    
"then get the transaction from the entity and check whether this save is possible or not.

    DATA: lr_transaction 
TYPE REF TO if_bol_transaction_context.


    lr_transaction ?= lr_header->get_transaction( ).

    
IF lr_transaction IS BOUND.


      
IF lr_transaction->check_save_possible( ) EQ abap_true.


        
"if we can save , then save the transaction and commit the changes.

        
IF lr_transaction->save( ) EQ abap_true.

          lr_transaction->commit( ).

        ENDIF.


        
"we changed the object description. read it again to get the new value.
        lr_header->get_property_as_value( 
EXPORTING iv_attr_name = 'DESCRIPTION'  
                 IMPORTING ev_result = lv_descr ).

      ENDIF.


    ENDIF.


  ENDIF.


ENDIF.




***************CREATE operation*****************************



*Let us create one service contract and fill some of its properties.

*"first step , we need to create the root entity.
DATA:  lr_factory       
TYPE REF TO cl_crm_bol_entity_factory,
       lr_order_new     
TYPE REF TO cl_crm_bol_entity,
       ls_params        
TYPE crmt_name_value_pair,
       lt_params        
TYPE crmt_name_value_pair_tab.


ls_params-name  = 
'PROCESS_TYPE'.
ls_params-value = 
'ZSZ'.
APPEND ls_params TO lt_params.

"create root entity will be handled by the factory class. we use CORE class
"to get the instance of required factory class by sending the root object to its
"method get entity factory. then we use CREATE method of factory class by sending
"the necessary parameters.

"here we are creating contracts, so we are sending the process type as input.

lr_factory   = lr_core->get_entity_factory( 
'BTOrder' ).    "#EC NOTEXT
lr_order_new = lr_factory->create( lt_params ).

IF lr_order_new IS BOUND.


  
"BTOrder is having only GUID, we need to get BTAdminH entity to fill up some of its properties.

  TRY.
      
CALL METHOD lr_order_new->get_related_entity
        
EXPORTING
          iv_relation_name = 
'BTOrderHeader'
          iv_mode          = cl_crm_bol_entity=>bypassing_buffer
        RECEIVING
          rv_result        = lr_header.
    
CATCH cx_crm_genil_model_error .
  ENDTRY.


  
"fill the properties using the setter method
  
IF lr_header IS BOUND.



    
"we use set_* methods to change the properties of BOL objects.
    lr_header->set_property_as_string( 
EXPORTING iv_attr_name = 'DESCRIPTION'  
    iv_value = 'New Contract'  ).



    lr_core->modify( ).


    lr_transaction ?= lr_header->get_transaction( ).

    
IF lr_transaction IS BOUND.


      
IF lr_transaction->check_save_possible( ) EQ abap_true.


        
"if we can save , then save the transaction and commit the changes.

        
IF lr_transaction->save( ) EQ abap_true.

          lr_transaction->commit( ).

        ENDIF.


        
"we changed the object description. read it again to get the new value.
        lr_header->get_property_as_value( 
EXPORTING iv_attr_name = 'DESCRIPTION'  
                  IMPORTING ev_result = lv_descr ).

      ENDIF.


    ENDIF.

  ENDIF.


ENDIF.


17 comments:

  1. Hi Expert,

    Please give more details about Root object,Access object and Dependent object .Why it is categorised??Also tell me in detail about how entities are related with each other ?And how to find out the relationship between the entities ??

    Thanks

    ReplyDelete
  2. really appreciate your efforts...itz of great help ...cheers

    ReplyDelete
  3. Very Very Useful...

    thanks a ton

    ReplyDelete
  4. It is really very helpful.. Thanks a lot for your effort.

    ReplyDelete
  5. In your 'create' scenario you should be using the create_related_entity method rather than get_related_entity

    ReplyDelete
  6. Hi,

    What is the difference between CL_CRM_BOL_CORE->START_UP() and CL_CRM_BOL_CORE->LOAD_COMPONENT_SET?

    - Prakash

    ReplyDelete
  7. Hi Prakash,

    START_UP will start the component set in ur BOL CORE. This is useful in reports and stuff where u dont have the BOL CORE running because a report is not linked to a UI component (ie the component u edit in BSP_WD_CMPWB).

    LOAD_COMPONENT_SET will be used when running from UI component, after this additional components external to this component set can also be loaded using LOAD_COMPONENT.

    Regards,
    Shreyas

    ReplyDelete
  8. This is really amazing for new starter in WEBUI.

    ReplyDelete
  9. Nice..
    Thanks for straight explanation.

    ReplyDelete
  10. Hi all,

    I'am new to BOL programming..
    In query search operation to generate loop.
    Here is my BOL code.

    ****************************************************
    WHILE lr_entity IS BOUND.

    lr_entity->get_property_as_string(
    EXPORTING
    iv_attr_name = 'OBJECT_ID' " Component Name
    * iv_use_iso_format = ABAP_FALSE
    RECEIVING
    rv_result = lv_object_id ).

    lr_entity->get_property_as_value(
    EXPORTING
    iv_attr_name = 'PROCESS_TYPE' " Component Name
    IMPORTING
    ev_result = lv_descr ).

    WRITE : / lv_object_id,
    20 lv_descr.

    lr_entity ?= lr_result->if_bol_bo_col~get_next( ).

    ENDWHILE.
    *******************************************************

    Here I'm getting so many records. I don't need that all records. I need 10 records. What code should i add.

    Thanks,
    Siva R.

    ReplyDelete
  11. in the create operation should it not be create_related_entity as we are trying to create new entity. i doubt get_related entity would give any entity as we don't have any related entity for newly created root entity.

    ReplyDelete