Zum Hauptinhalt springen

15. Aktionen implementieren

  • Die Message Class ZTRAVEL um Nachrichten zum Stornieren einer Reise erweitern
  • Die Nachrichtenklasse ZCM_TRAVEL um Nachrichten zum Stornieren einer Reise erweitern
  • Die Behavior Definition ZR_TRAVELTP um eine Aktion zum Stornieren einer Reise erweitern
  • Die Verhaltensimplementierung ZBP_TRAVELTP um eine Behandlermethode zum Stornieren einer Reise erweitern
  • Die Behavior Projection ZC_TRAVELTP um eine Aktion zum Stornieren einer Reise erweitern
  • Die Metadata Extension ZC_TRAVELTP um Annotationen für eine Aktion zum Stornieren einer Reise erweitern

Message Class ZTRAVEL

NachrichtennummerNachricht
001This is a Test Message from &1
002No Agency found for Agency ID &1
003No Customer found for Customer ID &1
004Begin Date must be before End Date
005Travel &1 is already cancelled
006Travel &1 was successfully cancelled

Nachrichtenklasse ZCM_TRAVEL

ZCM_TRAVEL.abap
CLASS zcm_travel DEFINITION PUBLIC
INHERITING FROM cx_static_check FINAL CREATE PUBLIC.

PUBLIC SECTION.
" Interfaces
INTERFACES if_abap_behv_message.
INTERFACES if_t100_message.
INTERFACES if_t100_dyn_msg.

" Message Constants
CONSTANTS:
BEGIN OF test_message,
msgid TYPE symsgid VALUE 'ZTRAVEL',
msgno TYPE symsgno VALUE '001',
attr1 TYPE scx_attrname VALUE 'USER_NAME',
attr2 TYPE scx_attrname VALUE '',
attr3 TYPE scx_attrname VALUE '',
attr4 TYPE scx_attrname VALUE '',
END OF test_message.

CONSTANTS:
BEGIN OF no_agency_found,
msgid TYPE symsgid VALUE 'ZTRAVEL',
msgno TYPE symsgno VALUE '002',
attr1 TYPE scx_attrname VALUE 'AGENCY_ID',
attr2 TYPE scx_attrname VALUE '',
attr3 TYPE scx_attrname VALUE '',
attr4 TYPE scx_attrname VALUE '',
END OF no_agency_found.

CONSTANTS:
BEGIN OF no_customer_found,
msgid TYPE symsgid VALUE 'ZTRAVEL',
msgno TYPE symsgno VALUE '003',
attr1 TYPE scx_attrname VALUE 'CUSTOMER_ID',
attr2 TYPE scx_attrname VALUE '',
attr3 TYPE scx_attrname VALUE '',
attr4 TYPE scx_attrname VALUE '',
END OF no_customer_found.

CONSTANTS:
BEGIN OF invalid_dates,
msgid TYPE symsgid VALUE 'ZTRAVEL',
msgno TYPE symsgno VALUE '004',
attr1 TYPE scx_attrname VALUE '',
attr2 TYPE scx_attrname VALUE '',
attr3 TYPE scx_attrname VALUE '',
attr4 TYPE scx_attrname VALUE '',
END OF invalid_dates.

CONSTANTS:
BEGIN OF travel_already_cancelled,
msgid TYPE symsgid VALUE 'ZTRAVEL',
msgno TYPE symsgno VALUE '005',
attr1 TYPE scx_attrname VALUE 'DESCRIPTION',
attr2 TYPE scx_attrname VALUE '',
attr3 TYPE scx_attrname VALUE '',
attr4 TYPE scx_attrname VALUE '',
END OF travel_already_cancelled.

CONSTANTS:
BEGIN OF travel_cancelled_successfully,
msgid TYPE symsgid VALUE 'ZTRAVEL',
msgno TYPE symsgno VALUE '006',
attr1 TYPE scx_attrname VALUE 'DESCRIPTION',
attr2 TYPE scx_attrname VALUE '',
attr3 TYPE scx_attrname VALUE '',
attr4 TYPE scx_attrname VALUE '',
END OF travel_cancelled_successfully.

" Attributs
DATA user_name TYPE syuname.
DATA agency_id TYPE /dmo/agency_id.
DATA customer_id TYPE /dmo/customer_id.
DATA description TYPE /dmo/description.

