0 フォロワー · 14 投稿

Angular(またはAngularJS)は、JavaScriptをベースにしたオープンソースのフロントエンドWebアプリケーションフレームワークであり、主にGoogleや個人や企業のコミュニティによって維持されており、単一ページアプリケーションの開発で直面する多くの課題に対応しています。 公式サイト

記事 Toshihiko Minamoto · 10月 9, 2025 8m read

少し遅れましたが、モバイルアプリケーションから接続する例を示して Workflow Engine に関する連載記事をようやく締めくくることにします。

前回の記事では、これから説明する例として、患者と担当医師の両方にとって高血圧症などの慢性病状の詳細な管理を可能にするアプリケーションを示しました。 この例では、患者は携帯電話からウェブアプリケーション(基本的に、デバイスに応答するように設計されたウェブページ)にアクセスし、ポータブル血圧計が IRIS インスタンスに送信する測定に基づく通知を受信します。

したがって、IRIS インスタンスへのアクセスは 2 つです。

  • モバイルアプリケーションからのユーザーアクセス。
  • 血圧の測定値を送信するデバイスアクセス。

この記事では、患者が測定値を生成するタスクを管理できる、最初のアクセスを確認します。

モバイルアプリケーションと IRIS の接続

この接続では、IRIS 内でウェブアプリケーションを構成するのが最も単純です。これを行うには、管理ポータルのシステム管理 -> セキュリティ -> アプリケーション -> ウェブアプリケーションからアクセスします。

次に、表示されるリストでアプリケーションの新規作成をクリックすると、以下のような画面が開きます。

この画面で、以下のフィールドを構成しましょう。

  • 名前: IRIS にデプロイされる機能にアクセスできるように公開する URL を定義します。
  • ネームスペース: ウェブアプリケーションを関連付けるネームスペースです。これによって、後で相互運用性プロダクションの機能を利用できるようになります。
  • REST: 公開するものが HTTP 接続を可能にする REST API であるため、このオプションを選択します。
  • ディスパッチクラス: HTTP 呼び出しを受け取り、その処理を決定する ObjectScript クラス。
  • JWT 認証を使用する: このオプションをオンにすると、アプリケーションに定義した URL の /login および /logout エンドポイントが有効になるため、IRIS への呼び出しを認証するための JSON ウェブトークンを取得できるようになります。
  • セキュリティ設定 -> 許可される認証方法: 呼び出しを安全にするためにパスワードを設定します。

Workflow.WS.Service クラスを確認しましょう。

