【簡単】queryを書かずに関連レコードを取得&集計

関連レコードを集計する場合は、こちらの記事のように、フィールド設定と同値のqueryを書きrecords.json等を用いてレコードの取得を行う必要があります。 今回、フィールドコードを入力するだけで該当するレコードを取得してくれるコンストラクタを作成しました。 是非ご活用ください。

コンストラクタ

・RelatedRecordsFieldManager.js

window.RelatedRecordsFieldManager = (function(fieldCode){
  var RelatedRecordsFieldManager = function(fieldCode){
    this.fieldCode = fieldCode;
    this.property = this.fieldProperties[fieldCode].referenceTable;
    this.targetAppId = this.property.relatedApp.app;
  }
  RelatedRecordsFieldManager.prototype = {
    selfAppId: kintone.app.getId(),
    records: [],
    limit: 500,
    getFieldProperties: function(){
      return kintone.api(kintone.api.url('/k/v1/app/form/fields', true), 'GET', {
        app: RelatedRecordsFieldManager.prototype.selfAppId,
      }).then(function(response){
        RelatedRecordsFieldManager.prototype.fieldProperties = response.properties;
      });
    },
    query: function(record){
      return (
        this.property.condition.relatedField +
        '="' +
        record[this.property.condition.field].value +
        (this.property.filterCond ? '" and ' : '"') +
        this.property.filterCond
      );
    },
    getRecords: function(record){
      var _this = this;
      return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', {
        app: this.targetAppId,
        query:
          this.query(record) +
          ' order by ' + this.property.sort +
          ' limit ' + this.limit +
          ' offset ' + this.records.length
      }).then(function(response){
        _this.records = _this.records.concat(response.records);
        return response.records.length === _this.limit ? _this.getRecords(record) : _this.records;
      });
    }
  }
  return RelatedRecordsFieldManager;
})();

利用例

営業支援パックの顧客管理アプリの関連レコードフィールドについて集計を行います。 案件一覧の合計費用の合計値と活動履歴の件数を表示します。 アプリの設定にて、要素ID「space1」と「space2」のスペースフィールドを追加しています。
上記の「RelatedRecordsFieldManager.js」を読み込み後、下記「sample.js」を読み込みます.

コード

・「sample.js」

