別アプリ内テーブルへの書き込み

背景・実現したいこと

お世話になります。

Aアプリ(行動履歴)・Bアプリ(お客様情報)があり、Aアプリの特定フィールドの情報をBアプリのサブテーブル内に行を追加する形で更新したいと考えております。

 テーブル内に更新されていることは確認が取れました。しかし、putのリクエストを投げると400で返されており必須項目に対しての入力がうまくできていないように感じています。

https://developer.cybozu.io/hc/ja/articles/201941984#step4

大変お手数をおかけいたしますが、アドバイスをいただけないでしょうか。

下記、エラーコードとなります。

利用したソースコード

(function () {

  “use strict”;

  let user = kintone.getLoginUser().code;

  console.log(user);

  if (user == “152006”) {

    kintone.events.on(“app.record.index.show”, function (event) {

      let records = event.records;

      for (var m = 0; m < records.length; m++) {

        let tagName = records[m][“文字列__1行__1”].value;

        let oldButton = document.getElementById(“UUアプリへ一括更新”);

        let button = document.createElement(“button”);

        if (oldButton !== null) oldButton.parentNode.removeChild(oldButton);

        button.innerHTML = “UUアプリ更新”;

        button.id = “UUアプリ更新”;

        kintone.app.getHeaderMenuSpaceElement().appendChild(button);

        button.addEventListener(“click”, function () {

          let GET_param = {

            app: 917,

            Query: kintone.app.getQuery(),

            fields: [“$id”, “文字列__1行__1”, “UURecordID”],

          };

          return kintone

            .api(kintone.api.url(“/k/v1/records”, true), “GET”, GET_param)

            .then(function (resp) {

              let resp1 = resp.records;

              console.log(resp);

              for (let j = 0; j < resp1.length; j++) {

                let UUrecID = resp1[j].UURecordID.value;

                console.log(UUrecID);

                //UUアプリに対して対象レコードを取得

                let GET_param2 = {

                  app: 906,

                  Query:

                    ‘record_id = "’ +

                    UUrecID +

                    ‘"  order by record_id desc limit 100 offset 0’,

                  fields: [“$id”, “テーブル”],

                };

                return kintone

                  .api(

                    kintone.api.url(“/k/v1/records”, true),

                    “GET”,

                    GET_param2

                  )

                  .then(function (resp2) {

                    console.log(resp2); //ここまでOK

                    let resp_2 = resp2.records;

                    for (let k = 0; k < resp_2.length; k++) {

                      let existing_subtable = resp_2[0][“テーブル”].value;

                      let subtable = []; // 最終的にPUTするサブテーブル

                      // 既存のサブテーブルを抽出

                      for (let l = 0; l < existing_subtable.length; l++) {

                        subtable.push(existing_subtable[k]);

                      }

                      let body = {

                        id: “15970462”,

                        value: [

                          {

                            文字列__1行__5: {

                              value: tagName,

                            },

                          },

                        ],

                      };

                      console.log(body);

                      subtable = subtable.concat(body); // 既存と追加分のサブテーブルを結合

                      console.log(subtable);

                      let put_record = {}; // レコード更新用オブジェクト

                      put_record[“テーブル”] = {

                        value: subtable,

                      };

                      let put_Params = {

                        app: 906,

                        id: resp_2[k].$id.value,

                        record: put_record,

                      };

                      return kintone

                        .api(

                          kintone.api.url(“/k/v1/records”, true),

                          “PUT”,

                          put_Params

                        )

                        .then(function () {

                          alert(“UUアプリへの登録が完了しました!”);

                          //location.reload();

                        })

                        .catch(function (error) {

                          alert(

                            “UUアプリへの登録でエラーが発生しました。” +

                              error.message

                          );

                          console.log(error);

                        });

                    }

                  });

              }

            });

        });

      }

    });

  }

})();

エラー自体は、レコードの一括更新API で、records が指定されていないからです。

ただ一覧のレコード数ループ内で、ヘッダ部のボタン処理があったり、レコードの一括更新APIで 1レコードのリクエストを出したりと、全体的にちぐはぐな感じです。

処理の流れを整理して、書き直してみてください。

rex0220

お世話になります。アドバイスありがとうございます。

様々ちぐはぐになっておりました。修正したコードを記載いたします。

