ゲーム化!tomo_manaのブログ

ゲーム化!tomo-manaのブログ

Unityでゲームを作る方法について紹介しています

簿記の観察#4 仕入単価が変わる時のデータ構造(台帳管理)

f:id:tomo_mana:20211221195443p:plain

仕入原価・売価が時々刻々と変わっていく場合のデータの持たせ方。

要約

仕入原価・売価のデータ構造は表現方法がいくつかあります。

そこで、先に、データ構造に依存しないインターフェースを考えます。

拡張性(階層化)
データ構造によらず、仕入と売上を同じインターフェースで処理できるようにするために、リストと登録用のインターフェースを層で分離します。構造を隠蔽し、データ構造自体は後から修正できるようにします。また、データをフォームと切り離して使えるように、フォームとアプリケーションAPIも分離します。

f:id:tomo_mana:20210912130601p:plain
フォームとデータ構造の分離

最も迷ったのは、仕入高と残数をどう分けるかでした。様々な原価計算の方法を当てはめた結果、最初に考えていた先入先出法を中心にした考えを捨てて、総額法のように決算時に原価を計算する方法向けに最適化することでした。

仕入・売上
最終的に、仕入、売上のデータは以下になります。

f:id:tomo_mana:20210912132516p:plain
1回の取引のデータ構造

在庫管理
また、在庫管理のデータは以下になります。

f:id:tomo_mana:20210912132605p:plain
在庫管理のデータ構造

なお、この記事では、取引による現金の増加(売上)は青、減少(仕入)は赤で示しています。
以下、仕入、売上、在庫のデータ構造について見ていきます。

仕入・売上に関する考察

仕入と売上は、原価計算に使うと共に、決算において通期の仕入高、売上高と、利益を求めるために、一年分の情報が必要でした。そして、原価計算には、大きく6つの方法があり、代表的なものは「先入先出法」と「総額法」の2つでした。

(6つの原価計算方法についてまとめた記事)
tomo-mana.hatenablog.com

先入先出法は、「N個目の商品の販売原価は、N個目の商品の仕入原価」でした。

総額法は、「当期に売り上げた商品の販売原価は、当期に売り上げた商品の仕入原価の合計」でした。

先入先出法ベースでの最適化

先入先出法をベースにしたリストでは、N個目をいつでも探索できるようにする必要があります。この探索時間を最小にするには、商品を1個単位で管理します。先入先出法のために最適化されたリストは、リストが長くなり、また2個以上同じ商品を仕入れた時に、個数分の登録処理が必要になります。

f:id:tomo_mana:20210912224408p:plain
先入先出法向けに最適化されたリスト

総額法ベースでの最適化

一方、総額法をベースにしたリストでは、期の途中で原価を計算するには不向きですが、決算時に、1年で販売したすべての個数とすべての仕入高を足しこむだけで計算できます。そのため、リストは最小化され、1回の仕入の個数が何個であっても、データをコンパクトにできます。

f:id:tomo_mana:20210912232850p:plain
総額法向けに最適化されたリスト

総額法ベースでのN個目の単価?

総額法をベースにしたリストで、先入先出法のように「N個目の単価」を調べるには、少し探索コストがかかります。N個目がどこにあるかを調べるために、仕入リストを先頭から足しこむ必要があるためです。しかし、総額法をベースにしたリストでも、先入先出法の単価を算出する方法は不可能ではありません。また、現代の発達したCPUでは、個数がよほどの数でもない限り、そこまでのコストにはならないと思います。

f:id:tomo_mana:20210912232922p:plain
総額法ベースのリストにおけるN個目の単価の検索

つまり、総額法をベースにした場合は、データは「仕入個数」と「仕入高」の2要素を持つデータ構造のキューにすればよく、リスト長も短くて済みます。そして、現実での会計でも、仕入台帳・売上台帳はこのようなデータ構造になっていそうです。

f:id:tomo_mana:20210912132516p:plain
1回の取引のデータ構造

在庫管理に関する考察

単純なキュー構造?

一方、在庫は、仕入れた時に増え、売り上げた時に減ります。一見すると、最新の状態を保持しておけばよく、その意味で、最初は単純なキュー構造にできると思い込んでいました。

f:id:tomo_mana:20210912233042p:plain
仕入と売上によるキューの出し入れ

ただし、このようにできるのは仕入単位数と売上単位数がピッタリ一致する時だけです。実際は仕入単位数と売上単位数が一致しないケースが多いはずです。

f:id:tomo_mana:20210912233118p:plain
仕入単位数より売上単位数が少ない場合
f:id:tomo_mana:20210912233803p:plain
仕入単価数より売上単価数の方が多い場合

また、この場合、すでに売上が確定した時の仕入原価が割り切れない値になっています。

最新の個数さえ合っていたら良い?

次に、在庫は最新の個数だけあればいいのかと考えました。

それに、仕入と売上の推移を見たい時だってあると思います。そうすると、結局在庫も最新の状態でなく、前回の状態にどんな変化があって、その結果今どうなっているのかが見られないといけないのではないかと思いました。

在庫台帳で全ての取引を見られるようにする

しかし、仕入高や売上高は仕入台帳や売上台帳に記載済みなので、在庫台帳には何を書くか。在庫台帳には、今回の変動数と残数を書きます。

f:id:tomo_mana:20210912132605p:plain
在庫管理のデータ構造

仕入・売上取引と在庫の関係を示すと、以下のようになります。

f:id:tomo_mana:20210912135843p:plain
仕入・売上取引と在庫の関係


 なお、このケースでは、仕入と売上はセットで使われるものの、クリティカルポイントは仕入リストでも売上リストでもなく、仕入と売上の両方の影響を受ける、在庫量になります。ここに排他制御を仕掛けることにします。

拡張性に関する考察

最後に、拡張性に関する考察を少しまとめます。

今後の使い勝手を考えた時、以下が浮かびました。
(1) 仕入と売上を対で管理(API対称性=同じグループ)
(2) 仕入と売上は、作り方によって全く同じ処理にできる(実装の不透明性)
(3) 仕入と売上の作り方に依らず、最終的なデータとして仕入と売上はものが異なる(データの所在の分離)
(4) それとは別に在庫も必要になる
これらをまとめると以下になります。

f:id:tomo_mana:20210914074411p:plain
階層化

さらに、入力方法はさまざまな表現があります。そのため、入力部と会計処理部を分けるため、以下の線を追加します。

f:id:tomo_mana:20210914074448p:plain
入力と機能の分離

すると、上記の図になります。実際にUnityで作る方法は別の記事にします。

台帳の英訳

仕入、売上の管理をするデータベースは、一般的な会計のツールでは台帳と呼ばれるものと同じです。また在庫管理に使用するものも台帳と呼ばれることがあります。

台帳の英訳は、いくつか候補がありましたが、以下の資料を参考にしました。ありがとうございます。
https://core.ac.uk/download/pdf/292904664.pdf
ledger: 口座別の分類記帳
register: 取引順序を記録したもの