発注フォームの単価をマスタと画面の2か所で持たない|片方だけ直して金額がずれる構造と、単価も配送区分もマスタ1本から画面へ渡す作りへ移す手順
発注フォームの単価をマスタと画面の2か所で持たない|片方だけ直して金額がずれる構造と、単価も配送区分もマスタ1本から画面へ渡す作りへ移す手順
【この記事でわかること】
- 単価を「マスタ」と「画面のプログラム」の2か所に持つと、なぜ金額がずれるのか
- 単価と配送区分をマスタ1本から画面へ渡す作りへ、止めずに移す手順
- 移したあとに確かめる項目と、次に商品を足すときに楽になる点
店舗や本部で使う発注フォームを自作していると、「商品の一覧はスプレッドシートの商品マスタにあるのに、画面に出す単価はプログラムの中に書いてある」という状態になりがちです。最初は困りません。商品が数十点で、単価もめったに変わらないからです。
先に結論を書きます。単価の正本は商品マスタ1か所に決め、画面はマスタから渡された値を表示するだけにしてください。 具体的には次の3点です。
- マスタから画面へ、商品ごとに単価と配送区分を渡す(画面側に価格表を持たない)
- 画面側は「渡された値を優先し、無ければ旧来の価格表」で読む(移行中も止まらない)
- 配送区分(どの仕入先の便か・送料判定に入れるか)もマスタ側の列から決める
「単価を変えるときはマスタとプログラムの両方を直す」という運用ルールは、作った直後の暫定策としては成り立ちます。ただ、ルールで守っている二重管理は、担当が変わった日や急ぎの日に必ず片方が漏れます。漏れたときに困るのは、実際に発注する店舗の側です。
弊社は名古屋でホームページ制作と店舗の業務自動化を行っており、名古屋の美容サロンFC(25店舗)の本部向けに、スマホから開ける発注フォームを作って運用しています。この記事では、そのフォームで単価の二重管理をやめた手順を整理します。
実例:25店舗の発注フォームで単価が2か所にあった構成
題材にするのは、次の構成の発注フォームです。
| 部品 | 役割 |
|---|---|
| 商品マスタ(Googleスプレッドシート) | 品番・商品名・発注単位・仕入先・税込単価などを1行1商品で管理 |
| フォーム本体(Google Apps Script) | 商品マスタを読んで商品一覧を組み立て、注文を受け付けてメールと記録を残す |
| 中継ページ(自社ドメインのPHP) | 店舗が実際に開くURL。フォーム本体を読み込み、金額の計算と送料の表示を足す |
店舗の画面では、商品ごとの税込単価、選んだ数量の小計、仕入先ごとの合計、そして「送料無料/送料必要」の表示が出ます。仕入先の一方は税抜3万円以上で送料無料、もう一方は常に送料無料、というルールでした。
この金額表示は、最初は中継ページの中に商品コードごとの価格表(36品分)を書いて実装しました。単価はすでに商品マスタにも入っているので、同じ数字が2か所にある状態です。そこで、運用ルールとして「単価を変えるときは、商品マスタの単価列と、中継ページの価格表の両方を更新する」と決めていました。
2か所に持つと何がずれるのか
この状態で起こりうることは、次の3つです。
- マスタだけ直した:画面には古い単価が出続け、店舗は古い金額で合計と送料を判断する
- 画面だけ直した:画面の金額は新しいが、マスタを見て集計する側(本部の確認や請求の突き合わせ)が古い単価のまま
- 商品を追加したのに価格表に足していない:その商品だけ単価と小計が出ず、送料判定の合計にも入らない
3つ目は見落としやすい点です。実例のフォームでは、仕入先の一方にカラー剤を6色追加したとき、商品マスタへの6行追加に加えて、中継ページの価格表にも6行足す作業が必要になりました。商品を足すたびに2か所を触る作りは、商品点数が増えるほど漏れやすくなります。
送料判定にずれが入ると影響はさらに大きくなります。「税抜3万円を超えたから送料無料」と画面が表示していても、その合計が古い単価で計算されていれば、実際には送料がかかる注文になりえます。店舗は画面を信じて発注するので、画面の金額が正本とずれていること自体がリスクです。
正しい作り:マスタから画面へ「単価」と「配送区分」を渡す
二重管理をやめるには、画面側から価格表をなくし、マスタの値を商品ごとに画面へ渡します。実例では次のようにしました。
1. フォーム本体が、商品の行ごとに単価と配送区分を出す
フォーム本体は、もともと商品マスタを読んで商品一覧のHTMLを組み立てています。そこで、各商品の行に次の2つの属性を足しました。
data-price:商品マスタの税込単価data-group:配送区分(商品マスタの「仕入先」列から決める)
マスタを読む処理の中で値を埋め込むだけなので、フォーム本体への変更は小さく済みます。
2. 画面側は「属性を優先し、無ければ旧価格表」で読む
中継ページの計算処理は、商品の単価を取り出す部分を1か所の関数にまとめ、次の順で値を探すように変えました。
- 商品の行に
data-price・data-groupがあれば、それを使う - 無ければ、従来の価格表を引く
旧価格表はすぐに消さず、互換用として残しました。これが移行を止めないための要点です。
3. 反映の順番を問わない作りにする
2つの部品を別々に更新する場合、「どちらを先に本番へ出すか」で一時的に壊れる時間ができることがあります。今回の作りでは、次の組み合わせのどれでも動くことを事前に確かめました。
| 中継ページ | フォーム本体 | 結果 |
|---|---|---|
| 旧 | 新 | 動く(属性は読まれず旧価格表で表示。旧価格表に無い新商品だけ金額が出ない) |
| 新 | 旧 | 動く(属性が無いので旧価格表にフォールバック) |
| 新 | 新 | 動く(マスタの値で表示) |
順不同で反映できるので、片方を出したあとに確認の時間を取っても、店舗の画面が止まることはありません。
4. 配送区分の決め方もマスタ側に寄せる
単価だけでなく、「その商品がどの配送区分に入るか」もマスタから決めるのが大事です。画面側に「この品番は区分1」と書いてしまうと、単価と同じ二重管理がもう一つ残ります。
実例では、商品マスタの「仕入先」列を読んで配送区分を決めています。のちに3社目の仕入先の商品を足した際は、この判定を「A社/B社/それ以外」の3区分に広げ、「それ以外」は送料判定に含めない形にしました。判定がマスタ側の1か所にあるので、直す場所も1か所で済みます。その経緯は「公開前の商品をマスタに登録するときは表示側を先に用意する」で詳しく書いています。
移したあとに確かめる項目
作りを変えたら、次の項目を実際の画面で確かめます。見るのは「コードが正しいか」ではなく、「店舗が開くURLで、マスタどおりの金額が出ているか」です。
- 全店舗のURLが正常に開くか:実例では当時の21店舗すべてで、エラーやリダイレクトが無いことを確認しました
- 配信された画面に属性が出ているか:各店舗の画面のHTMLに
data-priceとdata-groupが入っているかを数えます。実例では、送料無料側の区分に属する9品(既存3色+追加6色)が全店で出ていることを確認しました - 計算が合っているか:代表的な組み合わせを手で計算し、画面と照らします。例えば税込560円の商品を100本なら56,000円。税抜の判定は「税込÷1.1を四捨五入」で1点ずつ出してから合計する、というように、画面と同じ計算方法で検算します
- 送料表示の境目:税抜3万円の手前と超えた後の両方を作り、「送料必要」と「送料無料」が切り替わるかを見ます
- キャッシュの待ち時間:実例のフォームは画面を300秒キャッシュしていました。マスタを直しても最大5分は古い値が出るので、確認はその後に行い、本部にも「反映まで数分かかる」と伝えておきます
のちに12店舗限定の商品(税込5,500円)を追加したときは、対象店舗の画面に data-price="5500" と新しい配送区分が出ていることを確認しました。単価は画面側の価格表ではなく、マスタの行から渡された値で表示されています。単価を改定するときも、直すのはマスタの1セルだけです。
二重管理が残っていないかの見つけ方
自社のフォームに同じ問題がないかは、次の質問で確かめられます。
- 単価を1つ変えるとき、触るファイルやシートはいくつあるか。2つ以上なら二重管理です
- 画面側のプログラムに、品番と金額が並んだ一覧が書かれていないか
- 商品を1つ足すとき、マスタ以外に足さないと表示や計算が欠ける場所がないか
- 「送料無料」「割引」などの判定条件が、マスタの列ではなくプログラムの中の品番指定で書かれていないか
一つでも当てはまれば、その値はマスタ側へ寄せる候補です。単価に限らず、発注単位(何本単位か)や、店舗ごとの取り扱いの有無も同じ考え方で扱えます。発注単位の縛りをマスタの列で定義した例は「美容室FC21店舗の発注フォームを2日で進化させた実践記録」、店舗ごとの出し分けをマスタの列1本で行う方法は「発注フォームの商品を店舗ごとに出し分ける方法」にまとめています。
移行時に注意したいこと
最後に、作りを変える際に起こりうるつまずきと、その防ぎ方です。
- 旧価格表を先に消さない:属性を出す側がまだ本番に出ていない状態で価格表を消すと、全商品の金額が消えます。消すなら、属性が全店で出ていることを確認した後です。互換用として残しておいても害はありません
- マスタの単価列に空欄を作らない:空欄の商品は「属性が空」になり、旧価格表にも無ければ金額が出ません。移行前にマスタの単価が全件埋まっているかを数えておきます(実例では36品すべて入力済みにしてから移しました)
- 税込と税抜を混ぜない:マスタは税込で持ち、税抜が必要な判定だけ画面側で換算する、というように、どちらを正本にするかを決めて列名にも書いておきます
- 表示だけでなく受付側も同じ値を使う:画面の表示をマスタに寄せても、注文を受け付ける処理が別の値を見ていれば、ずれは残ります。表示と受付の両方がマスタを読む構成にしておくと安全です
まとめ
発注フォームの単価は、商品マスタ1か所を正本にしてください。
- 単価と配送区分を、マスタから商品の行ごとに画面へ渡す(
data-price・data-groupのような属性) - 画面側は「渡された値を優先し、無ければ旧価格表」で読む。旧価格表は互換用に残し、反映の順番を問わない作りにする
- 配送区分や送料の判定条件もマスタの列から決め、プログラムに品番を書かない
- 移したあとは、全店舗の実際のURLで、属性の有無・計算・送料の境目・キャッシュの待ち時間を確かめる
「両方を直す」というルールは、作った直後の一時しのぎとしては使えますが、長く運用する仕組みには向きません。直す場所を1か所にしておけば、商品の追加や単価の改定は、マスタに1行書くだけの作業になります。
弊社では、スプレッドシートとGoogle Apps Scriptを使った発注フォームや集計の仕組みづくり、既存の仕組みの見直しをお手伝いしています。「単価を変えるたびに誰かがプログラムを触っている」という状態があれば、お気軽にご相談ください。