Application Development and Automation Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
Pradeep555
Explorer
426

In the world of SAP RAP (RESTful Application Programming), Determinations and Side Effects play a crucial role in delivering responsive and intelligent user experiences. While determinations are used to implement logic that reacts to changes in data during specific RAP phases (such as on modify or on save), side effects ensure that related fields or entities stay consistent and updated on the UI without additional user actions. 

In his blog, I will demonstrate a practical scenario where determinations are used to dynamically calculate values based on user input, and side effects are configured to immediately reflect these changes on the UI. This not only improves the data integrity but also enhances usability in Fiori applications. By the end of this post, you will have a clearer understanding of how to leverage determinations and side effects together effectively within a RAP-based application. 

DETERMINATION : 

  • Actions modifies the existing BO instance where as Determination modifies the existing BO instances based on some  trigger condition  
  • We can see that Actions also triggers based on the conditions but cannot modify the BO instances , we can be able to throw the error messages. 

Pre requisites : 

During modification we change/modify  some fields / requirements  and we can compute the values of  particular fields 

Determination can be called during  Transactional phase/Save sequence where as validations always called during the save sequence 

Once a determination  has been triggered , it must run independently from other determinations 

During determination result must change if we execute detrmination several time under same condition  

 

Scenario : 

Here the determination calculateTotalPrice which is defined for all the three entities 

(Travel, booking and booking supplements) handles the  calculation of total  price of one travel. 

Based on the booking Fee total price must be calculated for the travel  

 

SIDE-EFFECTS: 

  • The SAP Fiori UI does not necessarily trigger a reload of all  related BO after every User input , as it simply does not know anything about data changes  on the tables 
  • Side effects are  used to reload data, permissions or messages based on data changes in UI scenarios with draft enabled BO’s  
  • Side effects reloads the screen but it does not reload entire screen  
  •  It changes some of the field values or will enable/ disable some of the fied values    Or status of the data in transactional buffer --> based on these same things should appear in the front end  
  • We need to define side effects in Behaviour definition  
  • Side effects will only reload the fields in front end  ,nothing will happen in backend  
  • The data which is available in the backend it will reload in the front end whihc is not currently displaying properly  

 

Side effects have two parts : 

  • Triggering condition : specifies when you should reload ( can be actions / validations) 
  • Target : which fields should get  reloaded ( value of a field / multiple fields / reload entire entity ) 

 

Important points: 

  • Determinations calculates the total  price and updates it into the transcational buffer 

But in the front end screen older values will be there . 

 

Requirement : 

  • Whenever I change the booking fee and booking supplement data and flight price 
  • The total  price should be updated not only in transactional buffer but also in the front end automatically  

And whenever we are updating booking fee the reload of total price should happen  

Based on the trigger condition --> it should reload the values / fields  

 

Here the source --> Booking fee 

Target --> totalprice 

 

Syntax: 

Side effects { filed MyField affects Target } 

                         { $self affects Targets ; } 

                 { action MyAction affects Tragets ;} 

     { determine action MyDetermineAction  

    Executed on sources  

Affects Tagets } . 

 

In the target we can specify : 

  • $self : The current RAP BO is reloaded  
  • Entity _MyAssoc  : the specified associated entity  _MyAssoc is reloaded when the side effect is triggered  
  • Message  : all the messages in the response parameter reported are reloaded when the side effects is triggered  
  • We can  also als provide multiple targets  

 

Side effects { field MyField affects Field1 , Field2 , action Action1 , 

                        Action Action 2 [..] } 

 

RESTRICTIONS : 

  • Static actions  defined using the addition static must  not be used as a side effect trigger , nor as a side effect target  
  • In case of the trigger entity property $sefl , the target cannot be a field of the current entity $self itself ,  

However fields  from the associated entity can be defined using path  expressions  

 

Side Effect In BDL: 

  • Side effects can be specified exactly once for each RAP BO entity in the entity  

Behaviour definition  

  • Multiple side effects can  be summarized with curly brackets , separated by a semicolon (; ) , if required. 
  • The syntax ‘use side effects’ is specified in the behaviour definition header and all  side effects from all  RAP BO entities of the underlying RAP BO are reused 

 

1. Create db table for travel  

@EndUserText.label : 'travel table' 
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE 
@AbapCatalog.tableCategory : #TRANSPARENT 
@AbapCatalog.deliveryClass : #A 
@AbapCatalog.dataMaintenance : #RESTRICTED 
define table zpd_dt_travel {
 
key client : abap.clnt not null; 
key travel_id : /dmo/travel_id not null; 
agency_id : /dmo/agency_id; 
customer_id : /dmo/customer_id; 
begin_date : /dmo/begin_date; 
end_date : /dmo/end_date; 
@Semantics.amount.currencyCode : 'zpd_dt_travel.currency_code' 
booking_fee : /dmo/booking_fee; 
@Semantics.amount.currencyCode : 'zpd_dt_travel.currency_code' 
total_price : /dmo/total_price; 
currency_code : /dmo/currency_code; 
description : /dmo/description; 
overall_status : /dmo/overall_status; 
created_by : abp_creation_user; 
created_at : abp_creation_tstmpl; 
last_changed_by : abp_locinst_lastchange_user; 
last_changed_at : abp_locinst_lastchange_tstmpl; 

} 

2.Create db table for Booking

@EndUserText.label : 'tbale for booking details' 
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE 
@AbapCatalog.tableCategory : #TRANSPARENT 
@AbapCatalog.deliveryClass : #A 
@AbapCatalog.dataMaintenance : #RESTRICTED 
define table zpd_dt_booking { 

key client : abap.clnt not null; 
@AbapCatalog.foreignKey.label : 'Travel' 
@AbapCatalog.foreignKey.screenCheck : false 
key travel_id : /dmo/travel_id not null 
with foreign key [0..*,1] zpd_dt_travel 
where travel_id = zpd_dt_booking.travel_id; 
key booking_id : /dmo/booking_id not null; 
booking_date : /dmo/booking_date; 
customer_id : /dmo/customer_id; 
carrier_id : /dmo/carrier_id; 
connection_id : /dmo/connection_id; 
flight_date : /dmo/flight_date; 
@Semantics.amount.currencyCode : 'zpd_dt_booking.currency_code' 
flight_price : /dmo/flight_price; 
currency_code : /dmo/currency_code; 
booking_status : /dmo/booking_status; 
last_changed_at : abp_locinst_lastchange_tstmpl; 

} 

 3.Crete a db table for Booking suppliment