Class Workflow.WS.Service Extends%CSP.REST
{

Parameter HandleCorsRequest = 0;Parameter CHARSET = "utf-8"; XData UrlMap [ XMLNamespace = "https://www.intersystems.com/urlmap" ] { <Routes> <Route Url="/getTasks" Method="GET" Call="GetTasks" /> <Route Url="/saveTask" Method="POST" Call="SaveTask" /> </Routes> }

ClassMethod OnHandleCorsRequest(url As%String) As%Status { set url = %request.GetCgiEnv("HTTP_REFERER") set origin = $p(url,"/",1,3) // origin = "http(s)://origin.com:port"// here you can check specific origins// otherway, it will allow all origins (useful while developing only)do%response.SetHeader("Access-Control-Allow-Credentials","true") do%response.SetHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE,OPTIONS") do%response.SetHeader("Access-Control-Allow-Origin",origin) do%response.SetHeader("Access-Control-Allow-Headers","Access-Control-Allow-Origin, Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control") quit$$$OK }

ClassMethod GetTasks() As%Status { Try { Do##class(%REST.Impl).%SetContentType("application/json") If '##class(%REST.Impl).%CheckAccepts("application/json") Do##class(%REST.Impl).%ReportRESTError(..#HTTP406NOTACCEPTABLE,$$$ERROR($$$RESTBadAccepts)) QuitDo##class(%REST.Impl).%SetStatusCode("200") set sql = "SELECT %Actions, %Message, %Priority, %Subject, TaskStatus_TimeCreated, ID FROM EnsLib_Workflow.TaskResponse WHERE TaskStatus_AssignedTo = ? AND TaskStatus_IsComplete = 0"set statement = ##class(%SQL.Statement).%New(), statement.%ObjectSelectMode = 1set status = statement.%Prepare(sql) if ($$$ISOK(status)) { set resultSet = statement.%Execute($USERNAME) if (resultSet.%SQLCODE = 0) { set tasks = [] while (resultSet.%Next() '= 0) { set task = {"actions": "", "message": "", "priority": "", "subject": "", "creation": "", "id": ""} set task.actions = resultSet.%GetData(1) set task.message = resultSet.%GetData(2) set task.priority = resultSet.%GetData(3) set task.subject = resultSet.%GetData(4) set task.creation = resultSet.%GetData(5) set task.id = resultSet.%GetData(6) do tasks.%Push(task) }
} } set result = {"username": ""} set result.username = $USERNAMEDo##class(%REST.Impl).%WriteResponse(tasks)

} <span class="hljs-keyword">Catch</span> (ex) {
    <span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%SetStatusCode</span>(<span class="hljs-string">"400"</span>)
    <span class="hljs-keyword">return</span> ex.DisplayString()
}

<span class="hljs-keyword">Quit</span> <span class="hljs-built_in">$$$OK</span>

}

ClassMethod SaveTask() As%Status { Try { Do##class(%REST.Impl).%SetContentType("application/json") If '##class(%REST.Impl).%CheckAccepts("application/json") Do##class(%REST.Impl).%ReportRESTError(..#HTTP406NOTACCEPTABLE,$$$ERROR($$$RESTBadAccepts)) Quit// Reading the body of the http call with the person dataset dynamicBody = {}.%FromJSON(%request.Content)

    <span class="hljs-keyword">set</span> task = <span class="hljs-keyword">##class</span>(EnsLib.Workflow.TaskResponse).<span class="hljs-built_in">%OpenId</span>(dynamicBody.<span class="hljs-built_in">%Get</span>(<span class="hljs-string">"id"</span>))
    <span class="hljs-keyword">set</span> sc = task.CompleteTask(dynamicBody.action)

    <span class="hljs-keyword">if</span> <span class="hljs-built_in">$$$ISOK</span>(sc) {	        
        <span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%SetStatusCode</span>(<span class="hljs-string">"200"</span>)
        <span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%WriteResponse</span>({<span class="hljs-string">"result"</span>: <span class="hljs-string">"success"</span>})         
	}	
    
} <span class="hljs-keyword">Catch</span> (ex) {
    <span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%SetStatusCode</span>(<span class="hljs-string">"400"</span>)
    <span class="hljs-keyword">Do</span> <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%REST.Impl</span>).<span class="hljs-built_in">%WriteResponse</span>({<span class="hljs-string">"result"</span>: <span class="hljs-string">"error"</span>})
}

<span class="hljs-keyword">Quit</span> <span class="hljs-built_in">$$$OK</span>

}

}

ご覧のとおり、WS から必要なすべてのロジックを解決していますが、この方法は推奨されません。ネームスペースに構成されたプロダクションに受信したリクエストを送信することで可能なトレーサビリティを失ってしまうためです。

URLMap セクションを確認すると、2 つのエンドポイントが WS で構成されていることが分かります。

  • getTasks: ユーザーのすべての保留中のタスクを復旧します(使用されている SQL を見ると、ログインしたときに生成される変数から直接ユーザー名を渡しています)。
  • saveTask: ユーザーのタスクへのレスポンスを受信し、EnsLib.Workflow.TaskResponse クラスの CompleteTaks メソッドを実行することで、タスクの終了に進みます。

IRIS の部分では、外部アプリケーションが接続できるようにすべてが構成済みです。

