【個人開発】世の「家事やれよ論争」を撲滅するスマホアプリをリリースしました

# なぜ家事は紛争を呼ぶのか

私の周りも結婚・出産をする友人が増えました。
そこで必ずと言っていいほど上がる議題がこれ。
### 「夫（妻）がぜんっぜん家事をやらない」
日本で婚姻制度が発足してから早100年。
これだけ長い年月「夫婦」という形が取られているのに、なぜこんなにも初歩的な不満が世に蔓延するのでしょう。

私も妻と結婚して5年経ちます。
知人からの愚痴なども収集した結果、**いくつかの原因が考えられました**。

## その１． 人は「自分が一番やってる」と思う生き物である
これは私がサラリーマンとして働いてて出した結論です。
殆どの人が「**自分は結構仕事してる**」と思いがちです。（これはマジ）
少なくとも同等の仕事量だとまず間違いなく「自分のほうが仕事してる」と勘違いします。

そのため、仮に夫婦が全く同じ量の家事を分担してたとしても、
それが正確に見える化されない限り、**必ず「俺(私)のほうが家事をやってる」という不満が発生する**、というわけです。

## その２． 他者から評価されない
仕事であれば社内の評価制度でしっかり自分の頑張りが認識・評価されます。
しかし**家事はとてもクローズドです**。
認識してくれるのはパートナーしかいませんが、そのパートナーさえ自分の家事を認識してくれることは稀です。
なにせ日中は外出てる人も多いですし、家事はルーティーンがほとんどのため、日に日に「当たり前感」が出て認知されなくなります。

誰にも認識されず感謝もされないタスクを毎日こなせば、そりゃ不満も溜まります。

## その３． 報酬がない
数年前に流行ったドラマ「**逃げるが恥だが役に立つ**」では妻のみくりさんが家事に対して対価を受け取っていましたが、
多くの家庭で家事に対して報酬は支給されません。

「家事も育児もやれば楽しいものよ！」という前向きな考えもありますが、
楽しさと報酬は別問題であり、それこそ世にはびこる「**やりがい搾取**」そのものでしかありません。

家事によって家族に与えた貢献度は**きちんと報酬という形で還元されるべきです**。


## 結論． これを解決すれば家事の不満なくなるんじゃね？
ってことで上記を解決するサービスを、
自分でも笑えてくるほど本気で作りました。

# 家事アプリ「CAJICO」
前段が長くなりましたが、これがこの度私がリリースしましたアプリです！
- iOS：https://apps.apple.com/jp/app/id6446474225
- Android：https://play.google.com/store/apps/details?id=com.herokuapp.cajico

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891369/04fcfe05-581f-5753-36fb-7e585d88ac09.png)


デザインがポップでとても可愛らしいですね。

サービスはもちろん上記の課題を解決する機能が実装されています。

## 機能１． 家事はポイントにして見える化
家事・育児は予め夫婦でポイントを決めておき、
それを達成することで定量的なポイントを獲得できる
という仕組みです。
これによって、根拠のない「**俺のほうが家事やってる理論**」は撲滅されます
家事の種類やポイントはもちろん家族内で自由に編集できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891369/727ea30a-e337-b108-c145-d0a2281cd43e.png)

## 機能２． 家事をやったら家族にお知らせが届く
家事をクリアすると自分の家族あてにpush通知が届くようになっています！
これによって相手に家事を強制的に知らせることができます。
アプリ上の機能ですので、**わざわざ口頭で伝えるよりいやらしさもありません**（これ大事）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891369/92354cd9-f39c-b28d-c30e-684976d417d6.png)
そしてパートナーがしてくれた家事には「**リアクション**」をすることができます！
リアクションUIは皆さんおなじみSla◯k。
我ながらよく完コピできたなと感心しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891369/8310e57b-68a9-0806-6964-0446e8b60f66.png)

## 機能３． たまったポイントはごほうびで還元
ごほうびはユーザーごとに「**大・中・小**」の３種類で設定可能です。
これがあれば「**あと何ポイントでこれがもらえる！**」みたいなワクワクもありますし、
何より家事にモチベーションが増えますね！

パートナーも日頃の感謝を表現するきっかけになると思えば、全員がハッピーな機能ではないでしょうか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891369/a6a2d465-a7dd-5b86-92b3-66cbf7309693.png)

## 機能４． 普通に家事管理アプリとしても使える！
仮にもともと夫婦円満な家庭だったとしても、
このアプリは通常の家事管理アプリとしても有能です。

スケジュール機能が実装されているため、**１日の家事の予定をアプリ上でカレンダーに登録しておくことができます！**
カレンダーは週と日のカレンダーを切り替えることができるので、お好きな方で閲覧ができます。（完了した家事は薄く表示されます）
Googleカレンダーのように「**繰り返し機能**」をつけてますので、定期的な予定を登録することで無駄な入力の手間を省くことができます。
（ここの繰り返し機能のスキーマがかなり頭を悩ませたんですが、そこは後述の技術面の話で記載します）

