第 7 章: アプリへの機能の追加
Kiana と Maria は、フィールド技術者である Caleb に在庫管理アプリを紹介します。 彼はそのアプリを気に入りますが、より使いやすくするため追加のユーザー インターフェイス機能をいくつか追加することを提案します。 具体的に、Caleb は次のことができるようにしたいと考えます:
ボイラーまたは空調ユニットで行われた作業の写真を追加し、それを 予定の編集 画面で詳細予定に追加します。 この画像は、実行された修理の証拠書類として役立つ可能性があります。 予定の編集 画面では現在、ユーザーが予定に画像を追加できますが、この機能がまだ完全に実装されていないため、画像は保存されません。 Kiana と Preeti が画像データを保存するのに最適な場所を決定する必要があるためです。 Caleb は、この機能をできるだけ早く追加したいと考えています。
顧客の完全な予約履歴を表示して、要求された修理を追跡し、技術者を繰り返し呼び出しかねない進行中の問題を監視します。
部品詳細 画面から部品を注文します。
さらに、部品詳細 画面の画像コントロールには、指定した URL に保存されている画像が表示されます。 現在、データの URL は単なるプレースホルダーです。 予約画面の写真と同様に、Kiana と Preeti は、アプリで利用できるよう画像を保存するのに最適な場所を決定する必要があります。
予定に写真を追加する
写真は、アプリによってアクセスできる場所に保存する必要があります。 パフォーマンスとセキュリティ上の理由から、Preeti は写真を OneDrive または Azure SQL Database 内に保存することを望みません。 代わりに、彼女と Kiana は Azure Blob Storage を使用することにします。 Blob Storage は、大規模なバイナリ オブジェクトを保持するために最適化されており、組み込まれたセキュリティにより堅牢です。 Power Apps には Blob Storage へのアクセスを許可するコネクタがあります。 Maria は、新しい写真撮影画面を追加して、Caleb のユーザー エクスペリエンスを向上させることを提案します。
詳細情報: Azure Blob Storage
Preeti は、次の手順に従って、Azure portal から Blob Storage アカウントを作成します:
Azure ポータルの、ホーム ページで、+ リソースの作成 を選択します。 MarketPlace を検索 ボックスに ストレージ アカウント と入力し、Enter キーを選択します。

ストレージ アカウント ページで、作成 を選択します。
ストレージ アカウントの作成 ページで、次の詳細を入力してから、レビューと作成 を選択します。
- サブスクリプション: ご使用のサブスクリプションを選択してください
- リソース グループ: webapi_rg
- ストレージ アカウント名: グローバルに一意の名前を指定し、後で使用できるようにメモします
- 場所: 最も近い場所を選択してください
- パフォーマンス: 標準
- アカウントの種類: BlobStorage
- レプリケーション: RA-GRS

検証ページで 作成 を選択し、ストレージ アカウントがプロビジョニングされるまで待ちます。
新しいストレージ アカウントのページに移動します。
概要 ページで、コンテナー を選択します。

コンテナー ページで、+ コンテナー を選択します。 写真 という名前の付いた新しいコンテナーを作成してから、作成 を選択します。 パブリック アクセス レベル を BLOB に変更します。

ストレージ アカウントの 概要 ページに戻り、設定の下で、アクセス キー を選択します。 アクセス キー ページで、表示キー を選択します。 key1 のキーの値をメモします。

Preeti は、ストレージ アカウント名とキーを Kiana に提供します。Kiana はこの情報を使用し、次の手順に従ってアプリのカスタム コネクタを作成します:
Power Apps にサインインします。
左ウィンドウで、データ を展開し、接続 を選択します。 アプリで使用されている既存の接続を一覧表示する必要があります。 + 新しい接続 を選択します。

新しい接続 ページで、下にスクロールして、接続 を選択し、Azure Blob Storage を選択してから、作成 を選択します。

Azure Blob Storage ダイアログで、Preeti が提供したストレージ アカウント名とアクセス キーを入力してから、作成 を選択します。

新しい接続が作成されるまで待機します。 接続の一覧に表示されます。
Maria は、アプリの Blob Storage へのこの接続を使用して、写真画像を保存および取得できます。 彼女が実行する最初のタスクは、次の手順に従ってアプリに接続を追加することです:
編集する VanArsdelApp アプリを Power Apps Studio で開きます。
データ ウィンドウで、データの追加 を選択し、Azure Blob Storage コネクタを検索してから、コネクタを選択します。

Azure Blob Storage ダイアログで、アプリに追加する Azure Blob Storage コネクタを選択します。

Maria が実行する次のタスクは、技術者またはエンジニアが写真を保存できるよう画面を追加することです。 Maria は、画像コントロールを備えた新しい画面を追加することにしました。 アプリをモバイル デバイスで実行すると、このコントロールをカメラと統合して、技術者が写真を撮ることができます。 他のデバイスでは、このコントロールはユーザーに代わりに画像ファイルをアップロードするように促します。 彼女は次の手順に従って、EditAppointment 画面からこの新しい画面へのリンクを追加します:
挿入 メニューで、新規画面 を選択してから、スクロール可能 なテンプレートを選択します。

