Create routings with recordings. Part 3 of 4.

Jimbo's picture

In many implementation projects for SAP it is necessary to break down the most complicated objects into manageable pieces for the purposes of time and energy. Routing data pulled from a legacy SAP system tends to load quite easily into a new system using the standard Direct Input or BAPI method, but this client wasn't using routings before.

Unlike other master data objects, The Routings were being created from scratch or rewritten to include alternate and parallel sequences. This exercise was spearheaded by Jagdish Lakshminarayanan, CSCP®, a supply chain expert, who had worked closely with SAPLSMW to define business rules to identify and monitor data exceptions as part of the LSMW upload process.

When the routings have never existed before the source file must come from manual data manipulation. Many system integrators will make customizations to routings by unnecessarily setting some fields as mandatory hoping that this setting will simplify their own jobs. In these cases the ease in which routings can be loaded is greatly diminished and alternative load methods grow from necessity.

Creating a routing header with a recording isn't very difficult and adding sequences with operations isn't very difficult either. Performing BOM allocations can be painfully difficult using a recording, but it is possible with some simple code.

Start by making a recording of a simple BOM allocation. For this example the client was using individual group codes for each routing, so the CA01 recording starts by populating the group field and clicking the "Sequences" button. This series of steps takes us to the Component Allocation screen with a stop along the way to populate the description of the Standard Sequence.


Luckily, each routing was assigned a single BOM, so just pressing "Enter" selects the first and only BOM (or Material Header).

Here is where it gets tricky. Each BOM has a different number of components and they must be allocated to different operations in the routing. It is unfeasible to create a recording for every combination of BOM item count and routing operation number, so a single recording with minor programmatic manipulation is used in this case. Select the first component and then click the "New Assignment" button. Populate the New Assignment window with the data from the source file and press "Enter". Then click the "Save" button.

The recording is created but will need some minor manual manipulation to handle various BOM components. Allocating to a specific operation in a specific sequence is made easy by the recording; simply populating the VORNR and PLNFL fields is enough. Selecting the BOM component automatically is more difficult--especially when the system contains alternate BOMs. Start by renaming the selection flag for the sequence as shown here. The default field name is the same as the field name for the first BOM component selection flag and changing the name will make it easier to identify later and prevent errors cause by ambiguous naming.

Add 8 more selection flags for the BOM components. If the target system has BOMs with more than 8 components then add more selection flags. Select the first flag and then click on Edit→Add Screen Field (Extended). Type the name of the second selection flag (see below) and press "Enter". Repeat for selection flags 3 to 9 and then rename the fields BOM_SEL_01 - 09. Save the recording and assign it as the recording for the new LSMW object.

Assign the obvious source fields to the recording fields in Maintain Field Mapping and Conversion Rules. The tricky part is selecting the correct BOM item from the correct alternate BOM. If there are no alternate BOMs created, then the first BOM (Alternate 1) will be selected. Here we recycle some code from SAP to find the number of the component in the alternate BOM that has the exact combination of header material, component position and component specified in the routing source file. With any luck the BOM and Routings source files were created by the same people from the same source data at the same time.

Add this snippet of code to the Global Definitions section of the LSMW. The p_STLAL parameter is explained in detail below. The variables store the BOM item number and the number of the alternate BOM that contains the component.

parameters:
 p_STLAL like STKO-STLAL default '01',
 p_Verbos as checkbox.

data: nItem type i, lSTLAL like STKO-STLAL.

Add this snippet of code to the Form Routines section of the LSMW. This code, when passed the header material number, plant, position and component will return the line item and alternate BOM number.

form GET_BOM_ITEM using lvMATNR lvWERKS lvPOSNR lvIDNRK
 changing lvItem type i lvSTLAL like MAST-STLAL.
  data: lvMAST like MAST, lvItemNo type i,
        lt_stko     type table of STKO_API02,
        lt_stpo     type table of STPO_API02,
        l_stpo type STPO_API02,
        l_flwarning type CAPIFLAG-FLWARNING.

  if lvMATNR co '1234567890 '.
    shift lvMATNR right deleting trailing space.
    overlay lvMATNR with '000000000000000000'.
  endif.

  move '00' to lvSTLAL.
  move 0 to lvItem.

  select * from MAST into lvMAST where MATNR eq lvMATNR.

    CALL FUNCTION 'CSAP_MAT_BOM_READ'
         EXPORTING
              MATERIAL       = lvMATNR
              PLANT          = lvWERKS
              BOM_USAGE      = '1'
              ALTERNATIVE    = lvMAST-STLAL
              VALID_FROM     = ''
         IMPORTING
              FL_WARNING     = l_flwarning
         TABLES
              T_STPO         = lt_stpo
              T_STKO         = lt_stko
         EXCEPTIONS
              ERROR          = 1
              OTHERS         = 2.

    move 0 to lvItemNo.
    loop at lt_stpo into l_stpo.
      add 1 to lvItemNo.
      if lvIDNRK cs l_stpo-COMPONENT and l_stpo-ITEM_NO eq lvPOSNR.
        move lvItemNo to lvItem.
        move lvMAST-STLAL to lvSTLAL.
      endif.
    endloop.

  endselect. " Select * from mast . . .
