SAP学习笔记 - 开发50 - RAP开发 Managed App Locking、Numbering

上一章学习了RAP开发的一些知识,Mapping,Behavior Pool Class,ETag。

https://blog.csdn.net/shi_ly/article/details/149477441

本章继续学习RAP的知识 - RAP开发中常用的两个概念,Locking 和 Numbering。

- Locking 是行级锁,不仅是本表,它也会同步锁住关联表的相应行;

- Numbering是自带採番,和Open系中的自增字段还是不一样的。

本章主要是偏理论的,以后再说实战内容。

目录

1,Locking

1-1,Locking业务流程

1-2,Locking的逻辑流程

1-3,Lock的继承/Lock master,Lock dependent

2,Numbering

2-1. Early Numbering(早期编号)

a.用途

b.使用时机

c.实现方式

2-2. Late Numbering(延迟编号)

a.用途

b.使用时机

c.实现方式

2-3. 对比与选择标准

2-4. 实际应用示例

a.Early Numbering实现示例

b.Late Numbering实现示例

2-5. 最佳实践建议

3,Early numbering - Travel ID

3-1,early numbering - Z04_DV_Travel_M (Behavior Definition)

a),加 association

b),Add earlynumbering method

3-2,entities 参数详解

a. 参数基础信息

b. 参数结构详解

(1) 字段列表(Components)

(2) 组件组(Component Groups)

(3) 表键(Table Keys)

c. 关键应用场景

(1) 自定义主键生成

(2) 字段默认值逻辑

(3) 控制字段访问

d. 注意事项

3-3,RAP开发中,Fiori element里面,derived type是什么?

a. 核心概念

b. 常见用途

c. 具体示例

(1) 在 CDS 中定义派生类型

(2) 在 RAP BO 行为定义中

d. Fiori Elements 中的效果

e. 与其他类型的区别

f. 最佳实践

3-4,Derived Type(派生类型的实例)

a. 基础数据类型标准化

(1) 通用业务键(Business Key)

(2) 金额与货币

b. 状态与枚举值

(3) 标准化状态码

(4) 布尔标志(Yes/No)

c. 日期与时间

(5) 带语义的日期

d. 复杂业务场景

(6) 地址信息组合

(7) 单位与数量

e. 派生类型的进阶用法

(8) 继承注解

(9) 跨服务复用

f.最佳实践总结

3-5,earlynumbering_create - 详解

a. 方法签名说明

(1) 输入参数 entities

(2) 输出参数 mapped

(3) 输出参数 failed

(4) 输出参数 reported

b. 典型代码实现示例

c. 关键注意事项

d. 常见业务场景

(1) 自动生成订单号

(2) 依赖外部系统的键分配

(3) 字段默认值


下面是详细内容。

1,Locking

1-1,Locking业务流程

- Update 请求: 由客户端请求到Business Object

- BO会去 Check有没有被Lock

  - 如果被Lock的话,就会拒绝该 Update操作

  - 如果没被Lock的话,就会设置Lock,然后执行该 Update操作

- 执行Update操作

- 执行完Update操作之后,就会移除该Lock,并返回Response给客户端

1-2,Locking的逻辑流程

- EML Modify:在作成/ 编集页面,入力时并不会Lock 该数据,当点 作成/保存的时候才会Lock

- 如果有 Global Authoritation,那么会先调用它

- 如果由 Lock Implement,那么会先调用它

- 执行 Managed Lock

- 如果是 Unmanaged BO,那么会去调用手写的 Lock 代码

 

1-3,Lock的继承/Lock master,Lock dependent

比如下图的示例,Travel(父对象)-》Booking(子对象)-》Booking Supplement(孙对象)

那么咱们在Travel上设置 Lock Master,Booking/Booking Supplement上设置Lock dependent,

那么它们三个就变成一个整体了。

- 当Travel表中的某条数据被Lock的时候,对应的Booking/Book Supplement表中的数据也被Lock

Travel_M的 写法就是这个:

lock master

Booking_M,BookSuppl_M 的写法都是这个:

lock dependent by _Travel 

注意点:当用 lock dependent 的时候,必须要显式的注明 association,比如

- Booking_M的 association :

  - association _Travel;

- BookSuppl_M的 association:

  - association _Travel;

  - association _Booking;

上面说的是locking 的概念,它实现的是行级锁。

