数据库设计:库存和销售系统?

12

我需要开发一个库存和销售系统。

对于库存,我需要能够跟踪理想库存水平、当前库存水平、重新订购点、成本、销售价格等。

并非库存中的每个物品都是“可销售”的。例如,我可能想要对用于苏打水的塑料杯进行库存管理。也就是说,每次我出售一份苏打水,我需要从塑料杯的库存数量中减去一份。因此,“中杯可乐”实际上是塑料杯、餐巾纸和液体,每个项目都有自己的当前库存水平、成本等。

然后还有“组合”概念。也许一份1美元的中杯可乐和一份3美元的汉堡包作为组合售价只需3.50美元(节省0.50美元)。可乐提到包括一些餐巾纸。假设汉堡包本身也包含餐巾纸。但是,作为组合,买家不会得到可乐和汉堡包各自的餐巾纸;而是只能得到与单买可乐时相同数量的餐巾纸。

对于销售系统,我需要跟踪每一次销售,可能需要与库存记录保持关联(这意味着一旦销售完成,我无法真正删除库存中的物品——出于历史目的)。当我以1美元的价格卖出“中杯可乐”时,也许我应该将其分解为0.90美元的液体和0.10美元的塑料杯。

而当我销售一个“组合”时,也许我需要能够指定汉堡实际上售价为3美元,而中杯可乐只需0.50美元(仅可乐打折扣,使组合更具吸引力)。

这不能是一个新的问题。有没有人有什么想法(或示例)可以帮助我解决这个问题? 我不确定如何对库存、可销售的物品(尤其是组合)进行建模,以及如何记录销售情况。


这个链接并没有解决我在这里提出的问题。我已经查看了一些现有的解决方案,但我并没有看到它们如何解决这里所述的问题。 - StackOverflowNewbie
2个回答

30
您正在寻找的解决方案将依赖于一个会计模型和一些材料清单(BOM)。 您的主要实体类型将包括:
  • SKU 这是您销售物品的列表。它的属性将包括产品描述和当前零售价格。您可以变得复杂,并将价格分解为子表,以提供随时间变化的价格。我们假设您现在要忽略这个细节。有些SKU可能是您所说的“组合套餐”。

  • COMPONENT 这是构成SKU的东西的列表,例如餐巾,纸杯,汉堡包,肉饼,可乐浆等。就像SKU具有描述和价格一样,组件也有描述和单位成本。(这也可以在子表中进行历史记录。)在这个表中,您通常会存储ROP。

  • COMPOSITION 这是一个BOM,它交叉SKU和COMPONENT,并说明每个COMPONENT的单位数量进入一个SKU的单位中。您需要其中一个来交叉两个SKU(用于组合套餐)。您可以使用一个表或两个表。两个表将让纯粹主义者感到满意,一个表从编码器的角度来看则更加方便。

  • SALE 这是一个交易表,提供了一个标题,用于记录一个或多个SKU的销售。该表将包括交易日期,收银员ID和其他标题项目。

  • SALE_ITEM 这是交易详细信息表,其中将包括销售了哪个SKU(以及数量)以及价格是多少。价格是以销售时的SKU价格的去归一化,但也可以包括任何特殊的价格覆盖。实际收取的SKU价格是归一化的好处,因为某些人可能会编辑SKU中的价格,并且您将失去跟踪该物品在销售时实际收取的金额。

  • INVENTORY_HDR 这是一个类似于销售概念的交易性表格,但它是用于记录库存交易的表头,例如收到新库存、使用库存(比如卖出)和用于库存调整。同样,这将包括日期/描述等信息,但如果您愿意,它可以包括指向 SALE_ITEM 的直接链接,以便跟踪与营收和成本有关的库存运动。虽然这不是必须的,但一些人喜欢建立交易之间的收入与成本之间的联系。

  • INVENTORY_DTL 这是一个库存交易的详细信息,表示哪个部件进出,进出数量,以及该移动应用于的 INVENTORY_HDR 交易。这也是您保留部件实际成本的地方。

  • LOCATION 如果您希望,还可以跟踪您收到和使用/出售的库存的物理位置。在餐厅中,这可能并不重要,但如果您有连锁店或者您的餐厅有用于组成原料的离线仓库,那么您可能会关心。