Workflow Engine で外部アプリケーションをテストする

まず、ファイル /shared/hl7/message_1_1.hl7 をパス /shared/in にコピーすることで、HL7 からプロダクションへのメッセージの送信をシミュレーションします。送信するメッセージを確認しましょう。

MSH|^~\&|HIS|HULP|EMPI||20240402111716||ADT^A08|346831|P|2.5.1
EVN|A08|20240402111716
PID|||07751332X^^^MI^NI~900263^^^HULP^PI||LÓPEZ CABEZUELA^ÁLVARO^^^||19560121|F|||PASEO MARIO FERNÁNDEZ 2581 DERECHA^^MADRID^MADRID^28627^SPAIN||555819817^PRN^^ALVARO.LOPEZ@VODAFONE.COM|||||||||||||||||N|
PV1||N
OBX|1|NM|162986007^Pulso^SNM||72|^bpm|||||F|||20240402111716
OBX|2|NM|105723007^Temperatura^SNM||37|^Celsius|||||F|||20240402111716
OBX|3|NM|163030003^Presión sanguínea sistólica^SNM||142|^mmHg|||||F|||20240402111716
OBX|4|NM|163031004^Presión sanguínea diastólica^SNM||83|^mmHg|||||F|||20240402111716

前回の記事を覚えていらっしゃらない方のために説明すると、BPL は収縮期血圧が 140 を超えるか拡張期血圧が 90 を超えるとアラートが生成されるように定義していたため、このメッセージにより、DNI(スペインの身分証明書)が 07751332X である患者に対する警告タスクと、IRIS が新しい通知を受信するまで開いたままになる別の自動タスクが生成されます。

モバイルアプリケーションを確認しましょう。

2 つのタスクが生成されています。1 つは手動タスクとして定義されており、ユーザーによって終了方法が異なります。もう 1 つは自動タスクとして宣言されており、それを終了するには、ユーザーが血圧計で新しい測定を行う必要があります。 HTTP 呼び出しを見てみると、これにどのように JWT を含めているのかが分かります。

ユーザーが保留中のタスクの Accept ボタンをクリックすると、このフローは血圧計の測定値の受信を待機したままとなり、次のステップに進みません。 手動タスクが受け入れられ、血圧計からの新しい測定値を受信し、それがもう一度制限を超えている場合は、システムは患者向けのタスクと、関連する医師向けに危険な状態の可能性を警告するタスクの 2 つの新しい警告タスクを生成します。 :

完璧です! 患者通知システムは素早く簡単にセットアップ済みです。

まとめ

この連載記事でご覧になったとおり、Workflow Engine の機能と InterSystems IRIS の相互運用性機能を合わせることで、他のビジネスソリューションではほとんど実現できないビジネス プロセスの実装において、驚異的な可能性を切り開くことができます。 最大限に活用するためには、技術的な知識が必要となる可能性がありますが、実際に必要な取り組みを投じる価値はあります。

0
0 23
記事 Toshihiko Minamoto · 5月 22, 2025 6m read

しばらくの間、私はワークフロー機能について何らかの概念実証を行おうと計画していましたが、これは IRIS に存在する他の多くの機能と同様に、お客様にほとんど気付かれないまま終わってしまう傾向があります(その点については申し訳ありません)。 そこで数日前、この機能を構成して、Angular で開発したユーザーインターフェースに接続して使用するための例を作成することに決めました。

記事が非常に長くならなずに読みやすくするために、3 部に分けて説明しようと思います。 この最初の記事では、Workflow の機能とこれから解決する例について説明します。 2 つ目の記事では、Workflow の管理を担うプロファクションの構成と実装について詳しく説明します。 最後に、ウェブアプリケーションを通じて Workflow にある情報にアクセスする方法を説明します。

InterSystems IRIS Workflow Engine

この Workflow 機能を説明するには、IRIS ドキュメントに記載の説明をコピーするのが一番でしょう。