下面说另外一个概念,Numbering,其实对应到SAP里面,就是採番,比如购买发注,受注等等,所有的传票都需要採番,是自带採番,还是手动输入,也是可以Customize的。

咱们这里说的Numbering,相当于是自带採番。

2,Numbering

RAP开发中有 Early Numbering与Late Numbering两种。

在SAP RAP (Restful ABAP Programming) 模型和Fiori Elements开发中,Early Numbering(早期编号)和Late Numbering(延迟编号)是两种处理实体键值生成的策略,它们在业务对象行为(BO Behavior)定义中扮演重要角色。

2-1. Early Numbering(早期编号)

a.用途

  • 客户端即时反馈:在数据发送到服务器前就生成键值,提供更流畅的用户体验

  • 依赖键值的操作:当后续操作需要依赖已生成的键值时使用

  • 乐观锁定场景:在乐观锁定策略下提前建立对象标识

b.使用时机

  • 创建新条目时需要立即显示键值

  • 当UI需要基于生成的键值执行后续操作时

  • 在离线场景或高延迟网络环境下

c.实现方式

在行为定义(BDEF)中:

abap

early numbering;

在行为池(BEHAVIOR POOL)中实现方法:

abap

METHODS earlynumbering FOR NUMBERING
  IMPORTING entities FOR CREATE <entity_name>.

2-2. Late Numbering(延迟编号)

a.用途

  • 服务器端生成键值:由数据库或业务逻辑决定最终键值

  • 复杂键生成逻辑:当键值生成需要访问服务器端数据或复杂逻辑时

  • 数据库序列依赖:当键值依赖于数据库序列或触发器时

b.使用时机

  • 键值需要从数据库序列获取

  • 键值生成需要复杂业务逻辑

  • 不要求客户端立即知道键值

  • 需要确保键值唯一性的严格场景

c.实现方式

在行为定义(BDEF)中:

abap

late numbering;

在行为池(BEHAVIOR POOL)中实现方法:

abap

METHODS latenumbering FOR NUMBERING
  IMPORTING entities FOR CREATE <entity_name>.

2-3. 对比与选择标准

特性Early NumberingLate Numbering
生成时机客户端提交前服务器端处理时
用户体验更流畅(立即显示ID)可能有短暂延迟
实现复杂度需客户端逻辑需服务器端逻辑
适用场景简单自增ID复杂ID(如依赖其他数据)
网络要求适合高延迟环境需要稳定连接

2-4. 实际应用示例

a.Early Numbering实现示例

abap

METHOD earlynumbering.
  DATA: max_travel_id TYPE /dmo/travel_id.
  
  " 获取当前最大ID
  SELECT MAX( travel_id ) FROM /dmo/travel INTO @max_travel_id.
  
  " 为新实体分配ID
  LOOP AT entities INTO DATA(entity).
    max_travel_id += 10.
    mapped-travel = VALUE #( BASE mapped-travel
      ( %cid = entity-%cid travel_id = max_travel_id )
    ).
  ENDLOOP.
ENDMETHOD.

b.Late Numbering实现示例

abap

METHOD latenumbering.
  " 使用数据库序列获取新ID
  LOOP AT entities INTO DATA(entity).
    /dmo/cl_flight_amdp=>get_next_travel_id( IMPORTING ev_travel_id = DATA(travel_id) ).
    
    mapped-travel = VALUE #( BASE mapped-travel
      ( %cid = entity-%cid travel_id = travel_id )
    ).
  ENDLOOP.
ENDMETHOD.

2-5. 最佳实践建议

  1. 简单场景优先Early Numbering:当键值生成逻辑简单时,优先使用Early Numbering提升用户体验

  2. 复杂逻辑使用Late Numbering:当键值生成需要数据库访问或复杂计算时使用Late Numbering

  3. 混合使用:某些场景可以组合使用 - 先用Early Numbering提供临时ID,再用Late Numbering分配最终ID

  4. 考虑事务一致性:Late Numbering更适合需要严格事务一致性的场景

  5. 性能考量:Early Numbering减少服务器往返,但可能增加客户端复杂度

理解这两种编号策略的区别和适用场景,将帮助您设计出更高效、用户体验更好的Fiori Elements应用。

下面我们在系统上看一下如何做Numberling。

3,Early numbering - Travel ID

