Using the Standard Status Management in Custom Developments
A few weeks back I was debugging some issue with the status management of an order in SAP CRM. That was the first time that I noticed, that the general status management functionality is part of the core functionality of SAP Netweaver. As I like to use SAP standard whenever possible I was wondering whether it is possible to use the standard status management in custom development.
Status management in custom developments is a requirement I encountered regularly in the past. Most of the time I implemented a basic status management myself on the basis of some custom domain with numerical status values. This basic status management notable lagged most of the features the standard status management provides, like e.g.
- the possibility to have different system and user status
- the ability to have multiple system status active
- or customizable and extendible status values.
Searching SDN I could only find little information regarding the standard status management. While there is a wiki page in the CRM area of the SDN wiki (Status Management – CRM – SCN Wiki) and a few threads on the topic (e.g. Integrating a Z Business Object with SAP Standard general status mangement?
with some very helpful comment by Rüdiger Plantiko) I couldn’t find any complete example or tutorial on the topic. Therefore, I decided to create one myself. I this blog I’ll provide a complete example consisting of creating a custom status object, customizing the status schema and finally using it in a simple example program.
Creating a custom status object
For the purpose of this blog I create a simple database table ZCD_D_STATUS_OBJ as an example business object. This table only contains the three field MANDT, OBJECT_ID and OBJECT_TEXT.
The first thing that is needed to create a new status object for this table is a new object type including the necessary control parameters in table TBO00. The control parameters basically specify in which database table the custom object is stored and which are the key fields identifying an entry. For this example I create an new object type “Z1” with the value “ZCD_D_STATUS_OBJ” for the fields “Table” and “Ref.Struc.” and “OBJECT_ID” for the field “Key Field”:
Next a new object type needs to be created using transaction BS12. For this example I created the object type ZT1. No further customizing is needed here for this example.
With this basic setup in place, it is now possible to customize the status schema for our new status object. Customizing the status schema is done via transaction BS12. I created a test status schema ZCDT0001 for this example. The status schema consists only of the following three status:
- CREA – Created
- PROC – Processes
- FINI – Finished.
CREA is set as the initial status value. The lowest and highest status numbers are set up in such a way that it is always only possible to go to a higher status, e.g. from PROC to FINI.
Now all the customizing is in place to use the custom status object.
Test program for the custom status object
The function modules necessary to use the standard status management are locate in the function group BSVA in the package BSV. The following simple test program shows how to use these function modules to create and update the custom status object. The test program consists of the following parts:
- First in lines 18-31 I simply use the BP number range to create an unique key for the entry in the custom table.
- After that in lines 33-68 the custom status object for the object type ZT1 and the status schema ZCDT0001 is created.
- In lines 70-98 the initial status values are read and printed to the output.
- Finally in lines 100-163 some external and internal status values are set and then read and printed to the output again.
REPORT zcd_test_status_object.
TYPES: BEGIN OF object_key,
object_id TYPE char10,
END OF object_key.
DATA: status_test_obj TYPE zcd_d_status_obj,
object_key TYPE object_key,
status_obj_nr TYPE j_objnr,
object_type TYPE j_obtyp,
status_schema TYPE j_stsma,
status_number TYPE j_stonr,
status_table TYPE ttjstat,
s TYPE string.
FIELD-SYMBOLS: <status> TYPE jstat.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Initialize the object key with an unique value
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
CALL FUNCTION 'NUMBER_GET_NEXT'
EXPORTING
nr_range_nr = '01'
object = 'BU_PARTNER'
IMPORTING
number = status_test_obj-object_id.
status_test_obj-object_text = 'Test Status Obj ' && status_test_obj-object_id.
INSERT zcd_d_status_obj FROM status_test_obj.
object_key-object_id = status_test_obj-object_id.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Creation of the status object
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
CALL FUNCTION 'OBJECT_NUMBER_GET_GENERIC'
EXPORTING
i_obart = 'Z1'
i_objectkey = object_key
IMPORTING
e_objnr = status_obj_nr
EXCEPTIONS
number_already_exists = 1
obart_invalid = 2
objectkey_missing = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
CALL FUNCTION 'STATUS_OBJECT_CREATE'
EXPORTING
objnr = status_obj_nr
obtyp = 'ZT1'
stsma = 'ZCDT0001'
EXCEPTIONS
obtyp_invalid = 1
status_object_already_exists = 2
stsma_invalid = 3
stsma_obtyp_invalid = 4
OTHERS = 5.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
COMMIT WORK AND WAIT.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Read the initial status values and print it
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
CALL FUNCTION 'STATUS_READ'
EXPORTING
objnr = status_obj_nr
IMPORTING
obtyp = object_type
stsma = status_schema
stonr = status_number
TABLES
status = status_table
EXCEPTIONS
object_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
WRITE / 'Initial status values'.
s = |Object Type: | && object_type && | - Status Schema: | && status_schema && | - Status Number: | && status_number.
WRITE / s.
WRITE / 'Status Table:'.
LOOP AT status_table ASSIGNING <status>.
s = |Status: | && <status>-stat && | - Inactive: | && <status>-inact.
WRITE / s.
ENDLOOP.
ULINE.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Set some external and internal status values and print it
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
CALL FUNCTION 'STATUS_CHANGE_EXTERN'
EXPORTING
objnr = status_obj_nr
user_status = 'E0003'
EXCEPTIONS
object_not_found = 1
status_inconsistent = 2
status_not_allowed = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
CLEAR status_table.
APPEND INITIAL LINE TO status_table ASSIGNING <status>.
<status>-stat = 'I0098'.
CALL FUNCTION 'STATUS_CHANGE_INTERN'
EXPORTING
objnr = status_obj_nr
TABLES
status = status_table
EXCEPTIONS
object_not_found = 1
status_inconsistent = 2
status_not_allowed = 3
OTHERS = 4.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
CLEAR status_table.
CALL FUNCTION 'STATUS_READ'
EXPORTING
objnr = status_obj_nr " Objektnummer
IMPORTING
obtyp = object_type " Objekttyp
stsma = status_schema " Statusschema
stonr = status_number " Statusordnungsnummer
TABLES
status = status_table " Tabelle der Einzelstatus zum Objekt
EXCEPTIONS
object_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
WRITE / 'New Status values'.
s = |Object Type: | && object_type && | - Status Schema: | && status_schema && | - Status Number: | && status_number.
WRITE / s.
WRITE / 'Status Table:'.
LOOP AT status_table ASSIGNING <status>.
s = |Status: | && <status>-stat && | - Inactive: | && <status>-inact.
WRITE / s.
ENDLOOP.
ULINE.
Running this program produces the following result:
After the status object has initially been created the user status E0001 is automatically set for the status object. This is the status that was defined in the status schema ZCDT0001. After setting the internal status I0098 and the user status E0003, the status E0001 is set to inactive.
I hope this blog provides an useful introduction for anyone trying to use the standard status management in a custom development.
Christian
Good to know this. Thank you for sharing this idea Christian.
However, the problems I have faced while trying to adapt this feature for custom built processes/screens is that there is customizing involved with tables having Delivery Class 'S'.
Hi Vimal,
yes I guess some of these tables have deliver class 'S'. Frankly,I didn't check this. For me it comes down to balance the advantages and disadvantages of creating entries in these tables to the ones of developing a custom status management. In this case, at least IMHO, the advantages of using the standard outweigh the disadvantages of adding entries to S-tables.
Christian
Thanks for this very useful blog.
Using transaction BSVW I have linked every status in my status profile with a business object type event. In this case, the name that you give to the key (ZR ) has to be the prefix for the object type (ZR1, ZR2).
Great blog, thanks Christian. One small correction, customising the status schema is done in transaction BS02 rather than BS12.
I'm hoping to use the standard status management in a bespoke development in the near future so this has been very helpful.
All the best, Jon
Christian - This documents has been so helpful. Thanks so much!
Thank you Christian, It is very useful blog.
Hi,
thank you for this summary. Is my understanding right that I need for each new business object an entry in TBO00?
Regards Wolfgang