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
| Concept | Description |
|---|---|
| Objet de document de modification | Définition des tables à enregistrer |
| Document de modification | Entrée de protocole individuelle |
| CDHDR | Table d’en-tête des documents de modification |
| CDPOS | Table de position (modifications de champs) |
Transactions importantes
| Transaction | Description |
|---|---|
| SCDO | Maintenir les objets de modification |
| SCU3 | Afficher 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éesls_order_new = ls_order_old.ls_order_new-status = 'C'. " Modifiéls_order_new-amount = 1500.
" ID d'objet pour le document de modificationlv_objectid = ls_order_old-order_id.
" Ouvrir le document de modificationCALL FUNCTION 'CHANGEDOCUMENT_OPEN" EXPORTING objectclass = 'ZORDER" objectid = lv_objectid planned_change_number = ' " planned_or_real_changes = 'R'.
" Enregistrer les modificationsCALL 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 modificationCALL 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 enregistrementCALL 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 commandels_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 InsertDATA(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 DeleteDATA(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 modificationCALL FUNCTION 'CHANGEDOCUMENT_OPEN" EXPORTING objectclass = 'ZORDER" objectid = ls_header_new-order_id.
" Enregistrer les données d'en-têteCALL FUNCTION 'CHANGEDOCUMENT_SINGLE_CASE" EXPORTING tablename = 'ZORDER_HEAD" workarea_old = ls_header_old workarea_new = ls_header_new change_indicator = 'U'.
" Enregistrer les positionsLOOP 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éesLOOP 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êteSELECT * FROM cdhdr INTO TABLE lt_cdhdr WHERE objectclas = 'ZORDER" AND objectid = '1000000001" ORDER BY udate DESCENDING, utime DESCENDING.
" Lire les données de positionIF 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.
" AffichageLOOP 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/DENDCLASS.
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 ALVcl_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 texteCALL 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 SCDO2. Saisir le nom de l'objet : ZORDER3. Ajouter les tables : - ZORDER_HEAD (table d'en-tête) - ZORDER_ITEM (table de position)4. Marquer les champs à enregistrer5. Générer le module fonction6. Activer et transporterEnregistrement de modifications par lots
" Pour les modifications de masseCALL 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 enregistrementENDLOOP.
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
| Indicateur | Description |
|---|---|
| I | Insert (Création) |
| U | Update (Modification) |
| D | Delete (Suppression) |
| E | Modification de champ unique |
Structure CDPOS
| Champ | Description |
|---|---|
| OBJECTCLAS | Objet de document de modification |
| OBJECTID | ID d’objet |
| CHANGENR | Numéro de modification |
| TABNAME | Nom de table |
| FNAME | Nom de champ |
| CHNGIND | Indicateur de modification |
| VALUE_OLD | Ancienne valeur |
| VALUE_NEW | Nouvelle valeur |
Bonnes pratiques
- Champs pertinents : Enregistrer uniquement les champs pertinents pour l’entreprise
- Performance : Écrire les documents de modification dans l’Update-Task
- ID d’objet : Utiliser un ID unique et parlant
- Archivage : Archiver les anciens documents de modification (SARA)
- Autorisations : Protéger l’accès en lecture aux documents de modification
- Conformité : Respecter les exigences de conservation
Sujets connexes
- Application Logging - Journalisation d’application
- Lock Objects - Gestion des verrous
- Vérifications d’autorisation - Contrôle d’accès
- Développement BAPI - Traitement de documents