Enterprise Resource Planning Blogs by Members
Gain new perspectives and knowledge about enterprise resource planning in blog posts from community members. Share your own comments and ERP insights today!
cancel
Showing results for 
Search instead for 
Did you mean: 
Abhishek_Parab
Active Participant

Hi Guys,

In this blog we are going to see the process of creating a custom Migration Object and the various Little Things that can be done to the migration object. You will be learning.

1. How to create a  Custom Function Module  for Migration object not available in SAP Standar

2. Create Custom Translation Object.

3.  Out of the Box Reporting Capability of MIgration Cockpit.

 

1. Create a Custom Function Module.

Lets say we want to migrate, Several Certificate profile as of S4 HANA 2023, there is no Standard Migration Object Given by SAP to meet the requirement, but there are guidelines given by SAP, mentioning below is a summary as per the SAP user Guide.

1. commit work and Rollback work statement should not be written in the custom Function module, as the SAP Migration cockpit takes care of the same.

2 For Error Handling the function module must use the ABAP Dictionary structure BAPIRET2 as a structure to return messages to the SAP S/4HANA migration object modeler. Also the function module should not throw a exception, and lastly Abort message should be converted to Error Message.

3. The function module must have a TESTRUN FLAG, so that the Migration object can be run in the Simulation Mode.

4. Developers can implement Consistency check and Plausibility Check similar to one mentioned in the Standard Migration Object FM : BAPI_ACC_DOCUMENT_CHECK for Plausibility check.

 

considering the above statement, the function module should look like this somewhat

first we create a Table type using se11

on a similar fashion create for qcvm and qcvv and use the same in the importing of the function module. 

Abhishek_Parab_0-1708886352588.png

Abhishek_Parab_2-1708886573975.png

Code for function module.

Please note : The Below code also consist of Logic to create a Status Object Number and Depending on the user Input fields for the data migration, the certificate profile is created in the Released Status or in the Created status.

AREAS OF IMPROVEMENT :  Current Code is not designed to handle the User status Profile, but depending on the business requirement, the below code should be modified to fit the purpose. Also the Code is not well Written as it is from the functional Perspective, More well Talented ABAPer can enhance it further.

 

 

 

 

FUNCTION zqc01_create.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" VALUE(TESTRUN) LIKE BAPIE1GLOBAL_DATA-TESTRUN OPTIONAL
*" VALUE(ST_QCVK) TYPE ZTT_QCVK OPTIONAL
*" VALUE(ST_QCVM) TYPE ZTT_QCVM OPTIONAL
*" VALUE(ST_QCVV) TYPE ZTT_QCVV OPTIONAL
*" VALUE(RELEASE) TYPE XFELD OPTIONAL
*" TABLES
*" RETURN STRUCTURE BAPIRET2 OPTIONAL
*"----------------------------------------------------------------------
DATA : ls_qcvk TYPE qcvk,
lt_qcvk TYPE TABLE OF qcvk,
ls_qcvv TYPE qcvv,
lt_qcvv TYPE TABLE OF qcvv,
ls_qcvm TYPE qcvm,
lt_qcvm TYPE TABLE OF qcvm,
lt_onnr TYPE TABLE OF onr00,
wa_onnr TYPE onr00,
lt_JSTAT TYPE TABLE OF jstat,
wa_JSTAT TYPE jstat,
lv_release type QKZ.

MOVE RELEASE TO LV_RELEASE.

LOOP AT st_qcvk ASSIGNING FIELD-SYMBOL(<fs_qcvk>).
"check if data already exist in the system.
SELECT SINGLE * FROM qcvk INTO _qcvk WHERE ctyp = @<fs_qcvk>-ctyp AND vorlnr = @<fs_qcvk>-vorlnr AND version = @<fs_qcvk>-version.
IF sy-subrc EQ 0.
PERFORM set_return_message USING 'E' '' '' <fs_qcvk>-vorlnr <fs_qcvk>-version <fs_qcvk>-ctyp 'already exist in the system' CHANGING return.
APPEND return TO return.
ENDIF.

" check if valid certificate type has been given the load file.
SELECT SINGLE * FROM tq05 INTO _Qcvk WHERE zgtyp = @<fs_qcvk>-ctyp.
IF sy-subrc NE 0.
PERFORM set_return_message USING 'E' '' '' <fs_qcvk>-ctyp 'is not a valid certificate type' space space CHANGING return.
APPEND return TO return.
ENDIF.
"check if valid stock transfer level has been specified in the load file
IF <fs_qcvk>-withtransf = '1' OR <fs_qcvk>-withtransf = 'X' .
PERFORM set_return_message USING 'E' '' '' 'Not a Valid Stock Transfer level has been defined' space space space CHANGING return.
APPEND return TO return.
ENDIF.