考虑以下 ERD 图:

ERD

要进行营收核算,您需要将 SALE_ITEM 表格中记录的金额加起来。

库存水平是基于为每个部件添加 INVENTORY_DTL 入库和出库而计算的。(不要将当前库存水平存储在表格中,这注定会导致对账问题。)

要进行成本核算,您需要将记录在INVENTORY_DTL表中的资金加起来。请注意,您通常不会知道确切地出售了哪个餐巾或面包,因此不可能将特定组件收据与特定SKU销售关联起来。相反,您需要有一种约定来确定用于任何给定SKU的组件。您可能有会计规则规定您需要使用哪种约定。大多数人使用FIFO。一些行业使用LIFO,我甚至看到过加权平均成本核算。


3
SALE视为收据,将INVENTORY_HDR视为提货单。每次销售可能涉及多个项目。这可能是因为您为几个人订购,或者您可能会点不同的菜品。您可能不需要此项标题,但它更能反映实际发生的情况。另一方面,如果您的仪表板指标之一是平均客户销售额,则需要标题以将同时出售的项目联系在一起。接收库存也是如此。交付通常包括许多不同的项目。 - Joel Brown
2
在这个模型中,您无法计算SKU的库存,因为SKU被宽泛地定义为一个或多个组件。OP的问题涉及快餐店场景。如果您去麦当劳,如何询问他们的Big Mac库存?Happy Meal的库存呢?这个问题没有答案,因为这些商品是从通用组件制备而成,这些组件用于许多商品。芥末只为Happy Meal准备吗?其中有多少是为Quarter Pounders准备的?这不是您应该应用于零售应用的模型,它适用于制造场景。 - Joel Brown
2
如果我们有一个E-R图表来更好地理解所有这些表,那就太好了 :) - abiieez
1
@abiieez - 我终于找到时间来满足你的建议。 - Joel Brown
1
@BlakeRivell 租赁物品与 OP 关于快餐店的问题不同。当您租赁物品时,它们通常在项目级别上进行标识。这意味着将“COMPONENT”拆分为两个表,一个用于标识出租物品的类型(“Husqvarna Chainsaw Model T540 XP” - 这将位于现在的组件位置),以及该物品的具体实例(“带有序列号 8843764 的链锯”)。物品实例可能是“INVENTORY_DTL”表和组件表之间的交集。 - Joel Brown
显示剩余5条评论

0

我建议完全将库存表与货币会计表分开。例如,你给出的例子我知道是荒谬的:对于普通快餐店来说,一杯价值0.90美元的可乐成本约为0.05-0.07美元,液体成本不到1美分,留下了约0.83美元的可观利润。为什么成本必须加起来等于0.90美元?

表格:

InventoryItems 字段:InventoryItemId、名称、当前库存水平、理想库存水平

InventoryChangeRecords 字段:InventoryChangeId、InventoryItemId、更改(整数)

RetailItems 字段:RetailItemId、名称、价格

RetailItemMakeup 字段:RetailItemId、InventoryItemId、数量

SaleTransactions 字段:SaleTransactionId、DateTime、TotalSale

SaleTransactionItems 字段:SaleTransactionId、RetailItemId、数量

对于每次销售,您应该使用 sproc(或触发器)更新 CurrentInventoryLevel,并将记录插入 InventoryChangeRecords 中。通过从 SaleTransaction 到 SaleTransactionItems 再到 RetailItemMakeup 的连接,您可以轻松地确定任何销售对库存的影响。

如果您想以更强大的方式(但在我看来是多余的)完成它,您可以在SaleTransactionItems和InventoryChangeRecords之间创建另一个多对多表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接