(function(){"use strict";kintone.events.on(['app.record.detail.show','app.record.edit.show'],function(event){// まず、アプリのフィールド設定を取得しておくRelatedRecordsFieldManager.prototype.getFieldProperties().then(function(){// 関連する案件一覧のレコードを取得する(newRelatedRecordsFieldManager('案件一覧')).getRecords(event.record).then(function(records){// space1に合計費用の合計値を表示kintone.app.record.getSpaceElement("space1").innerHTML=records.reduce(function(sum,record){returnsum+Number(record.合計費用.value);},0).toLocaleString();});// 関連する活動履歴のレコードを取得する(newRelatedRecordsFieldManager('活動履歴')).getRecords(event.record).then(function(records){// space2にレコード数を表示kintone.app.record.getSpaceElement("space2").innerHTML=records.length;});});});})();

デモ

 

※2019/01/28 記事修正しました。
(「RelatedRecordsFieldManager.js」と「sample.js」に分割。)

※2020/04/08 記事修正しました。
(「RelatedRecordsFieldManager.js」の「targetAppId」)

江田さま>ありがとうございました。「こちらの記事」から教えていただきました。

コンストラクタ理解できれば良いのですが、ちょっと・・・

もしできれば、、limit: 500 の具体的な意味だけでもm( _ )m

りょうすけ様

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

本コードにおいて関連レコードの取得はkintone REST APIを用いて行っておりますが、その一回の通信あたりに取得するレコード件数がlimitで設定する値にあたります。
本コードでは、再帰処理を行うことで関連レコードを全件取得するまで通信を繰り返します。
例えば、関連レコードが850件あるとき、
「limit: 500」の場合は通信を2回行い、
「limit: 100」の場合は通信を9回行います。
現状、limitは最大で500まで設定できるので、特別な理由がない限りは通信回数が最小となる500に設定しておくのが良いかと思います。
https://developer.cybozu.io/hc/ja/articles/202331474#step2

もし、全件取得はせず、取得する関連レコードの件数に制限をかけたい場合は、再帰処理をやめるとよいです。

if(response.records.length===\_this.limit){return\_this.getRecords(record);}else{return\_this.records;}

return\_this.records;

江田様

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

この記事のおかげで関連レコードから月別の売上と原価の集計ができるようになりました。

ありがとうございます。

その際、集計結果をスペースフィールドではなく数値フィールドに表示させるようにはできたのですが、その数値を利用して

計算値に利用することができないようです。

またその集計結果が一覧画面にも表示されない状態です。

この集計結果を利用可能な数値にすることはできますでしょうか?

jQuery.noConflict();
(function($) {
“use strict”;
kintone.events.on(“app.record.index.show”, function(e) {
});
})(jQuery);
(function() {
“use strict”;
kintone.events.on([
‘app.record.detail.show’,
‘app.record.edit.show’
], function(event){
// まず、アプリのフィールド設定を取得しておく
RelatedRecordsFieldManager.prototype.getFieldProperties().then(function(){
// 関連する案件一覧のレコードを取得する
(new RelatedRecordsFieldManager(‘関連レコード一覧4’)).getRecords(event.record).then(function(records){
// sale4に合計費用の合計値を表示
kintone.app.record.getFieldElement(“sale4”).innerHTML =
records.reduce(function(sum, record){
return sum + Number(record.sale.value);
}, 0).toLocaleString();
});
});
});

 

やるしかないんだ!様

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

DOMを書き換えるだけではレコードに反映されないので,「change」や「submit」イベントでeventオブジェクトを書き換えてreturnするのが良いと思います.
https://developer.cybozu.io/hc/ja/articles/201941984#step2

(function(){"use strict";kintone.events.on(['app.record.create.submit','app.record.edit.submit'],function(event){returnnewkintone.Promise(function(resolve){RelatedRecordsFieldManager.prototype.getFieldProperties().then(function(){(newRelatedRecordsFieldManager('関連レコード一覧4')).getRecords(event.record).then(function(records){event.record.sale4.value=records.reduce(function(sum,record){returnsum+Number(record.sale.value);},0);resolve(event);});});});});}());

※コード修正しました

江田様

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

関連レコードの集計ではなく、それぞれの数値、

上記の例ですと、それぞれの合計費用を数値フィールドに表示させ、利用したいと考えてます。

その場合のコードの仕組みを教えていただけませんでしょうか?

初歩的な質問で申し訳ありませんが、よろしくお願いします。

H_ishi様

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

やるしかないんだ!様の案件と同様と考えてよろしいでしょうか?

kintoneでは「‘app.record.create.submit’」および「‘app.record.edit.submit’」イベントで,eventオブジェクトを書き換えてreturnすると,レコードを書き換えることができます.
https://developer.cybozu.io/hc/ja/articles/201941984#step4

また,kintone.Promiseオブジェクトをreturnすると,非同期処理を待ってからレコードを書き換えることができます.
https://developer.cybozu.io/hc/ja/articles/204564604

非同期処理に関しては,google等で検索するとわかりやすく解説している記事があるかと思います.

江田様

はじめまして、お世話になっております.

関連レコードの集計が行いたくて、こちらの記事を発見しました。

 

コードの初心者で申し訳ないのですが、

コンストラクタの使い方がわかりません。

 

コードは「JavaScript / CSSでカスタマイズ」に、指定の拡張子で登録すればよいと思うのですが。

(アプリに合わせた変更を行いながら。ちょっと変更すべきところも正確には把握できておりません。)

以上、2点についてご教授いただけますでしょうか?

Masahiro Makita様

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

コンストラクタもJavaScriptファイル内に記述します.
1つのファイルが長くなるのを嫌うのであれば,ファイルを分けても問題ありません.
それぞれファイルを作成してkintoneに登録してください.

・RelatedRecordsFieldManager.js

// コンストラクタ定義varRelatedRecordsFieldManager=(function(fieldCode){functionRelatedRecordsFieldManager(fieldCode){this.fieldCode=fieldCode;this.targetAppId=kintone.app.getRelatedRecordsTargetAppId(fieldCode);this.property=this.fieldProperties[fieldCode].referenceTable;}RelatedRecordsFieldManager.prototype={selfAppId:kintone.app.getId(),records:[],limit:500,offset:0,getFieldProperties:function(){returnkintone.api(kintone.api.url('/k/v1/app/form/fields',true),'GET',{app:RelatedRecordsFieldManager.prototype.selfAppId,}).then(function(response){RelatedRecordsFieldManager.prototype.fieldProperties=response.properties;});},query:function(record){return(this.property.condition.relatedField+'="'+record[this.property.condition.field].value+(this.property.filterCond?'" and ':'"')+this.property.filterCond);},getRecords:function(record){var\_this=this;returnkintone.api(kintone.api.url('/k/v1/records',true),'GET',{app:this.targetAppId,query:this.query(record)+' order by '+this.property.sort+' limit '+this.limit+' offset '+this.offset}).then(function(response){\_this.records=\_this.records.concat(response.records);\_this.offset+=response.records.length;if(response.records.length===\_this.limit){return\_this.getRecords(record);}else{return\_this.records;}});}}returnRelatedRecordsFieldManager;})();

・sample.js

(function(){"use strict";kintone.events.on(['app.record.detail.show','app.record.edit.show'],function(event){// まず、アプリのフィールド設定を取得しておくRelatedRecordsFieldManager.prototype.getFieldProperties().then(function(){// 関連する案件一覧のレコードを取得する(newRelatedRecordsFieldManager('案件一覧')).getRecords(event.record).then(function(records){// space1に合計費用の合計値を表示kintone.app.record.getSpaceElement("space1").innerHTML=records.reduce(function(sum,record){returnsum+Number(record.合計費用.value);},0).toLocaleString();});// 関連する活動履歴のレコードを取得する(newRelatedRecordsFieldManager('活動履歴')).getRecords(event.record).then(function(records){// space2にレコード数を表示kintone.app.record.getSpaceElement("space2").innerHTML=records.length;});});});})();

使い方はサンプルの通りで,

RelatedRecordsFieldManager.prototype.getFieldProperties()

でアプリのフィールド設定を取得を取得した後,

(newRelatedRecordsFieldManager('関連レコードフィールドのフィールドコード')).getRecords(record)

で関連レコードを取得します.

非同期処理となるので,Promiseオブジェクトのthenメソッドを利用しています.
Promiseオブジェクトについては下記の記事などで解説されています.
https://developer.cybozu.io/hc/ja/articles/215029846
https://developer.cybozu.io/hc/ja/articles/204564604
また,Googleで「JavaScipt Promise」と検索すれば解説している記事が見つかると思います.

ご参考になりましたでしょうか?

江田様

丁寧に説明ありがとうございます。

まだ、稼働できておりませんが、やってみます。

また、わからなければ聞くかと思いますのでお願いいたします。

江田様

 

コンストラクトの変更点は

①return kintone.api(kintone.api.url(‘/k/v1/app/form/fields’, true), ‘GET’, { ←この部分

/k/v1/app/form/fields→/k/6/app/form/fields としました。(app/form/fieldsと、アプリ上にはないので会っているのかわかりません。)

(このスクリプトを使いたいアプリのアドレスが/k/6でした。

② return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, { ** ←この部分**

/k/v1/records→/k/6/records としました。

を変更して、

sampleのほうでは、

①(new RelatedRecordsFieldManager(‘案件一覧’)).getRecords(event.record).then(function(records){

案件一覧の部分

kintone.app.record.getSpaceElement(“space1”).innerHTML = (説明と同じようにspace1を作成しておく)
②return sum + Number(record.合計費用.value);

合計費用

 

③(new RelatedRecordsFieldManager(‘活動履歴’)).getRecords(event.record).then(function(records){

活動履歴の部分

kintone.app.record.getSpaceElement(“space2”).innerHTML = records.length; (space2も作成しておく)

の主に3か所かえれば合計と、レコード数がでるという考えではあっていますでしょうか?

とりあえず、それで変えてみても出なかったのですが、

何がよくないのでしょうか?

 

 

 

 

Masahiro Makita様

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

コンストラクタ(上記のRelatedRecordsFieldManager.js)を書き換える必要はありません.
「/k/v1/app/form/fields」などは,「kintone REST API」のパスなので,アプリ番号を含んでいるわけではなく,書き換えるとむしろ動作しなくなります.
https://developer.cybozu.io/hc/ja/articles/202166310#step1
https://developer.cybozu.io/hc/ja/articles/202331474
https://developer.cybozu.io/hc/ja/articles/204783170

案件に合わせて書き換える必要があるのは,sample.jsです.
合計値とレコード数を出すという実装は変わらず,フィールドコードのみデモと異なるという場合であれば,その変更の仕方で正しいと思います.
もし,それでも動かない場合,コードをそのまま掲載していただければ何かコメントできるかもしれません.

江田様ご連絡ありがとうございました。

コンストラクタはもとに戻して、下記sample.jsと同じファイル上にのっけて、

UPしましたが動きませんでした。変更点は上記に記載している部分で、

関連レコードのIDも同じように設定しています。

(キントーンのサンプルサイトもみたのですが、設定ができなくて、細かい部分がわかりませんでした。)

もしわかりましたらご教授いただけますでしょうか?

(function() {
“use strict”;
kintone.events.on([
‘app.record.detail.show’,
‘app.record.edit.show’
], function(event){
// まず、アプリのフィールド設定を取得しておく
RelatedRecordsFieldManager.prototype.getFieldProperties().then(function(){
// 関連する案件一覧のレコードを取得する
(new RelatedRecordsFieldManager(‘助成金一覧’)).getRecords(event.record).then(function(records){
// space1に合計費用の合計値を表示
kintone.app.record.getSpaceElement(“space1”).innerHTML =
records.reduce(function(sum, record){
return sum + Number(record.項目No.value);
}, 0).toLocaleString();
});
// 関連する活動履歴のレコードを取得する
(new RelatedRecordsFieldManager(‘助成金一覧’)).getRecords(event.record).then(function(records){
// space2にレコード数を表示
kintone.app.record.getSpaceElement(“space2”).innerHTML = records.length;
});
});
});
// コンストラクタ定義
var RelatedRecordsFieldManager = (function(fieldCode){
//上記参照
})();
})();

Masahiro Makita様

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

見た限りでは問題なさそうですね・・・

下記などを参考にデバッグをしていただいてもよろしいですか?
https://developer.cybozu.io/hc/ja/articles/207613916

sample.jsを下記に書き換えて,コンソール画面にどうに表示されたか教えていただけますか?
可能であればスクリーンショットなどがあるとわかりやすいです.

(function () {
  "use strict";
  console.log('aaa');
  kintone.events.on(['app.record.detail.show', 'app.record.edit.show'], function (event) {
    console.log(event);
    // まず、アプリのフィールド設定を取得しておく
    RelatedRecordsFieldManager.prototype.getFieldProperties().then(function () {
      console.log(RelatedRecordsFieldManager.prototype.fieldProperties);
      // 関連する助成金一覧のレコードを取得する
      (new RelatedRecordsFieldManager('助成金一覧')).getRecords(event.record).then(function (records) {
        console.log(records);
        // space1に項目Noの合計値を表示
        kintone.app.record.getSpaceElement("space1").innerHTML = records.reduce(function (sum, record) {
          return sum + Number(record.項目No.value);
        }, 0).toLocaleString();
        // space2にレコード数を表示
        kintone.app.record.getSpaceElement("space2").innerHTML = records.length;
      });
    });
  });
  // コンストラクタ定義
  var RelatedRecordsFieldManager = (function (fieldCode) {
    //上記参照
  })();
})();

江田様

度々ありがとうございます。

でバックしてみました。

以下のようになりました。申し訳ありません。ご確認お願いいたします。

拡張できる部分があったので、ひろげたものをもう一つ添付いたします。

Masahiro Makita様

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

RelatedRecordsFieldManagerが定義できていないようですね。 下記コードをそのまま使ってみて下さい。

(function(){"use strict";kintone.events.on(['app.record.detail.show','app.record.edit.show'],function(event){// まず、アプリのフィールド設定を取得しておくRelatedRecordsFieldManager.prototype.getFieldProperties().then(function(){// 関連する助成金一覧のレコードを取得する(newRelatedRecordsFieldManager('助成金一覧')).getRecords(event.record).then(function(records){// space1に項目Noの合計値を表示kintone.app.record.getSpaceElement("space1").innerHTML=records.reduce(function(sum,record){returnsum+Number(record.項目No.value);},0).toLocaleString();// space2にレコード数を表示kintone.app.record.getSpaceElement("space2").innerHTML=records.length;});});});// コンストラクタ定義varRelatedRecordsFieldManager=(function(fieldCode){functionRelatedRecordsFieldManager(fieldCode){this.fieldCode=fieldCode;this.targetAppId=kintone.app.getRelatedRecordsTargetAppId(fieldCode);this.property=this.fieldProperties[fieldCode].referenceTable;}RelatedRecordsFieldManager.prototype={selfAppId:kintone.app.getId(),records:[],limit:500,offset:0,getFieldProperties:function(){returnkintone.api(kintone.api.url('/k/v1/app/form/fields',true),'GET',{app:RelatedRecordsFieldManager.prototype.selfAppId,}).then(function(response){RelatedRecordsFieldManager.prototype.fieldProperties=response.properties;});},query:function(record){return(this.property.condition.relatedField+'="'+record[this.property.condition.field].value+(this.property.filterCond?'" and ':'"')+this.property.filterCond);},getRecords:function(record){var\_this=this;returnkintone.api(kintone.api.url('/k/v1/records',true),'GET',{app:this.targetAppId,query:this.query(record)+' order by '+this.property.sort+' limit '+this.limit+' offset '+this.offset}).then(function(response){\_this.records=\_this.records.concat(response.records);\_this.offset+=response.records.length;if(response.records.length===\_this.limit){return\_this.getRecords(record);}else{return\_this.records;}});}}returnRelatedRecordsFieldManager;})();})();

江田様

 

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

完成しました。

ありがとうございます。

素晴らしいです。何度もありがとうございます。

何がよくなかったのでしょうか?

江田様

 

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

サンプルアプリで試したいのですが、下記の手順でよろしいのでしょうか?

1、コントララスタ+コードを1つのjsふぁいるにしてアップする。

2、顧客管理(営業支援パック)へアップし、フォームで「space1」と「space2」を作成する。

 

実際に試しましたが表示されてきません。

お手数ですがご教示いただければと思います。

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

江田様

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

度々申し訳ございません。

①合計値を二つ作ったらうごきませんでした。JSを二つにしたらうごいたのですが、

添付のようにまとめることはできないのでしょうか?

②関連レコードの合計金額や、合計レコード数はグラフや、一覧表で使用することはできないでしょうか?

お忙しいところ恐縮ですが、ご教授いただけますでしょうか?