関連レコード集計について

いつも大変お世話になっております。

関連レコードの項目を条件付きで集計 を参考に、関連レコード一覧より、「出席」した方の人数を「出席人数」に計算したいですが、初心者のためサンプルの変更箇所を確定できず、彷徨って投稿させていただきました。

(function() {
“use strict”;

//レコードの編集、詳細画面で適用する
var events = [
‘app.record.detail.show’,
‘app.record.edit.show’
]
kintone.events.on(events, function(event) {
var record = event.record;
var client_rid = event.recordId;
var related = kintone.app.getRelatedRecordsTargetAppId(‘関連レコード一覧’);
var offset = 0;
var loop_end_flg = false;
var records = new Array();
while(!loop_end_flg){
var query = ‘ドロップダウン in (“出席”)’ +
’ limit 100 offset ’ + offset;
query = encodeURIComponent(query);
var appUrl = kintone.api.url(‘/k/v1/records’) + ‘?app=’+ related + ‘&query=’ + query;

// 同期リクエストを行う
var xmlHttp = new XMLHttpRequest();
xmlHttp.open(“GET”, appUrl, false);
xmlHttp.setRequestHeader(‘X-Requested-With’,‘XMLHttpRequest’);
xmlHttp.send(null);

//取得したレコードをArrayに格納
var resp_data = JSON.parse(xmlHttp.responseText);

if(resp_data.records.length > 0){
for(var i = 0; resp_data.records.length > i; i++){
records.push(resp_data.records[i]);
}
offset += resp_data.records.length;
}else{
loop_end_flg = true;
}
}

var amount = 0;
for (var i = 0; i < records.length; i++) {
amount = amount + parseFloat(records[i].数値.value);
}

var divTotalAmount = document.createElement(‘div’);
divTotalAmount.style.fontWeight = ‘bold’;
divTotalAmount.style.textAlign = ‘right’;
divTotalAmount.style.fontSize = 12;
var wString = String(amount.toFixed(0).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, ‘$1,’));
divTotalAmount.innerHTML = “\” + wString + “-”;
kintone.app.record.getSpaceElement(“TotalAmount”).appendChild(divTotalAmount);

return event;

});
})();

 

最後は「集客実績」に反映されたいですが、貴重なアドバイスいただいたら幸いです。よろしくお願い致します。

 

玲香様

お世話になっております。 cstapの江田です。

条件に一致するレコード数を数えるだけなので、

varamount=0;for(vari=0;i\<records.length;i++){amount=amount+parseFloat(records[i].数値.value);}

varamount=records.length;

に変更してください。

また、合計数をフィールドに登録するのであれば、

varevents=['app.record.detail.show','app.record.edit.show']

varevents=['app.record.create.submit','app.record.edit.submit']

に変更して、

vardivTotalAmount=document.createElement('div');divTotalAmount.style.fontWeight='bold';divTotalAmount.style.textAlign='right';divTotalAmount.style.fontSize=12;varwString=String(amount.toFixed(0).replace(/(\d)(?=(\d\d\d)+(?!\d))/g,'$1,'));divTotalAmount.innerHTML="\\"+wString+"-";kintone.app.record.getSpaceElement("TotalAmount").appendChild(divTotalAmount);

record.集客実績のフィールドコード.value=amount;

に変更してください。

あとは、フィールドコードを自分のアプリに合わせて変えれば動作すると思います。 パッと見ですが元コードのフィールドコードはどれも日本語になっていそうなのでそのあたりを調整するとよいかと思います。

余談ですが、records.jsonでGETを行う場合、totalCountというパラメータを用いるともっと簡単にレコード件数が取得できます。 https://developer.cybozu.io/hc/ja/articles/202331474#step2

また、XMLHttpRequestは非推奨とされているので、できればkintone.api()を用いた実装に変えた方がいいと思います。

江田篤史 様

いつもお世話になっております。

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

教えていただいたように以下のソースで動かしてみました。

