計算ボタンを作ってデータを追加する際の処理について

一覧画面に計算ボタンを作成して、ボタンをクリックすると、条件に合った計算をしてそのデータを同じアプリ内に登録する処理を実現させたいと思っています。

納品日 仕入先コード 納品先コード 納品金額 ・・・・・

上記のようなフィールドがあり、仕入れ先コードや納品先コードは複数あります。実現したいのは、納品日が当月の仕入先コードと納品先コードが同じものの納品金額を合計して、その合計の○○%の値を納品金額のフィールドに登録したいのです。

こういったことは実現可能でしょうか?

 

garden さん

対象レコードを取得して、集計・納品金額の登録は、JavaScript カスタマイズで可能です。
ただし、どちらかというと、業務分析と業務フローの検討が重要です。

当月といっても、対象データが月内にすべて揃っているのかどうか?
揃っていない場合は、月の締め日を決めて、運用することになると思います。
また、締め処理以降に入力漏れが判明した場合の運用はどうするのか?
仕入れ・納品の返品・キャンセルの扱いや単純な入力ミス対応など

現在、マニュアルで集計されているのであれば他にも、細かい要件がいろいろ出てくると思います。

それらに対する業務フローと、システム対応の範囲などの検討が必要だと思います。

納品金額がどう使われるのかにもよりますが、納品金額の集計・登録時のシステムトラブル時の影響と

リカバリー方法なども検討しておいたほうが良いと思います。

 

ご回答ありがとうございます。rex0220様のおっしゃる通り、業務フローをしっかり決める必要があると思います。

そこまで考えていただいてご回答いただきありがとうございます。そのあたりの事はしっかり決めるとして、今回

のようなことを実現するにあたって、どのようなJavaScriptを記述したらいいでしょうか。

一番わからないのが、複数の仕入先コードと納品先コードがある中で、仕入れ先コードと納品先コードが同じもの

の納品金額の合計を出す部分です。もしよろしければ、簡単でいいのでどのようにしたらいいかを教えていただければ

幸いです。

kintone の集計方法については、「kintone カスタマイズ関連リンク集 集計処理」にまとめています。

この中で、キーが複数で集計しやすいのは、下記の二つだと思います。
仕入先コードと納品先コードをキーに納品金額を集計するのは、それぞれ下記のようなコードになります。

kintone レコード集計の関数化

var summary = recordsSummary(records,['仕入先コード','納品先コード'],['納品金額']);

kintone でSQLを使う

var rs1 = convertToRows(records);
var result1 = alasql(
"SELECT a.[仕入先コード], a.[納品先コード], SUM(a.[納品金額]) as [納品金額] \
FROM ? AS a \
GROUP BY a.[仕入先コード], a.[納品先コード]", [rs1]);

どちらも、関数の部分はリンク先のものがそのまま使えますので、詳細はリンク先を見てください。
alasql のほうは、一般的なSQLと同じように書けますので、汎用的です。

 

回答していただき本当にありがとうございます。頂いた情報をもとに、とりあえず納品金額の合計を表示してみようかなと

試してみたのですが、うまくいきませんでした。まったくの初心者で手さぐりでやっているもので、まったく見当違いなことを

しているのかもしれません。以下のように書いてみたのですが、どこをどうしたらいいのか、できれば教えて頂ければ

幸いです。

