入出金管理 資金繰表

既出であれば申し訳ございません。

予定を含む入出金の登録データから資金繰り表を作成したく
色々と試しているのですが、標準機能では累計計算が出来ないようで
煮詰まってしまっています。

Excelと連携させるなどすればどうにかなりそうな予感はしているのですが、
出来る限りkintoneアプリ内にて完結させたいです。

ご教示のほどよろしくお願いいたします。

 

 

上田さん

こんにちは。

やりたいこととしては、下記のようなイメージでいいのでしょうか?

1.入出金を1件ずつレコードを登録

2.入力された情報をものとに資金繰り表を作成

この場合、資金繰り表をどこに作るのか(レコード内に表示、カスタマイズビューで作るなど)

で処理方法が多少変わるかと思います。

 

資金繰り表ということで、計算方法や、表示項目が異なると思うので、参考ですが

基本的にはどちらにしろ、下記ページのREST API で対象レコードを取得して、

計算し表示するという流れになる気がします。

https://cybozudev.zendesk.com/hc/ja/articles/202331474#step2

 

レコード内に作る場合、関連レコードを利用して、対象のレコードを取得、JSを用いて計算

というような感じのイメージです。

関連レコードの集計方法は下記ページ等を参考にしてもらうといいかと思います。

https://cybozudev.zendesk.com/hc/ja/articles/203030394

または、関連レコードでは表示せず、計算結果を表示するフィールドを作成しておき、

取得した情報の結果を表示させる方法などがあるかと思います。

サクラエビ様

ご回答ありがとうございます。

日付 | 入金 | 出金 | 残金
4/10| 10| 0| 10
4/15| 0| 5| 5
4/20| 0| 7| -2

みたいな感じにしたかったのですが、

日付 | 入金 | 出金 | 残金
4/10| 10| 0| 10
4/15| 0| 5| ー5
4/20| 0| 7| ー7

となってしまって困っていたのです。

どうやらJSで対応すればkintone内で完結しそうですね。
頂いた情報と合わせて色々と調べたところ、

別で資金繰り表作成アプリを入出金入力アプリとを
別々につくり、新規作成時にREST APIで入力値を全件取得し、
累積額を計算しつつevent.recordに放り込んでいく。といった処理で
解決できそうです。

まだまだ険しい道のりでしょうが、解決の出来そうであるとの手応えを得ることが出来ました。
本当にありがとうございました!

参考になったようで何よりです!

 

見た範囲では累積額(残金)のがうまく取得 or 計算できていないことで想定と違う動作に

なってしまっていそうですね。

イメージとしては、上田さんの書いている方法もしくは、累積額を管理するフィールドがあれば、

取得が全レコードにならなくて済みそうなので、計算が楽かもしれないですね。

また何かありましたら、相談してもらえれば回答できる範囲で回答しますね。

その後、どうにか実装出来ましたので、ソースを晒しときます。

フォームには、

日付:start_date

数値:carry_over

テーブル:Table(日付:settlement_date、数値:deposit_value、数値:payment_value、数値:margin、)

が置いてあり、start_dateに計算の起算日を入力後、保存すると資金繰り表が生成されます。

なお、

kintone でSQLを使う - Qiita

で紹介されているライブラリを使用しています。

 

(function () {
 “use strict”;
 var appId = 21;
 var events = [‘app.record.create.submit’];
 //var events = [‘app.record.create.show’];
 //繰り越し金額
 var carry_over = 0;
 kintone.events.on(events, function (event) {
  var record = event.record;
  //起算日が入力されていなければ処理終了
  if (!record.start_date.value) {
   return event;
  }
  var inputDate = record.start_date.value;
  var start_date = inputDate;
  //集計元データ取得→反映
  return  getRecords(appId, ‘’, [‘deposit_value’, ‘payment_value’, ‘settlement_date’]).then(function (records) {
   var data = adjustForAlasql(records);
   //指定日前日以前のものは全て合算して繰り越しとする
   var result =
       alasql(
           “SELECT SUM(deposit_value) - SUM(payment_value) AS carry_over” +
           " FROM ?" +
           " WHERE settlement_date < ‘" + start_date + "’"
           , [data]
           );
   carry_over = result[0].carry_over ? result[0].carry_over : 0;
   record.carry_over.value = carry_over;
   //指定月以降の入出金データを日毎に取りまとめる
   var list =
       alasql(
           “SELECT settlement_date, SUM(deposit_value) AS deposit_value, SUM(payment_value) AS payment_value” +
           " FROM ?" +
           " WHERE settlement_date >= ‘" + start_date + "’" +
           " GROUP BY settlement_date" +
           " ORDER BY settlement_date"
           , [data]
           );
   var total = carry_over;
   var insertArray = [];
   //繰り越し金額を踏まえて残高を計算する
   list.forEach(function (list) {
    total += (list.deposit_value - list.payment_value);
    list.margin = total;
    insertArray.push(adjustForTable(list.settlement_date, list.deposit_value, list.payment_value, list.margin));
   });
  record.Table.value = insertArray;
  return event;
  });
 });

 //入出金の全件取得
 function getRecords(appId, queryString, fieldsArray, offsetNum, limitNum, recordArray) {
  var query = queryString || ‘’;
  var offset = offsetNum || 0;
  var limit = limitNum || 500;
  var records = recordArray || [];
  var params = {app: appId, query: query + ’ limit ’ + limit + ’ offset ’ + offset};
  if (fieldsArray) {
   params.fields = fieldsArray;
  }
  return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, params).then(function (res) {
   records = records.concat(res.records);
   if (res.records.length === limit) {
    return getRecords(appId, query, fieldsArray, offset + limit, limit, records);
   }
   return records;
  });
 }

 //SQL利用対応
 function adjustForAlasql(records) {
  var rows = records.map(function (record) {
   var keys = Object.keys(record);
   var row = {};
   keys.map(function (key) {
    row[key] = record[key].type === ‘NUMBER’ ? Number(record[key].value) : record[key].value;
   });
   return row;
  });
  return rows;
 }

 //Tableの行の形に加工
 function adjustForTable(settlement_date, deposit_value, payment_value, margin) {
  return{
   ‘value’: {
    ‘settlement_date’: {
     ‘type’: ‘DATE’
     , ‘value’: settlement_date
    }
    , ‘deposit_value’: {
     ‘type’: ‘NUMBER’
     , ‘value’: deposit_value
    }
    , ‘payment_value’: {
     ‘type’: ‘NUMBER’
     , ‘value’: payment_value
    }
    , ‘margin’: {
     ‘type’: ‘NUMBER’
     , ‘value’: margin
    }
   }
  };
 }

})();