(function() {
“use strict”;

//レコードの編集、詳細画面で適用する
var events = [
‘app.record.create.submit’,
‘app.record.edit.submit’
]
kintone.events.on(events, function(event) {
var record = event.record;
var client_rid = event.recordId;
var related = kintone.app.getRelatedRecordsTargetAppId(‘関連レコード一覧’);
var offset = 0;
var loop_end_flg = false;
var records = new Array();
while(!loop_end_flg){
var query = ‘NO ="’ + client_rid +
‘" and ドロップダウン in (“出席”)’ +
’ limit 100 offset ’ + offset;
query = encodeURIComponent(query);
var appUrl = kintone.api.url(‘/k/v1/records’) + ‘?app=’+ related + ‘&query=’ + query;

// 同期リクエストを行う
var xmlHttp = new XMLHttpRequest();
xmlHttp.open(“GET”, appUrl, false);
xmlHttp.setRequestHeader(‘X-Requested-With’,‘XMLHttpRequest’);
xmlHttp.send(null);

//取得したレコードをArrayに格納
var resp_data = JSON.parse(xmlHttp.responseText);

if(resp_data.records.length > 0){
for(var i = 0; resp_data.records.length > i; i++){
records.push(resp_data.records[i]);
}
offset += resp_data.records.length;
}else{
loop_end_flg = true;
}
}

var amount = records.length;
record.集客実績.value = amount;

return event;

});
})();

エラーになっております。また「集客実績」は0となってます。

やっぱり教えて頂いたように、totalCount とkintone.api() に変えてやってみたほうがよろしいでしょうか?

玲香様

お世話になっております。
cstapの江田です。

XMLHttpRequestは非推奨なだけなので、動作しない場合は他に原因があるかと思います。

queryの設定は正しくできていますでしょうか?
records.jsonで関連レコードを取得する場合、関連レコードフィールドの設定の「表示するレコードの条件」と同じ条件をqueryに記述することで実装します。
上記コードからは、「レコード番号」と「NO」での関連レコードの紐づけを想定しているように見えますが、そちらで合っていますか?

江田篤史

いつも大変お世話になっております。

お返事ありがとうございます。

NOは【セミナーマスタ】でユーザーが手書きで番号いれるようにしてます。【参加者名簿】にはルックアップしております。

同じセミナーでも区分が違う場合があります。

なにかアドバイスいただいたら幸いです。よろしくお願い致します。

玲香様

お世話になっております。

左様でしたら、queryは

var query = 'NO ="' + event.record.NO.value +
'" and ドロップダウン in ("出席")' +
' limit 100 offset ' + offset;

となるかと思います。

江田篤史様

いつもご親切に幅広く教えていただき、とても感謝しております。

おかげ様で伝授して頂いた以下のソースでカウントは出来ました。

(function() {
“use strict”;

//レコードの編集、詳細画面で適用する
var events = [
‘app.record.create.submit’,
‘app.record.edit.submit’
]
kintone.events.on(events, function(event) {
var record = event.record;
var related = kintone.app.getRelatedRecordsTargetAppId(‘関連レコード一覧’);
var offset = 0;
var loop_end_flg = false;
var records = new Array();
while(!loop_end_flg){
var query = ‘NO ="’ + event.record.NO.value +
‘" and ドロップダウン in (“出席”)’ +
’ limit 100 offset ’ + offset;

query = encodeURIComponent(query);
var appUrl = kintone.api.url(‘/k/v1/records’) + ‘?app=’+ related + ‘&query=’ + query;

// 同期リクエストを行う
var xmlHttp = new XMLHttpRequest();
xmlHttp.open(“GET”, appUrl, false);
xmlHttp.setRequestHeader(‘X-Requested-With’,‘XMLHttpRequest’);
xmlHttp.send(null);

//取得したレコードをArrayに格納
var resp_data = JSON.parse(xmlHttp.responseText);

if(resp_data.records.length > 0){
for(var i = 0; resp_data.records.length > i; i++){
records.push(resp_data.records[i]);
}
offset += resp_data.records.length;
}else{
loop_end_flg = true;
}
}

var amount = records.length;

record.集客実績.value = amount;

return event;

});
})();

 