ENDLOOP.
"check whether the characteristics exist in the database or not
LOOP AT st_qcvk ASSIGNING <fs_qcvk>.
LOOP AT st_qcvm ASSIGNING FIELD-SYMBOL(<fs_qcvm>) WHERE ctyp = <fs_qcvk>-ctyp AND vorlnr = <fs_qcvk>-vorlnr AND version = <fs_qcvk>-version .
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = <fs_qcvm>-version
IMPORTING
output = <fs_qcvm>-version.

SELECT SINGLE * FROM qpmk INTO @DATA(ls_qpmk) WHERE zaehler = @<fs_qcvm>-zaehler AND mkmnr = @<fs_qcvm>-mkmnr AND version = @<fs_qcvm>-version.
IF sy-subrc NE 0.
PERFORM set_return_message USING 'E' 'QS' '145' <fs_qcvm>-zaehler <fs_qcvm>-mkmnr <fs_qcvm>-version space CHANGING return.
APPEND return TO return.
ELSE.
MOVE '1' TO <fs_qcvm>-blocknr.
MOVE sy-tabix TO <fs_qcvm>-merkmalnr.
TRANSLATE <fs_qcvm>-vorlnr TO UPPER CASE.

APPEND <fs_Qcvm> TO lt_qcvm.
PERFORM set_return_message USING 'I' '' '' <fs_qcvk>-vorlnr <fs_qcvk>-version <fs_qcvk>-ctyp 'will be loaded' CHANGING return.
ENDIF.
ENDLOOP.
ENDLOOP.

* SELECT SINGLE stsma FROM tq05 INTO @DATA(ls_status_profile) WHERE zgtyp = @<fs_qcvk>-ctyp.

" Get internal object number.
DATA : lc_objnR_new TYPE qcvk-objnr.
DATA : lc_objnr_old TYPE qcvk-objnr.

CALL FUNCTION 'QAST_STATUS_OBJECT_CREATE'
EXPORTING
iv_obtyp = 'QC1'
iv_stsma = ''
IMPORTING
ev_objnr = lc_objnr_old
EXCEPTIONS
invalid = 1
OTHERS = 2.
IF sy-subrc <> 0.
"Implement suitable error handling here
ENDIF.

IF RELEASE NE 'X'.
CLEAR lt_jstat.
wa_JSTAT-stat = 'I0098'.
wa_jstat-inact = ''.
APPEND wa_jstat TO Lt_jstat.
CLEAR wa_jstat.
wa_JSTAT-stat = 'I0001'.
wa_jstat-inact = 'X'.
APPEND wa_jstat TO Lt_jstat.
ELSE.
CLEAR lt_jstat.
wa_JSTAT-stat = 'I0098'.
wa_jstat-inact = 'X'.
APPEND wa_jstat TO Lt_jstat.
CLEAR wa_jstat.
wa_JSTAT-stat = 'I0001'.
wa_jstat-inact = 'X'.
APPEND wa_jstat TO Lt_jstat.
wa_JSTAT-stat = 'I0002'.
wa_jstat-inact = ''.
APPEND wa_jstat TO Lt_jstat.
ENDIF.
"update object number to ONR00 table

*
* CALL FUNCTION 'STATUS_BUFFER_SET_OBJECT'
* EXPORTING
* client = sy-mandt
* objnr = lc_objnr_old
* obtyp = 'QC1'
* stsma = ''
* TABLES
* status = lt_jstat.
*
* CALL FUNCTION 'STATUS_BUFFER_EXPORT_TO_MEMORY'
* EXPORTING
* i_memory_id = 'BSVA_BUFFER'.

CALL FUNCTION 'OBJECT_NUMBER_GET_GENERIC'
EXPORTING
i_obart = 'QC'
i_objectkey = ''
IMPORTING
e_objnr = lc_objnr_new
EXCEPTIONS
number_already_exists = 1
obart_invalid = 2
objectkey_missing = 3
OTHERS = 4.

IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
*
* CALL FUNCTION 'OBJECT_NUMBER_GET_QC'
* IMPORTING
* objnr = lc_objnr_new.

CALL FUNCTION 'STATUS_OBJECT_SWITCH_NUMBER'
EXPORTING
client = sy-mandt
objnr_new = lc_objnr_new
objnr_old = lc_objnr_old
EXCEPTIONS
object_not_found = 1
objnr_new_invalid = 2
objnr_old_invalid = 3
status_object_already_exists = 4
OTHERS = 5.
IF sy-subrc <> 0.
"Implement suitable error handling here
ENDIF.

CALL FUNCTION 'OBJECT_NUMBER_SAVE_GENERIC'
EXPORTING
i_update_task = 'X'.