@EndUserText.label : 'booking supplimnet' 
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE 
@AbapCatalog.tableCategory : #TRANSPARENT 
@AbapCatalog.deliveryClass : #A 
@AbapCatalog.dataMaintenance : #RESTRICTED 
define table zpd_dt_bsupplmnt { 

key client : abap.clnt not null; 
@AbapCatalog.foreignKey.label : 'Travel' 
@AbapCatalog.foreignKey.screenCheck : false 
key travel_id : /dmo/travel_id not null 
with foreign key [0..*,1] zpd_dt_travel 
where travel_id = zpd_dt_bsupplmnt.travel_id; 
@AbapCatalog.foreignKey.label : 'Booking' 
@AbapCatalog.foreignKey.screenCheck : false 
key booking_id : /dmo/booking_id not null 
with foreign key [0..*,1] zpd_dt_booking 
where travel_id = zpd_dt_bsupplmnt.travel_id 
and booking_id = zpd_dt_bsupplmnt.booking_id; 
key booking_supplement_id : /dmo/booking_supplement_id not null; 
supplement_id : /dmo/supplement_id; 
@Semantics.amount.currencyCode : 'zpd_dt_bsupplmnt.currency_code' 
price : /dmo/supplement_price; 
currency_code : /dmo/currency_code; 
last_changed_at : abp_locinst_lastchange_tstmpl; 

} 

 4.Create a root view entity for travel

AbapCatalog.viewEnhancementCategory: [#NONE] 
@AccessControl.authorizationCheck: #NOT_REQUIRED 
@EndUserText.label: 'root view for travel' 
@Metadata.ignorePropagatedAnnotations: true 
@ObjectModel.usageType:{ 
serviceQuality: #X, 
sizeCategory: #S, 
dataClass: #MIXED 

} 

define root view entity zi_travel_detail as select from zpd_dt_travel 
composition [0..*] of ZI_BOOKING_DETAIL as _booking 
association [0..1] to /DMO/I_Agency as _agency on $projection.AgencyId = _agency.AgencyID  
association [0..1] to /DMO/I_Customer as _customer on $projection.CustomerId = _customer.CustomerID 
association [1..1] to I_Currency as _currency on $projection.CurrencyCode = _currency.Currency 
association [1..1] to /DMO/I_Overall_Status_VH as _status on $projection.OverallStatus = _status.OverallStatus 

{ 

key travel_id as TravelId, 
agency_id as AgencyId, 
customer_id as CustomerId, 
begin_date as BeginDate, 
end_date as EndDate, 
@Semantics.amount.currencyCode: 'CurrencyCode' 
booking_fee as BookingFee, 
@Semantics.amount.currencyCode: 'CurrencyCode' 
total_price as TotalPrice, 
currency_code as CurrencyCode, 
description as Description, 
overall_status as OverallStatus, 
@Semantics.user.createdBy: true 
created_by as CreatedBy, 
@Semantics.systemDateTime.createdAt: true 
created_at as CreatedAt, 
@Semantics.user.localInstanceLastChangedBy: true 
last_changed_by as LastChangedBy, 
@Semantics.systemDateTime.localInstanceLastChangedAt: true 
last_changed_at as LastChangedAt, 
_agency, 
_customer, 
_currency, 
_status, 
_booking 

} 

5.Create interface view  for booking 

@EndUserText.label: 'root view for booking' 
@Metadata.ignorePropagatedAnnotations: true 
@ObjectModel.usageType:{ 
serviceQuality: #X, 
sizeCategory: #S, 
dataClass: #MIXED 

} 

define view entity ZI_BOOKING_DETAIL as select from zpd_dt_booking association to parent zi_travel_detail as _travel 
on $projection.TravelId = _travel.TravelId 
composition [0..*] of zi_booking_supp as _bookingsuppl  
association [1..1] to /DMO/I_Carrier as _carrier on $projection.CarrierId = _carrier.AirlineID 
association [1..1] to /DMO/I_Customer as _customer on $projection.CustomerId = _customer.CustomerID  
association [1..1] to /DMO/I_Connection as _connection on $projection.CarrierId = _connection.AirlineID 
and $projection.ConnectionId = _connection.ConnectionID 
association[1..1] to /DMO/I_Booking_Status_VH as _booking_status on $projection.BookingStatus = _booking_status.BookingStatus  

{  

key travel_id as TravelId, 
key booking_id as BookingId, 
booking_date as BookingDate, 
customer_id as CustomerId, 
carrier_id as CarrierId, 
connection_id as ConnectionId, 
flight_date as FlightDate, 
@Semantics.amount.currencyCode: 'CurrencyCode' 
flight_price as FlightPrice, 
currency_code as CurrencyCode, 
booking_status as BookingStatus, 
@Semantics.systemDateTime.localInstanceLastChangedAt: true 
last_changed_at as LastChangedAt, 
_carrier, 
_customer,
_connection,
_booking_status, 
_travel, 
_bookingsuppl 
} 

6.Create Interface view for Booking suppliment

@AbapCatalog.viewEnhancementCategory: [#NONE] 
@AccessControl.authorizationCheck: #NOT_REQUIRED 
@EndUserText.label: 'root view for booking suppliment' 
@Metadata.ignorePropagatedAnnotations: true 
@ObjectModel.usageType:{ 
serviceQuality: #X, 
sizeCategory: #S, 
dataClass: #MIXED 
} 

define view entity zi_booking_supp as select from zpd_dt_bsupplmnt 
association to parent ZI_BOOKING_DETAIL as _booking on $projection.TravelId = _booking.TravelId 
and $projection.BookingId = _booking.BookingId 
association[1..1] to zi_travel_detail as _travel on $projection.TravelId = _travel.TravelId 
association [1..1] to /DMO/I_Supplement as _suppliment on $projection.SupplementId = _suppliment.SupplementID 
association[1..*] to /DMO/I_SupplementText as _supplimentText on $projection.SupplementId = _supplimentText.SupplementID  

{ 

key travel_id as TravelId,  
key booking_id as BookingId, 
key booking_supplement_id as BookingSupplementId, 
supplement_id as SupplementId, 
@Semantics.amount.currencyCode: 'CurrencyCode' 
price as Price, 
currency_code as CurrencyCode, 
@Semantics.systemDateTime.localInstanceLastChangedAt: true 
last_changed_at as LastChangedAt, 
_travel, 
_supplimentText, 
_suppliment, 
_booking 

} 

7.Define projection for travel root entity 

@AccessControl.authorizationCheck: #NOT_REQUIRED 
@EndUserText.label: 'consumption view for travel' 
@Metadata.ignorePropagatedAnnotations: true 
@Metadata.allowExtensions: true 
define root view entity zc_travel_det provider contract transactional_query 
as projection on zi_travel_detail 

{ 

key TravelId, 
@ObjectModel.text.element: [ 'AgencyName' ] 
AgencyId, 
_Agency.Name as AgencyName, 
@ObjectModel.text.element: [ 'CustomerName' ] 
CustomerId, 
_Customer.LastName as CustomerName, 
BeginDate, 
EndDate, 
@Semantics.amount.currencyCode: 'CurrencyCode' 
BookingFee, 
@Semantics.amount.currencyCode: 'CurrencyCode' 
TotalPrice, 
CurrencyCode, 
Description, 
@ObjectModel.text.element: [ 'OverallStatusText' ] 
OverallStatus, 
_Status._Text.Text as OverallStatusText : localized, 
CreatedBy, 
CreatedAt, 
LastChangedBy, 
LastChangedAt, 
/* Associations */ 
_Agency, 
_booking : redirected to composition child zc_booking_det, 
_Currency, 
_Customer, 
_Status 

} 

 8.Define projection for booking  entity

@AccessControl.authorizationCheck: #NOT_REQUIRED 
@EndUserText.label: 'consumption view for booking' 
@Metadata.ignorePropagatedAnnotations: true 
@Metadata.allowExtensions: true 
define view entity zc_booking_det  
as projection on ZI_BOOKING_DETAIL 
{ 

key TravelId, 
key BookingId, 
BookingDate, 
@ObjectModel.text.element: [ 'CustomerName' ] 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Customer', 
element: 'CustomerID' 

} }] 