お忙しいところ大変恐縮でございますが、やっぱり前回江田篤史さんが提案して頂いたように、 totalCountkintone.api()を用いた実装に変えたくてちょっと試してみましたが、全然うまく組めなく(TーT)。お時間あるときにアドバイスいただけますでしょうか?よろしくお願い致します。

return kintone.api(kintone.api('/k/v1/records', true), "GET", {
totalCount: true,
query : 'NO ="' + client_rid +
'" and ドロップダウン in ("出席")'} .then(function(res) {
record["集客実績"].value = res.totalCount;
return event;
});

玲香様

お世話になっております。

このあたりの記事が参考になるかと思います。

kintone.apiの第1引数は、

kintone.api('/k/v1/records', true)

ではなく、

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

になります。

また、第3引数には対象となるアプリのIDを記述する必要があります。

{
  app: related,
  totalCount: true,
  query: 'NO ="' + record.NO.value + '" and ドロップダウン in ("出席")'
}

あと、「.then」の前に「)」が必要ですね。

江田篤史様

いつもお世話になっております。

おかげさまで解決できました。本当にありがとうございます。

しかも長かったソースが  totalCountkintone.api()を用いたことでこんなにも簡単になるって感動するばかりです。

(function() {
“use strict”;

//レコードの編集、詳細画面で適用する
var events = [‘app.record.create.submit’, ‘app.record.edit.submit’]
kintone.events.on(events, function(event) {
var record = event.record;
var related = kintone.app.getRelatedRecordsTargetAppId(‘関連レコード一覧’);

return kintone.api(kintone.api.url(‘/k/v1/records’, true), “GET”, {
app: related,
totalCount: true,
query: ‘NO ="’ + record.NO.value + ‘" and ドロップダウン in (“出席”)’
}).then(function(res) {
record[“集客実績”].value = res.totalCount;
return event;
});

});
})();

 

もう一個追加で質問させていただいてもよろしいでしょうか?

今のソースでは、「参加者名簿」に人数追加した場合、「マスター」いったん編集して保存すれば「集客実績」の数値が変更になる(プラスされる)ようになってますが、関連レコードの項目を条件付きで集計 のような自動で「小計」が更新されることは可能でしょうか?

長々といつもお手数をおかげしますが、アドバイスいただけたら幸いです。よろしくお願い致します。

玲香様

お世話になっております。

実装できると思います。
しかし、参考記事の場合と比較すると少し困難です。
参考記事での件数は保存されないため、利用する際は毎回数え直す必要があります。
今回の集客実績は保存することにより、様々なところに使いまわせる反面、データが古い可能性が出てきて管理が必要になります。
利用する局面が限られる場合や、更新が頻繁に行われる場合は、参考記事のような利用の都度数え直す実装法の方が向いています。
利用する回数と変更する回数を見比べて、集客実績を保存するべきか考え直しても良いかもしれません。

集客実績を保存する実装であれば、集客実績を変更し得る場所に更新するための機能を実装する必要があります。
今までのカスタマイズに加え、参加者名簿アプリをJavaScriptカスタマイズすることになります。
参加者名簿アプリ側でレコード追加・編集した際、影響を受けるマスターアプリのレコード(編集前後のNOと一致するマスターアプリのレコード)について集客実績を減らしたり増やしたりすることで実装できるかと思います。

参考になりそうな記事を載せておきます。
レコードの更新(PUT)

江田篤史様

いつもお世話になっております。何度も何度もアドバイスいただき本当にありがとうございます。

前の設定をちょっと変えてまして、NOを使わず、「セミナー名」で値の重複を禁止することにしました。

