<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SAP Experts: VMware Virtualization &#124; Consulting &#124; Integration - DataXstream &#187; ABAP</title>
	<atom:link href="http://www.dataxstream.com/tag/abap/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dataxstream.com</link>
	<description>SAP Certified Consultants</description>
	<lastBuildDate>Sat, 04 Feb 2012 05:00:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>It&#8217;s SAP Upgrade Time!  Do You Know Where Your Customizations Are?  Part 2.</title>
		<link>http://www.dataxstream.com/2011/11/sap-upgrade-and-customizations-2/</link>
		<comments>http://www.dataxstream.com/2011/11/sap-upgrade-and-customizations-2/#comments</comments>
		<pubDate>Tue, 01 Nov 2011 14:15:43 +0000</pubDate>
		<dc:creator>Mike Salvo</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Upgrade Blog]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[ABAP Code Objects]]></category>
		<category><![CDATA[ABAP development]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[Mike Salvo]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[sap upgrade]]></category>
		<category><![CDATA[Upgrade]]></category>
		<category><![CDATA[upgrade cost]]></category>
		<category><![CDATA[upgrade risk]]></category>
		<category><![CDATA[upgrade tips]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=2983</guid>
		<description><![CDATA[In my last post on this topic, I discussed two negative effects of customizations in an upgrade project – risk and cost.  I also discussed an obvious reason to eliminate unnecessary customization – the mitigation of risk and cost. In this post, we will look at some of the customization areas which add risk and [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://www.dataxstream.com/2009/11/sap-upgrade-and-customizations-1/">last post</a> on this topic, I discussed two negative effects of customizations in an upgrade project – risk and cost.  I also discussed an obvious reason to eliminate unnecessary customization – the mitigation of risk and cost.</p>
<p>In this post, we will look at <em><span style="text-decoration: underline;">some</span></em> of the customization areas which add risk and the cost to an upgrade project.</p>
<p><span id="more-2983"></span></p>
<h3>1. Direct Modifications to SAP Standard Objects</h3>
<p>Direct modifications to SAP standard objects bear the highest risk.  During the upgrade, these modifications will be lose&#8211;either because they will be overwritten by their respective upgraded SAP standard objects; or because these objects no longer exist and are not used by standard SAP in the upgrade system.</p>
<p><strong> <span style="font-weight: normal; background-color: #ffffff;">Typically, there are two reasons for performing direct modifications to SAP standard objects:</span></strong></p>
<ol>
<li>The application of authorized individual OSS corrections to fix problems.</li>
<li>Direct customer modification to provide business process enhancements.</li>
</ol>
<h4 style="padding-left: 30px;">1.1. Application of Individual OSS Corrections and Support Packs</h4>
<p style="padding-left: 30px;">Individual OSS corrections are patches supplied by SAP to fix recognized problems with SAP objects.  Sometimes, individual OSS correction instructions are included and delivered within a specific level of support packs.   That means that applying support packs to the specified level will apply the desired correction, and manual intervention is not needed.  Sometimes OSS correction instructions are not yet included in any specific level of support packs, and these will need to be applied either manually or with the SAP Note Assistant.</p>
<p style="padding-left: 30px;">It is important to carefully analyze the validity range of an OSS note to determine both how it was applied in the legacy system, and how it is to be applied in the upgrade system.  This analysis will help determine how far to patch the upgrade system to make sure that the desired corrections are included in the upgrade system.   Any needed correction that exists at a patch level beyond the highest patch level in the upgrade system will need to be addressed  manually or with the SAP Note Assistant.</p>
<p style="padding-left: 30px;">The decision of which support pack levels should be applied to the upgrade system must be made carefully.  One approach is to apply the highest level of support packs that are available.    The rationale for applying the latest available support packs is to insure that the most recent problem fixes are applied to the upgrade system.  This is a two-edged sword, as the most recent  support packs may also introduce other problems into the upgrade system.</p>
<h4 style="padding-left: 30px;">1.2. Direct Customer Modification of SAP Standard Objects to Provide Business Process Enhancements</h4>
<p style="padding-left: 30px;">Direct modifications of SAP standard objects to provide enhancements are most costly and bear the highest level of risk.  While direct modifications of SAP standard objects may have been technically expedient at the time of implementing the enhancement, they will always require additional work effort and analysis at upgrade time to determine:</p>
<ol>
<li>Whether or not the functionality provided by the enhancement is still required by the business.</li>
<li>Whether or not the functionality provided by the enhancement is already included in the upgrade system as standard SAP.  You will need the help of functional subject matter experts here.</li>
<li>Whether or not the modified SAP object still exists in the upgrade system.</li>
<li>How to move these required enhancements into the customer namespace, using the SAP preferred enhancement procedures.  Moving these types of enhancements to the customer namespace also moves them from the very costly and highest risk category to a lower cost and lower risk category.</li>
</ol>
<h3>2. Custom Interfaces</h3>
<p>Custom interfaces are loaded with opportunity for high upgrade risk.  Take, for example, the SAP standard IDOC Basic Type, which was copied as the baseline for an enhanced customized basic type containing additional custom segments and fields.  In the upgrade system, a new version of this SAP standard IDOC Basic Type may now contain additional segments and fields.</p>
<p>Likewise, the associated standard processing module for that standard basic type, which was copied as the baseline for an enhanced processing module to handle the custom segments and fields of the enhanced custom basic type, may also have changed in the upgrade to accommodate the new standard IDOC version.</p>
<p>So, in the upgrade system, especially if you need to implement the new upgrade IDOC version, it may be necessary to start with the new standard basic type and standard processing module, and reapply the customizations.</p>
<h3>3. ABAP Code Objects</h3>
<p>Of all customized objects discovered in most SAP systems, ABAP Code objects are the most numerous.  These objects include classes, methods, function modules, report programs, dialog programs, and include files which support the all of the other ABAP object types.</p>
<p>At greatest risk are the SAP standard ABAP code objects which were modified directly in the SAP namespace; and those that were copied into the customer namespace and subsequently modified.<strong> </strong>This is because the standard SAP code objects may have changed in the upgrade.    These changes can range anywhere from simple error corrections to complete process and code redesigns.  In these instances, each modified object must be compared to its counterpart in the upgrade system to determine its existence, and the nature and extent of what might have changed.   If the customization is still needed in the upgrade system, and to stay current with the enhanced standard code, it is probably best to start with the upgrade standard code and reapply the customizations.</p>
<p>ABAP code objects that were developed entirely in the customer namespace (not copied from standard SAP code) are usually low on the risk ladder.  Problems occur when data selected by these objects has moved elsewhere or behaves differently in the upgrade system, when ABAP constructs used are now obsolete in the upgrade system, or when standard called functions are changed in the upgrade system.</p>
<p>Ultimately, the business must decide why SAP standard code was directly modified, why SAP standard code was copied into the customer namespace and modified, why custom code was developed entirely within the customer namespace, whether or not any of these modifications are needed, and how they might be implemented differently in the upgrade system.  This evaluation presents another opportunity to remove some rocks from the customization rock bag.</p>
<h3>4. Automated Standard SAP Transactions</h3>
<p>Custom ABAP programs which automate standard SAP transactions bear an above-average risk.  This is because the behavior of some SAP transactions may have changed in the upgrade.  These changes can be manifest in the functional performance of the transaction, the technical location and existence of data fields on screens, screen field properties, IMG configuration specific to the transaction, the transaction code associated with the transaction, or even the existence of the transaction or an equivalent in the upgrade system.  The nature and the extent of the changes to the transaction in the upgrade system will determine the amount of effort needed to automate it.</p>
<p>Also, if an “old” SAP transaction has been replaced by a “new” upgraded equivalent, it is usually wise to make the change to the new transaction at upgrade time.  At some point in the future, the “old” version of the transaction will become obsolete and no longer useable or supported.</p>
<h3>5. Data Dictionary Customizations</h3>
<p>Many customizing projects within SAP require the storage and manipulation of data that is not included in the standard SAP dictionary.   One way in which these requirements can be addressed is by building complete custom transparent tables and data structures.  Another way is by adding append structures and append fields to existing standard SAP tables.  With either approach, it is always an excellent idea to evaluate the need to move these customizations into the upgrade; and another opportunity to lighten the customizing bag of rocks.</p>
<h3>6. Customer and User Exits</h3>
<p>Customer and user exits are provided by SAP as the SAP-approved mechanism for enhancing standard functionality.  Enhancements performed within these boundaries are guaranteed by SAP to bear low technical risk in an upgrade situation.  While SAP guarantees that the custom code will arrive technically intact in the upgrade system, functional analysis must still be performed to determine the continued need for the enhancement in the upgrade system.</p>
<p>Any enhancement implemented in a customer or user exit that is either functionally covered or determined to be unnecessary in the standard upgrade system should be retired.  This is consistent with the goal of lightening the load in the bag of rocks.  Since a customer or user exits may implement several different enhancements, take extra care to make sure that only the right code or other objects are retired.</p>
<h3>7. The Environmental Effects &#8211; Operating System Change</h3>
<p>OK, changing the operating system during an upgrade project is not customization of SAP objects.  But it does add risk and cost to the project.</p>
<p>Why?</p>
<p>If the upgrade operating system changes from UNIX to Windows or vice versa, then any ABAP program or interface which reads or writes a data file to an operating system folder must be changed.  The changes needed to these ABAP programs are very narrow in scope,  and reflect the manner in which the operating system specifies its file paths.  Additional BASIS work, such as determining the proper file system authorizations, may also be needed.</p>
<p>Using the SAP logical file name facility can help enormously by removing the need to make changes to hard-coded file names and path names in many different ABAP programs.</p>
<h3>Share Your Experience</h3>
<p>At the top of this post, I stated that I would discuss <span style="text-decoration: underline;">some </span>of the customization areas which add risk and cost to an upgrade project.  I look forward to hearing from our readers to reply to this post with their own experience with customizations, how they were handled, and how this affected an upgrade project.</p>
<p>In my next post on this topic, I will reveal some of the techniques I use to &#8220;discover&#8221; customizations, even in the absence of documentation.</p>
<p style="padding-left: 30px; padding-right: 30px;"><em>[Editor's Note] This blog is the second of a multi-part series:</em></p>
<ol>
<li><a title="It’s SAP Upgrade Time!  Do You Know Where Your Customizations Are?  Part 1." href="http://www.dataxstream.com/2009/11/sap-upgrade-and-customizations-1/">Part 1</a></li>
<li><a href="http://www.dataxstream.com/2009/11/sap-upgrade-and-customizations-2/">Part 2</a></li>
<li>Part 3</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2011/11/sap-upgrade-and-customizations-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SAP Data Migration – Dealing With Fallout (Part 3)</title>
		<link>http://www.dataxstream.com/2010/08/sap-data-migration-dealing-with-fallout/</link>
		<comments>http://www.dataxstream.com/2010/08/sap-data-migration-dealing-with-fallout/#comments</comments>
		<pubDate>Thu, 26 Aug 2010 14:15:25 +0000</pubDate>
		<dc:creator>Mike Salvo</dc:creator>
				<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Functional]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[ALE]]></category>
		<category><![CDATA[Basis/Netweaver]]></category>
		<category><![CDATA[Data Migration]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[Integration]]></category>
		<category><![CDATA[Mike Salvo]]></category>
		<category><![CDATA[NetWeaver]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[SAP ABAP]]></category>
		<category><![CDATA[upgrades]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=5591</guid>
		<description><![CDATA[One of the inevitable aspects of data migration is dealing with fallout from automated data loads.  Typically, this process includes identifying the data that will not load, analyzing the error messages to determine the root cause, formatting a readable report that can be used as a tool in the cleanup process, and fixing the root [...]]]></description>
			<content:encoded><![CDATA[<p>One of the inevitable aspects of data migration is dealing with fallout from automated data loads.  Typically, this process includes identifying the data that will not load, analyzing the error messages to determine the root cause, formatting a readable report that can be used as a tool in the cleanup process, and fixing the root cause of the problem so that it does not happen again.</p>
<h2>Why the data will not load correctly.</h2>
<p>There is a litany of reasons why some data records will load correctly while others will not.  Here is a list of some common root causes:</p>
<p>&nbsp;</p>
<ol>
<ol>
<li><strong>Poor quality legacy data.</strong><br />
Legacy systems which are not as tightly integrated as SAP, and are not under master data control allow the end user a bit of freedom when entering data.  A zip code may contain too little or too many characters; the email address is not properly formatted; numeric fields have transposed digits; various forms of abbreviations (especially in the city field), a quantity of zero (0) permitted by the legacy system and uploaded into a field where SAP will not accept a quantity of 0 and even simple misspellings  all can cause stringent validation checks to trigger an error and prevent the record from loading at all.  A more sinister type of error occurs when the data is functionally incorrect, but good enough to pass all of the SAP validity checks.  In this case, the data record will technically load into SAP, but will not be functionally correct.  Duplicate customers, duplicate vendors, and the data entry error for a quantity of 1000 instead of 100, and the wrong pricing condition applied to a sales order line are examples of this scenario.</li>
</ol>
</ol>
<p>&nbsp;</p>
<p>&nbsp;</p>
<ol>
<li><strong>Functional configuration and supporting data effects.</strong><br />
Many times I have watched the load statistics for a data object plummet from near 100% in the cycle two test load to near 0% in the cycle three test load.  This is very unnerving to the client because the cycle three test load is getting rather close to the go-live date, and “by the way, shouldn’t the statistics be getting better rather than worse?”  Functional configuration changes can wreak havoc on any data load.  Flipping the switch on a data field from optional to required; turning on batch management or serialization for materials for the first time; changes in the handling of tax, tax codes, and tax jurisdiction codes; that account determination entry that is missing or not set up correctly; a missing unit of measure or unit or measure conversion factor; the storage location in the upload file which does not exist in SAP – any of these can cause a load to drop mostly or completely onto the floor.While change is inevitable on any project, it is important to control and communicate the change so that the downstream impact can be recognized and understood.   Controlled change and communication always works better than total surprise.  Perhaps if we all know ahead of time about that data field that is now required, we can impose a requirement on the data extract side to make sure that the data field is populated before it enters the upload file.&nbsp;</li>
<li><strong>Additional data in the upload file.</strong><br />
Inserting a new field in the middle of the upload file data structure might be necessary for the business to close a gap, but if that change is not communicated to the technical team so that appropriate adjustments can be made to the load object’s input structures and processing logic, the new data will surely never load, and may cause misalignment of the data fields which follow it in the upload structure.</li>
</ol>
<p><span id="more-6104"></span></p>
<h2>The Finger Pointing Game</h2>
<blockquote><p>It’s the load program!  No, it’s the data!  No, it’s the configuration!  No, it’s … (fill in your favorite finger pointing game excuse explaining why data will not load).</p></blockquote>
<p>If you ever find yourself in the midst of this type of finger-pointing game, immediately stop the madness.  For this and similar situations, I apply a simple litmus test which has never failed me yet – manually enter the EXACT upload data into SAP for the transaction which has failed.  If one can be entered manually, then the program will be able to automatically load thousands with similar upload data and functional configuration.</p>
<p>I have lead many a functional analyst &#8211; kicking, screaming, and ranting about how terrible the load program is – to the terminal to play “let’s enter one manually”.  Typically, the result is that one cannot be entered manually due to configuration issues or the lack of supporting values data.  Once these issues are cleaned up, the load program “magically” begins to process thousands of records with no trouble at all.</p>
<p>Sometimes, the load object appears to be the cause, but is not the root cause.  The important data item not being handled by the load object (which was not called out in the functional specification document), the data item which turns blue (because the functional specification document explicitly stated “put this data item into the blue category”), the formula which is not calculating the desired result (but is indeed the exact formula found in the functional specification document) – all are examples of the load object adhering accurately to an incorrect functional specification document.  The root cause, then, is the functional specification document which must first be revised and checked into the controlled document repository before making any code modifications.</p>
<h2>It’s the Program</h2>
<p>Well, OK, sometimes the load object is at fault.  But it is extremely rare.</p>
<h2>Collecting and Reporting the Technical Load Statistics</h2>
<p>Load statistics are an important <span style="text-decoration: underline;">technical</span> metric, indicating what percentage of the upload file has successfully posted a transaction into SAP.  This is a basic and simple record count check.  How many records were presented in the upload file, how many records posted successfully to SAP, and how many records failed to post.  Also, does the number of successful transaction plus the number of failed transactions equal the total number of records presented in the upload file.</p>
<p>Here is how I communicate this technical metric:</p>
<table>
<tbody>
<tr>
<td>Total records in the upload file</td>
<td>100</td>
<td></td>
</tr>
<tr>
<td>Successful technical transactions</td>
<td>90</td>
<td>90% success</td>
</tr>
<tr>
<td>Failed technical transactions</td>
<td>10</td>
<td>10% fail</td>
</tr>
</tbody>
</table>
<p>This technical metric indicates only that all of the SAP validation rules for posting the transaction have passed.  It does not indicate that the master or transactional data posted to SAP is actually correct in functional terms.</p>
<h2>The Functional Review</h2>
<p>It is very possible for an entire upload file to technically load at 100%; while at the same time, functionally fail at 100%.  The customer may be missing a partner, the material or article may be categorized incorrectly, the pricing conditions on a sales order may not have the desired validity date range, the GL posting may be to the wrong accounts.  Hence, the need a functional review and validation of the data transacted into SAP.  The data type &#8211; master or transactional &#8211; determines the type of functional review and metrics to be employed here.</p>
<p>For master data, such as of materials, customers, vendors, etc., it is impossible to individually validate the many thousands of entries in your SAP system.  But statistical methods can be employed which will guide you through a random sampling of the data, while at the same time assuring accuracy at a high degree of confidence levels.</p>
<p>For transactional data, such as inventory, open sales orders, open AR, etc., direct mathematical comparisons can be employed.  On a grand scale, if an inventory value of $15,246,321.44 is being moved from your legacy system to SAP, then that exact amount must arrive in SAP when the migration task is complete.  It may be a bit more difficult to do this mathematical comparison at a more granular level.   If, in the move to SAP you are also redesigning your material/storage location combinations, a direct comparison between the legacy system and SAP may not be possible without a translation factor.  The same scenario exists if you redesign your GL chart of accounts, where one legacy GL account now maps to several SAP GL accounts, or vice versa.</p>
<h2>Reporting the Fallout</h2>
<p>If an automated data load was not technically 100% successful, a clear set of error messages complete with a link back to the legacy data must be mined, formatted, and presented to the business for analysis.  Such a report really helps to facilitate the fallout cleanup.  The link back to the legacy data must be carefully designed into the load process to make sure that, for example, the legacy customer number, legacy vendor number, legacy sales order number, legacy purchase order number, etc. is included as part of the data being handled.  Without the link back to the legacy data, it becomes very difficult to identify which data record needs to be fixed.</p>
<p>The error message mining technique that I use depends on the load method.  I will describe two here – one for a BDC load method and one for an IDOC load method.</p>
<h2>Mining Meaningful Error Messages from a BDC Session Log</h2>
<p>At the completion of a batch input session, the batch input session overview screen (SM35) displays the technical load statistics.  In this example, out of a total of 229 transactions, 13 failed and 216 succeeded.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-1.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5594 alignnone" title="dm3-1" src="http://www.dataxstream.com/wp-content/uploads/dm3-1.jpg" alt="" width="203" height="61" /></a></p>
<p>The session log shows the status of all 229 transactions.  This screen snapshot is a fragment of the complete session log for the batch input session.  It shows many successful transactions (Type = S) and one failed transaction (Type = E).  The error message here is clear – the article does not exist or is not activated.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-2.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5596 alignnone" title="dm3-2" src="http://www.dataxstream.com/wp-content/uploads/dm3-2.jpg" alt="" width="623" height="216" /></a></p>
<p>But as you can imagine, the 13 failed transactions with error type = E are sprinkled throughout the many pages of this log file.  With only 229 transactions, this log file is quite easy to pick through to find the 13 errors.  But imagine if the number of transactions were in the thousands or tens of thousands.  How do we extract only the failed transactions and present a concise report of the failed transactions?</p>
<p>To do this, I use SAP transaction SM35P – Batch Input Log Overview.  This transaction has the ability to set a filter on any field in the batch input log file, display the filtered results, and then to export the results to a local file.</p>
<p>To enter the mode where this is possible, first press the PRINT icon.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-3.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5597 alignnone" title="dm3-3" src="http://www.dataxstream.com/wp-content/uploads/dm3-3.jpg" alt="" width="441" height="95" /></a></p>
<p>Next, set the filter.  The appropriate filter field here is SESS. TYPE.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-4.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5598 alignnone" title="dm3-4" src="http://www.dataxstream.com/wp-content/uploads/dm3-4.jpg" alt="" width="449" height="66" /></a></p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-5.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5599 alignnone" title="dm3-5" src="http://www.dataxstream.com/wp-content/uploads/dm3-5.jpg" alt="" width="570" height="459" /></a></p>
<p>We only want the errors, so set the filter for field SESS. TYPE = E.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-6.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5600 alignnone" title="dm3-6" src="http://www.dataxstream.com/wp-content/uploads/dm3-6.jpg" alt="" width="328" height="91" /></a></p>
<p>The display now shows only the 13 rows containing the error messages.  This can be exported directly to a local spreadsheet for further analysis.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-7.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5601 alignnone" title="dm3-7" src="http://www.dataxstream.com/wp-content/uploads/dm3-7.jpg" alt="" width="625" height="146" /></a></p>
<h2>Mining Meaningful Error Messages from IDOCs</h2>
<p>Depending on the IDOC and the processing module, mining the error status messages from IDOCs can be very easy or somewhat challenging.  For the more difficult scenarios, you probably will need to hone your EXCEL skills to properly join several extracts together into one complete picture.</p>
<p>When creating IDOCs with a load object, I always note the date, time, and IDOC basic type.  I will use this information as the selection criteria for transaction WE05, which is going to locate the IDOCs and display the results information I need after the IDOCs are processed.  The results that I usually collect are the error status messages, and some data content from a segment or two to illustrate exactly where the problem is in the legacy data.</p>
<p>While the background job is busy processing the IDOCs, I usually take a peek, using transaction WE05, to see how the load is progressing.  If I see that most of the IDOCs are falling onto the floor (IDOC status 51) rather than moving into the database (IDOC status 53), I usually stop the background job and begin an immediate analysis of the fallout.  If the fallout solution does not require a change to the IDOC data content (e.g. a configuration change), then I can replay the fallout using SAP transaction BD87.  If the fallout solution does require a change to the IDOC data content, then the complete set of IDOCs must be regenerated again.</p>
<p>Let’s see what WE05 can tell us about a completed Article Master load.</p>
<p>On the WE05 screen below, we can see that of the total of 14,005 IDOCs, 11,412 have processed successfully and 2,593 have failed to process.  By double clicking the Status 51 folder, the display will show only the Status 51 IDOCs – the fallout.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-8.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5603 alignnone" title="dm3-8" src="http://www.dataxstream.com/wp-content/uploads/dm3-8.jpg" alt="" width="618" height="278" /></a></p>
<p>By pressing the “status list” icon (shown above), the display will show the status messages for the fallout.    Once these messages are displayed, pressing the “export” icon allows me to save the screen contents to a spreadsheet.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-9.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5604 alignnone" title="dm3-9" src="http://www.dataxstream.com/wp-content/uploads/dm3-9.jpg" alt="" width="624" height="331" /></a></p>
<p>Now it would be really nice if I could have the article number in the spreadsheet right next to the error message.  The article number in the ARTMAS IDOC is stored in segment E1BPE1MATHEAD.  The segment content for each IDOC can be displayed by pressing the “list specific segment” icon and entering the segment name in the box.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-10.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5605 alignnone" title="dm3-10" src="http://www.dataxstream.com/wp-content/uploads/dm3-10.jpg" alt="" width="623" height="256" /></a></p>
<p>The segment display will show all fields in the segment, so I usually hide all of the columns that I don’t want to see.  Here is the E1BPE1MATHEAD segment display showing only the article number.  I can use the export icon to save the list of article numbers to another spreadsheet.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-11.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5606 alignnone" title="dm3-11" src="http://www.dataxstream.com/wp-content/uploads/dm3-11.jpg" alt="" width="326" height="373" /></a></p>
<p>Here is a portion of the complete spreadsheet showing the error messages and the article numbers side by side.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-12.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5607 alignnone" title="dm3-12" src="http://www.dataxstream.com/wp-content/uploads/dm3-12.jpg" alt="" width="625" height="250" /></a></p>
<p>A filter applied to the spreadsheet shows that the 2,593 errors are all grouped into one of three error status categories.  By selecting a single category, Excel will also show me the number of records within that failure category.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-13.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5608 alignnone" title="dm3-13" src="http://www.dataxstream.com/wp-content/uploads/dm3-13.jpg" alt="" width="208" height="235" /></a></p>
<p>Sometimes it is easier to mine the status messages directly from the IDOC status table EDIDS.  This is especially true where the processing module is a BAPI which returns an error table rather than a single error message.  In this case, when you press the “status list” icon in WE05, only the first error status message of several is displayed for each IDOC.  I find that the first message is not very helpful (as shown below).  I also find that typically the second or third message in the return status table is usually the important one.  You won’t see it displayed on the WE05 screen, but you can mine it from the EDIDS table.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/dm3-14.jpg" rel="shadowbox[sbpost-6104];player=img;"><img class="size-full wp-image-5609 alignnone" title="dm3-14" src="http://www.dataxstream.com/wp-content/uploads/dm3-14.jpg" alt="" width="629" height="220" /></a></p>
<p>SAP transactions SE11 or SE16 both support this activity.  For the selection criteria I use the IDOC number range, status 51, and status type E.  On the display screen, choose only the relevant fields for display – the IDOC number (DOCNUM), IDOC status (STATUS), status message (STATXT), the four substitution parameters for the status message (STAPA1, STAPA2, STAPA3, STAPA4) and the message type (STATYP).  All of this can be exported into a spreadsheet.  If you really want to test your Excel skills, you can write code that will move the substitution parameters into their placeholders in the status text.</p>
<h2>Preparing for the next data migration cycle &#8211; Let the fallout analysis and cleanup begin.</h2>
<p>Presenting the fallout report to the business with a set of clear error reasons and links back to the legacy data is key to enabling the legacy data cleanup process to proceed.  In the iterative process of data migration cycles, cleansing the legacy data is a step in the right direction towards an improved next conversion cycle.</p>
<p>I hope you enjoyed this blog series on data migration.  Please feel free to send comments or questions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/08/sap-data-migration-dealing-with-fallout/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SAP Data Migration &#8211; Answering the Important Questions (Part 1)</title>
		<link>http://www.dataxstream.com/2010/07/sap-data-migration-and-data-conversion-1/</link>
		<comments>http://www.dataxstream.com/2010/07/sap-data-migration-and-data-conversion-1/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 14:00:20 +0000</pubDate>
		<dc:creator>Mike Salvo</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Project Management]]></category>
		<category><![CDATA[SAP Strategy]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[SAP Testing]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[Data Migration]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[Integration]]></category>
		<category><![CDATA[Mike Salvo]]></category>
		<category><![CDATA[NetWeaver]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[SAP programming]]></category>
		<category><![CDATA[SAP testing]]></category>
		<category><![CDATA[upgrades]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=5138</guid>
		<description><![CDATA[It is data migration time on your SAP business project.  Whether your project is implementation, acquisition, or merger, the goal is pretty much the same: the seamless inbound acquisition of master and transactional data from one or more external data sources while ensuring that this activity has minimal impact on the rest of the business.  [...]]]></description>
			<content:encoded><![CDATA[<p>It is data migration time on your SAP business project.  Whether your project is implementation, acquisition, or merger, the goal is pretty much the same: the seamless inbound acquisition of master and transactional data from one or more external data sources while ensuring that this activity has minimal impact on the rest of the business.  This is where we attempt to move years of neglected master and transactional data from a loosely structured, anything-goes legacy system into a very tightly integrated and highly structured SAP system.  You must consider the likelihood that the concept of master data management had not been invented yet when the legacy or source system providing your data was implemented.</p>
<p>How much data to move? How much data to leave behind? What to automate, and what to execute manually?  How to gracefully orchestrate and execute a data migration cutover from one system to another?  Where and how to fit the data migration plan into the overall business implementation plan?  How to continue to run the business during the data migration phase of the business project implementation? These questions are all part of the planning fun!</p>
<p><span id="more-5138"></span></p>
<h2>Data Migration Testing</h2>
<p>Processes that we have exercised and continue to exercise on a regular basis are no big deal, do not cause anxiety, or raise any blood pressures.  The daily report, the custom transaction, the interface that runs several hundred times a week – they are all second nature now.  They happen, and no one notices.</p>
<p>But reflect back to the very first time these processes went live.  This is precisely where you are with data migration.  For most, it is a once in a lifetime event.  It is important, then, to raise confidence levels, and reduce anxiety levels surrounding this activity.  This is achieved by practice, practice, practice.</p>
<p>Typically, I like to see at least three data migration test cycles executed in an isolated data migration client.  This allows for several attempts at exercising and fine-tuning the data migration plan; collecting nominal run time statistics to have some idea of how long the data migration might take; identifying and fixing any data migration program object defects; identifying and fixing any data mapping and content defects; and identifying and fixing any functional configuration issues. Each of these tasks are done with the goal of significantly improving the fallout rate with each data migration test cycle.  These data migration test cycles also give us the opportunity to practice our legacy extract skills, our fallout analysis skills, and our fallout manual cleanup skills.</p>
<h2>Source Data Quality</h2>
<p>Each data migration test cycle begins with the legacy or source data extract.  An important activity between data migration test cycles is the cleanup of the legacy or source data.  The data migration process will most likely discover many data problems.  Customer and vendor address data alone are enough to bring your bolt-on tax jurisdiction determination software to its knees – that zip code that is too short, too long, or just plain incorrect when combined with the associated city and state; the various abbreviations used in place of the actual city name; the city and state entered in the same field when they should have been entered into separate fields; etc.   If the source data is not fixed, your data migration test cycles will begin to look like the movie Groundhog Day.</p>
<p>Source data provisioning and cleanup could very well be problematic, especially in an acquisition or merger scenario where the providers are part of a different organization and have no incentive to participate in your project.  If you encounter this scenario, you will most likely need to engage the appropriate management level from your organization to have a serious discussion with the appropriate management level from the providing organization.  Recognize this, be in control, and raise that flag early.    Do not sit around for several days waiting for data to arrive, as this will only set your project behind schedule.</p>
<h2>Data Migration Support for Other Testing</h2>
<p>In any business project scenario, the development team will salivate at the thought of testing their customizations against your real data in the conversion test cycle box.  Likewise, the functional team will be chomping at the bit to use your real data to test configuration scenarios.  And the interface team and the data warehouse team can’t ever get enough data to play with.</p>
<p>While working within your three data migration test cycles, just say NO.  You absolutely need a controlled environment for data migration test cycles, and these other teams will not respect that.  They have a different focus and purpose which requires changing and manipulating degrees of freedom that you need held constant.</p>
<p>But, we are all on the same team trying to move the project to the finish line within the expected project timeline.  So to help your other team members, plan for additional data migration cycles to provide this data to these teams.  That’s more data migration practice for you, and it gives everyone else what they need.</p>
<h2>The Perfect World of Data Migration</h2>
<p>In a perfect world, for each data object to be converted:</p>
<ol>
<li>The functional specification and mapping documents are well-written and clear.</li>
<li>A data load file is built exactly in conformity to the well-written functional specification and mapping documents.</li>
<li>The data migration ABAP objects are built exactly as specified by the well-written functional specification and data mapping documents.</li>
<li>No one is insisting that we move a square peg into a round hole.</li>
</ol>
<p>In a perfect world, for each set of data that is to be migrated:</p>
<ol>
<li>The legacy system data has been thoroughly cleansed.</li>
<li>The providers of the legacy data are genuinely interested in providing accurate data on time.</li>
<li>Server-resident load files in a Unicode system are correctly encoded to UTF-8.</li>
<li>A delimiter other than comma has been specified for the load file.</li>
</ol>
<p>In a perfect world, the data migration test cycle client:</p>
<ol>
<li>Is built in a box that is not the development box.</li>
<li>Is configured exactly like the client where the data migration ABAP objects were built and tested.</li>
<li>Is not open for configuration, unless by design.</li>
<li>Is not part of a transport path. to prevent the current cycle of conversion testing from being blindsided by any new configuration changes.</li>
<li>Is locked down so that only data migration and data validation tasks can be performed.</li>
<li>Is configured to handle a more background and update processes and fewer dialog processes.</li>
<li>Is built in a box that has enough disk space to be the repository for the primary load files and any intermediate processing files needed.</li>
</ol>
<p>In a perfect world, at the project level:</p>
<ol>
<li>There is an overall business cutover or implementation plan into which you can assimilate your data migration plan.</li>
<li>The data migration plan integrates nicely into the overall business cutover plan.</li>
<li>There is a strategy in place to bring the data current between the time the cutover freeze is enforced and the implementation date.</li>
</ol>
<h2>Stay Tuned!</h2>
<p>In the real world, the fun is just beginning.  Those perfect world scenarios just never seem to happen.   But stay tuned!  In my next blog post in this series, I will discuss the details of the Data Migration Plan.  After that, in subsequent posts, I will drill down into some real world scenarios that I have encountered and discuss how I dealt with them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/07/sap-data-migration-and-data-conversion-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Native SQL in an ABAP Proxy</title>
		<link>http://www.dataxstream.com/2010/05/using-native-sql-in-an-abap-proxy/</link>
		<comments>http://www.dataxstream.com/2010/05/using-native-sql-in-an-abap-proxy/#comments</comments>
		<pubDate>Thu, 13 May 2010 13:30:22 +0000</pubDate>
		<dc:creator>Mike Salvo</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP PI Blog]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[ABAP development]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[Integration]]></category>
		<category><![CDATA[Mike Salvo]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[SAP ABAP]]></category>
		<category><![CDATA[SAP programming]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=4929</guid>
		<description><![CDATA[To implement a case-insensitive WHERE clause in ABAP, you simply needed to use the native SQL UPPER() construct. The database system that is being used is Microsoft SQL Server, but the UPPER() function and its syntax is similar across different database platforms. This seemed like an easy nut to crack. But, as I soon found out, I actually had a lot to learn.]]></description>
			<content:encoded><![CDATA[<p>Recently, I was looking at a requirements document to build an interface to an external system that wants to query customer master data by the customer first name and last name.  As I read this, there were a cacophony of thoughts, all demanding equal attention, racing through my head:</p>
<blockquote>
<ul>
<li><span style="color: #0000ff;">How will I ever match the inbound interface parameter &#8220;Tom&#8221; with &#8220;TOM&#8221;, or &#8220;tom&#8221;?</span></li>
<li><span style="color: #0000ff;">How will I ever match the inbound interface parameter &#8220;Smith&#8221; with &#8220;SMITH&#8221; or &#8220;smith&#8221;?</span></li>
<li><span style="color: #0000ff;">The ABAP WHERE clause is <strong>not</strong> case-INsensitive.</span></li>
<li><span style="color: #0000ff;">There could be hundreds of customers named Tom Smith.</span></li>
<li><span style="color: #0000ff;">KNA1-NAME1 and KNA1-NAME2 are not indexed fields.</span></li>
<li><span style="color: #0000ff;">And no, we are not storing any portion of either first or last name in an existing indexed field like SORTL.</span></li>
<li><span style="color: #0000ff;">There are well over one million customers in the database.</span></li>
<li><span style="color: #0000ff;">We have already decided to use PI for all interfaces.</span></li>
<li><span style="color: #0000ff;">I will have to buy the BASIS team a case of beer to get them to agree to create indices on the fields KNA1-NAME1 and KNA1-NAME2 in a table with over one million records</span>.</li>
</ul>
</blockquote>
<p>I arrived at the conclusion that I need a case-insensitive database query, along with database indices created for the fields KNA1-NAME1 and KNA1-NAME2.</p>
<p>But, what is a case-insensitive WHERE clause?  A little research and help from colleagues revealed that many had gone before me, and this was nothing new.  To implement a case-insensitive WHERE clause in ABAP, you simply needed to use the native SQL UPPER() construct.  The database system that is being used is Microsoft SQL Server, but the UPPER() function and its syntax is similar across different database platforms.  This seemed like an easy nut to crack.  But, as I soon found out, I actually had a lot to learn.<br />
<span id="more-4929"></span></p>
<h3>Take 1</h3>
<p>The examples I found were very explicit, showing actual code snippets.  Using my research examples as a template, I built what was to be my first attempt at using native SQL in a ZTEST ABAP program:</p>
<pre style="background-color: #eaeaea; color: #222;">exec sql.
  select kunnr name1 name2
    from kna1
    into table i_cust
    where upper(name1) like :l_name1
      and upper(name2) like :l_name2
endexec.</pre>
<p>Well, as a native SQL rookie, I was stopped dead in my tracks.  Native SQL does not allow a select into a table – you can only select into a work area.</p>
<h3>Take 2</h3>
<p>In my ZTEST ABAP program, I changed the code to SELECT into a work area and append the work area to an internal table in a subroutine:</p>
<pre style="background-color: #eaeaea; color: #222;">exec sql performing append_cust.
  select kunnr, name1, name2
    from kna1
    into :wa_cust
    where upper(name1) like :l_name1
      and upper(name2) like :l_name2
endexec.

form append_cust.
  append wa_cust to i_cust.
endform.</pre>
<p>I really thought that this would work.  But, I was getting a syntax error from native SQL – the table name was not being recognized.  A little more research revealed that, in <em>some</em> cases, only UPPER CASE is valid for table names and field names.  OK.  I can handle that.</p>
<h3>Take 3</h3>
<p>I changed the native SQL statement to all UPPER CASE in my ZTEST ABAP program:</p>
<pre style="background-color: #eaeaea; color: #222;">EXEC SQL PERFORMING APPEND_CUST.
  SELECT KUNNR, NAME1, NAME2
    FROM KNA1
    INTO :WA_CUST
    WHERE UPPER(NAME1) LIKE :L_NAME1
      AND UPPER(NAME2) LIKE :L_NAME2
ENDEXEC.

form append_cust.
  append wa_cust to i_cust.
endform.</pre>
<p>This <em>appeared</em>to work just fine&#8230;  Except, I noticed that too many records were being returned.  A little more analysis showed that I was getting records from ALL clients, not just my logon client.</p>
<h3>Take 4</h3>
<p>Again, in my ZTEST ABAP program, specify the client:</p>
<pre style="background-color: #eaeaea; color: #222;">EXEC SQL PERFORMING APPEND_CUST.
  SELECT KUNNR, NAME1, NAME2
    FROM KNA1
    INTO :WA_CUST
    WHERE UPPER(NAME1) LIKE :L_NAME1
      AND UPPER(NAME2) LIKE :L_NAME2
      <span style="color: #ff0000;">AND MANDT = :L_MANDT</span>
ENDEXEC.

form append_cust.
  append wa_cust to i_cust.
endform.</pre>
<p>Now I was getting the results that I wanted!!!!  So, I pasted this ZTEST ABAP code into the ABAP proxy.</p>
<p>A syntax check of the code immediately rejected the use of subroutines &#8211; they are not allowed in OO ABAP.  I suppose I should have known that.  The error message indicated that I needed to use a cursor instead of the subroutine.  So, I started cursing – a lot!!!</p>
<h3>Take 5 (The Final Version)</h3>
<p>Here is the final version of the code which works for OO ABAP, and, hence, the ABAP proxy:</p>
<pre style="background-color: #eaeaea; color: #222;">EXEC SQL.
  OPEN CUSTCURSOR FOR
    SELECT KUNNR, NAME1, NAME2
      FROM KNA1
      WHERE UPPER(NAME1) LIKE :L_NAME1
        AND UPPER(NAME2) LIKE :L_NAME2
        AND MANDT = :L_MANDT
ENDEXEC.

DO.
  EXEC SQL.
    FETCH NEXT CUSTCURSOR INTO :WA_CUST
  ENDEXEC.

  IF SY-SUBRC NE 0.
    EXIT.
  ELSE.
    APPEND WA_CUST TO I_CUST.
  ENDIF.
ENDDO.

EXEC SQL.
  CLOSE CUSTCURSOR
ENDEXEC.</pre>
<p>Well, I finally got it right after five tries.  As mentioned before, I found many explicit code examples, but none were for OO ABAP with a database  requiring UPPER CASE be used, so that the table and field names would be recognized in the native SQL SELECT statement.</p>
<p>I learned something new about SAP.  I hope that I never stop learning.  I also hope that this blog might save someone a bit of distress in trying to work through a similar situation.  Now, I just need to figure out what kind of beer to buy the BASIS team to get those indexes created&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/05/using-native-sql-in-an-abap-proxy/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>The Art of Writing an SAP Functional Specification</title>
		<link>http://www.dataxstream.com/2010/04/writing-sap-functional-spec/</link>
		<comments>http://www.dataxstream.com/2010/04/writing-sap-functional-spec/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 13:00:25 +0000</pubDate>
		<dc:creator>Mike Salvo</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Functional]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[functional specification document]]></category>
		<category><![CDATA[Mike Salvo]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[RICEF]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[upgrades]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=4599</guid>
		<description><![CDATA[Overview I am currently working on an SAP implementation project that is just starting its realization phase.  One of my first tasks, as a member of the technical implementation team, is to review completed functional specification documents for RICEF objects.  These documents, written by functional subject matter experts, are supposed to detail business requirements that [...]]]></description>
			<content:encoded><![CDATA[<h3>Overview</h3>
<p>I am currently working on an SAP implementation project that is just starting its realization phase.  One of my first tasks, as a member of the technical implementation team, is to review completed functional specification documents for RICEF objects.  These documents, written by functional subject matter experts, are supposed to detail business requirements that address gaps, and which need to be incorporated into the system being implemented. The purpose of the review is to make sure that the functional specification documents are complete, accurate, and contain the approval signatures required to move on to the technical design phase.</p>
<p><span id="more-4599"></span><br />
In my career, I have had the pleasure of working with some first-rate functional analysts who know how to draft an excellent functional specification document in a timely manner.  It is this type of performance that helps to move a project along in the right direction, on schedule, and within budget.  Likewise, I have had the not-so-pleasant task of working with not-so-first-rate functional analysts, who draft functional specification documents that are not clear, inaccurate, and incomplete.  The risks here are ultimately manifest as project delays and cost overruns.</p>
<h3>The Good…</h3>
<p>A really good functional specification document contains enough detailed information about the business process to enable a technical designer to use it as the foundation for drafting a complete and accurate technical design document.  The functional specification document should not only highlight the presence of a gap, but should demonstrate how the business process, accompanied by automation, will close the gap.  This document must also indicate the abnormal processing requirements – what should happen when that report or interface does not run, what are the recovery steps, how are key employees notified of the problem, etc.  The content of a functional specification document must be tuned to the flavor of the RICEF object that it is describing.  Since they perform very different tasks, a report specification document should be very much different from an interface, conversion, enhancement, or form functional specification document.  Using functional specification templates helps to insure the appropriate content for each type of RICEF object.</p>
<h3>… and the Not-So-Good.</h3>
<p>I am sometimes astonished by the sparse content that is actually offered up for review.  “We need a report” really does not tell me a whole lot about the business process that I am supposed to automate.  Nor does it even hint at the report purpose, content, layout, user interface, execution mode, authorization requirements, or error handling.  And likewise, “Build me an interface” does not even begin to describe the direction, payload content, mapping, frequency, error handling and recovery steps.  It would be so wrong for me to attempt to build a technical design on such meager functional definitions.   One of my favorite cartoons shows a development manager standing in front of rows of programmers saying “You guys start coding.  I’ll go and find out what they want”.</p>
<p>I am further astonished by:</p>
<p style="padding-left: 30px;">a)      the project managers who apply pressure to accept inaccurate and incomplete functional specification documents, to give the impression that the project is actually moving forward and making meaningful progress.</p>
<p style="padding-left: 30px;">b)      the functional analysts who whine incessantly when their paltry functional specification document is not accepted.</p>
<p>A functional specification document that does not meet expectations must be upgraded until it does.  But bouncing a functional specification document back and forth like a ping pong ball between the functional team and a technical reviewer is inefficient and wasteful.  I find that the best way to quickly firm up a weak functional specification document is to thoroughly research all of the issues that I found in the document, formulate proposed solutions where possible, and then schedule a face to face collaborative meeting with the functional analyst and the business process owner(s).  This type of collaboration can save hours, days, or even weeks of wasted ping-pong posturing, and that is always best outcome for the project.</p>
<h3><a href="http://www.dataxstream.com/2010/03/sap-upgrades-offshore-resources/">Off-Shore Technical Resources</a></h3>
<p>This face-to-face quick resolution scenario typically cannot happen if you have an off-shore technical contingent in play.  In this case, it is absolutely imperative that the functional specification document be most accurate and complete to mitigate the risk of excessive time loss.   Why is that?</p>
<p>Off-shore resources are sometimes time zone shifted eight or more hours ahead of where the project is located.  If a functional specification document is released for review, it will not be analyzed until we have left for the day.  If the off-shore reviewer has questions or raises issues, we will not see these questions or issues until the next day when we arrive at the project site.  When we respond to the questions or issues, the off-shore team will not see our response until we have left for the day.  And so on.</p>
<p>Under these conditions, a poorly written functional specification document with issues takes days instead of hours to resolve.  This leads to unnecessary project delays and cost overruns.</p>
<h3>When One is Really Many</h3>
<p>That 3PL interface, which was scoped and planned by the business process owners as a single RICEF object named “The 3PL Interface”; and for which only one interface functional specification document is written, is actually many RICEF objects.  We need to move purchase orders, inventory receipts, advance ship notices, inventory picks, and cycle counts between the two interfacing partners.  Each of these represents a different payload, different mapping, is triggered by a different point in the business process, has separate error handling and recovery procedures, and requires a separate RICEF development object.</p>
<p>That single enhancement functional specification document, which addresses all of SD pricing, has the potential to extend into many different user exits.  I just finished coding an ABAP proxy that was functionally specified as one interface.  In fact it was four.  The requirement was to search the database for sales and invoice data starting with either an invoice number, sales order number, customer name, or company name.  Each of these search techniques required the development of a separate method.  The only pieces of code that were shared among the four search techniques were the input parameters and the output return table.</p>
<p>The point here is to make sure that the project planners understand the real complexity and effort required on the development side, and to make sure that the project plan and budget reflects these more realistic metrics.  This really goes a long way to stop everyone from wondering, “It’s only one interface!  What is taking development so long?”</p>
<h3>Great Expectations</h3>
<p>So what is a reasonable set of expectations for a really good functional specification document?  What is it that we are asking the business analyst to do?</p>
<p>First, let me describe what I do not expect.  I do not expect a business analyst to write code, build tables, design efficient database retrievals, or to decide that one BAPI, function module, class, or IDOC is better than another.</p>
<p>Here is what I do expect:</p>
<p style="padding-left: 30px;">A clear definition of a business process that is repeatable, and which actually works.  As a pre-automation test for data conversions, I always require the functional analyst to manually enter one of whatever, using the standard SAP transaction for which a conversion program is to be built. Many times, they can’t because the system is not configured correctly, the supporting data is not present, or any number of other reasons which cause the transaction to fail.  An interesting observation is that there is much indignant huffing and puffing during this manual entry “test” process.  But when the manual test fails, I simply remind them that I cannot automate a broken or non-existent business process.</p>
<p style="padding-left: 30px;">A clear definition of what should happen under abnormal or failure circumstances.  This must include error handling, notification, recovery and reprocessing steps.</p>
<p style="padding-left: 30px;">A business process that can efficiently be automated.  Requiring a search of sales order header text for the phrase “This is a red order” is a very bad design for automation purposes.  While such a design is technically possible to build, it will certainly be inefficient at run time, and may not always produce all of the red orders.  This is because the key value is a free-form phrase that can and will be misspelled, and abbreviated, along with countless other mutilations of the key phrase “This is a red order”.  There are much better business processes and technical implementations that will more efficiently and more accurately find all of the red orders in your system.</p>
<p style="padding-left: 30px;">An explanation of the need for development.  Exactly what is the gap, and how will automating the business process close the gap?</p>
<p style="padding-left: 30px;">Screen shots from SAP transactions depicting data that is to be retrieved or stored.  From the screen shot in the transaction, I can usually determine the exact table and field in the SAP database.  Note that some business analysts are very adept at identifying the actual underlying table and field name.</p>
<p style="padding-left: 30px;">Clear and concise details with respect to data mappings, formulae, data transformations, conditional processing, etc.  If I come to an intersection and it is unclear whether I should continue to go straight, turn left, or turn right, then the functional specification document needs a bit more detail behind it.</p>
<p style="padding-left: 30px;">
<h3>How to insure Consistency in Functional Specification Document Review</h3>
<p>Design a separate functional specification document review checklist for each flavor of RICEF object.  Distribute these checklists to the functional specification writers so that they know what the expectations are.  Using a checklist will help to make sure that your review process is consistent and accurate.  Improve these checklists over time.  My Form functional specification checklist document now includes the following check:</p>
<p style="padding-left: 30px;">Is it physically possible to print the specified content on the specified form using the specified font style and size?  Was an actual printed mock-up provided as proof?</p>
<p>- but only after I had received a functional spec for a form that required four inches of print content on a one inch label.  And somehow, the business analyst who wrote this particular request erroneously thought that it was my problem to solve.   After all, writing code is magic!  Isn’t it?  In this case, I pushed back and insisted that an actual printed mock-up be produced &#8211; one that I would then agree to automate.</p>
<h3>Summary</h3>
<p>A good functional specification document will help tremendously in moving a project forward in the right direction with minimal cost and risk.  A poor functional specification document has serious potential to cause project delays, and  schedule and cost overruns.  The best goal for the project is to achieve a good functional specification document, using whatever means required.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/04/writing-sap-functional-spec/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Too Many Developers Spoil The Code</title>
		<link>http://www.dataxstream.com/2010/03/too-many-developers-spoil-the-code/</link>
		<comments>http://www.dataxstream.com/2010/03/too-many-developers-spoil-the-code/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 13:24:42 +0000</pubDate>
		<dc:creator>Craig Stasila</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Interface Blog]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[ABAP development]]></category>
		<category><![CDATA[BADI]]></category>
		<category><![CDATA[Basis/Netweaver]]></category>
		<category><![CDATA[Craig Stasila]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[Integration]]></category>
		<category><![CDATA[NetWeaver]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[SAP ABAP]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=4689</guid>
		<description><![CDATA[You may have heard the following idiom before: Too many cooks spoil the broth The common meaning extracted from this saying is that too many people working on a single task tend to make a mess of it.  But, what happens when you have too many developers working in a single piece of ABAP code? [...]]]></description>
			<content:encoded><![CDATA[<p>You may have heard the following idiom before:</p>
<blockquote><p>Too many cooks spoil the broth</p></blockquote>
<p>The common meaning extracted from this saying is that too many people working on a single task tend to make a mess of it.  But, what happens when you have too many developers working in a single piece of ABAP code?  That&#8217;s right, you get a big mess.  This issue is especially difficult to deal with when there are multiple functional requirements leveraging the same custom code object, form-based user-exit, or function-based user-exit.</p>
<p>While current releases of SAP (those built on SAP NetWeaver 2004s and later) have good built-in handling of enhancements and customizations via implicit and explicit enhancement points and BADIs, there still exists many old-school user-exits.</p>
<h2>Multiple Developers; One Code Object</h2>
<p>I recently worked on a project where three separate developers were creating three separate interfaces based on the outbound delivery IDOC.  While the development for all three interfaces was occurring at the same time, the go-live date for each of the interfaces were different (we&#8217;ll discuss that project management glitch at another time).  Each interface required a separate set of custom fields and, therefore, it&#8217;s own IDOC extension.  The problem is there is only one appropriate user-exit in IDOC_OUTPUT_DELVRY and three developers needed to be developing in it at the same time!</p>
<p>How did we solve this problem?<br />
<span id="more-4689"></span></p>
<h2>An Object To Call One&#8217;s Own</h2>
<p>To allow each developer his own development object and transport timeline, I decided to implement a custom multiple-use, filtered BADI <em>inside</em> the SAP user-exit function EXIT_SAPLV56K_002.  Actually, you can implement your own BADI almost anywhere you need alternate logic execution&#8211;even custom code!</p>
<p>So you might be saying, &#8220;Create my own multi-use, filtered BADI definition? Sounds complicated.&#8221; Well, it&#8217;s easier than you think!</p>
<p>NOTE: This solution was done on an ECC6 system based on SAP NetWeaver 2004s.  The steps to implement this type of solution in ECC5 (SAP NetWeaver 2004) are very similar.</p>
<h2>Create A Custom BADI Definition</h2>
<ol>
<li>To create a new enhancement spot definition, use transaction SE18.  I named my enhancement spot Z_EXIT_SAPLV56K_002 because the enhancement spot will be used in user-exit function EXIT_SAPLV56K_002.<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-01.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4694" title="BADI 01" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-01.jpg" alt="" width="399" height="179" /></a></li>
<li>In the ensuing dialog box, enter a description and choose <em>BAdi</em> <em>Definition</em> for the Technology<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-02.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4695" title="BADI 02" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-02.jpg" alt="" width="646" height="149" /></a></li>
<li>Next, create a new BADI definition.<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-03.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4696" title="BADI 03" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-03.jpg" alt="" width="614" height="191" /></a></li>
<li>Specify that the new BADI definition will be multiple use and limited to filtered use.<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-04.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4697" title="BADI 04" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-04.jpg" alt="" width="538" height="95" /><br />
</a>Making the BADI definition multiple use means that each developer can create his or her own BADI implementation.  Each BADI is implemented in its own class.  This promotes code separation and the proper reuse of shared development objects.<br />
Making the BADI definition limited to filter use ensures that the BADI implementations are separate and cannot affect every interface using the user-exit.</li>
<li>Now, create a new filter.<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-05.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4698" title="BADI 05" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-05.jpg" alt="" width="262" height="102" /></a><br />
BADI filtering in SAP NetWeaver 2004s is much more powerful than in previous versions of SAP.  Read more about BADI filtering <a href="http://help.sap.com/saphelp_nw04/helpdata/en/eb/3e7cf7940e11d295df0000e82de14a/frameset.htm" target="_blank">here</a>.</li>
<li><a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-05.jpg" rel="shadowbox[sbpost-4689];player=img;"></a> The BADI we are defining will be used to populate IDOC extensions.  Each IDOC extension has its own message type (e.g. ZMHL_DESADV, ZQTC_DESADV, ZMHL_SHPORD), therefore the message type of the IDOC being processed is a good value to filter on.  I named my BADI filter EDI_MESTYP.<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-06.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4710" title="BADI 06" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-06.jpg" alt="" width="588" height="288" /></a><br />
SAP allows for the automatic checking of BADI implementation filter values.  The standard domain EDI_MESTYP has a value range of table EDMSG attached to it.  This is exactly the range of values I want as allowable values, so I configure the BADI filter to automatically check the filter values against dictionary object EDI_MESTYP.</li>
<li>Next, create the BADI interface that will be inherited by each implementing class<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-07.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4700" title="BADI 07" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-07.jpg" alt="" width="572" height="149" /></a></li>
<li>The original user-exti function EXIT_SAPLV56K_002 is executed after each segment is added.  Our BADI will do the same.  Create a new public interface method SEGMENT_ADDED.<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-08.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4701" title="BADI 08" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-08.jpg" alt="" width="560" height="118" /></a></li>
<li>The BADI we are creating is replicating user-exit function EXIT_SAPLV56K_002.  Here is the function interface for EXIT_SAPLV56K_002:<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-09_1.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4711" title="BADI 09_1" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-09_1.jpg" alt="" width="602" height="383" /></a><br />
Here is the same data being passed via the interface method.<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-09.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4702" title="BADI 09" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-09.jpg" alt="" width="582" height="218" /></a></li>
<li>Lastly, the BADI has to be called from the existing user-exit.  I will not cover the steps required for implementing user-exit function EXIT_SAPLV56K_002 here, but once you have the user-exit implemented, add the following code.  This code should be the only logic directly inside the user-exit.  Any data processing logic should be implemented via a BADI implementation:
<pre style="background-color: #eaeaea; color: #222;">DATA: GO_BADI TYPE REF TO Z_EXIT_SAPLV56K_002.
DATA: L_STR TYPE STRING.
L_STR = MESSAGE_TYPE.

* Get BADI class based on IDOC message type
GET BADI GO_BADI
   FILTERS EDI_MESTYP = L_STR.

* Execute SEGMENT_ADDED BADI method
CALL BADI GO_BADI-&gt;SEGMENT_ADDED
   EXPORTING
     MESSAGE_TYPE       = MESSAGE_TYPE
     SEGMENT_NAME       = SEGMENT_NAME
     DATA               = DATA
     TAB_IDOC_REDUCTION = TAB_IDOC_REDUCTION
     FLT_VAL            = MESSAGE_TYPE
   CHANGING
     CONTROL_RECORD_OUT = CONTROL_RECORD_OUT
     IDOC_DATA          = IDOC_DATA[].</pre>
</li>
</ol>
<p>We&#8217;re done with creating the BADI definition!  Save and activate your work.  I bet you&#8217;re saying to yourself, &#8220;Wow, that was easy!&#8221;</p>
<h2>BADI Implementation</h2>
<p>Implementing the BADI you just created in the steps above is just like implementing any other BADI in SAP, so here are the Cliff Notes version of implementation instructions.</p>
<ol>
<li>Using transaction SE19, create a new enhancement spot implementation for Z_EXIT_SAPLV56K_002.<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-10.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4703" title="BADI 10" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-10.jpg" alt="" width="547" height="180" /></a></li>
<li>Enter the BADI implementation details.  This particular BADI implementation is for RICEF ID MHL-IO-007, so I added that identification to the BADI implementation name and implementing class name.<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-12.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4705" title="BADI 12" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-12.jpg" alt="" width="572" height="280" /></a></li>
<li>In the BADI definition, we required each BADI implementation to be filtered on message type. This particular BADI implementation is for message type ZMHL_SHPORD.  Create the filter combination for the BADI implementation.<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-13.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4706" title="BADI 13" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-13.jpg" alt="" width="586" height="149" /></a></li>
<li>This ensures that the other interfaces using this BADI (ZMHL_DESADV, ZQTC_DESADV) will not execute the code implemented with this BADI.<br />
<a href="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-14.jpg" rel="shadowbox[sbpost-4689];player=img;"><img class="alignnone size-full wp-image-4707" title="BADI 14" src="http://www.dataxstream.com/wp-content/uploads/2010/03/BADI-14.jpg" alt="" width="518" height="255" /></a></li>
<li>The final steps are to add the code to the SEGMENT_ADDED method just like you would in user-exit function EXIT_SAPLV56K_002.  Once you are done, save and activate your changes!</li>
</ol>
<h2>Summary</h2>
<p>As you can see, with a few extra steps, it is possible to have your cake and eat it, too, by create a custom BADI definition that can be used by other developers.  All this talk of food is making me hungry.  Is it lunchtime yet?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/03/too-many-developers-spoil-the-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SAP Upgrades &amp; Offshore Resources</title>
		<link>http://www.dataxstream.com/2010/03/sap-upgrades-offshore-resources/</link>
		<comments>http://www.dataxstream.com/2010/03/sap-upgrades-offshore-resources/#comments</comments>
		<pubDate>Tue, 23 Mar 2010 13:00:23 +0000</pubDate>
		<dc:creator>Tim Cooper</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP Project Management]]></category>
		<category><![CDATA[SAP Strategy]]></category>
		<category><![CDATA[sap upgrade]]></category>
		<category><![CDATA[SAP Upgrade Blog]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[ABAP development]]></category>
		<category><![CDATA[cost savings]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[sap customization]]></category>
		<category><![CDATA[sap upgrade help]]></category>
		<category><![CDATA[Tim Cooper]]></category>
		<category><![CDATA[upgrades]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=4462</guid>
		<description><![CDATA[How offshore SAP development resources can accelerate your SAP upgrade time line and contain overall project costs.]]></description>
			<content:encoded><![CDATA[<p>It looks like it is official: <a href="http://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/17930%3Fpage%3Dlast%26x-order%3Ddate">2010 is the year of the upgrade</a>.  A little validation is good for my self-esteem. Now that’s out of the way and I’m polishing my attaboy trophy let’s get on with it.</p>
<p>In this post I’ll do a combined discussion about the use of offshore resources in an upgrade project as well as share some experiences working with remote resources.  My colleague, Mike Salvo, has already discussed ABAP customizations in an upgrade in this <a href="../../../../../2009/11/sap-upgrade-and-customizations-1/">post</a>.  Now that you’ve found these customizations, what do you do next?  Actually Mike provides loads of <a href="http://www.dataxstream.com/2009/11/sap-upgrade-and-customizations-2/">good advice</a> about what to do next in terms of sorting out what is in the overall pile of objects that need to be examined.</p>
<p>What I hope is that you have <a href="../../../../../2010/02/sap-upgrades-recycling-project-artifacts/">documentation</a> related to these objects: information that tells you why they were created, what they do, where SAP functionality is deficient in the current release and how you worked around the shortcoming.  This should be helpful in making the evaluation about whether you can remove a particular object or if you need to make sure it works in the new release in a way that satisfies your business and/or technical need.</p>
<p>I going to assume that you have been through the “bag of rocks” analysis described in Mike Salvo’s posts and now have a collection of pebbles, stones and boulders to work through.  This is where you can make good use of offshore resources to help out: there’s a lot of discussion about the use of offshore resources and you can use them really well or really badly.  Let me digress.</p>
<h2><span id="more-4462"></span>SAP Offshore Development Resources</h2>
<p>I’ve heard many complaints regarding offshore resources, but the two biggest complaints that are trotted out as a serious offset to the expected cost savings are:</p>
<ul>
<li>The time difference makes turnaround time longer than projects plan for or like.  For example, if you work with resources in India you have to synchronize working schedules and often this means team members either work way late or very early in the day.</li>
<li>The accuracy and completeness of what you ask for determines the quality of what you get back (a.k.a. you get what you ask for, not necessarily what you want): the difference in time zones makes it difficult to get clarifications and address questions quickly.  Consequently, development life cycles can be extended even if the hourly cost is lower.</li>
</ul>
<p>A straightforward way to address the first issue is to work with an offshore partner in a time zone closer to yours.  In this respect I’ve worked with development partners in South America where the offset with US time zones is small.  This helps address the second complaint: by being in similar time zones it is much easier to either pick up the phone and address questions or send e-mail and get a quick response to a question.  I’ve been on projects where a quick answer to a question had to wait a day because of time zone and work schedule difficulties.  There may be a slight premium for using an offshore team in South America, but the turnaround time and responsiveness usually makes it worthwhile.</p>
<p><strong>How does this digression help your upgrade?</strong></p>
<p>Once you’ve sorted your bag of development rocks you can go through another level of review to rank the objects in terms of complexity and/or difficulty of remediation for the upgrade.  In general, I’d recommend keeping the most difficult work items close at hand and have onshore resources work them.  Any questions about what the object is supposed to do, any business process impacts can be addressed readily with end users and business analysts.  Objects that are less complex can be worked by the offshore team: you stand a good chance of getting what you need by providing clear documentation (all those project artifacts you maintain) and explicit instructions around what you think the remediation entails.  You should also set expectations around what comes back from your offshore partner: code that is free from syntax errors isn&#8217;t going to be enough, some level of testing and documented results are more likely what you want.</p>
<h2>SAP Upgrade Onshore and Offshore Resource Balancing</h2>
<p>I can’t tell you or even estimate how many onshore and offshore resources to engage in an upgrade project without knowing more about your environment and object analysis.  However, I would definitely recommend two key onshore roles:</p>
<ul>
<li><strong>Development Object Remediation Lead:</strong> an individual who has responsibility for coordinating and prioritizing the objects sent to the offshore team and managing the associated sign out and sign in process.  This person also has the unenviable task of serving as the quality control checkpoint and enforcer of expectations with the offshore team.  There should be a corresponding role in the offshore team, too.</li>
<li><strong>Development Object Remediation Senior Consultant:</strong> one or more individuals with the expertise to address the complex objects</li>
</ul>
<p>Smart use of offshore resources has the potential to reduce development object remediation cycle times and that should lead to direct cost savings.  Any steps that accelerate your overall upgrade project time line and contain costs should be viewed as a good thing.  Try it &#8211; you just might like it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/03/sap-upgrades-offshore-resources/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Build an SAP RFC Server using the SAP .Net Connector</title>
		<link>http://www.dataxstream.com/2010/03/build-an-sap-rfc-server-using-the-sap-net-connector/</link>
		<comments>http://www.dataxstream.com/2010/03/build-an-sap-rfc-server-using-the-sap-net-connector/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 13:30:58 +0000</pubDate>
		<dc:creator>Terry DeBruicker</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP Interface Blog]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[.Net Connector]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[Integration]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[SAP .Net Connector]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=4054</guid>
		<description><![CDATA[This blog post describes step-by-step how to use the SAP .Net Connector and Microsoft C# to create an SAP RFC Server. This allows an SAP process to call your custom C# code, which can accept parameters and return values. The SAP .Net Connector simplifies creating C# programs that can interoperate with an SAP host. The [...]]]></description>
			<content:encoded><![CDATA[<p>This blog post describes step-by-step how to use the SAP .Net Connector and Microsoft C# to create an SAP RFC Server. This allows an SAP process to call your custom C# code, which can accept parameters and return values.</p>
<p>The SAP .Net Connector simplifies creating C# programs that can interoperate with an SAP host. The SAP .Net Connector is available from the <a href="http://service.sap.com/connectors" target="_blank">SAP Service Marketplace</a>. You must have access to the SAP Service Marketplace to be able to download the SAP .Net Connector. The SAP .Net Connector must be installed on your development machine before we begin.</p>
<p>RFC is a Remote Function Call. In this case, the SAP process is a ‘client’ that is making an RFC call to our custom ‘server’ code. Our code uses the SAP .Net Connector to register on an SAP Application Gateway.</p>
<p>The TLA system we have been creating exists solely to demonstrate certain programming techniques involving the SAP .Net Connector and C#.  We will cover three separate parts of the solution: defining the function to SAP, creating a proxy object used to access SAP, and creating our C# code to perform the RFC function.</p>
<h2><span id="more-4054"></span>Defining the Function in SAP</h2>
<p>Before we build our RFC server, we will define our RFC function in the SAP system. There are two parts we will need to create:  the Function Signature, and the RFC Destination.</p>
<h3>Defining the RFC Function Signature</h3>
<p>Open the SAP SE37 Function Builder screen. For the Function Module field, enter <strong>Z_RFC_TLA_HELLO_WORLD</strong> and click Create. For the Function group, press the browse button to the right of the field, then select an appropriate function Group. Enter a short text description and click Save to save the function signature.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0013.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0013_thumb.jpg" border="0" alt="Image-0013" width="244" height="187" /></a></p>
<p>On the Attributes tab, be sure to select the <em>Remote-enabled module</em> radio button.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0027.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0027_thumb.jpg" border="0" alt="Image-0027" width="244" height="164" /></a></p>
<p>Now we will be asked to define the parameters that are used. SAP refers to values passed to the RFC call as Import values. Values that are returned from the RFC call are called Export values.</p>
<p>In the Function Builder screen, on the Import tab, define a Parameter named <strong>Name</strong>. Fill in the appropriate Type and Associated Type values. Be sure to check the Pass Value check box.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0016.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0016_thumb.jpg" border="0" alt="Image-0016" width="244" height="69" /></a></p>
<p>On the Export tab, create a Parameter named Hello_World. This will end up storing the result of the RFC call. Define the field in the same way as the Name import field.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0017.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0017_thumb.jpg" border="0" alt="Image-0017" width="244" height="75" /></a></p>
<p>Save your RFC Function. Then you need to activate your RFC function. To do that, from the SE37 screen, enter the function module name. then click the <em>Activate</em> button.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0019.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0019_thumb.jpg" border="0" alt="Image-0019" width="244" height="186" /></a></p>
<h3>Defining the RFC Destination</h3>
<p>SAP can direct an RFC call to different destinations. We will create an RFC Destination using SAP function SM59. This RFC Destination is used by the SAP system to route an RFC call to our program, which previously registered itself on the SAP Application Gateway.</p>
<p>In the SM59 screen, click the Create button.  Enter RFC destination of <strong>TLARFCSERVER</strong>. The Connection type is <strong>T</strong> for TCP/IP. Enter a description.</p>
<p>On the Technical settings tab, select Activation Type of <em>Registered Server Program</em>.</p>
<p>For the Registered Server Program Program ID, enter <strong>TlaRfcSrv</strong>. The Program ID we use here must match the Program ID used when our server code connects to the SAP Application Gateway.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0010.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0010_thumb.jpg" border="0" alt="Image-0010" width="346" height="387" /></a></p>
<p>If you try the Test connection button, it will fail, since we have not yet registered our program on the Application Gateway. Later, we can come back to SM59 and test this and see that our RFC destination is available.</p>
<h2>C# Code</h2>
<p>We will create an application that can be called from an SAP host. The SAP host will pass in a name, as a string. Our application will return a hello greeting back to the calling program.</p>
<p>Our solution will consist of two parts.</p>
<ol>
<li>The first part is the SAP .Net Connector Proxy project, named TlaRfcServerSapProxy. This will produce a Dynamic Link Library that encapsulates what we need to know to interoperate with the SAP host.</li>
<li>The second part is is our custom code project, named TlaRfcServer. This contains the code which will execute when called from the SAP host via RFC. Save the RFC destination.</li>
</ol>
<h3>Creating the SAP Proxy Project</h3>
<p>We will use Visual Studio 2003 to create a DLL that manages the interactions with the SAP host. The SAP .Net Connector version 2.0 works with Visual Studio 2003 or 2005. To use the .Net Connector in our preferred environment of Visual Studio 2008, we will create the proxy DLL in 2003 and add that to our 2008 project. The techniques are described in our earlier post, <a title="How to Build an SAP .Net Connector Proxy" href="http://www.dataxstream.com/2009/08/using-the-sap-net-connector-in-visual-studio-2008/" target="_blank">Using the SAP .Net Connector in Visual Studio 2008</a>.</p>
<p>In Visual Studio 2003, start a new Class Library project named TlaRfcServerSapProxy. Delete the default Class1.cs file that is created automatically.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0020.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0020_thumb.jpg" border="0" alt="Image-0020" width="341" height="248" /></a></p>
<p>From the Solution Explorer, Right-click on References and choose Add New References. Under the .Net tab, highlight SAP.Connector.dll and SAP.Connector.RFC. Click the Select button, then OK to add the SAP .Net Connector references.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0021.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0021_thumb.jpg" border="0" alt="Image-0021" width="352" height="246" /></a></p>
<p>Now add the SAP Connector Proxy to our project. Right click on the project and choose Add / Add New Item. Under the templates, highlight SAP Connector Proxy. In the Name field, give our proxy the name TlaRfcServerSapProxy.sapwsdl. The name we use here will become the object type name for our SAP Server Proxy object we use when we build our RFC server code.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0005.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0005_thumb.jpg" border="0" alt="Image-0005" width="353" height="280" /></a></p>
<p>The TlaRfcSerfverSapProxy.sapwsdl file will be displayed in Design mode. Right click on the Design surface and choose properties. This displays properties of our SAP Connector Proxy. Change the Proxy Type to Server.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0022.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0022_thumb.jpg" border="0" alt="Image-0022" width="359" height="127" /></a></p>
<p>Now we need to add in a reference to our SAP host so that we can pull in the signature and object model for our RFC function. Open the Server Explorer windows and expand SAP / Application Servers. Right-click on Application Servers and choose add New Server. Enter in the connection information for your SAP host. Click OK.</p>
<p>Expand the newly added SAP Server and right-click on Functions. Choose Add New Function Filter. In the Name Filter field, enter *HELLO* . The * is used as a wild card. Click OK to display our Z_TLA_RFC_HELLO_WORLD function in the Server Explorer.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0007.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0007_thumb.jpg" border="0" alt="Image-0007" width="351" height="150" /></a></p>
<p>Highlight the Z_TLA_RFC_HELLO_WORLD function in the Server Explorer, and drag it onto the TlaRfcServerSapProxy.sapwsdl design surface. This will add the necessary function signatures and object type definitions to the project.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0028.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0028_thumb.jpg" border="0" alt="Image-0028" width="350" height="121" /></a></p>
<p>Now attempt to build the project. It will fail, as we have not yet created the code to implement our remote function. But, when we ran the build, the SAP Connector generated an implementation stub for our server method. A new class was automatically added to our project, named TlaRfcServerSapProxyImpl.cs.</p>
<p>However, we desire to implement our RFC server using Visual Studio 2008.</p>
<p>So, we will modify this code so it will build, and later we will override the implementation from our Visual Studio 2008 project.</p>
<p>If you double-click on the build error, it will take you to the offending line of code. All we need to do is set the result of Hello_World to some value.  To prevent confusion with our Visual Studio 2008 code, we will just return foo.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0029.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0029_thumb.jpg" border="0" alt="Image-0029" width="356" height="73" /></a></p>
<p>Now build the TlaRfcSapServerProxy project and it will create TlaRfcServerSapProxy.dll, which we will use in our Visual Studio 2008 project.</p>
<h3>Creating the RFC Server Project</h3>
<p>Using Visual Studio 2008, create a C# console project named TlaRfcServer. In the Solution Explorer, right-click on References and choose Add New Reference. Using the Browse tab, select both SAP.Connector.dll and Sap.Connector.Rfc.dll, typically found in C:\Program Files\SAP\SAP .Net Connector 2.0.</p>
<p>Add a reference to the TlaRfcServerSapProxy.dll created earlier, also using the Browse tab. Add a reference to System.Web.Services using the .Net tab.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0024.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0024_thumb.jpg" border="0" alt="Image-0024" width="352" height="375" /></a></p>
<p>In our C# code, we need to provide the code to implement our RFC function, which we do by inheriting from TlaRfcServerSapProxyImpl and overriding the Hello World function.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0030.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0030_thumb.jpg" border="0" alt="Image-0030" width="357" height="141" /></a></p>
<p>On Line 3, with have our ‘using’ directive to include our custom proxy.</p>
<p>On line 8, we are creating a new class named SAPProxy, which is derived from our TlaRfcServerSapProxyImpl class that was created in our Visual Studio 2003 class.</p>
<p>On line 12 is the override of the Z_Tla_Rfc_Hello_World call. We provide our functionality and place the result in the Hello_World variable.</p>
<p>That concludes our class that will implement the RFC functionality.</p>
<p>Now we will finish off our console program so that we can establish our code on the SAP Application Gateway and execute it.</p>
<p>To do this,we will pass in command line arguments to our Main routine. These arguments are passed to the SAPProxy constructor, which uses them to connect to the correct SAP Application Gateway.</p>
<p>Each of our SAP Proxy objects are hosted by an SAPServerHost object, which is part of the SAP .Net Connector. The SAPServerHost object governs the connection to the SAP host.</p>
<p>Once we create the SAPProxy object and attach it to an SAPServerHost, we can start the host and that will cause our program to register and be available on the SAP Application Gateway.</p>
<p>Our program will continue to be available on the SAP Application Gateway as long as we have it running (until we press the enter key, in our example).</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0031.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0031_thumb.jpg" border="0" alt="Image-0031" width="369" height="212" /></a></p>
<p>On lines 22-25, we instantiate our proxy and SAP host. Notice how we pass in the command line arguments to the SAPProxy constructor (line 25).</p>
<p>We start the proxy on line 29. After we have done that, we can go back to the SAP SM59 function and test our RFC destination. If things are working, that test will success.</p>
<p>Our code will continue to be available until we press enter at line 37, after which we stop the SAP host.</p>
<h4>Command Line Arguments</h4>
<p>The command line arguments consist of three parts, and are specified in the Visual Studio environment under the Debug tab of the Project Properties display.</p>
<p>The three parts are</p>
<p>-aProgram ID</p>
<p>-XPort</p>
<p>-GHost</p>
<p>The Program ID specified here must match the Program ID we used when creating the SAP RFC Destination. In our case this is specified as –aTlaRfcSrv.</p>
<p>The Port field tells SAP what TCP/IP port to use. This is specified by –XSAPGW00. The SAPGW part specifies port 3300, we add whatever the 00 is to get the actual port number. In our case we are using port number 3300, so we use –XSAPGW00. If we wanted port 3302, we would have used –XSAPGW02.</p>
<p>The Host field is the DNS name or IP address of the SAP server.</p>
<p>So, your parameters will be different but they will look something like –aTlaRfcSrv –XSAPGW00 –Ghostname</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0032.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0032_thumb.jpg" border="0" alt="Image-0032" width="359" height="214" /></a></p>
<p>Now build and run TlaRfcServer. A console window will appear.</p>
<p>Go back to SAP and bring up the SM59 screen. Expand the TCP/IP connections and find TLARFCSERVER. Double click that to display the definition. When you click the Test Connection button, you should see something like :</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0034.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0034_thumb.jpg" border="0" alt="Image-0034" width="359" height="316" /></a></p>
<p>which indicates a successful test of the RFC destination.</p>
<p>Now we need to test our actual RFC function. Bring up the SAP SE37 screen. In the Function Module name, enter Z_TLA_RFC_HELLO_WORLD, which matches the name of the function signature we created earlier.</p>
<p>Press the F8 key to test the function. The Test Function Module screen is displayed.</p>
<p>For the RFC Target sys, we use the RFC Function destination we created earlier, TLARFCSERVER.</p>
<p>For the name field, type WORLD. Press F8 to execute the RFC call.</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0035.jpg" rel="shadowbox[sbpost-4054];player=img;"><img style="border-width: 0px;" src="http://www.dataxstream.com/wp-content/uploads/2010/02/Image0035_thumb.jpg" border="0" alt="Image-0035" width="360" height="213" /></a></p>
<p>This indicates a good test of our RFC function.</p>
<h4>Troubleshooting</h4>
<p>If things don’t work, check the following:</p>
<p>Program ID in RFC Destination matches –a parameter of TlaRfcServer command line.</p>
<p>Port number (SAPGW00) on TlaRfcSever comand line is set to correct port number.</p>
<p>Any firewalls in between the SAP host and the RFC Server program need to allow traffic in both directions over that port.</p>
<h2>Summary</h2>
<p>In this blog posting we have shown how you can call custom C# code from an SAP process.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/03/build-an-sap-rfc-server-using-the-sap-net-connector/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How To Implement Field-Level HRMD_A Reduction</title>
		<link>http://www.dataxstream.com/2010/02/how-to-implement-field-level-hrmd_a-reduction/</link>
		<comments>http://www.dataxstream.com/2010/02/how-to-implement-field-level-hrmd_a-reduction/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 13:08:42 +0000</pubDate>
		<dc:creator>Craig Stasila</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[SAP ABAP Blog]]></category>
		<category><![CDATA[SAP Interface Blog]]></category>
		<category><![CDATA[SAP Technical]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[ALE]]></category>
		<category><![CDATA[Craig Stasila]]></category>
		<category><![CDATA[HRMD_A]]></category>
		<category><![CDATA[IDOC]]></category>
		<category><![CDATA[Integration]]></category>
		<category><![CDATA[Interface]]></category>
		<category><![CDATA[SAP programming]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=4289</guid>
		<description><![CDATA[I love ALE.  It is super-powerful and, once you get the hang of it, is a snap to configure.  Recently, I was setting up an HRMD_A interface for my client.  Everything was going smoothly until I ran into a requirement to filter out the social security number (PERID), birthdate (GBDAT), and gender (GESCH) for privacy [...]]]></description>
			<content:encoded><![CDATA[<p>I love ALE.  It is super-powerful and, once you get the hang of it, is a snap to configure.  Recently, I was setting up an HRMD_A interface for my client.  Everything was going smoothly until I ran into a requirement to filter out the social security number (PERID), birthdate (GBDAT), and gender (GESCH) for privacy reasons.  All of these fields are in segment E1P0002.  Initially, I thought that this requirement was easy enough to accomplish.  I just created a IDOC reduction in transaction BD53 and filtered out the three fields.  I soon found out that while entire segments were getting reduced from the IDOC as configured, the individually reduced fields were still showing up in the IDOC.  What&#8217;s going on?!?<br />
<span id="more-4289"></span> Well, after some digging, I found <a href="https://service.sap.com/sap/bc/bsp/spn/sapnotes/index2.htm?numm=381766" target="_blank">OSS Note 381766</a>.  This note&#8217;s cause section states:</p>
<blockquote><p>The reduction at segment level (see also Note 301223) was facilitated in order to be able to copy message type HRMD_A. This involved setting the reduction at field level, which was not taken into account in the code because it is not possible to centrally determine which fields are mandatory and which are dependent for all country versions. In addition, for one info type there may several records for different periods of time, which may also cause a problem when you are reducing fields.</p></blockquote>
<p>So, in essence, field-level reduction isn&#8217;t supported for HRMD_A.  The solution supplied in the OSS note suggests creating user-exit code to filter out the unwanted fields.  I already have implemented BADI HRALE00OUTBOUND_IDOC to add some other processing logic (if you&#8217;re lucky I&#8217;ll cover that logic in this blog, too), so I have a module in which I can place the code. And while the code to loop through an IDOC and clear out all instances of E1P0002-PERID, E1P0002-GBDAT, and E1P0002-GESCH is very easy, I can&#8217;t help but think I can make the code more useful.  You see, I hate unitasking code.  I can see it now.  If I take the shortcut path and wrote the unitasking code to clear those 3 fields, the code won&#8217;t be in production for more than a month before the requirements change and now there is another field that needs to be filtered out as well.  With unitasking code, I would have to crack open the code, create a transport, unit test, transport to Q, integration test, wait for a transport window, blah, blah, blah.  Ugh!  What a waste of time for a minor change.  We can do better.</p>
<p>I decided to create a multi-tasking module that will work for HRMD_A message types.  The fields to be cleared will be stored in TVARV in the format &lt;SEGMENT&gt;-&lt;FIELD&gt; (e.g. E1P0002-PERID).  That way, whenever the HR functional team wanted to filter out a new field, all they had to do was to update a TVARV variable.</p>
<p>To implement the solution, I created a new method called CLEAR_IDOC_FIELDS in my class implementation for BADI HRALE00OUTBOUND_IDOC.  CLEAR_IDOC_FIELDS has the same method signature as IF_EX_HRALE00OUTBOUND_IDOC~IDOC_DATA_FOR_RECEIVER_MODIFY:</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/00-Method-Signature.jpg" rel="shadowbox[sbpost-4289];player=img;"><img class="alignnone size-full wp-image-4293" title="00 Method Signature" src="http://www.dataxstream.com/wp-content/uploads/2010/02/00-Method-Signature.jpg" alt="" width="605" height="163" /></a></p>
<p>The code is pretty straight forward.  To allow multiple interfaces to coexist in method CLEAR_IDOC_FIELDS, the TVARV variable that stores the fields to clear is in the format &#8216;ZHR_CLR_&#8217; concatenated with the IDOC message type.</p>
<pre style="background-color: #eaeaea; color: #222;">METHOD CLEAR_IDOC_FIELDS .
*----------------------------------------------------------------------*
* Class:     ZCL_IM_HRALE00OUTBOUNDIDOC                                *
* Method:    CLEAR_IDOC_FIELDS                                         *
* Author:    Craig Stasila                                             *
*----------------------------------------------------------------------*

  TYPES: BEGIN OF TY_FILTER,
           TABNAME   TYPE DFIES-TABNAME,
           FIELDNAME TYPE DFIES-FIELDNAME,
           POSITION  TYPE DFIES-POSITION,
           OFFSET    TYPE DFIES-OFFSET,
           LENG      TYPE DFIES-LENG,
        END OF TY_FILTER.

  DATA: WA_FILTER      TYPE TY_FILTER,
        LT_FILTER      TYPE TABLE OF TY_FILTER,
        LS_TABNAME     TYPE DDOBJNAME,
        LS_SAV_TABNAME TYPE DDOBJNAME.

  DATA: LS_NAME   TYPE TVARV-NAME,
        LT_TVARVC TYPE TABLE OF TVARVC,
        WA_TVARVC TYPE TVARVC.

  DATA: LT_DFIES TYPE TABLE OF DFIES,
        WA_DFIES TYPE DFIES.

  DATA: LR_SEGNAM TYPE RANGE OF EDIDD-SEGNAM,
        WR_SEGNAM LIKE LINE OF LR_SEGNAM.

  FIELD-SYMBOLS: &lt;FS&gt; TYPE LINE OF EDIDD_TT.

* Fields to clear are in variable
  CONCATENATE 'ZHR_CLR_' MESTYP INTO LS_NAME.

* Get list of fields to clear from TVARV
  SELECT * FROM TVARVC
    INTO TABLE LT_TVARVC
   WHERE NAME = LS_NAME
     AND TYPE = 'S'.

  CHECK SY-SUBRC = 0.

* Build list of fields to clear
  LOOP AT LT_TVARVC INTO WA_TVARVC.
    CLEAR WA_FILTER.
    SPLIT WA_TVARVC-LOW AT '-' INTO WA_FILTER-TABNAME WA_FILTER-FIELDNAME.
    CHECK SY-SUBRC = 0.

    COLLECT WA_FILTER INTO LT_FILTER.
  ENDLOOP.

  SORT LT_FILTER BY TABNAME.
  CLASS CL_ABAP_CHAR_UTILITIES DEFINITION LOAD.

* Get field offsets
  LOOP AT LT_FILTER INTO WA_FILTER.
    LS_TABNAME = WA_FILTER-TABNAME.

    IF LS_TABNAME NE LS_SAV_TABNAME.

      CALL FUNCTION 'DDIF_NAMETAB_GET'
        EXPORTING
          TABNAME   = LS_TABNAME
        TABLES
          DFIES_TAB = LT_DFIES
        EXCEPTIONS
          NOT_FOUND = 1
          OTHERS    = 2.

      IF SY-SUBRC &lt;&gt; 0.
        CONTINUE.
      ENDIF.

      SORT LT_DFIES BY TABNAME FIELDNAME.

    ENDIF.

    LS_SAV_TABNAME = LS_TABNAME.

    READ TABLE LT_DFIES INTO WA_DFIES
         WITH KEY TABNAME   = WA_FILTER-TABNAME
                  FIELDNAME = WA_FILTER-FIELDNAME
         BINARY SEARCH.

    CHECK SY-SUBRC = 0.

    WA_FILTER-POSITION = WA_DFIES-POSITION.
    WA_FILTER-OFFSET   = WA_DFIES-OFFSET / CL_ABAP_CHAR_UTILITIES=&gt;CHARSIZE.
    WA_FILTER-LENG     = WA_DFIES-LENG.

    MODIFY LT_FILTER FROM WA_FILTER.

* Build segment name range
    IF SY-SUBRC = 0.
      WR_SEGNAM-SIGN   = 'I'.
      WR_SEGNAM-OPTION = 'EQ'.
      WR_SEGNAM-LOW    = WA_FILTER-TABNAME.
      COLLECT WR_SEGNAM INTO LR_SEGNAM.
    ENDIF.
  ENDLOOP.

* Loop at IDOC to clear fields
  LOOP AT IDOC_DATA ASSIGNING &lt;FS&gt;.
    IF &lt;FS&gt;-SEGNAM IN LR_SEGNAM.
      LOOP AT LT_FILTER INTO WA_FILTER WHERE TABNAME = &lt;FS&gt;-SEGNAM.
        CLEAR &lt;FS&gt;-SDATA+WA_FILTER-OFFSET(WA_FILTER-LENG).
      ENDLOOP.
    ENDIF.
  ENDLOOP.
ENDMETHOD.</pre>
<p>I also added the following code to IF_EX_HRALE00OUTBOUND_IDOC~IDOC_DATA_FOR_RECEIVER_MODIFY:</p>
<pre style="background-color: #eaeaea; color: #222;">* Clear IDOC fields
CALL METHOD ME-&gt;CLEAR_IDOC_FIELDS
  EXPORTING
     IDOC_CONTROL = IDOC_CONTROL
     RECEIVER     = RECEIVER
     MESTYP       = IDOC_CONTROL-MESTYP
  CHANGING
     IDOC_DATA    = IDOC_DATA.</pre>
<p>Finally, I maintained the following TVARV variable:</p>
<p><a href="http://www.dataxstream.com/wp-content/uploads/2010/02/01-TVARV-Variable.jpg" rel="shadowbox[sbpost-4289];player=img;"><img class="alignnone size-full wp-image-4311" title="01 TVARV Variable" src="http://www.dataxstream.com/wp-content/uploads/2010/02/01-TVARV-Variable.jpg" alt="" width="611" height="362" /></a></p>
<p>That&#8217;s all it takes!  Now individual field values can be easily be filtered from outbound HRMD_A IDOCs!.</p>
<p><em>UPDATE: </em>My colleague informed me that instead of using TVARV, I should continue to use BD53 to manage the IDOC reduction and change my code to look up the field reductions in TBD24.  This would be a great idea, but my full HRMD_A solution uses custom filter objects and a custom IDOC formatting function module.  <a href="http://www.dataxstream.com/2010/02/bd53-doesn%E2%80%99t-play-well-with-others/" target="_self">And BD53 does not play well with these customizations.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2010/02/how-to-implement-field-level-hrmd_a-reduction/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>DataXstream Workflow Troubleshooting Guide</title>
		<link>http://www.dataxstream.com/2009/12/dataxstream-workflow-troubleshooting-guide/</link>
		<comments>http://www.dataxstream.com/2009/12/dataxstream-workflow-troubleshooting-guide/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 17:00:43 +0000</pubDate>
		<dc:creator>Dataxstream</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[ABAP]]></category>
		<category><![CDATA[DataXstream]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[ERP]]></category>
		<category><![CDATA[IT]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[SAP]]></category>
		<category><![CDATA[solutions]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[Thomas Nittman]]></category>
		<category><![CDATA[troubleshooting]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://www.dataxstream.com/?p=410</guid>
		<description><![CDATA[This article focuses on practical techniques used to assist in the debugging and resolving workflow issues during the development and production support phases of SAP implementations.]]></description>
			<content:encoded><![CDATA[<p>By: Thomas Nittmann</p>
<p>Description:<br />
This article focuses on practical techniques used to assist in the debugging and resolving workflow issues<br />
during the development and production support phases of SAP implementations.  The SAP Workflow<br />
application incorporates the use of several components, i.e. graphical editing tool (workflow builder),<br />
some object orientated concepts (use of the Business Object Repository), ABAP, and a hook/trigger<br />
mechanism into one of the SAP application modules (FI, CO, MM, etc).  As business requirements are<br />
mapped into a workflow process definition and prototyping starts, debugging becomes an essential tool<br />
to expedite the implementation of workflow process.</p>
<h4>To read more about SAP Workflow Troubleshooting please download the whitepaper <a href="http://www.dataxstream.com/success-stories/whitepapers/white-paper-request/">here</a> or simply click on the &#8220;Learn More&#8221; tab to the right to request this and other DataXstream white papers.</h4>
<p>Q2Q3Y6XJM37U</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dataxstream.com/2009/12/dataxstream-workflow-troubleshooting-guide/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

