新規投稿
フォローする

【簡単】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(){
      // 関連する案件一覧のレコードを取得する
      (new RelatedRecordsFieldManager('案件一覧')).getRecords(event.record).then(function(records){
        // space1に合計費用の合計値を表示
        kintone.app.record.getSpaceElement("space1").innerHTML =
          records.reduce(function(sum, record){
            return sum + Number(record.合計費用.value);
          }, 0).toLocaleString();
      });
      // 関連する活動履歴のレコードを取得する
      (new RelatedRecordsFieldManager('活動履歴')).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」)

10

58件のコメント

Avatar
青山昌司

江田篤史

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

先日ご教授いただいた方法を活用させていただいているのですが、関連レコードにデータがない場合エラーになり保存ができません。

if(latestRecord.対応日時.value!==undefined){

event.record.日付.value = latestRecord.対応日時.value

event.record.文字.value = latestRecord.対応内容.value

}

としてみましたがうまく動きません。

関連レコード内に参照するレコードがない場合の処理を

ご教授いただけませんでしょうか。

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

0
Avatar
江田篤史

青山昌司様

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

下記で対応可能かと思います。

var latestRecord =
  records.length && records.reduce(function (latestRecord, record) {
    if(!latestRecord.レコード番号) return record
    return latestRecord.対応日時.value > record.対応日時.value ? latestRecord : record;
  }, {});
if(latestRecord){
  event.record.日付.value = latestRecord.対応日時.value;
  event.record.文字.value = latestRecord.対応内容.value;
}
0
Avatar
青山昌司

江田篤史様

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

ご教授いただいた方法で問題解決できました。

いつもご丁寧な回答ありがとうございます。

今後ともよろしくお願いいたします。

 

 

 

0
Avatar
Yuichi Hanazono

江田様

お世話になります。

私も数値フィールドに集計を行う形式で実装できました。ありがとうございます。

これ、指定条件に該当するレコードだけを集計することはできますでしょうか?

例えば、案件に案件種別というドロップダウンがあって、案件種別の値が”新規”の合計費用だけを計算したいです。

コンストラクタのqueryを書き換えるのかとおもうのですが、書き方がわからず、ご共住いただけましたら幸いです。

0
Avatar
望月秀吉

江田様

 

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

 

関連レコードの号家を数値フィールドに入れてその数値を元に計算されるものを作りたいと思っております。

具体的には別アプリに売上データがあって、会社名をとってくると、軽減税率の売上と標準税率の売上に分けてそれぞれ関連レコードで引っ張ってくる。

手数料の計算をしたいので、それぞれの関連レコードで販売数と販売金額の合計を出してそれぞれ数値フィールドに転記されるようなものが作りたいです。

現在は、関連レコードの合計が関連レコードの項目名のところに出てくるTISさんの無料プラグインを使用して、出てきた合計を数値フィールドに手打ちで転記しております。

この部分を自動化できればと思っております。

アドバイスいただけると助かります。

 

宜しくお願い致します。

 

0
Avatar
江田篤史

Yuichi Hanazono様

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

見逃しておりました. 申し訳ございません.

解決済みかもしれませんが…
コンストラクタは書き換えずに,取得したrecordsに対してfilterをかけるのが良いかと思います.
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

(new RelatedRecordsFieldManager('案件一覧')).getRecords(event.record).then(function(records){
  event.record.金額.value = records.filter(function(record){
    return record.案件種別.value === '新規';
  }).reduce(function(sum, record){
    return sum + Number(record.合計費用.value);
  }, 0);
  resolve(event);
});
0
Avatar
江田篤史

望月秀吉様

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

下記が参考になるかと思います.
https://developer.cybozu.io/hc/ja/community/posts/360017851006/comments/360004419532

複数の関連レコードの値を用いるのであれば,Promise.all()を用いると良いと思います.
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

...
      RelatedRecordsFieldManager.prototype.getFieldProperties().then(function(){
        kintone.Promise.all([
          (new RelatedRecordsFieldManager('軽減税率')).getRecords(event.record),
          (new RelatedRecordsFieldManager('標準税率')).getRecords(event.record)
        ]).then(function(responses){
          var reducedTaxRecords = responses[0];
          var standardTaxRecords = responses[1];
          event.record.軽減税率販売数合計.value = reducedTaxRecords.reduce(function(sum, record){
            return sum + Number(record.軽減税率販売数.value);
          }, 0);
          ...
          resolve(event);
        });
      });
...
0
Avatar
watanabe

江田様

お世話になります。初心者なのですが、こちらのコードを拝見させていただき、数値フィールドに反映することができました。

