search
LoginSignup
4

More than 5 years have passed since last update.

posted at

linq.jsでkintoneに総平均法単価計算を組み込む

kintone Advent Calendar 2016 の 12日目です。
Qiita初投稿です。
今日は,linq.js を使って、kintoneに総平均法の単価計算を組み込みたいと思います。

linq.js とは

linq.jsはこちらからダウンロード

linq.js

linq.js が何かは、ここに書いてありました。

JavaScriptで配列をLINQにより処理できるライブラリ「linq.js」を利用するには? - @IT

マイクロソフトのLINQを、有志(多分)が、javascriptに移植した物の様です。
尚、私がこの存在を知ったのは、

グループ化による件数の集計について cybozu developer network

このスレッドにあった、rex0220 さんのコメントです。
今回書いたコードも、この rex0200さんの書いたコードが肝です。
(この場を借りてお礼を(笑))

総平均法による単価計算とは

業務システムで在庫を扱っている方々にはおなじみの計算です。
業務システムエンジニアは、総平均法をシステムに組み込んで初めて、一人前(か?)。

1.先月末時点で10個で1,000円のリンゴがあった(単価100円)
2.今月20個のリンゴを3,000円(単価150円),10個のリンゴを2,000円(単価200円)で買った。
3.じゃあ今手元にあるリンゴ1個あたり、一体いくらなの?

という問題を解決するための計算法ですね。

(先月末在庫金額+当月入庫金額)÷(前月末在庫数量+当月入庫数量)

で、リンゴ1個あたりの単価が計算可能です。
上記例の場合は、リンゴ1個あたり150円ですね。

kintoneのAPIは集計弱いです(いつか強くなるはず)

現状は、弱いというか、ないです。
レコード100件の合計を出そうとすると、レコードを100件取得して、それを合計するしかありません。その労力を、linq.jsで解消します。

早速組み込んでいきます。無駄に長いです。

注意:私、JavaScriptは必要な技術を必要な時に、基礎を無視してかじっていますので、以下のコードも色々とお見苦しいところがあると思います。先にお詫びしておきます。あと良いプログラマは変数名や関数名にローマ字とか使わない方がいいかもしれません。

APP作成

APP名 フィールドコード 表示名 タイプ
在庫 skubangou 品番 SINGLE_LINE_TEXT
zengetsumatsuzan 前月末残在庫数 NUMBER
zengetuzaikokingaku 前月末残在庫金額 NUMBER
商品 skubangou 品番 SINGLE_LINE_TEXT
zengetuzan 前月残数量 NUMBER
zengetuzankingaku 前月残金額 NUMBER
nyuukosuu 当月入庫数量 NUMBER
nyuukokingaku 当月入庫金額 NUMBER
heikintanka 総平均単価 NUMBER
recordno レコード番号
入庫 skubangou 品番 SINGLE_LINE_TEXT
nyuukabi 入荷日 DATE
nyuukasuuryou 今回入荷数 NUMBER
nyuukatankazeinuki 入荷単価(税抜) NUMBER
nyuukakingakuzeinuki 入荷金額(税抜) CALC
総平均計算 datefrom 処理日From DATE
dateto 処理日To DATE
zaikocal 総平均計算 DROPDOWN

総平均計算APPは処理を起動する為だけの画面です。

やること

1)商品を全件取得
2)在庫を全件取得
3)入庫を該当期間内全て取得
4)linq.js で各項目の合計と単価計算
5)計算結果を商品に書き込み(計算根拠と計算結果)

本来は商品、在庫、入庫をそれぞれの配列に代入して、linq.jsで連結。というのがスマートだと思うのですが、構文が難しそうなので、今回は、一つの配列に全部放り込んで、それを無理やり合計する方法を取ります。

画面1.PNG

総平均計算APPに必要なJSを読み込んでおきます。
zaikocal.js は今回のロジックを書き込むJSファイルです。
なんかいらないものがまじっていたらすみません。

画像0.PNG

商品全件取得

まずは商品を全件取得して、配列に代入します。
getRecordsAPI()はレコード取得用関数です。

zaikocal.js
        //レコード格納用
        var zaikocal = [];  

        //商品全件取得
        var obj = getRecordsAPI(shohinappId, '');

        //商品数分ループ
        for (var j = 0; j < obj.results.records.length; j++) {
            //挿入用文字列生成
            //skubangou             品番
            //heikintanka           総平均計算結果格納用(これいらないよな)
            //zengetuzaikokingaku   前月末残在庫金額
            //zengetsumatsuzan      前月末残在庫数
            //nyuukasuuryou         当月入庫数量
            //nyuukakingakuzeinuki  闘劇入庫金額

            //品番だけ代入。他は0。
            var row = {
                "skubangou" : obj.results.records[j]['skubangou']['value'], 
                "heikintanka" : 0,
                "zengetuzaikokingaku" : 0,
                "zengetsumatsuzan" : 0,
                "nyuukasuuryou" : 0,
                "nyuukakingakuzeinuki" : 0                      
                }
            //Objectに挿入
            zaikocal.push(row);
        }

