在庫管理システムを設計するときのデータベース設計の勘所

#概要
まず商品のマスターデータも管理する場合と管理しない場合があるだろう。今回は、多品種在庫を管理するための在庫管理システムについてのみ述べる。
なぜ少品種在庫を管理するための管理システムについて述べないかと言うと、それらは在庫マスターの作りが簡単でも問題ない上に、商品マスターを新品状態のみを管理するとして作成すれば十分であるので、比較的単純に作れてしまう。またそのような設計は、同一在庫の同一グレードの在庫は全く同一の品物として扱うというアマゾンの設計思想と同じであり、同じようなものを設計したとしてもアマゾンに勝ち目がないから作る人は少ないだろうと判断しているし、そのようなシステムはアマゾンを参考にすれば済むので解説しないこととする。
　同一在庫の同一グレードの在庫は全く同一の品物として扱うとは、携帯電話でいうと、

- 画面が傷が入っていて、カメラレンズに傷がない場合
- 画面に傷がなくて、カメラレンズに傷がある場合

２つの状態を中等程度の商品として、在庫データベースに登録することだ。

#商品のグレードとは
ここで「グレード」という単語を出したが、商品の状態の良し悪しを評価する指標に順序がある場合をいう。
例えば、

1. 新品
1. 未使用
1. 使用済み

のようなこと。

アマゾンはこれらを「コンディション」と命名しているけど、なんでもかんでもアマゾンに準拠する命名規則としてしまうと、順序がない商品の状態の特徴をグレードでもコンディションでもない別の名前で呼ばなくてはいけない。

- 画面が傷が入っていて、カメラレンズに傷がない場合
- 画面に傷がなくて、カメラレンズ似傷がある場合

これらをコンディションと呼ぶべきである。

#設計
まず、在庫管理システムと商品マスターのどちらが先に業務に使うと良いのかということを考える。
在庫管理システムは在庫管理システム自体で役に立つものでありますが、商品マスターは商品マスターがあっただけでは役に立ちません。したがってビジネス的なコストの回収の観点から、在庫管理システムのみで作成して、それから商品マスターを作成することになります。その時にどのような商品マスターを作成するかを考えてから在庫管理システムを作り始めるか否かで、将来のシステムの改造コストが全く違ってきます。そこでどのような商品マスターが理想なのかどのような在庫管理システムが理想なのかということを考えてから、全体の設計を進めます。

##在庫管理システムの目的
まず在庫管理システムとは

- どのような商品が
- どのような状態で
- どこに存在するのか

という情報を保存して読み出して、情報をもとにその商品を移動するシステムです。

##事実とは？
この中で、システムで事実とみなせることと事実と見なせないことを分けて考えましょう。どのように分けると失敗しがちなのかを述べます。
まず商品の緯度経度と高度で表現できる位置情報は、誰しも客観的に評価できる事実として扱えます。
その次に、誰に所有権があるかという事実は、誰しも客観的に評価できる事実として扱えるかどうかという問題があります。私が作成した買取システムでは、業務フローのどの段階で、所有権が移転するのかがとても流動的です。したがってこのような法的な事実は、客観的な事実として扱うことができません。
事実として扱うことができるのは

- 縦
- 横
- 高さ
- 緯度
- 経度
- 高度
- 区画
    - どの棚に入っているか
  