CustomerId, 
_customer.LastName as CustomerName, 
@ObjectModel.text.element: [ 'CarrierName' ] 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Carrier', 
element: 'AirlineId' 

} }] 

CarrierId, 
_carrier.Name as CarrierName, 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Flight', 
element: 'Connection Id' 

}  

}] 
ConnectionId,  
FlightDate, 
@Semantics.amount.currencyCode: 'CurrencyCode' 
FlightPrice, 
CurrencyCode, 
@ObjectModel.text.element: [ 'BookingStatusText' ] 
_booking_status._Text.Text as BookingStatusText : localized, 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Booking_Status_VH', 
element: 'Booking_Status' 

} }] 
BookingStatus, 
LastChangedAt, 
/* Associations */ 
_bookingsuppl : redirected to composition child zc_booking_supp, 
_booking_status, 
_carrier, 
_connection, 
_customer, 
_travel : redirected to parent zc_travel_det 

} 

9.Define projection for booking  suppliment  entity

@AccessControl.authorizationCheck: #NOT_REQUIRED 
@EndUserText.label: 'consumption view for booking suppliment' 
@Metadata.ignorePropagatedAnnotations: true 
@Metadata.allowExtensions: true 
define view entity zc_booking_supp  
as projection on zi_booking_supp 

{ 

key TravelId, 
key BookingId, 
key BookingSupplementId, 
@ObjectModel.text.element: [ 'SupplemenDesc' ] 
SupplementId, 
_SupplementText.Description as SupplemenDesc : localized, 
@Semantics.amount.currencyCode: 'CurrencyCode' 
Price, 
CurrencyCode, 
LastChangedAt, 
/* Associations */ 
_Travel : redirected to zc_travel_det,
_Booking : redirected to parent zc_booking_det, 
_Supplement, 
_SupplementText 

} 

10.provide metada extension for projected views

@Metadata.layer: #CORE 

@Search.searchable: true 
@UI.headerInfo: { 
typeName: 'Travel', 
typeNamePlural: 'Travels', 

title: { 
type: #STANDARD, 
label: 'Travel', 
value: 'TravelId' 

} 

} 
annotate view zc_travel_det 
with  

{ 

@UI.facet: [{ 
id: 'Travel', 
purpose: #STANDARD, 
position: 10 , 
label: 'Travel', 
type: #IDENTIFICATION_REFERENCE 

}, 

{ 

id: 'Booking', 
purpose: #STANDARD, 
position: 20 , 
label: 'Booking', 
type: #LINEITEM_REFERENCE, 
targetElement: '_booking' 

} 

] 

@UI.lineItem: [{ position: 10 }, { type:#FOR_ACTION, dataAction: 'CopyTravel', label: 'Copy Travel' } 
,{ type:#FOR_ACTION, dataAction: 'AcceptTravel', label: 'AcceptTravel' } 
,{ position: 30 },{ type:#FOR_ACTION, dataAction: 'RejectTravel', label: 'RejectTravel' }] 
@UI.identification: [{ position: 10 }] 
@Search.defaultSearchElement: true 
TravelId; 
@UI: { lineItem: [{ position: 40 }], 
selectionField: [{ position: 40 }], 
identification: [{ position: 40 }] 

} 

@Search.defaultSearchElement: true 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Agency', 
element: 'AgencyID' 

} }] 

AgencyId; 
// AgencyName; 
@UI: { lineItem: [{ position: 50 }], 
selectionField: [{ position: 50 }], 
identification: [{ position: 50 }] 
} 
@Search.defaultSearchElement: true 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Customer', 
element: 'CustomerID' 

} }] 
CustomerId; 
// CustomerName; 
@UI.lineItem: [{ position: 60 }] 
@UI.identification: [{ position: 60 }] 
BeginDate; 
@UI.lineItem: [{ position: 70 }] 
@UI.identification: [{ position: 70 }] 
EndDate; 
@UI.identification: [{ position: 75 }] 
BookingFee; 
@UI.lineItem: [{ position: 80 }] 
@UI.identification: [{ position: 80 }] 
TotalPrice; 
@Consumption.valueHelpDefinition: [{ entity: { 
name: 'I_Currency', 
element: 'Currency' 
} }] 

CurrencyCode; 
@UI.identification: [{ position: 85 }] 
Description; 
@UI: { lineItem: [{ position: 90 }],
selectionField: [{ position: 60 }], 
identification: [{ position: 90 }],
textArrangement: #TEXT_ONLY 
} 
@Search.defaultSearchElement: true 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Overall_Status_VH', 
element: 'OverallStatus' 
} }] 

