Triggering a Workflow for a custom Change Document Object linked to a custom Business Object
Objective
Businesses often maintain critical data in a bespoke table. This data is then rendered to users via a standard transaction/(s). The entries in the table are maintained from a single access point; using a bespoke transaction code that accesses the table maintenance transaction – SM30 or a dialog program. When the data changes, the updated value is displayed when the standard transaction is next executed. We will use the SAP Plant Maintenance module to demonstrate this.
Create the following objects
Table, Data Elements and Domains
Create table ZPRPS in SE11.
Include the following fields in it with the appropriate Data Elements and Domains –
These fields will be available to the user in the following standard transactions –
IW21 – Create PM Notification – General,
IW22 – Change PM Notification, and
IW23 – Display PM Notification.
Create the Table Maintenance Generator (menu – Utilities >> Table Maintenance Generator).
Name the Function group as ZPRPS, give it an appropriate package, Maintenance type – one step, Overview screen – 100, Recording routine – no, or user, recording routine (ignore the Authorization Group which has been set to ZMMT; this has been done to restrict user access). Click the Create icon (not shown here).
Change Document Object for the Table
In transaction SCDO create a Change Document Object – ZPRPS_CD for the table.
Save it, and Back out of this screen.
Place the cursor on ZPRPS_CD and click Generate update pgm.
Accept the following options, click Generate.
The next screen displays the objects that have been created.
We can call Function Module ZPRPS_CD_WRITE_DOCUMENT to log changes for new records, updates to exiting records, and records that are deleted from ZPRPS. We also need to foolproof the table maintenance to prevent users deleting records that are currently referenced in one or more Notification/(s).
Go to Table Maintenance Generator for table ZPRPS, (menu – Environment >> Modification >> Events).
Click through the pop-up screen.
Create 3 custom Form routines for keys 01, 02 and 03 and give them an appropriate name.
Z_BEFORE_SAVE retrieves the records currently in the database, Z_AFTER_SAVE writes the change records for inserts, updates and deletes, and Z_BEFORE_DEL prevents a record from being deleted if it is referenced in a Notification.
Click on the Editor button, this will take us to the include LZPRPSF01. This include is part of the Function Group ZPRPS which was created when we generated the table maintenance for table ZPRPS.
Before we code the routines we will need to declare a global variable in the TOP include LZPRPSTOP.
DATA: gt_zprps TYPE STANDARD TABLE OF zprps.
Now enter the code provided below for the routines –
*&———————————————————————*
*& Form z_before_save
*&———————————————————————*
* text
*———————————————————————-*
FORM z_before_save.
* Select all the current entries from ZPRPS
SELECT *
FROM zprps
INTO TABLE gt_zprps.
* Set the SY-SUBRC to 0 – the first time when you populate entries in the
* table, SY-SUBRC will be set to 4 and you will not be able to Save it
sy-subrc = 0.
ENDFORM. “Z_BEFORE_SAVE
*&———————————————————————*
*& Form z_after_save
*&———————————————————————*
* text
*———————————————————————-*
FORM z_after_save.
DATA: lt_cdtxt TYPE STANDARD TABLE OF cdtxt,
ls_cdtxt TYPE cdtxt,
lv_objectid TYPE cdobjectv,
ls_zprps_o TYPE zprps,
ls_zprps_n TYPE zprps,
lv_objkey TYPE swo_typeid,
lt_swcont TYPE STANDARD TABLE OF swcont,
ls_qmel TYPE qmel,
lv_exists_flg TYPE c.
* Insert and Update
LOOP AT extract.
* Check that this record exists in the database
CLEAR: ls_zprps_o.
READ TABLE gt_zprps
INTO ls_zprps_o
WITH KEY zzposid = extract+3(24).
IF sy-subrc = 0.
* Check that the current record differs from the original – comparison is
* based on Project Name and Project Date
CHECK: ls_zprps_o-zzpost1 <> extract+27(40) OR
ls_zprps_o-zzpstrt <> extract+80(8).
CLEAR: lv_objectid,
ls_cdtxt,
lt_cdtxt,
ls_zprps_n.
* Create the data to be written to the change logs
lv_objectid = extract+3(24).
ls_zprps_n-mandt = extract+0(3).
ls_zprps_n-zzposid = extract+3(24).
ls_zprps_n-zzpost1 = extract+27(40).
ls_zprps_n-zzprart = extract+67(13).
ls_zprps_n-zzpstrt = extract+80(8).
* Call the FM to write the changes to CDHDR & CDPOS for the updated record
CALL FUNCTION ‘ZPRPS_CD_WRITE_DOCUMENT’
EXPORTING
objectid = lv_objectid
tcode = sy-tcode
utime = sy-timlo
udate = sy-datlo
username = sy-uname
object_change_indicator = ‘U’
upd_icdtxt_zprps_cd = ‘U’
n_zprps = ls_zprps_n
o_zprps = ls_zprps_o
upd_zprps = ‘U’
TABLES
icdtxt_zprps_cd = lt_cdtxt.
* This raises the Event CHANGED which triggers the Workflow
COMMIT WORK AND WAIT.
ELSE.
* It’s a new record
CHECK: extract+3(24) IS NOT INITIAL.
CLEAR: lv_objectid,
ls_cdtxt,
lt_cdtxt,
ls_zprps_n.
* Create the data to be written to the change logs
lv_objectid = extract+3(24).
ls_zprps_n-mandt = extract+0(3).
ls_zprps_n-zzposid = extract+3(24).
ls_zprps_n-zzpost1 = extract+27(40).
ls_zprps_n-zzprart = extract+67(13).
ls_zprps_n-zzpstrt = extract+80(8).
* Call the FM to write the changes to CDHDR & CDPOS for the new record
CALL FUNCTION ‘ZPRPS_CD_WRITE_DOCUMENT’
EXPORTING
objectid = lv_objectid
tcode = sy-tcode
utime = sy-timlo
udate = sy-datlo
username = sy-uname
object_change_indicator = ‘I’
upd_icdtxt_zprps_cd = ‘I’
n_zprps = ls_zprps_n
o_zprps = ls_zprps_o
upd_zprps = ‘I’
TABLES
icdtxt_zprps_cd = lt_cdtxt.
* If there is an Event and a Workflow associated with Insert it will be
* triggered
COMMIT WORK AND WAIT.
ENDIF.
ENDLOOP.
* Delete
LOOP AT gt_zprps
INTO ls_zprps_o.
CLEAR: lv_exists_flg.
LOOP AT extract.
* If the record is not found in GT_ZPRPS then it was deleted
CHECK: extract+3(24) = ls_zprps_o-zzposid.
lv_exists_flg = ‘X’.
EXIT.
ENDLOOP.
CHECK: lv_exists_flg IS INITIAL.
CLEAR: lv_objectid,
ls_cdtxt,
lt_cdtxt,
ls_zprps_n.
lv_objectid = ls_zprps_o-zzposid.
* Call the FM to write the changes to CDHDR & CDPOS for the deleted record
CALL FUNCTION ‘ZPRPS_CD_WRITE_DOCUMENT’
EXPORTING
objectid = lv_objectid
tcode = sy-tcode
utime = sy-timlo
udate = sy-datlo
username = sy-uname
object_change_indicator = ‘D’
upd_icdtxt_zprps_cd = ‘D’
n_zprps = ls_zprps_n
o_zprps = ls_zprps_o
upd_zprps = ‘D’
TABLES
icdtxt_zprps_cd = lt_cdtxt.
* If there is an Event and a Workflow associated with Delete it will be
* triggered
COMMIT WORK AND WAIT.
CLEAR: ls_zprps_o.
ENDLOOP.
sy-subrc = 0.
ENDFORM. “z_after_save
*&———————————————————————*
*& Form Z_BEFORE_DEL
*&———————————————————————*
* text
*———————————————————————-*
FORM z_before_del.
DATA: lt_cdtxt TYPE STANDARD TABLE OF cdtxt,
ls_cdtxt TYPE cdtxt,
lv_objectid TYPE cdobjectv,
ls_zprps_o TYPE zprps,
ls_zprps_n TYPE zprps,
lv_objkey TYPE swo_typeid,
lt_swcont TYPE STANDARD TABLE OF swcont,
ls_qmel TYPE qmel,
lv_exists_flg TYPE c.
LOOP AT extract.
* Is this record being deleted?
CHECK: extract+89(1) = ‘M’.
* Is it being referenced in a Notification?
CLEAR: ls_qmel.
SELECT *
UP TO 1 ROWS
FROM qmel
INTO ls_qmel
WHERE zzposid = extract+3(24).
ENDSELECT.
CHECK: sy-subrc = 0.
* Produce an Error
MESSAGE e000(zs_cross_appl) WITH
‘Cannot delete Project – ‘
extract+3(24)
‘ its referenced in Notification – ‘
ls_qmel-qmnum.
ENDLOOP.
sy-subrc = 0.
ENDFORM. “Z_BEFORE_DEL
Business Object
In transaction SWO1 create an Object – ZPRPS.
Enter the following values –
Now, we give the object ‘eyes’ (to respond to the outside world), ‘ears’ (to hear for Event calls), and ‘limbs’ (to do some work) by defining a Key field, a Method, and an Event.
When a record is updated in ZPRPS, a Change Document is written for it. This raises an Event (which is linked to the Business Object in the next step). The Event triggers the Workflow. A Task in the Workflow executes the Method of the Business Object. The Method then updates the Notification.
Key field – Project ID
The following pop-up appears, click Yes.
Enter ZPRPS as the Table, the Primary Key is listed, select this and click Continue.
Click Create on the next screen.