![Screenshot_2023-04-23-12-26-55-725_com.herokuapp.cajico.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891369/b2643f30-25e0-4bd0-267b-2aed4e42c96f.jpeg)

# 技術系のお話
Qiitaなので技術系の話も書いておきます。
- API：**Laravel**
- アプリ：**Flutter**
- 管理画面：**Laravel/Vue.js（typeScript）**
- DB：**MySQL**
- サーバー：**Heroku**
- Pushサーバー：**FCM（firebase）**
- その他インフラ：**AWS（S3とかSESとか）**

## 実装に苦労したとこ
スケジュール機能はできるだけGoogleカレンダーを真似したくてテーブル構造を色々検討しましたが、
なかなか自分の要件を満たせる実装が難しかったです。
### 繰り返し機能
まずこれのせいで予定自体をレコード管理できなくなりました。
なにせ繰り返し終了日が未定のものをレコードで登録したら、**一気に予定レコードが爆発します**
しょうがないので繰り返しを含めた「**予定の設定情報**」をレコードで保管し、リクエストで送られてきた日付に該当すればレスポンスで返す、というやり方にしました。
ただ、それをやる時に更に問題になったのは「**特定の日付だけ予定を変更・削除したい、もしくはその日の予定が完了したフラグをつけたい**」という要件です。
予定自体がレコードになってれば楽勝で管理できますが、「その日の予定」というレコードは存在しないので、**どうやって繰り返し設定の中で特定の日付だけに情報を与えるか**に頭を悩ませました。

悩んだ末に思いついたのが「**予定テーブル**」と「**予定アクションテーブル**」の２つを用意する。というやり方です。
この手のスキーマは結構ネットに落ちていますが、私の以下のスキーマならGoogleカレンダーで搭載してる機能はほぼ対応できるはずですので、
カレンダー機能に悩まれてる方は是非ご参考ください！

- 予定テーブル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891369/b55d29e4-57d2-559a-81e4-ad69c60a3515.png)

- 予定アクションテーブル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891369/4fae44ea-aa3f-2829-49e4-f299b85d3383.png)

ざっくり説明すると、
予定テーブルで予定の内容や繰り返しルールを記載し、
予定アクションを子テーブルに、その予定のいつに何のアクション（削除・タスク完了）をしたのかを登録する。
といった感じです。
こうすれば繰り返し予定でも、特定の日付を削除したり完了したりのログを残すことができます。

肝心の予定の取得APIでは以下のようなscopeを登録しておき、
繰り返し予定の中で該当する予定を拾い上げてます。

```php:schedule.php
    public function scopeRepeatSchedule($query, $familyId, $date)
    {
        return $query
            ->orWhere(function ($query) use ($familyId, $date) {
                $query
                    // 該当家族のスケジュール
                    ->where('family_id', $familyId)

                    // 繰り返しスケジュールである
                    ->whereNotNull('repeat_rule')

                    // 繰り返し終了日が指定日よりも先もしくはnull
                    ->where(function ($query) use ($date) {
                        $query
                            ->whereDate('repeat_end_date', '>=', $date)
                            ->orWhereNull('repeat_end_date');
                    })

                    // 繰り返しによって指定日が被るものを絞り込み
                    ->where(function ($query) use ($date) {
                        $query
                            // 日毎の繰り返しで一致するスケジュール
                            ->where(function ($query) use ($date) {
                                $query
                                    ->where('repeat_rule', RepeatRule::Daily)
                                    ->whereDate('start_at', '<=', $date)
                                    ->whereRaw('DATEDIFF(?, start_at) % repeat_interval = 0', [$date]);
                            })
                            // 週毎の繰り返しで一致するスケジュール
                            ->orWhere(function ($query) use ($date) {
                                $query
                                    ->where('repeat_rule', RepeatRule::Weekly)
                                    ->whereDate('start_at', '<=', $date)
                                    ->whereRaw('DATEDIFF(?, start_at) % (repeat_interval * 7) = 0', [$date]);
                            })
                            // 月毎の繰り返しで一致するスケジュール
                            ->orWhere(function ($query) use ($date) {
                                $query
                                    ->where('repeat_rule', RepeatRule::Monthly)
                                    ->whereDate('start_at', '<=', $date)
                                    ->whereDay('start_at', $date->day);
                            });
                    });
            })

            // 削除された日付だった場合は除く
            ->whereNot(function ($query) use ($date) {
                $query->whereHas('actions', function ($query) use ($date) {
                    $query
                        ->where('action_type', ActionType::Delete)
                        ->whereDate('action_date', '=', $date);
                });
            });
    }
```
# CAJICOで家族に幸せあれ！
仕事の合間を縫って頑張って作りました！
一家族でも多くの家から「家事やれよ論争」がなくなることを祈っております！

是非使って使ってみてください！！！