ワークフロー管理システムは、ユーザーへのタスクの分配を自動化します。 事前定義済みの戦略に従ってタスクの分配を自動化することによって、より効率的にタスクを割り当て、タスクの実行に対する責任感を高めることができます。 一般的な例は、顧客から問題に関する報告を受け取り、適切に対応できる組織のメンバーにその報告を送信し、問題が解決したら結果を顧客に報告するヘルプデスクアプリケーションです。

InterSystems IRIS Workflow Engine は、従来のスタンドアロン型のワークフロー管理システムよりもはるかに高レベルの機能を提供しています。

この Workflow 機能は IRIS のどこにあるのでしょうか? 非常に簡単です。管理ポータルからアクセスできます。

サンプルプロジェクトを詳しく見る前に、使用できる各オプションを簡単に説明します。

ワークフローロール

このオプションは、機能を使用するユーザーのロールを分類します。 ロールの定義に混乱するかもしれませんが、プロダクションから作成できるタスクのタイプとして考えています。 これらのロールに割り当てられる名前は、後でプロファクションで宣言し、そのロールに関連するタスクを作成するビジネスオペレーションの名前に一致する必要があります。

ワークフローユーザー

様々なタスクに割り当てられる IRIS ユーザーは、1 つ以上のロールに関連付けられます。 ユーザーは IRIS に登録されている必要があります。

ワークフロータスク

関連情報と共にシステムで作成されるタスクのリスト。 このウィンドウから、タスクのロールに応じた様々なユーザーにタスクを割り当てられます。

タスクは何でしょうか? 非常に簡単です。タスクは、EnsLib.Workflow.TaskRequest クラスのインスタンスであり、このタイプのオブジェクトは、生成されたビジネスプロセスから、クラス EnsLib.Workflow.Operation のビジネスオペレーションに、以前に作成したロールの名前とともに送信されます。 このアクションによって、EnsLib.Workflow.TaskResponse クラスのインスタンスが作成されます。 ビジネスオペレーションは、TaskResponse クラスインスタンスの CompleteTask メソッドが実行されるまで、レスポンスを返しません。

ワークフロー作業リスト

前の機能と同様に、関連する情報と共にタスクのリストも表示されます。

ワークフローの例

この記事に関連するプロジェクトには、慢性患者の治療など、医療組織の一般的な問題に対するソリューションを単純化した例が含まれます。 こういったタイプの患者には、継続的な管理と厳格なモニタリングが必要で、多くの場合、治療に関わる医療専門家にはそれらを行うための最適な手段がありません。

この例では、高血圧症の患者をモニタリングする方法を確認したいと思います。 患者は毎日、血圧計で血圧を測り、その血圧計から InterSystems IRIS がインストールされたサーバーにその読み取り値が送信されることを前提とします。 血圧測定値の収縮期血圧が 140、拡張期血圧が 90 を超える場合、その患者には特定の期間が過ぎてからもう一度血圧を測るように通知されます。2 回目の測定値がもう一度制限を超えた場合、患者と医師の両方にその状況が通知され、処置を決定することができます。

これを行うには、このタスクフローを 2 つのステージに分割します。

ステージ 1: 血圧測定値を毎日受信する。

  1. HL7 メッセージと血圧測定値をプロダクションで受信します。
  2. システムでユーザーの存在をチェックし(存在しない場合は作成)、その後で、ワークフローに関わるロールにユーザーを登録します。
  3. 血圧データを抽出し、アラート基準と比較します。
  4. データがアラート基準を超える場合:
    1. 状況を説明し、血圧をもう一度測定するように要求するための、患者向けのタスクを作成します。
    2. 2 回目の血圧測定値を管理するための自動タスクを作成します。
  5. データがアラート基準を超えない場合、このプロセスは次回の読み取りが翌日受信されるまで閉じられます。

