店舗ごとの月次レポート作成を自動化する|20店舗分のPDFを一括生成する構成と、続けられる運用の作り方
店舗ごとの月次レポート作成を自動化する|20店舗分のPDFを一括生成する構成と、続けられる運用の作り方
月末が近づくと、店舗ごとの売上レポートを1枚ずつ作って配る作業が待っている。店舗数が5を超えたあたりから、この作業は「ちょっと面倒」から「毎月の固定業務」に変わります。
結論から書きます。多店舗の月次レポートを自動化するなら、集計データを1か所のデータベースに置き、画面で見ている印刷用ページをそのままサーバー側で一括PDF化する構成が正解です。レポートを作る仕組みとPDFを出す仕組みを別に持たない。これだけで、店舗が増えても作業量は増えなくなります。
名古屋のカラー専門サロンFC(20店舗)の本部向けに、この構成で毎月の配布物を出しています。現在の実測は、20店舗×3種類=60枚のPDFを約1分で生成、失敗0。以前は1店舗ずつ画面を開いて出力していた作業です。
ただし、全部が自動になるわけではありません。元データの取り出しと配布は人の作業として残ります。この記事では、構成の要点、自動化できる範囲とできない範囲、そして毎月止まらずに回すための運用の作り方を書きます。
月次レポート自動化の正しい形|画面とPDFを分けない
月次レポートの自動化でよくある設計は、「集計はスプレッドシート、PDFは別のテンプレートで生成」という二層構造です。これは最初は動きますが、項目を1つ足すたびに2か所を直すことになり、数か月で画面とPDFの内容がずれます。
正しい形は3層で、上から下へ一方通行です。
- データ投入: 各店の集計値を1つのデータベースに入れる。店舗×年月をキーにする
- 画面: 店舗を選ぶと最新月のレポートが表示される。印刷用のCSSを持たせておく
- PDF出力: サーバー側のヘッドレスブラウザ(画面を持たないブラウザ)が、その画面を全店舗ぶん順番に開いてPDFにし、ZIPにまとめる
ポイントは、3層目が2層目を「印刷している」だけという点です。PDF専用のテンプレートを持たないので、画面を直せばPDFも直ります。配布物の見た目が、本部の担当者が普段見ている画面と同じになるのも、受け取る店舗オーナーにとって分かりやすい。
実例|20店舗×3種のPDFを毎月配るFC本部
対象は、名古屋を中心に20店舗を展開するカラー専門サロンFCの本部です。毎月、各店のオーナーに次の3種類をPDFで配っています。
| 種類 | 内容 | 1店あたりのページ数 |
|---|---|---|
| 顧客区分別 | 新規・リピートなど区分ごとの売上と客数の月次推移 | 2〜3ページ |
| 技術売上 | メニュー分類ごとの売上明細と月別合計 | 1〜2ページ |
| AIレビュー | 自店の推移をもとにした講評と来月の具体策 | 5〜8ページ |
以前の運用は、担当者が自分のパソコンで店舗を1つずつ選び、タブを切り替え、印刷してPDFに保存する方法でした。18店舗の頃で54枚。店舗が増えて60枚になった月に、ボタン1つで全店ぶんを出す構成に切り替えました。
切り替え後の実測です。
| 項目 | 実測 |
|---|---|
| 生成枚数 | 60枚(20店舗×3種) |
| 所要時間 | 63秒 |
| 失敗 | 0 |
| 用紙 | A4縦・全枚数で統一 |
| PDF合計 | 約73MB |
| 配布用ZIP | 約33MB(フォルダごと圧縮) |
ファイル名は「店舗名_種類_年月.pdf」で、以前に手作業で配っていたものと完全に同じにしました。受け取る側から見れば、作り方が変わったことは分かりません。ここは意図的にそうしています。配布物の見た目や名前が変わると、オーナーから「今月は違うものが来た」と問い合わせが入り、本部の手間がかえって増えるためです。
構成の要点|サーバー側で「画面を印刷する」設計
一括PDF化を安定させるために決めた点を5つ挙げます。どれも最初から入れておくと後で困らないものです。
1. ログイン画面を操作せず、認証情報を直接渡す
ヘッドレスブラウザに管理者のログイン画面を操作させると、パスワード変更や画面の変更で止まります。代わりに、サーバー内で管理者用の認証トークンを発行し、ブラウザのCookieに直接入れてからレポート画面を開きます。ログイン画面は一切通りません。
2. 店舗ごとに縮尺を自動で決める
横切れは、一括PDFで最も起きやすい不良です。20か月分の列がある既存店と、開店したばかりの新店では表の横幅が大きく違います。全店に同じ縮尺をかけると、新店は小さすぎ、既存店は右端が切れます。
対策は、印刷幅に対する表の最大幅から縮尺を店舗ごとに計算することです。実測では、20か月ある店が0.54〜0.60、12か月の店が0.89、新店は1.0になりました。下限を0.4に置き、それより小さくなる場合は列数の見直しが必要と判断します。合わせて、カード単位で「途中で改ページしない」指定を入れると、表が2ページにまたがって読めなくなる事故を防げます。文字が切れて消える不良の検出方法は、HTMLから作ったPDFで文字が切れて消えるときで詳しく書いています。
3. 表示月が要求した月と一致しなければ、その店をエラーにする
画面は「最新月」を表示する仕組みなので、ある店だけ当月のデータ投入が漏れていると、前月のレポートが当月の名前で出力されてしまいます。これを防ぐため、PDF化の直前に画面の表の最終列と「最新月」の表示を読み取り、要求した年月と違えばその店をエラー扱いにして先へ進みます。「60枚出た」ではなく「60枚とも当月である」を機械で確かめる部分です。
4. 自動実行ではなく、ボタン実行にする
毎月決まった日時に自動で走らせる設計にはしていません。本部の担当者が「内容を見てから出したい」と決めたためです。データ投入の翌日にレビューの中身を確認し、問題なければ管理画面のボタンを押す。押すと「出力中 3/20」のように進み、完了すると「ZIPをダウンロード」に変わります。
同時に走らせられるジョブは1つに制限しています。2人が同時に押しても、後の1人には「実行中」と返るだけで、二重に生成されることはありません。
5. 生成器を1つにして、画面のボタンとコマンドの両方から呼ぶ
管理画面のボタンと、サーバー上で直接叩けるコマンドは、同じ生成処理を呼んでいます。画面が使えないときや、特定の店舗だけ出し直したいときに、コマンド側で店舗名を指定して再出力できます。生成器を分けると、ボタンとコマンドで結果が微妙に違うという状態になりやすいので、1つにまとめます。
自動化できる範囲と、人が残る範囲
多店舗の月次レポートで「完全自動」は、ほとんどの場合成立しません。理由は元データにあります。
各店の売上データは、店舗ごとに導入している管理システムから出します。この手のシステムは、自動ログインを不正アクセスとして検知する仕組みを強めているものが多く、ログインを自動化する行為自体が利用規約に触れる場合があります。ここは人が各店のIDでログインして、エクスポートするしかありません。
今回の実例で、毎月の流れは次のようになっています。
| 工程 | 担当 | 目安 |
|---|---|---|
| 各店の管理システムから月次データをエクスポート(20店で41ファイル) | 人 | 手作業 |
| 決まったフォルダに置く | 人 | 手作業 |
| ファイルを変換し、データベースへ投入、投入後の突合 | 仕組み | 数分 |
| AIレビューを全店ぶん生成 | 仕組み | 1店約2分半、20店で約50分 |
| 内容を確認して一括PDFボタンを押す | 人 | 約1分 |
| ZIPを展開し、各オーナーへ配布 | 人 | 手作業 |
自動化されているのは「投入後からZIPまで」です。それでも、以前は1店ずつ開いて出力していた作業が1分になり、月次の負担は元データの取り出しと配布だけになりました。
AIレビューの生成に50分かかるのは、1店ごとに直近6か月の推移と前月のレビュー本文を読み込み、前月に挙げた課題がクリアされたかを判定してから書かせているためです。時間はかかりますが、ここを短くするために前月分を渡さないと、毎月同じ講評が出るレポートになります。レビューの評価軸は他店との比較ではなく、自店の推移です。順位や店舗間のランキングは一切書かせていません。順位を出すと、単価の高い店への評価に偏るためです。
続けられる運用の作り方|毎月止まる要因を先につぶす
仕組みができても、月次で回すと必ずどこかで止まります。止まる要因はだいたい決まっているので、先に対処を入れておきます。
投入後は必ず「合計と明細」を突き合わせる
データを投入するスクリプトが「528件インポートしました」と成功を返しても、データベースには523件しか入っていない、ということが起こりえます。店舗×年月×商品コードを一意のキーにしていると、同じ商品コードが別の分類に再掲されたときに後から来た行が前の行を上書きし、5行・97,500円ぶんの明細が静かに消えます。更新も「1件処理」と数えるので、件数の報告は正常に見えます。
対策は2つです。投入後に、合計シートの金額・件数と明細の金額・件数を必ず突合すること。そして同じコードが複数の分類に出た場合は、変換の段階で2件目以降に分類コードを付けて別のキーにすること。「成功と出ているのに反映されていない」の見つけ方は、自動処理が「成功」と出ているのに反映されないときにまとめています。
フォルダ名は「対象月」で統一する
月次の納品フォルダは「2608」のように月で切ることが多いですが、これが「作った月」なのか「対象月」なのかを決めていないと、7月分のレポートが8月のフォルダに入り、翌月に「先月分が無い」と探し回ることになります。対象月で統一し、ファイル名にも「_2026-08」のように対象月を入れておく。フォルダと中身が食い違ったときは、ファイル名の月を真とします。
店舗マスタの表記ゆれを最初に消す
店舗名に半角スペースが1つ入っているだけで、レビューの照合が毎月外れ、その店だけ「未生成」と表示され続けることがあります。店舗マスタを作る時点で、前後と中間の空白、全角半角、「店」の有無をそろえておきます。1店だけ毎月手で直す運用は、担当者が変わった月に必ず抜けます。
新店が増えたときの手順を書いておく
多店舗の仕組みは、店舗が増えた月に壊れます。今回の構成でも、新店を1つ足すには「店舗マスタへの登録」「レビュー生成の店舗対応表への追加」「口コミ集計側での有効化」の3か所を触る必要があります。どれか1つ漏れると、その店だけレポートが出ない、あるいは前月のものが出る。新店追加のチェックリストを、レポートの手順書の中に置いておきます。
有効期限のあるデータは直前に取り直す
口コミ状況のレポートに載せる検索順位のように、計測結果が30日で自動的に消える仕様のデータがあります。前月に測った値をそのまま使うつもりでいると、翌月のレポートで順位欄が空になります。期限のあるデータは、レポート生成の直前に再計測する工程を手順に組み込みます。
出力物と一時データの掃除を決めておく
一括PDFは毎月70MB前後、生成物が増えます。サーバーのディスクは有限なので、何か月分残すかを最初に決めておきます。また、ジョブの進捗をメモリで持つ設計にすると、サーバー再起動のタイミングで進捗表示が消えます。生成済みのPDFはディスクに残るので実害はありませんが、「再起動したら進捗が消えるが、ファイルは残っている」と手順書に書いておかないと、担当者がもう一度押して二重に生成します。
目視は抜き取り、全数は機械で
60枚を毎月全部目で見るのは続きません。全数は機械で確かめる項目に絞ります。用紙サイズがA4縦か、ページ数が想定の範囲か、対象月の文言が全ページにあるか。目視は既存店・新店・特徴のある店の3枚程度に絞り、横切れと白紙ページの有無だけを見ます。
店舗数別の始め方
すべての規模で一括生成の仕組みが要るわけではありません。
- 1〜3店舗: 印刷用CSSを整えた画面を用意し、ブラウザの印刷機能でPDFにする。仕組みを作るより、印刷レイアウトを整える方が効きます
- 5〜10店舗: 店舗ごとの出力を1本のスクリプトにまとめる。この段階で、ファイル名とフォルダの規則、投入後の突合を決めておくと、その先が楽になります
- 10店舗以上・FC本部: 本記事の構成。データベース、印刷用の画面、サーバー側の一括PDF化、ボタン実行と進捗表示まで揃えます
どの規模でも共通するのは、「レポートを作る仕組み」と「PDFを出す仕組み」を別に持たないことです。
まとめ
- 多店舗の月次レポートは、集計データを1か所に置き、画面と同じ印刷用ページをサーバー側で一括PDF化する構成が正解。20店舗×3種=60枚を約1分で生成できる
- 認証は直接渡す、縮尺は店舗ごとに自動計算、表示月の一致を機械で検証、ボタン実行で同時1ジョブ。この4点で安定する
- 元データの取り出しと配布は人の作業として残る。自動化できるのは投入後からZIPまで
- 止まる要因は先につぶす。投入後の突合、対象月でのフォルダ統一、店舗マスタの表記ゆれ、新店追加のチェックリスト、期限付きデータの再取得、出力物の掃除
graciautoでは、多店舗の売上ポータルと月次レポートの一括生成を、データ投入からPDF配布までの運用設計込みで構築しています。店舗が増えるたびに作業が増えている状態であれば、まずどの工程に時間がかかっているかを洗い出すところから始めます。