fragmentary notesITエンジニアの気まぐれメモ

家計簿システムを自前運用してみた与太話

Introduction

2022/10から、自分個人用に新しい家計簿システムの運用を開始しました。趣味コーディングとして、初めて家計簿を運用し始めてからこれが5代目に当たります。折角なので忘備の意味も込めて何で私が家計簿システムを自前で運用しているのか、これまでの家計簿遍歴、新システムの概要等々を綴ってみます。

本業は基幹業務システム導入に携わるITエンジニア。業務で得られた経験・考え方も、この趣味コーディングに盛り込まれ、逆にこちらで得られた知見が逆に本業で役立つことも、おかげ様で楽しい毎日が送られているわけです。

Motivation

そもそもなぜ自前の家計簿を運用するのか、無料で提供されている各種サービスのほうが自動データ連携等もあり便利じゃないのか?

もちろんその通りなのですが。。。一応 ITエンジニアの端くれとしての自己満足・自分で何か作りたい・自分で作ったものを使いたいという欲求を満たすための対象として、家計簿は程よい大きさのテーマだと思います。またマスタ・トランザクションデータをどう持つか、どういう分析軸でデータを検証し・PDCAサイクルを回すか等、基幹業務システム導入という本業の考え方をある程度生かせるフィールドと考え、ここに至りました。

もちろん、数年に1回のシステム更新の際には既存の家計簿サービスへの移行、または併用も考えるわけです。今回の5代目システム検討時にももちろんいろいろ調べてみましたが、

  • 無料のサービスではデータを保持できる容量・期間が短い
  • データインポート・エクスポートの手段が限られている
  • APIの利用ハードルが高い

等々、諸々の理由で採用には至らず、結局スクラッチで作ってしまいました。あとは単純に、ある程度まとまった量のデータを、直接SQLでグリグリしたかった、というのもあります。SQLスキルを維持・強化したいので。

導入目的・スコープ

家計簿を作る・記録する目的・スコープは、手元の支出額を把握すること。普段の買い物や移動等で発生する財布・交通系IC・クレジットカードによる支出額を用途別に記録し、日々の記録と過去の実績を比較したり、月末に当月の活動内容の振り返りに使用したいと考えています。故に管理する対象は下記の通り。

  • 財布・交通系IC・クレジットカードによる支出額
  • 財布・交通系ICへの収入額(口座⇒財布、クレジットカードによる交通系ICのチャージ等の資産移動)
  • 財布・交通系ICの残高
  • クレジットカードの使用額(参考値)

銀行口座の残高や給与収入の管理、クレジットカード請求額との突き合わせ等、難しいことはしません。それらは通帳や明細を見ればわかることなので。

これまでの家計簿システム遍歴

  • 第1世代:Excel関数
    • 運用期間:半年
    • Excel関数 | エクセルシートに用途別の支出金額をひたすら記録し、ピボットテーブルでサマリを確認。

  • 第2世代:ローカルアプリ(Windows Form + SQLite3)
    • 運用期間:半年
    • ローカルアプリ(Windows Form + SQLite3) | エクセルシートをそのままWindows Formアプリケーション化したもの。DBはお手軽にSQLite3を使用。入力にはPC起動が必須で面倒でした。

  • 第2.5世代:無料家計簿サービス(Zaim) + ローカルアプリ(Windows Form + SQLite3)
    • 運用期間:1年
    • 無料家計簿サービス(Zaim) + ローカルアプリ(Windows Form + SQLite3) | お試しで家計簿サービスZaimを入力のためのフロントエンドとして使用。月末にエクスポートしたデータをこれまでのローカルアプリケーションに取込、過去実績との比較等を実施していた。

  • 第3世代:WEBアプリ、フロントエンド:Google Spreadsheet + Google Apps Script、バックエンド:Ruby on Rails + PostgreSQL
    • 運用期間:2年
    • WEBアプリ化の第1歩。とはいえ使い勝手のよいフロント画面を作るスキルがなかったため、Google Spreadsheetに入力した内容をGoogle Apps Scriptで読み取り、バックエンドのAPIをcall、結果をSpreadsheetに書き戻すという方式を採用。これはこれで使いやすかったものの、モバイル機器からの入力には限界があり。。。

  • 第4世代:WEBアプリ、フロントエンド:Vue.js、バックエンド:Ruby on Rails + PostgreSQL
    • 運用期間:3年半
    • Vue.jsを活用したフロント画面を用意し本格的にWEBアプリ化。 バックエンドも、データモデル設計を真面目に考えたり、ビジネスロジックを再利用しやすい形でモジュール化したり、メール通知や外部システムI/F(suicaデータ取込)を用意したり。この3年半、決済手段の多様化やコロナ禍でのライフスタイルの変化にも耐えうる、柔軟な運用、改修・拡張が容易な仕組みを実現。

  • 第5世代:WEBアプリ、フロントエンド:Nuxt.js、バックエンド:Express.js + PostgreSQL
    • 運用期間:4ヶ月目
    • More Simplifyをテーマに、追加機能の盛り込み・拡張を続け肥大化、使用ライブラリの依存性がぐちゃぐちゃで、再ビルドしたら動く保証のない状態になりつつあった前世代のリソースを全て捨て、1年弱かけて必要なものだけを1から再構築。これまでの世代交代と比べる派手さはないものの、モジュール間の独立性を保った設計を意識し、今後の機能拡張によるスパゲッティ化を抑えたい。