ステージ 2: 最初の測定値がアラート値を超えた後の 2 回目の測定値を受信します。

  1. HL7 メッセージと 2 回目のデータ測定値を受信します。
  2. 自動タスクの復旧が保留されます。
  3. 血圧レベルがアラート基準を超える場合:
    1. 自動タスクは警告ステータスを示して中止されます。
    2. 患者の状況を報告する医師の手動タスクが作成されます。
    3. 状況と、医師に報告されたことを警告する患者の手動タスクが作成されます。
  4. レベルがアラート基準を超えない場合:
    1. 自動タスクは危険がないことを示して中止されます。

次の記事では、上記で説明した内容を反映するフローチャートのデザインについてより詳しく説明します。

ユーザーインターフェース

添付されたスクリーンショットからわかるように、InterSystems IRIS がタスク管理用に提供するユーザーインターフェースは控えめに言っても質素ではありますが、IRIS で得られるメリットの 1 つは、非常に簡単な方法でタスクフローを管理するための API REST を独自に作成できることです。この点については、最後の記事で説明します。

ユーザーに使いやすいインターフェースを提供するために、Angular Material を使用して、Angular で小さなウェブアプリケーションを開発しました。モバイルアプリケーションをシミュレーションするインターフェースを作成できます。

このモバイルアプリケーションは JSON Web Tokens を使って InterSystems IRIS に接続し、IRIS に公開された特定のウェブアプリケーションに HTTP リクエストを送信します。これにより、タスクに対してさまざまなアクターが実行したアクションが、定義されたタスクフローに反映されます。

次回の記事では...

この記事では Workflow の機能に関する紹介を終えたため、次の記事では、BPL を使って提供した例を解決するために必要なタスクフローを実装する方法を説明します。プロダクション全体を構成し、Workflow に関わるメインのクラス(EnsLib.Workflow.TaskRequestEnsLib.Workflow.TaskResponse など)を確認します。

お読みいただきありがとうございました!

0
0 36
記事 Toshihiko Minamoto · 5月 22, 2025 7m read

前回の記事では、一般的な概念と、InterSystems IRIS に統合されたタスクエンジンを使用して解決する問題を紹介しました。今回の記事では、相互運用性プロダクションを構成してソリューションを提供する方法を確認します。

Workflow Engine の構成

First we are going to define the roles of the tasks that we are going to manage, in our example we are going to define two types:

  • AutomaticBloodPressureRole: ユーザーの介入が不要な自動タスクを作成します。
  • ManualBloodPressureRole: ユーザーが手動で検証する必要のあるタスクを作成します。

後で様々な患者から HL7 メッセージを受信するたびにロールをユーザーに割り当てるため、ここでは割り当てる必要はありません。

また、IRIS ユーザーを Workflow に追加する必要もありません。これはプロダクションからコードで実行します。

プロダクションのセットアップ

この例では、アドホックで作成した「WORKFLOW」というネームスペース内にプロダクションを作成します。 このプロダクションに、必要とするビジネスコンポーネントを含めます。

最も単純なコンポーネントから説明し始めましょう。

ビジネスサービス

  • HL7_File_IN: 医療装置からのメッセージの受信をシミュレーションする特定のサーバーパスから HL7 ファイルを収集します。

ビジネスオペレーション

  • AutomaticBloodPressureRole: クラス EnsLib.Workflow.Operation のコンポーネント。Workflow で生成するために使用する、定義済みのロールの 1 つの名前を使用します。ユーザーとの直接的な対話を伴わないタスクです。
  • ManualBloodPressureRole: 前のビジネスオペレーションに似ていますが、この場合、生成するタスクには、それらをクローンするための直接的なユーザーの介入が必要です。

では、情報のフロー、およびサイクルに関連するタスクの作成と管理を管理するビジネスプロセスを詳しく見てみましょう。

Workflow.BP.BloodPressurePlan

このビジネスプロセスは BPL タイプで、患者のケアに関わるタスクの作成と、患者と血圧レベルに関連する情報を送信する医療装置からのレスポンスの取得を行います。

