SAP学习笔记 - 开发57 - RAP开发 Managed App RAP action 之 Accept Travel 和 Reject Travel
上一章讲了RAP action 指 Copy Travel。
SAP学习笔记 - 开发56 - RAP开发 Managed App RAP action: Processor/ Approver,Copy Travel 功能实现-CSDN博客
本章继续将RAP action的相关内容。
目录
1,需求说明
2,New Projection View
2-1,Z04_PV_Travel_M_Approver
2-2,Z04_PV_Booking_M_Approver
2-3,设定Project View之间的父子关系
2-4,设定Metadata - Z04_PV_Travel_M_Approver
2-5,设定Metadata - Z04_PV_Booking_M_Approver
3,New Behavior Definition - Z04_PV_Travel_M_Approver
4,New Service Definition
5,New Service Binding
6,测试一下Layout
7,Accept Travel 功能实现
a),修改实体数据
b),读取更新后的数据
c),构建返回结果
d),总结
8,Reject Travel 功能实现
9,测试 Accept Travel 和 Reject Travel 功能
9-1,Accept Travel
9-2,Reject Travel
9-3,Accept Travel - Object Page
9-4,Reject Travel - Object Page
下面是详细内容。
1,需求说明
本章要做 Accept Travel,Reject Travel 两个更新操作。
设定的背景是该用户不能看到Create,Delete功能,只能做Accept,Reject,以及部分编集。
另外,该用户不需要看到 Booking Supplement,只需要看到 Travel,Booking两个表的数据。
为了实现这个功能,咱们需要新做一个 Projection View,并在其基础上,做 Behavior,Service。
下面来实操,看系统上怎么实现。
2,New Projection View
2-1,Z04_PV_Travel_M_Approver
右键 Data View,点 New Data Definition
输入Name,Description,点Next
选中ProjectionView模板,点Finish
这样就做好了,注意Currency Code,以及provider contract 设定
同样,把Booking 的Projection View也做了
2-2,Z04_PV_Booking_M_Approver
2-3,设定Project View之间的父子关系
2-4,设定Metadata - Z04_PV_Travel_M_Approver
推荐还是要使用单独的Metadata文件,这里就偷懒给放到 Projection View里面
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Data Definition for Z04_PV_Travel_M_Approver - Projection V'
@Metadata.ignorePropagatedAnnotations: true
@UI.headerInfo: {typeName: 'Travel',typeNamePlural: 'Travels',title: {type: #STANDARD,label: 'Travel',value: 'TravelId'}
}
define root view entity Z04_PV_Travel_M_Approverprovider contract transactional_queryas projection on Z04_DV_Travel_M{@UI.facet: [{id: 'TravelDetail',purpose: #STANDARD,parentId: '',position: 10,label: 'Travel Detail',type: #IDENTIFICATION_REFERENCE},{id: 'Booking',purpose: #STANDARD,parentId: '',position: 20,label: 'Bookings',targetElement: '_Booking',type: #LINEITEM_REFERENCE}]@UI:{ lineItem:[{ position: 10 }],identification: [{ position: 10 }]}@Search.defaultSearchElement: truekey TravelId,@UI:{ lineItem:[{ position: 20, importance: #HIGH }],selectionField: [{ position: 20 }],identification: [{ position: 20 }]}@Search.defaultSearchElement: true@Consumption.valueHelpDefinition: [{ entity: {name: '/DMO/I_Agency',element: 'AgencyID'},label: 'Agency'}]@ObjectModel.text.element: [ 'AgencyName' ]AgencyId,_Agency.Name as AgencyName,@UI:{ lineItem:[{ position: 30 }],selectionField: [{ position: 30 }],identification: [{ position: 30 }]}@Search.defaultSearchElement: true@Consumption.valueHelpDefinition: [{entity: {name: '/DMO/I_Customer',element: 'CustomerID'},label: 'Customer'}]@ObjectModel.text.element: [ 'CustomerName' ]CustomerId,_Customer.LastName as CustomerName,@UI:{ lineItem:[{ position: 40 }],identification: [{ position: 40 }]}BeginDate,@UI:{ lineItem:[{ position: 50 }],identification: [{ position: 50 }]}EndDate,@Semantics.amount.currencyCode: 'CurrencyCode'@UI:{ lineItem:[{ position: 55 }],identification: [{ position: 55 }]}BookingFee,@Semantics.amount.currencyCode: 'CurrencyCode'@UI:{ lineItem:[{ position: 60 }],identification: [{ position: 60 }]}TotalPrice,@Consumption.valueHelpDefinition: [{entity: {name: 'I_Currency',element: 'Currency'},label: 'Currency'}]CurrencyCode,@UI:{ lineItem:[{ position: 60 }],identification: [{ position: 65 }]}Description,@UI:{ lineItem:[{ position: 70 },{ type:#FOR_ACTION, dataAction: 'acceptTravel', label: 'Accept Travel' },{ type:#FOR_ACTION, dataAction: 'rejectTravel', label: 'Reject Travel' }],selectionField: [{ position: 70 }],identification: [{ position: 70 },{ type:#FOR_ACTION, dataAction: 'acceptTravel', label: 'Accept Travel' },{ type:#FOR_ACTION, dataAction: 'rejectTravel', label: 'Reject Travel' }],textArrangement: #TEXT_ONLY}@Search.defaultSearchElement: true@Consumption.valueHelpDefinition: [{entity: {name: '/DMO/I_Overall_Status_VH',element: 'OverallStatus'},label: 'Overall Status'}]@ObjectModel.text.element: [ 'OverallStatusText' ]OverallStatus,@UI.hidden: true_Status._Text.Text as OverallStatusText : localized,@UI.hidden: trueCreatedBy,@UI.hidden: trueCreatedAt,@UI.hidden: trueLastChangedBy,@UI.hidden: trueLastChangedAt,/* Associations */_Agency,_Booking : redirected to composition child Z04_PV_Booking_M_Approver,_Currency,_Customer,_Status
}
2-5,设定Metadata - Z04_PV_Booking_M_Approver
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Data Definition for Z04_PV_Booking_M_Approver - Projection V'
@Metadata.ignorePropagatedAnnotations: true
@UI.headerInfo: {typeName: 'Booking',typeNamePlural: 'Bookings',title: {type: #STANDARD,label: 'Booking',value: 'BookingId'}
}
@Search.searchable: true
define view entity Z04_PV_Booking_M_Approveras projection on Z04_DV_Booking_M
{@UI.facet: [{id: 'BookingDetail',purpose: #STANDARD,parentId: '',position: 10,label: 'Booking Detail',type: #IDENTIFICATION_REFERENCE}]@Search.defaultSearchElement: truekey TravelId,@UI:{ lineItem:[{ position: 20 }],identification: [{ position: 20 }]}@Search.defaultSearchElement: truekey BookingId,@UI:{ lineItem:[{ position: 30 }],identification: [{ position: 30 }]}BookingDate,@UI:{ lineItem:[{ position: 40 }],identification: [{ position: 40 }]}@Search.defaultSearchElement: true@Consumption.valueHelpDefinition: [{ entity: {name: '/DMO/I_Customer',element: 'CustomerID'} }]@ObjectModel.text.element: [ 'CustomerName' ]CustomerId,_Customer.LastName as CustomerName,@UI:{ lineItem:[{ position: 50 }],identification: [{ position: 50 }]}@Consumption.valueHelpDefinition: [{ entity: {name: '/DMO/I_Carrier',element: 'AirlineID'} }]@ObjectModel.text.element: [ 'CarrierName' ]CarrierId,_Carrier.Name as CarrierName,@UI:{ lineItem:[{ position: 60 }],identification: [{ position: 60 }]}ConnectionId,@UI:{ lineItem:[{ position: 70 }],identification: [{ position: 70 }]}FlightDate,@Semantics.amount.currencyCode: 'CurrencyCode'@UI:{ lineItem:[{ position: 80 }],identification: [{ position: 80 }]}FlightPrice,CurrencyCode,@UI:{ lineItem:[{ position: 90 }],identification: [{ position: 90 }],textArrangement: #TEXT_ONLY}@Consumption.valueHelpDefinition: [{ entity: {name: '/DMO/I_Booking_Status_VH',element: 'BookingStatus'} }]@ObjectModel.text.element: [ 'BookingStatusText' ]BookingStatus,@UI.hidden: true_Booking_Status._Text.Text as BookingStatusText : localized,@UI.hidden: trueLastChangedAt,/* Associations */_BookingSupplement,_Booking_Status,_Carrier,_Connection,_Customer,_Travel : redirected to parent Z04_PV_Travel_M_Approver
}
3,New Behavior Definition - Z04_PV_Travel_M_Approver
右键 Projection View,然后点 New Behavior Definition
输入Name,Description,点Next
然后点Finish,就建好了
但是注意我们这里不需要Create,Delete,所以都去掉
Booking方面,也不需要Update,Delete,也去掉,就变成下面这个样子的
projection;
strict ( 2 );define behavior for Z04_PV_Travel_M_Approver //alias <alias_name>
use etag
{
// use create;use update;
// use delete;use action acceptTravel;use action rejectTravel;
// use action copyTravel;// use association _Booking { create; }
}
//
//define behavior for Z04_PV_Booking_M_Approver //alias <alias_name>
//{
// use update;
// use delete;
//
// use association _Travel;
//}
4,New Service Definition
右键 Projection View,点 New Service Definition
输入Name,Description,点Next
再点Next,然后点Finish,这样就完成了
将 Booking 也暴露,然后点 Alt+F3,激活
5,New Service Binding
右键 Service Definition,然后点 New Service Binding
输入Name,Description,Binding Type,然后点Next
再点Finish 就建好了
按 Ctrl+F3激活,然后点Publish,发布
6,测试一下Layout
Layout基本上没啥问题。
List Report
Object Page
按钮位置好像不对,这个也可以通过Position设定
刷新一下,就OK了
万事具备,就剩下实现具体功能了。
7,Accept Travel 功能实现
METHOD acceptTravel.MODIFY ENTITIES OF Z04_DV_Travel_M IN LOCAL MODEENTITY Z04_DV_Travel_MUPDATE FIELDS ( OverallStatus )WITH VALUE #( FOR ls_keys IN keys ( %tky = ls_keys-%tkyOverallStatus = 'A' ) ).READ ENTITIES OF Z04_DV_Travel_M IN LOCAL MODEENTITY Z04_DV_Travel_MALL FIELDS WITH CORRESPONDING #( keys )RESULT DATA(lt_result).result = VALUE #( FOR ls_result IN lt_result ( %tky = ls_result-%tky%param = ls_result ) ).ENDMETHOD.
下面来看一下代码解释。
这段代码是一个RAP (Restful ABAP Programming) action的实现,用于将旅行记录的状态更新为"已接受"(A)。以下是代码的详细解释:
a),修改实体数据
abap
MODIFY ENTITIES OF Z04_DV_Travel_M IN LOCAL MODEENTITY Z04_DV_Travel_MUPDATE FIELDS ( OverallStatus )WITH VALUE #( FOR ls_keys IN keys ( %tky = ls_keys-%tkyOverallStatus = 'A' ) ).
这部分代码执行以下操作:
-
MODIFY ENTITIES
- 修改实体数据 -
OF Z04_DV_Travel_M
- 操作的是名为Z04_DV_Travel_M
的CDS视图实体 -
IN LOCAL MODE
- 在本地模式下运行(不触发到数据库的直接修改) -
更新
Z04_DV_Travel_M
实体的OverallStatus
字段 -
使用
VALUE #(...)
构造器为每个传入的key设置新值:-
%tky
- 技术key(包含业务对象的key字段) -
OverallStatus = 'A'
- 将状态设置为'A'(表示"已接受")
-
b),读取更新后的数据
abap
READ ENTITIES OF Z04_DV_Travel_M IN LOCAL MODEENTITY Z04_DV_Travel_MALL FIELDS WITH CORRESPONDING #( keys )RESULT DATA(lt_result).
这部分代码读取刚刚更新后的数据:
-
从同一个实体
Z04_DV_Travel_M
中读取数据 -
读取所有字段(
ALL FIELDS
) -
使用传入的
keys
作为筛选条件 -
将结果存储在内部表
lt_result
中
c),构建返回结果
abap
result = VALUE #( FOR ls_result IN lt_result ( %tky = ls_result-%tky%param = ls_result ) ).
这部分构建方法的返回结果:
-
使用
VALUE #(...)
构造器为每个结果记录创建条目 -
每个条目包含:
-
%tky
- 技术key -
%param
- 完整的实体数据(作为参数返回)
-
d),总结
这个acceptTravel
action的主要功能是:
-
接收一组旅行记录的key
-
将这些记录的
OverallStatus
字段更新为'A'(表示接受) -
读取并返回更新后的完整记录数据
这是RAP中处理业务对象状态变更的标准模式,遵循ABAP RESTful Application Programming Model的规范。
Reject Travel 和 Accept Travel 功能基本相同,唯一不同的就是设定的值不同。
8,Reject Travel 功能实现
- OverallStatus = 'X'
METHOD rejectTravel.MODIFY ENTITIES OF Z04_DV_Travel_M IN LOCAL MODEENTITY Z04_DV_Travel_MUPDATE FIELDS ( OverallStatus )WITH VALUE #( FOR ls_keys IN keys ( %tky = ls_keys-%tkyOverallStatus = 'X' ) ).READ ENTITIES OF Z04_DV_Travel_M IN LOCAL MODEENTITY Z04_DV_Travel_MALL FIELDS WITH CORRESPONDING #( keys )RESULT DATA(lt_result).result = VALUE #( FOR ls_result IN lt_result ( %tky = ls_result-%tky%param = ls_result ) ).ENDMETHOD.
OverallStatus 的值有 3个,O:Open/ A:Accepted/ X:Rejected
9,测试 Accept Travel 和 Reject Travel 功能
9-1,Accept Travel
选中一条,然后点 Accept Travel 按钮
状态已经变为了 A:Accepted(受入)
9-2,Reject Travel
选中一条,然后点 Reject Travel 按钮
状态已经变为了 X:Rejected(拒否)
看一下数据库,Accept Travel/ Reject Travel 都已经写到数据库里面去了。
9-3,Accept Travel - Object Page
点 Accept Travel
修改成功
9-4,Reject Travel - Object Page
点 Reject Travel
修改成功
数据也更新了
Accept Travel,Reject Travel 本身功能就是更新一个字段,所以代码也比较少。
但是因为功能所限,所以要单独开一个App,重新做一遍 Projection View,Service,Binding。
以上就是本篇的全部内容。
如果大家觉得还行,希望大家多点赞,收藏,转发,感谢!
更多SAP顾问业务知识请点击下面目录链接或东京老树根的博客主页
https://blog.csdn.net/shi_ly/category_12216766.html
东京老树根-CSDN博客