3-1,early numbering - Z04_DV_Travel_M (Behavior Definition)

a),加 association

- early numbering

- field ( readonly ) TravelId; =》因为既然已经是自带设定Key了,那么就不需要输入了嘛

b),Add earlynumbering method

它其实是在 Behavior Pool 里面生成了Method

METHODS earlynumbering_create FOR NUMBERING
  IMPORTING entities FOR CREATE Z04_DV_Travel_M.

点一下 entities,然后按 F2 

F2 是干啥的呢?

F2 - Show Code Element Information

看着像是你不知道某个元素是干啥的,点一下,然后按一下 F2,就能告诉你这个元素的详细

3-2,entities 参数详解

下面来看一下这些参数的含义。

entities type table for create z04_dv_travel_m
Components	Mand. Create	Mand. Save	Readonly
%cid	type abp_behv_cid				
travelid	type /dmo/travel_id				
agencyid	type /dmo/agency_id				
customerid	type /dmo/customer_id				
begindate	type /dmo/begin_date				
enddate	type /dmo/end_date				
bookingfee	type /dmo/booking_fee				
totalprice	type /dmo/total_price				
currencycode	type /dmo/currency_code				
description	type /dmo/description				
overallstatus	type /dmo/overall_status				
createdby	type abp_creation_user				
createdat	type abp_creation_tstmpl				
lastchangedby	type abp_locinst_lastchange_user				
lastchangedat	type abp_locinst_lastchange_tstmpl				
%control	[ control structure... ]				

Component Groups
%data	[ derived type... ]	
%key	[ derived type... ]	
Primary Table Key
primary_key	non-unique, standard, empty
Secondary Table Keys
cid	non-unique, sorted, userdefined
%cid	type abp_behv_cid
%key	[ derived type... ]
entity (id)	non-unique, sorted, userdefined
%key	[ derived type... ]

RAP(ABAP RESTful Application Programming) 开发中,earlynumbering_create 方法是用于在创建实体时 提前分配业务键(如 ID) 的关键扩展点。当通过 F2 查看 entities 参数的说明时,显示的是该参数的详细结构信息。以下是逐部分解析:


a. 参数基础信息

abap

IMPORTING entities FOR CREATE Z04_DV_Travel_M.
  • 作用:传入待创建的实体实例集合(entities 是一个内表,每个行项代表一个待创建的数据记录)。

  • 类型FOR CREATE Z04_DV_Travel_M 表示这是一个专为创建操作设计的动态结构,其字段与 CDS 实体 Z04_DV_Travel_M 的字段一致。


b. 参数结构详解

(1) 字段列表(Components)
字段名类型Mand. CreateMand. SaveReadonly说明
%cidabp_behv_cid---客户端的临时 ID(Client Identifier),用于在事务内跟踪新建的实体实例。
travelid/dmo/travel_id---业务主键(如旅行 ID),通常需要在 earlynumbering_create 中填充。
agencyid/dmo/agency_id✔️✔️-必填字段(如旅行社 ID),前端或逻辑需提供值。
customerid/dmo/customer_id✔️✔️-必填字段(如客户 ID)。
begindate/dmo/begin_date✔️✔️-必填字段(旅行开始日期)。
...其他业务字段(如费用、状态等)。
createdbyabp_creation_user--✔️自动填充的创建用户,只读。
createdatabp_creation_tstmpl--✔️自动填充的创建时间戳,只读。
%control[控制结构]---标记哪些字段被前端显式传值(用于部分更新场景)。
  • Mand. Create/Save:字段在创建或保存时是否必填(由 CDS 注解或行为定义控制)。

  • Readonly:字段是否仅由框架自动维护(如审计字段)。


(2) 组件组(Component Groups)
  • %data
    包含所有业务字段的派生类型(Derived Type),对应 CDS 实体的完整数据结构。

    abap

  • DATA(lt_entities) = entities->%data.  " 访问业务字段

  • %key
    主键字段的派生类型(如 travelid)。在 earlynumbering_create 中通常需要操作此字段:

    abap

  • LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_entity>).
      <fs_entity>-travelid = generate_travel_id().  " 生成业务键
    ENDLOOP.


