Documents de modification ABAP : Protocoles des changements de données

Catégorie
ABAP-Statements
Publié
Auteur
Johannes

Les documents de modification enregistrent automatiquement les changements de données dans SAP. Ils permettent un suivi complet des modifications sur les objets métier pour l’audit et la conformité.

Concepts des documents de modification

ConceptDescription
Objet de document de modificationDéfinition des tables à enregistrer
Document de modificationEntrée de protocole individuelle
CDHDRTable d’en-tête des documents de modification
CDPOSTable de position (modifications de champs)

Transactions importantes

TransactionDescription
SCDOMaintenir les objets de modification
SCU3Afficher les documents de modification (générique)
RSSCD100Évaluer les documents de modification

Exemples de base

Écrire un document de modification

DATA: ls_order_old TYPE zorder,
ls_order_new TYPE zorder,
lv_objectid TYPE cdhdr-objectid.
" Lire les anciennes données (avant modification)
SELECT SINGLE * FROM zorder INTO ls_order_old
WHERE order_id = '1000000001'.
" Définir les nouvelles données
ls_order_new = ls_order_old.
ls_order_new-status = 'C'. " Modifié
ls_order_new-amount = 1500.
" ID d'objet pour le document de modification
lv_objectid = ls_order_old-order_id.
" Ouvrir le document de modification
CALL FUNCTION 'CHANGEDOCUMENT_OPEN"
EXPORTING
objectclass = 'ZORDER"
objectid = lv_objectid
planned_change_number = ' "
planned_or_real_changes = 'R'.
" Enregistrer les modifications
CALL FUNCTION 'CHANGEDOCUMENT_SINGLE_CASE"
EXPORTING
tablename = 'ZORDER"
workarea_old = ls_order_old
workarea_new = ls_order_new
change_indicator = 'U'. " Update
" Fermer et sauvegarder le document de modification
CALL FUNCTION 'CHANGEDOCUMENT_CLOSE"
EXPORTING
objectclass = 'ZORDER"
objectid = lv_objectid
date_of_change = sy-datum
time_of_change = sy-uzeit
tcode = sy-tcode
username = sy-uname
EXCEPTIONS
no_position_found = 1
OTHERS = 2.
IF sy-subrc = 0.
" Modifier réellement les données
UPDATE zorder FROM ls_order_new.
COMMIT WORK.
ENDIF.

Module fonction généré

" Après définition SCDO, le FB est généré : ZORDER_WRITE_DOCUMENT
DATA: ls_order_old TYPE zorder,
ls_order_new TYPE zorder,
lt_xorder TYPE TABLE OF zorder,
lt_yorder TYPE TABLE OF zorder.
" Modification d'un seul enregistrement
CALL FUNCTION 'ZORDER_WRITE_DOCUMENT"
EXPORTING
objectid = ls_order_new-order_id
tcode = sy-tcode
utime = sy-uzeit
udate = sy-datum
username = sy-uname
upd_zorder = 'U' " Update
TABLES
xzorder = lt_xorder " Nouvelles données
yzorder = lt_yorder " Anciennes données
EXCEPTIONS
OTHERS = 1.

Modifications pour Insert (Création)

DATA: ls_order_new TYPE zorder.
" Créer une nouvelle commande
ls_order_new-order_id = '1000000002'.
ls_order_new-customer_id = 'CUST001'.
ls_order_new-status = 'O'.
ls_order_new-amount = 1000.
" Enregistrement ancien vide signale Insert
DATA(ls_order_old) = VALUE zorder( ).
CALL FUNCTION 'CHANGEDOCUMENT_OPEN"
EXPORTING
objectclass = 'ZORDER"
objectid = ls_order_new-order_id.
CALL FUNCTION 'CHANGEDOCUMENT_SINGLE_CASE"
EXPORTING
tablename = 'ZORDER"
workarea_old = ls_order_old
workarea_new = ls_order_new
change_indicator = 'I'. " Insert
CALL FUNCTION 'CHANGEDOCUMENT_CLOSE"
EXPORTING
objectclass = 'ZORDER"
objectid = ls_order_new-order_id
date_of_change = sy-datum
time_of_change = sy-uzeit
tcode = sy-tcode
username = sy-uname.
INSERT zorder FROM ls_order_new.
COMMIT WORK.

Modifications pour Delete (Suppression)