" Constructor
METHODS constructor
IMPORTING severity TYPE if_abap_behv_message=>t_severity DEFAULT if_abap_behv_message=>severity-error
textid LIKE if_t100_message=>t100key DEFAULT if_t100_message=>default_textid
!previous LIKE previous OPTIONAL
user_name TYPE syuname OPTIONAL
agency_id TYPE /dmo/agency_id OPTIONAL
customer_id TYPE /dmo/customer_id OPTIONAL
!description TYPE /dmo/description OPTIONAL.

PROTECTED SECTION.

PRIVATE SECTION.

ENDCLASS.

CLASS zcm_travel IMPLEMENTATION.
METHOD constructor ##ADT_SUPPRESS_GENERATION.
super->constructor( previous = previous ).

if_t100_message~t100key = textid.
if_abap_behv_message~m_severity = severity.
me->user_name = user_name.
me->agency_id = agency_id.
me->customer_id = customer_id.
me->description = description.
ENDMETHOD.
ENDCLASS.

Behavior Definition ZR_TRAVELTP

managed implementation in class zbp_traveltp unique;
strict ( 2 );

define behavior for ZR_TravelTP alias Travel
persistent table ztravel_a
lock master
authorization master ( instance )
//etag master <field_name>
{
create;
update;
delete;

association _Bookings { create; }

static action ShowTestMessage;
action CancelTravel result [1] $self;

validation ValidateDates on save { create; }
validation ValidateCustomer on save { create; }
validation ValidateAgency on save { create; }

determination DetermineStatus on modify { create; }
determination DetermineTravelId on modify { create; }

field ( readonly, numbering : managed ) TravelUuid;
field ( mandatory : create ) AgencyId, BeginDate, CustomerId, Description, EndDate;
field ( readonly : update ) AgencyId, BeginDate, CustomerId, Description, EndDate;
field ( readonly ) CreatedAt, CreatedBy, LastChangedAt, LastChangedBy, Status, TravelId;

mapping for ztravel_a corresponding
{
AgencyId = agency_id;
BeginDate = begin_date;
BookingFee = booking_fee;
CreatedAt = created_at;
CreatedBy = created_by;
CurrencyCode = currency_code;
CustomerId = customer_id;
Description = description;
EndDate = end_date;
LastChangedAt = last_changed_at;
LastChangedBy = last_changed_by;
Status = status;
TotalPrice = total_price;
TravelId = travel_id;
TravelUuid = travel_uuid;
}
}

define behavior for ZR_BookingTP alias Booking
persistent table zbooking_a
lock dependent by _Travel
authorization dependent by _Travel
//etag master <field_name>
{
update;
delete;

association _Travel;

field ( readonly, numbering : managed ) BookingUuid;
field ( readonly ) TravelUuid;

mapping for zbooking_a corresponding
{
BookingDate = booking_Date;
BookingId = booking_id;
BookingUuid = booking_uuid;
CarrierId = carrier_id;
ConnectionId = connection_id;
CurrencyCode = currency_code;
FlightDate = flight_date;
FlightPrice = flight_price;
TravelUuid = Travel_uuid;
}
}

Verhaltensimplementierung ZBP_TRAVELTP

Global Class ZBP_TRAVELTP

ZBP_TRAVELTP.abap
CLASS zbp_traveltp DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zr_Traveltp.
PROTECTED SECTION.

PRIVATE SECTION.
ENDCLASS.

CLASS zbp_traveltp IMPLEMENTATION.
ENDCLASS.

Local Type LHC_TRAVEL

ZBP_TRAVELTP.abap
CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Travel RESULT result.

METHODS showtestmessage FOR MODIFY
IMPORTING keys FOR ACTION travel~showtestmessage.

METHODS validateagency FOR VALIDATE ON SAVE
IMPORTING keys FOR travel~validateagency.

METHODS validatecustomer FOR VALIDATE ON SAVE
IMPORTING keys FOR travel~validatecustomer.

METHODS validatedates FOR VALIDATE ON SAVE
IMPORTING keys FOR travel~validatedates.

METHODS determinestatus FOR DETERMINE ON MODIFY
IMPORTING keys FOR travel~determinestatus.

METHODS determinetravelid FOR DETERMINE ON MODIFY
IMPORTING keys FOR travel~determinetravelid.

METHODS canceltravel FOR MODIFY
IMPORTING keys FOR ACTION travel~canceltravel RESULT result.
ENDCLASS.

CLASS lhc_travel IMPLEMENTATION.
METHOD get_instance_authorizations.
ENDMETHOD.

METHOD showtestmessage.
DATA message TYPE REF TO zcm_travel.