(3) 表键(Table Keys)
键名类型说明
primary_key非唯一、标准、空主表键(默认按 CDS 实体主键定义,如 travelid)。
cid非唯一、排序、自定义%cid 排序的辅助键,用于事务内跟踪临时实例。
entity (id)非唯一、排序、自定义按实体 ID 排序的辅助键(通常用于内部处理)。

c. 关键应用场景

(1) 自定义主键生成

earlynumbering_create 中,通常需要为 travelid 分配唯一值(如调用编号范围对象):

abap

METHOD earlynumbering_create.
  LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_entity>)
                   WHERE travelid IS INITIAL.  " 仅处理未提供ID的实例
    <fs_entity>-travelid = cl_numberrange_runtime=>number_get(
      EXPORTING
        nr_range_nr = '01',
        object      = 'ZTRVL'
    )-number.
  ENDLOOP.
ENDMETHOD.
(2) 字段默认值逻辑

abap

METHOD earlynumbering_create.
  LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_entity>).
    IF <fs_entity>-overallstatus IS INITIAL.
      <fs_entity>-overallstatus = 'N';  " 默认状态为New
    ENDIF.
  ENDLOOP.
ENDMETHOD.
(3) 控制字段访问

通过 %control 检查字段是否被显式传值:

abap

METHOD earlynumbering_create.
  LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_entity>).
    IF <fs_entity>-%control-agencyid = if_abap_behv=>mk-on.
      " 前端显式提供了agencyid,可做校验
    ENDIF.
  ENDLOOP.
ENDMETHOD.

d. 注意事项

  1. %cid 的作用
    用于在事务内关联操作(如后续的 late numberingsave 阶段),无需手动处理。

  2. %control 的用途
    在部分更新(PATCH)场景中,标记哪些字段需被更新(未标记的字段会被忽略)。

  3. late numbering 的区别

    • earlynumbering_create:在业务逻辑执行前分配键(如 ID)。

    • late numbering:在保存到数据库前最终处理键(如填充数据库自增字段)。


通过理解 entities 参数的结构,可以更精准地控制 RAP 实体的创建逻辑!

上面提到了一个概念 Drived type(派生类型)

3-3,RAP开发中,Fiori element里面,derived type是什么?

SAP Fiori Elements 开发中(基于 RAP 框架),Derived Type(派生类型) 是 ABAP CDS 或 RAP 模型中一种重要的数据类型复用机制,用于简化数据模型定义并增强一致性。以下是详细说明:


a. 核心概念

  • 派生类型 是基于现有数据类型(如 CDS 实体字段、ABAP 字典类型等)创建的 逻辑扩展,继承原类型的属性(如数据类型、长度、语义),但允许追加额外的元数据(如注解、标签、默认值等)。

  • 类似于面向对象中的“继承”,但仅作用于数据模型层。


b. 常见用途

在 Fiori Elements + RAP 开发中,派生类型通常用于:

  • 标准化字段定义
    例如,多个实体中重复使用的 CustomerID 字段,可通过派生类型统一语义和行为。

  • 简化注解维护
    将通用注解(如 @UI@Consumption)集中定义在派生类型中,避免重复。

  • 增强可读性
    通过有意义的类型名称(如 derived type StatusCode)替代原始类型(如 CHAR(4))。


c. 具体示例

(1) 在 CDS 中定义派生类型

abap

// 定义基础类型
@EndUserText.label: 'Status Code'
define type StatusCode : CHAR(4);

// 在实体中复用派生类型
define entity ZOrder {
    key OrderID    : UUID;
    OrderStatus   : StatusCode;  // 使用派生类型
    // ...其他字段
}
(2) 在 RAP BO 行为定义中

abap

// 行为定义中引用派生类型
define behavior for ZOrder {
  field ( readonly ) OrderStatus as StatusCode;  // 派生类型控制UI行为
  // ...其他行为
}

d. Fiori Elements 中的效果

派生类型的 元数据(如标签、UI注解)会自动传递到 Fiori UI,例如:

  • 表格列标题显示为 Status Code(来自派生类型的 @EndUserText.label)。

  • 若派生类型包含 @UI.hidden: true,则字段不会出现在界面上。


e. 与其他类型的区别

类型派生类型 (Derived Type)自定义类型 (Custom Type)
定义方式基于现有类型扩展完全独立定义
复用性高(继承原类型属性)低(需完整定义)
典型用途标准化字段+注解创建全新数据结构