OverallStatus; 
// OverallStatusText;
// .hidden: true 
// LastChangedAt; 

} 

11. metadata extension for booking entity

@Metadata.layer: #CORE 

@Search.searchable: true 
@UI.headerInfo: { 
typeName: 'Booking',
typeNamePlural: 'Bookings', 

title: { 
type: #STANDARD, 
label: 'Booking', 
value: 'BookingId' 

} 

} 

annotate view zc_booking_det 

with  

{ 

@UI.facet: [{ 
id: 'Booking', 
purpose: #STANDARD,
position: 10 , 
label: 'Booking', 
type: #IDENTIFICATION_REFERENCE 

}, 

{ 

id: 'BookingSuppl', 
purpose: #STANDARD, 
position: 20 ,  
label: 'Booking Suppliments', 
type: #LINEITEM_REFERENCE, 
targetElement: '_bookingsuppl' 

} 

] 

// .defaultSearchElement: true 
// TravelId; 

@UI.lineItem: [{ position: 10 }] 
@UI.identification: [{ position: 10 }] 
@Search.defaultSearchElement: true 
BookingId; 
@UI.lineItem: [{ position: 20 }] 
@UI.identification: [{ position: 20 }] 

BookingDate; 
@UI.lineItem: [{ position: 30 }] 
@UI.identification: [{ position: 30 }] 
@Search.defaultSearchElement: true 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Customer',
element: 'CustomerID' 

} }] 

CustomerId; 
@UI.lineItem: [{ position: 40 }] 
@UI.identification: [{ position: 40 }] 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Carrier', 
element: 'AirlineID' 

} }] 

CarrierId; 
@UI.lineItem: [{ position: 50 }] 
@UI.identification: [{ position: 50 }] 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Flight', 
element: 'ConnectionId' 

}, 

additionalBinding: [{ element: 'ConnectionId' ,  
localElement: 'ConnectionID'}, 
{ element: 'AirlineID' ,  
localElement: 'CarrierId'},  
{ element: 'CurrencyCode' ,  
localElement: 'CurrencyCode'}, 
{ element: 'Price' ,  
localElement: 'FlightPrice'} ] 

}]  

ConnectionId; 
@UI.lineItem: [{ position: 60 }] 
@UI.identification: [{ position: 60 }] 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Flight', 
element: 'FlightDate' 

}, 

additionalBinding: [{ element: 'FlightDate' ,  
localElement: 'FlightDate'}, 
{ element: 'AirlineID' ,  
localElement: 'CarrierId'},  
{ element: 'CurrencyCode' ,  

localElement: 'CurrencyCode'}, 
{ element: 'Price' ,  
localElement: 'FlightPrice'} ] 

}]  

FlightDate; 
@UI.lineItem: [{ position: 70 }] 
@UI.identification: [{ position: 70 }] 
FlightPrice; 
// @Consumption.valueHelpDefinition: [{ entity: { 
// name: 'I_Currency', 
// element: 'Currency' 

// } }] 

// CurrencyCode; 
@UI.lineItem: [{ position: 80 }]
@UI.identification: [{ position: 80 }] 
@UI.textArrangement: #TEXT_ONLY 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Booking_Status_VH', 
element: 'BookingStatus' 

} }] 

BookingStatus; 
// LastChangedAt; 

} 

12. Metadata extension for booking entity

@Metadata.layer: #CORE 

@Search.searchable: true 
@UI.headerInfo: { 
typeName: 'Booking', 
typeNamePlural: 'Bookings', 
title: { 
type: #STANDARD, 
label: 'Booking', 
value: 'BookingId' 

} 

} 
annotate view zc_booking_det 
with  

{ 

@UI.facet: [{ 
id: 'Booking', 
purpose: #STANDARD, 
position: 10 , 
label: 'Booking', 
type: #IDENTIFICATION_REFERENCE 

}, 

{ 

id: 'BookingSuppl', 
purpose: #STANDARD, 
position: 20 ,  
label: 'Booking Suppliments', 
type: #LINEITEM_REFERENCE, 
targetElement: '_bookingsuppl' 

} 

] 
// .defaultSearchElement: true 
// TravelId; 

@UI.lineItem: [{ position: 10 }] 
@UI.identification: [{ position: 10 }] 
@Search.defaultSearchElement: true 
BookingId; 
@UI.lineItem: [{ position: 20 }] 
@UI.identification: [{ position: 20 }] 
BookingDate; 
@UI.lineItem: [{ position: 30 }] 
@UI.identification: [{ position: 30 }] 
@Search.defaultSearchElement: true 
@Consumption.valueHelpDefinition: [{ entity: {
name: '/DMO/I_Customer', 
element: 'CustomerID' 

} }] 

CustomerId; 
@UI.lineItem: [{ position: 40 }] 
@UI.identification: [{ position: 40 }] 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Carrier', 
element: 'AirlineID' 

} }] 

CarrierId; 
@UI.lineItem: [{ position: 50 }] 
@UI.identification: [{ position: 50 }] 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Flight', 
element: 'ConnectionId' 

}, 
additionalBinding: [{ element: 'ConnectionId' ,  
localElement: 'ConnectionID'}, 

{ element: 'AirlineID' ,  
localElement: 'CarrierId'},  
{ element: 'CurrencyCode' ,  
localElement: 'CurrencyCode'}, 
{ element: 'Price' , 
localElement: 'FlightPrice'} ] 

}]  
ConnectionId; 
@UI.lineItem: [{ position: 60 }] 
@UI.identification: [{ position: 60 }] 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Flight', 
element: 'FlightDate' 

}, 

additionalBinding: [{ element: 'FlightDate' ,  
localElement: 'FlightDate'}, 
{ element: 'AirlineID' ,  
localElement: 'CarrierId'},  
{ element: 'CurrencyCode' ,  
localElement: 'CurrencyCode'}, 
{ element: 'Price' ,  
localElement: 'FlightPrice'} ] 

}]  
FlightDate; 
@UI.lineItem: [{ position: 70 }] 
@UI.identification: [{ position: 70 }] 

FlightPrice; 
// @Consumption.valueHelpDefinition: [{ entity: { 
// name: 'I_Currency', 
// element: 'Currency' 
// } }] 

