Square の決済データを月次集計して Next.js のトップに売上ダッシュボードを出す
Square Payments API をページングして JST で月次集計(COMPLETED・返金控除)、30分キャッシュ+stale フォールバックの API、スマホ向け進捗カードと月別表。生成AIが実際に出したバグ2件のレビュー観点と本番検証手順つき
約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 のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/square-next-js/raw を読み込んで、この指示書どおりに実装して"
中身
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 行)
lib/square-monthly.js… 取得と集計(純粋関数aggregatePaymentsと、API を叩くfetchSquareMonthlySummary)app/api/dashboard/route.js… 30 分のメモリキャッシュ付き GET。Square 障害時は前回値をstale:trueで返すapp/sales-dashboard.js+app/sales-dashboard.css… クライアントコンポーネント。マウント時に/api/dashboardを 1 回 fetch- トップページのコンポーネントに
<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で頼むだけで、仕事が完成」。
関連する巻物
Next.js + Supabase + Vercel 立ち上げ完全自動化MD
新規Webサービスの立ち上げ (GCP/GitHub/Vercel/Supabase のプロジェクト作成〜環境変数〜本番デプロイ) を AI に一気通貫でやらせる指示書。人間の作業はログイン1回だけ。
投稿の審査キューを「信頼済みだけ自動公開」で捌く設計(なりすまし穴つき)
審査キューに投稿が溜まったまま埋もれる問題を、信頼済み投稿だけ即公開する形で潰す指示書。無検証のキー発行を信頼判定に使うと第三者が自社メールを騙れる穴と、サーバレスで静的公開棚に実行時公開を足す方法、検証10項目まで含む。
DB型サイトを「一覧だけ会員限定・個別ページは残す」に切り替える指示書(Next.js App Router)
自社DBで集客していたサイトが競合のリスト抜き取りに気づいた時の改修手順。名前が並ぶバルクな一覧だけを会員限定にし、個別ページはtitle/H1とCTAを残す。ItemList JSON-LDやsitemapの漏れ、force-dynamic化のコスト副作用、Layer1(HTML)+Layer2(Playwright実描画)の受け入れテストまで含む。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア