コード初心者でも大丈夫。Einstein GPTでApex開発に挑戦！

# はじめに

こんにちは。本エントリーでは、2023/11/28(火) Salesforce World Tour Tokyo にて開催されたハンズオンワークショップ 「**コード初心者でも大丈夫。Einstein GPTでApex開発に挑戦！**」 で使用した手順書を公開します。
* 当日の参加者のかたで時間が足りなかった方は、ぜひ復習してみてください！
* 社内でワークショップを開催する際にはぜひご利用ください！！
* コメント欄にて感想もお待ちしております！！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/400fe340-9ddf-83ca-2d02-0ba66e768786.png)

# 0) 事前準備

ハンズオンを進めるために、まずはローカルの開発環境を整えてください。

https://qiita.com/takahito0508/items/809b278cd01bd1981219

ローカル環境の準備ができたら、Windows PowerShell を使ってSFDXプロジェクトを作成してください。

```sh
cd $HOME/Desktop

sf project generate -n demo -x
```

作成したSFDXプロジェクトディレクトリ直下に `node_modules` をインストールします。

```sh
cd demo

yarn install
```

ハンズオンに利用するSalesforce Developer edition環境を取得しましょう。

https://developer.salesforce.com/signup

取得した環境へアクセスし、Einstein for Developers機能を有効化してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/13c271e6-1ac6-b393-d1d5-80bc3518f061.png)

Einstein for Developers機能を有効化した環境をデフォルト組織として認証します。ログイン画面がブラウザで開いたら、ユーザ名・パスワードを入力して認証を完了させてください。

```sh
sf org login web -a demo -s
```

VS Codeを開き、拡張機能の読み込みが完了していれば、準備完了です！

```sh
code .
```

完了かどうかのチェック観点を赤で囲んでいます。拡張機能の読み込みが完了していなければ、数分待ちましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/c3df3128-d5e0-dc54-389a-d0694ede2e75.png)

さて、準備はよろしいですか？それでは、ハンズオンを始めます！
動画を見ながら一緒に進めていただいても、インストラクションだけを頼りに自力で進めていただいても、どちらでも結構です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/0edafbf0-0174-18de-5a44-97e7b4dd8b7a.png)

# 1) 画面フローを作成して動作確認

## 動画

https://youtu.be/uBrtexTEU4w

## インストラクション

* ハンズオン用のSalesforce環境へログインする
    * VS Code のターミナルで次のコマンドを実行する
```sh
sf org open -o demo
```

* 画面フローを作成する
    * [設定] > [プロセスの自動化] > [フロー] > [新規フロー] をクリックする
    * [画面フロー] > [作成] をクリックする
    * [画面フロー 開始] の下にコンポーネントを追加する
        * [画面] をクリックする
    * [画面のプロパティ] へ情報を入力する
        * [表示ラベル] Welcome
        * [API 参照名] Welcome
    * [項目] タブからレコード項目を追加する
        * [レコード変数] > [新規リソース] をクリックする
        * [新規リソース] へ情報を入力する
            * [API 参照名] newCase
            * [データ型] レコード
            * [オブジェクト] ケース
        * [完了] をクリックする
    * [フローの表示ラベル] の下に複数の項目をドラッグ＆ドロップする
        * 件名
        * 状況
        * 優先度
    * [新規画面] を閉じる
        * 一番外側の [完了] をクリックする
        * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/9edb220a-ef40-8079-9595-74b496dff55a.png)
    * [Welcome 画面] の下にコンポーネントを追加する
        * [レコードを作成] をクリックする
    * [新規のレコードの作成] へ情報を入力する
        * [表示ラベル] Create New Case
        * [API 参照名] Create_New_Case
        * [レコード] newCase
    * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/fd21ecf8-3845-bc16-1d17-01bccd336f5d.png)
    * [Create New Case レコードを作成] の下にコンポーネントを追加する
        * [画面] をクリックする
    * [画面のプロパティ] へ情報を入力する
        * [表示ラベル] Good Bye
        * [API 参照名] Good_Bye
    * [フローの表示ラベル] の下にコンポーネントをドラッグ＆ドロップする
        * コールスクリプト
    * [コールスクリプト] へ情報を入力する
        * [API 参照名] Output
        * [スクリプトテキスト] ① newCase を選択する > ② Id を選択する
    * [新規画面] を閉じる
        * 一番外側の [完了] をクリックする
    * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/c96866df-a730-90d7-15f3-12ca259d4488.png)
    * [保存] をクリックする
    * [フローを保存] へ情報を入力する
        * [フローの表示ラベル] Create Case and Next Actions
        * [API 参照名] Create_Case_and_Next_Actions
    * [保存] をクリックする
    * [有効化] をクリックする
* ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/91a06de5-7e10-f63c-ee09-b2bea786ddf3.png)
* フロービルダー画面を閉じて、設定画面に戻る
* ホーム画面に画面フローを配置する
    * アプリケーションランチャーのアイコン > [セールス] をクリックする
    *  [設定] > [編集ページ] をクリックする
    * [アシスタント] の下にコンポーネントをドラッグ＆ドロップ
        * フロー
    * [ページ > フロー] へ情報を入力する
        * [フロー] Create Case and Next Actions
    * [保存] をクリックする
    * [有効化] をクリックする
    * [組織のデフォルトとして割り当て] をクリックする
    * [保存] をクリックする
* ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/87df32e1-2313-2459-d2cd-de8882a3313e.png)
* ホーム画面へ戻る
* ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/bbb6f6ef-2a1b-5a8c-d3a5-25876d8b0b1f.png)
* 動作確認する
    * [Create Case and Next Actions] へ情報を入力する
        * [件名] 好きな値
        * [状況] 好きな値
        * [優先度] 好きな値
    * [次へ] をクリックする
    * レコードIDが表示されることを確認する
    * [クリップボードへコピー] をクリックしてレコードIDをコピーできたことを確認する
        * メモ帳などへ貼り付けてみる
    * [完了] をクリックする
* ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/15019de4-eda9-1b65-c15b-54059f36b1f1.png)

# 2) Einstein GPTを活用してApexを開発

## 動画

https://youtu.be/Bu96_0YFyl0

## インストラクション

* ウォーミングアップ 1： Einstein GPTの雰囲気を知ろう
    * VS Codeの左サイドバーの [Einstein Sidebar] をクリックする
    * 次の要件を満たす文章を日本語で自由に入力する
        * デバッグログに「Hello, Einstein!!」と出力する
        * 例： デバッグログに「Hello, Einstein!!」と出力するApexクラスを書いてください
    * [Ask] をクリックする
    * 生成されたコードを眺める
        * 要件を満たしているか
        * もし自力で書いた場合と比べてみてどうか
* ウォーミングアップ 2： Einstein GPTの実力を試してみよう
    * 次の要件を満たす文章を日本語で自由に入力する
        * 取引先オブジェクトに次のチェックボックス項目が存在することを前提とする
            * [名前] 納入先住所と同じ
            * [API 参照名] IsSameAsShippingAddress__c
        * 「納入先住所と同じ」チェックボックスがONの場合、Apexトリガーで請求先住所の値へ納入先住所の値をコピーする
        * 例： 取引先には「納入先住所と同じ」という名前のチェックボックス項目があります。API名はIsSameAsShippingAddress__cです。この項目がtrueの場合に、請求先住所に納入先住所の値をコピーするApexトリガーを作成してください
    * [Ask] をクリックする
    * 生成されたコードを眺める
        * 要件を満たしているか
        * もし自力で書いた場合と比べてみてどうか
* いよいよ実践： VS CodeでApexクラスを作成する
    * Ctrl + Shift + P を押下する
    * `SFDX` と入力し、[SFDX: Create Apex Class] を選択する
    * `CsvFormator` と入力し、Enter を押下する
    * `force-app/main/default/classes` を選択する
    * `CsvFormator.cls` が自動で開くことを確認する
* サンプルコードをコピペする
    * `CsvFormator.cls` の中身のコードをすべて削除する
    * 次のコードをコピペする

:::note warn
コードのインデント等がバラバラなのは、意図的なものです
:::

```apex
@SuppressWarnings('PMD.AvoidGlobalModifier,PMD.ApexDoc')
        global with sharing class CsvFormator{
          @InvocableMethod(
           label='Formats a record into a CSV string'
              category='Strings'
          )
         global static List<OutputParameters> bulkInvoke(
             List<InputParameters> inputs) {
            List<OutputParameters> outputs = new List<OutputParameters>();
            for (InputParameters input : inputs) {
                   outputs.add(invoke(input));
            }
             return outputs;
          }
        
          private static OutputParameters invoke(InputParameters input){
            Id caseId = input.inputRecordId;
        
            // TODO: Ask to Einstein
                
        
            OutputParameters output = new OutputParameters();
            output.outputCsvString= csvString;
            
            
            
            return output; 
            
          }
        
          global class InputParameters {
            @InvocableVariable(label='Record Id'  required=true)
             global Id   inputRecordId ;
          }
        
        global class OutputParameters {
             @InvocableVariable(label ='CSV String')
            global String outputCsvString;
          }
}
```

