RAP im Schweinsgalopp
Veröffentlicht am 7. Dezember 2023 von | ABAP | News |
Bei der ABAPConf 2023 durfte ich recht kurzfristig einen Vortragsslot zum Thema RAP ausfüllen. Mit dem Vortrag "RAP im Schweinsgalopp" wollte ich zeigen, wie man in einer halben Stunde "mal eben" eine kleine Anwendung mit RAP baut. Nicht ganz sauber, aber dafür mit extrem hoher Entwicklungseffizienz. Das ist sicherlich eine der Stärken vom RAP Programmiermodell.
Den Quellcode der Anwendung habe ich im Folgenden eingefügt. Der passt 1:1 zu dem, was ich live gezeigt habe. Nachträgliche Optimierungen und Verschönerungen habe ich mir verkniffen.
CDS ZAC2_USERS
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'users'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
@UI: { headerInfo: { typeName: 'User',
typeNamePlural: 'Users',
title:{ type: #STANDARD,
value: 'Email' },
description.value: 'UserId' } }
@Search.searchable: true
define root view entity zac1_users
as select from zbc_users
association [0..*] to zac1_tasks as _TasksToDo on $projection.UserId = _TasksToDo.Assignee
{ @UI.facet: [ { id: 'User',
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
label: 'User',
position: 10 } ,
{ id: 'TasksToDo',
purpose: #STANDARD,
type: #LINEITEM_REFERENCE,
label: 'Tasks to do',
targetElement: '_TasksToDo',
position: 10 } ]
@UI.lineItem: [{ position: 10 }]
@UI.identification:[ { position: 10 } ]
key user_id as UserId,
@Search:{ defaultSearchElement: true,
fuzzinessThreshold: 0.7 }
@UI.lineItem: [{ position: 20 }]
@UI.identification:[ { position: 10 } ]
firstname as Firstname,
@Search:{ defaultSearchElement: true,
fuzzinessThreshold: 0.7 }
@UI.lineItem: [{ position: 30 }]
@UI.identification:[ { position: 20 } ]
lastname as Lastname,
@Search:{ defaultSearchElement: true,
fuzzinessThreshold: 0.7 }
@UI.lineItem: [{ position: 40 }]
@Semantics.eMail.address: true
@UI.identification:[ { position: 30 } ]
email as Email,
@UI.identification:[ { position: 40 } ]
gender as Gender,
@UI.identification:[ { position: 50 } ]
date_of_birth as DateOfBirth,
@UI.identification:[ { position: 60 } ]
@Semantics.systemDateTime.lastChangedAt: true
changed_at as ChangedAt,
@UI.identification:[ { position: 70 } ]
@Semantics.user.lastChangedBy: true
changed_by as ChangedBy,
@UI.identification:[ { position: 80 } ]
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt,
@UI.identification:[ { position: 100 } ]
@Semantics.user.createdBy: true
created_by as CreatedBy,
_TasksToDo
}
Der CDS-View ZAC1_TASKS
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'tasks'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define view entity zac1_tasks as select from zbc_tasks
{
@UI.lineItem: [{ position: 10 }]
key task_key as TaskKey,
@UI.lineItem: [{ position: 10 }]
summary as Summary,
@UI.lineItem: [{ position: 10 }]
status as Status,
project as Project,
description as Description,
assignee as Assignee,
type as Type,
author as Author,
changed_at as ChangedAt,
created_at as CreatedAt,
@UI.lineItem: [{ position: 10 }]
due_date as DueDate,
solution as Solution,
priority as Priority,
product as Product,
estimated_effort as EstimatedEffort
}
Behaviour Definition zac1_users
managed implementation in class zbp_ac1_users unique;
strict;
define behavior for zac1_users //alias <alias_name>
persistent table ZBC_USERS
lock master
authorization master ( instance )
//etag master <field_name>
{
create;
update;
delete;
field ( readonly : update ) UserId;
field ( readonly ) ChangedAt,
ChangedBy,
CreatedAt,
CreatedBy;
mapping for zbc_users corresponding{
UserId = user_id;
DateOfBirth = date_of_birth;
ChangedBy = changed_by;
ChangedAt = changed_at;
CreatedBy = created_by;
CreatedAt = created_at;
}
}