Apexフローアクション+画面フローで取引先をSOQL&SOSL検索する

# はじめに

https://qiita.com/takaHAL/items/556d195a3dffcdf881f7

前回ApexでSOQLとSOSLを併用するものを作りました。
今回は、画面フローで前回作成したApexをベースに取引先を検索してみます。

# やること

- Apexの修正
- 画面フローの作成

# Apexの修正

## フローアクションとして呼び出せるように修正

```apex: SearchAccount.cls
public with sharing class SearchAccount {
  @InvocableMethod(
    label='Account 取引先名称検索'
    description='Accountの取引先名称検索(SOQL,SOSL)を行います。'
  )
  public static List<SearchAccountResult> SearchAccount(
    List<SearchAccountRequest> requests
  ) {
    List<SearchAccountResult> results = new List<SearchAccountResult>();
    String searchKeyword = requests[0].searchKeyword;
    Integer limitNum = requests[0].limitNum != null ? requests[0].limitNum : 10;
    SearchAccountResult result = getSearchAccountResult(
      searchKeyword,
      limitNum
    );

    results.add(result);

    return results;
  }

  private static SearchAccountResult getSearchAccountResult(
    String searchKeyword,
    Integer limitNum
  ) {
    // SOQLで検索
    List<Account> accountsBySoql = getAccountByNameSOQL(
      searchKeyword,
      limitNum
    );

    // SOSLで検索
    List<Account> accountsBySosl = getAccountByNameSOSL(
      searchKeyword,
      limitNum
    );

    // SOSL SOSLの検索結果をマージ
    Set<Account> accountSets = new Set<Account>();
    accountSets.addAll(accountsBySoql);
    accountSets.addAll(accountsBySosl);
    List<Account> deduplicationAccounts = new List<Account>(accountSets);
    
    SearchAccountResult result = new SearchAccountResult();
    result.accounts = deduplicationAccounts;

    return result;
  }

  private static List<Account> getAccountByNameSOQL(
    String searchKeyword,
    Integer limitNum
  ) {
    searchKeyword = '%' + searchKeyword + '%';
    List<Account> accounts = [
      SELECT Id, Name
      FROM Account
      WHERE Name LIKE :searchKeyword
      LIMIT :limitNum
    ];

    return accounts;
  }

  private static List<SObject> getAccountByNameSOSL(
    String searchKeyword,
    Integer limitNum
  ) {
    List<List<SObject>> searchSosl = [
      FIND :searchKeyword
      IN NAME FIELDS
      RETURNING Account(Id, Name LIMIT :limitNum)
    ];
    if (searchSosl.isEmpty()) {
      return null;
    }

    return searchSosl[0];
  }

  public class SearchAccountRequest {
    @InvocableVariable(label='検索キーワード' required=true)
    public String searchKeyword;
    @InvocableVariable(label='取得件数 デフォルト10件')
    public Integer limitNum;
  }

  public class SearchAccountResult {
    @InvocableVariable
    public List<Account> accounts;
  }
}

```

## 前回からの主な差分

InvocableMethod アノテーションとInvocableVariable アノテーションを追加しました。

`InvocableMethod`でフローから呼び出すアクションの対象に、`InvocableVariable`でアクション実行時の入力値とアクションの出力値の形式を決めます。

https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_InvocableMethod.htm

https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_annotation_InvocableVariable.htm

```apex
@InvocableMethod(
    label='Account 取引先名称検索'
    description='Accountの取引先名称検索(SOQL,SOSL)を行います。'
  )
  ・
  ・
  ・
  public class SearchAccountRequest {
    @InvocableVariable(label='検索キーワード' required=true)
    public String searchKeyword;
    @InvocableVariable(label='取得件数 デフォルト10件')
    public Integer limitNum;
  }

  public class SearchAccountResult {
    @InvocableVariable
    public List<Account> accounts;
  }
```

# 画面フローを作成

## 1. 検索画面を作成

取引先名を入力するテキストコンポーネントを設置し、必須入力にしました。

![スクリーンショット 2023-12-24 22.49.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/e4f56ce6-7742-2bf4-011c-6fbf53b55dfd.png)

## 2. 作成したApexを呼び出し

```apex
@InvocableMethod(
    label='Account 取引先名称検索'
    description='Accountの取引先名称検索(SOQL,SOSL)を行います。'
  )
```

`InvocableMethod`の`label`でアクションが作成されています。

```apex
  public class SearchAccountRequest {
    @InvocableVariable(label='検索キーワード' required=true)
    public String searchKeyword;
    @InvocableVariable(label='取得件数 デフォルト10件')
    public Integer limitNum;
  }
```

検索キーワードに画面フローの入力テキスト`input_name`を設定します。


![スクリーンショット 2023-12-24 22.52.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/a408a90c-441d-b84c-077a-359b82d1ee1c.png)

## 3. 検索結果画面を作成

表示テキストコンポーネントをを設置し、リソースピッカーにアクションの出力を指定します。

![スクリーンショット 2023-12-24 22.59.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/1fff0ad7-08a0-8abc-a17e-2134fd42f3b2.png)


![スクリーンショット 2023-12-24 22.59.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/1d3bf325-7a4a-e69e-2897-ecd89baceefd.png)

# 実行してみる

https://qiita.com/takaHAL/items/556d195a3dffcdf881f7

前回の検索結果と同じ内容が取得できました。

![スクリーンショット 2023-12-24 23.05.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/01308575-cd5e-6589-40e4-95c33003a8cd.png)

![画面フローで取引先検索.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/aa10ee28-fb84-3eea-6d83-cb6101e3580c.png)

検索結果がIDで表示されてしまいます。
- 検索結果を事前に割り当て要素で取引先名に変える
- Apexの返り値で表示したい目的の形式に変える

等の対応を行ったり
リンクにしたい場合は、LWCで`NavigationMixin`を使ったコンポーネントを作ってもいいかもしれません。

https://developer.salesforce.com/docs/platform/ja-jp/lwc/guide/use-navigate-basic.html

# 最後に

https://qiita.com/takaHAL/items/556d195a3dffcdf881f7

今回は前回作成したApexをフローアクションで呼び出せるように修正し、画面フローで取引先検索Apexを実行してみました。
フローアクションとしてのApexを用意することでフローではできないことをできるようにしたり、フローだと処理が長くて保守しにくくなってしまったものをリファクタリングすることもできます。