// CurrencyCode; 
@UI.lineItem: [{ position: 80 }] 
@UI.identification: [{ position: 80 }] 
@UI.textArrangement: #TEXT_ONLY 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_Booking_Status_VH', 
element: 'BookingStatus' 

} }] 
BookingStatus; 
// LastChangedAt; 


} 

 13. Metadata extension for booking  suppliment entity

@Metadata.layer: #CORE 

@Search.searchable: true 
@UI.headerInfo: { 
typeName: 'BookingSuppl', 
typeNamePlural: 'BookingSuppls', 
title: { 
type: #STANDARD, 
label: 'Booking Suppliments', 
value: 'BookingSupplementId' 

} 
} 

annotate view zc_booking_supp 
with  
{ 
@UI.facet: [{ 
id: 'BookingSuppl', 
purpose: #STANDARD, 
position: 10 ,
label: 'Booking Suppliments', 
type: #IDENTIFICATION_REFERENCE 
} 
] 
// @Search.defaultSearchElement: true 
// TravelId; 
@Search.defaultSearchElement: true 
BookingId; 
@UI.lineItem: [{ position: 10 }] 
@UI.identification: [{ position: 10 }] 
BookingSupplementId; 
@UI.lineItem: [{ position: 20 }] 
@UI.identification: [{ position: 20 }] 
@Consumption.valueHelpDefinition: [{ entity: { 
name: '/DMO/I_SUPPLEMENT', 
element: 'SupplementID' 
}, 

additionalBinding: [{ element: 'SupplementID' , 
localElement: 'SupplementId'}, 
{ element: 'Price' , 
localElement: 'Price'}, 
{ element: 'CurrencyCode' , 
localElement: 'CurrencyCode'} 

] 

}] 
SupplementId; 
@UI.lineItem: [{ position: 30 }] 
@UI.identification: [{ position: 30 }] 

Price; 
// @Consumption.valueHelpDefinition: [{ entity: { 
// name: 'I_Currency', 
// element: 'Currency' 
// } }] 
// CurrencyCode; 
// @UI.hidden: true 
// LastChangedAt; 

} 

14. Create behaviour definition travel root entity 

managed; 

strict ( 2 ); 
define behavior for zi_travel_detail //alias <alias_name> 
implementation in class zcl_bp_travel_maa unique 
persistent table zpd_dt_travel 
lock master 
authorization master ( global ) 
etag master LastChangedAt 
early numbering 

{ 

field ( readonly ) TravelId; 
action AcceptTravel result [1] $self; 
action RejectTravel result [1] $self; 

factory action CopyTravel [1]; 
internal action RecalcTotalPrice; 
determination CalcTotalPrice on modify { create; field BookingFee, CurrencyCode; } 

// authorization ( global ), 
create; 
update; 
delete; 
// field ( readonly ) TravelId; 
association _booking { create; } 
mapping for zpd_dt_travel 
{ 

TravelId = travel_id; 
AgencyId = agency_id; 
CustomerId = customer_id; 
BeginDate = begin_date; 
EndDate = end_date; 
BookingFee = booking_fee; 
TotalPrice = total_price; 
CurrencyCode = currency_code; 
Description = description; 
OverallStatus = overall_status; 
CreatedBy = created_by; 
CreatedAt = created_at; 
LastChangedBy = last_changed_by; 
LastChangedAt = last_changed_at; 

} 
} 
define behavior for ZI_BOOKING_DETAIL //alias <alias_name> 
implementation in class zcl_bp_booking_ma unique 
persistent table zpd_dt_booking 
lock dependent by _Travel 
//authorization dependent by _travel 
authorization master ( global ) 
etag master LastChangedAt 
early numbering 
{ 
update; 
delete; 
field ( readonly ) TravelId, BookingId;

determination CalcTotalPrice on modify { create; field FlightPrice, CurrencyCode; } 
association _travel; 
association _bookingsuppl { create; } 
mapping for zpd_dt_booking 

{ 
TravelId = travel_id; 
BookingId = booking_id; 
BookingDate = booking_date; 
CustomerId = customer_id; 
CarrierId = carrier_id; 
ConnectionId = connection_id; 
FlightDate = flight_date; 
FlightPrice = flight_price; 

CurrencyCode = currency_code; 
BookingStatus = booking_status; 
LastChangedAt = last_changed_at; 

} 

} 
define behavior for zi_booking_supp //alias <alias_name> 
implementation in class zcl_bp_booking_ma unique 
persistent table zpd_dt_bsupplmnt 
lock dependent by _Travel 
//authorization dependent by _Travel 
authorization master ( global ) 
etag master LastChangedAt 
early numbering 

{ 
update; 
delete; 
field ( readonly ) TravelId, BookingId, BookingSupplementId; 
determination CalcTotalPrice on modify { create; field Price, CurrencyCode; } 
association _Travel; 
association _Booking; 
mapping for zpd_dt_bsupplmnt 
{ 

SupplementId = supplement_id; 
TravelId = travel_id; 
BookingId = booking_id; 
BookingSupplementId = booking_supplement_id; 
Price = price; 
CurrencyCode = currency_code; 
LastChangedAt = last_changed_at; 

} 

} 

15. Define behavior definition for projection root entity 

projection; 

strict ( 2 );
define behavior for zc_travel_det //alias <alias_name> 

{ 
use create; 
use update; 
use delete; 

use action AcceptTravel; 
use action RejectTravel; 
use action CopyTravel; 
use association _booking { create; } 

} 
define behavior for zc_booking_det //alias <alias_name> 

{ 

use update; 
use delete; 
use association _travel; 
use association _bookingsuppl { create; } 

} 

define behavior for zc_booking_supp //alias <alias_name> 
{ 

use update; 
use delete; 

use association _Travel; 
use association _Booking; 

} 

16. Create Service Definition

@EndUserText.label: 'service def for travel' 
define service Zsr_travel_det { 

expose zc_travel_det; 
expose zc_booking_det; 
expose zc_booking_supp;
expose /DMO/I_Supplement_StdVH as Supplement; 
expose /DMO/I_SupplementCategory_VH as SupplementCategory; 
expose /DMO/I_Customer_StdVH as Passenger; 
expose /DMO/I_Agency_StdVH as TravelAgency; 
expose /DMO/I_Carrier_StdVH as Airline; 
expose /DMO/I_Connection_StdVH as FlightConnection; 
expose /DMO/I_Flight_StdVH as Flight; 
expose /DMO/I_Airport_StdVH as Airport; 
expose /DMO/I_Overall_Status_VH as OverallStatus; 
expose /DMO/I_Booking_Status_VH as BookingStatus; 
expose I_CurrencyStdVH as Currency; 
expose I_CountryVH as Country; 

} 