で表現出来ることと、それとそれらの状態が変化した時刻です。
これらの情報は、観測する主体(センサーでも人でも)の出力を人為的判断なしに直接記録することで表現できる情報かどうかで判定してください。
どのセンサーが事実を記録しているのか合意を取ることで、組織内で何を絶対に信用するのかを決めやすくなります。
この証拠能力の最も高い事実をもとに、どの程度証拠能力が低い法的事実などを基礎として、在庫管理を行っていくかということを考えてください。
なぜこのように考えるに至ったかというと、ビジネスフローのある時点で在庫の所有権が絶対に在庫管理システムの所有者に移転していることを前提にシステムを作りました。その結果、ビジネスフローは実際にそうはなっておらず、なおかつヒアリングでも例外処理はないと言われていたにもかかわらず、例外処理はたくさんあったのです。アマゾンを真似してしまうと、所有権に関して例外処理はないということになってしまいますが、零細企業ではここを曖昧にすることによってビジネスチャンスが生まれています。あやふやな法的な状態の遷移を扱えるように拡張できる余地を残しておくことは、小さい会社がいろいろな業務に利用する基幹システムになりたければ、重要な性能になってきます。どの点を柔軟にするべきかを絞り込むことが、実際の設計で一番面白いところです。

  商品の状態は主観でしかありません。すべての商品に共通する特徴（新品、開封済み、中古、など）で、商品の状態を表現するのがアマゾンの方針ですが、多品種少数在庫のデータベースではそのような状態がなく、カテゴリごとに評価するべき状態が違ってくる場合を考えております。例えば、スマホでは、画面、バッテリーの劣化度合いなどの要素が存在します。
これに対応するために商品ごとにどのような状態が存在するかを登録し又は保存するようになデータベース設計にすることは、無駄な情報量の増加につながるのでやりません。
例えば、スマホにはいろいろな機種がありますが、商品ごとに状態を表現する要素を登録するのは面倒です。
カテゴリーごとに状態の要素数を変化させるほうがいいという考え方があります。カテゴリーごとに変化させるとして、1番最上位のカテゴリーのみこれらの状態が変化するとしてしまうと、カテゴリー内で商品の状態を評価する指標の組み合わせがとても多い場合、評価する側が使いにくくなってしまいます。
例えば、スマホでいうなら、iPhoneにはカメラボタンがないけど、Androidにはあります。スマホカテゴリーに、カメラボタンの状態の要素をつけると、iPhoneの列は全部Nullになります。
したがってどのカテゴリーの階層でも、商品の状態を評価する指標の組み合わせを、親のカテゴリーを継承する形で記述する必要があります。ここで親カテゴリーからの継承がなかった場合、すべての組み合わせを1から入力する必要があるので、評価する点を、在庫システムの各ユーザがアップデートすることがとても難しくなります。
このようなツリー構造を関係性データベースで扱うことが非常に難しいです。したがってこれらには、グラフデータベースを導入することが適切でしょう。

#製造者の追跡について
どのような製造者が製造したのかという情報を保存する必要があるでしょう。ここで問題になるのは製造者が統廃合することです。製造者の統廃合は頻繁に起こることではないので隣接リストなどを使って関係性データベースの中で表現するべきことだと思います。

#アンチパターン
所有権が移転すると別テーブルにデータが移動する。
客観的に評価しづらい事実をもとに、テーブルを移動していると、ビジネスロジックが変わった時に問題が起きます。どんなに固まっているビジネスロジックであっても、システムで表現してみると曖昧だったりすることが多いと思いますので、この実装を取る事はほとんどお勧めしません。自分はこの状態からシステムを引き継いで大いに困りました。

#商品マスターが存在しない状態での在庫管理システムだけでのシステム導入方法
商品をどのように表現するかが問題であるが、商品の名前とグレード、文字列の自由入力欄と製造者の情報を最低限用意しておきそれぞれのシステムで必要な実数の入力列を持つのが良いと思う。
製造者の情報のみを管理する機能を、商品マスターに実装しておいて、それだけを在庫管理システムと連携することが良いだろう。


#在庫管理するための、モバイルアプリケーションについて
QRコードで読み込むことができれば、すべての情報が最新に更新されている画面を表示することができることを前提に考える。アプリを起動する手間を省きたくて、ラベルにラベル印刷時の情報をいろいろ印刷したくなるだろうが、それをできるだけ少なくするようなビジネスモデルを考えるべきである。それらは、変更されるし、データベースに登録せずに、ラベルをペンで修正するようになるので、そのような要求が上がってきたときには良くないシグナルと認識すると良い。それでも、ラベルに書く情報はあるけれども。例えば、IDとか不変な情報。

