ビジネスパーソン・ガジェット置場 empty lot for business

営業や仕事、それに伴う生活を便利に楽にするツール、ガジェットを作ります。既にあるツールも自分用にカスタマイズ。

ラインで入力、残高も確認できる家計簿【python + Line Messaging api】

今回はこんな声に対応するガジェットです。
「ラインなら外出先でもすぐに使用できるし、いつも見ているので、ラインで家計簿を管理でき、残高もラインですぐに確認できるようになったらいいな。」

f:id:kslabo51:20220228202330j:plain

ライン家計簿どこでも簡単入力、簡単残高チェック

買い物をした際には、すぐにラインから使った金額や項目を家計簿データベースに入力でき、あとどのくらい使えるお金があるのかもラインですぐに確認できるガジェットです。

f:id:kslabo51:20220228203058p:plain

 

このガジェットでできることはこちら

  • ライン上で使用したお金を入力、残高も一覧で確認できます。
  • データはスプレッドシートで管理します。
  • 会話形式ですので楽ちん。

注意点はこちら

  • 今回は使用したお金の入力でテキストを使っており、決まったフォーマットでの入力にしています。そのため、フォーマットに合わないと入力できないので、今後改良が必要です。

評価(自己)

役立ち度   ★★★★(良し)
効率化    ★★★★(良し)
ミス防止   ★★(悪い)
楽しさ    ★★★★(良し)
操作性    ★★(悪い)

※上の注意点にも書きましたが入力が決まったフォーマットに従わないといけないことと、選択形式にしていないので操作性は悪いです。また、なので打ち間違いが出る可能性があるのでミス防止も悪いにしています。(要改良)

実行環境

使用環境    GCP、Heroku、line messaging api
使用言語     python
使用ライブラリ  flask、inebot、os、json、pandas、datetime、gspread、   

        oauth2client

今回のコード

# app.py


from flask import Flask, request, abort

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)
import os
import json
import pandas as pd
from datetime import datetime
import gspread
from oauth2client.service_account import ServiceAccountCredentials

# スプレッドシートへのアクセスと必要な各シートを取り出す関数
def auth():
    SP_CREDENTIAL_FILE = 'secret.json'

    # APIを使用する範囲
    SP_SCOPE = [
        'https://spreadsheets.google.com/feeds',
        'https://www.googleapis.com/auth/drive'
    ]

    # 今回使用するスプレッドシートのurlのdの直後
    SP_SHEET_KEY = 'スプレッドシートのID'
    SP_SHEET1 = 'accountbook'
    SP_SHEET2 = 'this-month'
    SP_SHEET3 = 'balance'

    # 認証情報を組み合わせ認証する
    credentials = ServiceAccountCredentials.from_json_keyfile_name(SP_CREDENTIAL_FILE, SP_SCOPE)
    gc = gspread.authorize(credentials)

    # スプレッドシートの情報を取ってくる
    sh = gc.open_by_key(SP_SHEET_KEY)
    worksheet1 = sh.worksheet(SP_SHEET1)
    worksheet2 = sh.worksheet(SP_SHEET2)
    worksheet3= sh.worksheet(SP_SHEET3)
    return worksheet1, worksheet2, worksheet3

# 家計簿の入力
def input_accountbook(contents):
    worksheet1 = auth()[0]
    data = worksheet1.get_all_values()

    df = pd.DataFrame(data[1:])
    df.columns = data[0]
    timestamp = datetime.now()
    date = timestamp.strftime('%m/%d')
    df['支出金額'] = df['支出金額'].astype(int)

    # この項目と金額をラインから取ってくる
    item = contents.split('/')[1]
    money = int(contents.split('/')[2])
    df = df.append({'日付': date, '支出品目': item, '支出金額': money}, ignore_index=True)

    # ワークシート にアップデート
    worksheet1.update([df.columns.values.tolist()] + df.values.tolist())

# 手持ち現金の登録
def input_balance(contents):
    worksheet3 = auth()[2]
    worksheet3.cell(2, 1).value
    balance = int(contents.split('/')[1])
    worksheet3.update_cell(2, 1, balance)
    
# 集計データ(残高)の出力
def output():
    worksheet2 = auth()[1]
    data2 = worksheet2.get_all_values()
    df2 = pd.DataFrame(data2[1:])
    df2.columns = data2[0]
    df2 = df2.iloc[[32, 35, 37, 38, 39, 40, 41, 42, 43], :2]
    food = df2['金額'].values[1]
    free = df2['金額'].values[2]
    clothes = df2['金額'].values[3]
    rice= df2['金額'].values[4]
    education = df2['金額'].values[5]
    tobaco = df2['金額'].values[6]
    cash = df2['金額'].values[7]
    next_month = df2['金額'].values[8]
    text = f'現金残は、{cash}円です。\n食費残は、{food}、\n被服費残は{clothes}円、\n教育費残は{education}円、\nタバコ代残は{tobaco}円、\n自由に使える金額は{free}円です。\n繰り越しは{next_month}円です'
    return text


app = Flask(__name__)

line_bot_api = LineBotApi('Messaging api のChannel access token')
handler = WebhookHandler('Messaging apiのChannel secret')


# wewbhookを行うための設定
@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        print("Invalid signature. Please check your channel access token/channel secret.")
        abort(400)

    return 'OK'

# チャットボットの動きを設定
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    # 「入力/項目/金額」の形で入力すると家計簿に項目と金額を記載する関数を実行
    if event.message.text[:2] == '入力':
        input_accountbook(event.message.text)
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text='入力完了しました'))
    # 「現金/金額」の形で入力すると家計簿に現金残高を記載する関数を実行
    elif event.message.text[:2] == '現金':
        input_balance(event.message.text)
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text='入力完了しました'))
    # 「残高」と入力すると主要項目の残高一覧を表示
    elif event.message.text[:2] == '残高':
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text=output()))
    # 上記以外の項目を入力すると入力方法を伝えるメッセージを表示
    else:
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text='コメントは「入力/項目/金額」、「現金/金額」、また、「残高」のように入力してください'))



# herokuで動作させるように変更している
if __name__ == "__main__":
    port = os.getenv("PORT")
    app.run(host="0.0.0.0", port=port)