* `TODO: Ask to Einstein` の箇所にコードを追加する
    * VS Codeの左サイドバーの [Einstein Sidebar] をクリックする
    * 次の要件を満たす文章を日本語で自由に入力する
        * ケースレコードを取得する
            * 項目： ケースID、件名、状況、優先度
            * 条件： ケースIDが変数 caseId と一致する
        * 取得したケースレコードの項目をカンマ区切りの文字列へ変換する
        * 変換した値を変数 csvString へ代入する
    * 例： IDがcaseIdと一致することを条件にCaseレコードを検索する。取得したCaseレコードのID、件名、ステータス、優先度をカンマ区切りの文字列へ変換し、変数csvStringへ代入する。
    * [Ask] をクリックする
    * 生成されたコードを眺める
        * 要件を満たしているか
        * もし自力で書いた場合と比べてみてどうか
    * 必要な部分だけコピペする
    * 変数名の不備など、必要に応じて手で修正する
    * VS Codeでデプロイする
        * ファイル上で右クリック > [SFDX: Deploy This Source to Org] をクリックする
        * エラーがないこと確認する

### オプション

#### おすすめ その1： コード整形 (Prettier)

* ファイル上で右クリック > [Format Document] をクリックする
* コードが綺麗にフォーマットされたことを確認する
* VS Codeでデプロイする
    * ファイル上で右クリック > [SFDX: Deploy This Source to Org] をクリックする
    * エラーがないこと確認する

#### おすすめ その2： 静的コード解析 (Salesforce Code Analyzer)

* ファイル上で右クリック > [SFDX: Scan current file with Code Analyzer] をクリックする
* [Problems] タブに警告が表示されることを確認する
    * 例） `ApexCRUDViolation`： SOQLを実行する前にオブジェクト権限を検証していない場合、あるいはユーザーモードで実行されていない場合に警告される
* 可能であれば、警告が解消されるようにコードを修正する
* VS Codeでデプロイする
    * ファイル上で右クリック > [SFDX: Deploy This Source to Org] をクリックする
    * エラーがないこと確認する

# 3) 画面フローへApexを配置して動作確認

## 動画

https://youtu.be/a9jdTygoViA

## インストラクション

* 画面フローを修正する
    * [設定] > [プロセスの自動化] > [フロー] > [Create Case and Next Actions] をクリックする
    * [Create New Case レコードを作成] の下にコンポーネントを追加する
        * [アクション] をクリックする
        * [Strings] > [アクション] > [Formats a record into a CSV string] をクリックする
    * [新規アクション] へ情報を入力する
        * [表示ラベル] Format
        * [API 参照名] Format
        * [Record ID] ① newCase を選択する > ② Id を選択する
    * [完了] をクリックする
    * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/8cce17c0-5058-c8db-0484-0b703c18ba5c.png)
    * [Good Bye 画面] をクリックする
    * [要素を編集] をクリックする
    * 既存の [コールスクリプト] をクリックする
    * 既存の [コールスクリプト] の情報を変更する
        * [スクリプトテキスト] ① Format を選択する > ② outputCsvString を選択する
    * [画面を編集] を閉じる
        * 一番外側の [完了] をクリックする
    * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/2b680259-1b02-b60f-620d-ad2b05d46be5.png)
    * [別名で保存] をクリックする
    * [新規バージョン] > [保存] をクリックする
    * [有効化] をクリックする
* ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/5bf50452-2923-e6b8-bb31-444d58e32745.png)
* 設定画面に戻る
* アプリケーションランチャーのアイコン > [セールス] をクリックする
* 動作確認する
    * [Create Case and Next Actions] へ情報を入力する
        * [件名] 好きな値
        * [状況] 好きな値
        * [優先度] 好きな値
    * [次へ] をクリックする
    * レコード情報がカンマ区切りで表示されることを確認する
    * [クリップボードへコピー] をクリックしてレコード情報をコピーできたことを確認する
        * メモ帳などへ貼り付けてみる
    * [完了] をクリックする
* ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212555/3bc7a4f2-2690-7f49-7ec8-b562962cd30d.png)

以上です。お疲れ様でした。

# 考察的なもの

* 今回は項目4つを結合しただけだったから、これくらいならApexなしでも、数式を使って実装できそうですよね！
    * でも、ここから項目数がどんどん増えていったり、コロコロ順番が変わったりしたら、フローのメンテナンスがつらいですよね？
    * Apexが使えるとフローで表現できる自動化ロジックの幅が、とっても広がりそうです！
    * なので、AdminもDevも、Einsteinとお友達になることはマストだと思います！！
* CSV形式の文字列を眺めてみると、どうやら値をダブルコーテーションで括ったほうがよさそうです！
    * Einsteinと一緒に、そんなコードへ修正してみよう！
* そもそも、CSV形式にこだわらず、どんな文字列でも表示できそうです！
    * Einsteinと一緒に、いろいろ試してみよう！

# さいごに

今年のDreamforce 2023でも注目を浴びたVS Code拡張機能「Einstein for Developers」を活用し、日本語で要件を入力すればApexコードが自動出力されてしまう世界を体験いただきました。Einstein GPTと一緒に開発を進める未来が、これでイメージできたでしょうか？

それでは、またお会いいたしましょう。
<b>*Happy Coding!!*</b>