ツリー ビュー ウィンドウで、新しい画面を選択し、名前を TakePhoto に変更します。
この画面の LblAppNameX コントロールの テキスト プロパティを 写真を撮る に変更します。
画面からの CanvasX コントロールを削除します。
挿入 メニューの、メディア ドロップダウン一覧から、画像の追加 を選択して新しい画像コントロールを作成します。

注意
画像コントロールは、実際にはユーザーが画面に画像を追加して結果を表示できるようにする複合カスタムコンポーネントです。
画面の本体を占めるように、画像コントロールのサイズと位置を変更します。
ツリー ビュー ウィンドウで、AppointmentDetails 画面の IconBackarrowX コントロールを選択してから、コピー を選択します。

ツリー ビュー メニューで TakePhoto 画面を右クリックしてから、貼り付け を選択します。 IconBackArrowX コントロールが画面に追加されます。

IconBackArrowX コントロールをヘッダーバーの左上に移動します。
ツリー ビュー ウィンドウで、TakePhoto 画面の IconBackArrowX コントロールを選択します。 右側ウィンドウの 詳細 タブで、OnSelect アクション プロパティを Navigate(EditAppointment, ScreenTransition.None) に変更します。
新しい 保存 アイコン コントロールをヘッダー バーの右上に追加します。 このコントロールの Visible プロパティを If(IsBlank(AddMediaButton1.Media), false, true) に設定します。
この設定により、ユーザーが画像を選択していない場合、保存 アイコンは非表示になります。

保存 アイコン コントロールの OnSelect アクション プロパティで式を次のように変更します。
Set(ImageID, GUID() & ".jpg"); AzureBlobStorage.CreateFile("photos", ImageID, AddMediaButton1.Media); Patch(appointmentsCollection, LookUp(appointmentsCollection,id=BrowseAppointmentsGallery.Selected.id), {imageUrl:"https://myappphotos.blob.core.windows.net/photos/" & ImageID}); Navigate(EditAppointment,ScreenTransition.Cover);<storage account name> を Preeti が作成した Azure Storage アカウントの名前と置き換えます。
このコードは画像を Blob Storage の 写真 コンテナーにアップロードします。 各画像には一意のファイル名が付けられます。 Patch 関数は、Blob Storage 内の画像の URL を使用して、予定レコードの imageUrl プロパティを更新します。
ツリー ビュー ウィンドウで、AddMediaWithImageX コントロールを展開します。 UploadedImageX コントロールの 画像 プロパティを変更し、AppointmentImage に設定します。
AppointmentImage は、ユーザーがアップロードした画像、または写真を撮った結果として画像が入力される変数です。 この変数は、後で EditAppointment 画面で初期化されます。
ツリー ビュー ウィンドウで、AddMediaButtonX コントロールを選択します。 このコントロールの UseMobileCamera プロパティを true に設定します。 コントロールの OnChange アクション プロパティを次に設定します。
Set(AppointmentImage, AddMediaButton1.Media)この式は AppointmentImage 変数を変更して新しい画像を参照します。 UploadedImageX コントロールはこの画像を表示します。
ツリー ビュー ウィンドウで、EditAppointment 画面を選択します。
EditFormX コントロールを展開します。 Image_DataCardX コントロールで、AddPictureX コントロールを削除します。

ImageX コントロールを選択します。 次のようにプロパティを変更します:
- 画像: Parent.Default
- X: 30
- Y: DataCardKey X.Y + DataCardKey X.Height + 150 (DataCardKeyX は ImageX コントロールを含むデータ カードです)
- 幅: Parent.Width - 60
- Height: 400
注意
画像コントロールは画面の下部にドロップダウンしますが、画像を表示できるようにスクロール バーが自動的に追加されます。
カメラ アイコンをデータ カードに追加し、画像 ラベルと ImageX コントロールの間に配置します。 コントロールの名前を CameraIcon に変更します。
注意
カメラ メディア コントロール ではなく、カメラ アイコン コントロールを選択していることを確認してください。

