0% found this document useful (0 votes)
764 views

How To Access Delivery Objects in S4H

The document discusses different ways to access "Delivery - Warehouse Request" objects in SAP S/4HANA, including using the appropriate access layer, APIs for read/write access, and service providers for write-only access. It provides examples of calling APIs and service provider methods to read and modify delivery object data.

Uploaded by

Ravan Menia
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
764 views

How To Access Delivery Objects in S4H

The document discusses different ways to access "Delivery - Warehouse Request" objects in SAP S/4HANA, including using the appropriate access layer, APIs for read/write access, and service providers for write-only access. It provides examples of calling APIs and service provider methods to read and modify delivery object data.

Uploaded by

Ravan Menia
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 22

PUBLIC

How to Access “Delivery – Warehouse Request”


Objects in EWM in SAP S/4HANA
Access Layers and APIs Including Coding Examples

SAP S/4HANA 1709 and higher


DOCUMENT HISTORY
Document Version Description

1.0 First official release of this guide

2
TABLE OF CONTENTS
1 GLOSSARY ..................................................................................................................................... 4
2 ACCESSING EWM DELIVERY - WAREHOUSE REQUEST DATA .............................................. 5
2.1 Data Model of “Delivery - Warehouse Request” ......................................................................... 5
2.2 Using the Right Access Layer ...................................................................................................... 6
Application / UI Layer ..................................................................................................................... 6
Lower Level (you are not the LUW owner) .................................................................................. 6
2.3 Access for Read or Read/Write Access ....................................................................................... 7
Example of API Call for /SCWM/IF_API_WHR_OUTBOUND ...................................................... 8
2.4 Access for Write Access Only (SCDL Service Provider Layer) ............................................... 10
SCDL - Service Provider .............................................................................................................. 10
2.4.1.1 UI Service Providers ....................................................................................................................... 10
2.4.1.2 Delivery Service Provider ............................................................................................................... 11
Relation Between UI Service Provider and Delivery Service Provider ................................... 11
Aspects.......................................................................................................................................... 11
2.4.3.1 Example.......................................................................................................................................... 12
Delivery Service Provider Interfaces .......................................................................................... 13
Examples of Service Provider Calls ........................................................................................... 16
2.4.5.1 Some Method Calls of the Service Provider .................................................................................. 16
2.4.5.2 Sample Program to Change a Customer Field .............................................................................. 18

3
1 GLOSSARY

Term Definition

ABAP OO Advanced Business Application Programming, object-oriented


API Application programming interface
BO Business object (here usually a delivery)
BOPF Business Object Processing Framework
DR Delivery request
ESA Enterprise Service Architecture
ESF Enterprise Services Framework
FD Final delivery = outbound delivery
IDN Inbound delivery notification
LUW Logical unit of work
OD Outbound delivery
ODO Outbound delivery order
ODP Object data pattern
OIP Object identification pattern
PRD Processing delivery
SP Service provider
UI User interface
UIC User interface controller
WDP Web Dynpro pattern

4
2 ACCESSING EWM DELIVERY - WAREHOUSE REQUEST DATA
In EWM there are objects like outbound delivery orders, inbound deliveries, production material requests,
and posting changes, for example. The common name for these objects is “warehouse request” as they use
the same technical basis. They are distinguished by the document category (DOCCAT). For example, an
outbound delivery has the document category PDO while an inbound delivery has the document category
PDI.
In customer projects it may be required that such objects should be accessed in customer coding. In the
following, some guidelines are given on how to access them.
The focus will be on inbound and outbound deliveries as they are the objects that are used most frequently.

2.1 Data Model of “Delivery - Warehouse Request”


To get an understanding on how deliveries (= warehouse requests) should be accessed it is necessary to get
a picture of the underlying data model.
The warehouse request consists of a header and items where each of them includes further data (like
quantities, status, reference documents, dates / times, etc.). Most of this data is stored in database tables
(= persistent data). But some information is also only calculated on the fly and is not stored on the database
(= transient data).
Examples are:
• Persistent data: The product of an item or the delivery date is stored persistent on the database
• Transient data: Some quantities like the packed quantity or the picked quantity as well as the
corresponding status are not stored on the database but calculated on the fly.
The EWM warehouse request objects make usage of the so called Business Object Processing Framework
(BOPF). This contains determinations and validations which determine status or quantities, for example, and
validate whether data which is entered is valid.
This difference in persistent and transient data has important implications on how data should be accessed.
These are the following:
• For data changes, a direct database access is forbidden. The reason is that potentially necessary
determinations or validations that require the BO layer are not performed.
For reading purposes, it is also not recommended because transient data changes that may already
exist in the BO layer are not considered, for example.
• Another reason is that dependent on the context, different database tables may be used and a caller
usually does not know (and should not need to know) where the data is stored.
• Calculation of transient data consumes runtime. Therefore, unnecessary calculations should be
avoided. This can be done by using appropriate interfaces and usage of control parameters.
• In case BOPF is used and busines objects (BOs) are created this also results in a higher memory
consumption. This has to be considered especially in case functions are planned that may read
mass data.
As described, all determinations to calculate transient delivery data is done using BOPF. For this, the
delivery processing reads the database data, creates business object instances for the deliveries, and then
BOPF does the determination and validations on them. This is usually only necessary if delivery data is
created or changed, as only here all determinations and validations are required. For a simple read access,
in many cases the calculations using BOPF and the creation of delivery BO instances is not required. Figure
2-1 shows an overview of the delivery layers.

5
Application Layer / UI Layer Delivery
Pattern UI Layer

ServiceMethods Layer /SCWM/-Service Provider