endform.

Now add this snippet to the field code for the first BOM item selection flag. This is the field BOM_SEL_01 that we created above. This code places a check in the correct BOM_SEL_... flag such that the correct BOM component is ticked when the recording clicks the "New Assignment" button. Additionally, we resolve another problem wherein the recording did not present us with the opportunity to select the appropriate Alternate BOM. In a system where there are no alternate BOMs this is a non-issue, but in many cases there are.

The issue of alternate BOMs is resolved by creating batches with only allocations to BOMs with a particular alternate number. For example, if the parameter p_STLAL is set to 2 then the converted data (and the the batch that is created using that data) will only contain allocations to alternate BOMs with the number two. Then, while the batch is running in "Display Errors Only" mode, the operator need only double-click the number 2 alternate BOM for each allocation. It's a pretty rough solution, but it's faster and more accurate than manual entry.

*
*  Determine the BOM item no (in alternate BOM).
*
perform GET_BOM_ITEM using CA01BO-MATNR CA01S-WERKS
 CA01BO-POSNR CA01Bo-IDNRK changing nItem lSTLAL.

if nItem eq 0.  "BOM has no item at that POSNR.
  write: / CA01S-PLNNR_NEW, CA01BO-MATNR, CA01BO-POSNR, CA01BO-IDNRK,
   'No combination of POSNR/IDNRK exists for header material.'
   color col_negative.
  skip_record.
elseif lSTLAL ne p_STLAL.
  if p_Verbos eq 'X'.
    write: / CA01S-PLNNR_NEW, CA01BO-MATNR, CA01BO-POSNR,
     'Skipping Alternate BOM', lSTLAL color 3.
  endif.
  skip_record.
else.
  case nItem.
    when 1. CA01A-BOM_SEL_01 = 'X'.
    when 2. CA01A-BOM_SEL_02 = 'X'.
    when 3. CA01A-BOM_SEL_03 = 'X'.
    when 4. CA01A-BOM_SEL_04 = 'X'.
    when 5. CA01A-BOM_SEL_05 = 'X'.
    when 6. CA01A-BOM_SEL_06 = 'X'.
    when 7. CA01A-BOM_SEL_07 = 'X'.
    when 8. CA01A-BOM_SEL_08 = 'X'.
    when 9. CA01A-BOM_SEL_09 = 'X'.
  endcase.
endif.

The entire four-part LSMW project including recordings, source code and LSMW objects is available here.

Update: On larger projects performing the BOM Allocation may take several hours. To expedite delta loads add this snippet of code to the BOM Item selection routine to skip records that have already been allocated.

  select * from MAST into lMAST
   where MATNR eq CA01BO-MATNR
     and WERKS eq CA01S-WERKS
     and STLAL eq CA01BO-STLAL.
    shift CA01S-PLNAL right deleting trailing space.
    overlay CA01S-PLNAL with '00'.
    shift CA01BO-PLNFL right deleting trailing space.
    overlay CA01BO-PLNFL with '000000'.
    select * from PLMZ into lPLMZ
     where PLNNR eq CA01S-PLNNR_NEW
       and PLNAL eq CA01S-PLNAL
       and PLNFL eq CA01BO-PLNFL
       and STLNR eq lMAST-STLNR
       and STLAL eq lMAST-STLAL
       and STLKN eq nItem.
      if p_update ne 'X'.
        if p_Verbos eq 'X'.
          write: / CA01S-PLNNR_NEW, CA01BO-MATNR, CA01BO-POSNR,
           'BOM Item already allocated', lSTLAL color 3.
        endif.
        skip_record.
      endif.
    endselect.
  endselect.