f. 最佳实践

  • 命名清晰:如 derived type CurrencyCode 而非简单复用 CHAR(3)

  • 集中管理:在公共 CDS 库中定义高频派生类型。

  • 结合注解:通过派生类型统一控制UI行为(如字段必填、隐藏等)。

通过合理使用派生类型,可以显著提升 RAP 模型的 可维护性 和 Fiori Elements 的 一致性

下面来看一些 derived type的实例

3-4,Derived Type(派生类型的实例)

SAP Fiori ElementsRAP(ABAP RESTful Application Programming) 开发中,Derived Type(派生类型) 可以显著提升代码复用性和可维护性。以下是更多实用的 Derived Type 示例,涵盖不同业务场景和优化技巧:


a. 基础数据类型标准化

(1) 通用业务键(Business Key)

abap

// 定义派生类型
@EndUserText.label: 'Business Partner ID'
define type BPID : UUID;  // 或 CHAR(10) 等

// 在多个实体中复用
define entity ZCustomer {
    key CustomerID : BPID;  // 统一使用BPID类型
    // ...
}

define entity ZSupplier {
    key SupplierID : BPID;  // 确保语义一致
    // ...
}

作用:确保所有业务伙伴ID字段类型和语义一致,避免混用 CHAR(10)CHAR(20) 等。


(2) 金额与货币

abap

// 定义金额和货币的派生类型
@Semantics.amount.currencyCode: 'CurrencyCode'
define type AmountValue : DEC(23,2);

@EndUserText.label: 'Currency Code'
define type CurrencyCode : CUKY;  // CUKY = SAP货币类型

// 在订单实体中使用
define entity ZOrder {
    NetAmount    : AmountValue;
    CurrencyCode : CurrencyCode;
    // ...
}

作用

  • 自动关联金额与货币字段(通过 @Semantics 注解)。

  • 确保所有金额字段的小数位数一致(如财务要求 2 位小数)。


b. 状态与枚举值

(3) 标准化状态码

abap

// 派生类型 + 值帮助注解
@EndUserText.label: 'Order Status'
@Consumption.valueHelpDefinition: [{ entity: 'ZOrderStatus', element: 'Status' }]
define type OrderStatus : CHAR(2);

// 在行为定义中控制UI行为
define behavior for ZOrder {
    field ( readonly ) Status as OrderStatus;
}

作用

  • 所有订单状态字段统一为 CHAR(2),并绑定相同的值帮助(Value Help)。

  • 在 Fiori UI 中自动生成下拉列表。


(4) 布尔标志(Yes/No)

abap

// 定义语义化的布尔类型
@EndUserText.label: 'Active Flag'
define type ActiveFlag : abap.boolean;  // ABAP内置布尔类型

// 在客户主数据中使用
define entity ZCustomer {
    IsActive : ActiveFlag;
    // ...
}

UI 效果:在 Fiori 表格中自动显示为 勾选框(Checkbox)。


c. 日期与时间

(5) 带语义的日期

abap

// 定义业务日期类型
@Semantics.systemDate.createdAt: true
define type CreatedDate : TIMESTAMP;

@Semantics.systemDate.lastChangedAt: true
define type ChangedDate : TIMESTAMP;

// 在实体中自动填充
define entity ZOrder {
    CreatedAt : CreatedDate;  // 自动记录创建时间
    ChangedAt : ChangedDate;  // 自动记录修改时间
}

作用

  • 自动捕获创建/修改时间(配合 RAP 框架的 @Semantics 注解)。

  • 避免手动定义 TIMESTAMP 并重复写注解。


d. 复杂业务场景

(6) 地址信息组合

abap

// 定义地址组件派生类型
@EndUserText.label: 'Postal Code'
define type PostalCode : CHAR(10);

@EndUserText.label: 'Country Code'
define type CountryCode : CHAR(2);

// 在客户实体中复用
define entity ZCustomer {
    PostalCode  : PostalCode;
    Country     : CountryCode;
    // ...
}

优化点:若地址规则变更(如邮编长度扩展),只需修改 PostalCode 的派生类型定义。


(7) 单位与数量

abap

// 定义单位派生类型(带值帮助)
@Consumption.valueHelpDefinition: [{ entity: 'ZUnits', element: 'Unit' }]
define type QuantityUnit : UNIT;  // UNIT = SAP单位类型

