3

I'm facing to a problem today: how to update the MARA table with custom and non-custom fields?

I found some solutions, but I would like to know what is the best solution.

I came from HCM module. On this module we have changelogs. So I would like to update the MARA table with log changes if possible.

Context:

  1. Select one MARA entry from the table (OK)
  2. Edit fields (OK)
  3. Check for each fields, if the new value is already on the available values
  4. Update the table

Logic:

DATA:
  lt_mara TYPE TABLE OF mara,
  ls_mara TYPE mara.

lv_matnr = '000000000024856';

* Seelct data
"" matnr from CONVERSION_EXIT_MATN1_INPUT
SELECT SINGLE * INTO ls_mara FROM mara WHERE matnr = lv_matnr.

* Modification
ls_mara-vlumn = '999.9'. 
"ls_mara-z* = '...'.   

* Checks : volumn is numeric, ...
" [...]

* Update
" [...]

I have only information about the MARA, no data about related tables.

Solution 1 - MATERIAL_MAINTAIN_DARK

Use function module MATERIAL_MAINTAIN_DARK.

CALL FUNCTION 'MATERIAL_MAINTAIN_DARK'
    EXPORTING
        kz_activ_cad = blank
        flag_muss_pruefen = fest_x
        sperrmodus = fest_e
        max_errors = 0
        p_kz_no_warn = fest_x " 'N' ?
        kz_prf = blank " 's' ?
        kz_verw = fest_x
        kz_aend = fest_x
        kz_dispo = fest_x
        kz_test = blank
        kz_mdip = blank
        kz_mprp = blank
        kz_ale = blank
        kz_actv = blank
    TABLES
        AMARA_UEB = TMARA_UEB
        AMERRDAT = lt_amerrdat
    EXCEPTIONS
        OTHERS = 7.

" Loop lt_amerrdat.
"   CALL FUNCTION 'RPY_MESSAGE_COMPOSE' [...]
"     WRITE:/ lv_errmsg.

" ROLLBACK WORK.
" or
" CALL FUNCTION 'DB_COMMIT'.

(I used this logic of code https://archive.sap.com/discussions/thread/169786)

Problem: I successfully executed the code, but now I caught some functional errors. If I correctly understand the functionality of this FM, the modification will be executed through a tcode (i.e.: MM01/02/03). But, I don't know what was the initial tcode for each row and I have functional issues (i.e: Article category not correct, ...) depending of the tcode used.

Do you know how I can skip these checks? Or known the initial tcode?

Solution 2 - BAPI_MATERIAL_SAVEDATA

Use function module BAPI_MATERIAL_SAVEDATA. This FM allow to update MARA table with standard fields + custom (via EXTENSION(X))

For information, my BAPI_TE_MARA & BAPI_TE_MARAX looks like:

  • MATERIAL (MATNR, char, 18)
  • .APPEND (ZBAPI_TE_MARAX)
  • NOCHANGE (BAPIUPDATE, char, 1)

I guess I have to add each Z* fields on it, before use this FM ? Moreover, I didn't find a solution to update the fields of the table. If I'm checking the FM, I have some objects but the columns names are not the same. How I can find the mapping between the fields on this FM and the fields on the MARA table ?

Solution 3

Has I make my checks on integrity on my code, I guess I can use a simple INSERT/UPDATE (MODIFY) ? This should be the simplest solution.

CONCATENATE sy-mandt lv_matnr INTO lv_mara_key.

" Lock object
CALL FUNCTION 'ENQUEUE_E_TABLE'
    EXPORTING
        MODE_RSTABLE   = 'E'
        tabname        = 'MARA'
        varkey         = lv_mara_key
    EXCEPTIONS
        foreign_lock   = 1      system_failure = 2      OTHERS = 3.

ls_mara-ernam = sy-uname.
" ...
" std & custo

MODIFY mara FROM ls_mara.

" Unlock object
CALL FUNCTION 'DEQUEUE_E_TABLE'
    EXPORTING
        MODE_RSTABLE   = 'E'
        tabname        = 'MARA'
        varkey         = lv_mara_key
    EXCEPTIONS
        foreign_lock   = 1      system_failure = 2      OTHERS = 3.

I'm interested in all recommendations, tutorials or advices :)

Suncatcher
  • 10,355
  • 10
  • 52
  • 90
Georges O.
  • 972
  • 1
  • 9
  • 21
  • 1
    I would go for Solution 2. Solution 3 is not recommended unless you know that no other related tables should be updated too. – Christian Tapia Oct 31 '16 at 02:50
  • Hi. Thanks. Indeed, no other tables will be involved. I don't have other information than the MARA table. The way: mass upload of mara data. For the other, another program or manual process will be used. I didn't find any good documentation about Sol 2. Do you have one ? – Georges O. Oct 31 '16 at 07:53
  • 3
    Solution 2 would be the best of the three. The BAPI is an official interface from SAP, so you have a reliable connection that will likely not change after updates or upgrades, while internal function modules may change. The field names in BAPIs are different, but if you look at the function module declaration, you'll see that they use the same data types. Most of the time that's already enough to map internal fieldname to BAPI fieldname. Usually the BAPIs use standard english field names, while the tables often use 5 or 6 character long fieldnames, often in german. – Dirk Trilsbeek Oct 31 '16 at 10:03

5 Answers5

4

Solution 2. Period. For details see the great comments from @chrisian and @dirk-trilsbeek.

In regards to your follow up question about the field mapping. The more user friendly names are great for people using the BAPI's from outside of SAP but they do make it hard to map to the fields we know inside SAP. Luckily SAP used the same data elements most of the time in these cases so that is one way to match them. Otherwise the different BAPIs often have conversion function modules to translate from the BAPI fields to the database fields. For the material BAPI you mention you can check the subroutines <TABLE>_UEBERGEBEN (this translates to <TABLE>_TRANSFER) where <TABLE> is MARA, MARC etc. Note that for instance the MARA_UEBERGEBEN routine calls the FM MAP2I_BAPI_MARA_TO_MARA_UEB and this FM has the translation from the BAPI structure to MARA, e.g. NET_WEIGHT maps to NTGEW.

Gert Beukema
  • 2,510
  • 1
  • 17
  • 18
1

Use Solution 1, BUT these custom fields should be assign to group beforehand! This should be done in customization by path:

Logistic General-> Material Master-> Field Selection-> Assign fields to field selection group

You should create new group if there are no groups yet. This group determines when the fields will be enabled/disabled/active/inactive etc. The code should look like this:

CALL FUNCTION 'MATERIAL_MAINTAIN_DARK'
 EXPORTING
  sperrmodus = ' '
  kz_prf = 'W'
  max_errors = ' '
  p_kz_no_warn = 'X'
  kz_verw = 'X'
  kz_aend = 'X'
  kz_dispo = 'X'
  kz_test = ' '
  flag_muss_pruefen = ' '
  call_mode = 'ACT'
 IMPORTING
  matnr_last = w_matnr_last
  number_errors_transaction = w_nb_errors
 TABLES
  amara_ueb = t_amara_ueb
  amarm_ueb = t_amarm_ueb
 EXCEPTIONS
  kstatus_empty = 1
  tkstatus_empty = 2
  t130m_error = 3
  internal_error = 4
  too_many_errors = 5
  update_error = 6
 OTHERS = 7.

 IF sy-subrc <> 0.
  MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO.
 ELSE.
  COMMIT WORK.
 ENDIF.
Suncatcher
  • 10,355
  • 10
  • 52
  • 90
1

Finally this is the solution choosen. We used BAPI_MATERIAL_SAVEDATA with the extension. I commented the code to help you if you want to use it :)