Method – UpdateNotification
Answer No to the following pop-up.
Switch off Dialog, keep Synchronous on and click on Continue.
Select the Method, click Program, the following pop-up appears, click Continue.
Save the program and Back out.
When this Method is called by the Workflow we want it to update the Notification. Add the following lines of code to the Method –
begin_method updatenotification changing container.
DATA: lt_qmel TYPE STANDARD TABLE OF qmel.
* Check that the Project ID is referenced in a Notification
SELECT * FROM qmel
INTO TABLE lt_qmel
WHERE zzposid = object-key-projectid.
CHECK: sy-subrc = 0.
* Update the Notification
CALL FUNCTION ‘Z_QMEL_UPD’ IN UPDATE TASK
EXPORTING
it_qmel = lt_qmel
iv_zzposid = object-key-projectid
EXCEPTIONS
record_not_updated = 1
OTHERS = 2.
IF sy-subrc <> 0.
exit_return space space space space space.
ENDIF.
end_method.
Create Function Module Z_QMEL_UPD in a new Function Group ZPMWFUPD, with a Short Name – Update Notification PS Data.
FUNCTION z_qmel_upd.
*”———————————————————————-
*”*”Update Function Module:
*”
*”*”Local Interface:
*” IMPORTING
*” VALUE(IT_QMEL) TYPE LE_T_DLV_QMEL
*” VALUE(IV_ZZPOSID) TYPE ZPS_POSID
*” EXCEPTIONS
*” RECORD_NOT_UPDATED
*”———————————————————————-
DATA: wa_qmel TYPE qmel,
wa_zprps TYPE zprps,
lv_objectid TYPE cdobjectv,
lt_cdtxt TYPE STANDARD TABLE OF cdtxt,
ls_qmel_n TYPE qmel,
ls_iloa TYPE iloa,
ls_qmih TYPE qmih,
ls_qmfe TYPE qmfe,
ls_ihpa TYPE ihpa,
ls_qmma TYPE qmma,
ls_qmsm TYPE qmsm,
ls_qmur TYPE qmur.
* Get all linked Notifications for the Project ID
SELECT SINGLE *
FROM zprps
INTO wa_zprps
WHERE zzposid = iv_zzposid.
LOOP AT it_qmel
INTO wa_qmel.
* Update table QMEL with the changed values
UPDATE qmel
SET zzpost1 = wa_zprps-zzpost1
zzpstrt = wa_zprps-zzpstrt
WHERE qmnum = wa_qmel-qmnum.
IF sy-subrc = 0.
lv_objectid = wa_qmel-qmnum.
ls_qmel_n = wa_qmel.
ls_qmel_n-zzpost1 = wa_zprps-zzpost1.
ls_qmel_n-zzpstrt = wa_zprps-zzpstrt.
* Write the Change Document for the Notification
CALL FUNCTION ‘MELDUNG_WRITE_DOCUMENT’
EXPORTING
objectid = lv_objectid
tcode = sy-tcode
utime = sy-timlo
udate = sy-datlo
username = sy-uname
object_change_indicator = ‘U’
n_ihpa = ls_ihpa
o_ihpa = ls_ihpa
n_iloa = ls_iloa
o_iloa = ls_iloa
n_qmel = ls_qmel_n
o_qmel = wa_qmel
upd_qmel = ‘U’
n_qmfe = ls_qmfe
o_qmfe = ls_qmfe
n_qmih = ls_qmih
o_qmih = ls_qmih
n_qmma = ls_qmma
o_qmma = ls_qmma
n_qmsm = ls_qmsm
o_qmsm = ls_qmsm
n_qmur = ls_qmur
o_qmur = ls_qmur
TABLES
icdtxt_meldung = lt_cdtxt.
ELSE.
ROLLBACK WORK.
RAISE record_not_updated.
ENDIF.
CLEAR: wa_qmel.
ENDLOOP.
ENDFUNCTION.
Event – CHANGED
Change the status of the Object to Implemented, (menu – Edit >> Change Release Status >> Object Type >> To implemented).
Then change the status to Released.
Do the same for the Object Type Components (Key field, Method, and Event).
Link the Change Document Object with the Business Object
Assign the Change Document Object to an Object Type
Execute transaction SWED.
Click Change, and Continue on the pop-up.
Add a new entry to link the Change Document Object ZPRPS_CD and table ZPRPS so that changes are recorded when table entries change.
Save the entry.
Link the Change Document Object to an Event
Execute transaction SWEC. Click Continue on the pop-up.
Create a new entry to link the Change Document Object ZPRPS_CD with the Object ZPRPS and Event CHANGED earlier created. Select On Change as the Trigger Event.
When Function Module ZPRPS_CD_WRITE_DOCUMENT is called with the Change Indicator as Update, it will raise Event CHANGED in Object ZPRPS.
Save the entry.
Workflow
The Workflow is triggered when Event CHANGED is raised.
Go to transaction PFTC, select Workflow Template as Task Type, give the Workflow a meaningful name in Task (we will be using Z_NOTIF_UPD), and click Create.
Give a Name – Update Notification Data.
Create a new Container Element – ZPRPS, with reference to Object Type ZPRPS. The Name and Short Descript. is ZPRPS. On the Properties tab, tick Import in Parameter Settings.
Container Element ZPRPS receives the data passed to the Workflow from the Event triggered.
Create a Triggering Event with reference to Object Type ZPRPS and Event CHANGED. Click on the button to activate the Event (the icon turns from a Grey diamond to a Green square).
Select the entry and click the Call Binding Editor button. Now click Generate Automatic Binding to bind &_EVT_CREATOR& with &_WF_INITIATOR& and &_EVT_OBJECT& with &ZPRPS&.
Save the Workflow.
Go to the Basic Data tab and click on Workflow Builder.
Create an Activity step. Name it Update Notification Data. Create a Task – Z_NOTIF_UPD, with the Name – Update Notification Data, enter some appropriate Work item text, Object Category – BO, Object Type – ZPRPS, Method – UPDATENOTIFICATION.
Switch on Background processing since this step will be processed by the system and requires no user intervention.
Go back to the previous screen and click on Define Binding Autom., click Continue to accept the binding between _WI_OBJECT_ID in the Task and &ZPRPS& in the Workflow.
Display/Maintain Event Type Linkages
Execute transaction SWETYPV. Go to Object Type ZPRPS.
Double-click to bring up the next screen.
Extend the PM Notification
We now need to render the fields in ZPRPS in standard transactions IW21, IW22, and IW23. There are 2 parts to it; first we need to do some basic development to create a new sub screen for the fields, then we will look at configuration to assign the newly created screen area to the Notification Type. We will use Notification Type – M1 for our demo.
The fields will be added to table QMEL. Click on Append Structure, name it CI_QMEL and add the fields.
Go to transaction CMOD. Create a Project – ZPMNOTSC, click on Enhancement assignments to assign Enhancement – QQMA0001 to this Project. Save and Activate.
Go back into the Project, click on Components, double-click on Function exit – EXIT_SAPMIWO0_009, and create Include – ZXQQMU08. Add the following lines of code to ZXQQMU08 –
MOVE: viqmel-zzprart TO e_viqmel-zzprart,
viqmel-zzposid TO e_viqmel-zzposid,
viqmel-zzpost1 TO e_viqmel-zzpost1,
viqmel-zzpstrt TO e_viqmel-zzpstrt,
viqmel-zzflag TO e_viqmel-zzflag.
Execute transaction SE80, Function Group – XQQM. Create a new screen – 0100. Include the fields in this screen. Fields Project Name (VIQMEL-ZZPOST1) and Project Date (VIQMEL-ZZPSTRT) are output only. Define a new PBO and include the given code in the subroutine –
*&———————————————————————*
*& Form DYNMOD_0100_PAI
*&———————————————————————*
* text
*———————————————————————-*
* –> p1 text
* <– p2 text
*———————————————————————-
FORM dynmod_0100_pai .
* If it is display mode then disable all the fields
CHECK: gv_t365-aktyp NE ‘A’.
LOOP AT SCREEN.
screen-input = 0.
MODIFY SCREEN.
ENDLOOP.
ENDFORM. ” DYNMOD_0100_PAI
Define a new PAI and include the given code in the subroutine –
*&———————————————————————*
*& Form ZZ_CHECK_WBS
*&———————————————————————*
* text
*———————————————————————-*
* –> p1 text
* <– p2 text
*———————————————————————-*
FORM zz_check_wbs .
IF viqmel-zzposid IS NOT INITIAL.
* Fetch entries from ZPRPS
SELECT SINGLE *
FROM zprps
INTO CORRESPONDING FIELDS OF viqmel
WHERE zzprart = viqmel-zzprart AND
zzposid = viqmel-zzposid.
ENDIF.
ENDFORM. ” ZZ_CHECK_WBS
And that is all the coding we require . Now we come to the customization. hGo to SAP Reference IMG in transaction SPRO. Navigate to the menu path – Cross-Application Components >> Notification >> Overview of Notification Type. Execute node – Overview of Notification Type, select Notification Type – M1 Maintenance Request.
Double click on Screen Structure for Extended View.
Double click 10\TAB02 Additional data 1.
Reposition Screen area 2 to include 090 Customer Subscreen (One Screen/Not.Type).
Save the changes.
Create a Notification
Execute transaction SM30 to create an entry in table ZPRPS. Enter the following values and Save the record –
Assignment – CORRECTIVE,
Project ID – PROJECT DEMO,
Project Name – DEMO OF A WF UPDATING THIS NOTIFICATION,
Project Date – 10.03.2010.
Execute transaction IW21 to create a Notification. Our Notification Type is M1.
On the Notification tab enter all the mandatory data (depending on which fields are set to Required in customizing). We will enter a short Description for the Notification – Test. Click on the Risk Assessment tab. Enter Assignment – CORRECTIVE, select the Project ID we created in the above step and hit Enter (this will populate the dependant fields Project Name and Project Date). Feel free to enter a value in Switching Reqd or leave it blank (we will flag it as Y). Save the Notification.
Update the Notification
Switch On Event Trace
Execute transaction SWELS to switch on an Event Trace, click Switch on, Restriction for trace, enter ‘Creator’ object type – ZPRPS, Save and continue.
Update Table ZPRPS
Execute transaction SM30 and change the associate attributes for the Project ID – PROJECT DEMO to anything you want. We will change the Project Name to ‘HAS THE PROJECT NAME CHANGED?’ and the Project Date to ’10.03.2011’. Save it.
Display Event Trace
Execute transaction SWEL with ‘Creator’ object type – ZPRPS to see the Event and Workflow triggered for the Change Document.
We can thus confirm that the Workflow has successfully updated the Notification with the new values.
Execute transaction SWELS again and click Switch Off to switch off the Event Trace.
Display Change Documents
Carry out a sanity check just to confirm that the Change Documents were written for table ZPRPS. Execute transaction SE16N, enter the name of the Change Document Header table – CDHDR, and click Enter. Execute it with OBJECTCLAS – ZPRPS_CD, OBJECTID – PROJECT DEMO, UDATE – current date (whichever date you have created and changed the record). We will get the following 2 entries; one for Insert and the other for Update –
Make a note of the Document Numbers (CHANGENR), then query table CDPOS with them. This shows us what exactly changed in the record (from and to values).
Display Notification Changes
Execute transaction IW22/IW23 to see if the data has changed.
We see that both the Project Name and Project Date now have the new values.
View the change logs to the Notification (menu – Extras >> Notification documents >> Changes).
Related Content
Building a Workflow from Scratch
Extending a Business Object
Using the Event Trace