プロセスの開始:

この部分のフローは以下を行います。

  1. ユーザーのチェック: 受信した ADT^A08 メッセージのユーザーをチェックします。存在する場合はフローを続行し、存在しない場合は IRIS にユーザーを作成して、ワークフローに定義されたロールに割り当てます。 ユーザーをロールに割り当てるには、以下のコマンドを実行します。
    /// Workflow user creationset sc = ##class(EnsLib.Workflow.UserDefinition).CreateUser(username)
    /// Assigning Workflow user to the roleset sc = ##class(EnsLib.Workflow.RoleDefinition).AddUserToRole(role, username)
  2. 自動タスクの取得: このフローでは、自動タスクと手動タスクの両方を管理するため、受信した患者のユーザーに保留中の自動タスクがないかをチェックする必要があります。 保留中の自動タスクがある場合は、ノーマルレベルを超える値を持つ前の測定値があることを意味するため、重要です。 このチェックは、すべての作成されたタスクが保存されている TaskResponse テーブルで直接行います。クエリは以下のとおりです。
    &sql(SELECTIDINTO :taskId FROM EnsLib_Workflow.TaskResponse WHERE TaskStatus_AssignedTo = :username AND TaskStatus_IsComplete = 0AND %RoleName = :role)
  3. OBX 数の取得: HL7 メッセージから OBX セグメントの数を取得します。
  4. OBX 値の確認: OBX セグメントを確認し、血圧に関連するデータのみを抽出します。
  5. 保留中のタスクの有無: 2 番目のポイントで述べたように、保留中のタスクがあるかどうかを確認します。

1 回目の血圧測定:

この部分のフローでは、定義された最大血圧レベルを超える 1 回目の測定によって生成されていないメッセージを処理します。

  1. 血圧の確認: 血圧レベルが既定の制限を超えていないかをチェックします。超えていない場合は、プロセスは他の作業を行わずに終了します。 超えている場合は、櫃湯尾なタスクを作成する必要があります。
  2. 手動タスクの作成: 血圧が定義された安全レベルを超過している場合は、患者に状況を報告し、2 回目の測定が必要であることを示す手動タスクを作成する必要があります。 このアクティビティの構成を確認しましょう。    
    1. ビジネスオペレーション ManualBloodPressureRole を呼び出します。これにより、EnsLib.Workflow.TaskRequest タイプのメッセージを渡してタスクが生成されます。
    2. callrequest.%Actions に患者が実行できるアクションをカンマ区切りで定義します。ここでは、"Accept" アクションのみを定義しています。
    3. 患者に示すメッセージを callrequest.%Message に構成します。
    4. callrequest.%UserName でユーザー名を定義することで、作成したタスクに患者を割り当てます。
    5. 最後に、callequest.%Subject に題名またはタイトルを指定し、callrequest.%Priority に優先度(1~3)を指定します。
  3. 自動タスクの作成: 前のアクティビティの構成に似ていますが、ここではビジネスオペレーション AutomaticBloodPressureRole に送信します。 このタスクは、患者の 2 回目の血圧測定を待機するタスクで、保留中のタスクの有無のアクティビティで false を取得することによって、その患者に対してプロダクションで受信した新しいメッセージが新しいタスクを生成しないようにするタスクです。
  4. タスクの待機: このアクティビティは、タスクと手動操作が完了するまで、つまり、患者が ManualBloodPressureRole で作成されたアラームを閉じて IRIS プロダクションが医療装置から 2 回目のメッセージを受け取るまでタスクフローを停止します。
  5. 警告の有無のチェック: 前の保留中のタスクがクローズされたら、このアクティビティに進みます。 この時点では、自動タスクのクローズにおいて、構成された最大血圧値を超えるレベルの新しい測定を受信(タスクは警告アクションによってクローズされます)したかどうかを確認します。 測定値が最大値未満である場合、このプロセスは終了します。 測定値が最大値を超える場合は、次のアクティビティに進みます。
  6. 医師の警告タスク: 患者に割り当てられた医師に対し、患者が危険な状態にある可能性があることを報告する手動タスクが作成されます。
  7. 患者の警告タスク: 患者に対し、医師が状況が報告されたことを示す新しい手動タスクが作成されます。