17. Create service binding 

Pradeep555_0-1751354700486.png

18. Implement the class 

CLASS lhc_zi_travel_detail DEFINITION INHERITING FROM cl_abap_behavior_handler. 

PRIVATE SECTION. 

METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION 
IMPORTING REQUEST requested_authorizations FOR zi_travel_detail RESULT result. 
METHODS accepttravel FOR MODIFY 
IMPORTING keys FOR ACTION zi_travel_detail~accepttravel RESULT result. 
METHODS copytravel FOR MODIFY 
IMPORTING keys FOR ACTION zi_travel_detail~copytravel. 
METHODS recalctotalprice FOR MODIFY 
IMPORTING keys FOR ACTION zi_travel_detail~recalctotalprice. 
METHODS rejecttravel FOR MODIFY 
IMPORTING keys FOR ACTION zi_travel_detail~rejecttravel RESULT result. 
METHODS calctotalprice FOR DETERMINE ON MODIFY 
IMPORTING keys FOR zi_travel_detail~calctotalprice. 
METHODS earlynumbering_cba_booking FOR NUMBERING 
IMPORTING entities FOR CREATE zi_travel_detail\_booking. 
METHODS earlynumbering_create FOR NUMBERING 
IMPORTING entities FOR CREATE zi_travel_detail. 

ENDCLASS. 

CLASS lhc_zi_travel_detail IMPLEMENTATION. 
METHOD get_global_authorizations. 
ENDMETHOD. 

METHOD earlynumbering_create. 
DATA(lt_entities) = entities. 
DELETE lt_entities WHERE TravelId IS NOT INITIAL . 
TRY. 
cl_numberrange_runtime=>number_get( 

EXPORTING 
nr_range_nr = '01' 
object = '/DMO/TRV_M' 
quantity = CONV #( lines( lt_entities ) ) 
IMPORTING 
number = DATA(lv_latest_num) 
returncode = DATA(lv_code) 
returned_quantity = DATA(lv_qty) 

). 
CATCH cx_nr_object_not_found. 
CATCH cx_number_ranges INTO DATA(lo_error). 

LOOP AT lt_entities INTO DATA(ls_entities). 
APPEND VALUE #( %cid = ls_entities-%cid 
%key = ls_entities-%key ) 
TO failed-zi_travel_detail. 
APPEND VALUE #( %cid = ls_entities-%cid 
%key = ls_entities-%key 
%msg = lo_error ) 
TO reported-zi_travel_detail. 
ENDLOOP. 
EXIT. 
ENDTRY.. 

ASSERT lv_qty = lines( lt_entities ). 
DATA(lv_curr_num) = lv_latest_num - lv_qty. 
LOOP AT lt_entities INTO ls_entities. 
lv_curr_num = lv_curr_num + 1. 
APPEND VALUE #( %cid = ls_entities-%cid 
TravelId = lv_curr_num ) 
TO mapped-zi_travel_detail. 
ENDLOOP. 
ENDMETHOD. 

METHOD earlynumbering_cba_Booking. 

DATA : lv_max_booking TYPE /dmo/booking_id. 
READ ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_travel_detail BY \_booking 
FROM CORRESPONDING #( entities ) 
LINK DATA(lt_link_data). 
LOOP AT entities ASSIGNING FIELD-SYMBOL(<ls_group_entity>) 
GROUP BY <ls_group_entity>-TravelId. 

lv_max_booking = REDUCE #( INIT lv_max = CONV /dmo/booking_id( '0' ) 
FOR ls_link IN lt_link_data USING KEY entity 
WHERE ( source-TravelId = <ls_group_entity>-TravelId ) 
NEXT lv_max = COND /dmo/booking_id( WHEN lv_max < ls_link-target-BookingId 
THEN ls_link-target-BookingId 
ELSE lv_max ) ). 

lv_max_booking = REDUCE #( INIT lv_max = lv_max_booking 
FOR ls_entity IN entities USING KEY entity 
WHERE ( TravelId = <ls_group_entity>-TravelId ) 
FOR ls_booking IN ls_entity-%target 
NEXT lv_max = COND /dmo/booking_id( WHEN lv_max < ls_booking-BookingId 
THEN ls_booking-BookingId 
ELSE lv_max ) ). 
LOOP AT entities ASSIGNING FIELD-SYMBOL(<ls_entities>) 
USING KEY entity 
WHERE TravelId = <ls_group_entity>-TravelId. 

LOOP AT <ls_entities>-%target ASSIGNING FIELD-SYMBOL(<ls_booking>). 
IF <ls_booking>-BookingId IS INITIAL. 
lv_max_booking += 10. 
APPEND CORRESPONDING #( <ls_booking> ) TO mapped-zi_booking_detail ASSIGNING FIELD-SYMBOL(<ls_new_map_book>). 
<ls_new_map_book>-BookingId = lv_max_booking. 

ENDIF. 
ENDLOOP. 
ENDLOOP. 

ENDLOOP. 
ENDMETHOD. 

METHOD AcceptTravel. 
MODIFY ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_travel_detail 

UPDATE FIELDS ( OverallStatus ) 
WITH VALUE #( FOR ls_keys IN keys ( %tky = ls_keys-%tky 
OverallStatus = 'A') ). 
READ ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_travel_detail 
ALL FIELDS WITH CORRESPONDING #( keys ) 
RESULT DATA(lt_result). 
result = VALUE #( FOR ls_result IN lt_result ( %tky = ls_result-%tky 
%param = ls_result ) ). 

ENDMETHOD. 
METHOD CopyTravel. 
ENDMETHOD. 

 

METHOD RecalcTotalPrice.

TYPES : BEGIN OF ty_total, 
price TYPE /dmo/total_price, 
curr TYPE /dmo/currency_code, 
END OF ty_total. 

DATA : lt_total TYPE TABLE OF ty_total, 
lv_conv_price TYPE ty_total-price. 

READ ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_travel_detail 
FIELDS ( BookingFee CurrencyCode ) 
WITH CORRESPONDING #( keys ) 
RESULT DATA(lt_travel). 
DELETE lt_travel WHERE CurrencyCode IS INITIAL. 

READ ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_travel_detail BY \_booking 
FIELDS ( FlightPrice CurrencyCode ) 
WITH CORRESPONDING #( lt_travel ) 
RESULT DATA(lt_ba_booking) . 