(function() {

 “use strict”;
 kintone.events.on(‘app.record.index.show’, function(event) {

 // メニュ右側の空白部分にボタンを設置
var MenuButton = document.createElement(‘button’);
 MenuButton.id = ‘Menu_Button’;
 MenuButton.innerHTML = ‘ボタン’;

MenuButton.onclick = function () {

var query= kintone.app.getQuery();

kintone.api(
 kintone.api.url(‘/k/v1/records’, true),
 ‘GET’, {
 app: 42,
 query: query
 },
 function(resp) {

var summary1 = recordsSummary(resp.records,[‘仕入先コード’,‘納品先’],[‘納品金額’]);
 window.alert(summary1);

   function recordsSummary(records, keys, sumKeys) {
        var sumKeys2 = sumKeys.concat([‘$count’]);

        var hash = records.reduce(function(res,record) {
            // 集計キーを作成
            var key = keys.reduce(function(s,k) {
                if(s) s += ‘\t’;
                s += record[k][‘value’];
                return s;
            },‘’);
            // 初めての集計キー
            if(!(key in res)) {
                // 集計キーをオブジェクトに設定
                var keyList = keys.reduce(function(h,k) {
                    h[k] = record[k][‘value’];
                    return h;
                },{});
                // 集計項目の初期値を設定
                res[key] = sumKeys2.reduce(function(h,k) {
                    h[k] = 0;
                    return h;
                }, keyList);
            }
            // データを集計(加算)
            sumKeys.forEach(function(k){
                if(record[k][‘value’])
                    res[key][k] += Number(record[k][‘value’]);
            });
            res[key][‘$count’]++;

            return res;
        },{});

        // キーソート
        var hashKeys = Object.keys(hash);
        hashKeys.sort();

        // 配列化
        var summary = [];
        for(var i in hashKeys){
            var k = hashKeys[i];
            if(hash.hasOwnProperty(k)){
                summary.push(hash[k]);
            }
        }

        return summary;
    }

});

}

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

 });
})();

 

 

 

appId を自アプリ、 alert をconsole.table に変更して、試したところ問題なく集計されました。

たぶん、フィールドコードが合っていないとか、単純なミスがあるような気がします。

 

kintone.api(
kintone.api.url('/k/v1/records', true),
'GET', {
app: event.appId,
query: query
},
function(resp) {

var summary1 = recordsSummary(resp.records, ['仕入先コード', '納品先'], ['納品金額']);
console.table(summary1);

 

テスト結果

rex0220様

ご返信が遅くなってしまい、申し訳ございません。私もconsole.table に変更して、rex様のように集計されました。

ありがとうございます。そこでまた質問になってしまうのですが、各仕入先コード、納品先別の納品金額に0.8をかけた

金額を、納品金額のとろこに新しいデータとして登録をしたいのですが、どのようコードを書いたらいいのかを

できたら教えて頂きたいです。

アプリの構成が分かりませんので、分かる部分だけで、record を組み立てると下記のようになります。

あとは、レコードの一括登録 の手順で登録は出来ます。

他に、いろいろ細かな要件があると思いますので、これをベースに検討してください。

 

var summary1 = recordsSummary(resp.records, ['仕入先コード', '納品先'], ['納品金額']);
console.table(summary1);
var records = summary1.map(function(data) {
return {
'仕入先コード': { value: data['仕入先コード'] },
'納品先': { value: data['納品先'] },
'納品金額': { value: parseInt(data['納品金額'] * 0.8) }
}
});
console.log('records:', records);

rex0220様

いつも本当にありがとうございます。頂いたコードをもとに試してみました。

レコードの一括登録のところでエラーになってしまうのですが、どのあたりが問題でしょうか。

いつも質問ばかりで申し訳ありません。お手すきの時にでも教えて頂けますでしょうか。

 

(function() {

 “use strict”;
 
 moment.locale(‘ja’);

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

var MenuButton = document.createElement(‘button’);
 MenuButton.id = ‘Menu_Button’;
 MenuButton.innerHTML = ‘ボタン’;
 kintone.app.getHeaderMenuSpaceElement().appendChild(MenuButton);
MenuButton.onclick = function () {

var query= kintone.app.getQuery();
var appId = kintone.app.getId();

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

var summary1 = recordsSummary(resp.records,[‘仕入先コード’,‘納品先’],[‘納品金額’]);
 console.table(summary1);
  
var d1 = moment();
var records = summary1.map(function(data) {
 return {   
 ‘仕入先コード’: { value: data[‘仕入先コード’] },
 ‘納品日’: { value: moment(d1).endOf(‘month’).format(‘YYYY-MM-DD’)  },
 ‘発注番号’: { value: data[‘仕入先コード’] + moment(d1).endOf(‘month’).format(‘MMDD’) },
 ‘納品数’: { value: ‘-1’ },
 ‘単価’: { value: parseInt(data[‘納品金額’] * 0.08) },
 ‘納品金額’: { value: ‘-’ + parseInt(data[‘納品金額’] * 0.08) },

   };

});
     console.log(‘records:’, records);
kintone.api(kintone.api.url(“/k/v1/records”, true), ‘POST’, {“app” : 42, “record” : records }, function(res){
 // 成功時の処理
console.log(“success”);
 } ,function(err){
 // 失敗時の処理
console.log(“error”);
}
        );
      });

   function recordsSummary(records, keys, sumKeys) {
        var sumKeys2 = sumKeys.concat([‘$count’]);

        var hash = records.reduce(function(res,record) {
            // 集計キーを作成
            var key = keys.reduce(function(s,k) {
                if(s) s += ‘\t’;
                s += record[k][‘value’];
                return s;
            },‘’);
            // 初めての集計キー
            if(!(key in res)) {
                // 集計キーをオブジェクトに設定
                var keyList = keys.reduce(function(h,k) {
                    h[k] = record[k][‘value’];
                    return h;
                },{});
                // 集計項目の初期値を設定
                res[key] = sumKeys2.reduce(function(h,k) {
                    h[k] = 0;
                    return h;
                }, keyList);
            }
            // データを集計(加算)
            sumKeys.forEach(function(k){
                if(record[k][‘value’])
                    res[key][k] += Number(record[k][‘value’]);
            });
            res[key][‘$count’]++;

            return res;
        },{});

        // キーソート
        var hashKeys = Object.keys(hash);
        hashKeys.sort();

        // 配列化
        var summary = [];
        for(var i in hashKeys){
            var k = hashKeys[i];
            if(hash.hasOwnProperty(k)){
                summary.push(hash[k]);
            }
        }

        return summary;
   }
};

 });
})();

 

