第 55 页 / 共 275 页
Customized Fields in Purchase Orders 3.1
EE The IM_ELEMENT parameter either contains HEADER or ITEM as a value depend-
ing on whether the call is executed for the header or item level.
EE Depending on this value, you must populate the third parameter, RE_SUB-
SCRIBERS, which is an internal table. You can see its structure in Table 3.8.
Table Field Description
NAME A unique identification of the tabstrip of type MEPO_
NAME. Using this name, you can recognize which dynpro
is currently being run in other methods of the BAdI.
DYNPRO The number of your own dynpro.
PROGRAM The program in which your custom dynpro is located.
STRUCT_NAME An ABAP Dictionary structure that describes your
custom fields in this dynpro.
LABEL The title given to the tabstrip in the transaction.
POSITION The item of the tabstrip. If you enter the value 3 here,
for example, the tabstrip appears in the third position
from left.
HEIGHT The height of the tabstrip. Only two values are currently
interpreted here: A value less than or equal to 7 results
in a tabstrip with a height of seven lines. A value greater
than 7 results in a tabstrip with a height of 16 lines.
Table 3.8 Description of the Parameter RE_SUBSCRIBERS
3. You’ll require the unique identification of the tabstrip that you must assign to
the field NAME (see Table 3.8) in several methods. You should therefore define
these in the attributes of the implementing class as constants — you can access
the attributes of the class from all methods. To do this, open the implementa-
tion of the BAdI ME_GUI_PO_CUST. Double-click the name of the implementing
class (ZCL_IM_ME_GUI_PO_CUST), and switch to the Attributes tabstrip.
4. Create a constant of the type MEPO_NAME, which contains the programmed name
of your tabstrip and item tabstrip (see Figure 3.3). Then register your dynpros.
You can find the sample in Listing 3.11.
55
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
| Table Field | Description |
|---|---|
| NAME | A unique identification of the tabstrip of type MEPO_ NAME. Using this name, you can recognize which dynpro is currently being run in other methods of the BAdI. |
| DYNPRO | The number of your own dynpro. |
| PROGRAM | The program in which your custom dynpro is located. |
| STRUCT_NAME | An ABAP Dictionary structure that describes your custom fields in this dynpro. |
| LABEL | The title given to the tabstrip in the transaction. |
| POSITION | The item of the tabstrip. If you enter the value 3 here, for example, the tabstrip appears in the third position from left. |
| HEIGHT | The height of the tabstrip. Only two values are currently interpreted here: A value less than or equal to 7 results in a tabstrip with a height of seven lines. A value greater than 7 results in a tabstrip with a height of 16 lines. |
第 56 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
Figure 3.3 Attributes of the Implementing Class
METHOD if_ex_me_gui_po_cust~subscribe.
DATA: ls_subscriber LIKE LINE OF re_subscribers.
* Only from the purchase order (currently always ‘PO’, therefore only
* to be on the safe side)
CHECK im_application = ‘PO’.
REFRESH re_subscribers.
* Depending on whether header or item tabstrips
* are required to register custom dynpros
CASE im_element.
WHEN ‘HEADER’.
ls_subscriber-name = subscr_head.
* Dynpro from custom function group:
ls_subscriber-dynpro = ‘0100’.
ls_subscriber-program = ‘SAPLZME_CUST’.
ls_subscriber-struct_name = ‘ZME_POHEAD_DS’.
* Caption of the tabstrip
ls_subscriber-label = ‘Eigene Daten’(001).
* Position and height
ls_subscriber-position = 1.
ls_subscriber-height = 7.
APPEND ls_subscriber TO re_subscribers.
WHEN ‘ITEM’.
ls_subscriber-name = subscr_item.
56
© 2013 by Galileo Press Inc., Boston (MA)
第 57 页 / 共 275 页
Customized Fields in Purchase Orders 3.1
* Dynpro from custom function group:
ls_subscriber-dynpro = ‘0200’.
ls_subscriber-program = ‘SAPLZME_CUST’.
ls_subscriber-struct_name = ‘ZME_POITEM_DS’.
* Caption of the tabstrip
ls_subscriber-label = ‘Eigene Daten’(001).
* Position and height
ls_subscriber-position = 99.
ls_subscriber-height = 7.
APPEND ls_subscriber TO re_subscribers.
ENDCASE.
ENDMETHOD.
Listing 3.11 Method SUBSCRIBE from ME_GUI_PO_CUST
The fields of your dynpros must then be assigned to the metafields. This takes
place in method MAP_DYNPRO_FIELDS of the ME_GUI_PO_CUST BAdI. This method
only has an internal table CH_MAPPING as a parameter that contains all fields you’ve
redefined. You can query the respective field via the table column FIELDNAME. Here
you must assign each field via the METAFIELD table column.
Metafields have the data type MMPUR_METAFIELD, which ultimately displays only
one integer value. Values from 90000000 and above are reserved for customers.
In the MMMFD type group, there are 10 predefined customer metafields that you can
use. These are the fields MMMFD_CUST_01 (90000000) to MMMFD_CUST_10 (90000009).
If you require more fields, you can create more in a custom type group.
You can see how a predefined metafield is assigned using the following steps:
1. Open the implementation of the ME_GUI_PO_CUST BAdI, and navigate again to
the implementing class (ZCL_IM_ME_GUI_PO_CUST).
2. In the Properties tabstrip, you must now specify the type group MMMFD by
entering this on the right-hand side in the Forward declarations area (see
Figure 3.4).
57
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
第 58 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
Figure 3.4 Definition of the Type Group as a Forward Declaration
3. Go to the MAP_DYNPRO_FIELDS method, and assign a metafield to the fields of the
dynpros. For the fields ZK_FELD1 to ZK_FELD3, use the metafields MMMFD_CUST_01
to MMMFD_CUST_03, and for the fields ZP_FELD1 to ZP_FELD3, take the metafields
MMMFD_CUST_04 to MMMFD_CUST_06. Use Listing 3.12 as a template.
METHOD if_ex_me_gui_po_cust~map_dynpro_fields.
FIELD-SYMBOLS: <mapping> LIKE LINE OF ch_mapping.
LOOP AT ch_mapping ASSIGNING <mapping>.
CASE <mapping>-fieldname.
* Map header fields
WHEN ‘ZK_FELD1’.
<mapping>-metafield = mmmfd_cust_01.
WHEN ‘ZK_FELD2’.
<mapping>-metafield = mmmfd_cust_02.
WHEN ‘ZK_FELD3’.
<mapping>-metafield = mmmfd_cust_03.
58
© 2013 by Galileo Press Inc., Boston (MA)
第 59 页 / 共 275 页
Customized Fields in Purchase Orders 3.1
* Map item fields
WHEN ‘ZP_FELD1’.
<mapping>-metafield = mmmfd_cust_04.
WHEN ‘ZP_FELD2’.
<mapping>-metafield = mmmfd_cust_05.
WHEN ‘ZP_FELD3’.
<mapping>-metafield = mmmfd_cust_06.
ENDCASE.
ENDLOOP.
ENDMETHOD.
Listing 3.12 Method MAP_DYNPRO_FIELDS from ME_GUI_PO_CUST
If you activate your BAdIs, you can view the new tabstrips in Transaction ME23N.
However, the tabstrip isn’t yet displayed when created or in the change mode
because the fields are hidden in this case. To set the field status correctly, you still
need the methods FIELDSELECTION_HEADER and FIELDSELECTION_ITEM of the BAdI
ME_PROCESS_PO_CUST.
The internal table CH_FIELDSELECTION consists of two columns. The METAFIELD
column contains the metafield that you assigned to a dynpro field in the previous
step. You can overwrite the FIELDSTATUS field with the desired status using Table
3.9.
Status Explanation
- Hidden field (when you hide all fields, the tabstrip is also hidden)
* Display field
. Input field
+ Mandatory field
Table 3.9 Field Status — Overview of Options
You can also access the data model of the header data via the IM_HEADER param-
eter (reference to the interface IF_PURCHASE_ORDER_MM). The IM_ITEM parameter
(reference to the interface IF_PURCHASE_ORDER_ITEM_MM) also exists for the items.
Various methods are provided for the interfaces to obtain information on the
content and status of the purchase order. You can directly view the interfaces in
Transaction SE24.
As an example, the fields in the purchase order display should only be display
fields. However, a ready-for-input status is desired in the change mode. The header
59
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
| Status | Explanation |
|---|---|
| - | Hidden field (when you hide all fields, the tabstrip is also hidden) |
| * | Display field |
| . | Input field |
| + | Mandatory field |
第 60 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
field ZK_FELD3 should only become ready for input when the header of the pur-
chase order does not contain any errors. To make this happen, implement the
following steps:
1. Open your implementation for the ME_PROCESS_PO_CUST BAdI. Navigate to the
implementing class (ZCL_IM_ME_PROCESS_PO_CUST), and insert the MMMFD type
group.
2. Program the FIELDSELECTION_HEADER and FIELDSELECTION_ITEM methods ac-
cording to the description. You can find the methods in Listing 3.13 and Listing
3.14, respectively.
METHOD if_ex_me_process_po_cust~fieldselection_header.
FIELD-SYMBOLS <chfs> TYPE mmpur_fs.
DATA lv_changeable TYPE mmpur_bool.
* Can the purchase order be changed (create/change)?
lv_changeable = im_header->is_changeable( ).
* Override field selection
LOOP AT ch_fieldselection ASSIGNING <chfs>.
IF lv_changeable IS INITIAL.
* Display mode, field is not supposed to be ready for input
<chfs>-fieldstatus = ‘*‘.
ELSE.
* Field is to be ready for input
<chfs>-fieldstatus = ‘.‘.
ENDIF.
* Special rule for field ZK_FELD3 (detection via metafield):
* Hide, so long as header of the purchase order contains errors
IF <chfs>-metafield = mmmfd_cust_03.
IF im_header->is_valid( ) IS INITIAL.
<chfs>-fieldstatus = ‘-‘.
ENDIF.
ENDIF.
ENDLOOP.
ENDMETHOD.
Listing 3.13 Method FIELDSELECTION_HEADER of ME_PROCESS_PO_CUST
60
© 2013 by Galileo Press Inc., Boston (MA)
第 61 页 / 共 275 页
Customized Fields in Purchase Orders 3.1
METHOD if_ex_me_process_po_cust~fieldselection_item.
FIELD-SYMBOLS <chfs> TYPE mmpur_fs.
DATA lv_changeable TYPE mmpur_bool.
* Can the purchase order be changed (create/change)?
lv_changeable = im_header->is_changeable( ).
* Override field selection
LOOP AT ch_fieldselection ASSIGNING <chfs>.
IF lv_changeable IS INITIAL.
* Display mode, field isn’t supposed to be ready for input
<chfs>-fieldstatus = ‘*’.
ELSE.
* Field is supposed to be ready for input
<chfs>-fieldstatus = ‘.’.
ENDIF.
ENDLOOP.
ENDMETHOD.
Listing 3.14 Method FIELDSELECTION_ITEM of ME_PROCESS_PO_CUST
3.1.4 Integration of Customer Fields into the Business Logic
The dynpros have now been successfully integrated into the purchase order. How-
ever, the integration into the business logic of the purchase order is still missing.
Above all, the correct data must be retrieved from the data model at the correct
time and added to the dynpros. When changes are made, this data must be copied
back from the dynpro to the data model. Correct handling is important, particu-
larly for the items, because other data is supposed to be made visible in the dynpro
for every item here.
In the ME_GUI_PO_CUST BAdI, the process for each defined tabstrip is specified as
follows:
1. TRANSPORT_FROM_MODEL
Here you read the custom data to be displayed in the dynpro from the data
model (your function group) and temporarily save this in an attribute of your
implementing class.
2. TRANSPORT_TO_DYNP
The previously retrieved data must be transferred to the structure, the fields of
which are displayed in the dynpro. The dynpro is now displayed and can be
edited by the user.
61
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
第 62 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
3. TRANSPORT_FROM_DYNP
Now retrieve the data again from the dynpro structure, and save the result
in a second attribute of your implementing class. Compare whether there has
been a change to the data in comparison to the status in Step 1. If so, check the
RE_CHANGED flag.
4. TRANSPORT_TO_MODEL
This method is only called if you have set the RE_CHANGED flag in Step 3. Trans-
port the changed data here back to your function group.
In each method, obtain the name of the tabstrip previously defined in the SUB-
SCRIBE method via the IM_NAME parameter. The data of the purchase order is also
provided in a reference in the data model as the IM_MODEL parameter. Using this
reference, you obtain the header data via the interface IF_PURCHASE_ORDER_MM and
the item data via the interface IF_PURCHASE_ORDER_ITEM_MM.
To access this data, create a local reference in one of the two interfaces, and then
implement an upcast from the transferred data model. To do this, you can use the
MMPUR_DYNAMIC_CAST macro. You access the respective interfaces as follows:
DATA: l_header TYPE REF TO if_purchase_order_mm,
l_item TYPE REF TO if_purchase_order_item_mm.
mmpur_dynamic_cast l_header im_model.
mmpur_dynamic_cast l_item im_model.
You are now provided with all methods of both interfaces via L_HEADER or L_ITEM.
The most important method might be GET_DATA, through which you access the
fields of the purchase order. You can find out again about further methods and
their respective parameters for these interfaces directly via Transaction SE24.
Interfaces and Upcasts
The interface and upcast concepts come from object-oriented programming. An inter-
face describes an object in the form of attributes and methods. However, it doesn’t
contain any implementation, and the methods therefore don’t contain any coding. A
class can now refer to an interface. In this case, the class must implement all attributes
and methods defined in the interface and program the methods. The class may also
implement other interfaces or contain additional custom attributes and methods. The
class is therefore more detailed than the original interface.
You can create a local object with reference to an interface and assign the object of the
class (an object is an instance of a class). In this case, the assigned object contains more
information than your local object. Therefore, only part of the object defined in the
interface is copied. The navigation from one detailed object to a less detailed object is
referred to as an upcast.
62
© 2013 by Galileo Press Inc., Boston (MA)
| Interfaces and Upcasts |
|---|
| The interface and upcast concepts come from object-oriented programming. An inter- face describes an object in the form of attributes and methods. However, it doesn’t contain any implementation, and the methods therefore don’t contain any coding. A class can now refer to an interface. In this case, the class must implement all attributes and methods defined in the interface and program the methods. The class may also implement other interfaces or contain additional custom attributes and methods. The class is therefore more detailed than the original interface. You can create a local object with reference to an interface and assign the object of the class (an object is an instance of a class). In this case, the assigned object contains more information than your local object. Therefore, only part of the object defined in the interface is copied. The navigation from one detailed object to a less detailed object is referred to as an upcast. |
第 63 页 / 共 275 页
Customized Fields in Purchase Orders 3.1
The advantage of an interface is that only the interface must be specified to users (in
this case, you). You don’t need to know what the object is and what other information
this object contains. You simply retrieve the part relevant to you from the object via the
interface and the upcast.
An upcast is implemented via the assignment operator (?=). You can, however, use the
MMPUR_DYNAMIC_CAST macro in this BAdI, which also contains error handling.
Let’s implement this information in practice:
1. Navigate to your implementation for the ME_GUI_PO_CUST BAdI, go to the imple-
menting class, and then navigate to the Attributes tabstrip. Create four private
instance attributes: GS_HEADER_PBO and GS_HEADER_PAI of type ZME_POHEAD, as
well as GS_ITEM_PBO and GS_ITEM_PAI of type ZME_POITEM (see Figure 3.5).
Figure 3.5 Further Attributes in the BAdI ME_GUI_PO_CUST
2. Navigate to the TRANSPORT_FROM_MODEL method, retrieve the current values
from your function group depending on the tabstrip displayed, and save these
in the GS_HEADER_PBO or GS_ITEM_PBO attribute (see Listing 3.15).
METHOD if_ex_me_gui_po_cust~transport_from_model.
DATA: l_header TYPE REF TO if_purchase_order_mm,
l_item TYPE REF TO if_purchase_order_item_mm.
DATA: ls_mepoheader TYPE mepoheader,
ls_mepoitem TYPE mepoitem.
63
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
第 64 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
CASE im_name.
WHEN subscr_head.
* Header tabstrip, retrieve reference in header data
mmpur_dynamic_cast l_header im_model.
CHECK l_header IS NOT INITIAL.
ls_mepoheader = l_header->get_data( ).
* Retrieve current header data from model, and note
* in gs_header_pbo attribute
CALL FUNCTION ‘Z_ME_CUST_DATA_GET’
EXPORTING
i_type = ‘HEADER’
i_ebeln = ls_mepoheader-ebeln
IMPORTING
e_header = gs_header_pbo.
WHEN subscr_item.
* Item tabstrip, retrieve reference in item data
mmpur_dynamic_cast l_item im_model.
CHECK l_item IS NOT INITIAL.
ls_mepoitem = l_item->get_data( ).
* Retrieve current item data from model, and
* note in gs_item_pbo attribute
CALL FUNCTION ‘Z_ME_CUST_DATA_GET’
EXPORTING
i_type = ‘ITEM’
i_ebeln = ls_mepoitem-ebeln
i_ebelp = ls_mepoitem-ebelp
IMPORTING
e_item = gs_item_pbo.
ENDCASE.
ENDMETHOD.
Listing 3.15 Method TRANSPORT_FROM_MODEL
3. The TRANSPORT_TO_DYNP method must be created in the next step. Depending
on the tabstrip used, create a local structure for your dynpro structure, and copy
the relevant fields from the previously parked GS_HEADER_PBO and GS_ITEM_PBO
attributes. Transfer this structure to the dynpro of your function group so that
64
© 2013 by Galileo Press Inc., Boston (MA)
第 65 页 / 共 275 页
Customized Fields in Purchase Orders 3.1
the data contained in the structure is displayed there when the dynpro is called
(see Listing 3.16).
METHOD if_ex_me_gui_po_cust~transport_to_dynp.
* Local copies of the dynpro structures
DATA: ls_head_ds TYPE zme_pohead_ds,
ls_item_ds TYPE zme_poitem_ds.
CASE im_name.
WHEN subscr_head.
* Fill header data, Dynpro structure...
MOVE-CORRESPONDING gs_header_pbo TO ls_head_ds.
* ... and transfer
CALL FUNCTION ‘Z_ME_CUST_DYN_SET’
EXPORTING
i_type = ‘HEADER’
i_pohead = ls_head_ds.
WHEN subscr_item.
* Fill item data, dynpro structure ...
MOVE-CORRESPONDING gs_item_pbo TO ls_item_ds.
* ... and transfer
CALL FUNCTION ‘Z_ME_CUST_DYN_SET’
EXPORTING
i_type = ‘ITEM’
i_poitem = ls_item_ds.
ENDCASE.
ENDMETHOD.
Listing 3.16 Method TRANSPORT_TO_DYNP
4. Now focus on the TRANSPORT_FROM_DYNP method, and retrieve the data here
once again from the dynpro. Copy the data to the GS_HEADER_PAI or GS_ITEM_
PAI structure for comparison. Compare whether there have been any changes
to the data, and if necessary, set the RE_CHANGED flag (see Listing 3.17).
METHOD if_ex_me_gui_po_cust~transport_from_dynp.
* Local copies of the dynpro structures
DATA: ls_head_ds TYPE zme_pohead_ds,
ls_item_ds TYPE zme_poitem_ds.
65
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
第 66 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
CASE im_name.
WHEN subscr_head.
* Retrieve header data, dynpro data...
CALL FUNCTION ‘Z_ME_CUST_DYN_GET’
EXPORTING
i_type = ‘HEADER’
IMPORTING
e_pohead = ls_head_ds.
* ... and copy back
gs_header_pai = gs_header_pbo.
MOVE-CORRESPONDING ls_head_ds TO gs_header_pai.
WHEN subscr_item.
* Retrieve item data, Dynpro data...
CALL FUNCTION ‘Z_ME_CUST_DYN_GET’
EXPORTING
i_type = ‘ITEM’
IMPORTING
e_poitem = ls_item_ds.
* ... and copy back
gs_item_pai = gs_item_pbo.
MOVE-CORRESPONDING ls_item_ds TO gs_item_pai.
ENDCASE.
* Has the user changed data?
IF gs_header_pbo <> gs_header_pai OR
gs_item_pbo <> gs_item_pai.
* set flag
re_changed = ‘X’.
ENDIF.
ENDMETHOD.
Listing 3.17 Method TRANSPORT_FROM_DYNP
5. You must now copy possible changes to the TRANSPORT_TO_MODEL method back
to your function group. You have already saved the new data in the GS_HEADER_
PAI and GS_ITEM_PAI attributes. You must therefore copy the data back to the
function group only via the already existing function modules.
If you open an existing purchase order and then only change custom data and
want to save the purchase order again, you’ll get the message “No data has been
66
© 2013 by Galileo Press Inc., Boston (MA)
第 67 页 / 共 275 页
Customized Fields in Purchase Orders 3.1
changed.” To avoid this, you need to announce the data change. The TRANS-
PORT_TO_MODEL method will only run if custom data has been changed. This
method can therefore be used to announce the change. For this, retrieve the
IF_PURCHASE_ORDER_MM interface, and call the SET_CHANGED method there. The
complete example is shown in Listing 3.18.
METHOD if_ex_me_gui_po_cust~transport_to_model.
DATA: l_header TYPE REF TO if_purchase_order_mm.
* Inform model that data has been changed
mmpur_dynamic_cast l_header im_model.
l_header->set_changed( ).
CASE im_name.
WHEN subscr_head.
* Copy back header data to model
CALL FUNCTION ‘Z_ME_CUST_DATA_SET‘
EXPORTING
i_type = ‘HEADER‘
i_header = gs_header_pai.
WHEN subscr_item.
* Copy back item data to model
CALL FUNCTION ‘Z_ME_CUST_DATA_SET‘
EXPORTING
i_type = ‘ITEM‘
i_item = gs_item_pai.
ENDCASE.
ENDMETHOD.
Listing 3.18 Method TRANSPORT_TO_MODEL
6. The data transport is now completed. You still need to handle one situation,
however. If the user deletes a line of the purchase order, the associated custom
data should also be removed in the data model. When a line is deleted, none of
the previously mentioned methods will run. Therefore, this case must be han-
dled in the PROCESS_ITEM method of the ME_PROCESS_PO_CUST BAdI. Here the
reference in the IF_PURCHASE_ORDER_ITEM_MM interface is directly transferred as
the IM_ITEM parameter. Therefore, an upcast isn’t required. With the GET_DATA
method, you must only retrieve and check the data to determine whether the
deletion indicator (LOEKZ) is set (see Listing 3.19).
67
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
第 68 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
METHOD if_ex_me_process_po_cust~process_item.
DATA: ls_mepoitem TYPE mepoitem.
DATA: ls_item TYPE zme_poitem.
* Retrieve item data
ls_mepoitem = im_item->get_data( ).
* Is the deletion indicator set?
IF ls_mepoitem-loekz = ‘D’.
* Deleted item
ls_item-ebeln = ls_mepoitem-ebeln.
ls_item-ebelp = ls_mepoitem-ebelp.
CALL FUNCTION ‘Z_ME_CUST_DATA_SET’
EXPORTING
i_type = ‘ITEM’
i_item = ls_item
i_delkz = ‘X’.
ENDIF.
ENDMETHOD.
Listing 3.19 Method PROCESS_ITEM from ME_PROCESS_PO_CUST
3.1.5 Initializing, Reading, and Updating Data
To complete the enhancement, only a few more calls in the function group are now
necessary. The custom data must be initialized when the purchase order transac-
tion is started or a purchase order is closed. Moreover, the data from the database
needs to be read as soon as an existing purchase order is opened. Finally, you need
to activate the update of your own data when you save the purchase order.
1. Process the INITIALIZE (initialization of the purchase order transactions) and
CLOSE (exiting a purchase order) methods of the ME_PROCESS_PO_CUST BAdI, and
initialize your own data from here by calling the function module Z_ME_CUST_
INIT (see Listing 3.20 and Listing 3.21).
2. Navigate to the OPEN method, and then call your function module Z_ME_CUST_
OPEN to read the custom data. To do this, you only have to transfer the pur-
chase order number, which you obtain again via the GET_DATA method of the
IM_HEADER reference parameter (see Listing 3.22).
3. To update the data, you now need the POST method of the BAdI in which you
call your function module Z_ME_CUST_POST. This also requires the document
68
© 2013 by Galileo Press Inc., Boston (MA)
第 69 页 / 共 275 页
Customized Fields in Purchase Orders 3.1
number, which is directly transferred here in the IM_EBELN parameter (see List-
ing 3.23).
METHOD if_ex_me_process_po_cust~initialize.
* Initialize custom data
CALL FUNCTION ‘Z_ME_CUST_INIT’.
ENDMETHOD.
Listing 3.20 Method INITIALIZE of ME_PROCESS_PO_CUST
METHOD if_ex_me_process_po_cust~close.
* Initialize custom data
CALL FUNCTION ‘Z_ME_CUST_INIT’.
ENDMETHOD.
Listing 3.21 Method CLOSE of ME_PROCESS_PO_CUST
METHOD if_ex_me_process_po_cust~open.
DATA: ls_mepoheader TYPE mepoheader.
* Retrieve header data /Belegnummer
ls_mepoheader = im_header->get_data( ).
* Read custom data on purchase order number.
CALL FUNCTION ‘Z_ME_CUST_OPEN’
EXPORTING
i_ebeln = ls_mepoheader-ebeln.
ENDMETHOD.
Listing 3.22 Method OPEN of ME_PROCESS_PO_CUST
METHOD if_ex_me_process_po_cust~post.
* Update custom data
CALL FUNCTION ‘Z_ME_CUST_POST’
EXPORTING
i_ebeln = im_ebeln.
ENDMETHOD.
Listing 3.23 Method POST of ME_PROCESS_PO_CUST
3.1.6 Display of Error Messages
You are likely planning to carry out input checks for your own fields sooner or
later and to display warning or error messages. The Enjoy purchase order trans-
actions use a message collector for messages; that is, messages are not directly
69
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
第 70 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
displayed but are first collected, and then displayed as an overview upon request
(see Figure 3.6).
Figure 3.6 Messages via the Message Collector
Furthermore, you can mark notifications in this window, and navigate directly
to the relevant input field via Edit. To do this, you must link the message with a
metafield (that shows a dynpro element).
You can perform your input check in one of the methods listed in Table 3.10. Add
the MM_MESSAGES_MAC include, which includes some macros, and which you can use
to display messages very simply and execute the required metafield connections.
You then display messages as follows:
1. Use the MMPUR_METAFIELD macro to refer to subsequent messages in a specific
metafield:
mmpur_metafield mmmfd_cust_01.
2. Submit a message with the MMPUR_MESSAGE_FORCED macro to the message col-
lector. Transfer sequentially the message type, message class, message number,
and the placeholders 1-4:
mmpur_message_forced ‘W’ ‘ZME’ ‘001’
‘msgv1’ ‘msgv2’ ‘msgv3’ ‘msgv4’.
3. If the posting of the purchase order is supposed to be prevented until the errors
have been resolved, you must set the corresponding status yourself. This hap-
pens when you call the INVALIDATE method provided in all methods from
Table 3.10 via the model (IM_HEADER, IM_ITEM, IM_SCHEDULE or IM_ACCOUNT
parameters).
70
© 2013 by Galileo Press Inc., Boston (MA)
第 71 页 / 共 275 页
Customized Fields in Purchase Orders 3.1
Method Description
PROCESS_HEADER Processing of the header data
PROCESS_ITEM Processing of the item data
PROCESS_SCHEDULE Processing of scheduling data
PROCESS_ACCOUNT Processing of account assignment data
CHECK Closing checks complete document
Table 3.10 Methods for the Input Check
Listing 3.24 provides a simple example of an input check. The ZK_FELD2 field from
the header data of the purchase order must have the content “1” or “2” so that the
purchase order may be posted.
METHOD if_ex_me_process_po_cust~process_header.
* Macros for message handling
INCLUDE mm_messages_mac.
DATA: ls_mepoheader TYPE mepoheader,
ls_pohead TYPE zme_pohead.
* Retrieve custom data
ls_mepoheader = im_header->get_data( ).
CALL FUNCTION ‘Z_ME_CUST_DATA_GET’
EXPORTING
i_type = ‘HEADER’
i_ebeln = ls_mepoheader-ebeln
IMPORTING
e_header = ls_pohead.
* Field ZK_FELD2 must contain the value 1 or 2
IF ls_pohead-zk_feld2 NA ‘12’.
* Following notifications refer to
* metafield MMMFD_CUST_02:
mmpur_metafield mmmfd_cust_02.
* Display message:
* “Value & is not a valid entry for field 2”
mmpur_message_forced ‘E’ ‘ZME’ ‘001’
ls_pohead-zk_feld2 ‘’ ‘’ ‘’.
* Purchase order must not be posted:
im_header->invalidate( ).
71
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
| Method | Description |
|---|---|
| PROCESS_HEADER | Processing of the header data |
| PROCESS_ITEM | Processing of the item data |
| PROCESS_SCHEDULE | Processing of scheduling data |
| PROCESS_ACCOUNT | Processing of account assignment data |
| CHECK | Closing checks complete document |
第 72 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
ENDIF.
ENDMETHOD.
Listing 3.24 Input Checks in PROCESS_HEAD
3.2 Customizing the Document Overview in Purchase
Requisitions or Purchase Orders
This final part of the chapter introduces a still relatively unknown user exit, which
you can use to customize the document overview in purchase requisitions or pur-
chase orders (see Figure 3.7). It is also a simple matter of removing selection vari-
ants supplied in the SAP standard. You can also integrate custom queries into this
view. For example, you can remove the existing Purchase Orders selection vari-
ant, and using a custom selection variant, replace this with a less-extensive selec-
tion screen. Two user exits are provided for this purpose, which can be found in
the MEQUERY1 enhancement.
Figure 3.7 Selection Variants in the Document Overview
3.2.1 Removal of a Standard Selection Variant
The choice of selection variants is extensive. However, not every user requires this
complete choice. For example, a user who only processes purchase requisitions but
72
© 2013 by Galileo Press Inc., Boston (MA)
第 73 页 / 共 275 页
Customizing the Document Overview in Purchase Requisitions or Purchase Orders 3.2
who doesn’t have any authorization for purchase orders doesn’t need the selection
variants for queries, purchase orders, or contracts.
Cutting the existing choice is simple. Whenever the selection window is called
(see Figure 3.7), the EXIT_SAPLMEQUERY_001 user exit is run. This user exit only has
one internal table, META_TABLE, as a parameter (see Table 3.11), and each table line
contains two fields: The first field CLASSID is an internal reference to the underly-
ing selection; the second field LABEL contains the text as it is displayed in the docu-
ment in the selection window.
CLASSID LABEL
PO_QUERY Purchase orders
RFQ_QUERY Queries
AGREEMENT_QUERY Contracts
SCH_QUERY Scheduling agreements
PURDOCS_QUERY General purchasing documents
REQ_QUERY Purchase requisitions
POS_BY_USER_QUERY My purchase orders
PARKED_POS_BY_USER_QUERY Parked purchase orders
REQ_BY_USER_QUERY My purchase order requisitions
Table 3.11 Standard Content of the Table META_TABLE
If you reduce this table simply by the nonrequired selection variants, then these
are no longer displayed. To stay with the same example, you can implement an
authorization check in this user exit that checks whether the user has the autho-
rization to create purchase orders. If not, all entries, except the two for purchase
requisitions (REQ_QUERY and REQ_BY_USER_QUERY), are deleted.
1. Create a new project and include the MEQUERY1 enhancement. The procedure for
this is described in Section 2.1, Use of User Exits.
2. Navigate to the EXIT_SAPLMEQUERY_001 user exit, and then double-click on the
ZXM02U10 include integrated there. Create the include if it doesn’t yet exist.
3. An authorization check is now necessary. Because the MM authorization objects
mostly check at the plant or purchasing organization level, the only subject of
interest here is whether the user fundamentally has the authorization to create
73
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
| CLASSID | LABEL |
|---|---|
| PO_QUERY | Purchase orders |
| RFQ_QUERY | Queries |
| AGREEMENT_QUERY | Contracts |
| SCH_QUERY | Scheduling agreements |
| PURDOCS_QUERY | General purchasing documents |
| REQ_QUERY | Purchase requisitions |
| POS_BY_USER_QUERY | My purchase orders |
| PARKED_POS_BY_USER_QUERY | Parked purchase orders |
| REQ_BY_USER_QUERY | My purchase order requisitions |
第 74 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
the purchase order. The check for the transaction code can be used here. The
respective authorization object is S_TCODE.
Click Pattern, and select the option Authority Check in the dialog window
that opens. Specify the object S_TCODE, and confirm the dialog window using
the [Enter] key.
4. Replace the parameter behind the keyword FIELD with the transaction to be
checked, that is, ME21N for the purchase order creation.
5. The AUTHORITY-CHECK command provides a sy-subrc unequal to 0 if the user
doesn’t hold the checked authorization. In this case, the undesired lines are
now to be deleted. You can do this as usual via the DELETE command (see Listing
3.25).
*&-----------------------------------------------------*
*& Include ZXM02U10
*&-----------------------------------------------------*
*”*”Local interface:
*” TABLES
*” META_TABLE TYPE MMPUR_DATABL_META_TABLE
*”------------------------------------------------------
* Authorization check on Transaction ME21N
AUTHORITY-CHECK OBJECT ‘S_TCODE’
ID ‘TCD’ FIELD ‘ME21N’.
IF sy-subrc NE 0.
* No authorization for purchase order, remove all selection
* variants except REQ_QUERY and REQ_BY_USER_QUERY.
DELETE meta_table WHERE classid NE ‘REQ_QUERY’ AND
classid NE ‘REQ_BY_USER_QUERY’.
ENDIF.
Listing 3.25 Removing Selection Variants
6. Save and activate your coding.
7. Activate your project so that the user exit is active and will run. Test the result
with a user who doesn’t hold the respective authorization. You can view the
result in Figure 3.8.
74
© 2013 by Galileo Press Inc., Boston (MA)
第 75 页 / 共 275 页
Customizing the Document Overview in Purchase Requisitions or Purchase Orders 3.2
Figure 3.8 Reduced Document Overview with Only Two Selection Variants
3.2.2 Inserting Custom Selection Variants
The specified selection screen doesn’t always suit your individual requirements.
In the selection variant “Purchase Orders”, for example, you can access nearly all
fields via the dynamic selections. Perhaps you want to directly access fields from
this selection in the initial screen.
You can create virtually every query by yourself and integrate it into the document
overview. To do this, you need a report generated by SAP Query and the user exits
EXIT_SAPLMEQUERY_001 and EXIT_SAPLMEQUERY_002.
Creating SAP Queries
The selection variants in the document overview have been implemented by SAP
Query (Transaction SQ01). It’s possible with SAP Query to display lists without
any possessing knowledge about ABAP. To integrate a custom report, you must
first create this in an SAP Query.
Concepts from the World of Queries
Several concepts are used in the environment of SAP Queries that may be somewhat
confusing at first. The following explanations should help if you haven’t had experience
with SAP Queries:
EE Work area
All objects for SAP Queries can either be created in the global or local area. The
global area stands for objects independent of clients and the local area for the client-
dependent objects. A mixture of objects from both areas isn’t possible.
75
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
| Concepts from the World of Queries |
|---|
| Several concepts are used in the environment of SAP Queries that may be somewhat confusing at first. The following explanations should help if you haven’t had experience with SAP Queries: EE Work area All objects for SAP Queries can either be created in the global or local area. The global area stands for objects independent of clients and the local area for the client- dependent objects. A mixture of objects from both areas isn’t possible. |
第 76 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
EE InfoSet
An InfoSet views a data source. The InfoSet specifies which database tables are
provided, how they are linked with one another, and which fields can be used from
these tables in subsequent queries. An InfoSet can be used for any number of queries.
InfoSets are maintained in Transaction SQ02.
EE User group
Queries are bundled in a user group by logical association, for example, according to
a working group or specialist department. InfoSets are assigned to user groups that
are used by users to generate queries. A query is created in this case, but a user group
is required.
EE Queries
The actual queries are generated in the Query Painter. Fields from an InfoSet can be
assigned as selection fields or as output fields.
The first step is to create an InfoSet. However, there is a very comprehensive Info-
Set already provided for purchase orders in the global work area: /SAPQUERY/MEPO.
You can use the InfoSet /SAPQUERY/MEBANF for purchase requisitions.
1. Start Transaction SQ02, and make sure that you have chosen the global work
area. If required, you can navigate to the global work area via the Environ-
ment • QUERY Areas menu. Enter /SAPQUERY/MEPO as the name, and click on
Display.
2. You can now view all of the tables and fields available on the left-hand side (see
Figure 3.9). Get an initial overview, and exit the transaction again.
3. Start Transaction SQ01 (Information Systems • Ad hoc Reports • SAP Query
menu path). Switch the work area immediately if you haven’t done this already
in Step 1.
4. Because the query is only created for access from the purchase order and isn’t
supposed to be used by individual users directly in the SAP Query transactions,
you need a custom user group. Go to Environment • User Groups; enter the
name of a custom group, for example, ZME_QUERY; and click Create. Enter an
additional descriptive short text in the dialog window that opens, and click
Save.
76
© 2013 by Galileo Press Inc., Boston (MA)
第 77 页 / 共 275 页
Customizing the Document Overview in Purchase Requisitions or Purchase Orders 3.2
Figure 3.9 InfoSet /SAPQUERY/MEPO
5. Choose the Assign Users and InfoSets option. You can leave the list of assigned
users blank. No user will work directly with this group. It is called later via the
user exit. Choose instead the Assign InfoSets option in this dialog window.
Scroll to the entry /SAPQUERY/MEPO, and checkmark this line. Click Save. Now
go back three steps via Back ([F3]) until you are once again in the initial screen
of SAP Query.
6. In the title bar, you can now see that the user group already generated has been
directly selected. If this is not the group you want to use, you can change this
via menu path Edit • OTHER USER GROUP.
7. Now create a query. You can choose, for example, the name ZME_BEST. Then
click Create.
77
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
第 78 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
8. Select the InfoSet /SAPQUERY/MEPO by double-clicking in the dialog window that
appears.
9. You now need to enter a title in the following screen. This title appears as a
header when this selection is subsequently started. In the section Output for-
mat, activate the ABAP List option as well (see Figure 3.10).
Figure 3.10 Creating an SAP Query
10. Check whether the graphical Query Painter is activated via the Settings • Set-
tings menu. Finally, click on the Basic List button.
11. Select the fields on the left-hand side that are supposed to appear as a selec-
tion field and a list box in the selection variant. For this example, you can
mark the fields from Table 3.12, respectively.
78
© 2013 by Galileo Press Inc., Boston (MA)
第 79 页 / 共 275 页
Customizing the Document Overview in Purchase Requisitions or Purchase Orders 3.2
Field Name Description List Box Selection Field
EKKO-BEDAT Date of the purchasing X X
document
EKKO-BSTYP Document type X
EKKO-EBELN Document number X X
EKKO-EKGRP Purchasing group X
EKKO-ERNAM Name of person responsible X
EKKO-LIFNR Vendor number X X
EKPO-EBELP Item number X
EKPO-LOEKZ Deletion indicator X X
EKPO-MATNR Material number X X
Table 3.12 Field Selection for Query ZME_BEST
Note
If you want to use the selected documents via the ADOPT function of the docu-
ment overview or by double-clicking the document number, you must include at
least the following fields in a list box:
EE Purchase requisitions: EBAN-BANFN (purchase requisition number) and EBAN-
BNFPO (purchase requisition item).
EE Purchase orders: EKKO-BSTYP (document type), EKKO-EBELN (document num-
ber), and EKPO-EBELP (document item).
12. Save your selection, and then exit Query Painter via Back ([F3]).
13. You’re now back in the initial screen of the ZME_BEST query (see Figure 3.10).
Click Test ([Ctrl] + [F8]) to execute the report. Leave the query for a variant
empty in the dialog window that appears, and confirm the dialog window
using the [Enter] key.
14. Change the entry Max. Number of Hits to the value “250” in the General
Selections area to avoid unnecessary comprehensive selections later. Then,
click the disk icon to save a new variant. For example, enter ZME_BEST_STD as
the name of the variant and a meaning (see Figure 3.11). Now hide all of the
fields that aren’t directly required for the query. These are all the fields below
the Deletion Indicator field.
79
Personal Copy for Yang Meteor, user id a8103f58-81fe-4f49-acf6-cfb58959c618
| Field Name | Description | List Box | Selection Field |
|---|---|---|---|
| EKKO-BEDAT | Date of the purchasing document | X | X |
| EKKO-BSTYP | Document type | X | |
| EKKO-EBELN | Document number | X | X |
| EKKO-EKGRP | Purchasing group | X | |
| EKKO-ERNAM | Name of person responsible | X | |
| EKKO-LIFNR | Vendor number | X | X |
| EKPO-EBELP | Item number | X | |
| EKPO-LOEKZ | Deletion indicator | X | X |
| EKPO-MATNR | Material number | X | X |
| Note |
|---|
| If you want to use the selected documents via the ADOPT function of the docu- ment overview or by double-clicking the document number, you must include at least the following fields in a list box: EE Purchase requisitions: EBAN-BANFN (purchase requisition number) and EBAN- BNFPO (purchase requisition item). EE Purchase orders: EKKO-BSTYP (document type), EKKO-EBELN (document num- ber), and EKPO-EBELP (document item). |
第 80 页 / 共 275 页
3 User Exits and BAdIs in Purchasing
15. Now save the variant, and exit the query. You don’t need to enter the variant
as a standard variant. The assignment is made in the user exit.
Figure 3.11 Variant Attributes for Query ZME_BEST
Providing the Selection Variant in the Document Overview
After you’ve successfully created the new query, you must still integrate it into the
document overview. This happens via both user exits EXIT_SAPLMEQUERY_001 and
EXIT_SAPLMEQUERY_002.
80
© 2013 by Galileo Press Inc., Boston (MA)