関連テーブルの値で計算した値を一括更新ボタンですべてのレコードに反映したい

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

以下のサイトを参考に関連テーブルの値を計算し、フィールドに格納する検討をしております。

1.関連テーブルの集計値を特定のフィールドに返したい

2.後で追加したフィールドに一括で値を反映する方法

このときに以下の通り実装をしたいと考えております。

1.一括更新ボタンを押下した際に一覧のすべてのレコードについて、関連テーブルを再度取得し、計算し、数値フィールドに登録する。

2.一括更新ボタンを実装し一覧のレコードに対し一括で実装する。

1に関しては、実装できたので2を別に実装した際に、集計値が更新されると思いましたがされませんでした。

別途一括更新の際に再計算する必要があるのでしょうか。

1のソース************************************************************************

(function() {
“use strict”;

//レコードの追加、編集、詳細画面で適用する

var events = [
‘app.record.detail.show’,
‘app.record.edit.show’
]
kintone.events.on(events, function(event) {
// var client_rid = event.recordId;

// 関連テーブルのAppIdを取得
var related = kintone.app.getRelatedRecordsTargetAppId(‘仕入れ情報’);

// レコード取得関数(100行制限)
function fetchRecords(appId, opt_offset, opt_limit, opt_records) {

var offset = opt_offset || 0;
var limit = opt_limit || 100;

var allRecords = opt_records || [];

// 詳細画面のレコードの情報取得
var record = event.record;
var bukkenNo = record[“物件No”].value;

var s_query = ‘物件No="’ + bukkenNo + '" limit ';

var params = {app: related, query: s_query + limit + ’ offset ’ + offset};

return kintone.api(‘/k/v1/records’, ‘GET’, params).then(function(resp) {
allRecords = allRecords.concat(resp.records);

if (resp.records.length === limit) {
return fetchRecords(related, offset + limit, limit, allRecords);
}
return allRecords;
});
}

// 小数点n位までを残す関数(切上げ)
// number=対象の数値
// n=残したい小数点以下の桁数
function floatFormat( number, n ) {

var _pow = Math.pow( 10 , n ) ;

return Math.ceil
( number * _pow ) / _pow ;
}

fetchRecords(kintone.app.getId()).then(function(records) {
var amount = 0;
var data_count = 0;
for (var i = 0; i < records.length; i++) {
amount = amount + parseFloat(records[i].税抜き金額.value);
data_count++;
}

//集計値設定()
var appid = kintone.app.getId();
var recid = kintone.app.record.getId();

//売上高取得
var record_2 = event.record;
var sales = record_2[“売上高”].value;

// 利益率=(売上高-仕入れ情報「税抜き金額」小計)/売上高 × 100
// 0除算の場合エラーになるため|0で0設定
var interestRate = (sales - amount)/sales*100|0;
interestRate = floatFormat(interestRate,2);
//仕入情報が更新されている場合、再度修正して仕入れ計と利益率更新

//初期登録時、仕入れ計と利益率に初期値登録
if ( ((record_2.仕入れ計.value != amount) || (record_2.利益率.value != interestRate)) ||
((record_2.仕入れ計.value == “”) || (record_2.利益率.value == “”))){
var Param = {
“app”:appid,
“id”:recid,
“record”:{
“仕入れ計”:{
“value”: amount
},
“利益率”:{
“value”: interestRate
},
},
};

kintone.api(“/k/v1/record”,
“PUT”,Param,
function(resp){
location.reload(true);
// alert(“登録成功”);
},
function(resp){
// alert(“登録エラー”);
}
);
};

});

return event;

});
})();

2のソース*********************************************************************

(function () {

“use strict”;

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

if (document.getElementById (‘my_index_button’) != null) {

return;

}

var myIndexButton = document.createElement(‘button’);

myIndexButton.id = ‘my_index_button’;

myIndexButton.innerHTML = ‘再計算’;

 

// ボタンクリック時の処理

myIndexButton.onclick = function() {

var appId = kintone.app.getId();

kintone.api(‘/k/v1/records’, ‘GET’, {app: appId}, function(resp) {

//////// 空更新オブジェクトの生成

var param = {

“app”: appId,

“records”: []

};

for (var i = 0; i < resp[‘records’].length; i++) {

param[‘records’][i] = {

“id”: resp[‘records’][i][‘物件No’][‘value’],

“record”: {}

}

}

kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘PUT’, param, function(resp) {

// success

console.log(resp);

}, function(error) {

// error

console.log(param);

console.log(error);

});

});

}

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

});

})();

 

takokichi さん

レコードの更新の際に更新キーとして使用できるフィールドは以下の2種類が存在します。