CameraIcon コントロールの OnSelect アクション プロパティを次に設定します。
Set(AppointmentImage, SampleImage); Navigate(TakePhoto, ScreenTransition.None);ユーザーがこのアイコンを選択すると、写真を撮ったり画像をアップロードしたりできる TakePhoto 画面に移動します。 表示される最初の画像は、既定のサンプル画像になります。
アプリをテストするには、次の手順を実行します:
ツリー ビュー ウィンドウで、ホーム 画面を選択します。
F5 を選択してアプリをプレビューします。
ホーム 画面で、予定 を選択します。
参照画面で、任意の予定を選択します。
予定の詳細画面で、画面ヘッダーの編集アイコンを選択します。
編集画面で、画像の カメラ アイコンを選択します。
写真を撮る 画面が表示されることを確認してください。
画像の変更 および選択した画像のアップロード (または、モバイル デバイスでアプリを実行している場合は、写真を撮る) を選択します。
保存 を選択します。 詳細ページに画像が表示されていることを確認し、チェック アイコンを選択して変更をデータベースに保存します。
プレビュー ウィンドウを閉じて、Power Apps Studio に戻ります。
部品の画像を表示する
Preeti と Kiana は、Blob Storage が予定に関連する写真を保存するのに理想的な場所であると判断し、部品の画像を保存するために同じアプローチを使用する必要があると判断します。 このアプローチの主な利点は、アプリに変更を加える必要がないことです。 アプリは同じストレージ アカウントおよび同じ接続を再利用します。 個別の移行演習として、次の手順を実行できます:
新しい Blob Storage コンテナーを作成します。
部品画像をこのコンテナーにアップロードします。
InventoryDB データベースの 部品 テーブルの ImageUrl 参照を、各画像の URL に変更します。
アプリは各部品画像の新しい URL を自動的に取得し、PartDetails 画面の 画像 コントロールに画像が表示されます。
顧客の予約履歴を追跡する
Maria は、カスタム コンポーネントを作成することで、顧客の以前の技術者の訪問からのすべての履歴をすばやく表示できるようアプリに追加できると考えます。 Maria は、Caleb と協力し、表示する情報について、メモと各訪問の日付で構成されるシンプルなデザイン構想を練ります。

データを見ると、Maria は、ギャラリー コントロールがテーブル データを画面に表示するための最良の方法であると考えます。
Maria は次の手順でカスタム コンポーネントを作成します:
Power Apps Studio を使用して、ツリー ビュー ウィンドウで、コンポーネント を選択してから、+ 新しいコンポーネント を選択します。

Component1 という名前の付いた新しい空白のコンポーネントが作成されます。 コンポーネントの名前を DateHistoryComponent と変更します。

挿入 メニューで、ギャラリー を選択してから、高さ (伸縮可能、空) ギャラリー テンプレートを選択します。

ギャラリー コントロールを移動し、カスタム コンポーネントを埋めるようにサイズを変更します。
挿入ウィンドウで項目を追加する を選択してから、テキスト ラベル を選択します。

ツリー ビュー ウィンドウで、ラベル コントロールの名前を NotesLabel に変更します。 オーバーフロー プロパティを Overflow.Scroll に設定します。 この設定により、コントロールはテキストの複数行を表示し、ユーザーがそれをスクロールできるようになります。 コントロールの位置とサイズを設定できるように、次のプロパティを設定します:
- LineHeight: 2
- X: 28
- Y: 18
- Width: 574
- Height: 140
2 番目のテキスト ラベルをコントロールに追加します。 このコントロールの名前を DateLabel に変更し、次のプロパティを設定します:
- LineHeight: 2
- X: 28
- Y: 174
- Width: 574
- Height: 70
コントロールがアプリに挿入され、テーマとともに表示されたときの外観を確認するには、ツリー ビュー ウィンドウで、DateHistoryComponent を選択します。 右側ウィンドウの、詳細 タブで、塗りつぶし フィールドを選択して、色を RGBA(0, 0, 0, 1) に変更します。

挿入 ウィンドウで、形 を展開し、四角形 コントロールをカスタム コンポーネントにを追加します。 このコントロールに、次のプロパティを設定します:
- X: 0
- Y: 273
- 幅: Parent.Width
- Height: 2
このコントロールは、ギャラリーに表示されるレコード間の区切り文字として機能します。

Maria は、画面にコントロールを追加し、Power Apps を使用してアプリを構築することに精通しています。 ただし、再利用可能なコンポーネントはまったく同じようには機能しません。 Kiana は、カスタム コンポーネントでデータを使用できるようにするには、いくつかのカスタム入力プロパティを追加する必要があることを Maria に説明しました。 Kiana はまた、Maria がコンポーネント内のコントロールのデータ フィールドを参照できるように、これらのプロパティのサンプル データを提供する必要があることを説明しました。
ツリー ビュー ウィンドウで、DateHistoryComponent を選択します。 右側のウィンドウの プロパティ タブで、新しいカスタム プロパティ を選択します。

新しいカスタム プロパティ ダイアログで、次の値を指定してから、作成 を選択します:
- 表示名: データ
- 名前: データ
- 説明: メモと日付を表示する、顧客の予定の表
- プロパティの種類: 入力
- データの種類: 表
- 値が変更されたときに OnReset を上げる: 空白のまま

コントロールによって表示されるサンプル データを変更するには、新しい データ カスタム プロパティを選択します。 数式フィールドに、Table({Notes: "Example notes field text.", 'Appointment Date': Text(Today())}) と入力します。

ツリー ビュー ウィンドウで、DateHistoryComponent の GalleryX コントロールを選択し、名前を AppointmentHistory に変更します。
右側のウィンドウの、詳細 タブで、AppointmentHistory ギャラリー コントロールの 項目 プロパティを Parents.Data に設定します。

NotesLabel コントロールを選択します。 右側ウィンドウの 詳細 タブで、テキスト プロパティを ThisItem.Notes, に変更し、サイズ プロパティを 20 に変更します。
注意
サイズ プロパティは、コントロールによって表示されるテキストのフォント サイズを指定します。
DateLabel コントロールを選択して、テキスト プロパティを ThisItem.'Appointment Date' に変更し、サイズ プロパティを 20 に変更します。 カスタム コンポーネントのフィールドには、サンプル データが表示されます。