しかし、recordsの指定についてよく理解できておらずput_Params内のrecordsを指定するようなイメージでしょうか。

各種修正をしながら、実行しておりますがやはり400のエラーが返されてしまいます。

初心者な質問で大変申し訳ございませんが、何卒よろしくお願い申し上げます。

(function() {
  “use strict”;

  let user = kintone.getLoginUser().code;
  console.log(user);
  if(user == “152006”){
    kintone.events.on(‘app.record.index.show’, function(event) {
        let records = event.records;

      
    let oldButton = document.getElementById(‘UUアプリへ一括更新’);
    let button = document.createElement(‘button’);

    if(oldButton !== null) oldButton.parentNode.removeChild(oldButton);

    button.innerHTML = ‘UUアプリ更新’;
    button.id = ‘UUアプリ更新’;
    kintone.app.getHeaderMenuSpaceElement().appendChild(button);
    button.addEventListener(‘click’, function() {

    for (var m = 0; m < records.length; m++) {
        let tagName = records[m][‘文字列__1行__1’].value;

        let GET_param = {
            ‘app’: 917,
            ‘Query’:kintone.app.getQuery(),
            ‘fields’: [‘$id’, ‘文字列__1行__1’,‘UURecordID’]

            };

    return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, GET_param).then(function(resp) {
        let resp1 = resp.records;
        console.log(resp);

        for (let j = 0; j < resp1.length; j++ ) {
            let UUrecID = resp1[j].UURecordID.value;
            console.log(UUrecID);
        
        //UUアプリに対して対象レコードを取得
        let GET_param2 = {
            ‘app’: 906,
            ‘Query’:‘record_id = "’ + UUrecID + ‘"  order by record_id desc limit 100 offset 0’,
            ‘fields’: [‘$id’, ‘テーブル’]

            }
            
    return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, GET_param2).then(function(resp2) {
        console.log(resp2);//ここまでOK
        let resp_2 = resp2.records;
        
        for (let k = 0; k < resp_2.length; k++ ) {
        
            let existing_subtable = resp_2[k][‘テーブル’].value;
            
            //let subtable_id = resp_2[k][‘テーブル’].value.id;
            //console.log(subtable_id);
            
            let subtable = []; // 最終的にPUTするサブテーブル
            //let appended_subtable = []; // 追加したいサブテーブル
       
        // 既存のサブテーブルを抽出
        for (let l = 0; l < existing_subtable.length; l++) {
            subtable.push(existing_subtable[k]);
        }
        
            let body = {
                ‘app’: 906,
                ‘id’:resp_2[k].$id.value ,
                ‘records’: {
                    “テーブル” : {
                        “value” : [
                            {
                            ‘value’: {
                                “id”: “0”,
                                “文字列__1行__5”:{
                                    ‘value’ : tagName
                                      }
                                    }
                                 }
                              ]
                            }
                        }
                    };
                
            console.log(body);
            subtable = subtable.concat(body); // 既存と追加分のサブテーブルを結合
            console.log(subtable)
            
            let put_record = {}; // レコード更新用オブジェクト
            put_record[“テーブル”] = {
                value: subtable
            };
            
            let put_Params = {
                ‘app’: 906,
                ‘id’:resp_2[k].$id.value ,
                ‘records’: {
                    “テーブル” : {
                        “value” : put_record
                                }
                           }
                        }
                    
                
                    
        return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘PUT’, put_Params).then(function(resp3) {
            alert(‘UUアプリへの登録が完了しました!’);
            //location.reload();
            
                
        }).catch(function(error) {
            alert(‘UUアプリへの登録でエラーが発生しました。’ + error.message);
            console.log(error);

            });
        
    
        }
    });
    }
    });
  };
  });

    

});

}

})();

いくつか気になる点があります。

・一覧のレコード毎に、さらに一覧のレコード取得 API を発行してるので、むちゃくちゃ処理回数が増えます。
このループ処理は不要です。

