Wednesday, January 26, 2011

Adding attributes to a BOR Object

As mentioned in the previous post, actions can be scheduled according to schedule conditions and started according to start conditions.

Schedule conditions are checked during the saving of the document.
Start conditions are checked when transaction SPPFP is run.

This way, you can influence both whether an action is to be scheduled, and when it is to be executed.

The schedule and start conditions check whether conditions are met based on the context of the document. The context is both the document itself as well as attributes of the document such as the activity partner or the sold-to party or the product assigned to the document.

In some cases you might want to check on conditions that are not available in the standard system such as a marketing attribute of the sold-to party or an attribute of the assigned product.
In these cases, you might consider extending the BOR object with custom attributes.

Your new attribute will be occupied with a value by implementing ABAP code specific for this attribute.

Note that if you extend an object with new attributes, these attributes will be determined every time the object is used, so also outside of the action triggering mechanism.

If for instance you extend the BUS2000126, the coding behind the attribute will be run every time an object is occupied with a certain instance. The system does this all the time, so decent coding is exceptionally important here. You don’t want to lose performance because you have added a custom attribute.

The best way to add attributes is to create a subtype of the object you would like to enhance, and add the attribute here. This way, the standard stays the standard. Make sure that when defining the action definition, you enter your custom object as main object, or you will not be able to use you custom attribute.

Let’s say you want to use an attribute of the activity partner which is not available in the standard BOR object, such as a marketing attribute you have maintained.
This would be the way to do it:

Create a subtype
In transaction SWO1, find the object you would like to extend, in our case the BUS1006005 (business partner CRM). In the menu bar, click the ‘create new subtype’ button. Give the object a name (like ZUS1006005) Enter the details.






Add the attribute to the object
Open the newly created Z-object. Note that all attributes and methods are pink. This means they are inherited from their parent-object.
If you want to create a new attribute, click on the attributes node and click the ‘new’ button.
Enter the attributes properties in the details screen (like data type etc) and continue.

Add the coding to occupy the attribute
Now click on the new attribute, and navigate to the coding by clicking on ‘Program’.
I apologize for the old-school editor, there is unfortunately no way around it.
Check some of the standard attributes to see how SAP usually collects the coding.
In our case we want to read the values of a certain marketing attributes, so I enter the following code:

GET_PROPERTY changing <attribute_value> container.   

DATA: lt_bp_list TYPE TABLE OF crmt_mktbp_guid_range,
  ls_bp_list TYPE crmt_mktbp_guid_range,
  lt_ausp TYPE TABLE OF ausp,
  ls_ausp TYPE ausp,
  lv_partner_guid TYPE bu_partner_guid,
  lt_return TYPE TABLE OF bapiret2,
  lt_kssk TYPE TABLE OF kssk_v0,
  let_bp_list TYPE TABLE OF crmt_mktbp_inob_guid_str,
  lv_atinn TYPE ausp-atinn.


  CALL FUNCTION 'BUPA_NUMBERS_GET'
    EXPORTING
      iv_partner = object-key-businesspartner
    IMPORTING
      ev_partner_guid = lv_partner_guid
    TABLES
      et_return = lt_return.


  IF lt_return[] IS INITIAL.
    ls_bp_list-sign = 'I'.
    ls_bp_list-option = 'EQ'.
    ls_bp_list-low = lv_partner_guid.
    APPEND ls_bp_list TO lt_bp_list.
    CALL FUNCTION 'CRM_MKTBP_READ_KSSK_AUSP'
      TABLES
         it_bp_list = lt_bp_list
         et_ausp = lt_ausp
         et_kssk = lt_kssk
         et_bp_list = let_bp_list
       EXCEPTIONS
         others = 4.


     IF sy-subrc EQ 0.
      CALL FUNCTION 'CONVERSION_EXIT_ATINN_INPUT'
        EXPORTING
          input = '<name of the marketing attribute>'
        IMPORTING
          output = lv_atinn
      .


      READ TABLE lt_ausp INTO ls_ausp WITH KEY atinn = lv_atinn.
      IF sy-subrc EQ 0.
        object- = ls_ausp-atflv.
      ELSE.
        object-<attribute_value>= '0'.
      ENDIF.
    ELSE.
      object-<attribute_value>= '0'.
    ENDIF.
    swc_set_element CONTAINER '' object-<attribute_value>.
  ENDIF.