CALL FUNCTION 'STATUS_CHANGE_INTERN'
EXPORTING
* CHECK_ONLY = ' '
* CLIENT = SY-MANDT
objnr = lc_objnr_new
* ZEILE = ' '
* SET_CHGKZ =
* IMPORTING
* ERROR_OCCURRED =
* OBJECT_NOT_FOUND =
* STATUS_INCONSISTENT =
* STATUS_NOT_ALLOWED =
TABLES
status = lt_jstat
EXCEPTIONS
object_not_found = 1
status_inconsistent = 2
status_not_allowed = 3
OTHERS = 4.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.

"Define internal fields.
<fs_qcvk>-objnr = lc_objnr_new.
* <fs_qcvk>-stsma = ls_status_profile.
<fs_qcvk>-obtyp = 'QC1'.
<fs_qcvk>-ersteller = sy-uname.
<fs_qcvk>-ersteldat = sy-datum.
TRANSLATE <fs_qcvk>-vorlnr TO UPPER CASE.

IF testrun NE 'X'.
GET TIME STAMP FIELD <fs_qcvk>-changeddatetime.
ENDIF.

CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = <fs_qcvk>-version
IMPORTING
output = <fs_qcvk>-version.

APPEND <fs_qcvk> TO lt_qcvk.

"check whether the material exist in the database or not.
LOOP AT st_qcvk ASSIGNING <fs_qcvk>.
LOOP AT st_qcvv ASSIGNING FIELD-SYMBOL(<fs_qcvv>) WHERE ctyp = <fs_qcvk>-ctyp AND vorlnr = <fs_qcvk>-vorlnr AND version = <fs_qcvk>-version.
SELECT SINGLE * FROM mara INTO @DATA(ls_mara) WHERE matnr = @<fs_qcvv>-matnr.
IF sy-subrc NE 0.
PERFORM set_return_message USING 'E' 'M3' '305' <fs_qcvv>-matnr space space space CHANGING return.
APPEND return TO return.
ELSE.
SELECT SINGLE * FROM mara INTO ls_mara WHERE matnr = <fs_qcvv>-matnr AND lvorm NE 'X'.
IF sy-subrc NE 0.
PERFORM set_return_message USING 'E' 'M3' '008' space space space space CHANGING return.
APPEND return TO return.
ELSE.
SELECT SINGLE * FROM tq30 INTO @DATA(ls_tq30) WHERE art = @<fs_qcvv>-art.
IF sy-subrc NE 0.
PERFORM set_return_message USING 'E' '' '' 'No Valid Inspection type has been specified' space space space CHANGING return.
APPEND return TO return.

ELSE.
SELECT SINGLE * FROM tq31 INTO @DATA(ls_tq31) WHERE herkunft = @<fs_qcvv>-herkunft.
IF sy-subrc NE 0.
PERFORM set_return_message USING 'E' '' '' 'No Valid Inspection lot origin has been specified' space space space CHANGING return.
APPEND return TO return.
ELSE.
APPEND <fs_qcvv> TO lt_qcvv.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDLOOP.
ENDLOOP.


IF NOT return-id = 'E'.
MODIFY qcvk FROM TABLE lt_qcvk.
MODIFY qcvv FROM TABLE lt_qcvv.
MODIFY qcvm FROM TABLE lt_qcvm.

ELSE.
CLEAR ls_qcvk.
CLEAR lt_qcvk.
CLEAR ls_qcvv.
CLEAR lt_qcvv.
CLEAR ls_qcvm.
CLEAR lt_qcvm.
ENDIF.

IF testrun EQ 'X'.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
* ELSE.
* CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
* EXPORTING
* wait = 'X'.
* IMPORTING
* RETURN =
ENDIF.

ENDFUNCTION.

 

 

Code for the set_return_message.

 

 

 

*----------------------------------------------------------------------*
***INCLUDE LZQIRF01.
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form set_return_message
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> P_
*&      --> P_
*&      --> P_
*&      --> CUSTOMERNUMBER
*&      --> P_
*&      --> SPACE
*&      --> SPACE
*&      <-- RETURN
*&---------------------------------------------------------------------*