READ ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_booking_detail BY \_bookingsuppl 
FIELDS ( Price CurrencyCode ) 
WITH CORRESPONDING #( lt_ba_booking ) 
RESULT DATA(lt_ba_bookingsupp) . 
LOOP AT lt_travel ASSIGNING FIELD-SYMBOL(<ls_travel>). 
lt_total = VALUE #( ( price = <ls_travel>-BookingFee curr = <ls_travel>-CurrencyCode ) ). 

LOOP AT lt_ba_booking ASSIGNING FIELD-SYMBOL(<ls_booking>) 
USING KEY entity 
WHERE TravelId = <ls_travel>-TravelId 
AND CurrencyCode IS NOT INITIAL.

APPEND VALUE #( price = <ls_booking>-FlightPrice curr = <ls_booking>-CurrencyCode ) 
TO lt_total. 

LOOP AT lt_ba_bookingsupp ASSIGNING FIELD-SYMBOL(<ls_bookingsupp>) 
USING KEY entity 
WHERE TravelId = <ls_booking>-TravelId 

AND BookingId = <ls_booking>-BookingId 
AND CurrencyCode IS NOT INITIAL. 
APPEND VALUE #( price = <ls_bookingsupp>-Price curr = <ls_bookingsupp>-CurrencyCode ) 

TO lt_total. 
ENDLOOP. 
ENDLOOP. 

LOOP AT lt_total ASSIGNING FIELD-SYMBOL(<ls_total>). 
IF <ls_total>-curr = <ls_travel>-CurrencyCode . 
lv_conv_price = <ls_total>-price . 
ELSE. 

/dmo/cl_flight_amdp=>convert_currency( 

EXPORTING 
iv_amount = <ls_total>-price 
iv_currency_code_source = <ls_total>-curr 
iv_currency_code_target = <ls_travel>-CurrencyCode 
iv_exchange_rate_date = cl_abap_context_info=>get_system_date( ) 
IMPORTING 
ev_amount = lv_conv_price 

). 

ENDIF. 
<ls_travel>-TotalPrice = <ls_travel>-TotalPrice + lv_conv_price. 
ENDLOOP.

MODIFY ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_travel_detail 
UPDATE FIELDS ( TotalPrice ) 
WITH CORRESPONDING #( lt_travel ). 
ENDLOOP. 

ENDMETHOD. 
METHOD RejectTravel. 

MODIFY ENTITIES OF zi_travel_detail IN LOCAL MODE 

ENTITY zi_travel_detail 
UPDATE FIELDS ( OverallStatus ) 
WITH VALUE #( FOR ls_keys IN keys ( %tky = ls_keys-%tky 
OverallStatus = 'X') ) 
REPORTED DATA(lt_travel). 

READ ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_travel_detail 
ALL FIELDS WITH CORRESPONDING #( keys ) 
RESULT DATA(lt_result). 
result = VALUE #( FOR ls_result IN lt_result ( %tky = ls_result-%tky 
%param = ls_result ) ). 
ENDMETHOD. 

METHOD CalcTotalPrice. 

MODIFY ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_travel_detail 
EXECUTE RecalcTotalPrice 
FROM CORRESPONDING #( keys ). 
ENDMETHOD. 

ENDCLASS. 

18. Here we are calculating the total  price , whenever somebody changes the total  Price and currency manually this determination  should call on transactional phase(on modify) 

METHOD CalcTotalPrice. 

MODIFY ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_travel_detail 
EXECUTE RecalcTotalPrice 
FROM CORRESPONDING #( keys ). 

ENDMETHOD. 

19.  will call RecacTotalPrice for each determination 

All the travel id which we modify  will trigger when we are calculating total price  

RecacTotalPrice--> will be called . We need to write the logic to modify Our BO instance based on travel ID And it will read and updae the price  

 Here the action will take care of the process – when we change the price  ( based on determination ) action will be called  

And as soon as price filed changes, determination happens  And we need to read the travel entity with fields booking fee and currency code  And we need to provide travel IDs which is present in keys  Result is taken in LT_TRAVEL 

Same thing we need to do it for boking and booking suppliment 

METHOD RecalcTotalPrice. 

TYPES : BEGIN OF ty_total, 
price TYPE /dmo/total_price, 
curr TYPE /dmo/currency_code, 
END OF ty_total. 

DATA : lt_total TYPE TABLE OF ty_total, 
lv_conv_price TYPE ty_total-price. 

READ ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_travel_detail 
FIELDS ( BookingFee CurrencyCode ) 
WITH CORRESPONDING #( keys ) 
RESULT DATA(lt_travel). 

DELETE lt_travel WHERE CurrencyCode IS INITIAL. 
READ ENTITIES OF zi_travel_detail IN LOCAL MODE 

ENTITY zi_travel_detail BY \_booking 
FIELDS ( FlightPrice CurrencyCode ) 
WITH CORRESPONDING #( lt_travel ) 
RESULT DATA(lt_ba_booking) . 
READ ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_booking_detail BY \_bookingsuppl 
FIELDS ( Price CurrencyCode ) 
WITH CORRESPONDING #( lt_ba_booking ) 

RESULT DATA(lt_ba_bookingsupp) . 

LOOP AT lt_travel ASSIGNING FIELD-SYMBOL(<ls_travel>). 
lt_total = VALUE #( ( price = <ls_travel>-BookingFee curr = <ls_travel>-CurrencyCode ) ). 

LOOP AT lt_ba_booking ASSIGNING FIELD-SYMBOL(<ls_booking>) 
USING KEY entity 
WHERE TravelId = <ls_travel>-TravelId 
AND CurrencyCode IS NOT INITIAL. 
APPEND VALUE #( price = <ls_booking>-FlightPrice curr = <ls_booking>-CurrencyCode ) 
TO lt_total. 
LOOP AT lt_ba_bookingsupp ASSIGNING FIELD-SYMBOL(<ls_bookingsupp>) 
USING KEY entity 

WHERE TravelId = <ls_booking>-TravelId 
AND BookingId = <ls_booking>-BookingId 
AND CurrencyCode IS NOT INITIAL. 

APPEND VALUE #( price = <ls_bookingsupp>-Price curr = <ls_bookingsupp>-CurrencyCode ) 
TO lt_total. 

ENDLOOP. 
ENDLOOP. 


LOOP AT lt_total ASSIGNING FIELD-SYMBOL(<ls_total>). 