END_PROPERTY.

Generate the object
When you are confident you have done your work properly, you can generate and release the new object by clicking on the generate button and selecting release object from the menu bar.

Check the attribute is properly occupied.
SWO1 allows you to test an object by occupying the object with an instance. You will now immediately be able to see the outcome of your coding. This also allows you to debug your coding.

Create the delegation relationship between the standard and the new object in SWO6.
when you want to use your own object (like ZUS1006005), you should overrule the standard using SWO6. This way, the system looks at the Z-object instead of the standard BUS. In SWO6, create a new entry for the standard object. In the field 'Delegation type' enter the name of your new BUS object.
Enter the custom object as the main object in the action definition
When you are done coding your new attribute, you can now add it to the action definition, allowing you to use the attribute in the schedule and start condition. In our case though, we should also create a subobject for the BUS200110 (Activity CRM), where we add attribute ZACTIVITY_PARTNER as a related object of the type ZUS1006005 and copy the coding from attribute ACTIVITYPARTNER.

Add the attribute as a condition attribute
In the schedule and start conditions you should now be able to select the new attribute, and use it to determine whether an action should be scheduled and whether it should be executed under certain circumstances.

Wednesday, January 19, 2011

Actions in Transactions

Actions in SAP CRM are a way to add functionality to objects. Most used are actions in transactions. You would for instance use actions to send a quotation to the customer from the quotation document in SAP CRM. You can also use actions to for instance create a follow-on document. For instance, if the criteria are met, you might want to create a planned phonecall as a follow-on to an opportunity. This enables you to implement structured processes in the CRM system.

Another example of good use of actions is for instance triggering an approval workflow if the discount on an order is beyond a fixed threshold.

Another example would be an action to change the status of the current transaction. This would for instance be interesting if certain transactions should be closed automatically. An action for changing the status of the transaction is not delivered in the standard system, but can be easily incorporated with a little programming.

Implementing actions in SAP CRM consists of three steps.
• Defining the action
• Implementing schedule and start conditions for the action
• Assigning the action profile to the document type.

Defining the action
Defining the action means that you customize what type of action we are dealing with. So, what does the action do, what are the parameters it expects, what type of BOR object it is for, can it be triggered manually by the user, or just automatically by the system etc.

Implementing conditions for the action
After creating the action definition, you have to add scheduling conditions to the action. This is done in a separate step in customizing. Even if the action is only to be triggered manually, you should still enter schedule conditions to the action.

Schedule conditions are only evaluated when saving the document. This means that when saving the document, the system looks at the current situation, and decides whether an action is to be scheduled or not. Note that if the system decides not to schedule an action, it will not re-evaluate until the document is saved again.

Start conditions can be used to postpone scheduled conditions. You might want to schedule an action to be triggered a week after saving the document (or even a year if it concerns for instance a trigger to the sales manager to start contract discussions one year after the previous sale).
Start conditions usually contain a comparison of a date in the document with the current date.

Maintaining schedule and start conditions is a very precise exercise. You have to think of many reasons why an action should or should not be triggered, for instance:
-Status of the document
-Current date
-Attributes of the business partner (i.e. country, ID-numbers, classification, availability of an emailaddress etc)

Setting the schedule and start conditions can become quite complex, depending on the needs of your process.

Assigning the action profile to the document type
When you have maintained the action profile, you can assign it to the transaction type (or item type, depending on your requirements). This is done in the transaction customizing.

Now depending on the schedule and start conditions as well as on the specified processing time, the action will either automatically be triggered based on the conditions or can be manually triggered by the user.

Wednesday, January 12, 2011

Debugging the CRM Webclient


There are several ways to start debugging the CRM webclient.

1. Setting a breakpoint in the coding (i.e. in a BADI or in the BSP Workbench)
2. Conditional Breakpoints

1. Setting breakpoints in the coding.
If you know what code you want to debug, of course you can easily set a breakpoint in the coding, and when calling a screen in the webclient (or clicking a button or whatever), the debugger will automatically pop up. Note that only external breakpoints will be considered from the webclient.






If you do not know exactly where a problem is occurring, you can also try running a SQL trace using transaction ST05. In the trace, doubleclick on the line you are interested in in the column containing the operation (like OPEN, PREPARE or FETCH). This will open the ABAP statement where the database call was made. You can now set a breakpoint here. Running again will pop up the debugger.

