kintoneのテーブルでアプリのレコードの登録・更新・削除をする（１）

今回は↓の記事をパワーアップさせて、登録用アプリのテーブルの内容で別のアプリのレコードの登録・更新をします。

https://qiita.com/juri_don/private/eded7d5d8ce9ef2a3e8a

以前の記事では、

* 登録用アプリ
* 英単語一覧アプリ

の2種類を作成し、登録用アプリのテーブルの内容を英単語一覧アプリにただ登録する方法を紹介しました。
今回は登録・更新をやってみましょう。※次回は削除にチャレンジです。（沼です）

完成動画（ゆっくり音声。音量注意）↓

<iframe width="480" height="360" src="https://www.youtube.com/embed/QC5AFei3pfo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


今回は、登録用アプリから登録と更新ができるようにします。

# アプリの準備

登録用アプリと、英単語一覧アプリにフィールドを追加します。
ユニークキーのフィールドはJavaScriptで編集不可にしておくことをおすすめします。

参考：[フィールドの入力不可をラジオボタンとチェックボックスで完全制御！
](https://developer.cybozu.io/hc/ja/articles/200306919)

## 登録用アプリ

| フィールド種類 | フィールドコード | 備考 |
|:-:|:-:|:-:|
| スペース  | spBtn  |登録ボタン設置用   |
|文字列(1行)| 英単語  |  テーブル内 |   
|文字列(1行)| 日本語  |  テーブル内 | 
|数値| UID  | 英単語一覧用のキー、テーブル内 。編集不可推奨 |   
|文字列(1行)| uids  |テーブルのUIDをカンマ区切りで表示 。編集不可推奨|   
|数値| TUID  | 重複禁止 （登録アプリのキー） 編集不可推奨　登録用アプリのUIDなのでTUID。命名雑です。|   

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/074ded80-5087-f1de-87df-a861f5ab0f30.png)


## 英単語一覧アプリ

| フィールド種類 | フィールドコード | 備考 |
|:-:|:-:|:-:|
|文字列(1行)| 英単語  |   |   
|文字列(1行)| 日本語  |   | 
|数値| UID  | 英単語一覧アプリのキー 、編集不可推奨 |   
|数値| TUID  | 登録アプリのキー、編集不可推奨  登録用アプリのUIDなのでTUID。命名雑です。| 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/9c86cc74-d799-19c7-8851-389903efab64.png)

# カスタマイズの方針

今回は登録用アプリのカスタマイズをします。
以下のような方針で作っていきます。

* レコードの追加をした際に、TUIDを自動採番する。
* 詳細画面に設置したボタンで登録処理を行う
* テーブルのどれかの行の英語or日本語が空文字だったら何もしない
* テーブルの行の日本語＆英語が入力済みでUIDが空文字だったら新規登録
* テーブルの行の日本語＆英語が入力済みでUIDが空文字だったら更新
* 登録＆更新したレコードのUIDをカンマ区切りでuidsに入力する（今後削除で使用するため）
* 登録と更新を複数行う（今後削除もする）のでBulkRequestを使う


# JavaScript

kintone REST API Clientと、kintone UI Componentを使用します。

https://github.com/kintone/js-sdk/tree/master/packages/rest-api-client

https://kintone-ui-component.netlify.app/

## レコードの追加をした際に、TUIDを自動採番する

新規追加時にキーであるTUIDフィールドの値を自動採番して登録します。

```js
if (!event.record.TUID.value) {
  const client = new KintoneRestAPIClient();
  const res = await client.record.getRecords({
    app: kintone.app.getId(),
    fields: "TUID",
    query: "order by TUID desc limit 1",
  });
  // 1レコード目だったら1。その他は最大値のTUIDに+1する
  event.record.TUID.value =
    res.records.length > 0 ? Number(res.records[0].TUID.value) + 1 : 1;
}
```

## 詳細画面にボタンを設置する

詳細画面表示イベントで
別にスペースフィールドでなくてもよいのですが（今気づいた）
「レコードの登録更新削除」というボタンを設置しておきます。

```js
const sp = kintone.app.record.getSpaceElement("spBtn");
const appId = 英単語一覧アプリのID;
const btn_addRecords = new Kuc.Button({
  text: "レコードの登録更新削除",
  type: "submit",
});
sp.appendChild(btn_addRecords);

// ボタンクリック
btn_addRecords.addEventListener("click", async () => {
  // ボタンクリックの処理
});
```

## ボタンクリック

### 新規登録・更新の判定

テーブルのUIDに値があれば更新、なければ新規です。
一つでもUIDのない行があればAPIを叩く必要があるので、
API呼び出し回数節約のため、先にUIDが空の行があるかないか調べています。