(methods
/SCWM/IF_API_WHR_OUTBOUND,
Layer
/SCWM/IF_TM,
/SCWM/CL_DLV_MANAGEMENT_PRD->QUERY, (UI ServiceAdaptation e.g. classes
like /SCWM/CL_SP)
Read / Write Access

/SCDL/-Service Provider Layer


Read only access

(ServiceAdaptation e.g. classes like /SCDL/CL_SP)

Read / Write Access

BO-Layer (Business Object Layer).

Delivery / Warehouse Request Object instances like /SCDL/CL_DL_HEADER, are used


(also here determination and validations using BOPF take place)

Database Layer
(Database tables of delivery – Warehouse Request)

Restricted Access Layer


Proposed Access Layer Non Proposed Access Layer (only for access within Top Layer (LUW Owner)
BOPF BadIs)

Figure 2-1 Delivery - Warehouse Request Layers


Figure 2-1 also shows which access layers should be used and which should not be used.

2.2 Using the Right Access Layer


To ensure functional correctness and optimal performance, it is important to understand the layer concept of
the delivery and to use the right access layer. This is especially important because the use of the wrong layer
can cause problems/inconsistencies in different situations/BAdIs/implementations.

Application / UI Layer
In most cases you intend to create an own UI or report. This means you are on the application or UI layer
and you control the logical unit of work (LUW).
For such cases you should use the service methods layer or the SCDL - service provider layer. Which one is
more appropriate depends on whether you intend to only use a read-only access or a write access (to
change or create data).
On this layer, you are not allowed to use the Business Object (BO) layer or the database layer.

Lower Level (you are not the LUW owner)


Your code is called by standard SAP applications as well as your own main programs as described in 2.2.1.
Another use case is that your code is called as part of an SAP standard application as well as your own main
programs as described in chapter 2.2.1. This applies when you implement a BAdI, for example. In such
cases you must be very careful not to influence the standard behavior. In general, you should use an API
which is on the same access layer.
For example, if you are implementing a BAdI which is contained in the delivery BOPF/BO layer (such as the
BAdI /SCWM/EX_DLV_DET_AFTER_CHANGE), then the usage of the BO layer may be necessary (for

6
example to compare different states). The use of the service provider (SP) or other APIs which use the
service provider (like the warehouse request QUERY) is not recommended here and must not be used.

2.3 Access for Read or Read/Write Access


As mentioned before, it makes a difference whether the delivery / warehouse request is accessed using the
BO / BOPF layer or not.
In general, you should use the service methods layer using APIs. Depending on the API, they offer the
possibility to control whether BOPF / BO instances should be used (which calculate all data and which are
also required for write access) or not. This layer also partly offers functions to calculate transient data. You
can find further information in the documentation of the single APIs (for example corresponding constants
can also be found in /SCWM/IF_API_WAREHOUSE_REQUEST).
In general, these APIs are usually easier to consume as the SCDL service provider layer (which is described
in the next chapter). Therefore, it is recommended to first check if an API provides the required function
before the SCDL Service Provider is used.
The following APIs are available:
• See SAP Note “3115182 - Extended Warehouse Management - API's”.
Note that some of the APIs are only available from a certain SAP S/4HANA release on (for example
SAP S/4HANA 2020). In such a case use the described alternative APIs.
For example, the API /SCWM/IF_API_WHR_INBOUND for inbound deliveries is contained in here to access
inbound deliveries. The service interface offers for example methods like READ_DOCUMENT / READ_ITEMS or
QUERY_DOC / QUERY_ITEM which allows delivery data to be read in a fast and also convenient way.
For reading deliveries also method /SCWM/CL_DLV_MANAGEMENT_PRD->QUERY is available. As this method
contains many parameters it is recommended to use API /SCWM/IF_API_WHR_INBOUND or
/SCWM/IF_API_WHR_OUTBOUND instead. Only use /SCWM/CL_DLV_MANAGEMENT_PRD->QUERY if none
of the other APIs provides the required functions (or are not available yet in your SAP S/4
HANA release). Note that you must not use any other methods of class
/SCWM/CL_DLV_MANAGEMENT_PRD.
Documentation of the methods can be found in the method documentation in the system (use transaction
SE24, for example). The screenshot below shows how to display the documentation.

Method documentation

7
Example of API Call for /SCWM/IF_API_WHR_OUTBOUND
The following example is taken from the documentation of /SCWM/IF_API_WHR_OUTBOUND (note that this
API is only available from SAP S/4HANA 2020 on).
It firsts read and locks an outbound delivery document. Then it reduces all non-picked items to the lowest
possible quantity using a process code. This is similar to the “adjust quantity” action which can be found in
the delivery UI (transaction /SCWM/PRDO).
The following coding is a sample report which can be created using transaction SE38.

REPORT z_api_example_whr_outbound NO STANDARD PAGE HEADING.

DATA:
lo_transaction TYPE REF TO /scwm/if_tm,
lo_api_odo TYPE REF TO /scwm/if_api_whr_outbound,
lt_items_to_adjust TYPE /scdl/t_sp_k_item.

*----------------------------------------------------------------------*
* your selection screen definition
* Example:
PARAMETERS:
p_whno TYPE /scwm/lgnum OBLIGATORY,
p_docno TYPE /SCWM/SP_DOCNO_PDO OBLIGATORY,
p_pcode TYPE /scdl/dl_prcode DEFAULT 'O001'.
*----------------------------------------------------------------------*

*----------------------------------------------------------------------*
INITIALIZATION.
" get instance of API
/scwm/cl_api_factory=>get_service(
IMPORTING
eo_api = lo_api_odo ).
*----------------------------------------------------------------------*

*----------------------------------------------------------------------*
START-OF-SELECTION.

" initialize transaction manager and check warehouse number


lo_transaction ?= /scwm/cl_tm_factory=>get_service( /scwm/cl_tm_factory=>sc_manager ).
TRY.
lo_transaction->set_whno_w_check( p_whno ).
CATCH /scwm/cx_tm_check INTO DATA(lx_whno).
MESSAGE lx_whno TYPE 'E'.
ENDTRY.

TRY.
lo_api_odo->get_keys_for_bus_keys(
EXPORTING
it_whr_bus_keys = VALUE #( ( docno = p_docno ) )
IMPORTING
et_whr_keymap = DATA(lt_whr_keymap)
eo_message = DATA(lo_message_map) ).
IF lo_message_map IS BOUND AND
abap_true = lo_message_map->check( ).
DATA(ls_message_map) = lo_message_map->get_most_important_message( ).
MESSAGE ID ls_message_map-msgid TYPE 'E' NUMBER ls_message_map-msgno
WITH ls_message_map-msgv1 ls_message_map-msgv2 ls_message_map-msgv3 ls_message_map-
msgv4.
ENDIF.

" read and lock document


lo_api_odo->read_outbound_dlv_order_items(
EXPORTING
it_item_keys = CORRESPONDING #( lt_whr_keymap )
is_include = VALUE #( item_status = abap_true )
is_read_options = CORRESPONDING #( /scwm/if_api_warehouse_request=>sc_read_for_edit_doc )
is_locking = CORRESPONDING #( /scwm/if_api_warehouse_request=>sc_lock_for_whr_ui )
IMPORTING
et_headers = DATA(lt_headers)
et_items = DATA(lt_items)
eo_message = DATA(lo_message_lock) ).
IF lo_message_lock IS BOUND AND
abap_true = lo_message_lock->check( ).

8
DATA(ls_message_lock) = lo_message_map->get_most_important_message( ).
MESSAGE ID ls_message_lock-msgid TYPE 'E' NUMBER ls_message_lock-msgno
WITH ls_message_lock-msgv1 ls_message_lock-msgv2 ls_message_lock-
msgv3 ls_message_lock-msgv4.
ENDIF.

" your logic to decide input for API


" example:
LOOP AT lt_items ASSIGNING FIELD-SYMBOL(<ls_item>).
" something to adjust?
LOOP AT <ls_item>-status TRANSPORTING NO FIELDS
WHERE ( status_type = /scdl/if_dl_c=>sc_t_picking OR
status_type = /scdl/if_dl_c=>sc_t_planning_picking OR
status_type = /scdl/if_dl_c=>sc_t_split )
AND status_value CA '12'.
" some item is not yet completely picked and shall be reduced
APPEND VALUE #( docid = <ls_item>-docid itemid = <ls_item>-itemid ) TO lt_items_to_adjust.
EXIT.
ENDLOOP.
ENDLOOP.
IF lt_items_to_adjust IS INITIAL.
lo_transaction->cleanup( ).
MESSAGE ID 'YOUR_ID' TYPE 'S' NUMBER 123.
EXIT.
ENDIF.

lo_api_odo->adjust_item_quantities(
EXPORTING
it_item_keys = lt_items_to_adjust
iv_process_code = p_pcode
IMPORTING
et_result = DATA(lt_result)
eo_message = DATA(lo_message_adjust) ).
" check for errors is optional, SAVE does the SAVE of whatever was changed

lo_api_odo->save(
IMPORTING
eo_message = DATA(lo_message_save) ).

" your logic to


" - get the messages from the message collectors and write an
" application log if required
" - save additional data to DB that are not covered by EWM extensions

IF lo_message_save IS BOUND AND


abap_true = lo_message_save->check( ).
ROLLBACK WORK.
lo_transaction->cleanup( ).
ELSE.
COMMIT WORK AND WAIT.
lo_transaction->cleanup( ).
ENDIF.

CATCH /scwm/cx_api_faulty_call.
" happens for faulty calls
ROLLBACK WORK.
lo_transaction->cleanup( ).
ENDTRY.
*----------------------------------------------------------------------*

*----------------------------------------------------------------------*
END-OF-SELECTION.
* your logic to display result on screen, e.g. LT_RESULT or log
*----------------------------------------------------------------------*

9
2.4 Access for Write Access Only (SCDL Service Provider Layer)
The SCDL service provider layer can also be used for write access. This layer always creates BOPF/BO
instances. If only reading access should be done (and no BO instances got created before) then it is not
recommended to use this layer as it may consume too much runtime/memory compared to the APIs in the
service methods layer.
In the following chapters, you can find more detailed information about the SCDL service provider as well as
examples on how to use this provider.
Note: If you use functions or methods, make sure that you do not change the delivery data incorrectly. If you
change any fields, change only those fields whose meaning and dependencies you know precisely. Also,
you need to check if a change is allowed. For example, if you change a field which is not changeable in a UI
(as it is not foreseen to be changed) you must ensure that this does not cause side effects. Then you may
make usage of the field control and check which fields are changeable in SAP standard and which are not.

SCDL - Service Provider


The service provider is the external interface for the business object “Delivery”. Its task is to map the object-
oriented data model inside the business object “Delivery” to the aspect structure presented to the caller. The
aim is to provide a unified interface to callers to allow the business object to be used in a generic way.
Figure 2-1 shows the core service provider in the context of the general architecture of the delivery.
In EWM, there are multiple service providers. Therefore, it is necessary to differentiate between these
providers.

2.4.1.1 UI Service Providers


The service provider with prefix /SCWM/ is usually only used by (pattern) UIs. It is in the following also called
SCWM-Service Provider or UI-Service Provider. This means the methods are only used by pattern UIs.
Other UIs like Fiori Apps or WebDynpro do not make usage of them.
This is also called user interface controller or UI service adoption. It is only used by the UI. Here, only the
main /SCWM/ delivery UI service providers are mentioned. As the main focus of this document is not on the
UI, this is not described in more detail here. The following diagram shows the classes and the dependencies:

/SCMB/ /SCMB/ /SCMB/ /SCMB/ /SCMB/ /SCMB/


IF_SP_ACTION IF_SP_ASPECT IF_SP_LOCKING IF_SP_QUERY IF_SP_TRANSACTION IF_SP_VALUE_SET

/SCWM/CL_SP

/SCWM/CL_SP_DR /SCWM/CL_SP_PRD /SCWM/CL_SP_FD /SCWM/CL_SP_IM

/SCWM/ /SCWM/ /SCWM/


CL_SP_DR_OUT CL_SP_PRD_OUT CL_SP_IM_DR

/SCWM/ /SCWM/ /SCWM/


CL_SP_DR_INB CL_SP_PRD_INB CL_SP_IM_PC

/SCWM/ /SCWM/ /SCWM/


CL_SP_DR_EGR CL_SP_PRD_EGR CL_SP_IM_ST

The interfaces that the UI service provider implements (for example /SCMB/IF_SP_ASPECT) are similar to
the interfaces used in the delivery service provider (for example /SCDL/IF_SP1_ASPECT), but they are not
identical. Nevertheless, they use the same concepts. Therefore, the information about the delivery service
provider in the next chapters can also partly be reused for the UI service provider. Please keep in mind that
the focus is the delivery service provider mentioned in the next chapter and not the UI service provider.

10
2.4.1.2 Delivery Service Provider
In the following, the Service Provider in the /SCDL/ namespace is called Delivery Service Provider or SCDL-
Service Provider. The following diagram shows the classes and the relations.
/SCDL/ /SCDL/ /SCDL/ /SCDL/ /SCDL/ /SCDL/ /SCDL/
IF_SP1_ACTION IF_SP1_ASPECT IF_SP1_LOCKING IF_SP1_QUERY IF_SP1_TRANSACTION IF_SP_QUERY_ID IF_SP_BADI

/SCDL/CL_SP

/SCDL/CL_SP_DR /SCDL/CL_SP_FD /SCDL/CL_SP_PRD

/SCDL/ /SCDL/ /SCDL/ /SCDL/


/SCDL/CL_SP_FD_OUT
CL_SP_DR_OUT CL_SP_DR_INB CL_SP_PRD_INB CL_SP_PRD_OUT

Relation Between UI Service Provider and Delivery Service Provider


As described above, the service provider (SP) offers several methods to read, insert, update, and execute
actions, and so on, on a specific object (for example an outbound delivery order). Service providers exist for
all delivery objects (inbound delivery order or outbound delivery, for example). The service provider
instances contain the DOCCAT (PDO, FDO, for example). This means that if an outbound delivery is to be
changed, an instance of the service provider with DOCCAT=FDO must be used, while for an inbound
delivery order, for example, a service provider instance with DOCCAT=PDI must be used.
Both, UI-specific and delivery-object-specific service providers exist for the delivery service. The reason why
there are “UI” and “delivery-object” service providers is the following:
• In each delivery UI, the delivery may be structured differently (for example, fewer or more fields
compared to the data structure of the delivery).
• On the UI, specific checks should be done or additional UI-specific code needs to be executed.
The relationship between UI SP and delivery SP is the following:
• UI SP methods are only called from the UIs. Usually, UI methods call delivery SP methods to insert,
update, and so on.
• Delivery-SP methods can be called from multiple UIs as well as from code that is independent of UIs
(for example, RFC functions, batch jobs, etc.).
• The dependencies are described in more detail later on.

Aspects
One main term for the service provider is the “aspect”. An aspect can be described as a specific part of an
existing business object. For example, there is the aspect for products, containing the product, product ID,
product batch, and so on, or there is the aspect for dates, containing the date fields for the delivery item, for
example.
In Enterprise Service Architecture, there are two types of aspects: key aspects and aspects.
Key aspects hold the semantic key of an aspect row, which is not necessarily the syntactical key in the
database. Therefore, each aspect must have one associated key aspect. A key aspect is its own key aspect.
The usual naming convention for service providers is:
Table types
• /SCDL/T_SP_K_* or /SCWM/T_SP_K_* Key aspect
• /SCDL/T_SP_A_* or /SCWM/T_SP_A_* Aspect
Structure types

11
• /SCDL/S_SP_K_* or /SCWM/S_SP_K_* Key aspect
• /SCDL/S_SP_A_* or /SCWM/S_SP_A_* Aspect
• /SCDL/S_SP_D_* or /SCWM/S_SP_D_* Text aspect data
• /SCDL/S_SP_Q_* or /SCWM/S_SP_Q_* Query parameter
Constants
All constants defined to substitute the Enterprise Service Framework are defined in the interfaces
/SCDL/IF_SP_C and /SCWM/IF_SP_C.
Note that /SCWM/IF_SP_C contains the constants for the EWM UIs as well as the constants for the EWM
extension of SCDL.

2.4.3.1 Example
The data model for the outbound delivery order header contains a 1:n relation to dates. That means one
delivery header can have multiple dates like out-of-yard date, delivery date, etc.
The corresponding aspect would be
/SCDL/IF_SP_C=> SC_ASP_HEAD_DATE (fixed value ‘/SCDL/S_SP_A_HEAD_DATE')
The structure of the aspect would be /SCDL/S_SP_A_HEAD_DATE (as in the constant above)
And the table type (as 1:n relation) /SCDL/T_SP_A_HEAD_DATE
The aspect (structure) itself consists of the header date aspect key and the “data” fields. As the header date
aspect is an aspect of the header, it contains the header aspect key and the date keys. The header aspect
key identifies the delivery (header), while the date keys identify the date (showing, for example, whether it is
an out-of-yard date or a delivery date).
The following screenshot shows the outbound delivery order UI (transaction /SCWM/PRDO).
The following example shows the relation between the aspects of UI and SCDL.

(Note that these are the aspects of the UI service provider)

The aspect for the header dates contains


ASPECT /SCWM/S_SP_A_HEAD_DATE

12
.INCLUDE /SCDL/S_SP_K_HEAD_DATE Key Aspect: Header Dates/Times
TSTCATEGORY_TXT /SCWM/SP_TSTCATEGORY_TXT Date/Time Category
TSTTYPE_TXT /SCWM/SP_TSTTYPE_TXT Date/Time Type
TZONE /SCDL/DL_TZONE Time Zone
DATE DATS Field of type DATS
TIME /SCWM/SP_TIME Time
DYNAMIC /SCDL/DL_DYNAMIC Indicator: Dynamic and Non-Persistent
DATE_INDICATOR /SCDL/DL_INDICATOR Value Determination Indicator

The above key aspect /SCDL/S_SP_K_HEAD_DATE contains the following fields:


Aspect /SCDL/S_SP_K_HEAD_DATE
.INCLUDE /SCDL/S_SP_K_HEAD Key Aspect: Header
DOCID /SCDL/DL_DOCID Document ID
.INCLUDE /SCDL/DL_DATE_KEY_STR Date/Time Key
TSTTYPE /SCDL/DL_TSTTYPE Date/Time Type
TST_CATEGORY /SCDL/DL_TST_CATEGORY Date/Time Category

That means that the aspect key for header dates contains the header key aspect (/SCDL/S_SP_K_HEAD)
as well as the date aspect keys (/SCDL/DL_DATE_KEY_STR). Together, both identify one entry (line in the
UI) for a delivery header date.
The aspect /SCWM/S_SP_A_HEAD_DATE also contains the “data” information such as date, time, etc. It
displays only fields such as the date/time category short text. This information is displayed in the
/SCWM/PRDO UI, for example.
In the delivery SP, the aspects are different. For the same date header, they are as follows:
ASPECT /SCDL/S_SP_A_HEAD_DATE
.INCLUDE /SCDL/S_SP_K_HEAD_DATE Key Aspect: Header Dates/Times
.INCLUDE /SCDL/DL_DATE_DATA_STR Date/Time Data Fields
.INCLUDE /SCDL/DL_DATE_DB_STR Date/Time, Database Fields
.INCLUDE /SCDL/DL_TST_STR Date/Time (Interval)
TZONE /SCDL/DL_TZONE Time Zone
TSTFR /SCDL/DL_TSTFR Start Date/Time
TSTTO /SCDL/DL_TSTTO End Date/Time
DATE_INDICATOR /SCDL/DL_INDICATOR Value Determination Indicator
DYNAMIC /SCDL/DL_DYNAMIC Indicator: Dynamic and Non-Persistent

This already shows that a conversion between the two aspects is necessary. This is done in the UI SP. The
UI SP also “enhances” the aspects by the short text, for example, or does additional checks.

Delivery Service Provider Interfaces

The service providers implement multiple interfaces. The following gives a short overview.
/SCDL/IF_SP1_ACTION Allows Actions
EXECUTE Execute action

/SCDL/IF_SP1_ ASPECT Allows Operations on Aspects

13
SELECT Read
INSERT Insert
UPDATE Update
DELETE Delete
SELECT_BY_RELATION Read by relation

/SCDL/IF_SP1_LOCKING locking service


LOCK Lock aspect lines
UNLOCK Unlock aspect lines

/SCDL/IF_SP1_QUERY Query Interface


EXECUTE Executes a QUERY

/SCDL/IF_SP1_TRANSACTION Access Interface


BEFORE_SAVE Event before SAVE, check for consistency
CLEANUP Clean up, release all locks
SAVE Save accumulated changes

Note

The actions of /SCDL/IF_SP1_TRANSACTION do not only affect the delivery object of the DOCCAT of
the service provider that is used, but all other delivery objects.
This means if you call the CLEANUP method on a service provider for DOCCAT=PDI, this will also
clear DOCCATs for FDO, PDO, ODR, etc.

/SCDL/IF_SP_QUERY_ID Query by IDs


QUERY_DOCID Search for Header (GUID)
QUERY_DOCNO Search for Header (Number)
QUERY_MAPKEY Key Allocation
QUERY_DOCFLOW Search for Document Flow

These methods are implemented very generically. Usually, they do not contain specific data types but are of
the type STRING, ANY or TABLE. This is necessary because the data types depend on the aspect and/or
service provider instance used, for example. The specific data types can easily be found based on the
aspect name and the above-mentioned naming conventions.

/SCDL/IF_SP1_QUERY~EXECUTE
QUERY Importing STRING Name of the query. For example
/scdl/if_sp_c=>sc_qry_head or
/scdl/if_sp_c=>sc_qry_item

OPTIONS Importing /SCDL/S_SP_QUERY_OPTIONS Query options. For example read only headers, lock result,
sorting
SELECTIONS Importing /SCDL/T_SP_SELECTION Selections

14
OUTRECORDS Exporting INDEX TABLE Data type depends on QUERY. For example, header aspect
(/scdl/t_sp_a_head) is returned for a header query
(scdl/if_sp_c=>sc_qry_head).
REJECTED Exporting BOOLE_D Exception indicator

/SCDL/IF_SP1_ASPECT~UPDATE
ASPECT Importing STRING Aspect to update. For example
/SCDL/IF_SP_C=>SC_ASP_HEAD or
/SCDL/IF_SP_C=>SC_ASP_HEAD_PARTYLOC
INRECORDS Importing INDEX TABLE Entries to be changed. Data type must correspond to the above
aspect.
OUTRECORDS Exporting INDEX TABLE Entries after the change. Data type must correspond to the
above aspect. Usually 1:1 to INRECORDS, but could differ if
update was not possible or determinations were executed, for
example.
REJECTED Exporting BOOLE_D Exception indicator (Whole call failed. Usually caused by the
caller.)
RETURN_CODES Exporting /SCDL/T_SP_RETURN_CODE Success and failure information about each input line.

15
Examples of Service Provider Calls
This chapter provides some examples of how the delivery service provider is used in the code.
The following is an example of how a service provider is instantiated and how it is used to read and change
data.

Note:
• The description of functions and methods in this document does not mean that these
functions/methods are released by SAP or that SAP guarantees that they will be kept stable. SAP
may change/remove them without notice. Also, do not use any other methods or parameters from
the classes/interfaces mentioned. For example, /SCWM/IF_TM has many other methods. Only use
the methods mentioned in this document.
• The methods, functions, and classes mentioned in this document are not official programming
interfaces and are not released for customers/partners. They can be changed or deleted by SAP at
any time without prior/further notice. Any use is at your own risk.

2.4.5.1 Some Method Calls of the Service Provider

DATA:
lo_sp TYPE REF TO /scdl/cl_sp_prd_out,
lo_message_box TYPE REF TO /scdl/cl_sp_message_box,
ls_action TYPE /scdl/s_sp_act_action,
ls_sp_k_head TYPE /scdl/s_sp_k_head,
lt_sp_k_head TYPE /scdl/t_sp_k_head,
lt_a_head TYPE /scdl/t_sp_a_head,
ls_a_head_out TYPE /scdl/s_sp_a_head,
lt_a_head_incoterms_out TYPE /scdl/t_sp_a_head_incoterms,
lt_a_head_incoterms TYPE /scdl/t_sp_a_head_incoterms,
ls_a_head_incoterms TYPE /scdl/s_sp_a_head_incoterms,
lt_a_head_partyloc TYPE /scdl/t_sp_a_head_partyloc,
lt_a_head_partyloc_out TYPE /scdl/t_sp_a_head_partyloc, Create a service provider instance to
lt_a_item TYPE /scdl/t_sp_a_item, handle outbound delivery orders
lv_rejected_tmp TYPE boole_d,
lv_rejected TYPE boole_d, (DOCCAT = PDO).
lt_return_codes TYPE /scdl/t_sp_return_code,
lt_messages TYPE /scdl/dm_message_tab.
The attribute handler is only needed if the
CREATE OBJECT lo_message_box. field control should be determined and
CREATE OBJECT lo_sp
active. For example, to be able to
EXPORTING determine whether fields are changeable
* io_attribute_handler = lo_attribute_handler or not.
io_message_box = lo_message_box
* io_message_handler = lo_message_handler
iv_doccat = /scdl/if_dl_doc_c=>sc_doccat_out_prd
iv_mode = /scdl/cl_sp=>sc_mode_classic. Any messages issued are
stored in the message box.
CLEAR ls_sp_k_head.
ls_sp_k_head-docid = '00000000000000168042000000000000'.
APPEND ls_sp_k_head TO lt_sp_k_head.
Define an order to be read.
lo_sp->select(
EXPORTING
inkeys = lt_sp_k_head
aspect = /scdl/if_sp_c=>sc_asp_head
* OPTIONS Read the order (the order BO
IMPORTING instance is created with all items and
outrecords = lt_a_head data in the background).
rejected = lv_rejected
return_codes = lt_return_codes ).

lo_sp->select_by_relation( Read the items for the order header.


EXPORTING Note that this only returns the items
relation = /scdl/if_sp_c=>sc_rel_head_to_item that were read before with a
inrecords = lt_sp_k_head
aspect = /scdl/if_sp_c=>sc_asp_head SELECT or QUERY method.
* OPTIONS
IMPORTING
outrecords = lt_a_item

16
rejected = lv_rejected
return_codes = lt_return_codes ).

* get incoterms
lo_sp->select( Read detail data of an object
EXPORTING (Incoterms of an order header in this
inkeys = lt_sp_k_head
aspect = /scdl/if_sp_c=>sc_asp_head_incoterms
case).
IMPORTING
outrecords = lt_a_head_incoterms
rejected = lv_rejected_tmp
return_codes = lt_return_codes ).
This example shows how the
lo_sp->lock( EXPORTING inkeys = lt_sp_k_head (complete)order is locked.
aspect = /scdl/if_sp_c=>sc_asp_head
lockmode = /scdl/if_sp1_locking=>sc_exclusive_lock
IMPORTING rejected = lv_rejected
return_codes = lt_return_codes ).

lo_sp->insert(
EXPORTING
inrecords = lt_a_head_partyloc Here, an additional party/location is
aspect = /scdl/if_sp_c=>sc_asp_head_partyloc
relation = /scdl/if_sp_c=>sc_rel_head_to_partyloc
added on header level. As a header
relation_inkey = ls_sp_k_head can contain multiple parties/locations
IMPORTING (1:n), this uses a relation.
outrecords = lt_a_head_partyloc_out
relation_outrecord = ls_a_head_out
rejected = lv_rejected_tmp
return_codes = lt_return_codes ).

lo_sp->update(
EXPORTING
inrecords = lt_a_head_incoterms Here, a 1:n aspect of the header is
aspect = /scdl/if_sp_c=>sc_asp_head_incoterms updated.
IMPORTING
outrecords = lt_a_head_incoterms_out
rejected = lv_rejected_tmp
return_codes = lt_return_codes ).

ls_action-action_code = /scdl/if_bo_action_c=>sc_determine.
lo_sp->execute(
EXPORTING Here, an action is executed on
aspect = /scdl/if_sp_c=>sc_asp_head
inkeys = lt_sp_k_head
header level. In this example, the
inparam = ls_action generic action “execute action” is
action = /scdl/if_sp_c=>sc_act_execute_action used to execute the BOPF action
IMPORTING “determine”.
outrecords = lt_a_head
rejected = lv_rejected_tmp
return_codes = lt_return_codes ).

* add messages
IF lv_rejected = abap_true.
Get any detailed messages issued
lt_messages = lo_message_box->get_messages( ). during the service provider calls. In
ENDIF. the example, this is only done if a
major failure occurred (usually
RETURN_CODES should also be
evaluated).

17
2.4.5.2 Sample Program to Change a Customer Field
The above code examples do not contain a proper error handling. The return values and parameters should
usually be checked after an SP call. Only then should the data be saved. The following sample program
shows customer data may be changed.

Note: The program does not contain any checks (such as status checks) if a change of the delivery is
allowed, for example. A delivery for which a GI has been posted should usually never be changed, for
instance.
In the example, a customer-specific field is changed. It is very dangerous to change any other SAP fields
because you usually do not know whether a field change is allowed and, if so, when and how. Neither can
you be aware of the consequences of such a change. For example, if execution has started, changing might
lead to problems in the process. The same applies to actions or other methods. For example, the service
provider will allow you to change the product or the quantity, or delete items. But without knowing the exact
effects and consequences of these changes/actions, it is very dangerous to use them.
The report uses the statement SET_WHNO. If you are using SAP S/4HANA 2020 and higher, we suggest to
use SET_WHNO_W_CHECK as shown in chapter 2.3.1

REPORT ZUPDATE_HEADER_EEW_DATA.

* This sample program shows how one an outbound delivery order (ODO)
* a customer-specific field (Z_ZUSATZ) is filled/changed.
* The program does a locking and reading of the data
* it then changes the EEW field
* the program also contains error handling
* It also considers validation errors
* based on if errors occurred or not it saves or rejects (ROLLBACK) the changes.
* The program uses the delivery service provider (SP).
* The program is meant to be used as a separate program, so not to be used inside a BADI or
* other already running programs (as the setting of the warehouse/save/rollback will destroy a runni
ng LUW/transaction)

* Note: The program is only for demo purpose. It is not meant for any
* productive usage.

PARAMETERS:
p_docno TYPE /scwm/sp_docno_pdo OBLIGATORY,
p_whno TYPE /scwm/lgnum OBLIGATORY.

DATA:
lo_sp TYPE REF TO /scdl/cl_sp_prd_out,
lo_message_box TYPE REF TO /scdl/cl_sp_message_box,
lt_a_head TYPE /scdl/t_sp_a_head,
lt_sp_k_head TYPE /scdl/t_sp_k_head,
ls_sp_k_head TYPE /scdl/s_sp_k_head,
lt_a_head_eew TYPE /scdl/t_sp_a_head_eew_prd,
lt_a_head_eew_out TYPE /scdl/t_sp_a_head_eew_prd,
ls_sp_action TYPE /scdl/s_sp_act_action,
lt_no TYPE /scdl/dl_no_tab,
lt_sp_a_mapkey TYPE /scdl/t_sp_a_mapkey,
lv_rejected TYPE boole_d,
lv_error_occured TYPE boole_d,
lv_validation_error_occured TYPE boole_d,
lo_tm TYPE REF TO /scwm/if_tm,
lt_return_codes TYPE /scdl/t_sp_return_code,
lt_validation_messages TYPE /scdl/dm_message_tab,
lt_messages TYPE /scdl/dm_message_tab.

FIELD-SYMBOLS:
<ls_a_head_eew> TYPE /scdl/s_sp_a_head_eew_prd,
<ls_messages> TYPE /scdl/dm_message_str.

* create service provider for processing delivery and and message box
* the service provider is not used here for a UI (so no attribute handler is used)
CREATE OBJECT lo_message_box.

CREATE OBJECT lo_sp


EXPORTING
io_message_box = lo_message_box

18
iv_doccat = /scdl/if_dl_doc_c=>sc_doccat_out_prd
iv_mode = /scdl/cl_sp=>sc_mode_classic.

* set warehouse that is used


" initialize transaction manager and check warehouse number
lo_tm ?= /scwm/cl_tm_factory=>get_service( /scwm/cl_tm_factory=>sc_manager ).
lo_tm->set_whno( p_whno ).

* get keymaps (only necessary if you want to map from the document number to the DOCID
lt_no = VALUE #( ( docno = p_docno doccat = /scdl/if_dl_doc_c=>sc_doccat_out_prd ) ).
lo_sp->query_mapkey(
EXPORTING
it_no = lt_no
IMPORTING
et_keymap = lt_sp_a_mapkey
ev_rejected = lv_rejected ).
IF lv_rejected = abap_true OR lines( lt_sp_a_mapkey ) <> 1.
lv_error_occured = abap_true.
* handle error that document number was not found or more then one entry
ELSE.
* fill GUID of delivery header
CLEAR ls_sp_k_head.
ls_sp_k_head-docid = lt_sp_a_mapkey[ 1 ]-docid. .
APPEND ls_sp_k_head TO lt_sp_k_head.
ENDIF.

* try to lock (also creates the delivery instance immediately)


CLEAR lt_return_codes.
CLEAR lv_rejected.
IF lv_error_occured = abap_false.
lo_sp->lock(
EXPORTING
inkeys = lt_sp_k_head
aspect = /scdl/if_sp_c=>sc_asp_head
lockmode = /scdl/if_sp1_locking=>sc_exclusive_lock
IMPORTING
rejected = lv_rejected
return_codes = lt_return_codes ).

* check if any error occurred


READ TABLE lt_return_codes TRANSPORTING NO FIELDS WITH KEY failed = abap_true.
IF sy-subrc = 0 OR lv_rejected = abap_true.
lv_error_occured = abap_true.
ENDIF.
ENDIF.

* if no error so far...
IF lv_error_occured = abap_false.
* select customer fields EEW for the delivery
CLEAR lt_return_codes.
CLEAR lv_rejected.
lo_sp->select(
EXPORTING
inkeys = lt_sp_k_head
aspect = /scdl/if_sp_c=>sc_asp_head_eew_prd
* OPTIONS
IMPORTING
outrecords = lt_a_head_eew
rejected = lv_rejected
return_codes = lt_return_codes ).

* check if any error occurred


READ TABLE lt_return_codes TRANSPORTING NO FIELDS WITH KEY failed = abap_true.
IF sy-subrc = 0 OR lv_rejected = abap_true.
lv_error_occured = abap_true.
ENDIF.

LOOP AT lt_a_head_eew ASSIGNING <ls_a_head_eew>.


* now fill the customer specific field Z_ZUSATZ
<ls_a_head_eew>-z_zusatz = '1'.
ENDLOOP.
ENDIF.

* if no error so far...
IF lv_error_occured = abap_false.
* update customer fields EEW for the delivery

19
CLEAR lt_return_codes.
CLEAR lv_rejected.
lo_sp->update(
EXPORTING
inrecords = lt_a_head_eew
aspect = /scdl/if_sp_c=>sc_asp_head_eew_prd
* OPTIONS
IMPORTING
outrecords = lt_a_head_eew_out
rejected = lv_rejected
return_codes = lt_return_codes ).

* check if any error occurred


READ TABLE lt_return_codes TRANSPORTING NO FIELDS WITH KEY failed = abap_true.
IF sy-subrc = 0 OR lv_rejected = abap_true.
lv_error_occured = abap_true.
ENDIF.

ENDIF.

* if no error so far...
IF lv_error_occured = abap_false.

* validate the delivery (also triggers determinations)


* this is an optional step. It is assumed in this example that if validation errors occur
* the delivery should not get saved.
* If also deliveries with validation errors (blocked status) should get saved,
* the error handling has to distinguish between validation errors and other errors
* validation error messages are in the message box and are not returned as REJECTED or RETURN_CODES

ls_sp_action-action_code = /scdl/if_bo_action_c=>sc_validate.
CLEAR lt_return_codes.
CLEAR lv_rejected.
lo_sp->execute(
EXPORTING
aspect = /scdl/if_sp_c=>sc_asp_head
inkeys = lt_sp_k_head
inparam = ls_sp_action
action = /scdl/if_sp_c=>sc_act_execute_action
IMPORTING
outrecords = lt_a_head
rejected = lv_rejected
return_codes = lt_return_codes ).

* check if any error occurred


READ TABLE lt_return_codes TRANSPORTING NO FIELDS WITH KEY failed = abap_true.
IF sy-subrc = 0 OR lv_rejected = abap_true.
lv_error_occured = abap_true.
ENDIF.
ENDIF.

* get all messages that occurred. Get the always as validation messages
* are also of interest
lt_messages = lo_message_box->get_messages( ).

* build two tables, one with validation messages and one with "real" errors
LOOP AT lt_messages ASSIGNING <ls_messages> WHERE consistency_message = abap_true.
APPEND <ls_messages> TO lt_validation_messages.
DELETE lt_messages.
ENDLOOP.

LOOP AT lt_messages TRANSPORTING NO FIELDS WHERE msgty CA 'EAX'.


lv_error_occured = abap_true.
EXIT.
ENDLOOP.

LOOP AT lt_validation_messages TRANSPORTING NO FIELDS WHERE msgty CA 'EAX'.


lv_validation_error_occured = abap_true.
EXIT.
ENDLOOP.

* now save delivery dependant on if error occurred or not.


* here validation errors are also considered. This depends on the business logic.

IF lv_error_occured = abap_false AND lv_validation_error_occured = abap_false.

20
CLEAR lt_return_codes.
CLEAR lv_rejected.
lo_sp->save( IMPORTING rejected = lv_rejected ).

* check if during save serious errors occurred.


IF lv_rejected = abap_true.
lv_error_occured = abap_true.

* if errors occurred then get the messages again


lt_messages = lo_message_box->get_messages( ).
ENDIF.
ENDIF.

* now do a commit (here with wait) or rollback dependant on if errors occurred or not
IF lv_error_occured = abap_false AND lv_validation_error_occured = abap_false.
COMMIT WORK AND WAIT.
lo_tm->cleanup( ). "clear buffers and release locks
ELSE.
ROLLBACK WORK.
lo_tm->cleanup( ). "clear buffers and release locks
ENDIF.

* now for example, messages could be displayed

21
www.sap.com/contactsap
© 2022 SAP SE or an SAP affiliate company. All rights reserved.
No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of SAP SE or an SAP affiliate company.

The information contained herein may be changed without prior notice. Some software products marketed by SAP SE and its distributors contain proprietary software components of other software vendors.
National product specifications may vary.

These materials are provided by SAP SE or an SAP affiliate company for informational purposes only, without representation or warranty of any kind, and SAP or its affiliated companies shall not be liable for
errors or omissions with respect to the materials. The only warranties for SAP or SAP affiliate company products and services are those that are set forth in the express warranty statements accompanying such
products and services, if any. Nothing herein should be construed as constituting an additional warranty.

In particular, SAP SE or its affiliated companies have no obligation to pursue any course of business outlined in this document or any related presentation, or to develop or release any functionality mentioned
therein. This document, or any related presentation, and SAP SE’s or its affiliated companies’ strategy and possible future developments, products, and/or platform directions and functionality are all subject to
change and may be changed by SAP SE or its affiliated companies at any time for any reason without notice. The information in this document is not a commitment, promise, or legal obligation to deliver any
material, code, or functionality. All forward-looking statements are subject to various risks and uncertainties that could cause actual results to differ materially from expectations. Readers are cautioned not to
place undue reliance on these forward-looking statements, and they should not be relied upon in making purchasing decisions.

SAP and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries.
All other product and service names mentioned are the trademarks of their respective companies. See www.sap.com/trademark for additional trademark information and notices.

You might also like