・レコード番号

・「値の重複を禁止する」にチェックがされた、文字列(1行)または数値フィールド

また、レコード番号を指定する場合とそれ以外のフィールドを指定する場合で、

リクエストパラメータの設定方法が異なります。

参考いただいたページではレコード番号を指定していましたが、載せていただいたソースコードでは

レコード番号以外のフィールドだと想定される”物件No”を指定されているため、

レコード番号以外を指定する場合の書き方で、パラメータを作成する必要がありそうです。

詳しくはdeveloper networkに存在する、kintone REST API レコード更新(PUT)のページを参考に、

コードを修正してみてください。

また、一回のAPI呼び出しで更新できるのは100件までのため、それ以上のレコード数を更新する場合には

もうひと工夫が必要になりそうです。

以上、ご参考までに。

 

本田様

早急に回答頂きありがとうございます。

”物件No”フィールドですが、レコード番号のフィールドでフィールドコードをこちらで変更したものです。

補足が足りず申し訳ありません。

今回の件では現在関連テーブルで再計算している集計値を一括更新で更新できるのか。

この工夫ができず悩んでいる次第です。

100件の件は関連テーブルに関しては、了解済みです。(そこまでデータがないため考慮しません)

一括更新に際しては工夫が必要だとおもっております。

関連テーブルの一括更新が出来次第問題にしようかとおもっておりました。

 

takokichi さん

レコード番号のフィールドコードを変更しておられたのですね!

レコードIDであれば必ず $id で指定が行えるため、レコードIDの使用をオススメします。

 

>今回の件では現在関連テーブルで再計算している集計値を一括更新で更新できるのか。

上記については、可能だと考えています。

ソース1において、レコード単位での関連レコードの集計値を算出する処理はできていると

考えられます。(動作確認はされていると思います)

 

 

ただ、ソース1ではレコード単位でのイベントを検知しているため、

例えば1件のレコードを受け取って集計値を返すように処理を変更し、

ソース2でレコードの一括取得を行っている部分でレコード1件毎にソース1の処理を呼ぶ事で、

一覧画面から各レコードの集計値を取得できると考えられます。

各レコードの集計値を取得後、レコードの一括更新でフィールドに値をセットすれば、

目的の処理が実装できるかと思います。

(直接フィールドに値をセットしているため、空更新でなくページの更新の処理を行えば良いと思います)

 

 

本田様

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

 

以下のソースで関連レコードで取得したレコード(siireRec)を使用し、

アプリのレコードに(respdata)値を設定し、更新しようと試みました。

がアプリのレコードが引き継げずに苦戦しております。

引き継ぐ方法(JSの知識になるかもしれませんが。。。)はございますでしょうか。

fetchRecords(respdata[‘records’][i]).then(function(siireRec) {

var amount = 0;
var data_count = 0;
for (var i = 0; i < siireRec.length; i++) {
amount = amount + parseFloat(siireRec[i].税抜き金額.value);
data_count++;
}

var sales = respdata[‘records’][i][‘売上高’][‘value’];

// 利益率=(売上高-仕入れ情報「税抜き金額」小計)/売上高 × 100
// 0除算の場合エラーになるため|0で0設定
var interestRate = (sales - amount)/sales*100|0;
interestRate = floatFormat(interestRate,2);

//オブジェクトに値をセット
param[‘records’][i] = {

“id”: respdata[‘records’][i][‘物件No’][‘value’],

“record”:{
“仕入れ計”:{
“value”: amount
},
“利益率”:{
“value”: interestRate
},
},

}
}
);

takokichi さん

1行目のrespdata[‘records’][i]を、then以降のfunctionにて使いたい、とのご要望だと思います。

1行目のfetchRecords()を呼んでいる処理があると思いますが、fetchRecords()を呼ぶ前に、

適当な変数に対してrespdata[‘records’][i]をセットし、then以降のfunctionでその変数を

呼び出す事で、レコードが引き継げると思います。

以下のようなコードのイメージです。

// レコードのバックアップ用変数
var recordBackup = '';
function func1() {
for (var i = 0; i < respdata['records'].length; i++) {
recordBackup = respdata['records'][i];
fetchRecords(respdata['records'][i]).then(function(siireRec) {
// respdata['records'][i]の代わりにrecordBackupを使う
});
}
}

 

本田智明様

ご丁寧にソースまで記載していただきありがとうございました。

 

無事実装できました。

またご指定いただいたとおり、100件以上の更新となるため、GETの部分に関してはこちらを参考に同期処理に書き換えました。

PUTに関してはid指定のため同期処理のままにしております。

ありがとうございました。

 

 

takokichi さん

動作したようで良かったです!