IF <ls_total>-curr = <ls_travel>-CurrencyCode . 
lv_conv_price = <ls_total>-price . 
ELSE. 

/dmo/cl_flight_amdp=>convert_currency( 
EXPORTING 
iv_amount = <ls_total>-price 
iv_currency_code_source = <ls_total>-curr 
iv_currency_code_target = <ls_travel>-CurrencyCode 
iv_exchange_rate_date = cl_abap_context_info=>get_system_date( ) 
IMPORTING 
ev_amount = lv_conv_price 

). 
 
ENDIF. 

<ls_travel>-TotalPrice = <ls_travel>-TotalPrice + lv_conv_price. 

ENDLOOP. 

MODIFY ENTITIES OF zi_travel_detail in LOCAL MODE 
ENTITY zi_travel_detail 
UPDATE FIELDS ( TotalPrice ) 
WITH CORRESPONDING #( lt_travel ). 
ENDLOOP. 

ENDMETHOD. 

20.  Class for booking  suppliment

CLASS lhc_zi_booking_supp DEFINITION INHERITING FROM cl_abap_behavior_handler. 

PRIVATE SECTION. 

METHODS CalcTotalPrice FOR DETERMINE ON MODIFY 
IMPORTING keys FOR zi_booking_supp~CalcTotalPrice. 
METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION 
IMPORTING REQUEST requested_authorizations FOR zi_booking_supp RESULT result. 
ENDCLASS. 

CLASS lhc_zi_booking_supp IMPLEMENTATION. 
METHOD CalcTotalPrice. 

ENDMETHOD. 
METHOD get_global_authorizations. 
ENDMETHOD. 

ENDCLASS. 
 
CLASS lhc_zi_booking_detail DEFINITION INHERITING FROM cl_abap_behavior_handler. 

PRIVATE SECTION. 
METHODS earlynumbering_cba_Bookingsupp FOR NUMBERING 

IMPORTING entities FOR CREATE zi_booking_detail\_Bookingsuppl. 
METHODS CalcTotalPrice FOR DETERMINE ON MODIFY 
IMPORTING keys FOR zi_booking_detail~CalcTotalPrice. 

METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION 
IMPORTING REQUEST requested_authorizations FOR zi_booking_detail RESULT result. 

ENDCLASS. 


CLASS lhc_zi_booking_detail IMPLEMENTATION. 

METHOD earlynumbering_cba_Bookingsupp. 
DATA: max_booking_suppl_id TYPE /dmo/booking_supplement_id . 
READ ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_booking_detail BY \_Bookingsuppl 
FROM CORRESPONDING #( entities ) 
LINK DATA(booking_supplements). 

" Loop over all unique tky (TravelID + BookingID) 
LOOP AT entities ASSIGNING FIELD-SYMBOL(<booking_group>) GROUP BY <booking_group>-%tky. 

" Get highest bookingsupplement_id from bookings belonging to booking 
max_booking_suppl_id = REDUCE #( INIT max = CONV /dmo/booking_supplement_id( '0' ) 

FOR booksuppl IN booking_supplements USING KEY entity 
WHERE ( source-TravelId = <booking_group>-TravelId 
AND source-BookingId = <booking_group>-BookingId ) 
NEXT max = COND /dmo/booking_supplement_id( WHEN booksuppl-target-BookingSupplementId > max 
THEN booksuppl-target-BookingSupplementId 
ELSE max ) 

). 
" Get highest assigned bookingsupplement_id from incoming entities 

max_booking_suppl_id = REDUCE #( INIT max = max_booking_suppl_id 
FOR entity IN entities USING KEY entity 
WHERE ( TravelId = <booking_group>-TravelId 
AND BookingId = <booking_group>-BookingId ) 
FOR target IN entity-%target 
NEXT max = COND /dmo/booking_supplement_id( WHEN target-BookingSupplementId > max 
THEN target-BookingSupplementId 
ELSE max ) 

). 
" Loop over all entries in entities with the same TravelID and BookingID
LOOP AT entities ASSIGNING FIELD-SYMBOL(<booking>) USING KEY entity WHERE TravelId = <booking_group>-TravelId 
AND BookingId = <booking_group>-BookingId. 

" Assign new booking_supplement-ids 
LOOP AT <booking>-%target ASSIGNING FIELD-SYMBOL(<booksuppl_wo_numbers>). 
APPEND CORRESPONDING #( <booksuppl_wo_numbers> ) TO mapped-zi_booking_supp ASSIGNING FIELD-SYMBOL(<mapped_booksuppl>). 
IF <booksuppl_wo_numbers>-BookingSupplementId IS INITIAL. 
max_booking_suppl_id += 1 . 
<mapped_booksuppl>-BookingSupplementId = max_booking_suppl_id . 
ENDIF. 
ENDLOOP. 
ENDLOOP. 
ENDLOOP.
ENDMETHOD. 

21. Based on the booking fee  we need to calculate the total price  , So we need to write the logic in calcTotal price method

METHOD CalcTotalPrice. 

DATA : it_travel TYPE STANDARD TABLE OF zpd_dt_travel WITH UNIQUE HASHED KEY key COMPONENTS travel_id. 
it_travel = CORRESPONDING #( keys DISCARDING DUPLICATES MAPPING travel_id = TravelId ). 

MODIFY ENTITIES OF zi_travel_detail IN LOCAL MODE 
ENTITY zi_travel_detail 
EXECUTE RecalcTotalPrice 
FROM CORRESPONDING #( it_travel ). 

ENDMETHOD. 

22. OUTPUT

Pradeep555_1-1751356413745.png

 

23. Edit--> changing booking fee from 140 USD to 240 USD

Pradeep555_3-1751356464751.png

 

Pradeep555_4-1751356486334.png

24.   Click on save << after saving , the total price is still the same ---> not updated at the screen level 

Pradeep555_5-1751356553915.png

25.  When we refresh the page—the total price gets updated 

Pradeep555_6-1751356589520.png

 

26.  Now we need to use the side effects to make the data refreshed on save at screen level , So now it should not only be updated in the transactional buffer – it should  also be updated in the front end  

Pradeep555_7-1751356689309.png

27.  Change the booking fee 258 USD  and click on save 

Pradeep555_8-1751356741975.png

28. As soon as you click on save 

Pradeep555_9-1751356776648.png

 

Thanks and regards 

-PRADEEP ISHWAR DEVADIGA