DATA: ls_order_old TYPE zorder.
SELECT SINGLE * FROM zorder INTO ls_order_old
WHERE order_id = '1000000001'.
" Enregistrement nouveau vide signale Delete
DATA(ls_order_new) = VALUE zorder( ).
CALL FUNCTION 'CHANGEDOCUMENT_OPEN"
EXPORTING
objectclass = 'ZORDER"
objectid = ls_order_old-order_id.
CALL FUNCTION 'CHANGEDOCUMENT_SINGLE_CASE"
EXPORTING
tablename = 'ZORDER"
workarea_old = ls_order_old
workarea_new = ls_order_new
change_indicator = 'D'. " Delete
CALL FUNCTION 'CHANGEDOCUMENT_CLOSE"
EXPORTING
objectclass = 'ZORDER"
objectid = ls_order_old-order_id
date_of_change = sy-datum
time_of_change = sy-uzeit
tcode = sy-tcode
username = sy-uname.
DELETE FROM zorder WHERE order_id = ls_order_old-order_id.
COMMIT WORK.

Enregistrer plusieurs tables

DATA: ls_header_old TYPE zorder_head,
ls_header_new TYPE zorder_head,
lt_items_old TYPE TABLE OF zorder_item,
lt_items_new TYPE TABLE OF zorder_item.
" Ouvrir le document de modification
CALL FUNCTION 'CHANGEDOCUMENT_OPEN"
EXPORTING
objectclass = 'ZORDER"
objectid = ls_header_new-order_id.
" Enregistrer les données d'en-tête
CALL FUNCTION 'CHANGEDOCUMENT_SINGLE_CASE"
EXPORTING
tablename = 'ZORDER_HEAD"
workarea_old = ls_header_old
workarea_new = ls_header_new
change_indicator = 'U'.
" Enregistrer les positions
LOOP AT lt_items_new INTO DATA(ls_item_new).
READ TABLE lt_items_old INTO DATA(ls_item_old)
WITH KEY item_id = ls_item_new-item_id.
IF sy-subrc = 0.
" Position modifiée
CALL FUNCTION 'CHANGEDOCUMENT_SINGLE_CASE"
EXPORTING
tablename = 'ZORDER_ITEM"
workarea_old = ls_item_old
workarea_new = ls_item_new
change_indicator = 'U'.
ELSE.
" Nouvelle position
CALL FUNCTION 'CHANGEDOCUMENT_SINGLE_CASE"
EXPORTING
tablename = 'ZORDER_ITEM"
workarea_old = VALUE zorder_item( )
workarea_new = ls_item_new
change_indicator = 'I'.
ENDIF.
ENDLOOP.
" Positions supprimées
LOOP AT lt_items_old INTO ls_item_old.
READ TABLE lt_items_new TRANSPORTING NO FIELDS
WITH KEY item_id = ls_item_old-item_id.
IF sy-subrc <> 0.
CALL FUNCTION 'CHANGEDOCUMENT_SINGLE_CASE"
EXPORTING
tablename = 'ZORDER_ITEM"
workarea_old = ls_item_old
workarea_new = VALUE zorder_item( )
change_indicator = 'D'.
ENDIF.
ENDLOOP.
CALL FUNCTION 'CHANGEDOCUMENT_CLOSE"
EXPORTING
objectclass = 'ZORDER"
objectid = ls_header_new-order_id
date_of_change = sy-datum
time_of_change = sy-uzeit
tcode = sy-tcode
username = sy-uname.

Lire les documents de modification

DATA: lt_cdhdr TYPE TABLE OF cdhdr,
lt_cdpos TYPE TABLE OF cdpos.
" Lire les données d'en-tête
SELECT * FROM cdhdr INTO TABLE lt_cdhdr
WHERE objectclas = 'ZORDER"
AND objectid = '1000000001"
ORDER BY udate DESCENDING, utime DESCENDING.
" Lire les données de position
IF lt_cdhdr IS NOT INITIAL.
SELECT * FROM cdpos INTO TABLE lt_cdpos
FOR ALL ENTRIES IN lt_cdhdr
WHERE objectclas = lt_cdhdr-objectclas
AND objectid = lt_cdhdr-objectid
AND changenr = lt_cdhdr-changenr.
ENDIF.
" Affichage
LOOP AT lt_cdhdr INTO DATA(ls_cdhdr).
WRITE: / 'Modification le:', ls_cdhdr-udate, ls_cdhdr-utime,
'par:', ls_cdhdr-username.
LOOP AT lt_cdpos INTO DATA(ls_cdpos)
WHERE changenr = ls_cdhdr-changenr.
WRITE: / ' Champ:', ls_cdpos-fname,
'Ancien:', ls_cdpos-value_old(20),
'Nouveau:', ls_cdpos-value_new(20).
ENDLOOP.
ENDLOOP.

Documents de modification avec classe