それで、やっぱりおっしゃるとおり「集客実績」を保存する実装にしたいので、以下のようにコード書いてみました。

今までのように、編集をクリックすれば集客実績は更新されます。またコードがおかしいため、一覧のところで

のようなエラーになっております。コードのご指導いただけますでしょうか?

本当に申し訳ございませんが、ご指導していただけると幸いです。よろしくお願い致します。

(function() {
“use strict”;

var events = [‘app.record.create.submit’, ‘app.record.edit.submit’,‘app.record.index.show’,
‘app.record.create.submit.success’, ‘app.record.edit.submit.success’]
kintone.events.on(events, function(event) {
var record = event.record;
//var related = kintone.app.getRelatedRecordsTargetAppId(‘関連レコード一覧’);

return kintone.api(kintone.api.url(‘/k/v1/records’, true), “GET”, {
//app: related,
app: ****,//参加者名簿のアプリID
totalCount: true,
query: ‘セミナー名 ="’ + record.セミナー名.value + ‘" and 参加状況 in (“出席”)’
}).then(function(res) {
record[“集客実績”].value = res.totalCount;
return event;
});

return kintone.api(‘/k/v1/record’, ‘PUT’, {
“app”:****, //参加者名簿のアプリID
“updateKey”: {
 “field”: “セミナー名”,
“value”: セミナー名
},
“record”: {
“参加状況”: { “value”: relationRecords.length },
“会社名”: { “value”: 会社名 },
}

}).then(function(){
return event;
});

});
})();

玲香様

お世話になっております。

「app.record.index.show」を「app.record.index.edit.submit」に変更すればよいかと思います。
また、重複して更新してしまっているので、「app.record.create.submit」と「app.record.edit.submit」は指定しなくてよいかと思います。

var events = [‘app.record.index.edit.submit’, ‘app.record.create.submit.success’, ‘app.record.edit.submit.success’]

江田篤史様

いつもご指導いただき、本当にありがとうございます。

前回のエラーはなくなりましたが、今「集客実績」が自動計算されなくなって、 'PUT’のコードがおかしいでしょうか?

お手すきなときにご教示して頂いてもよろしいでしょうか?

(function() {
“use strict”;

var events = [‘app.record.index.edit.submit’, ‘app.record.create.submit.success’, ‘app.record.edit.submit.success’]
kintone.events.on(events, function(event) {
var record = event.record;

return kintone.api(kintone.api.url(‘/k/v1/records’, true), “GET”, {

app: 212,//参加者名簿のアプリID
totalCount: true,
query: ‘セミナー名 ="’ + record.セミナー名.value + ‘" and 参加状況 in (“出席”)’
}).then(function(res) {
record[“集客実績”].value = res.totalCount;
return event;
});

return kintone.api(‘/k/v1/record’, ‘PUT’, {
“app”:212, //参加者名簿のアプリID
“updateKey”: {
“field”: “セミナー名”,
“value”: “セミナー名”
},
“record”: {
“参加状況”: { “value”: 出席 },
“会社名”: { “value”: 会社名 },
}

}).then(function(){
return event;
});

});
})();

玲香様

お世話になっております。

GETが完了してからPUTする必要があります。 JavaScriptの非同期処理やPromiseオブジェクトについて調べてみるとよいと思います。

また、PUTするのは「参加者名簿」ではなく「マスタ」ではないでしょうか?