message = NEW zcm_travel( severity = if_abap_behv_message=>severity-success
textid = zcm_travel=>test_message
user_name = sy-uname ).

APPEND message TO reported-%other.
ENDMETHOD.

METHOD validateagency.
DATA message TYPE REF TO zcm_travel.

" Read Travels
READ ENTITY IN LOCAL MODE ZR_TravelTP
FIELDS ( AgencyId )
WITH CORRESPONDING #( keys )
RESULT DATA(travels).

" Process Travels
LOOP AT travels INTO DATA(travel).
" Validate Agency and Create Error Message
SELECT SINGLE FROM /dmo/agency FIELDS @abap_true WHERE agency_id = @travel-AgencyId INTO @DATA(exists).
IF exists = abap_false.
message = NEW zcm_travel( textid = zcm_travel=>no_agency_found
agency_id = travel-AgencyId ).
APPEND VALUE #( %tky = travel-%tky
%element = VALUE #( AgencyId = if_abap_behv=>mk-on )
%msg = message ) TO reported-travel.
APPEND VALUE #( %tky = travel-%tky ) TO failed-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.

METHOD validatecustomer.
DATA message TYPE REF TO zcm_travel.

" Read Travels
READ ENTITY IN LOCAL MODE ZR_TravelTP
FIELDS ( CustomerId )
WITH CORRESPONDING #( keys )
RESULT DATA(travels).

" Process Travels
LOOP AT travels INTO DATA(travel).
" Validate Customer and Create Error Message
SELECT SINGLE FROM /dmo/customer FIELDS @abap_true WHERE customer_id = @travel-CustomerId INTO @DATA(exists).
IF exists = abap_false.
message = NEW zcm_travel( textid = zcm_travel=>no_customer_found
customer_id = travel-CustomerId ).
APPEND VALUE #( %tky = travel-%tky
%element = VALUE #( CustomerId = if_abap_behv=>mk-on )
%msg = message ) TO reported-travel.
APPEND VALUE #( %tky = travel-%tky ) TO failed-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.

METHOD validatedates.
DATA message TYPE REF TO zcm_travel.

" Read Travels
READ ENTITY IN LOCAL MODE ZR_TravelTP
FIELDS ( BeginDate EndDate )
WITH CORRESPONDING #( keys )
RESULT DATA(travels).

" Process Travels
LOOP AT travels INTO DATA(travel).
" Validate Dates and Create Error Message
IF travel-EndDate < travel-BeginDate.
message = NEW zcm_travel( textid = zcm_travel=>invalid_dates ).
APPEND VALUE #( %tky = travel-%tky
%msg = message ) TO reported-travel.
APPEND VALUE #( %tky = travel-%tky ) TO failed-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.

METHOD determinestatus.
MODIFY ENTITY IN LOCAL MODE ZR_TravelTP
UPDATE FIELDS ( Status )
WITH VALUE #( FOR key IN keys
( %tky = key-%tky
Status = 'N' ) ).
ENDMETHOD.

METHOD determinetravelid.
DATA travel_id TYPE /dmo/travel_id.

" Get Travel ID
SELECT FROM /dmo/travel FIELDS MAX( travel_id ) INTO @DATA(max_travel_id).
travel_id = max_travel_id + 1.

" Modify Travels
MODIFY ENTITY IN LOCAL MODE ZR_TravelTP
UPDATE FIELDS ( TravelId )
WITH VALUE #( FOR key IN keys
( %tky = key-%tky
TravelId = travel_id ) ).
ENDMETHOD.

METHOD canceltravel.
DATA message TYPE REF TO zcm_travel.

" Read Travels
READ ENTITY IN LOCAL MODE ZR_TravelTP
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(travels).

" Process Travels
LOOP AT travels REFERENCE INTO DATA(travel).
" Validate Status and Create Error Message
IF travel->Status = 'X'.
message = NEW zcm_travel( textid = zcm_travel=>travel_already_cancelled
description = travel->Description ).
APPEND VALUE #( %tky = travel->%tky
%element = VALUE #( Status = if_abap_behv=>mk-on )
%msg = message ) TO reported-travel.
APPEND VALUE #( %tky = travel->%tky ) TO failed-travel.
DELETE travels INDEX sy-tabix.
CONTINUE.
ENDIF.

" Set Status to Cancelled and Create Success Message
travel->Status = 'X'.
message = NEW zcm_travel( severity = if_abap_behv_message=>severity-success
textid = zcm_travel=>travel_cancelled_successfully
description = travel->Description ).
APPEND VALUE #( %tky = travel->%tky
%element = VALUE #( Status = if_abap_behv=>mk-on )
%msg = message ) TO reported-travel.
ENDLOOP.

