如何跟踪POS系统的产品成本?

时间:2015-01-10 19:37:18

标签: mysql database database-design point-of-sale

我正在设计销售点“POS”数据库,同时使用MySQL作为我的DBMS。

将产品添加到产品数据库时,我添加了产品名称(即“Coca-Cola 2.L”)和UPC代码,成本,价格,部门,供应商和数量。

因此,如果我收到1000瓶的订单,每瓶花费1美元

然后让我们说在未来2个月,我只剩下100瓶现货“我的成本为100美元”。现在,我订购了5000瓶以上,但这次是因为我订购了5000瓶,供应商每瓶给我0.10美元(即每件0.90美元的成本。)所以,我的第二笔订单的成本是4500美元。我想确保我非常准确地追踪我的利润。因此,我以1美元购买的100美元我希望能够以1美元的成本和新的订单以0.90美元的成本单独跟踪这些。

我目前跟踪每个销售商品的成本的方式,通过从产品表中读取当前成本,并将其与sales_transactions_items表以及售价,transaction_id和product_id一起保存。

我现在遇到的问题是,当我收到5000瓶时,我将成本从1美元改为0.90美元,这使我的利润上升了(100瓶x每瓶0.10美元)100x0.10 = 10美元的利润我实际上没有获利。出售数量后,出现这种差异是因为数量达到了5100瓶,其中100件以1美元购买,5,000件以0.90美元购买。

我的问题:如何解决这个问题,我可以真实地捕捉到每件物品花费了多少钱。

3 个答案:

答案 0 :(得分:2)

这是一个足够通用但过于简单的示例,说明了您的架构的外观

CREATE TABLE products
(
  `id` int not null auto_increment primary key, 
  `name` varchar(13), 
  `price` decimal(12, 2), -- current sale price. You might want to extract it into it's own table `prices`
  ...
);

CREATE TABLE orders
(
  `id` int not null auto_increment primary key, 
  `date` date,
  ...
);

CREATE TABLE order_items
(
  `id` int not null auto_increment primary key, 
  `order_id` int not null, 
  `product_id` int, 
  `quantity` decimal(12, 3), 
  `cost` decimal(12, 2),
  foreign key (`order_id`) references orders (id),
  foreign key (`product_id`) references products (id)
);

CREATE TABLE sales
(
  `id` int not null auto_increment primary key, 
  `date` datetime,
  ...
);

CREATE TABLE sale_items
(
  `id` int not null auto_increment primary key, 
  `sale_id` int not null, 
  `product_id` int, 
  `quantity` decimal(12, 3), 
  `price` decimal(12, 2),
  foreign key (`sale_id`) references sales (id),
  foreign key (`product_id`) references products (id)
);

这是 SQLFiddle 演示

这使您能够独立跟踪成本和销售额。


计算总销售额,实际总成本和每件产品保证金的一种方法

SELECT product_id, p.name, sales_quantity, sales_total, cost_total, sales_total - cost_total margin
  FROM
(
  SELECT product_id, sales_quantity, sales_total, SUM(
    CASE WHEN sales_quantity >= running_quantity 
           THEN cost * quantity
         WHEN sales_quantity BETWEEN running_quantity - quantity AND running_quantity
           THEN cost * (sales_quantity - (running_quantity - quantity))
          ELSE 0 
     END) cost_total
    FROM
  (
    SELECT s.*, o.cost, o.quantity, o.running_quantity
      FROM
    (
      SELECT product_id, 
             SUM(quantity * price) sales_total, 
             SUM(quantity) sales_quantity
      FROM sale_items
     GROUP BY product_id
    ) s JOIN 
    (
      SELECT product_id, cost, quantity, (
        SELECT SUM(quantity)
          FROM order_items
         WHERE product_id = i.product_id
           AND order_id <= i.order_id
         ) running_quantity
        FROM order_items i
    ) o
        ON s.product_id = o.product_id
  ) q
   GROUP BY product_id, sales_quantity, sales_total
) q JOIN products p
    ON q.product_id = p.id

示例输出:

| PRODUCT_ID |          NAME | SALES_QUANTITY | SALES_TOTAL | COST_TOTAL | MARGIN |
|------------|---------------|----------------|-------------|------------|--------|
|          1 | Coca-Cola 2.L |            150 |       187.5 |        145 |   42.5 |

这是 SQLFiddle 演示

你可能会看到,在这个例子中,150个售出的100瓶装100美元(1美元* 100美元),其余50个售价45美元(0.9 * 50)

答案 1 :(得分:0)

Declare @FromDate DateTime=GetDate()
declare @ToDate DateTime=GetDate()
Select ToDateProfit.ProductID,ToDateProfit.Name,ToDateProfit.sales_quantity-   ISNULL(FromDateProfit.sales_quantity,0) as Sales_Quantity
,ToDateProfit.sales_total-ISNULL(FromDateProfit.sales_total,0) as Sales_Total
,ToDateProfit.cost_total-ISNULL(FromDateProfit.cost_total,0) as Cost_Total
,ToDateProfit.margin-ISNULL(FromDateProfit.margin,0) as Margin
 From