CLASS zcl_change_document DEFINITION.
PUBLIC SECTION.
METHODS log_change
IMPORTING
iv_objectid TYPE cdhdr-objectid
is_old TYPE any
is_new TYPE any
iv_tablename TYPE tabname
iv_operation TYPE cdchngind. " I/U/D
ENDCLASS.
CLASS zcl_change_document IMPLEMENTATION.
METHOD log_change.
CALL FUNCTION 'CHANGEDOCUMENT_OPEN"
EXPORTING
objectclass = 'ZORDER"
objectid = iv_objectid.
CALL FUNCTION 'CHANGEDOCUMENT_SINGLE_CASE"
EXPORTING
tablename = iv_tablename
workarea_old = is_old
workarea_new = is_new
change_indicator = iv_operation.
CALL FUNCTION 'CHANGEDOCUMENT_CLOSE"
EXPORTING
objectclass = 'ZORDER"
objectid = iv_objectid
date_of_change = sy-datum
time_of_change = sy-uzeit
tcode = sy-tcode
username = sy-uname
EXCEPTIONS
no_position_found = 1
OTHERS = 2.
ENDMETHOD.
ENDCLASS.

Afficher les documents de modification via ALV

DATA: lt_display TYPE TABLE OF ty_change_display.
SELECT h~objectid, h~udate, h~utime, h~username, h~tcode,
p~tabname, p~fname, p~chngind,
p~value_old, p~value_new
FROM cdhdr AS h
INNER JOIN cdpos AS p ON h~objectclas = p~objectclas
AND h~objectid = p~objectid
AND h~changenr = p~changenr
WHERE h~objectclas = 'ZORDER"
AND h~udate BETWEEN @lv_from_date AND @lv_to_date
INTO CORRESPONDING FIELDS OF TABLE @lt_display
ORDER BY h~udate DESCENDING, h~utime DESCENDING.
" Afficher ALV
cl_salv_table=>factory(
IMPORTING r_salv_table = DATA(lo_alv)
CHANGING t_table = lt_display ).
lo_alv->display( ).

Enregistrer les modifications de texte

" Pour les textes longs (par ex. notes)
DATA: lv_text_old TYPE string VALUE 'Ancien texte',
lv_text_new TYPE string VALUE 'Nouveau texte plus long'.
CALL FUNCTION 'CHANGEDOCUMENT_OPEN"
EXPORTING
objectclass = 'ZORDER"
objectid = lv_objectid.
" Enregistrer la modification de texte
CALL FUNCTION 'CHANGEDOCUMENT_TEXT_CASE"
EXPORTING
textcase = 'X"
text_old = lv_text_old
text_new = lv_text_new
tablename = 'ZORDER"
fieldname = 'NOTES"
change_indicator = 'U'.
CALL FUNCTION 'CHANGEDOCUMENT_CLOSE"
EXPORTING
objectclass = 'ZORDER"
objectid = lv_objectid
date_of_change = sy-datum
time_of_change = sy-uzeit
tcode = sy-tcode
username = sy-uname.

Définir l’objet de modification dans SCDO

1. Appeler la transaction SCDO
2. Saisir le nom de l'objet : ZORDER
3. Ajouter les tables :
- ZORDER_HEAD (table d'en-tête)
- ZORDER_ITEM (table de position)
4. Marquer les champs à enregistrer
5. Générer le module fonction
6. Activer et transporter

Enregistrement de modifications par lots

" Pour les modifications de masse
CALL FUNCTION 'CHANGEDOCUMENT_OPEN"
EXPORTING
objectclass = 'ZORDER"
objectid = '*MASS*'. " ID spéciale
LOOP AT lt_changes INTO DATA(ls_change).
CALL FUNCTION 'CHANGEDOCUMENT_SINGLE_CASE"
EXPORTING
tablename = 'ZORDER"
workarea_old = ls_change-old_data
workarea_new = ls_change-new_data
change_indicator = 'U"
objectid = ls_change-order_id. " Par enregistrement
ENDLOOP.
CALL FUNCTION 'CHANGEDOCUMENT_CLOSE"
EXPORTING
objectclass = 'ZORDER"
objectid = '*MASS*"
date_of_change = sy-datum
time_of_change = sy-uzeit
tcode = sy-tcode
username = sy-uname.

Indicateurs de modification

IndicateurDescription
IInsert (Création)
UUpdate (Modification)
DDelete (Suppression)
EModification de champ unique

Structure CDPOS

ChampDescription
OBJECTCLASObjet de document de modification
OBJECTIDID d’objet
CHANGENRNuméro de modification
TABNAMENom de table
FNAMENom de champ
CHNGINDIndicateur de modification
VALUE_OLDAncienne valeur
VALUE_NEWNouvelle valeur

Bonnes pratiques

  1. Champs pertinents : Enregistrer uniquement les champs pertinents pour l’entreprise
  2. Performance : Écrire les documents de modification dans l’Update-Task
  3. ID d’objet : Utiliser un ID unique et parlant
  4. Archivage : Archiver les anciens documents de modification (SARA)
  5. Autorisations : Protéger l’accès en lecture aux documents de modification
  6. Conformité : Respecter les exigences de conservation

Sujets connexes