How to detect status changes?

Sometimes we want to trigger an activity (e.g. PPF action) only if a (or if no) status change is performed. Sometimes it can be complicated to detect status changes since error messages are raising system status changes or since status changes can be cancelled.

Dependent on the requirements, we can try following solutions:

  1. Real status changes: Use function module CRM_STATUS_READ_OW and check the fields ACTIVE and ACTIVE_OLD of parameter ET_STATUS_WRK. Alternatively compare the result against CRM_STATUS_READ_DB.
  2. Real status changes or Status cancel: Use function module CRM_EVENT_PASS_INFO_EXE_OW with execution time ‚080‘ and check whether parameter contains ET_EVENT_CALLS contains object „STATUS“. If you are only interested in status changes on header level, please ensure that ORDER_GUID and OBJ_GUID are equal.
  3. Real status changes(?): Use method GET_PREV_STATUS_OF_CHNG_DOC of class CL_HF_HELPER.
  4. Real PPF action triggered status change: Define a PPF action check previous user status in Schedule condition and new user status in start condition. Ensure that the sort number of this action is higher than the sort number of the status change action.

These solutions are partially also working for partner changes, appointment changes, text changes etc.

Links:

https://scn.sap.com/thread/1270181

Use Case 1:

In ChaRM there is always a consistency check performed after status change. It might be useful to perform consistency checks on every transaction save to validate transaction consistency. However, this check should not be performed if the framework is perfoming it (because of performance reasons and because the check result might be different). Therefore we need to detect status change activities which includes real status changes as well as cancelled status changes. This can be done by solution (2).

Use Case 2:

In SAP Solution Manager IT Service Management status changes are not triggered by PPF actions, therefore solution (4) is not working. The same issue we have for ChaRM if status changes are triggered by CRM_SOCM_SERVICE_REPORT. If we want to trigger an action (e.g. e-mail notification) on status change only, we have to follow solution (1). Please note, that this solution is already available in SAP standard: Note 1007346 – Scheduling of actions only after resetting a status.

*"----------------------------------------------------------------------
*"Methoden Signatur:
*"  Importing
*"     VALUE(FLT_VAL) TYPE PPFDFLTCO2
*"    IO_CONTEXT TYPE REF CL_CONTEXT_PPF
*"    IP_PROTOCOL TYPE BALLOGHNDL
*"    IP_TTYPE TYPE PPFDTT
*"    II_CONTAINER TYPE REF IF_SWJ_PPF_CONTAINER
*"  Exporting
*"    EP_RC TYPE SY-SUBRC
*"----------------------------------------------------------------------

METHOD if_ex_eval_startcond_ppf~evaluate_start_condition.

  DATA:
    lr_crm_order        TYPE REF TO cl_doc_crm_order,
    lv_header_guid      TYPE crmt_object_guid,
    lv_exec_mode        TYPE sppfdxmode,
    lv_on_database_flag TYPE abap_bool,
    lt_events           TYPE crmt_event_call_tab.

* default false
  ep_rc = 4.

*Get Execution Mode
  lv_exec_mode = cl_manager_ppf=>get_instance( )->execution_mode.

*Get Header GUID
  TRY.
      lr_crm_order ?= io_context->appl.
    CATCH cx_root.
      RETURN.
  ENDTRY.

  lv_header_guid = lr_crm_order->get_crm_obj_guid( ).

*We need a Business Transaction.
  CHECK lv_header_guid IS NOT INITIAL.

*First Save?
  CALL FUNCTION 'CRM_ORDERADM_H_ON_DATABASE_OW'
    EXPORTING
      iv_orderadm_h_guid  = lv_header_guid
    IMPORTING
      ev_on_database_flag = lv_on_database_flag.

*We only want to allow our action in dialog mode or if we change the Transaction.
  CHECK lv_exec_mode IS INITIAL OR lv_on_database_flag = abap_false.

**Get Status
*  CALL FUNCTION 'CRM_STATUS_READ_OW'
*    EXPORTING
*      iv_guid        = lv_header_guid
*      iv_only_active = abap_false
*    IMPORTING
*      et_status_wrk  = lt_status_wrk1[]
*    EXCEPTIONS
*      not_found      = 1
*      OTHERS         = 2.
*
*  CHECK sy-subrc = 0.

*Find out wich objects are really changed.
  CALL FUNCTION 'CRM_EVENT_PASS_INFO_EXE_OW'
    EXPORTING
      iv_exetime          = '080'
      iv_order_guid       = lv_header_guid
      iv_obj_kind         = 'A'
    IMPORTING
      et_event_calls      = lt_events
*     et_segments_changed = lt_segments
    EXCEPTIONS
      OTHERS              = 99.

*We are only interested in changed objects on header level.
*Therefore we have to ignore/delete every change on item level.
  DELETE lt_events WHERE obj_guid <> lv_header_guid.

*Are there any status changes (including error free flag, including status change cancel)
  READ TABLE lt_events
    TRANSPORTING NO FIELDS
    WITH KEY obj_name = 'STATUS'.

*Fine. We are in normal save mode without any status change activity.
  CHECK sy-subrc <> 0 OR lv_on_database_flag = abap_false.

*Are there any header changes (CHANGED_AT)
  READ TABLE lt_events
    TRANSPORTING NO FIELDS
    WITH KEY obj_name = 'ORDERADM_H'.

*Fine somthing has really changed.
  CHECK sy-subrc = 0.

*OK. Action is allowed to be executed.
  ep_rc = 0.

ENDMETHOD.