マキモノ
Web開発無料✅ 公式検証済みv1.0.0 / 更新

Square の決済データを月次集計して Next.js のトップに売上ダッシュボードを出す

Square Payments API をページングして JST で月次集計(COMPLETED・返金控除)、30分キャッシュ+stale フォールバックの API、スマホ向け進捗カードと月別表。生成AIが実際に出したバグ2件のレビュー観点と本番検証手順つき

出品者: nishi@orgiast.jp📖 読込 約2,360トークン (約4円)💰 コスパ 17倍
トークン節約メーター89%節約
ゼロからAIに作らせた場合約4.5万トークン
このMDを読ませた場合約5,000トークン

約4万トークンの節約 (API料金換算で約60円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。

この巻物について

「Square の決済データを月次集計して Next.js のトップに売上ダッシュボードを出す」は、Web開発カテゴリのAI指示書(MDファイル)です。Square Payments API をページングして JST で月次集計(COMPLETED・返金控除)、30分キャッシュ+stale フォールバックの API、スマホ向け進捗カードと月別表。生成AIが実際に出したバグ2件のレビュー観点と本番検証手順つきこの巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約4万トークン(API料金換算で約60円)・89%のトークンを節約できます。

カテゴリ
Web開発
対応AI
claude-code、cursor、codex-cli
ライセンス
商用利用可 (再販不可)
価格
無料
ゼロから開発時
約4.5万トークン
この巻物使用時
約5,000トークン
節約量
約4万トークン (約60円)
更新日
2026-10-09

使い方 (AIに渡す3つの方法)

いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。

⬇ .md をダウンロード
claude "https://makimono-md.vercel.app/api/v1/files/square-next-js/raw を読み込んで、この指示書どおりに実装して"
claude-codecursorcodex-cliライセンス: 商用利用可 (再販不可)

中身

Square の決済データを月次集計して Next.js のトップに売上ダッシュボードを出す

店舗の Square(POS)に溜まっている決済データから、「直近 N ヶ月の売上・会計件数・客単価・営業日数の表」と「今月の進捗(累計・先月同日比・1日ペース・着地見込み)」を Next.js(App Router)のトップページに表示する手順。日報や手入力に頼らず、レジの数字だけで初日から表が埋まる。

対象: Next.js 14 App Router / Node.js 20 以上 / Square Payments API。外部ライブラリは不要。

前提

  • Square の Production Access Token を環境変数 SQUARE_ACCESS_TOKEN に設定済み(Developer Dashboard の自アプリから発行。claude.ai 等の Square コネクタ承認では代替できない)。
  • SQUARE_LOCATION_ID を設定済み(無ければ /v2/locations の ACTIVE な 1 件目を使う)。
  • 任意: SQUARE_API_BASE(既定 https://connect.squareup.com)、SQUARE_API_VERSION(既定 2025-01-23)。

構成(3 ファイル + 1 行)

  1. lib/square-monthly.js … 取得と集計(純粋関数 aggregatePayments と、API を叩く fetchSquareMonthlySummary)
  2. app/api/dashboard/route.js … 30 分のメモリキャッシュ付き GET。Square 障害時は前回値を stale:true で返す
  3. app/sales-dashboard.js + app/sales-dashboard.css … クライアントコンポーネント。マウント時に /api/dashboard を 1 回 fetch
  4. トップページのコンポーネントに <SalesDashboard /> を 1 行足す(ボタン類より上に置くと売上を先に意識できる)

1. 集計ロジックの要点(ここを間違えると数字がズレる)

  • status === "COMPLETED" だけ数える。CANCELED / FAILED は除外。
  • 金額は amount_money.amount − refunded_money.amount(チップを含む total_money は使わない。返金は差し引く)。JPY は最小単位が円なので割らない。通貨が JPY 以外の行は無視。
  • 月の判定は created_at(UTC)を JST に直してから。Date.parse(created_at) + 9*60*60*1000 を UTC メソッド(getUTCFullYear/getUTCMonth/getUTCDate)で読む。new Date() のローカルタイムゾーンに依存させない(Vercel は UTC)。
  • 対象月は「今月を含めて直近 N ヶ月」。決済が無い月も 0 件で含める(表の行が消えると見づらい)。
  • 各月: { month:"2026-10", label:"10月", sales, count, avgSpend: round(sales/count) か null, salesDays: 決済があった日数 }。
  • 今月の進捗: daysElapsed(今日の日)、daysInMonth、pace = round(sales/daysElapsed)、forecast = round(pace×daysInMonth)、prevMonthSales、prevMonthSameDaySales(先月 1 日〜同じ日まで。先月にその日が無ければ月末まで)、prevMonthSameDayRate = round(sales/prevMonthSameDaySales×100)。
  • 0 と null を区別し、ゼロ除算をしない。

生成 AI に書かせた場合に実際に出たバグ 2 件(レビューで必ず見る)

  • 先月の末日を Date.UTC(prev.year, prev.month, 0) で出す式で、prev.year が未定義・prev.month が "2026-09" 文字列だった → NaN になり先月同日比が常に 0。月情報には year と monthIndex(0 始まり)を数値で持たせ、Date.UTC(year, monthIndex + 1, 0).getUTCDate() で末日を取る。
  • AbortController の 10 秒タイムアウトをページング全体で 1 つ共有していた → 件数が多いと途中で abort。1 リクエストごとに new AbortController() を作り、finally で clearTimeout。

2. Square Payments API の取り方

GET {apiBase}/v2/payments?location_id=...&begin_time=...&end_time=...&limit=100&sort_order=ASC[&cursor=...]
Headers: Authorization: Bearer <token>, Square-Version: <version>
  • begin_time は対象の最初の月の YYYY-MM-01T00:00:00+09:00、end_time は現在時刻(RFC3339)。
  • レスポンスの cursor が無くなるまで繰り返す。暴走防止に最大 300 ページで打ち切る。
  • 6 ヶ月・約 1,000 件なら 11 リクエスト程度、数秒で終わる。
  • 失敗は { ok:false, configured:true, error:"Square の取得に失敗しました (<status>)" } の形で返し、例外も同じ形に畳む。未設定なら { ok:false, configured:false }。

3. API ルート(キャッシュと stale フォールバック)

  • export const dynamic = "force-dynamic"; にして毎回ハンドラを通し、キャッシュはモジュール変数の Map に持つ(キー = months、TTL 30 分)。
  • 有効キャッシュがあれば cached:true を付けて返す。
  • 取得に失敗したらキャッシュに入れず、古いキャッシュがあれば stale:true を付けて返す(Square が一時的に落ちても表が消えない)。
  • 常に Cache-Control: no-store。configured:false も 200 で返し、画面側で「未設定」を出す。
  • ?months=1..12(既定 6、範囲外は 6)。

4. 画面

  • "use client"。初回レンダーは「読み込み中」、useEffect で fetch。日付・金額の整形は取得後のデータにだけ行う(SSR とのずれを避ける)。
  • 今月の進捗カード: KPI 4 つ(今月の売上+先月同日比/着地見込み+1 日ペース/会計件数+客単価/先月の売上+先月同日まで)と、先月売上に対する進捗バー(100% 超はバー幅を 100% で止め、文字は実数)。
  • 月別の表: 月/売上/会計件数/客単価/営業日数。今月の行を強調。
  • 脚注に「Square の決済データから集計(チップ・返金を除く)。更新: HH:MM」。stale なら「前回取得した数字を表示しています」。
  • スマホ幅(360〜390px)優先。th と月名の列に white-space: nowrap、KPI の値に font-variant-numeric: tabular-nums。

5. テストと本番検証

  • node:test で aggregatePayments を直接テストする。最低限: 空配列で N 要素が 0 件で並ぶ/UTC→JST の月またぎ(2026-09-30T15:30:00Z は 10 月)/返金の控除/CANCELED と USD の除外/先月同日比の数値例/avgSpend と salesDays。
  • 本番検証は 2 段: GET /api/dashboard?v=<乱数> の JSON で ok:true と月数を見る → 実ブラウザ(playwright-core + ローカル Chrome)で .dash-table tbody tr の行数と getComputedStyle の display を見て CSS の適用まで確認。HTML を grep しても出ない(クライアント描画)。
  • Vercel と GitHub が連携されていないプロジェクトでは git push でデプロイが走らない。CLI の vercel deploy --prod --yes を使い、vercel ls の Age が更新されたことを見る。

同時にやると良いこと

  • Discord Webhook へ通知しているなら、送信関数の出口で content: "@here" と allowed_mentions: { parse: ["everyone"] } を全 payload に一括付与する。embed だけの投稿は通知が飛ばず見落とされる。payload ごとに書かず、送信点 1 か所で付けると経路が増えても漏れない。

よくある質問

+「Square の決済データを月次集計して Next.js のトップに売上ダッシュボードを出す」とは何ですか?

Square Payments API をページングして JST で月次集計(COMPLETED・返金控除)、30分キャッシュ+stale フォールバックの API、スマホ向け進捗カードと月別表。生成AIが実際に出したバグ2件のレビュー観点と本番検証手順つき

+どれくらいトークン(費用)を節約できますか?

ゼロから開発すると約4.5万トークンかかりますが、この巻物を使えば約5,000トークンで済みます。差し引き約4万トークン(API料金換算で約60円)・89%の節約です。

+どうやって使いますか?

無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。

+どのAIツールに対応していますか?

claude-code、cursor、codex-cli に対応しています。

+商用利用できますか?

ライセンスは「商用利用可 (再販不可)」です。

🤝 自分でAIを動かすのは、まだ不安…という方へ

この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。

AI代行堂を見る →

関連する巻物

この巻物、誰かのトークンも救えます

𝕏 で節約レシートをシェア