FORM set_return_message  USING  VALUE(p_msgty)
                              VALUE(p_msgid)
                              VALUE(p_msgno)
                              VALUE(p_msgv1)
                              VALUE(p_msgv2)
                              VALUE(p_msgv3)
                              VALUE(p_msgv4)
                     CHANGING p_return LIKE bapiret2.

      DATA: BEGIN OF message,
          msgty LIKE bapiret2-type,
          msgid LIKE bapiret2-id,
          msgno LIKE bapiret2-number,
          msgv1 LIKE bapiret2-message_v1,
          msgv2 LIKE bapiret2-message_v2,
          msgv3 LIKE bapiret2-message_v3,
          msgv4 LIKE bapiret2-message_v4,
        END OF message.

         message-msgty = p_msgty.
  message-msgid = p_msgid.
  message-msgno = p_msgno.
  message-msgv1 = p_msgv1.
  message-msgv2 = p_msgv2.
  message-msgv3 = p_msgv3.
  message-msgv4 = p_msgv4.

   CALL FUNCTION 'BALW_BAPIRETURN_GET2'
    EXPORTING
      type   = message-msgty
      cl     = message-msgid
      number = message-msgno
      par1   = message-msgv1
      par2   = message-msgv2
      par3   = message-msgv3
      par4   = message-msgv4
*     log_no = ' '
*     log_msg_no = ' '
    IMPORTING
      return = p_return
    EXCEPTIONS
      OTHERS = 1.
ENDFORM.

 

 

Code for the PLV

 

 

 

 

 

*&---------------------------------------------------------------------*
*& Include ZDMC_PLV_OLO_SIF_CERT_PROF
*&---------------------------------------------------------------------*


LOOP AT _lt_io_r_st_qcvk INTO _wa_io_r_st_qcvk .

PERFORM _rule_plv_olo_p
     USING
     _wa_io_r_st_qcvk-ctyp           "key value1
     _wa_io_r_st_qcvk-VORLNR       "key value2
     _wa_io_r_st_qcvk-VERSION                          "key value3
      ''
      ''.                            "key value4
             "additional text

  ENDLOOP.
*embed Include DMC_PLV_OLO for PLV processing
INCLUDE dmc_plv_olo.

** End of block for PLV application **

 

 

 

Step 2 : Create a Custom migration Object:

First we need to have a project created in Migrate your Data Fiori App.

Abhishek_Parab_0-1708891940105.png

Abhishek_Parab_1-1708891999276.png

In the same Project, we create a Migration object  > User Defined  > Using Staging table.

Abhishek_Parab_0-1708887142177.png

Next we define the source Structure, which will have the fields of our area of interest. The advantage of this is we can add more fields as the target structure qcvk, qcvv and qcvm supports it.

Abhishek_Parab_2-1708887227852.pngAbhishek_Parab_3-1708887233952.pngAbhishek_Parab_4-1708887241929.png

After we define the source structure we define the Relationship between the source and Target Structure.

Abhishek_Parab_5-1708887280632.png

Abhishek_Parab_7-1708887309542.png

As QCVM is a Item table, which will consist of the Characteristics for each of the Header Certificate profile, so the header Table in such cases will be Mapping only and the Item table will Loop at Table.

Abhishek_Parab_6-1708887286689.png

After the structure Relations are established, we need to do the fields mapping between the source and destination ( function module Import Parameters ) fields.

Abhishek_Parab_0-1708887818634.png.

Now assume a scenario, where we extract the data from the table and load the data in the excel, but as the Material number is changing in every SAP Instance , Dev, QA, Pre Prod and Prod. A Mapping object ( Translation Object ) Becomes handy.

Here we can leverage the Standard Pre-Delivered SAP Mapping Rules or we can create our own Rules with a check to the Standard Configuration value.

in the target field , just right click and click on assign rule and select from the available standard for the project.

 

Lets assume , we want to create a Translation object.

1.First we need to create a Translation object.

Abhishek_Parab_1-1708888249101.png

Abhishek_Parab_2-1708888279117.png

Abhishek_Parab_3-1708888306711.pngAbhishek_Parab_4-1708888313027.png

Please note the Translation object is create at the Sub-project Level and not at the migration object Level.

Abhishek_Parab_5-1708888380221.png

the Advantage of creating at the subproject level, is other objects Standard or custom Developed in the same project can use it.

Now we create a rule at the subproject Level with a similar intention so that it can be leveraged at Cross Object Level.

Abhishek_Parab_2-1708892085465.png

Note  :  if the mapping object is defined at the Project level then at the end of the Mapping object _M is to be added if its subproject then _S, if at the Object level then just the name of Translation object is enough

At the end in the field mapping of the LTMOM assign the assign to the required field.

Abhishek_Parab_3-1708892220043.png

Once all the process is complete Generate the migration Object, after that, the migration object is visible in the FIORI app : Migrate your Data.

Abhishek_Parab_0-1708892335094.png

Hope you a bit of insight of the possibility of the data Migration using Migrate Your Data Fiori app

 

Happy Learning:

 

Thanks and Regards,

Abhishek Parab.

 

 

 

 

 

 

 

 

 

 

3 Comments
Labels in this area