Skip to Content

Dangerous Liaisons in User-Exits – Revisited


It seems that my first blog about organizing Function Module-Exits (CMOD / SMOD) touched a sore point looking at the lively discussion that followed after its publication. Whereas I suggest to organize the exits in independent function groups others proposed to use BAdI like technologies (e.g. Implementing a BAdI in an enhancement Project (CMOD)). My major objections against this proposal are:

  • Using interfaces does not really increase transparency in case of the Multiple-Use exits
  • We should not mix two different kinds of Exit-technologies 

The latter point does not imply that we should refrain from using ABAP-OO within Function Module-Exits as you will see below.


Lindt UK: EDI vs. Retail Orders

Customers of Lindt UK sending their purchase orders via EDI are obliged to order our delicious chocolate products in so-called cases (= traded units, e.g. a box of chocolate bars) instead of consumer units (e.g. a single chocolate bar).

Example: 1 Case = 20 Consumer Units, i.e. a box of chocolate bar contains 20 bars.

If nevertheless a customer orders in consumer units the ordered quantity is calculated in cases within a user-exit (using fm MATERIAL_UNIT_CONVERSION).

Recently Lindt UK opened up a couple of LindtShops where the products are sold in consumer units. The shop sales are sent via EDI to the R/3 system where it creates (Retail) sales orders containing the quantities in consumer units. EDI orders and Retail orders can be distinguished based on the order type (AUART).


Below you see the package ZCMOD in the R/3 system of Lindt UK. Already at a glance we see that

  • a User-Exit has been implemented for SD-EDI
  • two different requirements have been implemented (EDI vs. Retail) 

Lindt UK: Package ZCMOD


The implementation of this User-Exit is simple and straightforward:

  • The Frame User-Exit ZEXIT_SAPLVEDA_011 is called within include ZXVEDU13 (not shown)
  • If the order type belongs to Retail we call fm ZEXIT_SAPLVEDA_011_RETAIL
  • ELSE we call fm ZEXIT_SAPLVEDA_011_EDI



A few months after implementing this User-Exit Lindt UK came up with a new Retail order type. A quick look at the TOP-include of the User-Exit function group revealed that I just had to add a single line of coding in order to take this new Retail order type into account. TOP-include of User-Exit Function Group


Lindt Italy (IT): Default vs. EDI Invoices

Lindt IT sends its outbound invoices to two destinations:

  1. 3rd party sales system
  2. EDI customers (as EDIFACT messages)


Below you see the package ZCMOD in the R/3 system of Lindt IT. Already at a glance we see that

  • a User-Exit has been implemented for Billing Document Output
  • two different requirements have been implemented (Default vs. EDI) 

Lindt IT: Package ZCMOD


All outbound INVOIC IDocs are enhanced by default, irrespective of their destination.

Again, the implementation of this User-Exit is simple and straightforward:

  • The Frame User-Exit ZEXIT_SAPLVEDF_002 is called within include ZXEDFU02 (not shown)
  • All outbound invoices pass fm ZEXIT_SAPLVEDF_002_DEFAULT
  • In addition, invoices for EDI customers pass fm ZEXIT_SAPLVEDF_002_EDI



Outbound invoices for EDI customers are well defined by their output attributes. The User-Exit service class ZCL_EXIT_SAPLVEDF_002_SERVICES (nomen est omen!) provides two methods:

  • ADD_CONSUMER_UNITS_PER_TU: The base unit of the sold products is cases (= traded units). The ratio Traded Unit : Consumer Units (CU) is missing in the standard INVOIC02 Idoc yet required by the EDI customers.
  • ADD_CONSUMER_UNITS_EAN: The base unit of the sold products is cases (= traded units) and, therefore, the TU-EAN (European Article Number) appears in the INVOIC02 IDoc. However, the EDI customers require to receive the CU-EAN as well

These two methods are called within User-Exit ZEXIT_SAPLVEDF_002_EDI. Mapping of these enhanced INVOIC02 IDocs to EDIFACT D.96A INVOIC messages happens on SAP-XI where the additional data show up in the LIN, PIA and PRI segments.



Lindt Poland (PL): EDI Invoicing without β-blockers

Lindt PL is about to catch up with other Lindt companies in terms of EDI trading. Namely, they want to start EDI invoicing with several customers.


Below you see the package ZCMOD in the R/3 system of Lindt PL. Already at a glance we see that

  • many more User-Exits are implemented on this system
  • the same User-Exits are used by different Lindt companies (Switzerland, Spain, Poland, and – not yet implemented – Sweden)

Lindt PL: Package ZCMOD


