同一アプリ内のキーが一致するレコードを一括更新したい。

お助けいただきたいです。

同様のトピックが多数あることは存じ上げておりますが、

それらを参考に、いろいろと試行錯誤してみても、

PUTでエラーとなり、思う通りに一括更新ができません。

◆実現したいこと

同一アプリ内において、追加または編集した現レコードのチェックボックスの値を

顧客Noが一致する全てのレコードに対して、反映したいです。

◆現状

更新対象のフィールドは、複数チェックボックスがある中の1つのみ。

フィールドコード:識別

選択肢:契約締結、抽出リストから除外

◆現段階でのコード

(function() { 'use strict'; kintone.events.on(['app.record.create.change.識別','app.record.edit.change.識別'], function(event) { var action = event.record.識別.value; if(action.indexOf('契約締結') != -1 && action.indexOf('抽出リストから除外') == -1){ event.record['識別'].value = ['契約締結','抽出リストから除外']; } }); function createPutRecords(records) { var putRecords = []; for (var i = 0, l = records.length; i < l; i++) { var rec = event.record; var record = records[i]; putRecords[i] = { id: record.$id.value, record: { 識別:{ value: rec['識別'].value } } }; } return putRecords; } // 「識別」変更時イベント kintone.events.on(['app.record.create.submit.success','app.record.edit.submit.success'], function(event) { var appId = kintone.app.getId(); var action = event.record.識別.value; // レコードの一括取得(100件まで) var paramGet = { 'app': appId, 'query': '顧客No = "' + event.record['顧客No'].value + '"' }; console.log(paramGet); return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', paramGet).then(function(resp) {
        // ルックアップの更新 var records = resp.records; var paramPut = { 'app': appId, 'records': createPutRecords(records) }; console.log(paramPut); return kintone.api(kintone.api.url('/k/v1/records', true), 'PUT', paramPut); }).then(function(resp2) {
            // 処理成功 alert('該当レコードの更新が完了しました!'); return event;
        }).catch(function(error) {
            // エラー表示をする alert('該当レコードの更新でエラーが発生しました。' + error.message); return event;
        });
    });})();

SK さん

PUT のときにエラーになるとのことですが、どんなエラーが出ていますか?

以下の記事を参考にエラーの情報を載せてもらえるとどこを直せばいいか判断しやすいです。
動かない?そんな時はデバッグをしてみよう!入門編

ソースコードを見ると、PUT でエラーになっているそうなので、
PUT のリクエストパラメータ(paramPut)を追ってみると、
この部分に原因がありそうです。

putRecords[i] = {
    id: record.$id.value,
    record: {
    識別:{
    value: rec['識別'].value
}
}
};

cybozu developer network 内にある「フィールド形式」の記事はご覧になりましたか?
今回更新しようとしているチェックボックスフィールドが内部的にどのような形で値を持っているか記載されています。
フィールドの形式 > カスタムフィールド > チェックボックス と順を追って探してみてください。

「識別」と記載しているところが以下の形になるように書き換えてみるのはどうでしょうか?

"<フィールドコード>": {
    "value": [
        "選択肢1",
        "選択肢2"
    ]
}

 

kzzz様

コメントありがとうございます。

現在のコードだと、コンソールログでエラーが出ずに、画像のようなアラート表示のみとなっており、

ご指摘の部分が問題だろうとは考え、ご提案いただいた書き方も既に試したのですが、

チェックボックスが常に固定の値になってしまうようです。

 

実現したいこととしては、「契約締結」にチェックを入れてレコードを保存した時は、

同アプリ内で顧客No.が一致する既存のレコードにも「契約締結」にチェックを入れて更新する。

同様に「抽出リストから除外」にチェックを入れて保存した時は、「抽出リストから除外」にチェックを入れて更新。

両方にチェックを入れて保存した時は、両方に。

チェックがなければチェックのない状態で、と流動的に対応したいです。

そもそも実現可能なのでしょうか?

SK さん

①エラーについて

画像の3行目に

Cannot read property ‘識別’ of undefined

とありますね。

上記のエラーについては調べましたか?
かんたんに説明すると、‘識別’ と記載している部分にアクセスできません、みたいなエラーです。
記載してくださったソースコードの中には ‘識別’ と記載しているところが2つあるのですが、
PUT の部分でエラーが出ていそうなので、やはり以下の部分がおかしそうですね。

putRecords[i] = {
    id: record.$id.value,
     record: {
     識別:{
    value: rec['識別'].value
}
}
};

‘rec’ という変数がきちんと定義・取得できているか確認してみるといいかもしれないです。

また、エラーの画像にドメイン名が見えてしまっているので、コメントアクションの部分からコメントを編集して、画像を削除するか、ドメイン名を隠したエラーの画像をアップするかどちらか対処したほうがよさそうです。

② for 文の書き方について

createPutRecords 関数の中に記載している for 文の引数部分がもしかすると違うかしれません。