@Semantics.quantity.unitOfMeasure: 'QuantityUnit'
define type QuantityValue : DEC(13,3);

// 在订单行项目中使用
define entity ZOrderItem {
    Quantity     : QuantityValue;
    QuantityUnit : QuantityUnit;
}

Fiori 效果

  • 数量字段自动关联单位。

  • 单位字段显示值帮助(如 KG, PC 等)。


e. 派生类型的进阶用法

(8) 继承注解

abap

// 定义带UI注解的派生类型
@UI: {
    lineItem:       [ { position: 10, importance: #HIGH } ],
    identification: [ { position: 10 } ]
}
define type ProductName : STRING(100);

// 在商品实体中直接复用
define entity ZProduct {
    Name : ProductName;  // 自动继承UI位置和重要性
    // ...
}

优势:避免在每个实体中重复定义 @UI 注解。


(9) 跨服务复用

RAP 外部服务集成 中,通过派生类型保持与外部 API 的数据类型对齐:

abap

// 与外部系统一致的派生类型
define type API_ProductID : CHAR(18);  // 匹配第三方系统ID格式

// 在本地实体中映射
define entity ZLocalProduct {
    key ExternalID : API_ProductID;
    // ...
}

f.最佳实践总结

  1. 语义化命名:如 EmailAddress 而非 CHAR(100)

  2. 集中管理:在共享 DDL 源(如 ZCommonTypes)中定义高频派生类型。

  3. 结合注解:通过派生类型统一控制 @UI@Semantics、值帮助等。

  4. 版本兼容:修改派生类型时评估对现有实体的影响。

通过合理使用派生类型,可以大幅减少重复代码,并确保 Fiori Elements UI 的一致性!

3-5,earlynumbering_create - 详解

这里就不展开了,想说一点, 

RAP(ABAP RESTful Application Programming) 开发中,earlynumbering_create 方法是 行为定义(Behavior Definition) 中的一个关键扩展点,主要用于在创建实体时 提前分配业务键(如 ID) 或处理其他初始化逻辑。以下是按 F2 显示的代码结构的详细解析:


a. 方法签名说明

abap

METHODS earlynumbering_create FOR NUMBERING
  IMPORTING
    entities TYPE TABLE FOR CREATE z04_dv_travel_m  " 待创建的实体数据
  CHANGING
    mapped   TYPE RESPONSE FOR MAPPED EARLY z04_dv_travel_m   " 成功映射的实体
    failed   TYPE RESPONSE FOR FAILED EARLY z04_dv_travel_m   " 失败的实体
    reported TYPE RESPONSE FOR REPORTED EARLY z04_dv_travel_m " 返回消息
(1) 输入参数 entities
  • 类型TABLE FOR CREATE z04_dv_travel_m

    • 这是一个动态内表,结构与 CDS 实体 z04_dv_travel_m 的字段一致,包含所有待创建的实例数据。

    • 关键字段:

      • %cid:客户端临时 ID(Client Identifier),用于在事务内跟踪新建的实体。

      • 业务键字段(如 travelid):通常需要在此方法中填充(若未由前端提供)。

      • 其他业务字段(如 agencyiddescription 等)。

    • 派生类型:实际类型是 z04_dv_travel_m%t_create(自动生成的派生类型)。

(2) 输出参数 mapped
  • 类型RESPONSE FOR MAPPED EARLY z04_dv_travel_m

    • 用于返回 成功处理的实体映射关系(如生成的业务键与 %cid 的对应关系)。

    • 典型用法:

      abap

    • mapped-z04_dv_travel_m = VALUE #(
        FOR <entity> IN entities WHERE ( travelid IS NOT INITIAL )
        ( %cid = <entity>-%cid
          travelid = <entity>-travelid
        )
      ).

    • 作用:确保后续操作(如 save 阶段)能通过 %cid 找到正确的数据库键。

(3) 输出参数 failed
  • 类型RESPONSE FOR FAILED EARLY z04_dv_travel_m

    • 用于标记 处理失败的实体(如业务键生成失败或校验不通过)。

    • 示例:

      abap

    • failed-z04_dv_travel_m = VALUE #(
        FOR <entity> IN entities WHERE ( agencyid IS INITIAL )  " 必填字段为空
        ( %cid = <entity>-%cid
          %fail-cause = if_abap_behv=>cause-mandatory
        )
      ).

    • 字段

      • %cid:关联到失败的实体。

      • %fail-cause:失败原因(如 if_abap_behv=>cause-mandatory 表示必填字段缺失)。

