ABAP Development for Materials Management in SAP (第3页)

第 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)

返回ABAP参考资料列表