在庫全件取得

在庫全件取得します。

zaikocal.js
        //在庫を全て取得
        var obj = getRecordsAPI(stockappId, '');

        //在庫全件ループ
        for (var j = 0; j < obj.results.records.length; j++) {
            //挿入用文字列生成
            //品番、前月末在庫金額、前月末在庫数を代入
            var row = {
                "skubangou" : obj.results.records[j]['skubangou']['value'],
                "heikintanka" : 0,
                "zengetuzaikokingaku" : Number(obj.results.records[j]['zengetuzaikokingaku']['value']),
                "zengetsumatsuzan" : Number(obj.results.records[j]['zengetsumatsuzan']['value']),
                "nyuukasuuryou" : 0,
                "nyuukakingakuzeinuki" : 0                      
                }
            //Objectに挿入
            zaikocal.push(row);
        }//for

該当期間内の入庫を取得します。

期間条件は画面上の値を取得しています。

zaikocal.js
        //入庫情報取得
        //画面上の日付条件範囲を取得
        var strQuery = 'nyuukabi <= "' + mrecord['dateto']['value'] + '"';
        strQuery += ' and nyuukabi >= "' + mrecord['datefrom']['value'] + '"';

        var obj = getRecordsAPI(nyuukameisaiappId, strQuery);

        for (var j = 0; j < obj.results.records.length; j++) {

            //挿入用文字列生成
            //品番、当月入荷数量、当月入庫金額を代入
            var row = {
                "skubangou" : obj.results.records[j]['skubangou']['value'],
                "heikintanka" : 0,
                "zengetuzaikokingaku" : 0,
                "zengetsumatsuzan" : 0,
                "nyuukasuuryou" : Number(obj.results.records[j]['nyuukasuuryou']['value']),
                "nyuukakingakuzeinuki" : Number(obj.results.records[j]['nyuukakingakuzeinuki']['value'])                        
                }
            //Objectに挿入
            zaikocal.push(row);
        }//for 

linq.jsで単価計算をします。

zaikocal.js
        //linqで集計
        var query1 = $.Enumerable.From(zaikocal)
        .GroupBy("$.skubangou", null,
        function (key, g) {
        var result = {
        skubangou: key,
        nyuukasuuryou: g.Sum("$.nyuukasuuryou"),
        nyuukakingakuzeinuki: g.Sum("$.nyuukakingakuzeinuki"),
        zengetuzaikokingaku: g.Sum("$.zengetuzaikokingaku"),
        zengetsumatsuzan: g.Sum("$.zengetsumatsuzan"),
        heikintanka: (g.Sum("$.zengetuzaikokingaku") + g.Sum("$.nyuukakingakuzeinuki"))/(g.Sum("$.zengetsumatsuzan")+g.Sum("$.nyuukasuuryou"))
        }
        return result
        })
        .ToArray();

上記コードを見て頂くのが一番早いですね。こんな感じで、品番をキーにして、各要素の合計計算や、合計結果を組み合わせた計算の実行が可能です。
超便利ですね。もうJavaScriptでいっぱいループをまわなさくてもいいですね。
早くkintoneのAPIで集計機能実装してほしいですね!
集計結果は、query1 に代入されます。

計算結果を商品APPに代入します。

zaikocal.js
        //最終結果をループして、商品マスタを更新
        for ( var i = 0; i < query1.length; ++i ) {
            var updatesku = query1[i];

            //販売単価更新
            hanbaitankaupdate(updatesku);

        } // for

hanbaitankaupdate は商品APP更新用の関数です。いるんですよねこういう関数名を付けるプログラマ(ほんとすみません)。

動作確認

商品APP
りんご
商品.PNG

在庫APP
前月残は 10個で1000円
在庫.PNG

入庫APP
入庫が2件
入庫.PNG

この条件で計算をかけると、、
計算.PNG

結果!
結果.PNG

総平均単価がちゃんと 150円になっていますね。
確認用は計算式を組み込んでいます。
(1,000+5,000)/(10+30)=150円 です。

まとめ

linq.jsをきちんと勉強すれば、kintoneでの集計処理がすごく楽になりそうな気がしています。サーバーサイドでの集計ではないので、集計対象が大量になると厳しいかもしれません、kintoneの標準APIで集計が可能になるまで、皆さんがんばりましょう。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4