できればレコード保存後ではなく、レコード追加画面、編集画面で指定フィールド(フィールドコード(ルックアップコピー先):注文番号)の値が変更された時に、数値フィールド(フィールドコード:売上数量)に値を出したいのですが、可能なことなのでしょうか?

また、関連レコードは、別アプリからではなく、同一アプリ内のデータを関連づけています。(注文を複数回に分けて納品するので、過去の売上数量を確認するためです)お教えいただければ幸いです。よろしくお願いいたします。

(function() {
"use strict";
kintone.events.on([
'app.record.create.change.注文番号',
'app.record.edit.change.注文番号'
], function(event){
return new kintone.Promise(function(resolve){
RelatedRecordsFieldManager.prototype.getFieldProperties().then(function(){
(new RelatedRecordsFieldManager('案件一覧')).getRecords(event.record).then(function(records){
event.record.案件一覧売上数量.value = records.reduce(function(sum, record){
return sum + Number(record.売上数量.value);
}, 0);
resolve(event);
});
});
});
});
}());

0
Avatar
江田篤史

watanabe様

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

changeイベントでの書き換えも可能です.

ただし,changeイベントではkintone.Promiseオブジェクトをreturnすることはできません.
https://developer.cybozu.io/hc/ja/articles/201941984#step3
代わりに,kintone.app.record.set()を利用すると良いと思います.
https://developer.cybozu.io/hc/ja/articles/201942014#step4

また,RelatedRecordsFieldManager.prototype.getFieldProperties()は一度だけ呼べば良いです.
'app.record.create.show'や'app.record.edit.show'内で呼んだ方が,パフォーマンス上良いかと思います.

0
Avatar
ayoko

江田篤史様

 

初めまして。

こちらの記事のコードを利用して、関連レコード取得集計が出来ました。

ありがとうざいました。

集計方法として、「受注予定日」や「対応日時」の日付を期間指定して集計することは可能でしょうか。

例:2020/1/1~2020/6/30

運用としましては、顧客アプリ関連レコード(該当顧客の受注金額)を年度や四半期で区切り、集計表示したいと考えております。

初歩的な質問で大変恐縮ですが、ご教授頂けますと幸いです。

何卒よろしくお願い申し上げます。

0
Avatar
江田篤史

ayoko様

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

filter()メソッドを用いると良いと思います.
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

(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.filter(function(record){
            var date = record.受注予定日.value;
            return (date >= '2020-01-01' && date <= '2020-06-30');
          }).reduce(function(sum, record){
            return sum + Number(record.合計費用.value);
          }, 0).toLocaleString();
      });
    });
  });
})();
1
Avatar
ayoko

江田篤史様

早々にご返答いただき、ありがとうございます。

サンプルコード利用で集計表示が出来ました。

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

少しずつ勉強していきたいと思います。

今後も、お伺いする事があるかと思いますがその際はご教授頂けますと幸いです。

 

 

1
Avatar
mm

お世話になります。

関連レコード内の数値の合計をspace1に表示させたいのですが(画像の①の部分を御覧ください)、

何も変わりません。console画面を見てもエラーは出ていないのですが、修正する箇所を教えて頂けますでしょうか。

 

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

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

mm

0
Avatar
江田篤史

mm様

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

問題点は見当たりませんね…

まずは古いコードがキャッシュされていないか,確認するとよいかと思います.
https://helpx.adobe.com/jp/legacy/kb/222659.html

それでも動作しなければ,下記などを参考に,コードのどの箇所まで動作しているか確認するとよいかと思います.
https://ics.media/entry/190517/

0
Avatar
mm

江田様

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

再度Consoleを確認したところ、RelatedRecordsFieldManager.jsの以下の箇所にエラーが表示されていました。

this.property = this.fieldProperties[fieldCode].referenceTable;

コンストラクターは、何か編集をしないといけないのでしょうか。

また、編集したsample.jsにもエラーが出ていました。

修正箇所を教えて頂けますでしょうか。

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

mm

0
Avatar
江田篤史

mm様

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

恐らく,フィールドコードの指定が正しくないのかと思います.

アプリの設定から,フィールド名「直近の申請(50件まで)」のフィールドコードが何になっているか,今一度ご確認いただけますか?

0
Avatar
mm

江田様

お世話になります。

ご丁寧にありがとうございました。ここはフィールドコードを入れなくてはならなかったのですね。

入れたところ、無事表示されました。ありがとうございます。

space1に表示された数値を図のように計算に利用したいのですが、どうすれば取り出せるでしょうか。

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

mm

0
Avatar
江田篤史