QRコードの反応速度は、1秒程度でiPhone で読み込むことができれば、普通に使ってもらえる。一般的なQRコードの読み込みの二倍程度遅いスピードであると、苦情が来ます。具体的な設定は、QRコードの汚損への耐性は最大にして、周りの文字との距離は2ミリ程度 で十分です。ラベルプリンタはRJ 2150でラベルの大きさは55*45です。このラベルの大きさはテストで使うときには、QRコードのみを印刷するという予定であってもこの程度の大きさにするべきだと考えております。何故ならこのシステムを使い出した瞬間にいろいろな情報を載せたくなってくるものなので、この大きさが良く、なおかつ最初にこれぐらいの大きさにカットされているシールの最大サイズがこの大きさのためです。
 このアプリを使って情報を最新に更新してもらうために、在庫管理システムを一部の工程のみで使用する方針を経営者から伝えられても、できるだけ商流の最初から最後までを同一の在庫IDで管理するようにしておかないと、統計的な分析やるときに複数の在庫管理システムをつなぎ込まなければならず、分析が非常に難しくなってしまう。予めメインの在庫管理システムがある特殊な状況でない限り、在庫IDを自社に所有権がない状態であっても同一にするべきだ。
　買取のシステムに当てはめると、検索エンジンから、顧客が流入してきた段階でその顧客の特徴に合わせて、どのような商品を相手が持っているかということを、商品マスターからカテゴリーだけ判明している状態でも良いので、在庫管理システムに登録して行を作ってしまうと良い。例えば、携帯電話を売りたいと問い合わせが入ったら、携帯電話カテゴリで登録してしまい、商品の情報が正確になるごとに商品情報を更新するが、IDは同一にして管理する。コレができると、どこからの流入があるのかを調べて広告の最適化も楽にできる。
　言い換えると、顧客である物品の売り主と会社が契約し、商品が会社に到着して検品した段階になって、商品の状態が完全に確定する業務フローがあります。そのフローの中で商品の状態の変化を記録することで、物品の売り主が最初に自己申告した物品の状態と会社に到着したあとの物品の情報の差異から、顧客の自己申告の信用度などいろいろな統計を取ることができるようになる。

#ツリー状の階層構造で商品情報を記述する利点
その商品を手に入れるためにコストを掛けてもよいかどうか判断できる範囲が広がれば、ビジネスチャンスも大きくなる。また、商品情報が標準的なフローで期待されているタイミングよりも後に特定できる例外パターンも存在する。例えば、 iPhone8 64GB 黒が一つの商品でそれ以上分割できないと思っていたら、キャリアごとに型番が違っていたと判明したら、それは商品じゃなくて、カテゴリになる。テーブルが分かれていると、情報をテーブル間で移動しなきゃいけない。コレはアンチパターンだと思う。
したがって、商品情報とカテゴリー情報のRDS上のテーブルを分割せず、特定したと思った商品情報の更に下の階層に商品情報を追加して、既存の商品情報はカテゴリ情報として扱えるようにしておいたほうが良い。このときに、商品の状態や特徴を親のカテゴリーも継承して記述することができれば、情報の重複を防ぐことができる。別の言い方をすると、商品の状態や特徴を詳細に正確に確認することができずないという前提をもとにデータ構造設計を行う。商品がどのカテゴリーまで特定できているかによって、行動をどのように変化させているかと言うことが記録できたとすると、顧客と従業員の行動を最適化することができる。したがって、商品の状態を評価する特徴だけではなく、商品の性能や製造者の情報も親のカテゴリーを継承して表現できるようにしておく方が良いであろう。具体例を言うならば、iPhoneのカテゴリーは全てApple社によって製造されているので、アップルのカテゴリーにApple社による製造と言う情報を記録すればそれぞれの携帯電話やパソコンにApple社が製造していると言う情報を付与しなくても良い。

#その他留意したいこと
最後に 小さく始めるにしても、heroku 12 factors of app の原則を守り、出来るだけこのシステムのログをredshift などの解析用データベースに流せるようにしておくべきだ。小さく始めても乱雑に始めると、よほど検証する目的が明確でない限り、後でデータを移し替えるのがとても大変になってしまう。