kintone REST API レコード登録パターン

kintone の REST APIを利用した、レコード登録パターンです。
よく使うパターンをまとめます。

逆引きできる様にやりたいことから分類していきます。

---
**公式リンク**
* [kintone REST API一覧](https://developer.cybozu.io/hc/ja/articles/360000313406)

---
# 同じドメインの別アプリにレコードを書き込みたい

## 1レコード書き込み（レコード登録）
APIを実行するアプリ（元）から同じドメインの別アプリ（先）にレコードを１件登録します。

###### API
* '/k/v1/record'

###### リクエストパラメータ
* record

* [レコードの登録（1件）](https://developer.cybozu.io/hc/ja/articles/202166160#step1)

#### 登録レコードの構造について

登録するレコードの構造は次の通りです。

* 大きく分けると→ `{"app": "(アプリのID)", "record": { （登録レコード） }}`

#### アクセス権

APIの実行には、次の権限が必要です。

* レコードの追加権限（追加権限が無い場合は、権限エラーとなります）
* 値を登録するフィールドの編集権限

#### 登録先のレコードフォーマットを準備（テーブルなし）

下記要領で、登録先のレコードをフォーマットを作成。

```javascript
    let fromTable = {
        "app" : 0,
        "record": {
            "文字列_1行": {"value": ""},
            "登録元の登録日時":  {"value": ""},
            "登録元レコード番号":  {"value": 0},
            "登録元ユーザー":  {"value": [{"code": ""}]}
        }
    };
```

#### ボタン押下で登録先のアプリにレコードを１件登録

```javascript
(function() {
    "use strict";
    /**
     * レコード詳細画面表示イベント 
     *
    */
    let fromTableApp = 270;
    (function () {
      kintone.events.on("app.record.detail.show", function (event) {
        let record = event.record;
        let kintoneSpaceElement = kintone.app.record.getHeaderMenuSpaceElement();
        let button = new kintoneUIComponent.Button({ text: '登録先へCOPY' });
        kintoneSpaceElement.appendChild(button.render());
        button.on('click', function(){
            let prepare = prepareInsertRecord(fromTableApp, record);
            // console.log("to JSON =>", JSON.stringify(prepare));
            kintone.api(kintone.api.url('/k/v1/record', true), 'POST', prepare, function(resp) {
                // success
                console.log(resp);
            }, function(error) {
                // error
                console.log(error);
            });
        });
      });
    })();
    
    let fromTable = {
        "app" : 0,
        "record": {
            "文字列_1行": {"value": ""},
            "登録元の登録日時":  {"value": ""},
            "登録元レコード番号":  {"value": 0},
            "登録元ユーザー":  {"value": [{"code": ""}]}
        }
    };
    
    let prepareInsertRecord = (id, rec) => {
        // console.log(JSON.stringify(rec));
        fromTable.app = id;
        fromTable.record["文字列_1行"].value = rec["文字列_1行"].value;
        fromTable.record["登録元の登録日時"].value = rec["作成日時"].value;
        fromTable.record["登録元レコード番号"].value = rec.$id.value;
        fromTable.record["登録元ユーザー"].value[0].code = rec["作成者"].value.code;
        // console.log(fromTable);
        return fromTable;
    };

})();

```

## 複数レコード書き込み（テーブル展開してレコード登録）

APIを実行するアプリ（元）のテーブルを展開して複数のレコードとして、同じドメインの別アプリ（先）にレコードを複数件登録します。

#### テーブル展開について

* kintoneのテーブル内のレコードを１レコードづつ別アプリに別々のレコードとして登録します。

#### テーブル構造について

* record→table（テーブルのフィールドコード）
* table→value→[レコードの配列]
* レコード配列の中に複数のレコードになっています。
* [{１番目のレコード},{２番目のレコード},{３番目のレコード}...{最後のレコード}] こんな感じ
* record.（テーブルのフィールドコード）.value[1]で{2番目のレコード}が取得できます。

```json
"<テーブルのフィールドコード（例 Table_0）>": {
    "type": "SUBTABLE",
    "value": [
        {
            "id": "99100",
            "value": {
                "No": {
                    "type": "NUMBER",
                    "value": "1"
                },
                "型番": {
                    "type": "SINGLE_LINE_TEXT",
                    "value": "001"
                },
                "商品名": {
                    "type": "SINGLE_LINE_TEXT",
                    "value": "ノート"
                }
            }
        },
        {
            "id": "99101",
            "value": {
                "No": {
                    "type": "NUMBER",
                    "value": "2"
                },
                "型番": {
                    "type": "SINGLE_LINE_TEXT",
                    "value": "002"
                },
                "商品名": {
                    "type": "SINGLE_LINE_TEXT",
                    "value": "鉛筆"
                }
            }
        }
    ]
}
```

#### ボタン押下で登録先のアプリにレコードを複数件登録

###### API

複数件登録のAPIはURIが1件登録と違います。

* '/k/v1/record' → **'/k/v1/records'** と複数形になっています。

###### リクエストパラメータ

* record → **records** とURIと同じく複数形になっています。

* API [レコードの一括登録](https://developer.cybozu.io/hc/ja/articles/202166160#step2)

```javascript
(function() {
    "use strict";
    /**
     * レコード詳細画面表示イベント 
     *
    */
    const TO_APP = 270;
    const TO_APP2 = 276;
    let notifyPopup = new kintoneUIComponent.NotifyPopup({
        text: 'Sucess',
        type: 'success'
    });
    let body = document.getElementsByTagName("BODY")[0];
    (function () {
      kintone.events.on("app.record.detail.show", function (event) {
        let record = event.record;
        let appId = kintone.app.getId();
        let kintoneSpaceElement = kintone.app.record.getHeaderMenuSpaceElement();
        let button = new kintoneUIComponent.Button({ text: '登録先へCOPY' });
        let button2 = new kintoneUIComponent.Button({ text: 'テーブル展開' });
        kintoneSpaceElement.appendChild(button.render().getElementsByTagName("button")[0]);
        kintoneSpaceElement.appendChild(button2.render().getElementsByTagName("button")[0]);
        
        /**
         * 登録先へCOPYボタン押下
        */
        button.on('click', function(){
            let rec = {
                "record": {
                    "文字列_1行": {"value": record["文字列_1行"].value},
                    "登録元の登録日時":  {"value": record["作成日時"].value},
                    "登録元レコード番号":  {"value": record.$id.value},
                    "登録元ユーザー":  {"value": [{"code": record["作成者"].value.code}]}
                }
            };
            let prepare = prepareInsertRecord(TO_APP, rec);
            console.log("to JSON =>", JSON.stringify(prepare));
            kintone.api(kintone.api.url('/k/v1/record', true), 'POST', prepare, function(resp) {
                // success
                console.log(resp);
                body.appendChild(notifyPopup.render());
            }, function(error) {
                // error
                console.log(error);
                notifyPopup.setText('Error');
                notifyPopup.setType('error');
                body.appendChild(notifyPopup.render());
            });
        });

        /**
         * テーブル展開ボタン押下
        */
        button2.on('click', function(){
            let insertRows = record['Table_0'].value.map(tableRow => {
                console.log(tableRow);
                let table2rec = prepareTableToRecord(tableRow);
                return prepareMergeRecord(table2rec, {"アプリId": {"value": kintone.app.getId()},
                                                "レコードId": {"value": kintone.app.record.getId()},
                                                "会社名": {"value": record["会社名"].value},
                                                "登録元日時":  {"value": record["作成日時"].value},
                                                "登録元作成者":  {"value": [{"code": record["作成者"].value.code}]}
                });
            });
            // console.log(insertRows);
            let prepare = prepareInsertRecord(TO_APP2, {"records": insertRows});
            // console.log(prepare);
            kintone.api(kintone.api.url('/k/v1/records', true), 'POST', prepare, function(resp) {
                // success
                console.log(resp);
                body.appendChild(notifyPopup.render());
            }, function(error) {
                // error
                console.log(error);
                notifyPopup.setText('Error');
                notifyPopup.setType('error');
                body.appendChild(notifyPopup.render());
            });
        });

      });
    })();
    
    /**
     * @param {number} id レコード登録先のアプリID
     * @param {object} rec kintoneレコード
     * @return {Object} insertRec kintone登録レコード
    */
    let prepareInsertRecord = (id, rec) => {
        let insertRec = Object.assign({}, {"app": id}, rec);
        // console.log(JSON.stringify(insertRec));
        return insertRec;
    };

    /**
     * @param {object} tableRow kintoneテーブル１行レコード
     * @return {object} rec テーブル１行からkintone登録レコードオブジェクトを生成
    */
    let prepareTableToRecord = (tableRow) => {
        let rec = {
            "テーブルId": {"value": tableRow.id},
            "No": {"value": tableRow.value["No"].value},
            "型番": {"value": tableRow.value["型番"].value},
            "商品名": {"value": tableRow.value["商品名"].value},
            "単価": {"value": tableRow.value["単価"].value},
            "数量": {"value": tableRow.value["数量"].value}
        };
        // console.log(JSON.stringify(rec));
        // console.log(rec);
        return rec;
    };


    /**
     * @param {object} target マージターゲット
     * @param {object} source マージ元
     * @return {object} merged マージしたオブジェクト
    */
    let prepareMergeRecord = (target, source) => {
        let merged = Object.assign({}, target, source);
        // console.log(merged);
        return merged;
    };

})();
```

```css
@charset "UTF-8";
.kuc-btn.normal {
    margin: 5px;
}
```

参考リンク

* [kintoneにおけるテーブル操作の基本（行の追加・更新・削除）](https://developer.cybozu.io/hc/ja/articles/360022502911)
* [レコード更新におけるテーブル操作のテクニック
](https://developer.cybozu.io/hc/ja/articles/200752984)
* [第6回 テーブルの値を利用する](https://developer.cybozu.io/hc/ja/articles/202422244)

#### ルックアップフィールドのコピーについて

コピーする元のレコードに、ルックアップフィールドが含まれる場合、ルックアップ元フィールドが重複禁止設定になっていない場合、エラーでコピー出来ません。

* [フィールド形式](https://developer.cybozu.io/hc/ja/articles/202166330) ※カスタムフィールドのルックアップを参照
* [kintone REST APIの共通仕様　制限事項](https://developer.cybozu.io/hc/ja/articles/201941754-kintone-REST-API%E3%81%AE%E5%85%B1%E9%80%9A%E4%BB%95%E6%A7%98#step12)