mm様

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

こちらのコメントが参考になるかと思います.

https://developer.cybozu.io/hc/ja/community/posts/360017851006/comments/360002846572

0
Avatar
mm

江田様

お世話になります。

コメントを参考に作成しましたが、コードの14,15行目にエラーが発生して動きません。どこを修正すればよいか教えていただけますでしょうか。

jQuery.noConflict();
(function($) {
"use strict";
kintone.events.on([
'app.record.craete.show',
'app.record.edit.show'
], function(event){

// まず、アプリのフィールド設定を取得しておく
RelatedRecordsFieldManager.prototype.getFieldProperties().then(function(){
// 関連する案件一覧のレコードを取得する
(new RelatedRecordsFieldManager('関連レコード一覧')).getRecords(event.record).then(function(records){
// 数値に数量の合計値を表示
event.record.数値.value = records.reduce(function(sum, record){
return sum + Number(record.数量.value);
}, 0).toLocaleString();
});
});
});
})(jQuery);

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

mm

0
Avatar
江田篤史

mm様

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

今回も,フィールドコードの指定が正しくないのかと思います.
アプリの設定から,フィールド名「数量」のフィールドコードが何になっているか,今一度ご確認いただけますか?

また,こちらのコメントで書きましたが,「submit」イベントでeventオブジェクトを書き換えてreturnしてください.
ご提示頂いたコードですと,「show」イベントになっているかと思います.
https://developer.cybozu.io/hc/ja/articles/201941954
eventオブジェクトのreturnも記述されていないかと思います.

参考コメントのフィールドコード部分を書き換えるのが手っ取り早いと思います.
関連レコード一覧4 -> 関連レコード一覧
sale4 -> 数値
sale -> フィールド名「数量」のフィールドコード

0
Avatar
mm

江田さま

お世話になります。

sale -> フィールド名「数量」のフィールドコード これは私のアプリでは該当するものがないです。

関連レコード一覧の中の「数量」の数値を「数値」フィールドに表示させたいのですがコードをどのように修正すればよいでしょうか。

 

0
Avatar
江田篤史

mm様

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

・コードをどのように修正すればよいでしょうか。
>ご自身のアプリのフォーム設定をご確認頂き,正しいフィールドコードをソースコードに記述してください.

「関連レコード一覧」で「参照するアプリ」に指定しているアプリについて,フォーム設定をご確認ください.
フィールド名が「数量」のフィールドの,フィールドコードはどのようになっていますか?

コンソール画面によると,「record.数量」がundefinedとなったということなので,フィールドコードが間違っている可能性を疑っております.
スペースフィールドへの表示はうまくいったとのことですので,間違っている可能性は低いとは思いますが,今一度ご確認いただけますか?

1
Avatar
mm

江田様

お世話になっております。ご丁寧にありがとうございました。

数量は参照するアプリのフィールドコードを書くのですね。

失礼いたしました。記入したところ、動くようになりました。

また、関連レコードをあと4つ表示させて、同様に数値を取得したいのですが、以下のコードは同じJSファイルに追加できますでしょうか。

その場合、どこに追加すればよいか教えていただけますでしょうか。

それとも、一つずつ別のJSファイルに分けたほうが良いですか?