どのようなエラーが出ていますか?

ざっと見たところ、“record” が誤っていると思います。

⇒ “records” 

{“app” : 42, “record” : records }

ご返信ありがとうございます。"records"に直してみましたが、登録されませんでした。

コンソールのログを見ると、データの内容は正常に表示されているのですが、

一括登録の処理のところで、”error”と表示されデータの登録ができない状態です。

私のソースのどこかがおかしいのだとは思うのですが、ほかに何か原因は考えられますでしょうか?

console.log(“error”, err); にして、エラー内容を確認しましょう。

ありがとうございます。すでに登録してあるデータで、おかしいものがあったので削除して試したところ

正常に登録できました。一人ではどうしていいか困っていたので、教えて頂き本当にありがとうございます。

あと最後に一つだけ教えて頂きたいことがあります。できればこの処理を実行する際に条件をつけたいです。

仕入先コードが複数ある中で、例えば「A01」と「A02」が含まれるデータだけに、今回の処理を適用して

データの登録を行いたいと思うのですが、その条件はどのように記載したらよろしいでしょうか?

レコードの一括取得(クエリで条件を指定) を参考にしてください。 in が使えると思います。

あと、作成されたコードだと、100 件のレコードしか処理しないなど問題がありますので、本番用開発はその辺も考慮してください。

kintone Utility for JavaScript を使ってみたよ を使うと容易だと思います。

本当にいろいろとありがとうございます。kintone Utility for JavaScript を使ってみたよ こちらを参考にして、データの登録ができました。

ただ、クエリの指定がうまくいきません。kintone.app.getQuery();に、プラスして仕入先コードの条件を入れたいのですが、そのような

ことはできますでしょうか?

kintone.app.getQueryCondition() こちらを使ってみてください。

limit, offset の指定がありません。 

いつもありがとうございます。

var query= kintone.app.getQueryCondition()  + “and” +   ‘仕入先コード in (“752”,“140”)’;

のような形で記載してみたのですが、うまくいきませんでした。おそらく記載方法がちがうのだと

思うのですが、よろしければ教えて頂けますでしょうか。

連結時にスペースが必要です。

結果を、console.log(query); で、検証しましょう。