2 回目の血圧測定:

この部分のフローは、前に作成された自動タスクが完了しなかった場合にのみ実行されます。

  1. 血圧のチェック: もう一度、血圧値が制限を超えるかどうかについて受信したメッセージを検証します。
  2. 通常タスクの終了: レベルが最大値を超えていない場合、タスクがインスタンス化する EnsLib.Workflow.TaskResponse クラスが提供する CompleteTask メソッドで保留中のタスクをクローズします。 使用されるパラメーターは対応処置を示しますが、この場合、FalseAlarm 値を渡して語法であることを示します。必要に応じて他の内容を定義することも可能です。
  3. 警告タスクの終了: 前の場合と同じですが、この場合に Workflow エンジンに渡すアクションは Warning であり、前の「警告の有無のチェック」アクティビティでチェックされる値です。

以下のダイアグラムで確認できるように(文字通りではありませんが、仕組みを把握することはできます)、タスクフローは 2 つの「スレッド」または「プロセス」で機能するようになっています。

最初のスレッド/プロセスは、2 回目の測定を待機する必要がある場合に備えてオープン状態のままとなり、2 回目の測定を受信したときに最初のオープンスレッドの再開を引き起こす、つまり定義されたタスクフローを終了するのは、2 つ目のスレッド/プロセスです。

まとめ

ご覧のように、BPL でタスクを構成するのは非常に単純です。それほど複雑な作業を行わずに、自動タスクと手動タスクをシミュレーションできます。 次の記事がこのシリーズの最後となりますが、ユーザーが外部アプリケーションからタスクを操作する方法を確認しましょう。

お読みいただきありがとうございました!

0
0 38
記事 Toshihiko Minamoto · 5月 16, 2025 5m read

Auth0 と InterSystems IRIS FHIR リポジトリ使った SMART On FHIR に関する連載最終回では、Angular 16 で開発したアプリケーションをレビューします。

このソリューションに定義されたアーキテクチャがどのように構成されているかを思い出しましょう。

フロントエンドのアプリケーションは 2 列目で、ご覧のように 2 つのことを行います。

  1. ログインリクエストを Auth0 にリダイレクトし、レスポンスを受信する。
  2. REST 経由でリクエストを FHIR サーバーに送信し、そのレスポンスを受信する。

Angular

Angular は TypeScript が開発し、Google が管理するオープンソースの Web アプリケーションフレームワークで、シングルページ Web アプリケーションの作成と管理に使用されます。 この「シングルページアプリケーション」デザイン手法によって、はるかに動的なユーザー向けアプリケーションを設計することができます。 最初の記事で説明したとおり、ここではアプリケーションサーバーとリバースプロキシとして NGINX を使用し、呼び出しヘッダーがサーバーの呼び出しヘッダーに一致するように変更して、CORS から派生する問題を回避します。

アプリケーションのデザイン

モバイルアプリケーションのデザインをシミュレートするように、Angular Material を使ってアプリケーションを設計しました。 この例では、アプリケーションは心拍数、血圧、および体重などの一連の患者データを記録することを目的としており、このために、2 種類の FHIR リソースをサーバーに送信します。1 つ目はユーザーがデータを登録する Patient タイプリソースで、2 つ目は、送信しようとしている各タイプのデータを送信する Observation リソースに対応します。

アプリケーションには、記録されたデータの変化がグラフで表示されます。

ログイン画面

ユーザーがパス https:\\localhost にアクセスすると最初の画面が表示され、そこからログインをリクエストできます。

 

