当前位置: 首页 > 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.dtcms.com/a/324057.html

相关文章:

  • 从色彩心理学看嵌入式设备UI设计:原则、挑战与实践
  • 数据结构:栈和队列(Stack Queue)基本概念与应用
  • SpringAi 通过大模型来实现调用自己的Api
  • 复现论文《基于深度强化学习的微能源网能量管理与优化策略研究》
  • 创建降阶模型用于搅拌槽中的涡流预测
  • nestjs官网推荐typeorm而不是prisma的原因
  • 第十六讲:AVL树和红黑树
  • MySQL的隔离级别及MVCC原理解析
  • AutoGPT与AgentGPT引领自动化革命
  • openresty-lua-redis案例
  • 无须炮解,打开即是Pro版
  • 商业银行元宇宙布局现状及未来图景三维思考
  • 基于BP神经网络PID控制的电机转速控制器设计复现
  • 使用tcp ntrip 协议 接收数据报错 java.net.SocketException: Connection reset
  • Shell脚本-变量的定义方式有哪些
  • TF-IDF提取关键词(附实战案例)
  • ​LabVIEW键盘鼠标监控
  • Python 2025:最新技术趋势与展望
  • [激光原理与应用-223]:机械 - 机加厂加工机械需要2D还是3D图?
  • 红楼梦文本数据分析
  • Fish shell的abbr命令行参数介绍和Bat文件查看工具
  • 诺基亚就4G/5G相关专利起诉吉利对中国汽车及蜂窝模组企业的影响
  • (一)Tailwindcss
  • 【开源】分层状态机(HFSM)解析:复杂逻辑的清晰表达与FPGA实现(附完整的Verilog交通灯案例及仿真)
  • Loki+Alloy+Grafana构建轻量级的日志分析系统
  • aurora接口ufc控流设计
  • Rust面试题及详细答案120道(11-18)-- 控制流与函数
  • Docker 镜像常见标签(如 `标准`、`slim`、`alpine` 和 `noble`)详细对比
  • 利用 SD-WAN 技术优化机房运维与网络安全评估的最佳实践
  • 2025下半年AI技术热点全景透视:从多模态革命到具身智能爆发