(4) 输出参数 reported
  • 类型RESPONSE FOR REPORTED EARLY z04_dv_travel_m

    • 用于返回 提示或错误消息(如校验失败的详细原因)。

    • 示例:

      abap

    • reported-z04_dv_travel_m = VALUE #(
        FOR <entity> IN entities WHERE ( agencyid IS INITIAL )
        ( %cid = <entity>-%cid
          %msg = new_message(
            id       = 'ZMSG'
            number   = '001'
            severity = if_abap_behv=>msgerror
            v1       = 'Agency ID is mandatory'
          )
        )
      ).

    • 作用:在前端 Fiori UI 中显示自定义错误消息。


b. 典型代码实现示例

以下是一个完整的 earlynumbering_create 方法实现,包含 业务键生成字段校验

abap

METHOD earlynumbering_create.
  DATA: lv_next_travelid TYPE /dmo/travel_id.

  " 1. 为未提供 travelid 的实体生成业务键
  LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_entity>)
                   WHERE travelid IS INITIAL.
    " 调用编号范围对象生成唯一ID
    lv_next_travelid = cl_numberrange_runtime=>number_get(
      EXPORTING
        nr_range_nr = '01',
        object      = 'ZTRVL'
    )-number.

    " 分配生成的ID
    <fs_entity>-travelid = lv_next_travelid.

    " 记录映射关系(cid -> travelid)
    mapped-z04_dv_travel_m = VALUE #(
      BASE mapped-z04_dv_travel_m
      ( %cid    = <fs_entity>-%cid
        travelid = lv_next_travelid
      )
    ).
  ENDLOOP.

  " 2. 校验必填字段
  LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_check>).
    IF <fs_check>-agencyid IS INITIAL.
      " 标记失败实体
      failed-z04_dv_travel_m = VALUE #(
        BASE failed-z04_dv_travel_m
        ( %cid       = <fs_check>-%cid
          %fail-cause = if_abap_behv=>cause-mandatory
        )
      ).
      " 返回错误消息
      reported-z04_dv_travel_m = VALUE #(
        BASE reported-z04_dv_travel_m
        ( %cid = <fs_check>-%cid
          %msg = new_message(
            id       = 'ZMSG'
            number   = '001'
            severity = if_abap_behv=>msgerror
            v1       = 'Agency ID is mandatory'
          )
        )
      ).
    ENDIF.
  ENDLOOP.
ENDMETHOD.

c. 关键注意事项

  1. %cid 的作用

    • 由前端生成,用于在事务内唯一标识新建的实体实例。

    • 必须在 mapped 中正确关联 %cid 和生成的业务键,否则后续操作(如 save)无法找到对应实例。

  2. mapped 的必要性

    • 如果未填充 mapped,框架无法将前端请求中的 %cid 映射到数据库键,导致后续逻辑错误。

  3. 错误处理优先级

    • 若同时设置 failedreported,前端会优先显示 reported 中的消息。

  4. late numbering 的区别

    • earlynumbering_create:在业务逻辑执行前分配键(适合生成业务主键)。

    • late numbering:在保存到数据库前分配键(适合数据库自增字段)。


d. 常见业务场景

(1) 自动生成订单号

abap

<fs_entity>-orderid = cl_system_uuid=>create_uuid_c32( ).  " 生成UUID
(2) 依赖外部系统的键分配

abap

CALL FUNCTION 'BAPI_PO_CREATE1'
  EXPORTING
    poheader = ls_po_header
  IMPORTING
    po_number = <fs_entity>-poid.  " 从外部系统获取PO号
(3) 字段默认值

abap

IF <fs_entity>-status IS INITIAL.
  <fs_entity>-status = 'NEW'.  " 默认状态
ENDIF.

通过合理使用 earlynumbering_create,可以确保业务键的唯一性和一致性,同时实现灵活的校验逻辑。如果有更多具体场景需求,欢迎进一步探讨!

实战放在下一章里面,文章有点儿长了。

以上就是本篇的全部内容。

更多SAP顾问业务知识请点击下面目录链接或东京老树根的博客主页

https://blog.csdn.net/shi_ly/category_12216766.html

东京老树根-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值