for(vari =0, l = records.length; i < l; i++) {

for 文の引数は3つのはずですが、現在4つあるように見受けられます。
ドキュメントサイトなどを確認して正しい書き方に直してください。
参考: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for

直すとしたら以下のような感じになるかなと思います。

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

③実現可能かどうかについて

実現可能かどうかということですが、カスタマイズをすればできることなのではないかと思います。
まずは一つ一つエラーをなくしていって、正しい書き方に近づけていきましょう。

kzzz様

コメントありがとうございます。

ドメイン名、失念しておりました。ご指摘いただき、ありがとうございます。

①につきましては、いろいろと試行錯誤するも、実現したい形になりませんでした。

ちなみに、

【パターン1】 putRecords[i] = {
id: record.$id.value,
record: {
識別:{
value: ['契約締結','抽出リストから除外']
}
}
};

にすると、更新はされるが、全ての該当レコードの値が両方チェックとなり、

【パターン2】 putRecords[i] = {
id: record.$id.value,
record: {
識別:{
value: record.識別.value
}
}
};

にすると、各レコードそのままの値になるだけでした。

パターン1の記述で、格納する値を4通りつくり、if文で書き分けてもみましたが、今一歩思い通りになりませんでした。

自レコードの値を用いて、他の該当レコードを更新するための

具体的な書き方を教えていただくことは可能でしょうか?

 

②につきましては、第11回 kintone REST APIを利用したレコード更新(ルックアップ自動更新)の中でも紹介されており、

引数としては3つで、実質上記コードに中身を書き換えても動いてはいるので、問題ないはずですが…ダメでしょうか?

よろしくお願いいたします。

SK さん

簡単にこちらで似たようなアプリを作成し、いろいろ試してみました。

重ねての内容にはなってしまいますが、
まず、原因としては、createPutRecords 関数内で定義してる rec という変数がきちんと定義されていないため、

Cannot read property ‘識別’ of undefined

というエラーが出ています。

おそらく、レコード編集画面の保存成功後イベントが実行されたときのレコードが持っている「識別」フィールドの値を
定義したくて、rec という変数を定義しているのかと考えます。

そのため、この rec をきちんと定義することができればこのソースコードは動くかと思います。
kintone.app.get.record() はイベントハンドラー内では使えないため、
取得したレコードのうち、どのレコードがコピー元にするレコードなのかを判別することができれば解決できそうです。

 

for 文については失礼しました。あまり書かない書き方だったので、違和感を感じたのでコメントしました…。
SK さんが書きやすい書き方で大丈夫かと思います。

SK さん

createPutRecords 関数に現在作成・編集しているレコードの「識別」フィールドの値を渡せていないことが原因だったので、
kintoneにおけるPromiseの書き方の基本 の「Promise を利用する(複数回)」を参考に書き換えてみたところ、正常に動きました。

以下に一番最初に記載していたソースコードを抜粋して、書き換える箇所をコメントアウトで書いてみました。

PUT のリクエストパラメータの中で、
「識別」フィールドに渡す値をすでに定義している変数 action で渡してあげるのがポイントです。
push() メソッドなんかを使うとうまくいくかもしれないです。

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

var records = resp.records;

// この部分に createPutRecords 関数の処理を書く
var putRecords = [];

// for 文を書く
    for (var i = 0; i < records.length ; i++) {


}

var paramPut = {
app: appId,
records: putRecords
};

return kintone.api(kintone.api.url('/k/v1/records', true), 'PUT', paramPut);
}).then(function(resp2) {

 

kintone REST API のレコードの一括更新のドキュメントも参考になるのでぜひ。

 

 

kzzz様

何度もご丁寧に教えていただき、ありがとうございます。

教えていただいた内容を元に下記に書き換えて、ようやく思いどおりに実現できました!

(function() {
'use strict';

kintone.events.on(['app.record.create.change.識別','app.record.edit.change.識別'], function(event) {
var action = event.record.識別.value;

if(action.indexOf('契約締結') != -1 && action.indexOf('抽出リストから除外') == -1){
event.record.識別.value = ['契約締結','抽出リストから除外'];
}
});

// 「識別」変更時イベント
kintone.events.on(['app.record.create.submit.success','app.record.edit.submit.success'], function(event) {
var rec = event.record;
var appId = kintone.app.getId();
var action = rec.識別.value;

// レコードの一括取得(100件まで)
var paramGet = {
'app': appId,
'query': '顧客No = "' + rec.顧客No.value + '"'
};

console.log(paramGet);
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', paramGet).then(function(resp) {

// ルックアップの更新
var records = resp.records;
var putRecords = [];

for (var i = 0; i < records.length; i++) {
var record = records[i];
putRecords[i] = {
id: record.$id.value,
record: {
識別:{
value: action
}
}
};
}

var paramPut = {
'app': appId,
'records': putRecords
};

console.log(paramPut);
return kintone.api(kintone.api.url('/k/v1/records', true), 'PUT', paramPut);

}).then(function(resp2) {
// 処理成功
console.log('更新完了!');
return event;
}).catch(function(error) {
// エラー表示をする
alert('顧客No.が一致するレコードの一括更新でエラーが発生しました。' + error.message);
return event;
});

});
})();

原因が見つけられても、どうするのが正解なのか分からず、本当に困っていました。

見よう見まねで進めてきたが故に、根本的な部分の理解がまだまだだと痛感したので、

それぞれのドキュメントを熟読したいと思います。

本当にありがとうございました!

SK さん

無事に解決されたとのことで安心しました。
今回私も勉強になることがありました。
こちらこそありがとうございました!