たろすの技術メモ

Jot Down the Tech

ソフトウェアエンジニアのメモ書き

【個人開発】同棲カップル・夫婦のための支出管理アプリを作った話

※この記事は【個人開発】同棲カップル・夫婦のための支出管理アプリを作った話の記事をエクスポートしたものです。内容が古くなっている可能性があります。

概要

「ファミコスト」という、同棲カップルや夫婦など2人で支出管理している方向けのモバイルアプリを作りました🎉アプリの紹介と、開発期間に考えていたことを備忘録的に書いていきます。

apps.apple.com

play.google.com

作った経緯

我が家は共働き夫婦なので、2人の生活費をジャンル毎に負担割合を決めてそれぞれ出し合い、月一回スプレッドシートでお金のやり取りを計算していました(「今月は妻に〇〇円渡す」など)。半年ほど続けてみてほとんどの支出が固定(金額は変動する)でルーチンワークということが分かり、月一回の作業が面倒になってきたので効率化するためにアプリを作り始めました。

どんなアプリか

2人でお金を出し合う出費を「コスト」として登録すると、月ごとに「相手にいくら渡す」「相手からいくら受け取る」を計算してくれるアプリです。自分の方が実際の負担額より多く立替えている場合は緑色で「自分が受け取る金額」を表示し、逆に相手の方が多い場合は赤色で「相手に渡す金額」を表示してくれます。

2人それぞれの画面

その他にも、「繰り返し設定」で毎月・2ヶ月に1回などの定期的なコストを登録できたり、カテゴリ別にデフォルト値を設定できたり(「食料品は6:4の負担割合」など)、入力の手間を省く機能もあります。

使った技術

Flutter

普段使いするアプリで入力する機会も多いため、モバイルアプリを選択しました。端末依存の機能は一切無いため、自分が一番得意でiOS/Android両方でリリースできるFlutterを選択しました。

Firebase

シンプルなアプリかつ低予算で運用したいのでFirebaseを選択しました。

  • Firestore
  • Authentication
  • Functions
    • アカウント削除とPush通知で使用
  • Remote Config
    • 強制アップデートで使用
  • Crashlytics
    • 監視

各機能

  • 認証系
    • アカウント作成
    • ログイン
    • アカウント削除
  • コストCRUD
  • コスト編集履歴
  • カテゴリ別設定機能
  • 繰り返し設定機能
  • メンバー招待機能

コアな課題を解決するためにMustな機能

このアプリで解決したい一番コアな課題は

「相手にいくら渡すのか」or「相手からいくら受け取るのか」が簡単に分かること

でした。そのため、それ以外の機能はできるだけ削り、上記を解決するために必要な機能を実装しました(取捨選択難しい)。

コスト登録機能

これは言わずもがなですが、一番よく使う機能なので、そのUXはリッチなものにしようと考えました。ファミコストでは以下の項目を入力・選択してコストを作成します。たくさん入力項目があっても使いにくいので、必要最小限の項目に留めました。

  • 一般的な項目
    • 金額
    • カテゴリ
      • 後述する「カテゴリ別設定」をしておけば、カテゴリを選択しただけで負担割合がセットされる状態にしたかった
    • 日付
    • 支払った人
      • 金銭授受を計算する際に必要
    • 内容
      • 一覧画面で表示する
    • 負担割合
      • 金銭授受を計算する際に必要
  • 繰り返し設定
    • 支払いタイミング(毎月 or 2ヶ月に1回)
      • 家賃などの毎月支払うものや、水道代などの2ヶ月に1回支払うものを設定しておくと、翌月以降は入力しなくていい
    • 支払日
    • 金額を固定するかどうか
      • 家賃など金額固定のコストと、電気代など金額が変動するコストの両方に対応するため追加したフラグ

またコストを連続で入力できるように、よくある登録後に一覧画面へ戻るUIではなく、登録後はフォームの値をリセットして編集画面に留まるようにして、ストレスなく登録できることを目指しました。

繰り返し設定機能

毎月・2ヶ月に1回など固定でかかるコストの内容を毎回入力するのは面倒なので、繰り返しを設定できる機能が必要でした。

支払いタイミング

「毎月」か「2ヶ月に1回」から選択できます。これが設定されたコストを登録する場合には翌月以降の分も同時に登録する処理が必要になります。

  • 毎月
    • 登録月の翌月(+翌々月)分を登録
  • 2ヶ月に1回
    • 登録月の翌々月分を登録

この辺りのロジックが複雑になりそうだったので、不本意ながら前月の1日〜翌月末までのコストしか登録できないようにしました(上記以外にも支払いタイミングを変更した時にどうするか?など考えることが多いにもかかわらず、エッジケースなので労力に見合わない)。

