kakeibo-memo: LINE Flex 月次サマリ調査

調査のみ。kakeibo-memo への実装 PR なし。本番 LINE 送信なし。金額は合成例。個人の支出実額・家族の実名・チャネル鍵・.env は載せない。

job 0028 repo hayashiroto/kakeibo-memo @ 3e36f0c read src/ docs/ + LINE送信経路 既存: Flex 月次サマリ(支払い方法別横棒) src/: LINE送信 未実装 docs/仕様書.md: Echo Bot のまま(古い)
結論。 スクショ契約(白バブル / 緑タイトル「YYYY年M月サマリ」 / サブ「支払い方法別」 / 太字「総支出: ¥…」 / 横棒=ラベル・%・金額)は、すでに amplify/function/line-webhook の LINE Flex Message として実装されている。 src/ は Cognito 管理画面であり、Flex を組み立てて LINE へ送る処理は無い。 後続で見た目を触るなら差し込み点は amplify/function/line-webhook/service/messageBuilder.tscreateMonthlySummaryMessage。新規機能を足す必要は、この調査範囲では見当たらない。

1. スクショ契約と既存コードの対応

LINE bubble mock / dummy yen
2026年9月サマリ
支払い方法別
総支出: ¥48,000
現金 (40%)¥19,200
クレジットカード (35%)¥16,800
電子マネー (25%)¥12,000

左は契約レイアウトの合成モック。金額・支払い方法名はダミー。実データ・家族名は使っていない。

契約 既存 根拠
白いバブル 既存 messageBuilder.ts createMonthlySummaryMessagetype: "bubble"
緑タイトル YYYY年M月サマリ 既存 ${year}年${month}月サマリ / color: "#1DB446"
サブ「支払い方法別」 既存 groupBy === 'payment' ? "支払い方法別" : "タイプ別"
太字 総支出: ¥… 既存 総支出: ¥${totalAmount.toLocaleString()} / weight: "bold"
横棒(ラベル・%・金額) 既存 行テキスト name (percentage%) + 幅 ${percentage}% の box
LINE Flex 相当 既存 戻り値 type: "flex"。送信は messageSender.tsreplyMessage

2. 既存の送り方(呼び出し経路)

ユーザーが LINE で「サマリ」と送ると、Webhook が Flex を Reply API で返す。Push / 定期配信の専用関数は src/ にも docs/ にも無い。

  1. amplify/function/line-webhook/handler.tsX-Line-Signature を検証し、text / postback を処理する。
  2. 本文 サマリMessageBuilder.createSummarySelectionMessage()(カルーセル。月別 / 年別 × 支払い方法別 / タイプ別)。
  3. postback summary_month_payment → 状態 WAITING_SUMMARY_MONTH_SELECTION + 月選択 Flex。
  4. 本文 YYYY年M月TransactionService.getMonthlySummary(ownerID, year, month, "payment")
  5. MessageBuilder.createMonthlySummaryMessage(...) がスクショ形の Flex を組み立てる。
  6. replyMessage(client, replyToken, [flex]) が LINE Messaging API の Reply に載せる。
送信の一点: amplify/function/line-webhook/service/messageSender.ts → messagingApi.MessagingApiClient.replyMessage

チャネルトークンは環境変数名 LINE_CHANNEL_ACCESS_TOKEN だけがコード上に出る。値は書いていない。

集計

getMonthlySummaryLKM-Transaction を年月で取り、支払い方法 ID または費目 ID で合算する。ラベルは LKM-PaymentMethod / LKM-Typename。金額降順。月はゼロ埋めする。

amplify/function/line-webhook/service/transactionService.ts :: getMonthlySummary

3. src/ と docs/ の証拠