カスタム コンポーネントが完了しました。 Maria は、次のように、このコンポーネントを使用して顧客の予定履歴を表示する新しい画面を作成します。
ツリー ビュー ウィンドウで、画面 タブを選択します。
BrowseAppointments 画面を展開し、BrowseAppointmentsGallery コントロールを展開してから、Body1_1 コントロールを選択します。 挿入 メニューで、アイコン を選択してから、詳細一覧 アイコンを選択します。

アイコン コントロールの名前を ViewAppointments に変更します。
ツリー ビュー メニューで、BrowseAppointmentsGallery コントロールを選択します。 右側のウィンドウの、詳細 タブで、TemplateSize プロパティを 220 に変更します。 このプロパティを増やすと、ギャラリーで使用可能なスペースが拡張されます。
ViewAppointments アイコンを顧客名の下の空白スペースに移動します。

ViewAppointments アイコン コントロールを選択します。 OnSelect アクション プロパティを次の式に設定します。
ClearCollect(customerAppointmentsCollection, FieldEngineerAPI.getapicustomeridappointments(ThisItem.customerId)); Navigate(AppointmentsHistoryScreen, ScreenTransition.Fade)この式は、選択した顧客の予定を含む customerAppointmentsCollection という名前のコレクションにデータを入力してから、AppointmentHistoryScreen に移動してそれらを表示します。 次の手順でこの画面を作成します。
挿入 メニューで、新規画面 を選択してから、スクロール可能 なテンプレートを選択します。

AppointmentHistoryScreen への新しい画面の名前を変更します。
この画面に追加された CanvasX コントロールを削除します。

この画面の LblAppNameX コントロールを選択します。 右側のウィンドウの、詳細 タブで、テキスト プロパティを次のように変更します。
"Appointments History for " & BrowseAppointmentsGallery.Selected.customer.nameLblAppNameX コントロールの次のプロパティを設定して、位置とサイズを調整します:
- X: 90
- Y: 0
- Width: 550
- Height: 140
RectQuickActionBarX コントロールを選択し、高さ プロパティを 140 に設定します。
左アイコン コントロールを、タイトルの左側にある画面ヘッダーに追加します。 このコントロールの OnSelect アクション プロパティを Navigate(BrowseAppointments, Transition.None) に設定します。

挿入 メニューで、カスタム を選択してから、DateHistoryComponent を選択します。

コンポーネントを移動してサイズを変更し、画面の本体、見出しの下を占めるようにします。

このコンポーネントに、次のプロパティを設定します:
- データ: customerAppointmentsCollection
- 予約日: startDateTime
- メモ: メモ
アプリを保存します。
アプリをテストするには、次の手順を実行します:
ツリー ビュー ウィンドウで、ホーム 画面を選択します。
F5 を選択してアプリをプレビューします。
ホーム 画面で、予定 を選択します。
参照画面で、任意の予定の 詳細一覧 アイコンを選択します。
選択した顧客の 予定履歴 画面が表示されるのを確認します。
プレビュー ウィンドウを閉じて、Power Apps Studio に戻ります。
部品を注文する
システムの主な要件は、技術者が顧客を訪問している間に必要な部品を注文できるようにすることです。 部品の在庫がある場合は、お客様にとって次の都合の良い日に修理を完了するために、別の訪問をスケジュールすることが可能になります。 現在部品が在庫切れで注文する必要がある場合、技術者は顧客にその点を伝えることができます。 Malik は、部品が倉庫に到着したという通知を Maria が受け取ったら、顧客との予定を手配できます。
アプリの予約部分は、次の図に示すように、InventoryDB データベースのテーブルを使用します。 注文 テーブルには、部品の注文に関する情報が含まれています。 予約 テーブルでは、技術者およびエンジニアが部品に対して行った予約要求を一覧表示します。 エンジニア テーブルには、予約を取ったエンジニアの名前と連絡先番号が記載されています。これにより、在庫管理者の Maria が必要に応じて容易に問い合わせができます。

