Day29 前半のゴール
「“バラバラに学んだピースを、1つのECシステムとして頭の中で組み上げる”」
ここまでで、テーブル設計、インデックス、API連携、ログ、権限、障害対応まで、一通りのピースを学んできました。
Day29 は、それらを「総合課題」として一つのシステムにまとめるフェーズです。
前半のゴールはこうです。
ユーザー管理・商品管理・注文処理・売上集計が、どうつながるかをイメージできる。
それぞれの機能に対して「最低限必要なテーブル」と「代表的な処理」を言葉で説明できる。
“とりあえず動く”ではなく、“破綻しにくい設計”を意識して全体像を描ける。
ここでは、まだ細かいSQLやコードに入らず、「設計の地図」を丁寧に描いていきます。
全体像を一枚の絵として捉える
「“ECサイトのバックエンド”を4つの機能に分解する」
今回の総合課題は、ざっくり言うと「小さなECサイトのバックエンド」を作るイメージです。
機能は4つに分かれています。
ユーザー管理
商品管理
注文処理
売上集計
大事なのは、「これらはバラバラの機能ではなく、全部つながっている」という感覚です。
ユーザー管理で作られたユーザーが、商品管理で登録された商品を、注文処理で購入し、その結果が売上集計に反映される。
この流れを、頭の中で一本の線として描けるようになることが、Day29 前半の一番大きなテーマです。
ユーザー管理の役割と最低限の設計
「“誰が使っているか”を一意に識別し、認証の土台を作る」
ユーザー管理は、「システムを使う人」を表現する部分です。
ここでの主役は users テーブルです。
前のDayでも出てきましたが、総合課題として改めて整理すると、ユーザー管理には次のような責任があります。
ユーザーを一意に識別する(id)。
連絡先としてのメールアドレスなどを持つ。
ログインのためのパスワード(ハッシュ)を持つ。
作成日時・更新日時を持ち、監査や履歴の基礎になる。
ここで重要なのは、「users はほぼ全ての機能の“起点”になる」ということです。
注文は「誰が買ったか」を users.id で紐づける。
売上集計は「どのユーザーの注文か」を軸に集計することもある。
監査ログや権限管理も、最終的には users.id に結びつく。
つまり、ユーザー管理は「全体の土台」です。
このテーブルがブレると、他の機能も全部揺れます。
商品管理の役割と最低限の設計
「“何を売るか”を安定して表現する」
商品管理は、「売る対象」を表現する部分です。
ここでの主役は products テーブルです。
商品管理の責任を、総合課題の視点で整理すると、こうなります。
商品を一意に識別する(id)。
商品名・説明・価格などの基本情報を持つ。
在庫数を持つかどうか(今回はシンプルに持つ想定でもよい)。
公開・非公開フラグなど、「販売可能かどうか」の状態を持つ。
ここで重要なのは、「価格」と「在庫」の扱いです。
価格は、注文時点の値を order_items にコピーすることで、「過去の価格変更に影響されない」ようにする。
在庫は、注文処理と密接に関わるので、「どのタイミングで減らすか」「マイナスにならないようにどう制御するか」を意識する。
商品管理は、「売るもののマスタ情報」を安定して持つ役割です。
ここがぐちゃぐちゃだと、注文処理や売上集計が一気に不安定になります。
注文処理の役割と最低限の設計
「“誰が・いつ・何を・いくつ買ったか”を正しく残す」
注文処理は、この総合課題の中で一番“動き”がある部分です。
ここでは、orders と order_items の二段構造が中心になります。
orders は、「1回の注文そのもの」を表します。
order_items は、「その注文の中の明細(どの商品を何個買ったか)」を表します。
注文処理の責任を整理すると、こうなります。
orders で、「誰が」「いつ」「合計金額はいくらか」「ステータス(新規/支払い済み/キャンセルなど)」を管理する。
order_items で、「どの商品を」「いくらで」「何個買ったか」を管理する。
products から価格をコピーしておき、「注文時点の価格」を保持する。
在庫を減らすタイミングを決め、トランザクションで整合性を保つ。
ここで特に重要なのは、「注文時点の価格をコピーする」という設計です。
もし order_items に「product_id と数量だけ」しか持たず、
合計金額を「常に products.price × 数量」で計算してしまうと、
後から価格を変更したときに、過去の注文の金額まで変わってしまいます。
それを防ぐために、order_items.unit_price のようなカラムに、
注文時点の価格をコピーしておくわけです。
これは、Day23 のEC設計でやった「履歴管理」の応用そのものです。
売上集計の役割と最低限の設計
「“あとから振り返るための数字”を取り出せるようにする」
売上集計は、「過去の注文データを、いろいろな切り口で眺める」ための機能です。
ここでは、新しいテーブルを作らなくても、orders と order_items から集計する形で十分です。
売上集計の責任を整理すると、こうなります。
日別売上(1日ごとの合計金額・件数)を出せる。
商品別売上(商品ごとの売上金額・販売数量)を出せる。
ユーザー別売上(ユーザーごとの購入金額・件数)を出せる。
ここで重要なのは、「集計に必要な情報が、すでに注文データの中に入っているか」です。
日別売上には、orders.created_at と orders.total_amount が必要。
商品別売上には、order_items.product_id と order_items.unit_price・quantity が必要。
ユーザー別売上には、orders.user_id と orders.total_amount が必要。
つまり、「集計したい軸(時間・商品・ユーザー)」に対応する情報が、
orders / order_items / products / users のどこかにちゃんと入っている必要があります。
総合課題としては、「どんな集計をしたいか」から逆算して、
「どのテーブルに何を持たせるか」を考える、という視点が大事です。
4つの機能がどうつながるかをストーリーで追う
「“1人のユーザーが1つの注文をする”流れを頭の中で再生する」
ここまでを、ストーリーとして一本につなげてみます。
あるユーザーが会員登録をする。
users に1行が追加される。
管理者が商品を登録する。
products に複数行が追加される。
ユーザーが商品一覧を見て、カートに入れ、注文を確定する。
orders に1行が追加される(user_id・合計金額・ステータスなど)。
order_items に複数行が追加される(product_id・unit_price・quantity)。
products の在庫数が減る(在庫管理をする場合)。
後日、管理画面で売上集計画面を開く。
orders と order_items を集計して、「日別売上」「商品別売上」が表示される。
この一連の流れの中で、
users・products・orders・order_items がどう連携しているかを、
自分の言葉で説明できれば、Day29 前半としてはかなり良い状態です。
総合課題で意識してほしい“設計の視点”
「“動けばいい”から一歩進んで、“後から困らないか”を考える」
総合課題は、「とりあえず動くものを作る」だけなら、かなりシンプルにできます。
しかし、ここまで学んできたあなたには、もう一歩踏み込んでほしいです。
例えば、こんな問いを自分に投げてみてください。
ユーザーを削除するとき、そのユーザーの注文はどう扱うか。
商品を非公開にしたとき、過去の注文の表示に影響は出ないか。
注文のステータス(新規/支払い済み/キャンセル)は、どのタイミングで変わるか。
売上集計は「キャンセルされた注文」を含めるのか、含めないのか。
これらは、全部「設計の選択」です。
正解は一つではありませんが、「何も考えずに作る」と、後から必ず困ります。
Day29 前半では、
「ユーザー管理・商品管理・注文処理・売上集計がどうつながるか」
「それぞれの機能にどんな責任を持たせるか」
を、自分なりに言語化してみることが一番のトレーニングになります。
後半では、この全体像を前提にして、
具体的なテーブル構成例と、代表的なクエリ・処理フローをもう少し踏み込んで見ていきます。
Day29 前半のまとめ
総合課題では、ユーザー管理(users)、商品管理(products)、注文処理(orders+order_items)、売上集計(orders/order_items/users/products を組み合わせた集計)という4つの機能を、「1人のユーザーが商品を買い、その履歴があとから集計できる」という一本のストーリーとしてつなげて考え、ユーザー管理は「誰が使っているか」の土台、商品管理は「何を売るか」のマスタ、注文処理は「誰が・いつ・何を・いくらで・何個買ったか」の事実、売上集計は「その事実を時間・商品・ユーザーなどの軸で振り返る」役割を持つと整理する。
そのうえで、「注文時点の価格をコピーしておく」「集計したい軸に必要な情報をどこかのテーブルに必ず持たせる」「ユーザー削除や商品非公開が過去データにどう影響するかを考える」といった“後から困らないための設計視点”を意識し、Day29 後半で具体的なテーブル構成と処理フローに落としていく準備を整える。