ログインボタンをクリックすると、アプリケーションは構成済みの API に対して有効化された Auth0 ページに自動的にユーザーをリダイレクトします。

ユーザー名とパスワードを入力すると、Auth0 はデータへのアクセス許可をアプリケーションに付与するよう求めます。 データへのアクセスが確認されたら、Auth0 は、構成プロセス中に指定した URL にリダイレクトします。 アクセストークンが生成されると、Auth0 ライブラリは、サーバーに対して発行するすべての呼び出しのヘッダーにそのトークンを含めるようになります。 これは以下の図で確認できます。

最初の画面

ログインが完了すると、ログインユーザーが使用できる情報を FHIR サーバーにリクエストする最初の通信が発生します。これには、パラメーターによるクエリを使用して、次のような GET 呼び出しを送信します。

https://localhost:8443/smart/fhir/r5/Patient?email=lperezra%40intersystems.com

サーバーのレスポンスは次の情報を含む Bundle タイプリソースです。

{
    "resourceType":"Bundle",
    "id":"8c5b1efd-cfdd-11ee-a06b-0242ac190002",
    "type":"searchset",
    "timestamp":"2024-02-20T10:48:14Z",
    "total":0,
    "link":[
        {
            "relation":"self",
            "url":"https://localhost:8443/smart/fhir/r5/Patient?email=lperezra%40intersystems.com"
        }
    ]
}

ご覧のように、そのメールアドレスを使用する患者は合計 0 人であるため、アプリケーションにはデータを登録できる最初の画面が表示されます。

 

ご覧のように、メールアドレスのフィールドにはログインユーザーのアドレスが入力されています。これは、最初のクエリで見たように、メールアドレスを ID として使用するためです。 フォームの入力が完了したら、POST 経由で次のような呼び出しを送信します。

https://localhost:8443/smart/fhir/r5/Patient

Patient リソースによって形成されたメッセージ本文:

{
    "resourceType":"Patient",
    "birthDate":"1982-03-08",
    "gender":"male",
    "identifier":[
        {
            "type":{
                "text":"ID"
            },
            "value":"12345678A"
        }
    ],
    "name":[
        {
            "family":"PÉREZ RAMOS",
            "given":[
                "LUIS ÁNGEL"
                ]
        }
    ],
    "telecom":[
        {
            "system":"phone",
            "value":"600102030"
        },
        {
            "system":"email",
            "value":"lperezra@intersystems.com"
        }
    ]
}

患者データがサーバーに登録され、患者のクエリによって結果が返されるようになったため、さまざまな経過観察を記録できる準備が整いました。 最初の画面がどのように表示されるか見てみましょう。

経過観察画面

患者のデータを送信したのと同じ方法で、特定の画面から経過観察を送信します。

サーバーに送信されたリソースごとに、アプリケーションは新しい点をグラフに追加します。

これを行うために、そのユーザーに属する Observation タイプリソースをリクエストするクエリをサーバーに発行します。

https://localhost/smart/fhir/r5/Observation?patient=Patient/1

すると、サーバーはもう一度、その患者に対して記録されたすべての経過観察を含む Bundle タイプリソースを返します。

結果が取得されたので、アプリケーションはすべての数値を抽出し、関連するグラフを構築します。

まとめ

この記事と前回の 2 つの記事で確認したように、SMART On FHIR アプリケーションの設計と作成はそれほど複雑ではなく、FHIR サーバーで使用できるすべての機能を利用するアプリケーションを素早くアジャイルに構築することができます。

この種のアプリケーションでは、データに対する CRUD タイプの操作を管理する複雑なバックエンドの開発が不要であり、OAuth2 を使用することで、アプリケーションのユーザーを管理する必要もありません。その機能は Auth0 または選択した認証・承認サーバーに任せることができます。

SMART On FHIR では、簡単かつ単純な方法で、患者と医療専門家に対し医療データ管理に必要なツールを提供することができます。

お読みいただきありがとうございました!

0
0 40