FORM update_mara
  USING
    us_result TYPE mara. "Input entry of mara with masterdata to update in the system

  DATA :  ls_mara           TYPE bapi_te_mara,
          ls_head           TYPE bapimathead,
          lt_extensionin    TYPE TABLE OF bapiparex,
          ls_extensionin    TYPE bapiparex,
          lt_extensioninx   TYPE TABLE OF bapiparexx,
          ls_extensioninx   TYPE bapiparexx,
          ls_return         TYPE bapiret2,
          lv_x              TYPE char41,
          lv_mara           TYPE string. "Container for all data of ls_mara

  " MASTERDATA PART
  MOVE-CORRESPONDING us_result TO ls_mara.
  ls_mara-material = ls_head-material = us_result-matnr.
  "At least the mendatory key field: 'material'

  " DATA PART
  " Use extension BAPI_TE_MARA
  ls_extensionin-structure = 'BAPI_TE_MARA'.
  lv_mara = ls_mara.
  " Fill data into the extension
  ls_extensionin+30(960) = lv_mara.
  APPEND ls_extensionin TO lt_extensionin.

  " FLAG PART
  CLEAR lv_x.
  DO 41 TIMES. "Don't forget to change 'lv_x TYPE char41' if needed
    CONCATENATE lv_x 'X' INTO lv_x.
    "Add an 'X' where you want to activate the update
    "Here, it's for all fields
  ENDDO. " End of the do loop for all fields of the mara

  " Use extension BAPI_TE_MARAX
  ls_extensioninx-structure  = 'BAPI_TE_MARAX'.
  ls_extensioninx-valuepart1(18)  = us_result-matnr.
  ls_extensioninx-valuepart1+19   = lv_x.
  " The first part (18) of the extensioninx is the matnr and the next ones some 'X' flags to activate the update or not.
  APPEND ls_extensioninx TO lt_extensioninx.

  " PROCESS PART
  CALL FUNCTION 'BAPI_MATERIAL_SAVEDATA'
    EXPORTING
      headdata     = ls_head
    IMPORTING
      return       = ls_return
    TABLES
      extensionin  = lt_extensionin
      extensioninx = lt_extensioninx
  .

  IF ls_return-type = 'E'.
    CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
  ELSE.
    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
      EXPORTING
        wait = 'X'.
  ENDIF.  " End if of check of BAPI result

ENDFORM.                    " UPDATE_MARA
Georges O.
  • 972
  • 1
  • 9
  • 21
  • Instead of hardcoding the number of fields (41 in this case) in the update flag structure, you can go with `DESCRIBE FIELD TYPE DATA(lv_type) COMPONENTS DATA(lv_number_of_fields).` and then `DO lv_number_of_fields TIMES.`. This way your code gains in reusability and avoids a possible DUMP in the future – cape_bsas Dec 14 '20 at 14:35
1

Solution #3 is simply NOT a VALID option in SAP systems.

cape_bsas
  • 638
  • 5
  • 13
0

Both of the solutions 1 and 2 are good. You could directly fill custo-fields, as you did it in the solution 3, after you changed standard fields with one of the FMs.