在庫管理ってけっこう大変だよね
この記事は異世界行ったら本気だすぴょこりんクラスタ Advent Calendar 2021のために書いたものです。このアドベントカレンダーそのものに関しては、主催者による紹介記事を見てください。
はじめに
ここ2年くらい、消耗品はいくつもまとめて買うようになった。 そうなると困るのは数の管理であり、買い物のたびにあれ買うんだっけとか、 そろそろこれが切れそうとかを覚えておくのも大変になったので、 まずは数だけでも管理できるようにした。
完成品
ソースコード
README作ってないので、代わりに
- 道具
- 言語: Go
- Webアプリフレームワーク: Gin
- ORM: GORM
- DB: SQLite
- CSS: Vanilla Framework(https://vanillaframework.io/)
- 立ち上げ方
- Makeでビルド
- できたバイナリを実行すると、デフォルト12000番ポートで立ち上がる。
-port <port#>
をつけるとport#で立ち上がる。
動作イメージ
トップ画面はこんな感じで、最終更新日が古いものから順に品名と数がひたすら並ぶ。 プラスボタン/マイナスボタンでそれぞれインクリメント/デクリメントを行い、 ゴミ箱ボタンでエントリそのものを消す。 メニューボタンは数を大幅に変えたり名前を変えたいときに使うが、基本使わない。
カテゴリごとにフィルタもできる。 filterを押すとメニューが出てきて、一旦全部見えなくなる。 チェック入れたものだけ見られるようになっている。
追加はシンプルにフォーム。
設計
以降、作るときに意識したことを書いていく。
要件
要件は以下とした。品数のメンテがだるいのはともかく避けたかったので、 手軽というかまあ許せるくらいに簡単なもので、かつそんなに作るのに苦労しないものをめざした。
# | 要件 | 対応方針 |
---|---|---|
1 | ぱっと見で何がどれくらいあるかわかる | 品名と数だけ表示し、更新日時等は出さない |
2 | スマホでもPCでも使える | Webアプリとし、レスポンシブに動くようにする |
3 | 品数メンテ時に文字入力させない | インクリメント/デクリメントボタンで増減できるようにする |
4 | 探しやすくする | カテゴリでフィルタをかける |
アーキテクチャ
いくつかAPIを用意し、それをブラウザから適宜叩くようにする、 (たぶん)よくある感じのウェブアプリとした。
UI
問題なのはレスポンシブに動くようにするところ、画面に合わせてデータを取得したりすることだった。 前者はCSSフレームワークにVanilla Frameworkを使ったら実現できてしまったので、 特に考えることはなかった。 後者は、特にフレームワークに頼らずともJavaScript使うだけでなんとかなってしまった。 async/awaitのおかげで素人でもあまり困らずにこの辺なんとかできてしまいますね。
APIモデル
consumable-item
オブジェクトが1個あるだけ。全部リクエスト同期で処理する。
インクリメント/デクリメントはPATCHとかPUTとかとはちょっと性質が違うのではと
思って、オブジェクトにくっついてる特殊操作扱いにした。
これでよかったかは謎だが、特に困ってはいない。
# | HTTP Methodとendpoint | 概要 |
---|---|---|
1 | GET /api/v1/consumable-items | 管理品一覧取得 |
2 | GET /api/v1/consumable-items/:id | id指定で管理品取得 |
3 | POST /api/v1/consumable-items | 管理品新規作成 |
4 | POST /api/v1/consumable-items/actions/plus-one/invoke | id指定で管理品の数をインクリメント |
5 | POST /api/v1/consumable-items/actions/minus-one/invoke | id指定で管理品の数をデクリメント |
6 | PATCH /api/v1/consumable-items/:id | id指定で管理品情報修正 |
7 | DELETE /api/v1/consumable-items/:id | id指定で管理品情報削除 |
データモデル
品名、数、カテゴリを1つエントリで持つ。 カテゴリに関してはテーブルを分けようかとも思ったが、 使っていると結構気軽に分類を変えることがわかった(最初はキッチンでまとめていたが、出し入れが激しいので別枠を作って管理するとか)ので、 1つにして、テーブル間の同期を考えないようにした。 大した量もないので、これでも問題ないはず。
type Consumable struct { Id uint32 `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` Name string `json:"name"` Count uint32 `json:"count"` Category string `json:"category"` SubCategory string `json:"subcategory"` }
おわりに
けっこう便利に使っているが、結局日々のメンテがいちばん大変なのであった。 次は数のメンテが楽になる何かを作りたいですね。