Bienvenue dans la Partie 2 de la série de tutoriels RAP ! Dans la Partie 1, vous avez créé une application Fiori fonctionnelle. Maintenant, nous allons la rendre vraiment intelligente avec de la logique métier.
Ce que vous allez apprendre
- Actions : Boutons personnalisés pour les opérations métier
- Validations : Vérification des données (ex. format ISBN)
- Determinations : Définir automatiquement des valeurs
- Value Helps : Listes déroulantes
- Feature Control : Afficher/masquer dynamiquement des boutons
Base : Nous construisons sur l’application Book Management de la Partie 1.
Temps estimé : 45-60 minutes
Prérequis
- Partie 1 terminée
- L’application Book Management fonctionne
- ADT (Eclipse) ouvert
Fonctionnalité 1 : Gestion du statut avec Actions
Nous ajoutons un Status (Nouveau, En lecture, Terminé) et des Actions pour changer le statut.
Étape 1 : Étendre la table
Ouvrez ZBOOK_TAB et ajoutez :
define table zbook_tab { // ... champs existants ...
status : abap.char(1); // N=Nouveau, R=En lecture, F=Terminé
// ... created_by, etc. ...}Activer : Ctrl+F3
Étape 2 : Étendre les CDS Views
Dans ZI_BOOK :
define root view entity ZI_BOOK as select from zbook_tab{ // ... champs existants ...
status as Status,
// Texte du statut via Association case status when 'N' then 'Nouveau" when 'R' then 'En lecture" when 'F' then 'Terminé" else 'Inconnu" end as StatusText,
// ... created_by, etc. ...}Dans ZC_BOOK :
define root view entity ZC_BOOK as projection on ZI_BOOK{ // ... champs existants ...
@ObjectModel.text.element: ['StatusText'] Status, StatusText,
// ... created_by, etc. ...}Activer les deux !
Étape 3 : Étendre la Behavior Definition - Ajouter des Actions
Ouvrez la BDEF Interface (ZI_BOOK -> Behavior Definition) :
managed implementation in class zbp_i_book unique;strict ( 2 );
define behavior for ZI_BOOK alias Bookpersistent table zbook_tablock masterauthorization master ( instance )etag master LastChangedAt{ create; update; delete;
field ( readonly ) BookId; field ( readonly ) CreatedBy, CreatedAt, LastChangedBy, LastChangedAt; field ( numbering : managed ) BookId;
// NOUVEAU : Actions avec Feature Control action ( features : instance ) startReading result [1] $self; action ( features : instance ) markAsFinished result [1] $self; action ( features : instance ) resetStatus result [1] $self;
// NOUVEAU : Validation à la sauvegarde validation validateIsbn on save { field Isbn; } validation validatePages on save { field Pages; }
// NOUVEAU : Determination à la création determination setDefaultStatus on modify { create; }
mapping for zbook_tab { BookId = book_id; Title = title; Author = author; Publisher = publisher; Isbn = isbn; Price = price; CurrencyCode = currency_code; Pages = pages; PublicationYear = publication_year; Language = language; Status = status; // NOUVEAU CreatedBy = created_by; CreatedAt = created_at; LastChangedBy = last_changed_by; LastChangedAt = last_changed_at; }}Activer : Ctrl+F3
Étape 4 : Étendre la Projection BDEF
Ouvrez la Behavior Definition de ZC_BOOK :
projection;strict ( 2 );
define behavior for ZC_BOOK alias Book{ use create; use update; use delete;
// NOUVEAU : Exposer les Actions use action startReading; use action markAsFinished; use action resetStatus;}Activer !
Étape 5 : Behavior Implementation - Implémenter les Actions
ADT a automatiquement créé ZBP_I_BOOK. Ouvrez la classe et ajoutez :
Local Types (à la fin de la classe) :
CLASS lhc_book DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS: " Feature Control (quelles Actions sont disponibles ?) get_instance_features FOR INSTANCE FEATURES IMPORTING keys REQUEST requested_features FOR Book RESULT result,
" Actions startReading FOR MODIFY IMPORTING keys FOR ACTION Book~startReading RESULT result,
markAsFinished FOR MODIFY IMPORTING keys FOR ACTION Book~markAsFinished RESULT result,
resetStatus FOR MODIFY IMPORTING keys FOR ACTION Book~resetStatus RESULT result,
" Validations validateIsbn FOR VALIDATE ON SAVE IMPORTING keys FOR Book~validateIsbn,
validatePages FOR VALIDATE ON SAVE IMPORTING keys FOR Book~validatePages,
" Determinations setDefaultStatus FOR DETERMINE ON MODIFY IMPORTING keys FOR Book~setDefaultStatus.ENDCLASS.
CLASS lhc_book IMPLEMENTATION.
" ===== FEATURE CONTROL ===== METHOD get_instance_features. " Lire les livres actuels READ ENTITIES OF zi_book IN LOCAL MODE ENTITY Book FIELDS ( Status ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_books) FAILED failed.
" Feature Control basé sur le Status result = VALUE #( FOR ls_book IN lt_books ( %tky = ls_book-%tky
" startReading : Disponible uniquement si Status = 'N' (Nouveau) %features-%action-startReading = COND #( WHEN ls_book-Status = 'N' THEN if_abap_behv=>fc-o-enabled ELSE if_abap_behv=>fc-o-disabled )
" markAsFinished : Disponible uniquement si Status = 'R' (En lecture) %features-%action-markAsFinished = COND #( WHEN ls_book-Status = 'R' THEN if_abap_behv=>fc-o-enabled ELSE if_abap_behv=>fc-o-disabled )
" resetStatus : Toujours disponible sauf pour 'N" %features-%action-resetStatus = COND #( WHEN ls_book-Status <> 'N' THEN if_abap_behv=>fc-o-enabled ELSE if_abap_behv=>fc-o-disabled ) ) ). ENDMETHOD.
" ===== ACTIONS ===== METHOD startReading. " Mettre le Status à 'R' (En lecture) MODIFY ENTITIES OF zi_book IN LOCAL MODE ENTITY Book UPDATE FIELDS ( Status ) WITH VALUE #( FOR key IN keys ( %tky = key-%tky Status = 'R' ) ) FAILED failed REPORTED reported.
" Retourner les livres mis à jour READ ENTITIES OF zi_book IN LOCAL MODE ENTITY Book ALL FIELDS WITH CORRESPONDING #( keys ) RESULT result. ENDMETHOD.
METHOD markAsFinished. " Mettre le Status à 'F' (Terminé) MODIFY ENTITIES OF zi_book IN LOCAL MODE ENTITY Book UPDATE FIELDS ( Status ) WITH VALUE #( FOR key IN keys ( %tky = key-%tky Status = 'F' ) ) FAILED failed REPORTED reported.
READ ENTITIES OF zi_book IN LOCAL MODE ENTITY Book ALL FIELDS WITH CORRESPONDING #( keys ) RESULT result. ENDMETHOD.
METHOD resetStatus. " Remettre le Status à 'N' (Nouveau) MODIFY ENTITIES OF zi_book IN LOCAL MODE ENTITY Book UPDATE FIELDS ( Status ) WITH VALUE #( FOR key IN keys ( %tky = key-%tky Status = 'N' ) ) FAILED failed REPORTED reported.
READ ENTITIES OF zi_book IN LOCAL MODE ENTITY Book ALL FIELDS WITH CORRESPONDING #( keys ) RESULT result. ENDMETHOD.
" ===== VALIDATIONS ===== METHOD validateIsbn. " Lire les livres READ ENTITIES OF zi_book IN LOCAL MODE ENTITY Book FIELDS ( Isbn ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_books).
LOOP AT lt_books INTO DATA(ls_book). " L'ISBN doit avoir 10 ou 13 caractères DATA(lv_isbn_length) = strlen( ls_book-Isbn ).
IF lv_isbn_length <> 10 AND lv_isbn_length <> 13. APPEND VALUE #( %tky = ls_book-%tky %element-Isbn = if_abap_behv=>mk-on ) TO failed-book.
APPEND VALUE #( %tky = ls_book-%tky %element-Isbn = if_abap_behv=>mk-on %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'L''ISBN doit avoir 10 ou 13 caractères" ) ) TO reported-book. ENDIF.
" L'ISBN ne doit contenir que des chiffres (vérification simplifiée) IF ls_book-Isbn IS NOT INITIAL AND ls_book-Isbn CO '0123456789' = abap_false. APPEND VALUE #( %tky = ls_book-%tky %element-Isbn = if_abap_behv=>mk-on ) TO failed-book.
APPEND VALUE #( %tky = ls_book-%tky %element-Isbn = if_abap_behv=>mk-on %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'L''ISBN ne doit contenir que des chiffres" ) ) TO reported-book. ENDIF. ENDLOOP. ENDMETHOD.
METHOD validatePages. READ ENTITIES OF zi_book IN LOCAL MODE ENTITY Book FIELDS ( Pages ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_books).
LOOP AT lt_books INTO DATA(ls_book). " Le nombre de pages doit être > 0 IF ls_book-Pages IS NOT INITIAL AND ls_book-Pages <= 0. APPEND VALUE #( %tky = ls_book-%tky %element-Pages = if_abap_behv=>mk-on ) TO failed-book.
APPEND VALUE #( %tky = ls_book-%tky %element-Pages = if_abap_behv=>mk-on %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'Le nombre de pages doit être supérieur à 0" ) ) TO reported-book. ENDIF. ENDLOOP. ENDMETHOD.
" ===== DETERMINATIONS ===== METHOD setDefaultStatus. " Lire les livres nouvellement créés READ ENTITIES OF zi_book IN LOCAL MODE ENTITY Book FIELDS ( Status ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_books).
" Définir le Status par défaut à 'N' (Nouveau) MODIFY ENTITIES OF zi_book IN LOCAL MODE ENTITY Book UPDATE FIELDS ( Status ) WITH VALUE #( FOR ls_book IN lt_books WHERE ( Status IS INITIAL ) ( %tky = ls_book-%tky Status = 'N' ) ) REPORTED reported. ENDMETHOD.
ENDCLASS.Activer : Ctrl+F3
Étape 6 : UI-Annotations pour les Actions
Ouvrez la Metadata Extension (ZC_BOOK) :
@Metadata.layer: #CORE
annotate view ZC_BOOK with{ @UI.headerInfo: { typeName: 'Livre', typeNamePlural: 'Livres', title: { value: 'Title' }, description: { value: 'Author' } }
@UI.facet: [ { id: 'BookDetails', purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE, label: 'Détails du livre', position: 10 } ]
// NOUVEAU : Actions dans la liste @UI.lineItem: [ { position: 10, importance: #HIGH }, { type: #FOR_ACTION, dataAction: 'startReading', label: 'Commencer la lecture' }, { type: #FOR_ACTION, dataAction: 'markAsFinished', label: 'Marquer comme terminé' }, { type: #FOR_ACTION, dataAction: 'resetStatus', label: 'Réinitialiser le statut' } ] @UI.identification: [{ position: 10 }] @UI.selectionField: [{ position: 10 }] BookId;
@UI.lineItem: [{ position: 20, importance: #HIGH }] @UI.identification: [{ position: 20 }] @UI.selectionField: [{ position: 20 }] Title;
@UI.lineItem: [{ position: 30, importance: #HIGH }] @UI.identification: [{ position: 30 }] @UI.selectionField: [{ position: 30 }] Author;
@UI.lineItem: [{ position: 40 }] @UI.identification: [{ position: 40 }] Publisher;
@UI.identification: [{ position: 50 }] Isbn;
@UI.lineItem: [{ position: 50 }] @UI.identification: [{ position: 60 }] Price;
@UI.identification: [{ position: 70 }] Pages;
@UI.lineItem: [{ position: 60 }] @UI.identification: [{ position: 80 }] PublicationYear;
@UI.identification: [{ position: 90 }] Language;
// NOUVEAU : Afficher le Status @UI.lineItem: [{ position: 35, importance: #HIGH, criticality: 'Status' }] @UI.identification: [{ position: 35 }] @UI.selectionField: [{ position: 40 }] Status;}Activer !
Étape 7 : Republier le Service Binding
- Ouvrir
ZUI_BOOK_O4(Service Binding) - Cliquer sur Unpublish
- Cliquer sur Publish
Étape 8 : Tester !
- Ouvrir Preview
- Créer un livre
- Les boutons apparaissent :
- “Commencer la lecture” (uniquement si Status = Nouveau)
- “Marquer comme terminé” (uniquement si Status = En lecture)
- “Réinitialiser le statut” (pas pour Nouveau)
Essayez :
- Cliquez sur “Commencer la lecture” -> Le statut passe à “En lecture”
- Maintenant “Marquer comme terminé” apparaît
- Tester la validation : Entrez un ISBN avec des lettres -> Erreur !
Fonctionnalité 2 : Value Help (Liste déroulante pour le Status)
Actuellement, le statut doit être saisi manuellement. Mieux : Liste déroulante avec sélection !
Étape 1 : Créer des valeurs fixes de domaine
Dans la Metadata Extension ZC_BOOK :
annotate view ZC_BOOK with{ // ... autres champs ...
@UI.lineItem: [{ position: 35, importance: #HIGH }] @UI.identification: [{ position: 35 }] @UI.selectionField: [{ position: 40 }] @Consumption.valueHelpDefinition: [{ entity: { name: 'I_Status_VH', element: 'StatusCode' } }] Status;}Mieux : Value Help personnalisée via CDS View
Créez une nouvelle Data Definition ZI_BOOK_STATUS_VH :
@AccessControl.authorizationCheck: #NOT_REQUIRED@EndUserText.label: 'Value Help pour le statut du livre"
define view entity ZI_BOOK_STATUS_VH as select from DDCDS_CUSTOMER_DOMAIN_VALUE_T( p_domain_name: 'ZBOOK_STATUS" ){ @ObjectModel.text.element: ['Description'] key domain_name as DomainName, key value_position as ValuePosition, @Semantics.language: true key language as Language, value_low as StatusCode, text as Description}Alternative : Version plus simple sans domaine
@AccessControl.authorizationCheck: #NOT_REQUIRED@EndUserText.label: 'Book Status Value Help"
define view entity ZI_BOOK_STATUS_VH as select from I_Language{ key 'N' as StatusCode, cast( 'Nouveau' as abap.char(20) ) as StatusText}union select from I_Language{ key 'R' as StatusCode, cast( 'En lecture' as abap.char(20) ) as StatusText}union select from I_Language{ key 'F' as StatusCode, cast( 'Terminé' as abap.char(20) ) as StatusText}Activer et référencer dans la Metadata Extension :
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_BOOK_STATUS_VH', element: 'StatusCode' }}]Status;Ce que nous avons appris
Actions
- Définition :
action startReading result [1] $self; - Feature Control : Rendre les boutons disponibles dynamiquement
- Implémentation :
MODIFY ENTITIESpour changer le statut - UI : Afficher les Actions dans
@UI.lineItem
Validations
- Quand :
on save(avant sauvegarde) ouon modify(immédiatement) - Vérifier les champs : Format ISBN, nombre de pages > 0
- Signaler les erreurs : Remplir
failed+reported - UI : Champs marqués en rouge, message d’erreur affiché
Determinations
- Quand :
on modify { create; }(à la création) - Objectif : Définir des valeurs par défaut (ex. Status = ‘N’)
- Implémentation :
MODIFY ENTITIESpour définir
Feature Control
- Boutons dynamiques : Basés sur les données (ex. Status)
- Méthode :
get_instance_features - Logique :
if_abap_behv=>fc-o-enabledvs.disabled
Prochaines étapes
Dans la Partie 3 : Bonnes pratiques :
- Optimisation des performances (Performance SELECT, EML Batching)
- Gestion des erreurs et Logging
- Tests unitaires pour RAP
- Déploiement et versioning
- Éviter les erreurs courantes
Aperçu du code
Objets nouveaux/modifiés :
ZBOOK_TAB(champ Status ajouté)ZI_BOOK(Status, StatusText)ZC_BOOK(exposer Status)- BDEF Interface (Actions, Validations, Determinations)
- BDEF Projection (exposer les Actions)
ZBP_I_BOOK(Implémentation)- Metadata Extension (UI-Annotations pour les Actions)
Des questions ?
- Les Actions fonctionnent-elles ?
- Les Validations s’affichent-elles correctement ?
- Quelle logique métier souhaiteriez-vous ajouter ?
Continuez avec la Partie 3 : Bonnes pratiques ->