convert-ui5-to-fiori-elements について
従来の UI5 JavaScript アプリから UI の特徴を抽出し、Fiori Elements V4 のアノテーションとリストレポート、オブジェクトページを生成するワークフロースキルです。テンプレートで表現できない動作には拡張機能を使います。
主な機能
- 01旧アプリの機能から UI アノテーションを導出
- 02RAP プロジェクションにアノテーションを適用
- 03リストレポートとオブジェクトページを生成
- 04拡張機能で独自動作を実装
- 05SAP のアノテーション資料を参照
活用シーン
- 01旧 UI5 アプリを Fiori Elements V4 に再構築
- 02旧画面の列、検索、並べ替え、操作を再現
MCP 対応
SAP Fiori MCP サーバーを使って Fiori Elements プロジェクトを生成します。また、アノテーションパターンの検索に sap-docs MCP を使う手順も記載されています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ arc-mcp/ arc-1 --skill convert-ui5-to-fiori-elementsインストール後、Claude Code で/convert-ui5-to-fiori-elementsを入力して読み込まれたか確認します。
詳細
レガシー UI5 JS アプリを Fiori Elements V4 に変換(アノテーション優先)
RAP CDS プロジェクション上の @UI.* アノテーションを使って、リストレポートとオブジェクトページからなる Fiori Elements V4 アプリを生成します。バックエンドのアノテーションは、レガシー UI5 アプリの実際の機能(列、検索、並べ替え、フォーマッター、アクションボタン、タブ構成)をもとに導き出し、FE アプリでユーザーに見える仕様を再現します。FE テンプレートでは表現できないカスタム動作は、拡張 API で接続します。
このスキルは、RAP バックエンドの完成後に選択できる、並行する 2 つの UI パスのうちの 1 つです。ターゲットのアーキテクチャが Fiori Elements V4(アノテーション駆動、カスタムコードは最小限)なら、こちらを選んでください。ターゲットが フリースタイル TypeScript(カスタムコントローラー、手動バインディング)なら、代わりに modernize-ui5-app.md を選んでください。どちらも、同じレガシー JS アプリと同じ V4 RAP サービスから始めます。
migrate-segw-to-rap.md (backend: SEGW V2 → RAP V4)
│
┌─────────────┴─────────────┐
▼ ▼
modernize-ui5-app.md convert-ui5-to-fiori-elements.md
(freestyle TS) (Fiori Elements V4)
このスキルは、次の前提に依存します。
migrate-segw-to-rap.mdによって、V4 RAP サービスが有効化されていること(CDS ルートとプロジェクション、BDEF、SRVD、SRVB が公開され、V4 ルーティンググループが/n/IWFND/MAINT_SERVICEに登録されていること)。- レガシーアプリ(
<source_app>/)を引き続き読み取れること。Phase 1 ではレガシーアプリ自体を変更せず、その機能を調査します。
modernize-ui5-app.mdとは独立しています。 このスキルでは、最新の TS アプリが存在している必要はありません。ユーザーに見える機能の信頼できる唯一の情報源はレガシーアプリです。FE アプリでは、アノテーションと拡張機能を通じて、それらの機能を直接再現します。
ドメインの例。 アノテーションのテンプレートでは、例示として
Project → Tasks → TimeEntriesのドメインを使用します。ユーザーのエンティティに合わせて置き換えてください。LLM がすべてのプロジェクション、エンティティ、フィールドの識別子を書き換え、V4 サービスに合わせます。
標準的なアノテーションのリファレンス。 このスキルでは、
@UI.*/@ObjectModel.*/@Common.*アノテーションのパターンを示す信頼できる情報源として、ABAP RAP Fiori Feature Showcase(SAP-samples/abap-platform-fiori-feature-showcase)を参照します。レガシー UI の機能をアノテーションでどう表現するか不明な場合は、その機能の Search Term(例:#OPHeaderAction、#LineItemHighlight、#HeaderInfo、#ActionInLineItem)を使ってmcp__sap-docs__searchで Showcase を検索してください。Showcase は、このスキル内の各アノテーションが対応する、正確な情報を網羅したカタログです。
アノテーションを調べるための mcp__sap-docs__search の使い方(最初にお読みください)
このスキルでは、代表的なアノテーションパターンをいくつか本文中に示します。それらは出発点であり、カタログのすべてではありません。 明示的に説明されていない項目(別の視覚表現、動的な機能制御、チャート、値ヘルプ、セマンティックキー、複数レベルの OP ルーティング、ドラフト固有の UI 動作、7.58 固有の構文上の問題など)は、推測する前に mcp__sap-docs__search で調べてください。 この MCP では、SAP が管理する信頼できるリファレンスをインデックス化し、最新の Showcase タグとリリースごとのドキュメント(758 の新機能、クラウドとの違いなど)も収録しています。このスキルの本文だけでは、そうした情報を常に最新の状態に保てないためです。
知っておくべき標準ライブラリ
| ライブラリ ID | 内容 |
|---|---|
/abap-fiori-showcase | SAP-samples/abap-platform-fiori-feature-showcase — オンプレミスの RAP + FE V4 カタログです。すべてのパターンに、#HeaderInfo、#LineItemHighlight、#OPHeaderAction、#OPTable、#DataFieldForAction、#SemanticKey などの検索語がタグ付けされています。このスキルの 7.58 に正確に対応したベースラインです。 |
/cap-fiori-showcase | SAP-samples/fiori-elements-feature-showcase — CAP/CDS V4 の対応版です。CAP 側から見た同じ概念的なパターンを収録しています。ABAP ショーケースのタグに必要なバリエーションが含まれていない場合に役立ちます。特に FE マニフェストのレイアウト(layouts_ChildEntities*.cds、#Subpages、#InboundNav)を調べる際に便利です。 |
/abap-docs-standard | 公式 ABAP キーワードドキュメント(オンプレミス)です。構文(FOR BEHAVIOR OF、仮想要素、プロジェクション BDEF のルール)、リリース固有の機能(7.58 で利用できる機能を示す ABENNEWS-758-RESTFUL)、RAP の構成要素に関する詳しい理論を確認するための決定版です。 |
/abap-docs-cloud | 上記と同じ内容のクラウド/BTP 版です。クラウド専用に見える機能がある場合に、オンプレミスの 7.58 でも利用できるか確認するのに役立ちます。 |
/sap-help(オンライン) | SAP Help の全コンテンツです。SAPUI5 マニフェストの設定、FE テンプレートのランタイムの詳細、内部ナビゲーションの設定を調べるのに最適です。includeOnline=true が必要です。 |
/abap-cheat-sheets | 現行の構文バリエーションを含む、実用的な RAP/ABAP のスニペットです。 |
検索手順 — アノテーションに関する質問すべてに適用
- ユーザーに何が表示されるかを特定します:「色付きチップとしてのステータス」、「行をクリック → 子詳細ページ」、「固定値でフィルター」などです。
- ハッシュタグでショーケースを検索します — ほとんどのパターンには、Markdown 内にそのままタグが付いています。
mcp__sap-docs__search(query="#TagName") // exact tag lookup mcp__sap-docs__search(query="<visual description>") // semantic fallback - 最も関連性の高い検索結果のパターン全体を取得します。
mcp__sap-docs__fetch(id="/abap-fiori-showcase/<section>#<tag>") - ユーザーのエンティティに合わせて調整します — ショーケースでは
/DMO/FSA_R_RootTPなどが使われています。ユーザーのプロジェクション名に置き換えてください。 - 対象リリースでオンプレミスのパターンが拒否された場合は、別の観点から再検索します:
- ABAP クラスによる計算を伴う仮想要素については、
/abap-docs-standard/ABENCDS_PROJ_VIEW_VIRTUAL_ELEMENT(および例ABENCDS_PROJ_VIEW_VIRTEL_ABEXA)を確認します。 - リリースに依存する機能については、
/abap-docs-standard/ABENNEWS-<release>-RESTFUL(例:ABENNEWS-758-RESTFUL)を確認します。 - 同じ概念を CAP の別の表現で確認するには、
/cap-fiori-showcaseを検索します。 - DDLS プロジェクションでエンティティレベルのアノテーションが拒否された場合は、代替手段として DDLX の
annotate viewを使用します(Run 7 の証拠:7.58 では@UI.facet、@UI.selectionFields、ヘッダーのFOR_ACTIONが DDLX 経由で処理されます)。
- ABAP クラスによる計算を伴う仮想要素については、
スタータータグの手がかり(網羅的ではありません。さらに検索してください)
ショーケース内の具体的なアノテーションパターンにたどり着く検索語の参照です。それぞれが入口です。リリースに対応する正式な構文を確認するには、内容全体を取得してください。
| 必要なもの | 検索語/ドキュメントの開始点 |
|---|---|
| リスト行の色付きステータス/重要度 | #LineItemHighlight、criticality: 'CriticalityCode'、@UI.Criticality |
| 計算ロジックを伴う重要度(実際の列ではないもの) | /abap-docs-standard/ABENCDS_PROJ_VIEW_VIRTUAL_ELEMENT、例:ABENCDS_PROJ_VIEW_VIRTEL_ABEXA。また、@ObjectModel.virtualElementCalculatedBy: 'ABAP:<class>' |
| ヘッダーデータポイント/ステータスインジケーター | #HeaderFacet、#KeyValue、#DataPointProgress、@UI.dataPoint |
| 子エンティティ用のオブジェクトページテーブル | #OPTable、子プロジェクション上の@UI.lineItem、type: #LINEITEM_REFERENCEを指定した@UI.facet、targetElement: '_AssocName' |
| ある OP から別の OP へのドリル(例:Project → Task → TimeEntry) | #OPTable(エントリー)、cap-fiori-showcase/app/listreport-objectpage/layouts_ChildEntities1.cdsなど(サブページのレイアウト)、マニフェストのルーティング形式については SAPUI5 の 「Configuring Internal Navigation」(sap-help) |
| ファセット間のページ内ナビゲーション | #InboundNav、targetSections、@UI.facetのnavigationプロパティ |
| アクションボタン — OP ヘッダー | #OPHeaderAction、type: #FOR_ACTION、DataFieldForAction |
| アクションボタン — LR テーブルのツールバー | #ActionInLineItem、#WithAction |
| ソート+フィルターバー | #SelectionFields、#PresentationVariant、@UI.selectionFields |
| フィールド横断検索 | #Search、@Search.searchable、@Search.defaultSearchElement |
| セマンティックキー(テーブル内で強調表示/太字) | #SemanticKey、@ObjectModel.semanticKey |
| 値ヘルプ/固定値リスト | #ValueHelp、@Consumption.valueHelpDefault、@ObjectModel.text.element |
| 動的 CRUD(行の状態に応じて編集/削除を非表示/表示) | #DynamicCRUD、@UI.updateHidden、@UI.deleteHidden、BDEF features: instance |
| ドラフト+UI 固有の設定 | #DraftHandling、編集可能な修飾子を指定した@UI.lineItem、アクションキーワード( precheck ) |
| 副作用/アクション実行時の再読み込み | #SideEffects、@Common.SideEffects |
| BDEF アクションのシグネチャのバリエーション(precheck、factory、copy) | /abap-docs-standard/ABENBDL_ACTION、#OPCopyAction、action ( precheck ) <name> |
| 7.58 の機能境界 | /abap-docs-standard/ABENNEWS-758-RESTFUL+ABENNEWS-758-CDS_BDL |
アンチパターン
- このスキルのサンプルコードを絶対的な正解として扱わないでください。 これは、ある時点で書かれた説明用のサンプルです。正しい情報はショーケースにあります。
- 別のリリースのショーケース例を、確認せずに貼り付けないでください。 BTP-Cloud ブランチにある
#DataFieldForActionの例では、クラウド専用のキーワードが使われている場合があります。7.58 では、オンプレミスのmainブランチを安全な基準としてください。 - SAPUI5 の内部ナビゲーションのドキュメントを参照せずに、FE のルーティング/マニフェスト項目を手作業で記述しないでください。 形式はテンプレートとリリースによって異なります。実行時の失敗から逆算するより、
sap-helpから導き出すほうが簡単です。 - 最初に見つかった有効化失敗の症状を最終回答にしないでください。 Run 7 では、1 つの仕上げ項目に対して、4 つの異なるレイヤーで 4 つの異なる阻害要因に遭遇しました。いずれの場合も、
mcp__sap-docs__searchを使って追加検索すれば、ロールバックする前に代替案が見つかったはずです。検索を 1 回追加するコストは 5 秒です。不要なロールバックには 10 分以上かかります。
これが独立したスキルである理由
Fiori Elementsはコード変換ではなく、削除+移設です。フリースタイルアプリの大半は、CDSアノテーションを解釈するFEテンプレートに置き換えられます。このスキルの主な役割は次の3つです。
- レガシーアプリでユーザーに表示される機能から適切な
@UI.*アノテーションを導き出し、FEで同等のUXをレンダリングできるようにします。 - それらのアノテーションをRAP CDSプロジェクション(SRVBが公開するサービス)に適用します。
- SAP Fiori MCP server(
@sap-ux/fiori-mcp-server)を使ってFEのリストレポート+オブジェクトページのプロジェクトを生成し、FEテンプレートで表現できない機能には拡張機能を組み込みます。
スマートな既定値(調査前に確認せず、暗黙に適用)
| 設定 | 既定値 | 根拠 |
|---|---|---|
| レガシーアプリ | <source_app>/ | フリースタイルのJSアプリです。読み取り専用で、Phase 1で機能一覧を作成するために調査します。FEアプリが再現すべき、ユーザーに表示されるすべての動作の信頼できる情報源です。 |
| FEターゲットアプリ | <fe_app>/ — ユーザーがパスを指定しない場合の既定名はmodern-fe-app/です(ワークスペースのパターンlegacy-ui5-app/ → modern-ui5-app/ → modern-fe-app/に合わせます) | Fiori MCPはここに生成します。フォルダーは存在し、空(または空のサブフォルダーのみ)である必要があります。 |
| FEフロアプラン | BOに明確なルートと子ファセットがある場合は、リストレポート+オブジェクトページ(LROP V4) | 典型的なRAPのコンポジションルート+子要素に自然に対応します。OVPはユーザーが明示的に希望した場合に限ります。 |
| テンプレート | lropv4 | ユーザーが別のものを希望しない限り、既定値です。 |
| ジェネレーター | list_functionalities → get_functionality_details → execute_functionalityの順に実行するSAP Fiori MCP server(@sap-ux/fiori-mcp-server) | SAPのファーストパーティツールであり、FE V4のパターンをネイティブに理解します。 |
| アプリの名前空間 | <source_namespace>.fe | レガシーアプリとFEアプリを区別しやすくします(別の方法としてmodernize-ui5-appも実行した場合は、モダンなTSアプリも区別できます)。 |
| UI5バージョン | ユーザーが指定しない限り、最新の1.xリリース(例:1.147.2) | LTSトラックで、最新のFE V4機能を利用できます。 |
| 言語 | TypeScript | モダンな既定値です。拡張ファイルでは型安全なAPIを使用します。 |
| OData V4サービスURL | システムのHTTPSポート上のSRVD直結パスを優先します:https://<host>:<https-port>/sap/opu/odata4/sap/<srvb>/srvd/sap/<srvb>/0001(例:https://a4h.marianzeis.de:50001/sap/opu/odata4/sap/zui_dm_projects_o4/srvd/sap/zui_dm_projects_o4/0001)。SRVD直結パスに到達できない場合のみ、Gatewayハブパスhttp://<host>:<http-port>/sap/opu/odata4/sap/<srvb>/srvd_a2x/sap/<service>/0001にフォールバックします。 | Run 5とRun 6では、7.5xシステムでSRVD直結パスが/n/IWFND/MAINT_SERVICEへの登録なしで動作することを確認しました。ハブパスではルーティンググループの手動設定が必要です。 |
| メインエンティティ | SRVBが公開するルートエンティティのエイリアス(例:define root view entity ... alias <X>のエイリアス) | LR+OPフロアプランは単一のエンティティをルートとします。 |
| アノテーションの配置場所 | SAPWrite update DDLSを使ってCDS内に配置します。FEアプリ内のローカルアノテーションファイルには配置しません。 | アノテーションはサービスに属します。FEアプリは$metadataを通じてアノテーションを読み取ります。RAPにバインドされたアプリでは、ローカルアノテーションファイルはアンチパターンです。 |
| 拡張言語 | TypeScript(コントローラー拡張機能) | ワークフローの他の部分と統一します。 |
| 検証 | mcp__SAPUI5_MCP_Server__run_ui5_linter+run_manifest_validation+tsc --noEmitがすべて成功すること | 必須の受け入れ基準です。 |
| 受け入れ条件 | FEアプリがV4サービスに対してエンドツーエンドで動作すること。ブラウザーでのスモークテストでPhase 1に記録したすべての機能を確認し、アノテーションまたは拡張フックを通じて再現します。 | 具体的な成果物です。 |
入力
ユーザーが指定する項目:
- パス:機能の洗い出しに使用するレガシーアプリのパス(デフォルト:
<source_app>/)。読み取り専用です。 - パス/名前:FE アプリのパス(デフォルト:
<fe_app>/)。 - OData V4 サービス URL —
migrate-segw-to-rapの SRVB 出力から取得します。必須です。 - ルートエンティティエイリアス(例:
Project)。デフォルト:SRVB の$metadataから推測します。 - アプリの名前空間(デフォルト:
<source_namespace>.fe)。 - トランスポート:CDS アノテーションの書き込みに使用します(デフォルト:
migrate-segw-to-rapで使用したものと同じトランスポート、またはSAPTransport(action="create")で自動作成)。 - UI5 バージョン(デフォルト:最新の 1.x)。
レガシーアプリのパスと V4 URL だけが指定された場合は、スマートデフォルトを適用し、書き込みを行う前に、Phase 3 でユーザーに計画を提示して ok を得ます。
Phase 0 — 事前確認
0a. RAP V4 サービスが稼働しており、バインド可能である
SAPManage(action="probe")
rap.available == true であることを確認します。
SAPRead(type="SRVB", name="<V4_SRVB>")
SRVB が存在し、有効であることを確認します。存在しない、または無効な場合は、"V4 サービスバインディング <V4_SRVB> が存在しないか、無効です — まず migrate-segw-to-rap.md を実行してください。" と表示して停止します。
Bash: curl -s -o /tmp/svc_metadata.xml -w "%{http_code}\n" "<V4_service_URL>/\$metadata?sap-client=<client>"
200 OK であることを確認します。まず SRVD 直通パスを試します(HTTPS ポート + /srvd/sap/<srvb>/0001/)。
IWBEP/CM_V4_COS/136 を伴う 403 が返された場合、URL は Gateway ハブのパスを使用しており、ルーティンググループが登録されていません。停止する前に、SRVD 直通 URL パターンに切り替えてください — 直通パスはハブの登録を迂回します。両方の URL パターンが失敗した場合に限り、"サービスグループを /n/IWFND/MAINT_SERVICE で登録" に切り替えてください。
IWBEP/CM_V4_RUNTIME/000(「サービスエイリアスのキャッシュが古い」)を伴う 503 が返された場合は、一度再試行します — これは一時的な Gateway キャッシュの問題です。再試行しても解消しない場合は、403 として扱い、URL パターンを切り替えます。
0b. CDS プロジェクションが読み取り可能かつ書き込み可能である
SAPRead(type="DDLS", name="<root_projection>")
有効なバージョンが返されることを確認します。返されない場合は、"ルートプロジェクションが見つかりません — migrate-segw-to-rap.md の Phase 6 Step 3 を再実行してください。" と表示して停止します。
0c. レガシーアプリが存在し、読み取り可能である
Bash: ls <source_app>/webapp/controller/ <source_app>/webapp/view/
両方のフォルダーにファイルが含まれていることを確認します。いずれかが見つからない場合は、その理由を明示して停止します — アノテーション計画(Phase 1+2)と拡張リスト(Phase 2b)の両方で、レガシーアプリが唯一の信頼できる情報源となります。
0d. SAP Fiori MCP サーバーに接続できる
mcp__fiori-mcp__list_functionalities
この呼び出しが失敗した場合、このチャットでは Fiori MCP サーバーが設定されていません。設定ブロックを提示して停止します:
// .cursor/mcp.json (or equivalent)
{
"mcpServers": {
"fiori-mcp": {
"type": "stdio",
"timeout": 600,
"command": "npx",
"args": ["--yes", "@sap-ux/fiori-mcp-server@latest", "fiori-mcp"]
}
}
}
(出典:github.com/SAP/open-ux-tools の @sap-ux/fiori-mcp-server README。)
任意の補助ツール:生成後のリントとマニフェスト検証には mcp__SAPUI5_MCP_Server__* を使用します。
0e. Connection Manager(任意)
サービス URL を直接指定するのではなく、保存済みの BTP/オンプレミスシステム接続を使用するシナリオでは、Fiori MCP サーバーは Connection Manager for SAP Systems VS Code 拡張機能に依存します。このスキルで使用する直接 URL のフローでは、この拡張機能は不要です — サービス URL は execute_functionality に直接渡されます。
Phase 1 — レガシーアプリのユーザーに見える機能を洗い出す
ここがアノテーション計画の中心です。FE アプリでは、レガシーアプリのユーザーに見えるすべての動作を再現する必要があります。関連するレガシーファイルをすべて読み、機能の一覧を作成します。
1a. レガシーマニフェストを読む
Read: <source_app>/webapp/manifest.json
取得する項目:sap.ui5.routing.routes(ユーザーがアクセスできる URL)、sap.ui5.rootView、sap.app.dataSources、i18n。ルートからナビゲーションツリーがわかり、データソースからレガシーアプリが想定するサービス構造がわかります。
1b. すべてのレガシービューを読む
Bash: ls <source_app>/webapp/view/
Read: <source_app>/webapp/view/<each>.view.xml
各ビューについて、以下を一覧にまとめます。
- ページタイトル(
<Page title=...>から取得)。 - ヘッダーの内容 — ボタンとその条件(例:
enabled="{= ${Status} === 'D'}")。 - リスト/テーブルの列 — 各
<Column>のバインド先フィールド、ソート順、配置。 - 検索フィールド —
liveChangeとplaceholderを含む<SearchField>。 - デフォルトのソート — リストのバインディングにある
sorter句(パスと昇順/降順)。 - アイテムの構造 — 属性、ステータスフィールド、フォーマッター呼び出しを含む
ObjectListItem/ColumnListItem/ObjectHeader。 - タブの構造 —
IconTabBarとIconTabFilterのエントリー(タブ分けされているエンティティ、各タブのカウンターの有無)。 - ナビゲーションハンドラー —
press/selectionChangeのコールバック(行のクリックからナビゲーションへの流れ)。 - カウンター、フッター — 情報表示用ウィジェット(アイテム数、合計など)。
1c. すべてのレガシーコントローラーを読む
Bash: ls <source_app>/webapp/controller/
Read: <source_app>/webapp/controller/<each>.controller.js
各コントローラーについて、以下を一覧にまとめます。
- アクションハンドラー — 各
on<Action>メソッドは何をするか(OData ファンクションインポートの呼び出し、フィルター処理、再バインド、MessageBox の表示など)。 - フィルタリング/検索ロジック — 使用するフィールド、
FilterOperator、バインドパス。 - ファンクションインポートの呼び出し —
oModel.callFunction(...)の呼び出しとそのパラメーターの形式。 - カスタムバリデーション — ファンクションインポートの呼び出し/送信前のチェック。
- カスタムナビゲーション — マニフェストルーターを介さない処理。
- カスタムのクライアントサイド状態 — UI 専用の状態(例:OData 以外のデータを使ったタブカウンター)のために作成された JSONModel。
1d. すべてのレガシーフォーマッターを読む
Read: <source_app>/webapp/model/formatter.js
各フォーマッター関数について、以下を一覧にまとめます。
- フォーマットする内容 — ステータスコードからテキスト、ステータスコードからセマンティック状態(Success/Warning/Error)、日付から短い形式、時間から小数値など。
- コードからテキストへのマッピング — 正確な値を記録します(例:
D → "Draft"、A → "Active"、C → "Closed")。
これらは CDS アノテーションのパターン(@Common.Text と @UI.TextArrangement、@UI.Criticality、値ヘルプコレクションなど)に直接対応します。
1e. 機能一覧を作成する
構造化された一覧をユーザーに出力します。
Feature inventory — <source_app>:
ROOT ENTITY (Project):
Display name (header): Title
Description (sub): ProjectId
Status (criticality): Status field — values D=Draft (Warning) / A=Active (Success) / C=Closed (Neutral)
Sort default: StartDate descending
Search (master): ProjectId, Title (Contains, OR-joined)
Audit fields: Erdat (Created), Ernam (Created by), Aedat (Changed), Aenam (Changed by)
Header button: Approve — enabled when Status == 'D', calls /ApproveProject(ProjectId)
Count footer: "<n> projects" displayed below the list
CHILD ENTITY (Task):
Tab in detail: "Tasks"
Counter: from binding length
Columns: TaskId, Title+Description, Status, Priority, DueDate, AssignedTo, EstimatedHours
Status criticality: Status: D/IP/D/C (Draft/InProgress/Done/Cancelled) — see formatter
Priority criticality: L/M/H (Low/Medium/High) — see formatter
Click behavior: Selecting a task populates the TimeEntries tab
CHILD-OF-CHILD ENTITY (TimeEntry):
Tab in detail: "Time Entries"
Counter: from selected task's TimeEntries length
Columns: EntryId, TaskId, WorkDate, WorkHours, Description, Username
FORMATTERS:
statusText: D → "Draft", A → "Active", C → "Closed"
statusState: D → Warning, A → Success, C → Neutral
taskStatusText: D → "Draft", IP → "In Progress", DN → "Done", CN → "Cancelled"
taskStatusState: same scheme
priorityText: L → "Low", M → "Medium", H → "High"
priorityState: L → Neutral, M → Warning, H → Error
dateShort: custom YYYY-MM-DD
hoursDecimal: two decimal places
FUNCTION IMPORT (V2):
ApproveProject(ProjectId) → translates to RAP action approve_project (already in BDEF)
この一覧がフェーズ 2 の仕様となります。
フェーズ 2 — 機能をアノテーションと拡張機能にマッピングする
一覧内の各項目を、次のいずれかに分類します。
- STANDARD — FE テンプレートが標準でレンダリングする機能(ページネーション、行クリックによるナビゲーション、キーによる検索、基本的な編集、基本的な作成、基本的な削除、ドラフトのサポート)。
- ANNOTATION — CDS プロジェクションに特定の
@UI.*/@Common.*/@ObjectModel.*アノテーションが必要な機能。レガシー機能の多くはここに分類されます。 - EXTENSION — FE テンプレートでは表現できない、本当にカスタムな動作。FE アプリ側のコントローラー拡張が必要です。
2a. アノテーションマップ — 出発点(各パターンを sap-docs で検証)
以下の表はクイックリファレンスであり、決定版のカタログではありません。上記の「mcp__sap-docs__search の使用」セクションにある検索手順を適用して、ご使用のリリースにおける現行の正式な構文を確認してください。特に、以下で ⚠ が付いている項目は必ず確認してください。
| レガシー機能 | アノテーションの出発点+ショーケースタグ |
|---|---|
ヘッダータイトル = Title | @UI.HeaderInfo.title.value: 'Title' — #HeaderInfo |
ヘッダーの説明 = ProjectId | @UI.HeaderInfo.description.value: 'ProjectId' — #HeaderInfo |
| ヘッダーのタイプラベル | @UI.HeaderInfo.typeName: 'Project', typeNamePlural: 'Projects' — #HeaderInfo |
| リスト列(マスター) | フィールドごとに @UI.lineItem: [{ position: N, importance: #HIGH }] — クリティカリティを使用するバリアントは #LineItemHighlight |
| ⚠ ステータスコード → テキスト+色 | 有効なパターンは複数あります。リリース/ドラフトの制約に応じて選択してください。 実列を使ったクリティカリティのパターンは #LineItemHighlight を検索してください。永続列を使わずに計算したクリティカリティを使用する場合は、/abap-docs-standard/ABENCDS_PROJ_VIEW_VIRTUAL_ELEMENT と @ObjectModel.virtualElementCalculatedBy: 'ABAP:<class>' を参照してください。7.58 +ドラフトでは、どちらにも既知の制約があります(Run 7 §1 に詳細があります)。採用前に検索してください。 |
| デフォルトの並べ替え | @UI.presentationVariant.sortOrder: [{ by: '<field>', direction: #DESC }] — #PresentationVariant |
| フィールド全体を対象にした検索 | ビューのレベルで @Search.searchable: true +フィールドごとに @Search.defaultSearchElement: true — #Search |
| フィルターバー | @UI.selectionFields: [...] — #SelectionFields |
| 監査フィールドの表示 | @UI.fieldGroup + #FIELDGROUP_REFERENCE の @UI.facet — #HeaderFieldGroup |
| 承認ボタン(ヘッダー) | @UI.identification: [{ type: #FOR_ACTION, dataAction: 'approve_project', label: 'Approve', criticality: 3, criticalityRepresentation: #WITH_ICON }] — #OPHeaderAction。アクションは BDEF から自動的に描画されません。 Projection BDEF で use action approve_project; がすでに公開されている必要があります。 |
| LR ツールバーアクション | @UI.lineItem に同じ形式で指定 — #ActionInLineItem、#WithAction |
| 子エンティティの OP テーブル | 親に @UI.facet: [{ type: #LINEITEM_REFERENCE, targetElement: '_AssocName', label: '...' }] を指定し、子の Projection に @UI.lineItem を指定 — #OPTable |
| ⚠ 複数レベルのナビゲーション(Project → Task → TimeEntry) | 有効な形式は 2 つあります — 選択前に調査してください。(a)ルート Projection から _Tasks._TimeEntries を参照するネストされた LineItem facet(FE のサポートはリリースに依存します)。(b)個別の Task OP ルート — ZC_DM_TASK に @UI.headerInfo と独自の _TimeEntries facet をアノテーションし、FE アプリの manifest に Task のルーティングターゲットを追加します。#OPTable、#Subpages、#InboundNav(cap-fiori-showcase)に加え、manifest のルーティング形式について SAPUI5 の 「Configuring Internal Navigation」(sap-help)を検索してください。 |
| セマンティックキーの太字表示 | @ObjectModel.semanticKey: ['ProjectId'] — #SemanticKey |
| 動的 CRUD(行の状態に応じたボタンの非表示) | フィールドにバインドした @UI.updateHidden + @UI.deleteHidden — #DynamicCRUD |
7.58 における DDLS と DDLX の適用範囲。 複数のエンティティレベルのアノテーション(
@UI.facet、@UI.selectionFields、@UI.identificationによるヘッダーのFOR_ACTION)は、Run 7 で Projection DDLS に指定すると拒否されましたが、DDLX の メタデータ拡張(annotate view <ZC_*> with @UI.facet: [...]など)に移すと成功しました。DDLS のエンティティレベルのアノテーションで「wrong scope」/「unknown」エラーが発生する場合は、DDLX 経由で指定してください。/abap-fiori-showcaseで該当する#Tagを確認してください。オンプレミスのリリースで必要な場合、ショーケースのパターンはすでに DDLS と DDLX に分けられています。
2b. 拡張マップ(一般的な例)
| レガシー機能 | 拡張フック |
|---|---|
| Approve 時の Status === 'D' ガード | FE の BDEF アクションボタンは、BDEF の precheck に応じて有効になります。レガシーアプリの有効化ルールが BDEF と異なる場合は、JS で上書きするのではなく、BDEF に precheck を追加してください(Step 2c)。 |
| Approve 前のカスタム検証(例:Description の必須化) | ObjectPage の editFlow.onBeforeAction コントローラー拡張 |
| クライアント側カウントフッターのカスタム表現 | スキップ — FE のリストレポートには標準の件数が表示されます |
| カスタムナビゲーションパターン | ほとんど必要ありません。FE の行 → OP ナビゲーションがデフォルトです |
| Approve 失敗時の MessageBox | 標準の FE エラートーストで処理されます |
2c. BDEF 側の準備(2b の後、Phase 4 の前に実行)
インベントリで「Status === 'D' の場合のみ Approve ボタンを表示」のようなガードが見つかった場合、それは UI の懸念事項ではなく、事前条件です。アクションの precheck
句を使って BDEF 側に記述し、再アクティブ化します。(このステップは
migrate-segw-to-rap.md の Step 5 に含まれますが、レガシーガードをすでに移行していない場合は、ここで明示的に取り上げてください。)例:
action approve_project precheck result [1] $self;
ビヘイビアプールに precheck メソッドを用意し、%cid / %key を設定して
Status == 'D' をアサートします。必要に応じて、スキルは実際の precheck 本体を
edit_method に委ねます。
Phase 3 — 計画とユーザーの承認
次の正確な形式で計画を表示し、ok / edit / 質問を待って停止します:
Plan — generate FE app at <fe_app>:
Floorplan: List Report + Object Page (LROP V4)
Namespace: <source_namespace>.fe
UI5 version: <user-provided, default latest 1.x>
V4 service: <V4_service_URL>
Main entity: <root_alias> (alias on the root projection)
Generator: SAP Fiori MCP server (@sap-ux/fiori-mcp-server)
Backend annotation writes (via SAPWrite update DDLS on the projection):
<root_projection>:
@UI.HeaderInfo, @UI.SelectionFields, @UI.LineItem (root columns),
@UI.Identification, @UI.PresentationVariant.SortOrder,
@UI.FieldGroup.Audit, @UI.Facet (Identification + Tasks)
@Common.Text + virtual <field>Criticality (Status)
<child_projection_task>:
@UI.LineItem (Task columns), @UI.HeaderInfo,
@UI.Facet (Task identification + TimeEntries),
@Common.Text + virtual fields for Status, Priority
<child_projection_timeentry>:
@UI.LineItem (TimeEntry columns), @UI.HeaderInfo
BDEF-side adjustments (via SAPWrite update BDEF / edit_method):
<list precheck additions, if any>
FE app generation (via Fiori MCP):
Step 1: list_functionalities → enumerate supported FE app creations
Step 2: get_functionality_details → "create FE V4 list-report+OP for external OData service"
Step 3: execute_functionality → pass service URL, root entity, namespace, target folder
Extension scaffold (post-generation):
- <controller-extension list per Phase 2b>
Validation:
- ui5-linter clean
- manifest validation clean
- tsc --noEmit clean
- browser smoke against every Phase 1 inventory item
Type `ok` to proceed, `edit` to revise, or ask any question.
SAP システム内の変更または FE アプリの生成を行う前に、ok を待ちます。
Phase 4 — CDS プロジェクションへの @UI.* アノテーションの書き込み(バックエンドの準備)
これは「バックエンドでアノテーションを準備する」ステップです。Fiori MCP ジェネレーターを呼び出す前に、ここですべての CDS 書き込みを完了してください。ジェネレーターはアノテーション付きの $metadata を読み取るため、ジェネレーターの実行前にアノテーションを有効化し、SRVB を再公開する必要があります。
4a. ルートプロジェクションにアノテーションを付与する
SAPRead(type="DDLS", name="<root_projection>")
計画したアノテーションを挿入します。具体的な形(エンティティを置き換えてください):
@Metadata.allowExtensions: true
@UI.headerInfo: {
typeName: 'Project',
typeNamePlural: 'Projects',
title: { value: 'Title' },
description: { value: 'ProjectId' }
}
@UI.selectionFields: [ 'ProjectId', 'Title', 'Status' ]
@UI.presentationVariant: [{
qualifier: 'DefaultSort',
sortOrder: [{ by: 'StartDate', direction: #DESC }]
}]
@UI.facet: [
{ id: 'GeneralInfo', purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE, label: 'General' },
{ id: 'AuditInfo', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE, label: 'Audit',
targetQualifier: 'Audit' },
{ id: 'Tasks', purpose: #STANDARD, type: #LINEITEM_REFERENCE, label: 'Tasks',
targetElement: '_Tasks' }
]
// Header action — renders as an "Approve" button on the OP header (showcase #OPHeaderAction).
// criticality 3 = green (success), 0 = neutral, 1 = red.
@UI.identification: [
{ type: #FOR_ACTION,
dataAction: 'approve_project',
label: 'Approve',
criticality: 3,
criticalityRepresentation: #WITH_ICON }
]
@Search.searchable: true
define root view entity <root_projection>
provider contract transactional_query
as projection on <root_view>
{
key @UI.lineItem: [{ position: 10, importance: #HIGH }]
@UI.identification: [{ position: 10 }]
@UI.selectionField: [{ position: 10 }]
@Search.defaultSearchElement: true
ProjectId,
@UI.lineItem: [{ position: 20, importance: #HIGH }]
@UI.identification: [{ position: 20 }]
@UI.selectionField: [{ position: 20 }]
@Search.defaultSearchElement: true
Title,
@UI.lineItem: [{ position: 30, criticality: 'StatusCriticality' }]
@UI.identification: [{ position: 30 }]
@UI.selectionField: [{ position: 30 }]
Status,
@UI.lineItem: [{ position: 40 }]
@UI.identification: [{ position: 40 }]
StartDate,
@UI.lineItem: [{ position: 50 }]
@UI.identification: [{ position: 50 }]
EndDate,
@UI.identification: [{ position: 60 }]
Description,
@UI.fieldGroup: [{ qualifier: 'Audit', position: 10, label: 'Created at' }]
Erdat,
@UI.fieldGroup: [{ qualifier: 'Audit', position: 20, label: 'Created by' }]
Ernam,
@UI.fieldGroup: [{ qualifier: 'Audit', position: 30, label: 'Changed at' }]
Aedat,
@UI.fieldGroup: [{ qualifier: 'Audit', position: 40, label: 'Changed by' }]
Aenam,
// virtual criticality field (computed from Status code)
@ObjectModel.virtualElementCalculatedBy: 'ABAP:<root_class>' // OR via case-when below
virtual StatusCriticality : abap.int1,
/* associations */
_Tasks
}
仮想クリティカリティには、7.58 以前との互換性を保つ最も簡単な方法として、プロジェクション内に case-when を直接記述します:
case Status
when 'D' then 2 // Critical (Warning)
when 'A' then 3 // Positive (Success)
when 'C' then 0 // Neutral
else 0
end as StatusCriticality,
挿入後のソースを書き込みます:
SAPWrite(action="update", type="DDLS", name="<root_projection>",
source="<spliced source>", transport="<transport>")
SAPActivate(type="DDLS", name="<root_projection>")
4b. すべての子プロジェクションにアノテーションを付与する
各 <child_projection_X> に対して同じパターンを繰り返します。各子には次を設定します。
@UI.headerInfo(タイトル/説明)- レガシービューに表示されていた各列の
@UI.lineItem - 子がさらに子を持つ場合の
@UI.facet(例:Task 配下の_TimeEntries) - インベントリで確認された、色付きコードフィールドに対応する仮想クリティカリティフィールド
4c. SRVB を公開する
新しいアノテーションを $metadata に反映するには、SRVB を再公開する必要があります:
SAPWrite(action="publish_srvb", name="<V4_SRVB>")
4d. アノテーションが $metadata に反映されたことを確認する
Bash: curl -s "<base>/<V4_service_URL>/$metadata" | grep -oE 'UI\.(LineItem|HeaderInfo|Facets|SelectionFields|PresentationVariant|FieldGroup|Identification)' | sort -u
期待される出力:記述したすべての種類のアノテーションが一覧に表示されます。何も表示されない場合、SRVB に変更が反映されていません。publish_srvb を再実行してください。一部しか表示されない場合、プロジェクションが正常に再アクティブ化されていません。SAPDiagnose(action="object_state", type="DDLS", name="<root_projection>")
で調査してください。
Phase 5 — SAP Fiori MCP サーバーを介して FE アプリを生成する
ここでは「Fiori MCP を使ってアプリを作成する」手順を説明します。Fiori MCP サーバーは、3 つのツールを順番に実行する流れ、list_functionalities → get_functionality_details → execute_functionality を提供します。各手順で対象範囲を絞り込みます。パラメーターがわかっていると思っても、手順を省略しないでください。
参照先:
- SAP/open-ux-tools — fiori-mcp-server README
- npm: @sap-ux/fiori-mcp-server
- SAP Community: SAP Fiori MCP Server の初回リリース
このスキルの執筆時点では、Fiori MCP サーバーは実験的です。ツールのシグネチャは変更される場合があります。
list_functionalitiesの戻り値の形式が想定と異なる場合は、実際の応答に従ってください。上記の README が信頼できる情報源です。
5a. サーバーでできることを確認する
mcp__fiori-mcp__list_functionalities
応答を確認し、「外部 OData V4 サービス向けに新しい Fiori elements アプリケーションを作成する」機能を探します。応答に表示される正確な名前はサーバーのバージョンによって異なるため、create、fiori-elements、list-report、lropv4、external-service などのキーワードを探してください。
一致する機能がサーバーにない場合:
- CAP プロジェクトが必要な可能性があります。その場合は、従来の代替手段(
@sap/generator-fioriCLI — 5d を参照)を使って生成し、次のイテレーションに向けた Run capture として不足点を記録します。 - または、ユーザーの Fiori MCP バージョンが想定より古い可能性があります。次を実行して再確認します:
そのうえで、MCP 設定を最新バージョンに固定するようユーザーに案内します。Bash: npx --yes @sap-ux/fiori-mcp-server@latest --version
5b. 選択した機能のパラメーター要件を取得する
mcp__fiori-mcp__get_functionality_details(name="<the-functionality-name-from-5a>")
応答には必須パラメーターとオプションのパラメーターが一覧表示されます。外部サービス向け LROP フローでは、一般的な必須パラメーターとして次のものがあります:
serviceUrl—<V4_service_URL>(Phase 0a で取得した、$metadataを提供するエンドポイント)mainEntityまたはentitySet— SRVB のルートエンティティのエイリアス(例:Project)targetPath—<fe_app>/(生成先のフォルダー)namespace—<source_namespace>.feappId/appName— アプリケーション識別子ui5Version— ユーザー指定(デフォルト:最新の 1.x)language—typescript
ユーザーから提供された入力を必須パラメーターに割り当てます。対応する値がない必須パラメーターがある場合は、停止してユーザーに確認してください。値を勝手に作らないでください。
5c. ジェネレーターを実行する
mcp__fiori-mcp__execute_functionality(
name="<the-functionality-name-from-5a>",
parameters={
serviceUrl: "<V4_service_URL>",
mainEntity: "<root_alias>",
targetPath: "<fe_app>",
namespace: "<source_namespace>.fe",
appName: "<short-app-id>",
ui5Version: "<ui5-version>",
language: "typescript"
}
)
ジェネレーターが完了するまで待ちます。次の構成を確認してください:
Bash: ls <fe_app>/webapp/ && cat <fe_app>/webapp/manifest.json | head -40
想定される構成:
webapp/Component.tssap.ui.generic.app/sap.fe.templatesの設定を含むwebapp/manifest.jsonwebapp/i18n/i18n.propertieswebapp/ext/(拡張フォルダー — 空の場合もあります)package.json/ui5.yaml/tsconfig.json
5d. MCP サーバーで生成できない場合の代替手段
list_functionalities に外部サービス向けのパスがない場合は、@sap/generator-fiori CLI に切り替えます:
Bash: cd <workspace> && npx --yes @sap/generator-fiori --no-deploy
プロンプトに従って進めます(または、明示的な引数を指定して --skip-install を渡します)。これは MCP サーバーが内部で使用するものと同じジェネレーターです。対話形式のため時間はかかりますが、確実に動作します。
5e. Fiori MCP で判明している問題点(上流で追跡中)
Fiori MCP サーバーは実験的です。認識して回避すべき既知の問題が 2 つあります。
fetch-service-metadataは、構造化レスポンスではなく MCP フレームワークエラーを返します 対象システムのエントリーが@sap-ux/storeにない場合に発生します。回避策:$metadataを 自分でローカルファイル(例:<fe_app>/metadata.xml)にcurlし、そのファイルをexecute_functionalityに指定します。上流で追跡中: SAP/open-ux-tools#4652 — この問題が 解決したら、curlを使う回避策は不要になります。fetch-service-metadataで保存済みシステムのエントリーを使用するには、Connection Manager の設定が必要ですexecute_functionalityに URL を直接渡すと、この設定を回避できます。スキルの Phase 0e では、URL を直接指定する方法をすでに説明しています。
新たに判明した問題点は RUN-NOTES.md に記録してください。次のイテレーションで
回避策を講じるか、上流に追加の問題を報告できます。
Phase 6 — Phase 2b の EXTENSION リストにある拡張機能を設定する
Phase 2b の拡張機能マップにある各行について、TS コントローラー拡張機能のひな形を作成します。FE V4 拡張機能には、次の 2 種類があります。
- コントローラー拡張機能 —
editFlow/routing/appComponentAPI を使って LR または OP コントローラーを拡張します。 - 拡張ポイント — カスタム XML/Fragment を特定の位置(ヘッダー、フッター、 セクションの前後)に挿入します。
トークデモでよくある拡張機能(BDEF ではすでに表現されていない、承認時の事前チェック)については:
Write: <fe_app>/webapp/ext/ObjectPageExt.ts
import ControllerExtension from "sap/ui/core/mvc/ControllerExtension";
import MessageBox from "sap/m/MessageBox";
/**
* @namespace <source_namespace>.fe.ext
*/
export default class ObjectPageExt extends ControllerExtension {
public static overrides = {
editFlow: {
onBeforeAction: async function (
this: ObjectPageExt,
mParameters: { actionName: string; context: any }
) {
if (!mParameters.actionName.endsWith(".approve_project")) return;
const description = mParameters.context.getProperty("Description");
if (!description) {
MessageBox.error("Cannot approve a project without a description.");
throw new Error("Approval blocked by extension");
}
}
}
};
}
拡張機能を <fe_app>/webapp/manifest.json に登録します。
"sap.ui5": {
"extends": {
"extensions": {
"sap.ui.controllerExtensions": {
"sap.fe.templates.ObjectPage.ObjectPageController": {
"controllerName": "<source_namespace>.fe.ext.ObjectPageExt"
}
}
}
}
}
拡張機能のひな形を作成するたびに、リンターを実行します。
mcp__SAPUI5_MCP_Server__run_ui5_linter(files=["<fe_app>/webapp/ext/ObjectPageExt.ts"])
拡張機能マップのすべてのエントリーについて繰り返します。拡張機能は小さく保ち、クラスごとに 関心事を 1 つにします。
機能の分類(アノテーションか、拡張機能か)が曖昧な場合は、Fiori MCP のドキュメント検索を使って 確認します。
mcp__fiori-mcp__search_docs(query="custom validation before action Fiori elements V4")
これにより、信頼できる SAP のガイダンスを取得し、推測を避けられます。
Phase 7 — 検証とスモークテスト
7a. 静的チェック
mcp__SAPUI5_MCP_Server__run_ui5_linter
mcp__SAPUI5_MCP_Server__run_manifest_validation
Bash: cd <fe_app> && npx tsc --noEmit
3 つすべてがエラーなしで完了する必要があります。
7b. 開発サーバー
空いているポートで開発サーバーを再起動します(デフォルトは 8082 です。レガシーアプリの開発
サーバーまたは別の実行中のツールがすでに使用している場合は、別のポートを選びます)。
Bash: cd <fe_app> && pkill -f "ui5 serve" ; (npm start -- --port 8082 &)
サーバーが起動するまで約 5 秒待ちます。エントリーポイントを確認します。
Bash: curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8082/index.html
7c. Phase 1 のインベントリに対するブラウザースモークテスト
ブラウザーで http://localhost:8082 を開き、Phase 1 のインベントリにあるすべての項目を検証します。
合格基準は、アノテーションまたは拡張機能を使って、FE アプリがレガシーアプリでユーザーに表示される
すべての機能を再現していることです。
チェックリスト(ユーザーのインベントリに合わせて調整してください):
- リストレポートが表示される。
@UI.LineItemの列が正しい順序で並んでいる。 - フィルターバーに
@UI.SelectionFieldsのフィールドが表示される。 @Search.defaultSearchElementが付いたフィールドで検索できる。- デフォルトの並べ替えが
@UI.PresentationVariant.SortOrderと一致する。 - 行をクリックすると OP が開く。
- OP ヘッダーに
@UI.HeaderInfoに基づく正しいタイトル/説明が表示される。 - 行のステータスフィールドに正しい色(クリティカリティ)が表示される。
- タブ/ファセットに、それぞれ
@UI.Facetが参照する関連が表示される。 - ネストされたファセットで孫エンティティ(例:Tasks 配下の TimeEntries)を参照できる。
- アクションボタンが BDEF アクション(
@UI.identificationのDataFieldForAction)に対して表示される。クリックすると、フレームワーク標準の CSRF/etag フローで実行されるため、一連の処理に拡張機能は不要。 - 拡張フックが Phase 2b でインベントリに記録したケース(検証、カスタムプロンプト)で実行される。
- OP の Audit ファセットに監査フィールドが表示される。
- リストレポートのヘッダーに表示されるFE ネイティブの件数が、レガシーアプリのフッターの表現と一致する(「X projects」と「Showing X of Y」のような UX 上の違いは許容)。
7c.1 — V4 の実態(Run 6 で検証済み)
V4 サービスでは、ドラフトシナリオにおいて、すべてのエンティティキーの一部として IsActiveEntity が公開されます。
テストに関する影響は次の 2 点です。
- キー指定の読み取りでは
IsActiveEntityを含める必要があります。Project(ProjectId='PRJ-0001',IsActiveEntity=true)は 200 を返しますが、従来形式のProject('PRJ-0001')は 400 を返します。 - アクションの呼び出しでは、CSRF トークンの取得と送信が必要です。まず
X-CSRF-Token: Fetchを指定して<service-root>/?sap-client=<n>に GET リクエストを送信します → 返されたX-CSRF-Token、セッション Cookie、およびIf-Match: <etag>を指定してアクション URL に POST リクエストを送信します。If-Matchを省略すると 428(CX_OD_PRECOND_REQUIRED)が返されます。
これらは、V4 とドラフトを使用するサービスでは一般的な動作です。FE テンプレートが実行時に自動的に処理します。ここに記載した手順は、手動で curl によるスモークテストを行う場合のみを対象としています。
手順が失敗した場合:
- アノテーションの問題の場合は、フェーズ 4 に戻って CDS を調整し、再アクティブ化してから、
publish_srvbを実行し、 スモークテストの手順を再実行します。 - 拡張機能の問題の場合は、ブラウザーの DevTools でコントローラー拡張機能をデバッグします。
- ツールの不具合と思われる FE のレンダリング問題の場合は、
mcp__fiori-mcp__search_docs(query="<exact symptom>")を実行して、信頼できるリファレンスを検索します。
7d. 最終レポート
Fiori Elements conversion complete — <fe_app>
Floorplan: LROP V4 (TS)
UI5: <version>
V4 service: <V4_service_URL>
Annotations: <n> @UI.* annotations written across <m> projections
Extensions: <n> controller extensions
Linter: clean
Manifest: clean
TypeCheck: clean
Browser smoke: <12+/12+> inventory items reproduced
What just happened (3 sentences):
- Mined the legacy app's user-visible feature set (columns, sort, search, actions,
tab structure, formatters).
- Wrote the equivalent @UI.* / @Common.* / @Search.* annotations onto the RAP CDS
projections via ARC-1.
- Generated the FE app on top of the now-annotated $metadata via the SAP Fiori MCP
server, with extension hooks for the few cases FE templates can't express natively.
ARC-1 calls used:
- SAPManage(action=probe)
- SAPRead(type=DDLS, name=<root_projection>)
- SAPRead(type=SRVB, name=<V4_SRVB>)
- SAPWrite(action=update, type=DDLS, ...) × <m> projections
- SAPActivate(type=DDLS, ...)
- SAPWrite(action=publish_srvb, name=<V4_SRVB>)
- (Optional) SAPWrite(action=update, type=BDEF, ...) + SAPActivate for BDEF precheck
Fiori MCP calls used:
- mcp__fiori-mcp__list_functionalities
- mcp__fiori-mcp__get_functionality_details(name=<chosen>)
- mcp__fiori-mcp__execute_functionality(...)
- mcp__fiori-mcp__search_docs(...) × <n> (during extension scaffolding)
UI5 MCP calls used:
- mcp__SAPUI5_MCP_Server__run_ui5_linter × <n>
- mcp__SAPUI5_MCP_Server__run_manifest_validation
エラー処理 — 既知の状況
| 症状 | 原因 | 修正方法 |
|---|---|---|
SAPWrite update DDLS の後も $metadata にアノテーションが反映されない | DDLS は再アクティブ化されたが、SRVB が再公開されていない | SAPWrite(action="publish_srvb", name="<V4_SRVB>") |
mcp__fiori-mcp__list_functionalities が空を返す/失敗する | サーバーが登録されていない、または npx キャッシュが古い | .cursor/mcp.json を確認します。新しいシェルで npx --yes @sap-ux/fiori-mcp-server@latest fiori-mcp を実行すると、サーバーの準備完了ログが出力されるはずです |
| ジェネレーターが「service unreachable」で失敗する | V4 ルーティンググループが原因で、<V4_service_URL> が 403 でブロックされている | migrate-segw-to-rap.md のフェーズ 6 に記載されている /n/IWFND/MAINT_SERVICE の手動手順を案内します |
| ジェネレーターは成功するが、FE アプリに空のシェルが表示される | アノテーション付き CDS を指定せずに mainEntity を渡している | フェーズ 4 を再確認します。@UI.Facet チェーン内のすべてのエンティティには、少なくとも @UI.LineItem が必要です。また、OP ルートには @UI.HeaderInfo も必要です |
| リストレポートに列が表示されない | @UI.LineItem アノテーションがルートビューにあり、プロジェクションにない | アノテーションをプロジェクションに移動します。FE は SRVB が公開するプロジェクションから読み取ります |
| アクションボタンが表示されない | アクションがプロジェクション BDEF で公開されていない、またはプロジェクション BDEF に use action approve_project がない | プロジェクション BDEF(define behavior for <root_projection> { ... use action approve_project; })を確認し、再公開します |
| フィルターバーが空 | @UI.SelectionFields アノテーションがない、またはビューのレベルで @Search.searchable が指定されていないフィールドを参照している | ビューのレベルで @Search.searchable: true を追加し、適切なフィールドに @Search.defaultSearchElement: true を追加します |
| ステータスフィールドに色が付かない | クリティカリティのバインドがない | @UI.LineItem のエントリーに criticality: '<field>Criticality' の参照を追加し、コードを FE のクリティカリティ(0=中立、1=ネガティブ、2=重要、3=ポジティブ)に対応付ける仮想の <field>Criticality プロジェクションフィールドも追加します |
| ネストされたファセット(Tasks 配下の TimeEntries)がレンダリングされない | 7.5x の一部のリリースでは、_Tasks._TimeEntries の LineItem ファセットパスが機能しない | 必要であれば、TimeEntries を独立した OP としてレンダリングし、Task の LineItem からドリルダウンします。ユーザーのリリースで動作することを確認してください |
| コントローラー拡張機能が「Override target not found」をスローする | manifest のコントローラーパスが間違っている | LR:sap.fe.templates.ListReport.ListReportController、OP:sap.fe.templates.ObjectPage.ObjectPageController |
MCP server timed out | $metadata の取得が遅く、実行時間の長い execute_functionality がブロックされている | .cursor/mcp.json の MCP timeout を増やします(現在は 600s)。通常、talk-demo のサービス規模であればデフォルトで十分です |
| ジェネレーターが確認プロンプトで停止する | MCP サーバーが上書きを対話形式で確認しようとしている | 再実行前に <fe_app>/ を事前に削除するか、機能の詳細に記載されている場合は overwrite: true を渡します |
このスキルで明示的に扱わないこと
- 複数フロアプランの構成(Overview Page + LRO + ALP)。単一の LRO+OP がトークデモの範囲です。構成は今後の対応となります。
- FE の構成要素では実現できない、本格的なカスタムレンダリング。そのような要件がある場合は、代わりにフリースタイルの手順(
modernize-ui5-app.md)を選んでください。 - モック/ローカルサービスモード。このスキルはライブの V4 RAP サービスを対象としています。Fiori MCP は CAP プロジェクトのアプリを生成できますが、それは別のフローです。
- 認可ポリシー。FE はサービスが認可した内容をレンダリングします。PFCG/S_DEVELOP の変更は、このスキルではなく SAP 側で行います。
- CDS
@EndUserText.labelで提供される範囲を超える翻訳/ローカライズ。FE はサービスのメタデータからラベルを取得します。追加の i18n は FE アプリの i18n ファイルに記述します。 - CAP 側での生成。このスキルは RAP バックエンドを前提としています。CAP のみを対象とするフローでは、Fiori MCP サーバーの CAP 対応プロンプトを直接使用してください。
このスキルを実行する LLM 向けの注意事項
- アノテーションを最優先することが、このスキルの要点です。アノテーションのない
$metadataに対して FE ジェネレーターを決して実行しないでください。生成されるのは役に立たない枠組みだけです。 - Fiori MCP サーバーは実験的です。このスキルの作成後に、ツール名やパラメーターの形式が変わっている可能性があります。必ず最初に
list_functionalitiesを実行し、それに合わせてください。 - アノテーションを記述するのはルートビューではなく、プロジェクションです。SRVB がプロジェクションを公開し、FE はそこから読み取ります。
- 公開するアノテーションに影響する CDS の変更を行うたびに、SRVB を再公開してください。ADT はこれを自動では行いません。
- 「ファセットがアソシエーションを参照する」パターンが最も難しい部分です。
targetElement: '_Tasks'を指定した#LINEITEM_REFERENCE型のファセットが機能するのは、_Tasksがプロジェクションで公開されたアソシエーションである場合に限られます。プロジェクションのuse association _Tasks { ... }ブロックを確認してください。 - コントローラー拡張は最後の手段です。何かにコントローラー拡張が必要かどうか判断に迷ったら、ユーザーに確認してください。FE テンプレートで実現できることは想像以上に多いため、本当に必要な場合にのみエスカレーションしてください。
- アノテーションの構文を推測する前に、
mcp__fiori-mcp__search_docs(またはtopic="fiori-elements"を指定したmcp__sap-docs__search)を利用してください。SAP のアノテーションリファレンスが正式な情報源です。 mcp__fiori-mcp__list_functionalitiesが想定外の機能(例:「既存アプリにページを追加」、「manifest を変更」)を返した場合は、計画に反映してください。Phase 6 の拡張作業を簡素化できる可能性があります。- Fiori MCP が
execute_functionality経由で対応できる場合、ページの追加やルーティングの変更のためにmanifest.jsonを手動で編集しないでください。MCP による編集はスキーマを認識しており、再生成後も維持されますが、手動編集は上書きされる可能性があります。