kintoneの「アプリ内で別アプリのレコードを検索、参照したい」というニッチな要望を解決する


# はじめに

今回アドベントカレンダー何書こうかな...と悩んでいたのですが、折角なのでチームでの取り組みの一部を軽く紹介していこうと思います。

私達のチームでは、[マルチサイズプラットフォーム事業（MSP）](https://zozo.jp/multisize/)におけるデジタルトランスフォーメーション（DX）の取り組みを行っています。
要するにアパレル生産の業務の自動化とか効率化ですね。

今回は事業で使っている[kintone](https://kintone.cybozu.co.jp/)という業務改善プラットフォームで使えるニッチなコードについて書きたいと思います！

元々、有料プラグインとかで実装されている機能みたいですが、なんとかコードで再現できないかと要望を貰い実装してみました。

# 軽く背景
今回の実装は、とある契約書のドキュメントを自動生成するために作ったアプリのフロントエンド部分に使っています。

ドキュメントはレコード毎に作られており、ドキュメントを発行したいレコードを検索条件をもとに検索し、該当したレコードから発行するレコードのみを選びバックエンド側に情報を送るといった流れです。

正直、既存のプラグインで代用できそうな機能ではありますが、レコードの内容を参照して〜処理したいといった要望も出てきそうだったのでコードで実装することにしました。

# 特定の条件に一致するレコードを他アプリから検索する

以下の様にレコードの特定フィールドを指定し、検索ボタンを押下します。
![form.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308887/2b372768-1b56-99cc-2a72-ff99949d0714.png)

検索ボタン押下後に、検索結果を以下のテーブルに表示します。

![スクリーンショット 2020-12-05 16.42.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308887/e4988827-c6b5-2303-d3e9-bfbc6ab542cc.png)

今回作ったアプリでは発行フィールドを選択することで、検索して列挙されたレコードから必要なレコードだけを絞り込みすることができる仕様になっています。

## 特定のワードを含んだレコードの要素を検索する
レコードのフィールドコートの頭に`search_`とついているモノだけを抽出します。
`search_`のキーワードを外しているのは、後々テーブルのフィールドコートの参照に使うためです。

```JS
// アプリ内のレコード要素を取得
let record = kintone.app.record.get();

search_key_list = []
for (r_key in record.record){
  if (r_key.indexOf('search_') != -1){
    search_key_list.push(r_key.replace('search_', ''))
  }
}
```


## 他のkintoneアプリのレコードを参照する為のクエリを作成する
指定した条件でkintoneのレコードを検索するために、クエリを作成します。

```JS
let query_text = ''

for (const [search_key_index, search_key_value] of search_key_list.entries()){
  let search_val = record.record['search_' + search_key_value].value
  if (search_key_index == 0) {
    query_text += search_key_value + ' in ("' + search_val + '")'
  }else{
    query_text += " and " + search_key_value + ' in ("' + search_val + '")'
  }
}
```

## 他アプリからレコードを参照する
上記で作成したクエリでkintoneの他アプリからレコードを参照し、検索結果をテーブルに追加した後にレコードを更新しています。
IDと発行のフィールドコートは固定なので別で処理しています。
検索条件やテーブルの項目を編集することで、コードを変えずに検索条件や検索後の結果を変えることができます。

```JS
// bodyを作成
let body = {
  "app": "appのID",
  totalCount: true
}
body["query"] = query_text

kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body).then(function(resp){
  return resp;
}, function(error) {
  console.log(error);
}).then(function(resp){
  // 取得したレコードの処理
  let records = JSON.stringify(resp);
  let results = JSON.parse(records);

  for(const [r_index, r_record] of results.records.entries()){
      
    // dictを新規作成
    let new_table_value = {
      id: r_index,
      value: {
        "発行": {
          type: "CHECK_BOX",
          value: []
        },
        "レコードID": {
          type: "SINGLE_LINE_TEXT",
          value: r_record["$id"].value,
          disabled: true
        },
      }
    }
      
    // tableのkey分ループを回す
    for(const key of key_list){
      if(key == "発行" || key == "レコードID"){
        // 事前に代入したフィールドは飛ばす
      }else{
        if(r_record[key] == undefined){
          record.record['ログ表示'].value = 'エラーが発生しました。存在しないキーをテーブルで指定しています。'
          kintone.app.record.set(record);
          return
        }
        new_table_value.value[key] = {
          type: "SINGLE_LINE_TEXT",
          value: r_record[key].value,
          disabled: true
        }
      }
    }
    table_set_records.push(new_table_value)
  }
  record.record['テーブル'].value = table_set_records
  record.record['ログ表示用に用意したフィールド'].value = '検索結果は' + results.records.length + '件です。'
  kintone.app.record.set(record);
});
```

# さいごに
kintoneは公式ドキュメントが沢山挙がってたりするので実装しやすかったです。
ただ、アプリにアップするコードの管理はどんな感じでやろうかな...という悩みはありますね。

今回思いつきで実装したところがあるので、もっといい方法あるよー！という方いらっしゃいましたら教えてください〜
(そしてコードがあまり整理できていなくてすみません...)

他にも便利そうな実装があればブログにしていきたいなと思います〜。