5代目 家計簿システム概要

システム構成

今回のシステムを実現する上で、採用した技術とプラットフォーム、システム構成はこんな感じです。個人用との趣味コーディング故に運用コスト:0円でできる形にしています。

  • フロントエンド
  • フレームワーク:Nuxt.js + Vuetify
  • プラットフォーム:netlify
  • バックエンド
  • フレームワーク:Express.js + Sequelize
  • DB:PostgreSQL
  • プラットフォーム:Fly.io
  • 認証システム
  • Firebase Authentication
  • システム通知
  • Discord Webhook

肝となるバックエンドアプリケーションを動かすプラットフォームとして、Fly.io を採用。前世代まではherokuを利用してきましたが、heroku無料枠廃止に伴い代替プラットフォームの1つとして界隈で話題になっていたものをこの度 活用。今のところherokuに比べ利用制限が優しく、また日本国内のリージョンが指定できる等の恩恵にあずかっています(いつまで今の状態が続くのか心配ではありますが)。

言語・フレームワークとしては、サーバーサイドJavaScriptのNode.jsのWebアプリケーションフレームワークであるExpress.jsを採用。これまで利用してきたRuby on Railsはどちらかといえばフルスタックな考え方で、全てを実現できる代わりに、コード構成が複雑、かつ使わない部分・何が書いてあるのかわからないが大部分を占めていたのに対し、Express.jsはよく言えば自由度が高い、悪く言えば素の状態ではできることが限られている。そのためベース部分のコーディング量はRailsのときよりも多くなるものの、そこを含め自分でコントロールできる(逆にコントロールしてあげないと何もできない)ため、何だかんだ使い勝手がよかった。また必要な機能しか実装しないため、全体的なコード構成はシンプルにできるわけです。

ユーザー認証部分は、車輪の再開発をすべきポイントではないと考え、Firebase Authenticationを活用。フロントエンドから認証を通したJWTをバックエンドで検証する形をとりました。流れを簡単にまとめた以前のメモです。

【備忘】firebase JWTをJavaScriptで検証してみた

一連の開発は、docker on WSL2上に環境を用意して実施しています。今回は開発・運用中にPCの乗り換えをしましたが、docker上においていたおかげで、すんなりと開発環境を再構築できました(Rails時代は、直接Windowsにのせていたので、乗り換え時のバージョン違い・依存性エラー多発で大変な思いをしていました)。docker on WSL2上でのExpress.jsとPostgreSQLによるアプリケーション開発環境構築メモは自分の忘備としてまとめています(いまでも頻繁に見返して、作業しています)。

【備忘】Express.js + PostgreSql をdocker上に構築

データモデル概要

家計簿ってそんなに難しいロジックを必要としないと思います。ものすごく乱暴に言ってしまえば、日付と科目と金額を記録できればOKと。でも、データをどうやって保持するかをちゃんと考えずに作ると、後々泣くことに。。。過去に訳が分からなくなったこととして、金額値の符号。収入と支出、それに対する正データと取消データの組み合わせで、だんだん混乱していくわけです、集計するときとか。