for (var m = 0; m < records.length; m++) {

・for ループ内で非同期処理の REST API を発行すると、REST API の終了を待たずにループが進みます。
for ループではなく、再帰呼び出しでループしましょう。

・処理対象のレコード数が不明ですが、REST API で処理できるレコード数に制限があります。
100 レコード以上の場合は、全レコードを処理するコードが必要です。
kintone JavaScript Client のようなライブラリを使うと処理を簡単に記述できると思います。

・フィールドコードが規定値のままで、コードをみても意味が分からない
内容にあったフィールドコードにしましょう。

・アプリ構成や関連情報がよくわかっていないので、要望どおりかわかりませんが、ざっとコードを書いてみました。

(function () {

    'use strict';

    let user = kintone.getLoginUser().code;

    console.log(user);

    if (user !== "152006") return;

    const UUAPPID = 906;

    kintone.events.on('app.record.index.show', function (event) {

        let oldButton = document.getElementById('UUアプリへ一括更新');

        if (oldButton !== null) oldButton.parentNode.removeChild(oldButton);

        let button = document.createElement('button');

        button.innerHTML = 'UUアプリ更新';

        button.id = 'UUアプリ更新';

        kintone.app.getHeaderMenuSpaceElement().appendChild(button);

        button.addEventListener('click', function () {

            UUAppAllProc(event.appId);

        });

    });

    // UUアプリ更新

    function UUAppAllProc(appId) {

        // 一覧レコード取得

        const query = kintone.app.getQueryCondition();

        const fields = ['$id', '文字列 __1行__ 1', 'UURecordID'];

        fetchRecords(appId, query, fields).then(function (records) {

            console.log('view Records', records);

            return UUAppProc(records, 0);

        }).then(function(resp) {

            alert('UUアプリへの登録が完了しました!');

        }).catch(function(error){

            alert('UUアプリへの登録でエラーが発生しました。' + error.message);

        });

    }

    // UUアプリレコード処理

    function UUAppProc(records, pos) {

        console.log('UUAppProc', pos);

        if (pos >= records.length) return kintone.Promise.resolve(0);

        return UUAppUpdate(records[pos]).then(function (resp) {

            return UUAppProc(records, pos + 1);

        });

    }

    // UUアプリ更新処理

    function UUAppUpdate(record) {

        const tagName = record['文字列 __1行__ 1'].value;

        const UUrecID = record.UURecordID.value;

        const query = 'record_id = "' + UUrecID + '"';

        const fields = ['$id', 'テーブル'];

        return fetchRecords(UUAPPID, query, fields).then(function (records) {

            console.log('UUAPPID Records', records);

            let put_records = [];

            records.forEach(function (rec) {

                let subtable = rec['テーブル'].value.map(function(row) { return { id: row.id } });

                subtable.push({ value: { '文字列 __1行__ 5': { value: tagName } }} );

                put_records.push({

                    id: rec.$id.value,

                    record: { 'テーブル': { value: subtable } }

                });

            });

            return updateRecords(UUAPPID, put_records);

        });

    }

    // レコード取得処理

    function fetchRecords(appId, opt_query, opt_fields, opt_limit, opt_startid, opt_records) {

        const startid = opt_startid || 0;

        let query = opt_query || '';

        query = query ? '( ' + query + ' ) and $id > ' + startid : '$id > ' + startid;

        const limit = opt_limit || 500;

        let allRecords = opt_records || [];

        let params = { app: appId, query: query + ' order by $id asc limit ' + limit };

        if (opt_fields) {

            let fields = opt_fields;

            if (fields.indexOf('$id') < 0) fields.push('$id');

            params.fields = fields;

        }

        return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', params).then(function (resp) {

            allRecords = allRecords.concat(resp.records);

            if (resp.records.length === limit) {

                const next_startid = resp.records.slice(-1)[0]['$id'].value;

                return fetchRecords(appId, opt_query, opt_fields, limit, next_startid, allRecords);

            }

            return allRecords;

        });

    }

    // レコード更新処理

    function updateRecords(appId, opt_records) {

        var records = opt_records.slice(0, 100);

        var next = opt_records.slice(100);

        if (records.length === 0) return kintone.Promise.resolve(0);

        var params = { app: appId, records: records };

        return kintone.api(kintone.api.url('/k/v1/records', true), 'PUT', params).then(function (resp) {

            console.log('update records', resp);

            if (next.length === 0) {

                return 0;

            }

            return updateRecords(appId, next);

        });

    }

})();

rex0220

お世話になります。

詳細にご教示いただきまして誠にありがとうございます。いただきましたコードで無事、動きが確認できました!

いただきましたコードと自分が書いてみたコードを比べてみて一つずつ勉強していければと思います。

この度は大変ありがとうございました!