Slide 1

Slide 1 text

在庫管理の実装 on Rails

Slide 2

Slide 2 text

自己紹介 ほりゆう GMOペパボ SUZURI事業部エンジニア タクラミの開発担当 趣味はマジック ハトを飼っています 好きなエディタ: Cursor

Slide 3

Slide 3 text

SUZURIとは 1枚画像をアップロードするだけで、オリジナ ルアイテムをつくることができ、 1個から販売 できるサービスです。

Slide 4

Slide 4 text

タクラミとは クリエイターが有償でオリジナルイラストや似顔絵などのリクエストを募集できる SUZURIの新機能です。

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

今日のテーマ 在庫管理の設計 在庫管理と決済の実装

Slide 7

Slide 7 text

在庫管理の設計 編

Slide 8

Slide 8 text

タクラミの在庫管理とは クリエイターが作ったタクラミに「何回応募できるか」というもの

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

どうやって在庫管理しよう

Slide 11

Slide 11 text

パターン A タクラミのテーブルにそのまま持たせる create_table "takuramis", force: :cascade do |t| t.string "title", null: false t.text "description" t.integer "price", null: false t.integer "stock", null: false, default: 0 # 在庫 t.references :user, foreign_key: true t.timestamps end ※ コードはダミーです

Slide 12

Slide 12 text

テーブルにそのまま持たせる 単一テーブルで管理できるのでデータの取得や更新がしやすい 設計がシンプルになる

Slide 13

Slide 13 text

パターン B 在庫テーブルを作る create_table "stocks", force: :cascade do |t| t.integer "quantity", null: false, default: 0 t.references :takurami, foreign_key: true t.timestamps end ※ コードはダミーです

Slide 14

Slide 14 text

在庫テーブルを作る タクラミテーブルと管理が別なので DBのロックを気にしなくてよくなる

Slide 15

Slide 15 text

選ばれたのは ...

Slide 16

Slide 16 text

両方活用することにした 総枠数という概念を Takuramiに持たせる 実在個は Stockテーブルに持たせる 実在庫とは申し込める枠数のこと

Slide 17

Slide 17 text

こうしました create_table "takuramis", force: :cascade do |t| t.string "title", null: false t.text "description" t.integer "price", null: false t.integer "slot", null: false, default: 0 # 総枠数 t.references :user, foreign_key: true t.timestamps end create_table "stocks", force: :cascade do |t| t.integer "quantity", null: false, default: 0 # 実際の在庫 t.references :takurami, foreign_key: true t.timestamps end ※ コードはダミーです

Slide 18

Slide 18 text

どういうことか タクラミには作成段階で枠数( slot)を持たせて、総数がわかるようにした 実在個には在庫数( quantity)を持たせて、実際の残りの枠数を管理できるようにした

Slide 19

Slide 19 text

何がいいのか 枠数を持ったことで、そのタクラミが何分の何枠なのか表現できる 例: 1/10となっていれば人気なタクラミだということがわかる Stockだけを使って残り枠数を出すだけもできる 購入中にタクラミの在庫の編集をしても在庫がずれる心配がなくなった 過受注の防止

Slide 20

Slide 20 text

過受注とは

Slide 21

Slide 21 text

こういう表現にできた

Slide 22

Slide 22 text

在庫管理と決済の実装 編

Slide 23

Slide 23 text

応募したら在庫を減らしつつ、決済をしないといけない

Slide 24

Slide 24 text

応募されたら Stocksの quantityを 1個減らせばいいんじゃない? 決済はその後すぐすればよさそう!

Slide 25

Slide 25 text

在庫を減らして決済したら ... 残高不足 残高はあるが 3Dセキュア認証失敗 3Dセキュア諦める キャンセルする場合は? 残り 1枠で応募失敗 同時応募

Slide 26

Slide 26 text

エラーハンドリング:応募中に ... 在庫 0になったものを応募した時 自分のものに応募しようとした時 各種クレカのエラーが発生した時 クリエイターが非公開にした時

Slide 27

Slide 27 text

特に工夫した部分

Slide 28

Slide 28 text

在庫の減少タイミング 決済トランザクション 例外処理

Slide 29

Slide 29 text

takurami_order.rb def self.process_order valid_order! takurami.stock.decrement_quantity! ActiveRecord::Base.transaction do case Payment.process!(user: user, amount: takurami.price) when :success true when :insufficient_funds raise PaymentError, "残高不足" else raise PaymentError, "不明なエラー" end rescue ActiveRecord::RecordNotFound => e raise e, '応募可能な商品が見つからないか、申し込み中に在庫がなくなりました' rescue StandardError => e takurami.stock.increment_quantity! raise e end end ※ コードはダミーです

Slide 30

Slide 30 text

決済の大まかな流れ 1. タクラミのバリデーション 認可 2. タクラミの在庫を減らす 決済の成功可否に関わらず減らす 3. 決済のトランザクション 応募レコードの作成 カード関連のエラーはここで補足 4. 例外処理 申し込み中に在庫が 0...etc それ以外のエラーの場合、在庫を戻す

Slide 31

Slide 31 text

TIPS

Slide 32

Slide 32 text

Increment / Decrement便利 Active Record Persistence Takurami.increment!(:stock) Takurami.decrement!(:stock) Rails5から同時実行を意識したメソッドとして更新

Slide 33

Slide 33 text

transactionの仕様

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

rescueの中で例外を再スローするか transaction外でエラーを補足する必要があった

Slide 36

Slide 36 text

まとめ

Slide 37

Slide 37 text

まとめ 在庫管理と決済は考えることが多い レコード作成のタイミング 決済失敗時の取り扱い キャンセルの扱いなどは、特に注意 クリエイター:自動で戻してほしい or そのまま ご清聴ありがとうございました