And here is the implementation of this Multiple-Use User-Exit:

  • The Frame User-Exit ZEXIT_SAPLVEDF_002 is called within include ZXEDFU02 (not shown)
  • Depending on the client the company-specifc User-Exit is called (e.g. ZEXIT_SAPLVEDF_002_ES for Spain and ZEXIT_SAPLVEDF_002_PL for Poland)



The implementation of the EDI requirements in User-Exit ZEXIT_SAPLVEDF_002_PL is done by an external consultant mandated by Lindt PL. The User-Exit Framework ensures structural independence among the different Lindt companies on the same R/3 system. Despite the fact that external consultants are currently working on a business-critical User-Exit in our R/3 system I can sleep well without the need for any β-blockers (see my previous Dangerous Liaisons in User-Exits and How to Avoid Them).


Lindt Australia (AU): ToBeDone…

Lindt AU does not yet use any User-Exits (or to be more precise: I have not yet done the refactoring of existing User-Exits). However, you need little imagination to guess

  • what package you will find on the R/3 system of Lindt AU,
  • the naming convention of the User-Exits and
  • how they will be organized  



In this Weblog I have presented you the current benefits of the User-Exit Framework we are reaping among the Lindt companies. These benefits include:

  • High transparency of implemented User-Exits
  • High transparency of implemented requirements
  • Reusability of implementations due to recurring requirements among different Lindt companies
  • Structural independent implementation (resulting in a significant drop of sleepless nights…)

The User-Exit Framework consists of “old” technology (function groups and modules). However, this technology is highly sufficient for the structural organization of different requirements and Multiple-Use implementations of User-Exits. Yet as soon as the structural purpose is served I prefer to switch to ABAP-OO means, i.e. to implement the required services within methods. 



In the long-term my User-Exit Framework, based on function groups, is likely to be superseded by the Enhancement Framework. However, what remains is that a smart organization of Exits / Enhancements is a prerequisite for high transparency and reusability. Both factors will speed up your implementations and eventually will reduce the development costs.

You must be Logged on to comment or reply to a post.
  • Hi Uwe,

    Thanks for sharing. There are some take-aways from this approach.

    However, I feel BAdI's and/or an OO based solution would be more powerful than this approach. I don't understand why you would say that one shouldn't mix types of enhancement technologies. Even SAP itself has started including BAdI's in their EDI customer exits. Could you expand on this?




    • Dear Bruno

      Using BAdI's or OO-based approaches makes perfect sence if two preconditions are fulfilled:

      1. The BAdI receives all required information via the (method) signature and does NOT depend on knowledge about any global data variables of the User-Exit function group.
      2. The BAdI receives all required information via the (method) signature to distinguish between different SAP organizational units.

      While a solution has been described by Jeff Goldstein ("SAP User Exits and the People Who Love Them") to overcome such restrictions (1.) we all know that we should NOT do this.

      Regarding (2.) I will give you an example. Let us assume we have multiple companies (like Lindt UK & ZA) working in the same R/3 client. They co-exist as different company codes (BUKRS). Now we need to implement a user-exit for inbound EDI orders only for Lindt UK. If the interface provides us with the SalesOrg (VKORG) from the sales area then this information is sufficient to determine the company code (table TVKO). The BAdI itself could be implemented as filter-dependent.

      Best Regards


      • Hi again Uwe,

        Thanks for replying! However, I fail to understand the relation between the conditions you mentioned and your suggestion that one should not mix types of exit-technologies.

        I'm interested in knowing how you would deal with sales user-exits in MV45AFZZ in an international environment, without mixing types of exit-technologies...

        Thanks! Best,


        • Hello Bruno,

          FYI, there is an Enhancement Spot available as replacement for the MV45AFZZ user-exit routines - ES_SAP*45*.

          I know you had mentioned it as an example 🙂  



          • How can I find out, for example, what enhancement point CUA_SETZEN_13 in ES_SAPMV45A is for?

            Do you have any nice documentation about this kind of enhancements? I'm going through SAP's online documentation but it's not helping very much...




          • Hello Bruno,

            Unfortunately i don't have any documentation either, may there is some note somewhere which might help.

            I have not worked on SD too much. But once i was asked to code something in MV45AFZZ, & the subroutine i was asked to code already had some 1000 odd lines. So i started looking for alternative solutions & i came across these enh. spots. But my lead disapproved my idea & i had to (reluctantly) use the subroutine. 😡 His argument was not many people know they exist & it'll be difficult to trace 😐



          • And your lead was right! I have found some of these spots implemented in our system and I'm pretty sure no one else was aware 🙂

            Hence why I'm very curious about this and it's actually quite important for me to get to the bottom of this 🙂

            The more you know...



          • And how can I, for example, move all the requirement implementations from MV45AFZZ, for example move field to vbak, to the equivalent enhancement spot??

            You shouldn't have showed this to me 😀

            Thanks, best,