当前位置: 首页 > news >正文

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' ) ).

这部分代码执行以下操作:

  1. MODIFY ENTITIES - 修改实体数据

  2. OF Z04_DV_Travel_M - 操作的是名为Z04_DV_Travel_M的CDS视图实体

  3. IN LOCAL MODE - 在本地模式下运行(不触发到数据库的直接修改)

  4. 更新Z04_DV_Travel_M实体的OverallStatus字段

  5. 使用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).

这部分代码读取刚刚更新后的数据:

  1. 从同一个实体Z04_DV_Travel_M中读取数据

  2. 读取所有字段(ALL FIELDS)

  3. 使用传入的keys作为筛选条件

  4. 将结果存储在内部表lt_result

c),构建返回结果

abap

result = VALUE #( FOR ls_result IN lt_result ( %tky = ls_result-%tky%param = ls_result ) ).

这部分构建方法的返回结果:

  1. 使用VALUE #(...)构造器为每个结果记录创建条目

  2. 每个条目包含:

    • %tky - 技术key

    • %param - 完整的实体数据(作为参数返回)

d),总结

这个acceptTravel action的主要功能是:

  1. 接收一组旅行记录的key

  2. 将这些记录的OverallStatus字段更新为'A'(表示接受)

  3. 读取并返回更新后的完整记录数据

这是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博客

http://www.xdnf.cn/news/1276471.html

相关文章:

  • special topic 8 (2) and topic 9 (1)
  • 一键复制产品信息到剪贴板
  • Kafka消费者相关原理
  • K8s DaemonSet 详解
  • es-drager-blog
  • 安全生产基础知识(一)
  • ThreadLocal的原理是什么,使用场景有哪些?
  • 状态机浅析
  • Linux操作系统从入门到实战(十八)在Linux里面怎么查看进程
  • Pico+unity VR入门开发超详细笔记2025
  • SpringBoot实现文件上传
  • 一些js数组去重的实现算法
  • 故障诊断 | VMD-CNN-BiLSTM西储大学轴承故障诊断附MATLAB代码
  • MyBatis进阶:动态SQL、多表查询、分页查询
  • openresty-lua-redis案例
  • Python 的列表 list 和元组 tuple 有啥本质区别?啥时候用谁更合适?
  • Ubuntu 安装 Kibana
  • 旅行者1号无线电工作频段
  • MyBatisPlus插件原理
  • MVCC和日志
  • 音视频学习(五十一):AAC编码器
  • C4.5算法:增益率(Gain Ratio)
  • 嵌入式第二十四课!!linux应用软件编程与文件操作!!!
  • Rust 实战四 | Traui2+Vue3+Rspack 开发桌面应用:通配符掩码计算器
  • JAVA+AI简化开发操作
  • Java集合中的 LinkedList
  • 每日任务day0810:小小勇者成长记之武器精炼
  • node.js 学习笔记3 HTTP
  • Django @login_required实现登陆认证
  • C/C++内存管理函数模板