パス 判定 メモ
src/App.tsx LINE Flex 未実装 Cognito 管理画面。LINE連携と取引管理だけ。
src/components/LineLinkage.tsx 送信なし Cognito ↔ LINE ID の紐付け UI。getLinkStatus / linkLineUser
src/components/TransactionList.tsx Web のみ既存 MonthlyBarGraph が「支払い方法別」横棒を描く。LINE には送らない。
src/components/TransactionImporter.tsx 無関係 PayPay CSV 取込。
src/utils/csvParser.ts 無関係 列名「取引日」「取引先」「出金金額(円)」。
src/client.ts 無関係 Amplify Data クライアント生成のみ。
README.md 文書あり 「Flex Message」「サマリ=今月の合計と支払い方法別内訳」と書いてある。実装本体は amplify。
docs/仕様書.md 未記載 / 古い Echo Bot(受け取ったテキストを返す)のまま。Flex / サマリ / 横棒は無い。
docs/📗line-id連携.md 送信なし LINE ID 取得と Cognito 連携。グラフ送信の話は無い。
docs/📗ショートカットで登録する.md 登録フローのみ ショートカットと対話登録。完了文に「今月の合計」とあるが Flex グラフではない。
docs/📗家計簿のpaypay同期を簡単にする.md Web サマリ要求 フロントの月次サマリ(費目別・支払い方法別)を依頼した記録。LINE Flex ではない。
docs/LKM-PaymentMethod.csv スキーマのみ使用 列は id,name,ownerID。公開成果には実名ラベルを載せない。
docs/LKM-Type.csv スキーマのみ使用 列は id,name,ownerID。費目名の例(食費 / 外食 / その他)はマスタ種別名。
docs/LKM-Transaction-2025-12.csv 実額あり → 非掲載 列構造の確認だけ。金額・メモは公開 HTML に出さない。

4. 差し込み点(実装しない。触るならここ)

スクショ形は既にある。後続 Job でレイアウトや集計を変える場合の最小地点:

目的 ファイル 関数
バブル見た目・棒の色 / 幅 amplify/function/line-webhook/service/messageBuilder.ts createMonthlySummaryMessage
支払い方法別の合算 amplify/function/line-webhook/service/transactionService.ts getMonthlySummary(..., "payment")
「サマリ」コマンドと月選択 amplify/function/line-webhook/handler.ts processMessageEvent / processPostbackEvent
Reply 送信 amplify/function/line-webhook/service/messageSender.ts replyMessage
Web の横棒(LINE ではない) src/components/TransactionList.tsx MonthlyBarGraph

createSummaryMessage(タイトル「サマリレポート」)も同ファイルにあるが、handler からの呼び出しは見当たらない。現行のスクショ形は createMonthlySummaryMessage

年次は createYearlySummaryMessage(積み上げ縦棒 + 凡例)。契約の「月次 + 支払い方法別横棒」とは別。

5. Flex JSON 骨格(ダミー金額)

createMonthlySummaryMessage("2026", "9", "payment", 48000, ...) 相当。色配列の先頭 3 色を使用。

{
  "type": "flex",
  "altText": "2026年9月サマリ",
  "contents": {
    "type": "bubble",
    "header": {
      "type": "box",
      "layout": "vertical",
      "contents": [
        {
          "type": "text",
          "text": "2026年9月サマリ",
          "weight": "bold",
          "size": "xl",
          "color": "#1DB446"
        },
        {
          "type": "text",
          "text": "支払い方法別",
          "size": "xs",
          "color": "#aaaaaa"
        },
        {
          "type": "text",
          "text": "総支出: ¥48,000",
          "size": "lg",
          "weight": "bold",
          "margin": "md"
        }
      ]
    },
    "body": {
      "type": "box",
      "layout": "vertical",
      "contents": [
        {
          "type": "box",
          "layout": "horizontal",
          "margin": "md",
          "contents": [
            { "type": "text", "text": "現金 (40%)", "size": "sm", "color": "#555555", "flex": 1 },
            { "type": "text", "text": "¥19,200", "size": "sm", "color": "#111111", "align": "end", "flex": 1 }
          ]
        },
        {
          "type": "box",
          "layout": "vertical",
          "margin": "xs",
          "contents": [
            {
              "type": "box",
              "layout": "horizontal",
              "backgroundColor": "#f0f0f0",
              "cornerRadius": "2px",
              "height": "6px",
              "width": "100%",
              "contents": [
                {
                  "type": "box",
                  "layout": "vertical",
                  "width": "40%",
                  "height": "6px",
                  "backgroundColor": "#FF6384",
                  "cornerRadius": "2px",
                  "contents": []
                }
              ]
            }
          ]
        }
      ]
    }
  }
}

6. 未実装(根拠つき。捏造しない)

7. 調査範囲と除外