2. Conditional breakpoints.
The use of conditional breakpoints can be activated using transaction SAAB. In SAAB, enter checkpoint group CRMUIF_CONDITIONAL_BREAKPOINTS, and click the activate button.
In the personal activation box, tick the ‘BREAK' radiobutton under ‘Asserts’ and save.














Setting conditional breakpoints can be done in the webclient using <alt>-F2.
This will open the following window:

Useful conditional breakpoints are for instance:

UI Framework – Common Application Features -> Navigation via Navigation Bar or Cross Component.
This will break on every screen change.

UI Framework -> Create Text Message
This will break when a message is raised.

UI Framework -> 4) View Controller - Handle Event (*)
This will break when an event is raised.

UI Framework -> 9) View Controller – Do Prepare Output
This will break on the do_prepare_output (the generation of a screen).

Generic Interaction Layer -> GenIL Component – Get Query Result
This will break before a GenIL query is called.

Wednesday, January 5, 2011

Extending the Business Object Repository

When calling transactions using the ITS, you might run into the limitations of the Business Object Repository. The available objects and methods of the Business Object Repository can be found in transaction SWO1.

Often used objects to call transactions or reports using the ITS are TSTC and REPORT.

If you want to use TSTC, you will have to create a copy (like ZTSTC) of the standard TSTC

The execute method of the ZTSTC should be the same as the standard execute from TSTC, except that the checkbox 'synchronous' should be checked.

An often heard requirement is to forward parameters like the businesspartnernumber to the transaction. This unfortunately is not possible with the standard TSTC object. To work around this limitation, you can add a method to the ZTSTC called for instance ZEXECUTE_WITH_PARAM.
When defining the method, you should add 4 import parameters:
  • Param1 type structure CPIDLIST
  • Param2 type structure CPIDLIST
  • Param3 type structure CPIDLIST
  • Skipsc type BUTOOO-BP_EEW_DUMMY (or any other CHAR1 field).

The ABAP code in the method should be a copy of the TSTC-EXECUTE, but with some extra ABAP coding between the AUTHORITY_CHECK_TCODE and the CALL TRANSACTION OBJECT-KEY-CODE.

BEGIN_METHOD ZEXECUTE_WITH_PARAM CHANGING CONTAINER.

CALL FUNCTION 'AUTHORITY_CHECK_TCODE'
   EXPORTING
      tcode = OBJECT-KEY-CODE
   EXCEPTIONS
      ok = 0
      not_ok = 1
      others = 2.

IF sy-subrc NE 0.
    MESSAGE s059(eu) WITH OBJECT-KEY-CODE.

ELSE.

DATA:
  lv_param1 TYPE CPIDLIST,
  lv_param2 TYPE CPIDLIST,
  lv_param3 TYPE CPIDLIST,
  lv_skipscreen TYPE char1.

   swc_get_element container 'param1' lv_param1.
   swc_get_element container 'param2' lv_param2.
   swc_get_element container 'param3' lv_param3.
   swc_get_element container 'skipsc' lv_skipscreen.

   IF lv_param1 IS NOT INITIAL.
      SET PARAMETER ID: lv_param1-pid FIELD lv_param1-value.
   ENDIF.
   IF lv_param2 IS NOT INITIAL.
      SET PARAMETER ID: lv_param2-pid FIELD lv_param2-value.
   ENDIF.
   IF lv_param3 IS NOT INITIAL.
      SET PARAMETER ID: lv_param3-pid FIELD lv_param3-value.
   ENDIF.
   IF lv_skipscreen IS INITIAL.
      CALL TRANSACTION OBJECT-KEY-CODE.
   ELSE.
      CALL TRANSACTION OBJECT-KEY-CODE and skip first screen.
   ENDIF.
ENDIF.
END_METHOD.

In the coding, the parameters are read, and forwarded to the parameter-id’s. Because the Parameters are defined as name-value-pairs, this is fully flexible.

As an example, if you would want to call transaction BP in ERP using the ZEXECUTE_WITH_PARAM, you would go ahead as follows:

1. Define the method as described above.

2. Check the ParameterID of the field you want to add the parameter to.

3. Create a transaction launch definition in SAP CRM using the transaction launcher wizard (CRMC_UI_ACTIONWZ).