Вы находитесь на странице: 1из 62

Моделирование транзакционных приложений в CDS*

Ренцо Колле

Ральф Дентцер

Ян Храстник
Прочитать позже
432

Core Data Services for ABAP

Renzo Colle, Ralf Dentzer, Jan Hrastnik

Погрузитесь в моделирование данных с помощью этого всеобъемлющего руководства по


основным службам данных ABAP (CDS). Получите навыки, необходимые для создания
моделей данных с подробной информацией о синтаксисе CDS, его ключевых компонентах
и возможностях. Пройдите пошаговое руководство по моделированию данных
приложений в SAP S/4HANA и разработке аналитических и транзакционных моделей
приложений.

*Оригинал (англ.): Core Data Services for ABAP. Ренцо Колле, Ральф Дентцер, Ян


Храстник. Издательство SAP PRESS. Глава 9. 2019, с. 325–385.

Корректура: Олег Точенюк.

Моделирование транзакционных приложений в CDS // SAP Professional Journal


Россия, январь–февраль, №1 (78), стр. 110–156. @ 2020, Ренцо Колле, Ральф Дентцер, Ян
Храстник.

Эта глава посвящена использованию моделей Core Data Services (CDS) для
транзакционных приложений. Это приложения, которые не только считывают данные,
но и изменяют их.

Модели CDS не только используются для моделирования и чтения данных, но и


формируют базу для моделирования транзакционных аспектов, определяя, таким образом,
дополнительные объекты и поведение приложений, которые изменяют данные. В целом,
данные можно создавать, изменять или удалять посредством прямого ввода
пользователем через пользовательский интерфейс (UI) или машинные интерфейсы,
например, через средства связи между приложениями (application-to-application, A2A).

Изменения, явно запрошенные пользователем одного из таких интерфейсов, могут иметь


побочные эффекты в виде дополнительных последующих изменений.

В данной главе показано, как определить транзакционное приложение. Соответствующие


особенности, которые необходимо учесть, описаны в Разделе 9.1. В Разделе 9.2 также
показано, как работает транзакционная инфраструктура в SAP S/4HANA, как определить
модели транзакционных объектов и реализовать их бизнес-логику (см. статью
«Транзакционные приложения и инфраструктура в SAP S/4HANA» в этом номере SAP
Professional Journal Россия, — №1, 2020). В эту бизнес-логику входят блокировки,
полномочия и проверки данных, а также динамический контроль свойств, действия и
вычисляемые поля (Раздел 9.3. — см. статью «Модели транзакционных объектов
в SAP S/4HANA» в этом номере журнала).

Далее мы будем использовать эти приложения в различных сценариях с применением


моделей транзакционных сервисов (Раздел 9.4. — см. статью «Модели транзакционных
сервисов в SAP S/4HANA» в этом номере журнала).

Транзакционные приложения и
инфраструктура в SAP S/4HANA*
Показано, как определить транзакционное приложение. Описаны соответствующие
особенности, которые необходимо учесть, описаны. Показано, как работает
транзакционная инфраструктура в SAP S/4HANA, как определить модели
транзакционных объектов и реализовать их бизнес-логику.
*Оригинал (англ.): Core Data Services for ABAP. Ренцо Колле, Ральф Дентцер, Ян
Храстник. Издательство SAP PRESS. Разделы 9.1, 9.2. 2019, с. 325–330.

Корректура: Олег Точенюк.

Транзакционные приложения и инфраструктура в SAP S/4HANA // SAP Professional


Journal Россия, январь–февраль, №1 (78), стр. 111–156. @ 2020, Ренцо Колле, Ральф
Дентцер, Ян Храстник.

Транзакционные приложения (раздел 9.1)


Из предыдущих глав вы узнали, как используются ракурсы CDS при моделировании
доступа для чтения. Вопрос в том, можно ли, а если да, то как, использовать эту
семантически обогащённую модель для создания сценариев доступа с правом записи.
Особенно при работе с этими моделями через интерфейсы на базе архитектуры REST
(передача состояния представления) в сети Интернет становится очевидным, что операции
чтения и записи в идеальном сценарии должны выполняться на базе одной модели. В этом
разделе представлены основные сведения и специфичные аспекты транзакционных
приложений.

Бизнес-объекты
Бизнес-объекты логически объединяют несколько сущностей (entity). В качестве примера
бизнес-объекта мы уже рассматривали заказ клиента, который состоит, помимо прочего,
из данных заголовка, данных позиций и графика поставок. Между ними установлены
композиционные взаимосвязи, поэтому экзистенциально они не зависят от
соответствующей родительской сущности. Несмотря на то, что для чтения бизнес-
объекты играют второстепенную роль, они формируют контекст, который очень важен
при записи. Обычно несколько сущностей одного бизнес-объекта обрабатываются и
записываются вместе. Другие упоминаемые или привязанные сущности часто только
считываются или имеют собственную реализацию для доступа с правом записи.

Полномочия и блокировка
Помимо выделенных средств управления полномочиями для записи данных также
требуются эксклюзивные блокировки, которые обеспечивают транзакционную
непротиворечивость данных. В большинстве случаев поведение средств проверки
полномочий и блокировок реализуется на уровне бизнес-объекта в целом, а не на уровне
отдельной подсущности бизнес-объекта. Лишь в самых редких случаях бизнес-объекты
поддерживают блокировку на уровне подсущности.

Бизнес-логика
Обычно при записи данные, введённые пользователем или переданные через машинный
интерфейс, сохраняются не сразу. Сначала выполняется проверка введённых данных.
Другие данные выбираются или вычисляются, что зависит от изменений в данных или от
бизнес-конфигурации и т. д. Все эти правила и условия называются общим термином
бизнес-логика. Изменяются не только данные бизнес-объекта, к которому выполняется
обращение. Во многих случаях также инициируются и обрабатываются другие бизнес-
объекты и даже целые бизнес-процессы или последующие процессы.

Действия
Для изменения данных и бизнес-объектов можно использовать элементарные операции:
создание, изменение или удаление (вместе с чтением они называются операциями
управления данными (CRUD)). Однако бизнес-логика часто выводится в более
комплексных операциях, которые содержат несколько изменений, обеспечивая
непротиворечивость обработки операций. Операции такого типа вызываются в
следующих действиях. Действия помогают снять с конечного пользователя или
потребителя ответственность за бизнес-логику или непротиворечивость множественных
изменений. Они обеспечивают повышенное удобство при считывании повторяющихся
изменений. Если требуется, действия также могут явно контролировать расширенные
полномочия. Рассмотрим это в Раздел 9.3.6 на примере.

Трудности при работе с CDS и SAP


S/4HANA
В контексте CDS ABAP и предлагаемых функциях произошли дополнительные
изменения. Во-первых, в настоящее время CDS ABAP предлагает только определения
данных, например, ракурсы CDS и таблицы CDS для моделирования данных. По
определению эти сущности поддерживают только доступ для чтения. Таким образом, с
чисто технической точки зрения соответствующие операции SQL для изменения данных
должны выполняться непосредственно через таблицы базы данных или внутри этих
таблиц. Инфраструктура может автоматически делегировать доступ с правом записи
моделям CDS только в том случае, если модели CDS представляют собой простую
проекцию таких таблиц базы данных. При использовании более комплексной логики SQL
в моделях или ракурсе CDS создание, запись или поиск данных и базы данных для записи
больше не являются простой задачей, а иногда вообще невозможны. По сути, в модели
виртуальных данных (VDM) SAP S/4HANA, которая выводится как семантически
обогащённая модель, структура данных коренным образом упрощена во многих аспектах
в отношении существующих таблиц базы данных и модели хранения, поэтому
объединения, соединения и другие функции также применяются для определения моделей
CDS VDM.

Транзакционная инфраструктура
в SAP S/4HANA (раздел 9.2)
Сервер приложений или база данных
На этом этапе может возникнуть вопрос, на каком уровне должна быть реализована и
интегрирована бизнес-логика. В среде ABAP ответ достаточно однозначен: бизнес-логика
(в том понимании, в котором мы говорим о ней здесь) выполняется на сервере
приложений и реализуется в ABAP. Это обусловлено масштабируемостью серверов
приложений и подробной бизнес-логикой SAP S/4HANA, которая, разумеется, должна
быть понятной и применяемой. Такой подход не противоречит цели перевода логики с
обработкой большого объёма данных в базу данных. В оптимальном варианте базу
данных SAP HANA следует использовать, разумеется, для всех операций чтения с
мэппингом трансформаций, насколько возможно, посредством SQL при чтении данных.
Этот подход разумным образом также можно применять в транзакционной логике.

Эффективное использование базы данных SAP HANA

Рассмотрим пример. При обработке заказов клиента перед подтверждением заказа


необходимо проверить кредитный лимит клиента по текущему заказу и открытым
позициям. Вычисление значений для открытых позиций выполняется на основе
агрегации (итоговая сумма по открытым позициям) в базе данных SAP HANA. На
сервер приложений переносится только результат вычисления. На сервере
приложений при выполнении соответствующей проверки данное значение добавляется
к значению текущего заказа и сравнивается с кредитным лимитом клиента. Если
лимит превышен, генерируется сообщение. При необходимости в документе
устанавливается соответствующий статус.

CDS и BOPF
Платформа ABAP позволяет использовать модели CDS в качестве базы для
моделирования транзакционных приложений. В этом контексте необходимо учитывать
все требования, определённые в предыдущем разделе для транзакционных приложений
или соответствующей инфраструктуры. Для этого в транзакционную среду выполнения
интегрирована структура обработки бизнес-объектов (Business Object Processing
Framework; BOPF), которая является частью платформы ABAP и учитывает все эти
аспекты. На момент написания этой книги (весна 2019 года) это единственный способ
интеграции транзакционной логики в CDS, который поддерживается платформой ABAP
для внедрения приложения на базе CDS. Интеграция других транзакционных структур
или реализаций за пределами BOPF в настоящее время не поддерживается, но
планируется в будущих версиях (а именно, модель программирования ABAP RESTful).

При создании сервисов OData (Раздел 9.4.2) транзакционную логику можно реализовать
непосредственно в процессе внедрения сервиса, а с помощью модели CDS определить
доступ для чтения. Мы не будем останавливаться на этой теме, а рассмотрим подробнее
сценарий, создаваемый с нуля.

В рамках описанного подхода бизнес-объект BOPF создаётся на основе моделей CDS. Для
полноты картины здесь следует заметить, что модели BOPF, созданные таким способом, в
настоящее время не предоставляют полный диапазон функций и возможностей BOPF.
Однако они постоянно расширяются.

Дополнительные ресурсы

Для получения дополнительной информации о BOPF см. статью BOPF: разработка


бизнес-объектов (BOPF: Business Object Development) Джеймса Вуда (James Wood) и
Джозефа Руперта (Joseph Rupert), издательство SAP PRESS, sap-press.com/ 4300, а
также руководство «Начало работы со структурой обработки бизнес-объектов»
(Getting Started with Business Object Processing Framework) в сообществе SAP
Developers Network (SDN) по адресу http://s-prs.co/ v482207 и соответствующую
документацию к платформе ABAP по адресу http://s-prs.co/v482208.

В примерах мы постоянно используем редактор BOPF в Eclipse, поскольку недоступные


для BOPF на базе CDS функции здесь даже не предлагаются. Большая часть
транзакционных расширений пока не интегрирована в синтаксис CDS, но управляется с
помощью аннотаций. В этой главе указаны все аннотации, влияющие на модель BOPF, с
описанием результатов такого влияния.

Главное правило заключается в том, что моделирование данных или объектов для бизнес-
объекта и его свойств выполняется посредством CDS. Изменить эту информацию в
модели BOPF, созданной на их основе, невозможно. Моделирование поведения, т. е.
определение бизнес-логики (средства выбора и вычисления данных, а также проверки
непротиворечивости и действия), выполняется в модели BOPF.

Среда выполнения BOPF, которая работает на базе модели BOPF, обеспечивает полную
поддержку операций управления данными (CRUD) и чётко определённых интерфейсов
для интеграции проверок полномочий, блокировок и бизнес-логики с возможностью
последующей реализации.

Первичный ключ и модель данных BOPF

Для операций изменения вызывается инфраструктура BOPF для релевантного бизнес-


объекта BOPF. Всем пользователям, знакомым с BOPF, известно, что эта структура
создана на основе технического ключа типа RAW16 (глобальный уникальный
идентификатор [GUID]) в среде выполнения. Однако базовая модель CDS может не
иметь такого ключа. Обычно она содержит семантические ключи. По этой причине
во время выполнения создаётся временный технический ключ, для которого
выполняется мэппинг по фактическому семантическому ключу связанных сущностей.
На данный момент платформа ABAP не предоставляет общий интерфейс доступа к
определённому таким образом бизнес-объекту. Поэтому пользователь интерфейсов
BOPF (уровня сервисов BOPF) также должен получить доступ и выполнить
преобразование ключа из семантического ключа сущности и временного технического
ключа BOPF.