```js
const obj = kintone.app.record.get();
if (
  obj.record.テーブル.value.some((r) => {
    return !r.value.英単語.value || !r.value.日本語.value;
  })
) {
  console.log("英単語と日本語両方入力してね（終了）");
  return;
}

// 空白のUIDがあれば新規登録行がある（true）と判定する
const retUID = obj.record.テーブル.value.some((r) => {
  return !r.value.UID.value;
}); 

const client = new KintoneRestAPIClient();

// 英単語一覧アプリ用の新しいUID
let newUID;
// 新規登録行がある場合、新しいUIDを求める
if (retUID) { 
  const resGet = await client.record.getRecords({
    app: appId,
    fields: "UID",
    query: "order by UID desc limit 1",
  });
  newUID =
    resGet.records.length > 0 ? Number(resGet.records[0].UID.value) + 1 : 1;
}
```

###  新規登録と更新用のレコードを作る

続けて、新規登録用と、更新用のレコードを作ります。
uids,uuids,regUidsは削除の時に使いますが、次回の記事で「ここに追加～」のように説明するのが面倒なのでもうここに書いておきます。

```js
const postRecs = []; // 新規登録レコード
const putRecs = [];  // 更新レコード
const uids = obj.record.uids.value.split(",").map(Number); // uidsフィールドを配列に入れる
const uuids = [];  // 更新したレコードのuidの配列（今後削除で使用）
const regUids = [];  // 新規登録＆更新したレコードのuid（今後削除で使用）
let idx = 0;

obj.record.テーブル.value.forEach((r, i) => {
  if (!r.value.UID.value) {
    // 新規
    let uid = Number(newUID) + idx;
    postRecs.push({
      英単語: {
        value: r.value.英単語.value,
      },
      日本語: { value: r.value.日本語.value },
      UID: { value: uid },
      TUID: { value: event.record.TUID.value },
    });
    event.record.テーブル.value[i].value.UID.value = uid;
    regUids.push(uid);
    idx += 1;
  } else {
    // 更新
    uuid.push(Number(r.value.UID.value));
    regUids.push(Number(r.value.UID.value));
    putRecs.push({
      updateKey: { field: "UID", value: Number(r.value.UID.value) },
      record: {
        英単語: {
          value: r.value.英単語.value,
        },
        日本語: { value: r.value.日本語.value },
        TUID: { value: event.record.TUID.value },
      },
    });
  }
});
```


## APIのリクエストパラメータ作成

bulkRequestでAPIを一気に流します。
英単語一覧アプリに新規レコードがあればPOSTを、更新レコードがあればPUTを。
それと自分（登録用アプリ）のuidsとテーブルの更新をします。


```js
// リクエストパラメータ
const requestParams = [];

// 新規レコードがあるときのみパラメータ作成
if (postRecs.length > 0) {
  requestParams.push({
    method: "POST",
    api: "/k/v1/records.json",
    payload: {
      app: appId,
      records: postRecs,
    },
  });
}
// 更新レコードがあるときのみパラメータ作成
if (putRecs.length > 0) {
  requestParams.push({
    method: "PUT",
    api: "/k/v1/records.json",
    payload: {
      app: appId,
      records: putRecs,
    },
  });
}

// 自分のuidsフィールドはいつも更新したい
requestParams.push({
  method: "PUT",
  api: "/k/v1/record.json",
  payload: {
    app: kintone.app.getId(),
    id: kintone.app.record.getId(),
    record: {
      テーブル: event.record.テーブル,
      uids: { value: regUids.join(",") },
    },
  },
});

try {
  // bukRequestでAPIをたたく
  const res = await client.bulkRequest(params);
  location.reload();
} catch (err) {
  console.log(err);
}
```

# まとめ
以前の記事に、それぞれキーを追加して「更新」機能も追加してみました。
次回は削除について書きます。

↓続きの記事たち↓
* [kintoneのテーブルのレコードを別アプリのレコードに登録する](https://qiita.com/juri_don/items/eded7d5d8ce9ef2a3e8a)
* [kintoneのテーブルでアプリのレコードの登録・更新・削除をする（１）（今見てる記事）](https://qiita.com/juri_don/items/d69e375498e96847d4d9)
* [kintoneのテーブルでアプリのレコードの登録・更新・削除をする（２）](https://qiita.com/juri_don/private/2ddb06c5ddaade5b7209)
* [kintoneのテーブルでアプリのレコードの登録・更新・削除をする（３）](https://qiita.com/juri_don/private/70fa08591ac1304df36d)
* [kintoneのテーブルでアプリのレコードの登録・更新・削除をする（４）](https://qiita.com/juri_don/items/aacd9c761ee84f7b7282)