returnkintone.api(kintone.api.url('/k/v1/records',true),"GET",{app:kintone.app.getId(),//参加者名簿のアプリIDtotalCount:true,query:'セミナー名 ="'+record.セミナー名.value+'" and 参加状況 in ("出席")'}).then(function(res){returnkintone.api('/k/v1/record','PUT',{"app":kintone.app.getLookupTargetAppId('セミナー名'),//マスタのアプリID"updateKey":{"field":"セミナー名","value":record.セミナー名.value},"record":{"集客実績":{"value":res.totalCount;}}});}).then(function(){returnevent;});

あとお節介かもしれませんが、後で見た人の混乱を避けるためにも「レコードの編集、詳細画面で適用する」というコメントは修正するか削除するかした方が良いかと思います。

江田篤史 様

お忙しいところ、いつもご指導いただき、ありがとうございます。

セミナー参加状況は名簿アプリに記入するようにしております。

教えて頂いたようにkintone.Promiseの書き方を閲覧致しましたが、

頂いたコードにはreturn kintone.となってますので、

return new kintone.Promise(function(resolve, reject) {

resolve(event);とかは追加不要でしょうか?

またGETとPUTについて、

app: kintone.app.getId(), //参加者名簿のアプリID

⇒「マスタのアプリID」になるでしょうか?

以下のように試してみましたが、エラーになっておりまして・・・

(function() {
“use strict”;

var events = [‘app.record.create.submit’, ‘app.record.edit.submit’,‘app.record.index.edit.submit’]
kintone.events.on(events, function(event) {
var record = event.record;

var related = kintone.app.getRelatedRecordsTargetAppId(‘関連レコード一覧’);

return kintone.api(kintone.api.url(‘/k/v1/records’, true), “GET”, {
app: related,
totalCount: true,
query: ‘セミナー名 ="’ + record.セミナー名.value + ‘" and 参加状況 in (“出席”)’
}).then(function (res) {

return kintone.api(‘/k/v1/record’, ‘PUT’, {
“app”:kintone.app.getId(), //マスタのアプリID
“updateKey”: {
“field”: “セミナー名”,
“value”: record.セミナー名.value
},
“record”: {
“集客実績”: {
“value”: res.totalCount
}
}
});
}).then(function () {
return event;
});

});

})();

うまく理解できず、何度も何度もご迷惑をおかけまして申し訳ございませんが、再度教授いただけることは可能でしょうか?

玲香様

お世話になっております。
返信遅くなりました。

「セミナー管理マスタ」アプリにJavaScriptを追加していませんか?
「セミナー参加者名簿」のレコードが追加・編集されたときに処理を行いたいので、JavaScriptを読み込ませるのは「セミナー参加者名簿」アプリです。

江田篤史 様

お忙しいところ、いつもご指導いただき、ありがとうございます。

おっしゃるとおり、「セミナー管理マスタ」アプリにJavaScriptを追加してました。ずっと悩んで来た原因が自分の勘違いで、ご迷惑ばかりかけて大変申し訳ございません。お蔭様で自動計算ができるようになりました。(とてもうれしいです。感謝いたします。)

ただ、検証の段階でまだ2個問題が発生しております。

①「セミナー参加者名簿」の一覧画面から 参加状況 を編集&レコードの削除を実行すると「セミナー管理マスタ」の 集客実績が 更新されない。

②「セミナー参加者名簿」のレコード編集画面からレコードの削除をすると「セミナー管理マスタ」の 集客実績が 更新されない。

試しにvar events = [‘app.record.create.submit’, ‘app.record.edit.submit’,‘app.record.index.edit.submit’]に

‘app.record.index.delete.submit’,‘app.record.detail.delete.submit’, ‘app.record.index.edit.show’,‘app.record.index.edit.change.参加状況’,‘app.record.create.change.参加状況’,'app.record.edit.change.参加状況’など追加してみましたが解決できなくて、なんででしょうか?再度助けていただけることは可能でしょうか?宜しくお願い致します。

玲香様

お世話になっております。

レコード保存後の件数を数えて、集客実績を書き換えたいので、
var events = [‘app.record.create.submit.success’, ‘app.record.edit.submit.success’,‘app.record.index.edit.submit.success’]
にした方がいいかと思います。

削除系のイベントについては、削除後のイベントがないので
‘app.record.index.delete.submit’,‘app.record.detail.delete.submit’
のまま
“record”: {
“集客実績”: {
“value”: res.totalCount - 1
}
とするしかないですね。

江田篤史様

いつも大変お世話になっております。

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