SADL и OData
Мы будем рассматривать работу с приложениями через веб-стандарты REST и OData,
поскольку платформа ABAP уже предоставляет реальную сквозную поддержку этих
стандартов. Например, в данном случае инфраструктура обрабатывает не только
указанные выше ключи, но и обеспечивает маршрутизацию обращений с правом чтения и
записи. Все нетранзакционные запросы на чтение и аналитические запросы делегируются
напрямую базе данных SAP HANA через интерфейс Open SQL. Транзакционные запросы
на чтение и запись данных передаются в транзакционную среду выполнения (BOPF) и
транзакционный буфер сервера приложений. Таким образом, сочетается оптимальное
использование базы данных SAP HANA с обработкой всех постоянных данных при всех
преимуществах транзакционной среды выполнения на сервере приложений ABAP и
возможности применения существующей бизнес-логики.
Для перевода запросов GET OData в запросы SQL используется инфраструктура Service
Adaptation Definition Language (SADL) на платформе ABAP. Инфраструктура SADL
разработана для чтения и обработки данных на базе моделей.

Дополнительные ресурсы

Для получения дополнительной информации о SADL посетите портал SAP Help Portal
по адресу https:// help.sap.com и введите в строке поиска Consuming Business Entities
with SADL (http://s-prs.co/v482202).

Схематичное представление инфраструктуры ABAP для транзакционных приложений с


наиболее важными динамическими компонентами показано на Рис. 9.1.
Рис. 9.1. Инфраструктура ABAP для транзакционных приложений

Модели транзакционных объектов в SAP S/4HANA*

Описаны блокировки, полномочия и проверки данных, а также динамический контроль


свойств, действия и вычисляемые поля, входящие в бизнес-логику моделей
транзакционных объектов.
*Оригинал (англ.): Core Data Services for ABAP. Ренцо Колле, Ральф Дентцер, Ян
Храстник. Издательство SAP PRESS. Раздел 9.3. 2019, с. 331–370.

Корректура: Олег Точенюк.

Модели транзакционных объектов в SAP S/4HANA // SAP Professional Journal


Россия, январь–февраль, №1 (78), стр. 115–156. @ 2020, Ренцо Колле, Ральф Дентцер, Ян
Храстник.

Этот раздел посвящён моделям транзакционных объектов. Вы узнаете, как определить и


реализовать бизнес-объект и бизнес-логику для этого объекта. Сначала определим модель
данных и введём структуру объектов. Далее мы расширим определенный таким образом
бизнес-объект для поддержки транзакционных изменений. Наконец, мы завершим работу
над приложением, реализовав расширенные функции: эксклюзивные блокировки,
контроль полномочий, бизнес-логику и действия. Постепенно на основе этого примера
будет создано полное приложение.

Определение моделей объектов (раздел


9.3.1)
Композиционная структура
Как было сказано выше, бизнес-объекты определяются как древовидные или
композиционные структуры сущностей. Для описания бизнес-объектов в сети сущностей
и привязок CDS помечается корень композиционного дерева, а релевантные привязки
(association) определяются как композиции. Чтобы пометить корень, используйте
следующую аннотацию для соответствующего ракурса CDS:

@AbapCatalog.sqlViewName: 'ZISALESORDERTP'

@AbapCatalog.compiler.compareFilter: true

@AccessControl.authorizationCheck: #CHECK

@EndUserText.label: 'Sales Order'

@ObjectModel.modelCategory: #BUSINESS_OBJECT

@ObjectModel.compositionRoot: true

define view ZI_SalesOrderTP

as selectfrom ZI_SalesOrder

association [0..*] to ZI_SalesOrderItemTP as _SalesOrderItem

on $projection.SalesOrder = _SalesOrderItem.SalesOrder

{
key SalesOrder,

SalesOrderType,

SalesOrganization,

DistributionChannel,

OrganizationDivision,

DeliveryStatus,

DeletionIndicator,

CreatedByUser,

CreationDateTime,

LastChangedByUser,

LastChangeDateTime,

@ObjectModel.association.type: [#TO_COMPOSITION_CHILD]

_SalesOrderItem

Листинг. 9.1. Ракурс CDS для заказа клиента

@ObjectModel.compositionRoot: true

Композиционные привязки к подсущностям помечаются следующей аннотацией:

@ObjectModel.association.type: #TO_COMPOSITION_CHILD

Если вы знакомы с BOPF, вы, вероятно, знаете, что здесь также можно выполнить
обратные привязки композиции к родительскому узлу и корню. Поскольку такие привязки
целесообразно настроить для навигации, их следует пометить следующей аннотацией:

@ObjectModel.association.type: #TO_COMPOSITION_PARENT

@ObjectModel.association.type: #TO_COMPOSITION_ROOT

Чтобы явно пометить бизнес-объект как таковой, используйте следующую аннотацию для
корневой сущности, представляющей бизнес-объект:

@ObjectModel.modelCategory: #BUSINESS_OBJECT

Эта аннотация не является релевантной во время выполнения и имеет значение только для
семантической категоризации в контексте VDM.
Уровень транзакционных ракурсов

Для транзакционного приложения на базе ракурсов интерфейса мы рекомендуем


определить выделенные ракурсы CDS. С одной стороны, это делает модель и её
использование более понятным. С другой стороны, модель остаётся открытой для
дополнительной разработки и реализации новых функций. Рекомендуем добавить
суффикс TP к именам соответствующих ракурсов CDS в рамках соглашения о
присвоении имён для подобных ракурсов CDS.

Бизнес-объект и корневая сущность


В разговорной речи обычно не проводится различия между бизнес-объектом (в
рассматриваемом примере это заказ клиента, и его корневой сущностью (заголовок заказа
клиента). В обоих случаях имя бизнес-объекта используется синонимично. В следующем
примере мы будем использовать корректные определения, чтобы избежать путаницы
понятий и чётко понимать, где речь идёт о бизнес-объекте, а где — о корневой сущности.

Пример: бизнес-объект

Итак, определим модель бизнес-объекта для заказа клиента. Поскольку в основе ракурсов
CDS лежат уже определённые базовые ракурсы интерфейса, известные аннотации к
соответствующим полям (их семантике) доступны автоматически через логику
распространения аннотаций. Кроме того, для имён полей уже определены подходящие
псевдонимы.

Определите заголовок заказа клиента, как показано в Листинге 9.1. Здесь уже имеется
дочерняя привязка к позиции заказа клиента, определённой в Листинге 9.2. Новые
аннотации выделяются соответствующим образом.

@AbapCatalog.sqlViewName: 'ZISALESORDERITTP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales OrderItem'
define view ZI_SalesOrderItemTP
as selectfrom ZI_SalesOrderItem
association [1..1] to ZI_SalesOrderTP as _SalesOrder
on $projection.SalesOrder = _SalesOrder.SalesOrder
association [0..*] to ZI_SalesOrderScheduleLineTP
as _SalesOrderScheduleLine
on $projection.SalesOrder =
_SalesOrderScheduleLine.SalesOrder
and $projection.SalesOrderItem =
_SalesOrderScheduleLine.SalesOrderItem
{
key SalesOrder,
key SalesOrderItem,
Product,
OrderQuantity,
OrderQuantityUnit,
NetAmount,
TransactionCurrency,
CreatedByUser,
CreationDateTime,
LastChangedByUser,
LastChangeDateTime,
@ObjectModel.association.type: [#TO_COMPOSITION_PARENT,
#TO_COMPOSITION_ROOT]
_SalesOrder,
@ObjectModel.association.type: [#TO_COMPOSITION_CHILD]
_SalesOrderScheduleLine
}

Листинг. 9.2. Ракурс CDS для позиции заказа клиента

В Листинге 9.2 представлена позиция заказа клиента с привязками к заголовку заказа


клиента и графику поставок, определённому в Листинге 9.3.

@AbapCatalog.sqlViewName: 'ZISALESORDERSLTP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales OrderScheduleLine'
define view ZI_SalesOrderScheduleLineTP
as selectfrom ZI_SalesOrderScheduleLine
association [1..1] to ZI_SalesOrderTP as _SalesOrder
on $projection.SalesOrder = _SalesOrder.SalesOrder
association [1..1] to ZI_SalesOrderItemTP as _SalesOrderItem
on $projection.SalesOrder = _SalesOrderItem.SalesOrder
and $projection.SalesOrderItem =
_SalesOrderItem.SalesOrderItem
{
key SalesOrder,
key SalesOrderItem,
key SalesOrderScheduleLine,
DeliveryDate,
OrderQuantity,
OrderQuantityUnit,
CreatedByUser,
CreationDateTime,
LastChangedByUser,
LastChangeDateTime,
@ObjectModel.association.type: [#TO_COMPOSITION_ROOT]
_SalesOrder,
@ObjectModel.association.type: [#TO_COMPOSITION_PARENT]
_SalesOrderItem
}

Листинг. 9.3. Ракурс CDS для графика поставки по заказу клиента

В Листинге 9.3 показан график поставок по заказу клиента с привязками к заголовку


заказа клиента в качестве корневой сущности и к позициям заказа клиента в качестве
родительской сущности.

Активация ракурса CDS


Чтобы избежать проблем при активации ракурсов CDS, рекомендуется сначала
определить и активировать ракурсы CDS без привязок, а затем добавить привязки
вторым шагом.

Определение моделей транзакционных


объектов (раздел 9.3.2)
Модель транзакционных объектов
Теперь рассмотрим, как можно определить модель транзакционных объектов для модели
данных бизнес-объекта. Поскольку с точки зрения сущностей и привязок модель уже
полностью определена, достаточно пометить корневую сущность, чтобы разрешить
использование транзакционной среды выполнения для бизнес-объекта. Для этого
применяется аннотация @ObjectModel.transactionalProcessingEnabled:true в корневой
сущности бизнес-объекта.

Однако, как было сказано выше, при работе с ракурсами CDS встречаются объекты базы
данных, которые изначально разрешают только доступ к данным в режиме чтения.
Теоретически в простых случаях можно установить доступ с записью в корректные
таблицы согласно определению ракурса с учётом аспектов создания ракурса и присвоения
ему псевдонима. Однако в инфраструктуре всегда должно присутствовать явное указание
таблицы базы данных, в которую выполняется запись. Эту таблицу необходимо указать
для каждой сущности с помощью аннотации @ObjectModel.writeActivePersistence:’<имя
таблицы базы данных>’. Указанная таблица базы данных должна иметь такую же
структуру, как и ракурс CDS, или быть совместимой с ним. Также требуются
соответствующие имена полей (в верхнем регистре согласно ABAP).

Пример: добавление аннотаций

В нашем примере модель расширяется новыми аннотациями с соответствующим


выделением для заголовка заказа клиента в Листинге 9.4.

@AbapCatalog.sqlViewName: 'ZISALESORDERTP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Order'
@ObjectModel.modelCategory: #BUSINESS_OBJECT
@ObjectModel.compositionRoot: true
@ObjectModel.transactionalProcessingEnabled: true
@ObjectModel.writeActivePersistence: 'ZSALESORDER'
define view ZI_SalesOrderTP

Листинг. 9.4. Ракурс CDS для заказа клиента с транзакционными аннотациями

В Листинге 9.5 представлены аннотации для позиции заказа клиента.

@AbapCatalog.sqlViewName: 'ZISALESORDERITTP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales OrderItem'
@ObjectModel.writeActivePersistence: 'ZSALESORDERITEM'
define view ZI_SalesOrderItemTP

Листинг. 9.5. Ракурс CDS для позиции заказа клиента с транзакционными аннотациями

В Листинге 9.6 представлены соответствующие аннотации для графика поставки по


заказу клиента.

@AbapCatalog.sqlViewName: 'ZISALESORDERSLTP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales OrderScheduleLine'
@ObjectModel.writeActivePersistence: 'ZSALESORDERSLINE'
define view ZI_SalesOrderScheduleLineTP

Листинг. 9.6. Ракурс CDS для графика поставки по заказу клиента с транзакционными
аннотациями

Модель BOPF
Если вы добавили эти аннотации, при активации корневого ракурса CDS автоматически
создаётся бизнес-объект BOPF. В результате активируется транзакционная среда
выполнения. Если установить курсор на пиктограмме слева от аннотации, появится
информация о созданном объекте (см. Рис. 9.2). Для прямого перехода к бизнес-объекту
BOPF используйте отображаемую здесь ссылку «Бизнес-объект» (Business Object).

Рис. 9.2. Бизнес-объект BOPF, сгенерированный из CDS


Имя бизнес-объекта BOPF совпадает с именем корневого ракурса CDS. Имена узлов в
бизнес-объекте BOPF соответствуют именам ракурсов CDS для отдельных подсущностей.
Композиционным привязкам к дочерним узлам также присваивается то же самое имя.
На Рис. 9.3 показаны соответствующие элементы в ракурсе Eclipse Обзор (Outline) для
BOPF. В общем смысле мы будем называть сущностями ракурс CDS и связанный узел
BOPF.

Рис. 9.3. Бизнес-объект BOPF: обзор модели BOPF

В BOPF привязки к родительским и корневым узлам всегда доступны в каждом


некорневом узле. Этим привязкам присваивается стандартное имя, которое может не
совпадать с именем соответствующей привязки в модели CDS. Другие привязки в
настоящее время недоступны по умолчанию в бизнес-объекте BOPF, при необходимости
их придётся добавить вручную. Однако это применимо только к привязкам в том же
бизнес-объекте. Обязательно используйте одинаковые имена для обеспечения
автоматической работы сквозной среды выполнения. Это относится, например, к
специализациям в композиционных взаимосвязях.

Привязки к другим сущностям или бизнес-объектам в BOPF не требуются и не могут быть


созданы. Альтернативные ключи DB_KEY, PARENT_KEY и ROOT_KEY можно
игнорировать. Они требуются только технически для инфраструктуры, поскольку в
данном примере выбрана модель с семантическим ключом.
Действие LOCK_... рассматривается в Раздел 9.3.4. Более подробно действия с
именем ACTION_AND_FIELD_CONTROL описаны в Раздел 9.3.7.

На Рис. 9.4 обзорно представлен бизнес-объект BOPF. В отображаемой ссылке на ракурс


CDS напрямую указан его источник. Отсюда можно перейти к структуре узлов в
древовидном ракурсе или просмотреть подробные данные узла.
Рис. 9.4. Обзор бизнес-объектов BOPF

На Рис. 9.5 показан пример корневого узла. Здесь очень хорошо видно, что автоматически
создаётся не только сам бизнес-объект BOPF, но и различные объекты ABAP-словаря
(ABAP DDIC), а также классы ABAP.

Рис. 9.5. Бизнес-объект BOPF: корневой узел

Удаление модели BOPF


В случае удаления модели CDS модель BOPF и все дополнительно созданные
артефакты разработки сохраняются. В данном случае необходимо удалить модель
BOPF и все прочие релевантные объекты разработки вручную для очистки всех
артефактов. Поскольку все созданные объекты разработки относятся к тому же
пакету, что и ракурс CDS, найти их достаточно просто.

Тестовая среда BOPF


Созданный таким образом бизнес-объект BOPF теперь позволяет получать доступ через
транзакционный интерфейс — уровень сервисов BOPF. Данные можно считывать
посредством уровня сервисов BOPF. Например, как показано на Рис. 9.6, это можно
выполнить с помощью тестовой среды BOPF.

Рис. 9.6. Тестовая среда BOPF с данными

Тестовую среду можно запустить напрямую с помощью ABAP Development Tools (ADT) в
Eclipse для бизнес-объекта BOPF в древовидной структуре. Для этого
выберите «Выполнить • Выполнить как • Тестовая среда» (Run • Run As • Test
Environment). С помощью этого инструмента также можно осуществлять навигацию по
всей модели. Указанные в Раздел 9.2 технические ключи не входят в модель CDS
(поскольку эта модель работает с семантическими ключами).
Загрузка экземпляров узлов в тестовую среду

В настоящее время определить запрос в модели BOPF невозможно, поэтому данные


необходимо всегда загружать в тестовую среду с явным указанием ключа. В модели
на базе GUID для этого применяются собственные ключи BOPF (DB_ KEY), а в нашей
модели с семантическими ключами — автоматически создаваемые альтернативные
ключи. Их имена совпадают с именами собственных ключей BOPF, но структура
соответствует семантическому ключу вашей модели CDS.

Необходимо заметить, что в тестовой среде недоступны операции создания, изменения и


удаления записей данных. Соответствующие кнопки деактивированы/выделены серым
цветом, поскольку эти операции ещё не определены. В BOPF по умолчанию
предполагается, что, следовательно, они запрещены. В следующем разделе
рассматривается процедура добавления определения и активации разрешённых операций.

Использование существующих хранилищ и таблиц базы данных

В большинстве случаев приложение реализуется не с нуля, а с использованием уже


существующего хранилища. С помощью некоторых манипуляций можно выполнить
простое переименование полей в семантической модели CDS. Вместо исходной
таблицы, определённой в транзакции SE11, в качестве хранилища записываемых
данных в модели CDS можно указать определённый вручную ракурс SQL с функцией
записи. В этом ракурсе SQL имена полей можно изменить так же, как и для ракурса
CDS.

Более сложный мэппинг моделей хранения, которые выводятся посредством


транзакционного ракурса CDS, в настоящее время недоступен, поскольку инфраструктура
ABAP не поддерживает собственную реализацию логики такого мэппинга. В данном
случае инфраструктура ABAP не позволяет реализовать транзакционное приложение.

Определение статических свойств (раздел


9.3.3)
Активация изменений
Поскольку пользователь обычно может изменить не все данные бизнес-объекта напрямую
(например, внутренний номер документа или технические административные данные),
операции изменения изначально в модели транзакционных объектов недоступны. Эти
операции необходимо явно активировать. Для управления такой активацией применяются
аннотации. Аннотации на уровне сущности определяют общие возможности создания,
изменения или удаления экземпляров сущности. Аннотации на уровне поля подробно
определяют возможности просмотра и изменения отдельных полей. Аннотации
определяют возможности изменения поля в целом, а также указывают, является ли поле
обязательным для заполнения.

Статические свойства определяются с помощью следующих аннотаций.

 @ObjectModel.createEnabled:true
Эта аннотация используется для создания экземпляров сущности.

 @ObjectModel.updateEnabled:true

Эта аннотация используется для изменения экземпляров сущности.

 @ObjectModel.deleteEnabled:true

Эта аннотация используется для удаления экземпляров сущности.

 @ObjectModel.readOnly:true

Эта аннотация используется для пометки полей как доступных только для чтения.
При создании и изменении все поля можно сначала записать. Этой аннотацией
помечаются поля, вычисляемые или определяемые внутренним образом, без
возможности изменения пользователем напрямую.

 @ObjectModel.mandatory:true

Эта аннотация используется для указания обязательных полей для обеспечения


непротиворечивости экземпляра бизнес-объекта с точки зрения бизнес-данных.

Пример: транзакционные аннотации


Эта последняя аннотация используется только в информационных целях. Однако она
может применяться инфраструктурой при проверке данных во время сохранения и на
экране ввода для пользователей при идентификации обязательных полей.

Перейдём к заполнению модели соответствующими транзакционными аннотациями. В


заголовке заказа клиента вы определяете возможность создания и изменения (но не
удаления напрямую) заказа клиента, как показано в Листинге 9.7. Как было сказано
выше, последнее ограничение также применяется в случае отсутствия соответствующей
аннотации. Однако добавление аннотации делает модель более удобной для чтения.

@AbapCatalog.sqlViewName: 'ZISALESORDERTP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Order'
@ObjectModel.modelCategory: #BUSINESS_OBJECT
@ObjectModel.compositionRoot:true
@ObjectModel.transactionalProcessingEnabled:true
@ObjectModel.writeActivePersistence: 'ZSALESORDER'
@ObjectModel.createEnabled: true
@ObjectModel.updateEnabled: true
@ObjectModel.deleteEnabled: false
define view ZI_SalesOrderTP
as selectfrom ZI_SalesOrder
association [0..*] to ZI_SalesOrderItemTP as _SalesOrderItem
on $projection.SalesOrder = _SalesOrderItem.SalesOrder
{
@ObjectModel.readOnly: true
key SalesOrder,
@ObjectModel.mandatory: true
SalesOrderType,
@ObjectModel.mandatory: true
SalesOrganization,
@ObjectModel.mandatory: true
DistributionChannel,
@ObjectModel.mandatory: true
OrganizationDivision,
DeliveryStatus,
@ObjectModel.readOnly: true
DeletionIndicator,
@ObjectModel.readOnly: true
CreatedByUser,
@ObjectModel.readOnly: true
CreationDateTime,
@ObjectModel.readOnly: true
LastChangedByUser,
@ObjectModel.readOnly: true
LastChangeDateTime,
@ObjectModel.association.type: [#TO_COMPOSITION_CHILD]
_SalesOrderItem
}

Листинг. 9.7. Ракурс CDS для заказа клиента со статическими транзакционными


свойствами

Пример: расширение позиции заказа


клиента
Вы также можете смоделировать некоторые поля как обязательные, но изменить поля для
системного администрирования невозможно. Выполните соответствующее расширение
позиции заказа клиента (см. Листинг 9.8).

@AbapCatalog.sqlViewName: 'ZISALESORDERITTP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales OrderItem'
@ObjectModel.writeActivePersistence: 'ZSALESORDERITEM'
@ObjectModel.createEnabled: true
@ObjectModel.updateEnabled: true
@ObjectModel.deleteEnabled: true
define view ZI_SalesOrderItemTP
as selectfrom ZI_SalesOrderItem
association [1..1] to ZI_SalesOrderTP as _SalesOrder
on $projection.SalesOrder = _SalesOrder.SalesOrder
association [0..*] to ZI_SalesOrderScheduleLineTP
as _SalesOrderScheduleLine
on $projection.SalesOrder
= _SalesOrderScheduleLine.SalesOrder
and $projection.SalesOrderItem
= _SalesOrderScheduleLine.SalesOrderItem
{
@ObjectModel.readOnly: true
key SalesOrder,
@ObjectModel.mandatory: true
key SalesOrderItem,
@ObjectModel.mandatory: true
Product,
@ObjectModel.mandatory: true
OrderQuantity,
@ObjectModel.mandatory: true
OrderQuantityUnit,
NetAmount,
TransactionCurrency,
@ObjectModel.readOnly: true
CreatedByUser,
@ObjectModel.readOnly: true
CreationDateTime,
@ObjectModel.readOnly: true
LastChangedByUser,
@ObjectModel.readOnly: true
LastChangeDateTime,
@ObjectModel.association.type: [#TO_COMPOSITION_PARENT,
#TO_COMPOSITION_ROOT]
_SalesOrder,
@ObjectModel.association.type: [#TO_COMPOSITION_CHILD]
_SalesOrderScheduleLine
}

Листинг. 9.8. Ракурс CDS для позиции заказа клиента со статическими транзакционными
свойствами

Расширение графика поставок по заказу


клиента
В следующем шаге выполняется соответствующее расширение графика поставок по
заказу клиента (см. Листинг 9.9).

@AbapCatalog.sqlViewName: 'ZISALESORDERSLTP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales OrderScheduleLine'
@ObjectModel.writeActivePersistence: 'ZSALESORDERSLINE'
@ObjectModel.createEnabled: true
@ObjectModel.updateEnabled: true
@ObjectModel.deleteEnabled: true
define view ZI_SalesOrderScheduleLineTP
as selectfrom ZI_SalesOrderScheduleLine
association [1..1] to ZI_SalesOrderTP as _SalesOrder
on $projection.SalesOrder = _SalesOrder.SalesOrder
association [1..1] to ZI_SalesOrderItemTP as _SalesOrderItem
on $projection.SalesOrder = _SalesOrderItem.SalesOrder
and $projection.SalesOrderItem = _SalesOrderItem.SalesOrderItem
{
@ObjectModel.readOnly: true
key SalesOrder,
@ObjectModel.readOnly: true
key SalesOrderItem,
@ObjectModel.mandatory: true
key SalesOrderScheduleLine,
@ObjectModel.mandatory: true
DeliveryDate,
@ObjectModel.mandatory: true
OrderQuantity,
@ObjectModel.mandatory: true
OrderQuantityUnit,
@ObjectModel.readOnly: true
CreatedByUser,
@ObjectModel.readOnly: true
CreationDateTime,
@ObjectModel.readOnly: true
LastChangedByUser,
@ObjectModel.readOnly: true
LastChangeDateTime,
@ObjectModel.association.type: [#TO_COMPOSITION_ROOT]
_SalesOrder,
@ObjectModel.association.type: [#TO_COMPOSITION_PARENT]
_SalesOrderItem
}

Листинг. 9.9. Ракурс CDS для графика поставок по заказу клиента со статическими
транзакционными свойствами

Результаты на примере
Если взглянуть на бизнес-объект BOPF после активации изменений, вы увидите, что
аннотированные свойства также присутствуют. Свойства сущности определяют
возможности её создания, изменения и удаления пользователем и копируются в узел
BOPF, как показано на Рис. 9.7.
Рис. 9.7. Бизнес-объект BOPF: узел со статическими свойствами

Свойства поля определяют возможности изменения поля пользователем или указывают


его как обязательное и также копируются в поля узла BOPF, как показано на Рис. 9.8.

Рис. 9.8. Бизнес-объект BOPF: поля со статическими свойствами

Таким образом, бизнес-объект BOPF автоматически синхронизируется с моделью CDS


при активации корневого ракурса CDS. Поэтому введённые свойства будут также
доступны в среде выполнения BOPF с возможностью оценки и использования в вашей
собственной реализации посредством динамической конфигурации BOPF.

Синхронизация/создание модели BOPF

В настоящее время модель BOPF синхронизируется только при изменении ракурсов


CDS, если активирован корневой ракурс CDS. Поэтому корневой ракурс CDS всегда
необходимо активировать для внесения релевантных изменений, даже если изменения
относятся не к нему, а к дочерним ракурсам CDS.

Тестовая среда BOPF


В тестовой среде BOPF (см. Рис. 9.9), которую можно запустить непосредственно в ADT в
Eclipse из бизнес-объекта BOPF по пути «Выполнить • Выполнить как • Тестовая среда»
(Run • Run As • Test Environment), теперь можно создавать новые заказы клиента,
изменять заказы клиента, а также создавать, изменять и удалять новые позиции заказов
клиента.

Рис. 9.9. Тестовая среда BOPF с изменяемыми данными


Изменения возможны только в полях, не помеченных как доступные только для чтения.
Удаление заказа клиента невозможно, поскольку удалять их не требуется и они помечены
соответствующими аннотациями в модели CDS.

Сквозная поддержка
Теперь ракурсы CDS можно использовать для нетранзакционного чтения, а
инфраструктуру BOPF для транзакционного чтения и записи данных. Как было сказано в
Раздел 9.2, на сегодняшний день на платформе ABAP для интегрированной среды
выполнения интерфейс программирования недоступен. Поэтому
пользователь/разработчик принимает решение о том, как предоставляется доступ для
чтения: напрямую через CDS/SQL к базе данных (для неизменённых сохраненённых
данных) или транзакционный доступ для чтения необходимо инициировать в
транзакционной среде выполнения, если требуется учитывать транзакционные изменения.
Кроме того, пользователь/разработчик должен понимать, как BOPF обрабатывает ключи,
если в модели применяются семантические ключи. При использовании моделей в
сервисах OData платформа ABAP предлагает сквозную поддержку, которая
рассматривается в Раздел 9.4, в рамках выделенного использования моделей сервисов.

Вы можете перейти к соответствующему разделу и протестировать модель с


использованием клиента REST или пользовательского интерфейса SAPUI5/SAP Fiori.
Либо изучайте следующие разделы, в которых рассматривается добавление к модели
других функций и возможностей, а также реализованной логики для завершения работы
над приложением.

Установка и проверка эксклюзивных


блокировок (раздел 9.3.4)
Реализация по умолчанию для
эксклюзивных блокировок
Как вы уже могли заметить в примере и тестовом пользовательском интерфейсе, для
полного документа при переходе в режим редактирования или при редактировании
документа заказа клиента блокировка (объект блокировки) не устанавливается. BOPF
предоставляет реализацию блокировки по умолчанию на базе центрального объекта
блокировки с включением имени бизнес-объекта в аргумент блокировки. Эта реализация
доступна автоматически, но только для модели на базе GUID. Поскольку в примере
рассматривается реализация нового приложения с семантическим ключом, вы должны
действовать самостоятельно. Разумеется, вы также можете заменить реализацию по
умолчанию для нового приложения с GUID в качестве ключей, например, если требуется
определить собственный или использовать существующий объект блокировки.

Собственная реализация для


эксклюзивных блокировок
Для замены реализации по умолчанию необходимо переопределить метод LOCK_
ACTIVE_ENTITY в созданном классе ABAP для реализации блокировки и выполнить
требуемую реализацию. Необходимые данные экземпляра, который требуется
заблокировать, считываются с помощью стандартных средств BOPF с IO_READ. Если не
удаётся установить блокировку, необходимо передать об этом информацию в структуру с
помощью параметра экспорта ET_FAILED_KEY. Пример реализации на основе объекта
блокировки ZSALESORDER представлен в Листинге 9.10.

METHOD /bobf/if_lib_lock_active~lock_active_entity.
DATA lt_sales_order TYPE ztisalesordertp.
io_read->retrieve( EXPORTING iv_node =is_ctx-node_key
it_key =it_key
IMPORTING et_data =lt_sales_order).
LOOP AT lt_sales_order
ASSIGNING FIELD-SYMBOL(<ls_sales_order>)
WHERE salesorder IS NOTINITIAL.
CALL FUNCTION 'ENQUEUE_ZSALESORDER'
EXPORTING
salesorder =<ls_sales_order>-salesorder
EXCEPTIONS
foreign_lock = 1
system_failure = 2
OTHERS = 3.
IF sy-subrc <> 0.
APPEND INITIALLINETO et_failed_key
ASSIGNING FIELD-SYMBOL(<ls_failed_key>).
<ls_failed_key>-key = <ls_sales_order>-key.
ENDIF.
ENDLOOP.
ENDMETHOD.

Листинг. 9.10. Реализация блокировки BOPF в среде ABAP

Использование существующего объекта блокировки

Если выполняется преобразование приложения с существующим объектом блокировки


SAP, можно и следует повторно использовать этот объект блокировки для
обеспечения совместимости между новым и старым приложениям, а также
целостности данных.

Администрирование блокировок
Далее реализация блокировки вызывается автоматически посредством BOPF. Это можно
легко проверить в тестовой среде BOPF и с помощью данных администрирования
блокировок в транзакции SM12 (см. Рис. 9.10).
Рис. 9.10. ABAP-список записей блокировки

Сообщение об ошибке с конфликтами


блокировки
Как вы уже могли заметить, не существует способа и нет необходимости передавать
сообщения в структуру при реализации блокировки. Это делает BOPF с автоматическим
созданием сообщения об ошибке. Этот момент также можно проверить в тестовой среде
BOPF. Для этого перезапустите тестовую среду BOPF во втором сеансе, снова откройте
тот же документ и попробуйте изменить поле. Изменение отклоняется структурой с
выводом соответствующего сообщения об ошибке, см. Рис. 9.11.

Рис. 9.11. Тестовая среда BOPF с сообщением об ошибке при конфликте блокировки

Блокировка на уровне узла

В настоящее время блокировки можно моделировать, реализовывать и устанавливать


только на уровне корневого узла, т. е. для всего бизнес-объекта. В большинстве
случаев этого достаточно. Однако чтобы избежать конфликтов блокировки, иногда
целесообразно установить блокировки для поддеревьев бизнес-объекта, если это
позволяют приложение и процедура обработки документа. BOPF уже предоставляет
здесь больше гибкости, но для транзакционных приложений на базе CDS такие опции
пока не доступны.

Реализация выбора и проверок данных


(раздел 9.3.5)
Побочные эффекты
В транзакционных приложениях данные часто изменяются, что инициирует изменение
других данных и свойств или приводит к созданию сообщений о статусе бизнес-объекта
во время обработки или после неё. Такие побочные эффекты бывают трёх типов:

 изменение зависимых данных;


 проверка данных с соответствующими сообщениями об ошибке;
 изменение свойств.

В следующих разделах рассмотрим первые два типа. Поскольку такие побочные эффекты
моделируются и реализуются полностью в бизнес-объекте BOPF, а не в контексте
моделирования CDS, не будем делать этот раздел слишком объёмным. Предлагаем вам
обратиться к документации по приложениям BOPF и соответствующей технической
литературе. Далее в Раздел 9.3.7 рассматриваются изменения свойств, поскольку CDS
играет важную роль в моделировании и дополняет статические свойства, которые мы уже
изучили и определили в Раздел 9.3.3.

Реализация выбора данных


Средства выбора
Рассмотрим простые примеры изменения зависимых данных, т. е. изменения,
инициирующие изменения других данных. Например, при вводе почтового индекса
определяется соответствующий город и вводится в специальное поле. В качестве второго
примера можно привести вычисление полной суммы заказа по ценам товаров в корзине
покупок. Разумеется, дополнительные изменения могут инициироваться изменёнными
данными с помощью бизнес-логики, т. е. побочные эффекты на основе изменений в
результате побочных эффектов. Например, в корзине покупок при изменении суммы за
товары пересчитываются суммы налогов и стоимость доставки. Изменения зависимых
данных в BOPF реализуются в средствах выбора (determination).

Условия триггера
В BOPF такие средства выбора можно до определённой степени моделировать. Вы можете
определить собственно средство выбора и изменения, которые это средство инициирует.
В BOPF это называется условием триггера (trigger condition). В этой структуре побочный
эффект и вызов реализующего класса происходят только в том случае, если
соответствующее изменение релевантно для выбора. Инициировать изменения можно в
конкретном экземпляре (в примере это почтовый индекс и город) или других связанных
экземплярах (в примере с корзиной покупок, когда данные заголовка изменяются в случае
изменений в позициях). Если изменения в других экземплярах выступают в роли условий
триггера, должен быть указан путь привязки от инициирующего изменения к узлу, для
которого определён вариант выбора. Также можно смоделировать тип изменений
(создание, изменение или удаление экземпляра), на которые требуется реагировать.

Время выполнения для средств выбора


Для средств выбора доступны разные значения времени выполнения, определяющие
момент совершения выбора. В приложениях на базе CDS доступны следующие значения
времени выполнения.

 После изменения данных

Это значение времени выполнения используется для немедленного применения


бизнес-логики после изменения данных. Результат этого побочного эффекта
доступен другим компонентам приложения или пользователю на экране
непосредственно во время выполнения транзакции.

 До сохранения данных

Это значение времени выполнения используется для применения бизнес-логики в


конце транзакции, если выполнение возможно только в этот момент времени
(например, выбор номеров из диапазона) или не требует участия пользователя и
поэтому выполняется в конце (и только один раз) по причинам
производительности (например, инициируются последующие бизнес-процессы).

Другие известные в BOPF события недоступны для приложений на базе CDS.

Пример: выбор номера документа


В следующем примере выбирается только номер документа, поскольку это поле
статически установлено как неизменяемое (not changeable) в модели. Обычно такой выбор
не выполняется до сохранения. Однако в нашем примере номер документа присваивается
напрямую при создании экземпляра. Для этого создайте средство выбора с необходимыми
свойствами в BOPF (см. Рис. 9.12): откройте бизнес-объект BOPF в Eclipse,
нажмите «Применить к корню ROOT» (Go to the ROOT node) и перейдите на
вкладку «Средства выбора» (Determinations). Введите значения в поля «Имя»
(Name) и «Описание» (Description), а затем нажмите кнопку «Готово» (Finish).

Рис. 9.12. Выбор номера документа в BOPF


Здесь нажмите кнопку «Создать» (New), чтобы создать класс реализации напрямую и
добавить соответствующую реализацию. Пример можно увидеть в Листинге 9.11. Номер
документа взят из определённого диапазона номеров ZSALESORD.

METHOD /bobf/if_frw_determination~execute.
DATA ls_salesorder TYPE REFTO zsisalesordertp.
DATA ls_msg TYPE symsg.
LOOP AT it_key ASSIGNING FIELD-SYMBOL(<ls_key>).
CREATE DATA ls_salesorder.
CALL FUNCTION 'NUMBER_GET_NEXT'
EXPORTING
nr_range_nr = '01'
object = 'ZSALESORD'
IMPORTING
number = ls_salesorder->salesorder
EXCEPTIONS
interval_not_found = 1
number_range_not_intern = 2
object_not_found = 3
quantity_is_0 = 4
quantity_is_not_1 = 5
interval_overflow = 6
buffer_overflow = 7
OTHERS = 8.
IF sy-subrc <> 0.
IF eo_message IS NOTBOUND.
eo_message =/bobf/cl_frw_factory=>get_message( ).
ENDIF.
ls_msg-msgid =sy-msgid.
ls_msg-msgno =sy-msgno.
ls_msg-msgty =sy-msgty.
ls_msg-msgv1 =sy-msgv1.
ls_msg-msgv2 =sy-msgv2.
ls_msg-msgv3 =sy-msgv3.
ls_msg-msgv4 =sy-msgv4.
eo_message->add_message(
EXPORTING
is_msg =ls_msg
iv_node =is_ctx-node_key
iv_key =<ls_key>-key
iv_attribute = 'SALESORDER'
iv_lifetime =/bobf/cm_lib=>co_lifetime_transition
).
ENDIF.
io_modify->update(
EXPORTING
iv_node =is_ctx-node_key
iv_key =<ls_key>-key
is_data =ls_salesorder
it changed fields = VALUE #( ( CONV #('SALESORDER') ) )
).
ENDLOOP.
ENDMETHOD.

Листинг. 9.11. Реализация средства выбора номер документа в BOPF в среде ABAP

Зависимости между средствами выбора


Поскольку мы работаем с моделью с семантическим ключом, в которой ключевые поля
родительского узла являются частью ключа дочернего узла, необходимо обеспечить ввод
данных при создании подузла. В модели на базе GUID для выполнения этой задачи
используются собственные средства BOPF. Такая поддержка для семантических ключей в
настоящее время отсутствует. По этой причине выбор требуется в каждом подузле
(см. Рис. 9.13).

Рис. 9.13. Средство выбора в BOPF для распространения номера документа

Зависимости
Такие средства выбора реализуются так же, как и для номера документа. Обратите
внимание на то, что важно выполнить ведение зависимостей между средствами выбора.
Если заголовок заказа клиента и одна или несколько позиций заказа клиента (или график
поставки по заказу клиента) создаются в одном запросе, важно сначала присвоить номер
документа (в заголовке заказа клиента), а затем скопировать в связанные позиции. После
этого номер документа и номера позиций (установленные внешне или предложенные
внутри системы) копируются в (связанные) графики поставки. Ведение зависимостей
между средствами выбора можно выполнить на вкладке «Зависимость» (Dependency) в
нижней части экрана, показанного на Рис. 9.14.

Рис. 9.14. Зависимости между средствами выбора в BOPF

Функции библиотеки
BOPF также предлагает различные функции библиотеки с использованием метаданных
модели BOPF. Для особых административных данных (дата создания, дата последнего
изменения и т. д.) ведение этой информации можно выполнить посредством
семантических аннотаций в модели CDS. В инфраструктуре ABAP эта информация
используется для автоматического добавления соответствующего варианта библиотеки к
бизнес-объекту BOPF с целью автоматического и корректного ввода данных во время
выполнения. Для этого вы уже проаннотировали поля как изменяемые, поскольку они
устанавливаются не пользователем или другим приложением, а системой.

В модели CDS для активации этой функциональности вы также добавили к этим полям в
каждой релевантной сущности семантические аннотации, выделенные в Листинге 9.12.

define view ZI_SalesOrderTP



{

@ObjectModel.readOnly: true
@Semantics.user.createdBy: true
CreatedByUser,
@ObjectModel.readOnly: true
@Semantics.systemDateTime.createdAt: true
CreationDateTime,
@ObjectModel.readOnly: true
@Semantics.user.lastChangedBy: true
LastChangedByUser,
@ObjectModel.readOnly: true
@Semantics.systemDateTime.lastChangedAt: true
LastChangeDateTime,

}

Листинг. 9.12. Ракурс CDS для заказа клиента с аннотациями для системных
административных данных

После активации ракурсов CDS автоматически созданные средства выбора


административных данных становятся доступны в модели BOPF (см. Рис. 9.15). Они
запускаются при сохранении данных и ввода в поля текущего пользователя и системной
метки времени.

Рис. 9.15. Выбор системных административных данных в BOPF

Реализация проверок данных


Проверки непротиворечивости
В то время как средства выбора обогащают введённые данные, необходимо также
проверять данные перед сохранением в базу данных и не допускать сохранения в случае
выявления противоречий. Как правило, в данных транзакций необходимо обеспечить
непротиворечивость бизнес-данных. К простым проверкам, которые помогут
предотвратить ошибки в записях, относятся проверки допустимых значений
(фиксированных значений или внешних ключей). Даже если отдельные значения
являются верными, превышение лимитов комбинациями значений и т. п. может привести
к появлению противоречий в данных, например, если введённые вместе почтовый индекс
и город не соответствуют друг другу, либо общая стоимость товаров в корзине покупок
превышает установленный бюджет. Проверки данных в BOPF реализуются
через проверки непротиворечивости (consistency validation).

Условия триггера
Проверки непротиворечивости моделируются в BOPF и инициируются изменениями так
же, как и средства выбора. Это означает, что соответствующие проверки можно
выполнять автоматически при внесении релевантных изменений. Если требуется,
создаются сообщения для поддержки пользователя и обеспечения ввода
непротиворечивых данных. Обычно такие проверки требуется выполнять не только как
побочный эффект изменений, но и как явные запросы. Одной из причин для этого
является невозможность исправления ряда ошибок непосредственно в бизнес-объекте
путём изменения данных. Вместо этого требуется реакция на изменения в среде
(конфигурация системы, основные данные и другие бизнес-объекты). В BOPF доступна
опция выполнения проверки непротиворечивости по условию триггера check, что
соответствует явному требованию выполнить проверку. В модели BOPF на базе CDS это
условие триггера всегда установлено автоматически, поскольку это отвечает стандартам
передового опыта. По этой причине оно не отображается в редакторе BOPF.

Функции библиотеки
Для проверок непротиворечивости также существуют функции библиотеки. Некоторые из
них мы будем использовать в примере. Для этого определите новую проверку
непротиворечивости в бизнес-объекте BOPF, но не создавайте реализующий класс,
который вы реализуете самостоятельно. Вместо этого укажите существующий класс из
библиотеки BOPF. В соответствии с информацией в Раздел 9.3.3 вы определили
статические свойства в модели, которые также переносятся в модель BOPF. Одно из этих
статических свойств является обязательным, т. е. выражает необходимое значение для
аннотированного поля, без которого в экземпляре возникнут противоречия. Для проверки
обязательных полей в BOPF предоставляется функция библиотеки.

В своём примере определите проверку непротиворечивости в каждом узле, как показано


для корневого узла Рис. 9.16. Для этого откройте бизнес-объект BOPF в Eclipse,
нажмите «Применить в узле ROOT» (Go to the ROOT node) и перейдите на
вкладку «Проверки» (Validations). Введите значения в поля «Имя» (Name) и «Описание»
(Description), а затем нажмите кнопку «Готово» (Finish). Здесь выполняется проверка
полей на наличие начальных значений с созданием соответствующих сообщений об
ошибке, если поля не заполнены (конечным пользователем или средством выбора
данных).
Рис. 9.16. Проверка непротиворечивости в BOPF

Результат
В тестовой среде BOPF (Рис. 9.17) отображается результат проверки для нового заказа
клиента, для которого ещё не были введены дополнительные данные. Сообщение об
ошибке не даёт сохранить данные, что обеспечивает запись в базу данных только
непротиворечивой информации.

Рис. 9.17. Тестовая среда BOPF с сообщениями из проверки непротиворечивости

Моделирование и реализация действий


(раздел 9.3.6)
Действия
В дополнение к стандартным операциям (создание, изменение и удаление) в приложениях
также требуется предоставить общие операции с более удобными функциональными
возможностями, которые будут связывать несколько базовых операций в один
согласованный пакет. Такие операции в BOPF называются действиями (action). Проще
говоря, в большинстве случаев действия соответствуют кнопкам в пользовательском
интерфейсе приложения. Поскольку действия также могут изменять данные (например,
стандартные операции «Создать» (Create), «Изменить» (Change) и «Удалить» (Delete), они
оказывают в BOPF побочные эффекты. Действия невозможно определить в модели CDS,
но они определяются и реализуются в BOPF тем же способом, что и средства
выбора/проверки непротиворечивости.

Параметры действия
В отличие от стандартных операций, для действий можно установить параметры. Это
позволяет пользователю (например, конечному пользователю) влиять на поведение
действия в предварительно определённых границах. В пользовательском интерфейсе это
соответствует диалоговому окну пользователя после нажатия соответствующей кнопки, в
котором вводятся допустимые значения.

Результат действия
В классической структуре BOPF действия не дают результата, а выполняются с данными
бизнес-объекта и изменяют их. Напротив, модель BOPF на базе CDS в настоящее время
позволяет явно моделировать результат в действиях. Это может быть узел бизнес-объекта
BOPF или тип данных по вашему выбору. Можно использовать любые типы данных из
ABAP DDIC, включая глубокие структуры и таблицы.

Пример: действие удаления


Добавим действие в нашем примере. В модели вам по-прежнему недоступно прямое
удаление заказов клиента. Для активации удаления вы реализуете действие, которое на
основе статуса поставки заказа клиента будет выполнять физическое удаление или
установку индикатора удаления. Для этого определите действие в BOPF и введите
необходимые данные (см. Рис. 9.18), вызвав бизнес-объект BOPF в Eclipse,
нажав «Применить к узлу ROOT» (Go to the ROOT node) и открыв вкладку «Действия»
(Actions). Введите значения в поля «Имя» (Name) и «Описание» (Description), а затем
нажмите кнопку «Готово» (Finish).
Рис. 9.18. Действие удаления в BOPF

Здесь тестовая среда также предоставляет мощную поддержку. Функция «Создать» (New)
создаёт класс с интерфейсом, который требуется реализовать. Реализация выполняется в
соответствии со стандартной для BOPF процедурой. Пример показан в Листинге 9.13.

METHOD /bobf/if_frw_action~execute.
DATA lt_sales_order TYPE ztisalesordertp.
DATA ls_msg TYPE symsg.
CLEAR et_failed_key.
CLEAR eo_message.
io_read->retrieve( EXPORTING iv_node =is_ctx-node_key
it_key =it_key
IMPORTING et_data =lt_sales_order).
LOOP AT lt_sales_order REFERENCE INTODATA(ls_sales_order).
CASE ls_sales_order->deliverystatus.
WHEN ' '.
io_modify->delete(
EXPORTING
iv_node =is_ctx-node_key
iv_key =ls_sales_order->key
).
WHEN 'A'.
ls_sales_order->deletionindicator =abap_true.
io_modify->update(
EXPORTING
iv_node =is_ctx-node_key
iv_key =ls_sales_order->key
is_data =ls_sales_order
it_changed_fields = VALUE #( (
CONV #('DELETIONINDICATOR')
) )
).
WHEN OTHERS.
IF eo_message IS NOTBOUND.
eo_message =/bobf/cl_frw_factory=>get_message( ).
ENDIF.
eo_message->add_cm(
NEW /bobf/cm_lib(
textid
= /bobf/cm_lib=>action_not_allowed2
severity
= /bobf/cm_lib=>co_severity_error
lifetime
= /bobf/cm_lib=>co_lifetime_transition
ms_origin_location = VALUE #(
bo_key =is_ctx-bo_key
node_key =is_ctx-node_key )
mv_object_name = 'ZI_SALESORDERTP'
mv_node_name = 'ZI_SALESORDERTP' )
).
ENDCASE.
ENDLOOP.
ENDMETHOD.

Листинг. 9.13. Реализация действий в BOPF в среде ABAP

Динамическое управление свойствами


(раздел 9.3.7)
Специфичные для приложений
ограничения
В дополнение к изменениям данных и проверкам как побочному эффекту изменений,
изменяться могут и свойства экземпляра. Например, в результате изменения или действия
устанавливается статус, который запрещает дальнейшее изменение сущности или
определённых полей. С другой стороны, некоторые поля можно заполнить или изменить
только после заполнения другого поля, например, вид заказа клиента. Такие побочные
эффекты описывают специфичные для приложения ограничения на основе конкретных
данных экземпляра. Здесь также следует учитывать и другие данные в дополнение к
данным бизнес-объекта, например, конфигурацию приложения, на основе чего данные не
должны изменяться или отображаться независимо от условий для специфичного
экземпляра. В этом разделе рассматриваются возможности расширения модели для
определения соответствующей логики управления приложением.
Эксклюзивная блокировка и полномочия
Помимо специфичных для приложения ограничений в зависимости от данных, вы уже
изучили и реализовали прочие ограничения из предыдущих разделов. С одной стороны,
параллельные изменения разными пользователями одних и тех же сущностей и
экземпляров в концепции блокировки нежелательны (см. Раздел 9.4.3). С другой стороны,
не все пользователи имеют полномочия на изменения, либо могут изменять только
определённые данные в некоторых экземплярах и выполнять операции из ограниченного
списка. Мы используем концепцию полномочий SAP, дополненную в Разделе 9.3.8. К
специфичной для приложения управляющей информации BOPF автоматически добавляет
информацию, релевантную для среды выполнения. Таким образом, помимо реализации,
специфичной для приложения, блокировки и полномочия не требуют специальной
реализации для управления динамическими свойствами.

Моделирование
В Разделе 9.3.3 мы уже рассмотрели моделирование и результаты применения
статических свойств. В сущности, эти свойства можно контролировать динамически. На
уровне сущности или экземпляра можно определить возможность изменения или
удаления экземпляров. На уровне поля можно определить, готово оно к вводу или нет,
является ли обязательным, должно ли быть скрыто от пользователя по причине
нерелевантности в данном контексте (и, как правило, вследствие отсутствия присвоенного
значения). Последнее, т. е. статическое скрытие поля, конечно, не является
целесообразным, поскольку в этом случае поле вообще не стоило включать в модель.
Вообще, статические свойства модели можно дополнительно динамически ограничить
только с помощью CDS (в отличие от стандартной процедуры BOPF). Например, если
сущность невозможно удалить статически, для неё можно динамически установить
свойство deletable.

Для добавления реализации к модели используются аннотации, с которыми вы уже


знакомы по теме статического управления свойствами. Замените статические значения
(true или false) специальным значением аннотации EXTERNAL_CALCULATION, которое
выражает ваше намерение вычислять это значение динамически.

На уровне сущности аннотация выглядит следующим образом:

@ObjectModel.updateEnabled: #(‘EXTERNAL_CALCULATION’)

@ObjectModel.deleteEnabled: #(‘EXTERNAL_CALCULATION’)

На уровне поля аннотации выглядят следующим образом:

@ObjectModel.readOnly: #(‘EXTERNAL_CALCULATION’)

@ObjectModel.mandatory: #(‘EXTERNAL_CALCULATION’)

@ObjectModel.enabled: #(‘EXTERNAL_CALCULATION’)

Пример: контроль действия


Разумеется, также можно динамически контролировать действия. Эта тема раскрыта в
Раздел 9.6.3. Поскольку действия в CDS не моделируются, выразить данное намерение в
модели CDS невозможно. Таким образом, действия или точнее возможность их
выполнения можно всегда динамически контролировать с выполнением по умолчанию.

Например, требуется отключить возможность изменения номера позиции заказа клиента


после сохранения. Для этого добавьте модель, как указано в Листинге 9.14.

define view ZI_SalesOrderItemTP



{
@ObjectModel.readOnly: true
key SalesOrder,
@ObjectModel.mandatory: true
@ObjectModel.readOnly: #('EXTERNAL_CALCULATION')
key SalesOrderItem,

}

Листинг. 9.14. Ракурс CDS для заказа клиента с динамическими свойствами

Пример реализации
Аннотация в модели CDS автоматически создаёт средство выбора в модели BOPF (если
оно ещё не доступно) для вычисления свойств с именем
ACTION_AND_FIELD_CONTROL, а также связанный класс, в котором можно выполнить
реализацию. Как и было сказано, реализация выполняется по стандартной процедуре в
BOPF. Пример реализации представлен в Листинге 9.15.

METHOD /bobf/if_frw_determination~execute.
DATA lt_sales_order_item TYPE ztisalesorderitemtp.
io_read->retrieve( EXPORTING iv_node =is_ctx-node_key
it_key =it_key
IMPORTING et_data =lt_sales_order_item
).
LOOP AT lt_sales_order_item
ASSIGNING FIELD-SYMBOL(<ls_sales_order_item>)
WHERE creationdatetime IS NOTINITIAL.
NEW /bobf/cl_lib_h_set_property(
is_context =is_ctx
io_modify =io_modify
)->set_attribute_read_only(
EXPORTING
iv_attribute_name = 'SALESORDERITEM'
iv_key =<ls_sales_order_item>-key
).
ENDLOOP.
ENDMETHOD.

Листинг. 9.15. Реализация динамических свойств в BOPF в среде ABAP


Настройка динамических свойств

Для динамической настройки свойств рекомендуется использовать вспомогательный


класс /BOPF/CL_LIB_H_SET_PROPERTY, предоставляемый в BOPF. Для быстрой
настройки соответствующих динамических свойств здесь применяются значимые
методы.

Реализация проверок полномочий


(раздел 9.3.8)
Объект полномочий
В то время как эксклюзивные блокировки предотвращают одновременное редактирование
и перезапись данных, проверки полномочий управляют доступом к данным. Полномочия
на выполнение различных операций с документами (создание, чтение, изменение и
удаление), а также на каждое специально определённое действие, могут присваиваться по
отдельности. Поскольку полномочия всегда являются специфичными для приложения и
зависят от конкретных данных приложения (например, организационные единицы, виды
заказов и т. д.), нужный объект полномочий необходимо определить самостоятельно.

Реализация
Как вы уже знаете из главы 4, полномочия на чтение моделируются с помощью средств
управления доступом CDS (язык управления данными, DCL) при обращении к данным
через Open SQL. Эти средства управления доступом применяются автоматически при
выборе данных с помощью ракурсов CDS. Иначе происходит при транзакционном
доступе и даже при транзакционном доступе для чтения на уровне сервисов BOPF.
Поэтому для таких вариантов доступа необходимо всегда самостоятельно добавлять
реализацию проверки полномочий. В структуре уже создан релевантный класс с двумя
методами для реализации. В методе CHECK_STATIC_AUTH можно выполнить
статическую проверку (не на основе экземпляра). Здесь проверяется возможность
выполнения пользователем определённых действий (создание, изменение или удаление
бизнес-объекта) независимо от специфичного экземпляра бизнес-объекта. Проверку на
основе экземпляра можно реализовать в методе CHECK_INSTANCE_AUTH. Эта проверка
позволяет узнать, может ли пользователь выполнять конкретные действия с одним или
несколькими экземплярами бизнес-объекта.

Пример: Проверка полномочий


В примере используется объект полномочий V_VBAK_AAT, который относится к
стандартной функциональности SAP для обработки заказов клиента.
В Листинге 9.16 показан пример реализации статической проверки полномочий.

METHOD /bobf/if_lib_auth_draft_active~check_instance_authority.
DATA lt_sales_order TYPE ztisalesordertp.
DATA ls_key TYPE /bobf/s_frw_key.
DATA lv_textid TYPE scx_t100key.
CLEAR et_failed_key.
CLEAR eo_message.
EXIT.
IF is_ctx-node_key =zif_i_salesordertp_c=>
sc_node-zi_salesordertp.
io_read->retrieve( EXPORTING iv_node =is_ctx-node_key
it_key =it_key
IMPORTING et_data =lt_sales_order).
ELSEIF is_ctx-node_key =zif_i_salesordertp_c=>
sc_node-zi_salesorderitemtp.
io_read->retrieve_by_association(
EXPORTING
iv_node =is_ctx-node_key
it_key =it_key
iv_association =zif_i_salesordertp_c=>
sc_association-zi_salesorderitemtp-to_root
iv_fill_data =abap_true
IMPORTING
et_data =lt_sales_order
).
ELSEIF is_ctx-node_key =zif_i_salesordertp_c=>
sc_node-zi_salesorderschedulelinetp.
io_read->retrieve_by_association(
EXPORTING
iv_node =is_ctx-node_key
it_key =it_key
iv_association =zif_i_salesordertp_c=>
sc_association-zi_salesorderschedulelinetp-to_root
iv_fill_data =abap_true
IMPORTING
et_data =lt_sales_order
).
ENDIF.
LOOP AT lt_sales_order ASSIGNING FIELD-SYMBOL(<ls_sales_order>).
AUTHORITY-CHECK OBJECT 'V_VBAK_AAT'
ID 'ACTVT' FIELD is_ctx-activity
ID 'AUART' FIELD <ls_sales_order>-salesordertype.
IF sy-subrc <> 0.
ls_key-key =<ls_sales_order>-key.
APPEND ls_key TO et_failed_key.

CASE is_ctx-activity.
WHEN /bobf/cl_frw_authority_check=>sc_activity-display.
lv_textid =/bobf/cm_lib=>no_auth_display.
WHEN /bobf/cl_frw_authority_check=>sc_activity-create.
lv_textid =/bobf/cm_lib=>no_auth_create.
WHEN /bobf/cl_frw_authority_check=>sc_activity-change.
lv_textid =/bobf/cm_lib=>no_auth_update.
WHEN /bobf/cl_frw_authority_check=>sc_activity-delete.
lv_textid =/bobf/cm_lib=>no_auth_delete.
WHEN /bobf/cl_frw_authority_check=>sc_activity-execute.
lv_textid =/bobf/cm_lib=>no_auth_execute_action.
WHEN OTHERS.
RETURN.
ENDCASE.
IF eo_message IS NOTBOUND.
eo_message =/bobf/cl_frw_factory=>get_message( ).
ENDIF.
eo_message->add_cm( NEW /bobf/cm_lib(
textid =lv_textid
severity =/bobf/cm_lib=>co_severity_error
lifetime =/bobf/cm_lib=>co_lifetime_transition
ms_origin_location = VALUE #( bo_key=
is_ctx-bo_key node_key=is_ctx-node_key )
mv_object_name = 'ZI_SALESORDERTP'
mv_node_name = 'ZI_SALESORDERTP'
mv_action_name = CONV #( is_ctx-action_name )
)
).
ENDIF.
ENDLOOP.
ENDMETHOD.

Листинг. 9.16. Реализация статической проверки полномочий в BOPF в среде ABAP

Пример: проверка полномочий для


экземпляра
В Листинге 9.17 показан пример проверки полномочий для экземпляра.

METHOD /bobf/if_lib_auth_draft_active~check_static_authority.
DATA lv_textid TYPE scx_t100key.
rv_failed =abap_false.
AUTHORITY-CHECK OBJECT 'V_VBAK_AAT'
ID 'ACTVT' FIELD is_ctx-activity
ID 'AUART' DUMMY.
IF sy-subrc <> 0.
rv_failed =abap_true.
CASE is_ctx-activity.
WHEN /bobf/cl_frw_authority_check=>sc_activity-display.
lv_textid =/bobf/cm_lib=>no_auth_display.
WHEN /bobf/cl_frw_authority_check=>sc_activity-create.
lv_textid =/bobf/cm_lib=>no_auth_create.
WHEN /bobf/cl_frw_authority_check=>sc_activity-change.
lv_textid =/bobf/cm_lib=>no_auth_update.
WHEN /bobf/cl_frw_authority_check=>sc_activity-delete.
lv_textid =/bobf/cm_lib=>no_auth_delete.
WHEN /bobf/cl_frw_authority_check=>sc_activity-execute.
lv_textid =/bobf/cm_lib=>no_auth_execute_action.
WHEN OTHERS.
RETURN.
ENDCASE.
eo_message =/bobf/cl_frw_factory=>get_message( ).
eo_message->add_cm( NEW /bobf/cm_lib(
textid =lv_textid
severity =/bobf/cm_lib=>co_severity_error
lifetime =/bobf/cm_lib=>co_lifetime_transition
ms_origin_location = VALUE #( bo_key=
is_ctx-bo_key node_key=is_ctx-node_key )
mv_object_name = 'ZI_SALESORDERTP'
mv_node_name = 'ZI_SALESORDERTP'
mv_action_name = CONV #( is_ctx-action_name )
)
).
ENDIF.
ENDMETHOD.

Листинг. 9.17. Реализация проверки полномочий для экземпляра в BOPF в среде ABAP

Привилегированный доступ из бизнес-логики

Определённые и реализованные проверки полномочий выполняются посредством


уровня сервисов BOPF только при обращении извне, т. е. при обращении пользователя.
Программный доступ к данным в BOPF посредством бизнес-логики всегда является
привилегированным. Соответствующие обращения должны также успешно
выполняться во внутренней бизнес-логике. В качестве примера можно привести
проверку на дубликаты для внешней нумерации, для которой при поиске
потенциальных дубликатов не должны применяться ограничения по полномочиям.

Определение вычисляемых полей


(раздел 9.3.9)
Виртуальные поля
Поскольку ракурсы CDS используются для моделирования бизнес-объекта, может
потребоваться переопределить бизнес-объект независимо от (возможно, устаревшего)
моделирования базы данных, а не просто считать один-к-одному из таблицы базы данных.
Вообще, при моделировании CDS можно использовать различные функции SQL,
например, соединение, объединение и т. д. Если при записи возможен взаимно
однозначный мэппинг, применение таких функций будет весьма вероятным. Однако
поскольку невозможно записать данные в подпрограмме ABAP собственно в базу данных,
указанные функции SQL применяются в очень ограниченном объёме (см. Раздел 9.3.2).
При этом вы можете добавить отдельные поля ракурсов к транзакционным ракурсам CDS
с вычислениями посредством логики SQL или CDS. В этом случае необходимо обеспечить
неизменность набора результатов ракурса CDS (т. е. числа строк в результате). Эти поля
должны быть помечены аннотациями как доступные только для чтения.

Вычисление в базе данных


Это целесообразно, например, в том случае, если общая сумма по заказу клиента
вычисляется непосредственно в базе данных с помощью функции агрегации и связанных
позиций заказа клиента для эффективного определения значений при чтении (особенно
при большом количестве заказов клиента). Ещё одним примером является трансформация
значения поля для предоставления пользователю информации в удобном формате.
В Листинге 9.18 это показано на примере, в котором специальное значение выводится как
отдельное поле DeliveryIsCompleted из статуса заказа клиента с несколькими значениями.

define view ZI_SalesOrderTP



{

DeliveryStatus,
@ObjectModel.readOnly: true
cast ( case DeliveryStatus
when 'C' then 'X' else ' ' end
as compl_ind preserving type)
as DeliveryIsCompleted,

}

Листинг. 9.18. Ракурс CDS для заказа клиента с вычисляемым полем

Вычисление в ABAP
Обратите внимание на то, что для вычисляемых в базе данных полей данные
необязательно поступают напрямую из базы данных во время транзакционного доступа.
Поэтому вычисление не может выполняться только здесь. Позиции заказа клиента во
время транзакции могут изменяться. В этом случае корректное значение общей суммы
также должно быть вычислено и возвращено для транзакционного доступа. Это
применимо и в примере с полем DeliveryIsCompleted. Таким образом, по-прежнему
необходимо предоставить средство выбора, которое будет выполнять аналогичное
вычисление в BOPF и в ракурсе CDS. Несмотря на избыточность реализации, такая
процедура целесообразна во многих случаях, поскольку вычисление с помощью ABAP
выполняется только для транзакционного доступа, а вычисление с помощью CDS
выполняется в базе данных исключительно для чтения данных.

Данные, вычисляемые только в среде ABAP

Поля, вычисление для которых возможно только на платформе ABAP, в настоящее


время на уровне модели транзакционных объектов не поддерживаются. Вы можете
добавить и реализовать такие поля только в модели транзакционных сервисов. Для
получения подробной информации см. Раздел 9.4.3. Также в настоящее время
невозможно определить и реализовать полные сущности в модели BOPF на базе CDS,
которые не определяются посредством ракурсов CDS.

Модели транзакционных сервисов


в SAP S/4HANA*
Показано как использовать транзакционные приложения в различных сценариях с
применением моделей транзакционных сервисов.

*Оригинал (англ.): Core Data Services for ABAP. Ренцо Колле, Ральф Дентцер, Ян


Храстник. Издательство SAP PRESS. Раздел 9.3. 2019, с. 331–370.

Корректура: Олег Точенюк.

Модели транзакционных сервисов в  SAP S/4HANA // SAP Professional Journal


Россия,  январь–февраль, №1 (78), стр. 144–156.  @ 2020, Ренцо Колле, Ральф Дентцер,
Ян Храстник.

Использование бизнес-объектов в
нескольких приложениях
В этом разделе рассматриваются модели транзакционных сервисов CDS, которые выводят
приложение в специфичном сервисе. Реализовать бизнес-объект и связанную бизнес-
логику нужно только один раз, чтобы избежать избыточности и обеспечить
непротиворечивость системы. Однако одновременно требуется использовать бизнес-
объект в разных бизнес-процессах, разных приложениях и разных пользовательских
интерфейсах. Помимо этого, вам требуется выводить только определённые компоненты
транзакционной модели в специфичном интерфейсе программирования приложений (API)
или пользовательском интерфейсе. Необходимо определить ограничения как на уровне
данных, так и на уровне поведения или доступных функций.

Как было сказано выше, модель CDS и модель BOPF изначально работают во время
выполнения параллельно. В целом, пользователь вашего приложения должен иметь
представление об этой корреляции, чтобы получать доступ к данным по правильному
каналу. Разрешая определять модели сервисов на базеCDS и выполнять мэппинг
сущностей для сервисов OData, платформа ABAP предоставляет комплексную модель
программирования для непротиворечивого выполнения этой задачи.

Определение моделей транзакционных


сервисов (раздел 9.4.1)
Модели сервисов как уровни ракурсов
Модели сервисов, как и всегда, определяются с помощью CDS.Соответствующие ракурсы
CDS определяются как проекции (projection) ракурсов CDS модели транзакционных
объектов. Здесь следует учесть ряд ограничений, чтобы эту модель можно было
использовать позднее для транзакционной обработки. Для моделей общих сервисов,
которые используются только для чтения, к реализации можно применять весь диапазон
языковых опций CDS. Если требуется использовать модель сервисов в транзакционной
среде выполнения, не все из этих опций будут доступны для связанных ракурсов CDS. В
моделях транзакционных сервисов можно, по сути, только ограничить модель
транзакционных объектов приложения для вывода выбранной части полного приложения.
Разрешены следующие ограничения и изменения.

 Псевдонимы (ключевое слово AS)

Поля можно переименовывать.

 Выводимые поля (столбцы; ключевое слово SELECT)

Можно ограничить набор полей базовых ракурсов.

 Набор результатов (строки; ключевое слово WHERE)

Набор результатов можно ограничить с помощью условий.

 Выводимые узлы

Не все сущности бизнес-объекта требуется выводить.

 Статические свойства

Можно ограничить операции (создание, изменение и удаление), а также свойства


полей для определения возможности их изменения.

Правила для моделей транзакционных


сервисов
Вы должны соблюдать следующие правила.

 Ключ ракурсов CDS в модели сервисов должен соответствовать ключу в модели


объектов. В частности, все поля ключей базового ракурса CDS должны
присутствовать в списке проекций модели сервисов.
 Корневой узел выводится всегда. Кроме того, в модели сервисов должны
присутствовать все узлы на пути к корневому узлу для каждого узла в структуре.
Это означает, что опустить можно только концевые узлы или целые поддеревья.
 Поскольку для каждой выводимой сущности в модели сервисов вводится новый
ракурс CDS, композиционные привязки невозможно проецировать, поскольку они
относятся к ракурсу CDS модели объектов как цель, а не как проекция. Поэтому
необходимо переопределить и проаннотировать нужные привязки
соответствующим образом. Обратите внимание на то, что имя определённой таким
способом привязки должно совпадать с именем выводимой привязки в модели
объектов. Однако это имя можно заменить псевдонимом в списке проекций
ракурса CDS.

Функции агрегации и вычисления с использованием соответствующих опций CDS


запрещены, равно как и объединения или соединения для ракурсов CDS модели
транзакционных сервисов. Согласно основному правилу запрещены функции, которые не
позволяют выполнять мэппинг набора результатов для ракурса CDS в модели сервисов по
набору результатов для базового ракурса CDS в модели объектов. Добавлять поля к
списку проекций с использованием выражений пути или явных соединений можно в том
случае, если получаемые соединения не изменяют кардинальность набора результатов.
Добавленные поля по определению не являются частью модели объектов и поэтому не
могут изменяться. Их можно только считывать или пометить аннотацией как доступные
только для чтения (read-only).

Аннотации
Известные аннотации также используются для определения структуры объектов в модели
сервисов:

 @ObjectModel.compositionRoot: true
 @ObjectModel.association.type: [#TO_COMPOSITION_CHILD]
 @ObjectModel.association.type: [#TO_COMPOSITION_PARENT]
 @ObjectModel.association.type: [#TO_COMPOSITION_ROOT]

В отличие от модели объектов, модель сервисов необязательно должна выводить (и,


следовательно, аннотировать) привязки к родительскому или корневому узлу. Однако, как
правило, весьма целесообразно предлагать такую навигацию в модели сервисов.

Наконец, модель транзакционных объектов используется следующей аннотацией,


которую необходимо указать в корневом ракурсе CDS модели сервисов:

@ObjectModel.transactionalProcessingDelegated:true

Эта информация означает, что соответствующая модель транзакционных объектов (в


частности, ее транзакционная среда выполнения) должна использоваться из данной
модели сервисов. Обратите внимание на то, что модель транзакционных сервисов должна
быть определена непосредственно над моделью транзакционных объектов. В основе
второй модели сервисов, например, для второго приложения UI, также должна лежать
модель транзакционных объектов, а не другая модель транзакционных сервисов. В
инфраструктуре ABAP для транзакционного использования допускается только один
уровень соответствующих ракурсов CDS.

Наконец, ракурсы CDS модели сервисов можно подготовить для использования


расширений метаданных. Для этого пометьте аннотациями ракурсы CDS в модели
сервисов следующим образом:

@Metadata.allowExtensions: true.

В этом примере модель транзакционных объектов для заказа клиента должна выводиться
полностью как сервис. Таким образом, ракурс CDS определяется для каждой из трёх
сущностей со всеми необходимыми аннотациями. Определение заголовка заказа клиента
представлено в Листинге 9.19.

@AbapCatalog.sqlViewName: 'ZCSALESORDERTP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Order'
@Metadata.allowExtensions: true
@ObjectModel.compositionRoot: true
@ObjectModel.transactionalProcessingDelegated: true
@ObjectModel.createEnabled: true
@ObjectModel.updateEnabled: true
@ObjectModel.deleteEnabled: false
define view ZC_SalesOrderTP
as selectfrom ZI_SalesOrderTP
association [0..*] to ZC_SalesOrderItemTP as _SalesOrderItem
on $projection.SalesOrder = _SalesOrderItem.SalesOrder
{
key SalesOrder,
SalesOrderType,
SalesOrganization,
DistributionChannel,
OrganizationDivision,
DeliveryStatus,
DeletionIndicator,
CreatedByUser,
CreationDateTime,
LastChangedByUser,
LastChangeDateTime,
@ObjectModel.association.type: [#TO_COMPOSITION_CHILD]
_SalesOrderItem
}

Листинг. 9.19. Ракурс CDS для заказа клиента в модели сервисов

Пример: позиция заказа клиента


В Листинге 9.20 показано определение позиции заказа клиента.

@AbapCatalog.sqlViewName: 'ZCSALESORDERITTP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales OrderItem'
@Metadata.allowExtensions: true
@ObjectModel.createEnabled: true
@ObjectModel.updateEnabled: true
@ObjectModel.deleteEnabled: true
define view ZC_SalesOrderItemTP
as selectfrom ZI_SalesOrderItemTP
association [1..1] to ZC_SalesOrderTP as _SalesOrder
on $projection.SalesOrder = _SalesOrder.SalesOrder
association [0..*] to ZC_SalesOrderScheduleLineTP as _
SalesOrderScheduleLine
on $projection.SalesOrder = _
SalesOrderScheduleLine.SalesOrder
and $projection.SalesOrderItem = _
SalesOrderScheduleLine.SalesOrderItem
{
key SalesOrder,
key SalesOrderItem,
Product,
OrderQuantity,
OrderQuantityUnit,
NetAmount,
TransactionCurrency,
CreatedByUser,
CreationDateTime,
LastChangedByUser,
LastChangeDateTime,
@ObjectModel.association.type: [#TO_COMPOSITION_PARENT,
#TO_COMPOSITION_ROOT]
_SalesOrder,
@ObjectModel.association.type: [#TO_COMPOSITION_CHILD]
_SalesOrderScheduleLine
}

Листинг. 9.20. Ракурс CDS для позиции заказа клиента в модели сервисов

Пример: график поставок по заказу


клиента
В Листинге 9.21 показано определение графика поставок по заказу клиента.

@AbapCatalog.sqlViewName: 'ZCSALESORDERSLTP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales OrderScheduleLine'
@Metadata.allowExtensions: true
@ObjectModel.createEnabled: true
@ObjectModel.updateEnabled: true
@ObjectModel.deleteEnabled: true
define view ZC_SalesOrderScheduleLineTP
as selectfrom ZI_SalesOrderScheduleLineTP
association [1..1] to ZC_SalesOrderTP as _SalesOrder
on $projection.SalesOrder = _SalesOrder.SalesOrder
association [1..1] to ZC_SalesOrderItemTP as _SalesOrderItem
on $projection.SalesOrder = _SalesOrderItem.SalesOrder
and $projection.SalesOrderItem = _SalesOrderItem.SalesOrderItem
{
key SalesOrder,
key SalesOrderItem,
key SalesOrderScheduleLine,
DeliveryDate,
OrderQuantity,
OrderQuantityUnit,
CreatedByUser,
CreationDateTime,
LastChangedByUser,
LastChangeDateTime,
@ObjectModel.association.type: [#TO_COMPOSITION_ROOT]
_SalesOrder,
@ObjectModel.association.type: [#TO_COMPOSITION_PARENT]
_SalesOrderItem
}

Листинг. 9.21. Ракурс CDS для графика по ставок по заказу клиента в модели сервисов

Создание сервиса OData (раздел 9.4.2)

Сервис OData
Самым простым способом создания сервиса OData из модели сервисов, определённой в
предыдущем разделе, является использование аннотации @OData.publish: true.

При добавлении этой аннотации в корневой ракурс CDS модели сервисов


соответствующий сервис OData создаётся на базе модели сервисов. Он помечается
небольшим маркером рядом с аннотацией. Если установить поверх этого маркера курсор,
появится информационное окно, показанное на Рис. 9.19. Отсюда можно напрямую
запустить URL сервиса. Также сервис OData можно определить с помощью построителя
сервисов в SAP Gateway (транзакция SEGW), но эту процедуру здесь мы рассматривать не
будем.

Рис. 9.19. Создание сервиса OData с помощью CDS

Чтобы сервис OData можно было вызвать с помощью клиента REST или OData (например,
тестового клиента SAP Gateway), он должен быть явно активирован с использованием
транзакции /IWFND/ MAINT_SERVICE (активация сервисов и управление ими).

Активация сервиса OData


В зависимости от настроек системы сервис OData активируется в бэкэнд-системе
(локальная среда SAP Gateway) или в системе фронтэнд-сервера (хаб SAP Gateway).

Для получения дополнительной информации о SAP Gateway перейдите на портал SAP


Help Portal и выполните поиск названию SAP Gateway Foundation (SAP_GWFIND), см.
http://s-prs.co/ v482203.

Метаданные OData
Созданный таким образом сервис теперь содержит все метаданные, которые можно
получить из модели сервисов на базе CDS. Например, некоторые аннотации CDS
переводятся напрямую в аннотации OData с соответствующим обогащением модели.
Таким образом, каждый ракурс CDS в OData становится сущностью OData
соответствующего типа, которая содержит поля ракурса CDS в виде свойств OData с
именем и типом, а также аналогичной информацией по ключу. Мэппинг привязок CDS
выполняется как мэппинг привязок OData или наборов привязок OData и свойств
навигации OData. Поскольку модель транзакционных объектов в дополнение к CDS
содержит действия, определённые в BOPF, их также необходимо вывести. Это
выполняется автоматически. Мэппинг действий, определённых в BOPF, выполняется как
мэппинг операций импорта функции (в OData V2). Для выбора действий, которые будут
выводиться через сервис OData, используется аннотация @ObjectModel.delegatedAction.

Внешние ключи, справки по вводу и


тексты
Помимо фактической транзакционной модели сервисов при создании сервисов OData вы
получаете следующие преимущества. Привязки внешних ключей и аннотации к справкам
по вводу также оцениваются. Для справок по вводу создаются соответствующие типы и
наборы сущностей OData с аннотациями. Привязки текстов оцениваются для всех
созданных наборов сущностей OData. Текст включается в виде дополнительного свойства
OData в релевантном типе сущности.

С помощью исполнимого на данный момент сервиса OData можно протестировать наше


приложение в клиенте REST или OData, например, в клиенте SAP Gateway (транзакция
/IWFND/GW_CLIENT).

Определение вычисляемых полей


(раздел 9.4.3)
Виртуальные элементы
Как было сказано в Раздел 9.9.3, в модель данных может потребоваться включить поля,
которые не являются сохранёнными, особенно в среде транзакционных приложений. Это
могут быть, например, преобразованные поля, которые используются для упрощённого
или дополнительного представления в пользовательском интерфейсе. В отличие от
модели объектов в модели сервисов можно добавлять такие поля и заполнять их
значениями с использованием реализации ABAP. Для этого определите поле в
соответствующем ракурсе CDS модели сервисов со специфичной для вида константной и
добавьте следующие аннотации:

 @ObjectModel.virtualElement: true
 @ObjectModel.virtualElementCalculatedBy:’...’

Первая аннотация определяет поле как виртуальный элемент, а вторая аннотация


определяет реализующий класс, который используется для корректного заполнения поля
во время выполнения. Реализующий класс должен реализовать интерфейс
IF_SADL_EXIT_ CALC_ELEMENT_READ. В методе GET_CALCULATION_INFO
определяются поля собственной сущности, необходимые для вычисления, чтобы данные
можно было считать из базы данных и использовать для вычисления при отсутствии
явного запроса от пользователя. После считывания данных в методе CALCULATE данные
становятся доступными. После этого их можно расширить с помощью поля, значение
которого здесь требуется вычислить. Виртуальное поле по определению не может быть
готовым для ввода и должно быть указано как доступное только для чтения. Поэтому для
него необходимо указать аннотацию @ObjectModel.readOnly: true, как описано в Раздел
3.9.3.

Ограничение для вычисляемых полей в ABAP

Поскольку виртуальные элементы также формально определяются в ракурсе CDS, к


этим полям можно применить функции базы данных. Однако это нецелесообразно,
поскольку значения вычисляются на ABAP, а на уровне базы данных имеется только
одно постоянное значение. Это влияет на такие операции базы данных, как поиск,
фильтрация, сортировка и т.  д. При создании сервиса OData характер виртуальных
элементов учитывается автоматически, а соответствующие свойства OData в
типах сущностей OData выводятся как недоступные для поиска, фильтрации и
сортировки.

Пример: виртуальный элемент


Теперь пример необходимо расширить на уровне позиции заказа клиента и включить в
качестве примера такое поле. Поэтому выполните расширение модели, как показано
в Листинге 9.22.


@ObjectModel.readOnly: true
@ObjectModel.virtualElement: true
@ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_F_
SALESORDERITEM'
cast( ' ' as boole_d preserving type ) as OrderIsFreeOfCharge,

Листинг. 9.22. Ракурс CDS для заказа клиента в модели сервисов с виртуальным
элементом

В реализации этого поля значение устанавливается с помощью стандартных средств


ABAP. В примере в Листинге 9.23 поле NETAMOUNT определено как обязательное поле
для вычисления. Теперь в рамках непосредственно вычисления проверяется, равно ли
значение 0 с установкой значения в виртуальном поле ORDERISFREEOFCHARGE (в
данном случае).

METHOD if_sadl_exit_calc_element_read~get_calculation_info.
INSERT CONV #('NETAMOUNT')
INTO TABLE et_requested_orig_elements.
ENDMETHOD.
METHOD if_sadl_exit_calc_element_read~calculate.
LOOP AT it_original_data
ASSIGNING FIELD-SYMBOL(<ls_salesorderitem>).
ASSIGN COMPONENT 'NETAMOUNT'
OF STRUCTURE <ls_salesorderitem>
TO FIELD-SYMBOL(<lv_netamount>).
CHECK sy-subrc = 0.
CHECK <lv_netamount> IS INITIAL.
ASSIGN COMPONENT 'ORDERISFREEOFCHARGE'
OF STRUCTURE ct_calculated_data[ sy-tabix ]
TO FIELD-SYMBOL(<lv_orderisfreeofcharge>).
CHECK sy-subrc = 0.
<lv_orderisfreeofcharge> =abap_true.
ENDLOOP.
ENDMETHOD.

Листинг. 9.23. Реализация в среде ABAP с вычислением виртуального элемента

Сортировка и фильтрация виртуальных элементов

Ограничения по сортировке и фильтрации можно снять, если возможен простой и


уникальный мэппинг этих операций по постоянным полям в ракурсе CDS. Правила
мэппинга можно хранить в аннотированных подпрограммах ABAP. Для получения
дополнительной информации см. стандартную документацию SAP.

Определение приложения SAP Fiori


(раздел 9.4.4)
Элементы SAP Fiori
В конце главы совершим краткий экскурс в мир приложений SAP Fiori. У нас уже
имеются обогащённые метаданные, доступные через сервисы OData, которые можно
использовать в реализации приложений пользовательского интерфейса. Через элементы
SAP Fiori (см. http://s-prs.co/v482204) SAP реализует основанный на шаблонах подход с
эффективным использованием этих метаданных для простой реализации приложений
пользовательского интерфейса. С помощью CDS и инфраструктуры ABAP можно
определить дополнительные специфичные для пользовательского интерфейса метаданные
посредством аннотаций CDS в модели сервисов CDS. Эти метаданные предоставляются
как отдельные метаданные посредством OData. В пользовательском интерфейсе SAP Fiori
на базе элементов SAP Fiori с помощью этих метаданных можно создавать исполняемые
приложения SAP Fiori и тестировать их всего за несколько дополнительных шагов.
Аннотации UI
Здесь для раскрытия темы мы используем ограниченный набор аннотаций, выбранных из
большого пула аннотаций UI. Итак, нам требуется определить, какие поля будут доступны
в стандартном представлении для каждой сущности в виде таблицы или формуляра, а
также в каком порядке эти поля будут отображаться. Также необходимо указать, какие
поля будут по умолчанию предоставляться как поля выбора для фильтрации в отчёте со
списком. Разумеется, все выводимые поля доступны в сервисе OData, поэтому
пользователь может добавлять поля или устанавливать последовательность с помощью
возможных опций персонализации.

Рассмотрим подробнее выбранные аннотации.

 @UI.selectionField

Эта аннотация и её элементы определяют представление полей выбора.

 @UI.lineItem

Эта аннотация и её элементы определяют представление сущности в табличном


формате.

 @UI.identification

Эта аннотация и её элементы определяют представление экземпляра сущности на


базе одной формы.

Соответствующая последовательность определяется элементом position. Элемент


importance используется для объявления важности поля. Это нужно, чтобы скрывать
менее важные поля в пользовательском интерфейсе в случае недостатка места, например,
на экране планшета или мобильного устройства (адаптивный дизайн [responsive design]).

Следующие аннотации используются для дополнительной настройки представления на


странице подробных данных:

 @UI.headerInfo;
 @UI.facet;
 @UI.fieldGroup.

Мы не будем рассматривать их здесь подробно. Наконец, в пользовательский интерфейс в


виде кнопки также требуется добавить действие, определённое в Раздел 6.9.3. Для этого
существует специальная аннотация CDS. Если действие должно отображаться в списке,
просто добавьте следующую аннотацию к одному из аннотированных полей:

@UI.lineItem: {

type:#FOR_ACTION,

dataAction:’BOPF:<name of action>’,

label: ‘<label of action button>’ }


Если действие должно отображаться на странице подробных данных, используйте
следующую аннотацию:

@UI.identification: {

type:#FOR_ACTION,

dataAction:’BOPF:<name of action>’,

label: ‘<label of action button>’ }

Пример: расширение метаданных


Как описано в главе 3, для определения аннотаций, специфичных для пользовательского
интерфейса, используется расширение метаданных. Для конкретного сервиса OData
расширение метаданных добавляется в модель CDS, как показано в Листинге 9.24 для
заказа клиента.

@Metadata.layer: #CUSTOMER
@UI.headerInfo.typeName: 'Sales Order'
@UI.headerInfo.typeNamePlural: 'Sales Orders'
@UI.headerInfo.title.label: 'Sales Order'
@UI.headerInfo.title.value: 'SalesOrder'
annotate view ZC_SalesOrderTP with
{
@UI.identification: [{position: 10, importance: #HIGH},
{type:#FOR_ACTION, position: 0,
dataAction: 'BOPF:DELETE',
label: 'Delete SalesOrder' }]
@UI.lineItem: [{position: 10, importance: #HIGH}]
@UI.fieldGroup: [{qualifier: 'GeneralData', position: 10,
importance: #HIGH }]
@UI.selectionField: [{position: 10}]
SalesOrder;
@UI.identification: [{position: 20, importance: #HIGH}]
@UI.lineItem: [{position: 20, importance: #HIGH}]
@UI.fieldGroup: [{qualifier: 'GeneralData', position: 20,
importance: #HIGH }]
@UI.selectionField: [{position: 20}]
SalesOrderType;
@UI.identification: [{position: 20, importance: #HIGH}]
@UI.lineItem: [{position: 20, importance: #HIGH}]
@UI.fieldGroup: [{qualifier: 'GeneralData', position: 30,
importance: #HIGH }]
@UI.selectionField: [{position: 20}]
SalesOrganization;
@UI.identification: [{position: 30, importance: #HIGH}]
@UI.lineItem: [{position: 30, importance: #HIGH}]
@UI.fieldGroup: [{qualifier: 'GeneralData', position: 40,
importance: #HIGH }]
@UI.selectionField: [{position: 30}]
DistributionChannel;
@UI.identification: [{position: 40, importance: #HIGH}]
@UI.lineItem: [{position: 40, importance: #HIGH}]
@UI.fieldGroup: [{qualifier: 'GeneralData', position: 50,
importance: #HIGH }]
@UI.selectionField: [{position: 40}]
OrganizationDivision;
@UI.identification: [{position: 50, importance: #HIGH}]
@UI.lineItem: [{position: 50, importance: #HIGH}]
@UI.selectionField: [{position: 50}]
DeliveryStatus;
@UI.identification: [{position: 60, importance: #LOW}]
@UI.lineItem: [{position: 60, importance: #LOW}]
DeletionIndicator;
@UI.identification: [{position: 70, importance: #LOW }]
@UI.fieldGroup: [{qualifier: 'AdminData', position: 10,
importance: #LOW }]
CreatedByUser;
@UI.identification: [{position: 80, importance: #LOW}]
@UI.fieldGroup: [{qualifier: 'AdminData', position: 20,
importance: #LOW }]

CreationDateTime;
@UI.identification: [{position: 90, importance: #LOW}]
@UI.fieldGroup: [{qualifier: 'AdminData', position: 30,
importance: #LOW }]
LastChangedByUser;
@UI.identification: [{position: 100, importance: #LOW}]
@UI.fieldGroup: [{qualifier: 'AdminData', position: 40,
importance: #LOW }]
LastChangeDateTime;
}

Листинг. 9.24. Расширение метаданных CDS для заказа клиента с аннотациями UI 

Определение приложения SAP Fiori


Для создания приложения SAP Fiori используется среда SAP Web IDE (см. http://s-prs.co/
v482205) на платформе SAP Cloud Platform (см. http://s-prs.co/v482206) с подключением к
бэкэнд-системе или хабу SAP Gateway. Указанные аннотации пользовательского
интерфейса предоставляют приложение SAP Fiori, в котором аннотированные поля
отображаются по умолчанию. Здесь можно создавать, изменять и удалять документы с
помощью определённых действий. Начальный список с широкими возможностями
фильтрации и выбора похож на представленный на Рис. 9.20. Кроме того, для ввода новых
заказов клиента можно использовать кнопку + над списком, как показано на этом рисунке.
Рис. 9.20. Отчёт со списком элементов SAP Fiori

Для полей выбора также доступны справки по вводу, описанные в главе 10 (см. Рис. 9.21).
Рис. 9.21. Страница объекта с элементами SAP Fiori для ввода заказа

На Рис. 9.22 показано возможное представление пользовательского интерфейса на базе


формуляров при переходе в заказ клиента. Поскольку вы разрешили редактирование в
модели сервисов и указали действие, определённое для удаления в аннотациях UI, кнопки
для этих операций будут доступны (на экране сверху справа).
Рис. 9.22. Страница объекта с элементами SAP Fiori с кнопками «Редактировать» (Edit) и
«Удалить» (Delete)

Дополнительные ресурсы

Для получения дополнительной информации о SAPUI5 см. SAPUI5: полное руководство


(SAPUI5: Comprehensive Guide) Кристиана Гебельса (Christiane Goebels), Дениз
Непрауниг (Denise Nepraunig) и Тило Зиделя (Thilo Seidel) по адресу www. sap-
press.com/3980, а также Начало работы с SAPUI5 (Getting Started with SAPUI5)
Мирослава Антоновича (Miroslav Antolovic) по адресу www.sap-press.com/3565.

Заключение (раздел 9.5)
В этой главе показано, как можно эффективно использовать CDS для определения и
реализации транзакционных приложений. Здесь обзорно рассматривается транзакционная
среда выполнения, а также способы активации транзакционной среды выполнения для
приложения, настройки статических и динамических свойств, реализации эксклюзивных
блокировок и проверок полномочий, реализации бизнес-логики в виде побочных
эффектов и добавления действий. Кроме того, мы изучили возможности вывода
приложения в виде сервиса OData и размещения поверх него простого пользовательского
интерфейса SAP Fiori.

Следующая глава посвящена функциональности поиска на базе CDS.

Авторы

Ренцо Колле (Renzo Colle) отвечает за модель программирования SAP S / 4HANA в


группе центральной архитектуры. Он изучал бизнес-математику в Университете Карлсруэ
и проработал в SAP более 20 лет в самых разных областях. Изобретатель платформы
обработки бизнес-объектов (BOPF).

Ральф Дентцер (Ralf Dentzer) несколько лет работал в группе по центральной


архитектуре пакета SAP S/4HANA, уделяя особое внимание использованию основных
служб данных в SAP S/4HANA. Он присоединился к SAP более 20 лет назад. Он
разработал HR-приложения для SAP R/3, SAP ERP и SAP Business ByDesign.
Ян Храстник (Jan Hrastnik) является членом команды разработчиков архитектуры
пакета SAP S / 4HANA, где он сосредоточен на модели виртуальных данных и
использовании основных служб данных в приложениях ABAP. Он работал в различных
областях разработки SAP более 15 лет.

Корректура

Олег Точенюк — занимал должности консультанта по SAP ММ в различных компаниях,


с 1997 года, занимался внедрением модулей FI-FM (контроль исполнения бюджета),
Управления материальными потоками (ММ), Управление складом СУС (WMS), был
консультантом по интеграции MM<->ТОРО, занимался разработками расширений
системы на языке ABAP. Связаться с Олегом можно по адресу uukrul@hotmail.com.