(
SELECT P.ProductID, p.name, sales_quantity, sales_total, cost_total, sales_total - cost_total margin
  FROM
(
  SELECT productid, sales_quantity, sales_total, SUM(
CASE WHEN sales_quantity >= running_quantity 
       THEN  PurchasePrice* quantity
     WHEN sales_quantity BETWEEN running_quantity - quantity AND running_quantity
       THEN PurchasePrice * (sales_quantity - (running_quantity - quantity))
      ELSE 0 
 END) cost_total
FROM
  (
SELECT s.*, o.PurchasePrice, o.quantity, o.running_quantity
  FROM
(
  SELECT ProductID, 
         SUM((quantity * UnitPrice)/ExchangeRate) sales_total, 
         SUM(quantity) sales_quantity
  FROM SaleDetail
  Inner Join Sale on Sale.SaleID=SaleDetail.SaleID
 where Convert(Date,Sale.SaleDate)<=Convert(date,@ToDate) --(must minus saledate <FromDate            (GetDate() is ToDate)         )
 GROUP BY ProductID
) s JOIN 
    (
  SELECT  productid, BuyingPrice/ExchangeRate as PurchasePrice, quantity, (
    SELECT SUM(quantity)
      FROM PurchaseDetail
     inner join Purchase Pur on Pur.PurchaseID=PurchaseDetail.PurchaseID 
     WHERE productid = i.productid
       AND Pur.Date <= PurI.date ----Fifo (if want lifo change <= to >=)
     ) running_quantity
    FROM PurchaseDetail i
    Inner join Purchase PurI on PurI.PurchaseID=i.PurchaseID
) o
ON s.productid = o.productid
)q
GROUP BY productid, sales_quantity, sales_total
) q JOIN product p
ON q.ProductID = p.ProductID
)ToDateProfit 
Left Join
(
SELECT P.ProductID, p.name, sales_quantity, sales_total, cost_total, sales_total - cost_total margin
FROM
(
SELECT productid, sales_quantity, sales_total, SUM(
CASE WHEN sales_quantity >= running_quantity 
       THEN  PurchasePrice* quantity
     WHEN sales_quantity BETWEEN running_quantity - quantity AND running_quantity
       THEN PurchasePrice * (sales_quantity - (running_quantity - quantity))
      ELSE 0 
 END) cost_total
FROM
(
SELECT s.*, o.PurchasePrice, o.quantity, o.running_quantity
FROM
(
SELECT ProductID, 
         SUM((quantity * UnitPrice)/ExchangeRate) sales_total, 
         SUM(quantity) sales_quantity
  FROM SaleDetail
  Inner Join Sale on Sale.SaleID=SaleDetail.SaleID
 where Convert(Date,Sale.SaleDate)<Convert(date,@FromDate) --(must minus saledate <FromDate            (GetDate() is ToDate)         )
 GROUP BY ProductID
) s JOIN 
(
  SELECT  productid, BuyingPrice/ExchangeRate as PurchasePrice, quantity, (
    SELECT SUM(quantity)
      FROM PurchaseDetail
     inner join Purchase Pur on Pur.PurchaseID=PurchaseDetail.PurchaseID 
     WHERE productid = i.productid
       AND Pur.Date <= PurI.date ----Fifo (if want lifo change <= to >=)
     ) running_quantity
    FROM PurchaseDetail i
    Inner join Purchase PurI on PurI.PurchaseID=i.PurchaseID 
) o    ON s.productid = o.productid 
) q 
GROUP BY productid, sales_quantity, sales_total
) q JOIN product p
ON q.ProductID = p.ProductID
)FromDateProfit on FromDateProfit.ProductID=ToDateProfit.ProductID
Inner Join ---------Only Product
(
Select Product.ProductID From Product
Inner Join SaleDetail On SaleDetail.ProductID=Product.ProductID
Inner Join Sale On Sale.SaleID=SaleDetail.SaleID
Where CONVERT(Date,SaleDate)>=CONVERT(Date,@FromDate) And  CONVERT(Date,SaleDate)<=CONVERT(Date,@ToDate)
Group By Product.ProductID)SP On SP.ProductID=ToDateProfit.ProductID

答案 2 :(得分:0)

“我想确保我非常准确地追踪我的利润。因此,我以1美元购买的100美元我希望能够以1美元的成本和新的订单以0.90美元的成本单独跟踪这些。” - 这不是必需的。您必须计算当前平均价格并使用它计算利润。您没有每个瓶子的序列号,因此即使您想知道每个项目的利润 - 您也无法做到。从业主的角度来看,重要的是要知道可口可乐的总利润,而不是“从这个瓶子里得到0.50,从那瓶子里得到0.45”。