この機能をサポートするには、Kiana は次のように、指定された部品の予約済み品目の数をフェッチするメソッドで Web API を更新する必要があります。
Visual Studio Code の FieldEngineerApi Web API プロジェクトを開きます。
Order.cs という名前の付いたファイルを モデル フォルダーに追加します。 次のコードをこのファイルに追加します。 注文 クラスは、部品の注文の詳細を追跡します。
using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace FieldEngineerApi.Models { public class Order { [Key] public long Id { get; set; } public long BoilerPartId { get; set; } public BoilerPart BoilerPart { get; set; } public long Quantity { get; set; } [Column(TypeName = "money")] public decimal TotalPrice { get; set; } [Display(Name = "OrderedDate")] [DataType(DataType.DateTime)] [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")] public DateTime OrderedDateTime { get; set; } public bool Delivered { get; set; } [Display(Name = "DeliveredDate")] [DataType(DataType.DateTime)] [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")] public DateTime? DeliveredDateTime { get; set; } } }Reservation.cs という名前の付いた別の新しいファイルを モデル フォルダーに追加し、このファイルに次のコードを追加します。 予約 クラスには、現在他の顧客のために予約されている特定の部品の品目数に関する情報が含まれます。
using System; using System.ComponentModel.DataAnnotations; namespace FieldEngineerApi.Models { public class Reservation { [Key] public long Id { get; set; } public long BoilerPartId { get; set; } public BoilerPart BoilerPart { get; set; } public int NumberToReserve { get; set; } public string EngineerId { get; set; } public InventoryEngineer Engineer { get; set; } } }次のコードを使用して、InventoryEngineer.cs, という名前のファイルを モデル フォルダーにもう 1 つ追加します。 InventoryEngineer クラスでは、どのエンジニアがどの予約を行ったかを記録します。
using System.ComponentModel.DataAnnotations; using System.Collections.Generic; namespace FieldEngineerApi.Models { public class InventoryEngineer { [Key] public string Id { get; set; } [Required] public string Name { get; set; } public string ContactNumber { get; set; } public List<Reservation> Reservations { get; set; } } }モデル フォルダーの InventoryContext.cs ファイルを開き、次のステートメントを InventoryContext クラスに追加します。
public class InventoryContext : DbContext { public InventoryContext(DbContextOptions\<InventoryContext\> options) : base(options) { } public DbSet<BoilerPart> BoilerParts { get; set; } public DbSet<InventoryEngineer> Engineers { get; set; } public DbSet<Order> Orders { get; set; } public DbSet<Reservation> Reservations { get; set; } }Visual Studio Code のターミナル ウィンドウで、次のコマンドを実行して、注文と予約を処理するためのコントローラーを構築します。
dotnet aspnet-codegenerator controller ^ -name OrdersController -async -api ^ -m Order ^ -dc InventoryContext -outDir Controllers dotnet aspnet-codegenerator controller ^ -name ReservationsController -async -api ^ -m Reservation ^ -dc InventoryContext -outDir Controllersコントローラー フォルダーの BoilerPartController.cs ファイルを開き、次の GetTotalReservations メソッドを BoilerPartsController クラスに追加します。
public class BoilerPartsController : ControllerBase { private readonly InventoryContext _context; public BoilerPartsController(InventoryContext context) { _context = context; } ... // GET: api/BoilerParts/5/Reserved [HttpGet("{id}/Reserved")] public async Task<ActionResult<object>> GetTotalReservations(long id) { var reservations = await _context .Reservations .Where(r => r.BoilerPartId == id) .ToListAsync(); int totalReservations = 0; foreach(Reservation reservation in reservations) { totalReservations += reservation.NumberToReserve; } return new {id, totalReservations}; } ... }OrdersController.cs ファイルを編集し、次に示すように、OrdersController クラスの PostOrder メソッドを変更します。
[HttpPost] public async Task<ActionResult<Order>> PostOrder(long boilerPartId, int quantity) { var part = await _context.BoilerParts.FindAsync(boilerPartId); Order order = new Order { BoilerPartId = boilerPartId, Quantity = quantity, OrderedDateTime = DateTime.Now, TotalPrice = quantity * part.Price }; _context.Orders.Add(order); await _context.SaveChangesAsync(); return CreatedAtAction("GetOrder", new { id = order.Id }, order); }ReservationsController.cs ファイルを編集します。 次のように、ReservationsController クラスの PostReservation メソッドを変更します。
[HttpPost] public async Task<ActionResult<Reservation>> PostReservation(long boilerPartId, string engineerId, int quantityToReserve) { Reservation reservation = new Reservation { BoilerPartId = boilerPartId, EngineerId = engineerId, NumberToReserve = quantityToReserve }; _context.Reservations.Add(reservation); await _context.SaveChangesAsync(); return CreatedAtAction("GetReservation", new { id = reservation.Id }, reservation); }ターミナル ウィンドウで、次のコマンドを実行して、展開するための Web API を構築および公開します。
dotnet build dotnet publish -c Release -o ./publishVisual Studio Code で 公開 フォルダーを右クリックし、Web アプリに展開 を選択します。
Preeti は、VanArsdel アプリで使用される API 管理サービスを更新して、更新された Web API を反映できるようになりました。 これは互換性のない変更です。既存の操作は引き続き機能しますが、予約と注文を行うための新しいコントローラーと操作の違いがあります。 Preeti は次のタスクを実行します:
注意
Preeti は、既存のフィールド エンジニア API を削除して新しいバージョンに置き換えることを選択できましたが、そのアプローチでは、現在 API を使用している可能性のある既存のアプリケーションが破損するリスクがあります。 既存の API をそのまま残し、変更をリビジョンとして追加することをお勧めします。
Azure ポータルで、API 管理サービスに移動します。
API 管理サービス ページの、API 下の左側ウィンドウで、API を選択します。
フィールド エンジニア API を選択し、省略記号メニューを選択してから、リビジョンを追加 を選択します。

フィールド エンジニア API の新しいリビジョンを作成する ダイアログで、部品の予約と注文に対する GET 操作と POST 操作を追加済 という説明を入力してから、作成 を選択します。

REVISION 2 ページで、デザイン を選択します。

デザイン ページで、操作の追加 を選択します。 FrontEnd ページで、次のプロパティを設定してから、保存 を選択します。 この操作は、特定のボイラー部品用に予約された品目の数を取得するために使用されます:
- 表示名: api/BoilerParts/{id}/Reserved
- 名前: api-boilerparts-id-reserved
- URL: GET api/BoilerParts/{id}/Reserved

新しい操作の テスト タブで、id パラメーターを有効な部品番号 (画像の例では部品 1 を使用) に設定してから、送信 を選択します。

テストが成功したことを確認します。 操作は、HTTP 200 応答と、製品の予約数を示す本文で完了する必要があります。

デザイン ページで、操作の追加 を選択します。 FrontEnd ウィンドウで、次のプロパティを設定します (この操作は新しい注文を作成するための POST 要求を定義します):
- 表示名: api/Orders - POST
- 表示名: api-orders-post
- URL: POST api/Orders
クエリ タブで、+ パラメーターを追加 を選択し、次のパラメーターを追加してから、保存 を選択します:
- 名前: boilerPartId、説明 : ボイラー部品 ID、種類: 長い
- 名前: 数量、説明 : 数量、種類: 整数

FrontEnd ウィンドウの 操作の追加 を再度選択し、次のプロパティを設定します (この操作は新しい予約を作成するための POST 要求を定義します):
- 表示名: api/Reservations - POST
- 表示名: api-reservations-post
- URL: POST api/Reservations
クエリ タブで、次のパラメーターを追加してから、保存 を選択します:
- 名前: boilerPartId、説明: ボイラー部品 ID、種類: 長い
- 名前: engineerId、説明: エンジニア ID、種類: 文字列
- 名前: quantityToReserve、説明: 予約する数量、種類: 文字列
リビジョン タブで、新しいバージョンを選択します。 このバージョンの省略記号メニューで、最新にする を選択します。

リビジョンを最新にする ダイアログで、保存 を選択します。
Web ブラウザーで別のページを開き、URL https://<APIM name>.azure-api.net/api/boilerparts/1/reserved に移動します。<APIM name> は API サービスの名前です。 次のような応答が返されることを確認します。
{"id":1,"totalReservations":5}
更新された Web API が利用可能になりました。 理論的には、Kiana は更新された Web API 用の新しいカスタム コネクタを作成し、それをアプリに追加できます。 次にアプリは独自のロジックを実装して、指定した製品の現在在庫数、品目の予約数、必要な品目数との結果の比較、必要に応じた追加在庫の注文、または既存の在庫からの品目の予約を決定します。 ただし、この種類のロジックは、Azure ロジック アプリでより適切に実装されます。 Power Apps は、技術者が部品の予約または注文を希望する場合、カスタム コネクタを介してロジック アプリを呼び出すことができます。
ロジック アプリを作成するため、Kiana は次の手順を使用します:
注意
簡単にするために、この例で作成されたロジック アプリは非トランザクションです。 部品の在庫状況を確認してから予約するまでの間に、同時実行ユーザーが競合する予約を行う可能性があります。 このロジック アプリのロジックの一部を InventoryDB データベースのストアド プロシージャに置き換えることで、トランザクション セマンティクスを実装できます。
Azure ポータルの、ホーム ページで、+ リソースの作成 を選択します。
Marketplace を検索 ボックスに、ロジック アプリ と入力してから、Enter キーを選択します。
ロジック アプリ ページで、作成 を選択します。

ロジック アプリの作成 ページで、次の値を入力してから、レビューと作成 を選択します。
- サブスクリプション: ご使用の Azure サブスクリプションを選択してください
- リソース グループ: webapi_rg
- ロジック アプリ名: FieldEngineerPartsOrdering
- 地域: Web API に使用したのと同じ場所を選択します
- 統合サービス環境の関連付け: 空白のまま
- ログ分析の有効化: 空白のまま
検証ページで、作成 を選択し、ロジック アプリが展開されるまで待ちます。
展開が完了したら、リソースに移動 を選択します。
Logic Apps デザイナー ページで、テンプレート セクションまで下にスクロールしてから、空のロジック アプリ を選択します。

すべて タブの、コネクタとトリガーを検索する テキスト ボックスで、要求 を選択します。

トリガー タブで、HTTP 要求の受信時 を選択します。

要求本文の JSON スキーマ ボックスに、次のスキーマを入力してから、+ 新しいステップ を選択します。
{ "type": "object", "properties": { "boilerPartId": { "type": "integer" }, "numberToReserve": { "type": "integer" }, "engineerId": { "type": "string" } } }
このスキーマは、ロジック アプリが想定している HTTP 要求のコンテンツを定義します。 要求本文は、ボイラー部品の ID、予約する品目の数、および要求を行うエンジニアの ID で構成されます。 エンジニアが部品を予約する時に、アプリはこの要求を送信します。
操作の選択 ボックスで、すべて を選択してから、HTTP を選択します。

ロジック アプリは Web API の BoilerParts{id} 操作を呼び出して、アプリからの要求によって提供されたボイラー部品に関する情報を取得します。
アクション ウィンドウで、HTTP アクションを選択します。

HTTP アクション ボックスの、省略記号メニューで、名前の変更 を選択し、アクションの名前を CheckBoilerPart に変更します。

HTTP アクションのプロパティを次のように設定してから、+ 新しいステップ を選択します:
- メソッド: GET
- URI: https://<APIM name>.azure-api.net/api/boilerparts/、<APIM name>_ は API 管理サービスの名前です。この URI の _ 動的コンテンツ ボックスの、動的コンテンツ タブで、boilerPartId を選択します

操作の選択 ボックスの、コネクタとアクションを検索する ボックスで、JSON の解析 を入力してから、JSON の解析 アクションを選択します。

JSON の解析 アクションの省略記号メニューを使用して、アクションの名前を ParseBoilerPart に変更します。
ParseBoilerPart アクションの コンテンツ ボックスの、動的コンテンツ ボックスで、本文 を選択します。 スキーマ ボックスに、次の JSON スキーマを入力してから、+ 新しいステップ を選択します。
{ "type": "object", "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "categoryId": { "type": "string" }, "price": { "type": "number" }, "overview": { "type": "string" }, "numberInStock": { "type": "integer" }, "imageUrl": { "type": "string" }, } }
このアクションは、getBoilerParts/{id} 要求によって返された応答メッセージを解析します。 応答には、現在の在庫数など、ボイラー部品の詳細が含まれます。
新しいステップの 操作の選択 ボックスで、HTTP コネクタを選択します。
アクション タブで、HTTP アクションを選択します。
操作の省略記号メニューを使用して、操作の名前を CheckReservations に変更します。
この操作のプロパティを次のように設定してから、+ 新しいステップ を選択します:
- メソッド: GET
- URI: https://<APIM name>.azure-api.net/api/boilerparts/。 前と同じように、この URI の 動的コンテンツ ボックスの、動的コンテンツ タブで、boilerPartId を選択します。 URI フィールドで、boilerPartId プレースホルダーの後にテキスト /reserved を追加する

新しいアクションの 操作の選択 ボックスの、コネクタとアクションを検索する ボックスで、JSON の解析 を入力してから、JSON の解析 アクションを選択します。
操作の名前を ParseReservations に変更します。
コンテンツ プロパティを 本文 に設定します。
次のスキーマを入力してから、+ 新しいステップ を選択します。
{ "type": "object", "properties": { "id": { "type": "integer" }, "totalReservations": { "type": "integer" } } }
新しいアクションの 操作の選択 ボックスの、コネクタとアクションを検索する ボックスで、条件 を入力してから、条件コントロール アクションを選択します。

操作の名前を CompareStock に変更します。
値の選択 ボックスを選択します。 動的コンテンツの追加 ボックスの、式 タブで、次の式を入力してから、OK を選択します。
add(body('ParseReservations')?['totalReservations'], triggerBody()?['numberToReserve'])この式は、現在予約されている指定したボイラー部品の品目の数と、エンジニアにより要求された数の合計を計算します。

条件ドロップダウン リスト ボックスで、次の値より大きい を選択します。
残りの 値の選択 ボックス、動的コンテンツ ボックス、動的コンテンツ タブの、ParseBoilerPart の下で numberInStock を選択します。

必要な品目の数と予約数の合計が在庫数よりも多い場合、アプリは在庫を補充するために注文する必要があります。 CompareStock アクションの True の分岐で、アクションの追加 を選択します。
新しい操作の すべて タブで、HTTP を選択してから、HTTP アクションを選択します。
操作の名前を PostOrder に変更します。
PostOrder 操作に、次のプロパティを設定します:
- メソッド: POST
- URI: https://<APIM name>.azure-api.net/api/orders
- クエリ テーブルの、最初の行に、キー boilerPartId を入力します。 動的コンテンツの追加 ボックスの値に関しては、動的コンテンツ タブで、boilerPartId を選択します
- クエリ テーブルの、2 番目の行に、キー 数量 を入力します。 値フィールドに、50 と入力します。

ロジック アプリは、在庫が少なくなると、指定された部品の 50 品目を自動的に注文します。
注意
ロジック アプリでは、エンジニアが 1 回の要求で指定された部品の 50 を超える品目を実際に予約しないことを想定しています。
CompareStock アクションの False の分岐を空のままにします。
CompareStock アクションの下で、+ 新しいステップ を選択します。
新しい操作の すべて タブで、HTTP を選択してから、HTTP アクションを選択します。
操作の名前を PostReservation に変更します。
PostReservation 操作に、次のプロパティを設定します:
- メソッド: POST
- URI: https://<APIM name>.azure-api.net/api/reservations
- クエリ テーブルの、最初の行に、キー boilerPartId を入力します。 動的コンテンツの追加 ボックスの値に関しては、動的コンテンツ タブで、boilerPartId を選択します。
- 2 行目に、キー engineerId を入力します。 動的コンテンツの追加 ボックスの値に関しては、動的コンテンツ タブで、engineerId を選択します
- 3 行目に、キー quantityToReserve を入力します。 動的コンテンツの追加 ボックスの値に関しては、動的コンテンツ タブで、numberToReserve を選択します
+ 新規ステップ を選択します。 操作の選択 ボックスで、応答 アクションを検索して選択します。
応答 アクションに、次のプロパティを設定します:
- 状態コード: 200
- ヘッダー: キー - content-type、値 - application/json
- 本文: 動的コンテンツ ボックスで、 PostReservation 要求からの 本文 要素を選択します。 これは予約時に返される本文です。

Logic Apps デザイナー ページの左上で、保存 を選択します。 ロジック アプリがエラーなしで保存できることを確認します。
Power Apps がロジック アプリをトリガーするために使用できるカスタム コネクタを作成するには、Kiana は Azure ポータル内で次の手順を実行します:
ロジック アプリの 概要 ページで、エクスポート を選択します。

Power Apps へのエクスポート ウィンドウで、コネクタに PartsOrderingConnector という名前を付け、Power Apps 環境を選択してから、OK を選択します。

Power Apps にサインインします。
ご使用の環境の、データ の下で、カスタム コネクタ を選択し、PartsOrderingConnector が表示されていることを確認します。

Maria は、VanArsdel アプリを変更して、技術者が顧客サイトにアクセスしながら部品を注文できるようになりました。 彼女は次のように、注文 ボタンを PartDetails 画面に追加します:
Power Apps にサインインします (まだサインインしていない場合)。
アプリ の下で、VanArsdelApp アプリを選択します。 アプリの省略記号メニューで、編集 を選択します。
データ ウィンドウで、データの追加 を選択し、PartsOrderingConnector コネクタを検索し、そのコネクタを使用して新しい接続を追加します。

ツリー ビュー ウィンドウで、PartDetails 画面を展開してから、DetailForm1 フォームを展開します。
右側の プロパティ ウィンドウで、フィールドの編集 を選択します。 フィールド ウィンドウの、省略記号メニューで、カスタム カードの追加 を選択します。

ツリー ビュー ウィンドウで、新しいカードの名前を DataCard1 から ReserveCard に変更します。 デザイン ビュー ウィンドウで、カードのサイズを変更して、画面の下部、Image_DataCard1 コントロールの下を占めるようにします。

挿入 メニューで、入力 サブ メニューから、テキスト入力 コントロール、ボタン コントロール、および ラベル コントロールを ReserveCard コントロールに追加します。
コントロールのサイズを変更して、ボタン コントロールを テキスト入力 コントロールの右側に、ラベル を ボタン コントロールの下に隣接するように配置します。
テキスト入力 コントロールの プロパティ ウィンドウで、既定 プロパティを解除します。
ボタン コントロールの プロパティ ウィンドウで、テキスト プロパティを 予約 に設定します。

テキスト入力 コントロールの名前を NumberToReserve に変更し、ボタン コントロールの名前を 予約 に変更し、ラベル コントロールの名前を メッセージ に変更します。
メッセージ コントロールの プロパティ ウィンドウで、テキスト プロパティを 予約済部品 に設定し、表示 プロパティを MessageIsVisible に設定します。
注意
MessageIsVisible は画面が表示された場合に false に初期化する変数ですが、ユーザーが 予約 ボタン選択すると true に変更されます。
予約 ボタン コントロールの OnSelect プロパティを次の式に設定します。
FieldEngineerPartsOrdering.manualinvoke({boilerPartId:ThisItem.id, engineerId:"ab9f4790-05f2-4cc3-9f01-8dfa7d848179", numberToReserve:NumberToReserve.Text}); Set(MessageIsVisible, true);注意
この式は、ハードコーディングされたエンジニア ID を使用して、現在アプリを実行している技術者を表します。 第 8 章では、サインオンしたユーザーの ID を取得する方法について説明します。
さらに、アプリはエラー チェックを実行しません。部品を予約する要求は常に成功することを想定しています。 エラー処理の詳細については、Power Apps の機能のエラーを参照してください。
PartDetails 画面の OnVisible プロパティを Set(MessageIsVisible, false) に設定します。
アプリをテストするには、次の手順を実行します:
ツリー ビュー ウィンドウで、ホーム 画面を選択します。
F5 を選択してアプリをプレビューします。
ホーム 画面で、部品 を選択します。
参照画面で、任意の部品を選択します。
部品詳細 画面で、予約セクションまで下にスクロールし、正の整数値を入力してから、予約 を選択します。 予約済部品 メッセージが表示されることを確認します。

プレビュー ウィンドウを閉じて、Power Apps Studio に戻ります。
Azure ポータルで、InventoryDB SQL データベースのページに移動します。
クエリ エディター を選択し、パスワードを使用して sqladmin としてサインインします。
クエリ 1 ウィンドウで、次のクエリを入力してから、実行 を選択します。 VanArsdel アプリで行った予約が表示されることを確認します。
SELECT * FROM [dbo].[Reservations]
フィードバック
フィードバックの送信と表示