(new RelatedRecordsFieldManager('関連レコード一覧_2')).getRecords(event.record).then(function(records){
event.record.数値.value = records.reduce(function(sum, record){
return sum + Number(record.p2_amt.value);

(new RelatedRecordsFieldManager('関連レコード一覧_3')).getRecords(event.record).then(function(records){
event.record.数値.value = records.reduce(function(sum, record){
return sum + Number(record.p3_amt.value);

(new RelatedRecordsFieldManager('関連レコード一覧_4')).getRecords(event.record).then(function(records){
event.record.数値.value = records.reduce(function(sum, record){
return sum + Number(record.p4_amt.value);

(new RelatedRecordsFieldManager('関連レコード一覧_5')).getRecords(event.record).then(function(records){
event.record.数値.value = records.reduce(function(sum, record){
return sum + Number(record.p5_amt.value);

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

mm

0
Avatar
江田篤史

mm様

フィールドコードのミスはよくあるケースかと思います。
JSカスタマイズのチュートリアルは、すでにご覧になられていますか?
https://developer.cybozu.io/hc/ja/articles/115002336526
kintoneカスタマイズにおける注意点を理解できるので、「はじめようJavascript」と「はじめようkintone API」は一通り目を通しておくことをお勧めいたします。

・関連レコードをあと4つ表示させて、同様に数値を取得したいのですが、以下のコードは同じJSファイルに追加できますでしょうか。
> 同じJSファイルに記述するのが良いです。
下記コメントが参考になるかと思います。
https://developer.cybozu.io/hc/ja/community/posts/360017851006/comments/900000480046

0
Avatar
mm

江田様

お世話になります。

チュートリアルは読んでみたのですが、これまでコードを触ったことがないため、とても難しく、理解が出来ないです。

頂いたコメントを参考にコードを修正したところ、エラーが8、33、37行目に表示されているのですが、どこを修正すればよいかわからないです。

このエラーのときは、どこを確認してどのように修正すればよいのでしょうか?

kintone.events.on([
'app.record.create.submit',
'app.record.edit.submit'
], function(event){
return new kintone.Promise(function(resolve){
   // まず、アプリのフィールド設定を取得しておく

   RelatedRecordsFieldManager.prototype.getFieldProperties().then(function(){
   kintone.Promise.all([
    // 関連する案件一覧のレコードを取得する
    (new RelatedRecordsFieldManager('関連レコード一覧')).getRecords(event.record),
    (new RelatedRecordsFieldManager('関連レコード一覧_2')).getRecords(event.record),
    (new RelatedRecordsFieldManager('関連レコード一覧_3')).getRecords(event.record),
    (new RelatedRecordsFieldManager('関連レコード一覧_4')).getRecords(event.record),
    (new RelatedRecordsFieldManager('関連レコード一覧_5')).getRecords(event.record)

    ]).then(function(records){


    // 申請書アプリから数量を取得して数値に表示
    kintone.Promise.all([
    event.record.数値.value = records.reduce(function(sum, record){
    return sum + Number(record.p1_amt.value),
    event.record.数値_2.value = records.reduce(function(sum, record){
    return sum + Number(record.p2_amt.value),
    event.record.数値_3.value = records.reduce(function(sum, record){
    return sum + Number(record.p3_amt.value),
    event.record.数値_4.value = records.reduce(function(sum, record){
    return sum + Number(record.p4_amt.value),
    event.record.数値_5.value = records.reduce(function(sum, record){
    return sum + Number(record.p5_amt.value);
    }, 0);
    ]).resolve(event);
});
});
});
}));
}());

また、レコードを一度開いて保存しないと正しい値が表示されないので、

一覧画面に一括更新ボタンを作りました。

(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.innerText = '在庫を一括更新する';

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

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

ボタンクリック時の処理のコードを教えていただけますでしょうか。

以下を参考にしましたが、私がやりたいことは値を上書きすることではなく、ただ開いて保存なので、その場合のやり方をチュートリアルでも見つけることが出来ませんでした。

https://developer.cybozu.io/hc/ja/community/posts/360017977863
https://developer.cybozu.io/hc/ja/articles/202331474#step2
https://developer.cybozu.io/hc/ja/articles/201941784#step2

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

mm

mmにより編集されました
0
Avatar
TT

江田様

お世話になります。

コメントを見させていただいたのですが、数値に合計値を表示させることが出来ず、見よう見まねで作ってみたのですが、アドバイスをいただけないでしょうか?

関連レコード一覧から数値に合計値を表示させ、その合計値をさらに計算に使いたいです。

 

(function() {
"use strict";
kintone.events.on([
'app.record.create.submit',
'app.record.edit.submit'
], function(event){
return new kintone.Promise(function(resolve){
RelatedRecordsFieldManager.prototype.getFieldProperties().then(function(){
(new RelatedRecordsFieldManager('案件一覧')).getRecords(event.record).then(function(records){
event.record.合計費用合計値.value = records.reduce(function(sum, record){
return sum + Number(record.合計費用.value);
}, 0);
resolve(event);
});
});
});
});
}());

0
Avatar
上田

江田 様

いつもお世話になっております。プログラミング完全初心者です。

本ソースを使って数値ではなく「文字列」の数を集計することは可能でしょうか。

関連レコード集計の「ステータス」項目に開始・処理中・完了などあり、「完了」になっている数を集計したいです。

 

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

 

0
Avatar
江田篤史

上田さん

こちらのコメントにあるように,filterを用いると良いです.

記事でいう,「関連する活動履歴」を「対応内容が商談」という条件で絞り込んで件数を取得には,下記のようになります.

// 関連する活動履歴のレコードを取得する
(new RelatedRecordsFieldManager('活動履歴')).getRecords(event.record).then(function(records){
  // space2にレコード数を表示
  kintone.app.record.getSpaceElement("space2").innerHTML = records.filter(function(record){
    return record.対応内容.value === '商談';
  }).length;
});
0
サインインしてコメントを残してください。