" Modify Travels
MODIFY ENTITY IN LOCAL MODE ZR_TravelTP
UPDATE FIELDS ( Status )
WITH VALUE #( FOR t IN travels
( %tky = t-%tky Status = t-Status ) ).

" Set Result
result = VALUE #( FOR t IN travels
( %tky = t-%tky
%param = t ) ).
ENDMETHOD.
ENDCLASS.

Behavior Projection ZC_TRAVELTP

projection;
strict ( 2 );

define behavior for ZC_TravelTP alias Travel
{
use create;
use update;
use delete;

use association _Bookings { create; }

use action ShowTestMessage;
use action CancelTravel;
}

define behavior for ZC_BookingTP alias Booking
{
use update;
use delete;

use association _Travel;
}

Metadata Extension ZC_TRAVELTP

@Metadata.layer: #CUSTOMER
@UI.headerInfo:
{
typeNamePlural: 'Travels',
typeName: 'Travel',
title.value: 'TravelId',
description.value: 'Description'
}
@UI.presentationVariant: [{sortOrder: [{ by: 'BeginDate', direction: #DESC }]}]
annotate view ZC_TravelTP with
{

/* Facets */
@UI.facet:
[
{ position: 10, targetQualifier: 'TravelDetails', label: 'Travel Details', type: #FIELDGROUP_REFERENCE },
{ position: 20, targetQualifier: 'AdminData', label: 'Administrative Data', type: #FIELDGROUP_REFERENCE },
{ position: 30, targetElement: '_Bookings', label: 'Bookings', type: #LINEITEM_REFERENCE }
]

/* Actions */
@UI.lineItem:
[
{ position: 10, dataAction: 'ShowTestMessage', label: 'Show Test Message', type: #FOR_ACTION },
{ position: 20, dataAction: 'CancelTravel', label: 'Cancel Travel', type: #FOR_ACTION }
]


/* Fields */
@UI.fieldGroup: [{ position: 10, qualifier: 'AdminData' }]
TravelUuid;

@UI.lineItem: [{ position: 10 }]
@UI.fieldGroup: [{ position: 10, qualifier: 'TravelDetails' }]
TravelId;

@UI.lineItem: [{ position: 20 }]
@UI.selectionField: [{ position: 10 }]
@UI.fieldGroup: [{ position: 20, qualifier: 'TravelDetails' }]
AgencyId;

@UI.lineItem: [{ position: 30 }]
@UI.selectionField: [{ position: 20 }]
@UI.fieldGroup: [{ position: 30, qualifier: 'TravelDetails' }]
CustomerId;

@UI.lineItem: [{ position: 40 }]
@UI.selectionField: [{ position: 30 }]
@UI.fieldGroup: [{ position: 40, qualifier: 'TravelDetails' }]
BeginDate;

@UI.lineItem: [{ position: 50 }]
@UI.selectionField: [{ position: 40 }]
@UI.fieldGroup: [{ position: 50, qualifier: 'TravelDetails' }]
EndDate;

@UI.fieldGroup: [{ position: 60, qualifier: 'TravelDetails' }]
BookingFee;

@UI.lineItem: [{ position: 60 }]
@UI.selectionField: [{ position: 50 }]
@UI.fieldGroup: [{ position: 70, qualifier: 'TravelDetails' }]
TotalPrice;

// CurrencyCode;

@UI.lineItem: [{ position: 70, criticality: 'BeginDateCriticality', criticalityRepresentation: #WITHOUT_ICON }]
@UI.fieldGroup: [{ position: 80, qualifier: 'TravelDetails' }]
Description;

@UI.lineItem: [{ position: 80, criticality: 'StatusCriticality', criticalityRepresentation: #WITHOUT_ICON }]
@UI.selectionField: [{ position: 60 }]
@UI.fieldGroup: [{ position: 90, qualifier: 'TravelDetails', criticality: 'StatusCriticality', criticalityRepresentation: #WITHOUT_ICON }]
Status;

@UI.fieldGroup: [{ position: 20, qualifier: 'AdminData' }]
Createdby;

@UI.fieldGroup: [{ position: 30, qualifier: 'AdminData' }]
Createdat;

@UI.fieldGroup: [{ position: 40, qualifier: 'AdminData' }]
Lastchangedby;

@UI.fieldGroup: [{ position: 50, qualifier: 'AdminData' }]
Lastchangedat;

}