支払日

繰り返す日付を設定します(毎月27日など)。ここで考えたのは、例えば31日で登録している繰り返し設定の場合、2月のように28日までしか無い月にどうするかでした。最終的には以下のように愚直に対応しました。

final now = DateTime.now();
final nextMonth = DateTime(now.year, now.month + 1);
final repeatDay = 31;
var date = DateTime(nextMonth.year, nextMonth.month, repeatDay);

// 月が違う = 日付が存在しない(31日指定でその月が30日までの場合など)ので月末の日付にする
while (date.month != nextMonth.month) {
  date = date.subtract(const Duration(days: 1));
}

金額を固定するかどうか

家賃など毎月金額が固定の支払いの場合はその金額を繰り返せばいいのですが、ほとんどのコストは毎回金額が変動すると思うので、「金額を固定しない」という選択肢を作りました。その際そのコスト分を入れての計算はできなくなるので、一覧画面にBadgeを表示してユーザーに気づいてもらえるようにしました。

badgesというPluginを使用しました。

pub.dev

メンバー招待機能

二人で同じデータを編集・閲覧できるように、メンバー招待機能が必要でした。招待の手順は以下です。

  1. 1人目のメンバーが招待コードを生成する
  2. 2人目のメンバーが会員登録時に招待コードを入力して参加を申請する
  3. 1人目のメンバーが申請を承認する
  4. (1人目のメンバーが申請を拒否する→1に戻る)
  5. 招待完了

同棲カップルや夫婦など物理的に近くにいる人と使う場面を想定しているので、申請・承認のフローは不要かなとも考えたのですが、何かの間違いで赤の他人が参加できてしまうのも怖いので、念の為実装しました。順番にどうやって実現したのか書いていきます。

1人目のメンバーが招待コードを生成する

サービス内で一意の文字列を生成します。この処理は本来サーバー側で行うべきだと思いますが、個人開発というリソースが限られた状況を鑑みて、管理しやすいアプリ側に実装することを決めました。

2人目のメンバーが会員登録時に招待コードを入力して参加を申請する

入力された招待コードから参加するファミリー(ファミコスト内で2人が参加するグループの名称)を特定してisRequestedフラグをtrueにし、1人目のメンバーに通知します。

1人目のメンバーが申請を承認する

2人目のメンバーから申請があるとダイアログが表示され、承認・拒否を選択できます。承認した場合は招待に関するデータを削除&2人目のメンバーに通知し、招待が完了します。

1人目のメンバーが申請を拒否する

申請を拒否した場合も招待に関するデータを削除&2人目のメンバーに通知し、ファミリーへ参加できないようにします。

カテゴリ別設定機能

「食費は7:3」「家賃は6:4」など個別に設定できると便利だと思い実装しました。

SSSAPI

アカウント作成時に、あらかじめ作成しておいたカテゴリデータを各ファミリーのDBに保存するのですが、そのマスターデータの管理に利用させていただきました🙏記事執筆時点ではAPI3本までなら無料で使えるのでぜひ使ってみてください。

sssapi.app

デザイン

使った技術

画面レイアウト・アプリアイコン・ストアのスクリーンショットなどは全てFigmaで作成しました。簡単なデザインなら初心者の自分でもFigmaだけで作れそうです。

アイコン

我ながら気に入ってます

お金を管理するアプリということでドルマークと、それを2人でやりとりするということで双方向に矢印が流れるデザインにしました。ちなみに矢印の色はNASDAQの株価上昇・下降色を参考にしました。

その他

  • 多言語対応
    • 海外のユーザーにも使ってほしいので(とりあえず英語だけですが)頑張りました。特にカテゴリの翻訳は文字数の問題や伝わる言葉選びが難しかったです。
  • Linter
    • 1人で開発してますが、これが無いとモヤモヤする体になってしまいました。
  • AdMob
    • ストアとリンクする前に広告を表示しているとリリース版で広告が表示されなくなるという話を聞いたので、v1.0.0では広告無しで配信し、AdMobとリンクさせてからv1.0.1から表示するようにしました。特に問題なくできたと思います。
  • 強制アップデート
    • ファーストリリース時には絶対に欲しかったので早々に実装しました。
  • ライセンス情報画面
  • Push通知

まとめ

久しぶりの個人開発だったのですが、ストアの審査も一発でクリアしたので一安心しました(以前は4.2 Minimum Functionalityに苦しめられた)。自分が普段使いするアプリなので、どんどんアップデートして使いやすいアプリにしていきたいです。最後まで読んでいただきありがとうございました🙇