そんなこともあり、今回は複式簿記チックな考え方を取り入れた形にしてみました(故に移行データを作るのに苦労しましたが)。データモデルの概要を語っておきます。この形がbestとは思いませんが、いろいろな事情を考慮するとbetterかな。

マスタ系

  • 会計GPマスタ
  • 家計簿を管理する最上位単位。今のところ使う用途はないですが、1人のユーザーが用途によって家計簿を分けて管理する(自分用と家族共用etc)、また1つの家計簿を複数ユーザーで共有する際に使えるようにした概念。会計GPユーザー割当マスタによってユーザーと会計GPを割当することで、ユーザーが使える家計簿が決まる。

  • 科目タイプ
  • 科目をグルーピングする最上位単位。主な用途は、その科目が、費用なのか 収益なのか(P/L科目)、資産なのか負債なのか(B/S科目)を定義する区分値。

  • 科目GPマスタ
  • 科目をグルーピングする単位で、会計GPと科目タイプに依存する。科目集計が目的で、私は「食費」「交通費」etcくらいの粒度で設定している。

  • 科目マスタ
  • 科目の最下位レイヤー。家計簿転記する際に指定する科目で、科目GPに依存する。「食費」という科目GPに対し「食費」「嗜好品」etc、「交通費」に対し「私用」「通勤費」etc、具体的な内訳を定義している。

  • 会計期間管理
  • 会計GP単位で現在オープンされている会計期間を定義するマスタ。間違って変な年・月を指定して転記しないよう、現在月 or 翌月以外に転記できないようにする制御に使用している。

トラン系

  • 家計簿伝票ヘッダ・家計簿伝票明細
  • 家計簿の一番メインとなるトランザクション。会計GP・伝票タイプ毎に伝票番号を発番し、借方・貸方明細の科目・明細金額を記録します。後々追いかけられるよう、どの機能で伝票登録したかを「転記プログラム」に、外部IFで取り込んだ際のキー情報を「外部IF伝票No」「外部IF伝票明細No」にもたせました。また伝票取消や修正は対応せず、反対伝票登録⇒修正転記する赤黒方式としているため、伝票間の紐づきを持たせる「参照オブジェクト」項目も用意しています。

  • 伝票タイプ
  • 伝票のグルーピングや、伝票Noを分けたい場合に使用する概念。移行で突っ込んだ伝票と新システムで登録した伝票を分けるために用意しました。やっぱり1発目の伝票は1番からにしたいよね。また反対伝票転記する際も伝票タイプを分けるようにしています。

主要なテーブルはこんな感じです。月次サマリみたいなスタンプデータは今回持たせませんでした。1人で使う分にはそれほどデータ量が増えることはないので、これらは都度 Viewで集計してデータ取得するようにしました。Code push down ということで(多分 言葉の使い方を間違っている気もしますが)。

分析系機能

単に実績を記録するだけではなく、データを見える化して、簡単に参照したい!ということでいくつかレポート画面も作ってみました。その中で特に重宝しているのがこの科目GP別進捗状況。科目GP毎に現在月と指定した過去月の実績集計を比較し、現時点の状況「今月は食費を使いすぎているな」「このままいくとこのくらいの着地になるかな」といったことを確認できるようにしています。

グラフ描画にはVue Apexchartsを使用。

終わりに

ざっと思いの丈を書ききってみました。新システムはまだ稼働し始めたばかりで、今後も改善活動は続ける予定です。具体的には、現状の実績収集だけでなく、あらかじめ予定(例えば食費であれば、先数日分の自炊・外食計画をたて、それに基づく支出予定)を登録おき、予実管理みたいなことまでできると良いかなと思っています。以前Excelベースで予定をたてる運用を3週間くらい試してみて、いろいろ良さはあったものの、家計簿とExcelの予定表の2重登録が手間になりやめてしまった経緯もあり。。。

他には、スマートフォンのカメラでJANコードを読んで、家計簿入力画面の摘要欄に品名を自動提案するとか、あとはウェアラブル端末からのライフログのデータと組み合わせてみるとか。

データ活用・データ分析の遊び 兼 勉強のために、自分からとれる情報をなるべく貯めていきたいな。もの好きな人間の趣味コーディングの題材として、しばらくはネタ切れしなさそうです。

  • Home
  • /
  • Posts
  • /
  • 家計簿システムを自前運用してみた与太話
Tech-TIPS

Comments

© 2024 shunya_wisteria