0

我正在爲租賃發票生成創建一些數據庫模型。 發票由N個預訂時間範圍組成。DB架構:版本化的價格模型與發票相關的數據

每個預訂都屬於價格模式。價格模型是一組確定最終價格的規則(基準價格+季節價格+數量減少+ ...)。

這意味着發票內N張預訂的最終價格可能是一個複雜的計算,當然我想跟蹤最終價格計算的每個方面以便以後查看發票。

問題是,價格模型可能在未來發生變化。因此,在發票生成時,有兩種可能性:

  • (a)絕對不要更改價格模型。通過對其進行版本控制,使其不可變,並從發票中引用具體版本。 (b)將所有價格信息,折扣和額外費用存入發票中。這意味着很多數據,因爲發票包含N份預訂,部分預訂可能在季節價格的範圍內。 基本上,我會分解每個預訂到它的日子,每天我會有N行計算基本價格,折扣和額外費用。

可能表型號:

Invoice 
    id: int 

InvoiceBooking   # Each booking. One invoice has N bookings 
    id: int 
    invoiceId: int 
    (other data, e.g. guest information) 

InvoiceBookingDay  # Days of a booking. Each booking has N days 
    id: int 
    invoiceBookingId: id 
    date: date 

InvoiceBookingDayPriceItem # Concrete discounts, etc. One days has many items 
    id: int 
    invoiceBookingDayId: int 
    price: decimal 
    title: string 

我的問題是,我應該喜歡,爲什麼它的方式。

我考慮:

  • 隨着溶液(a)中,發票將每一個數據被看作時間使用價格模型信息重新計算。我不喜歡這個,因爲算法可以改變。發票的「只讀」性質並不自然。 此外,價格模型的版本處理並不是一項簡單的任務,用戶需要了解版本概念,這增加了應用程序的複雜性。

  • 有了解決方案(b),我生成了一堆嵌套的數據,它增加了架構的複雜性。

您更喜歡哪種方式?我錯過了什麼嗎?

謝謝

回答

1

怎麼樣 B'

重新計算髮票的任何組件並不是最佳實踐,特別是在打印組件時。發票和發票細節應該是不可變的,並且您應該能夠重新生成它而不用重新計算。

如果您在確定如何達到一定數量時遇到問題,或者如果程序中存在錯誤,您會很高興獲得詳細信息,特別是在計算複雜時。

此外,保留定價模型的歷史記錄是一個不錯的主意,因此您可以驗證如何達到一定的價格。你可以簡化你的用戶。他們不必查看歷史記錄 - 但是您應該將其更改記錄在歷史記錄中。

2

我推薦了第三種選擇。我稱之爲暫時(時間)版本化,表格的佈局非常簡單。你沒有描述你的定價數據,所以我只是展示一個簡單的例子。

Table: DailyPricing 
ID EffDate  Price ... 
A 01/01/2015 17.50 ... 
B 01/01/2015 20.00 ... 
C 01/01/2015 22.50 ... 
B 01/01/2016 19.50 ... 
C 07/01/2016 24.00 ... 

這表明,所有三個價格明細表(A,B和C的任何方法,您使用的價格水平來區分只是代表)分別獲得了價格上的1月1日,2015年在2016年1月1日,價格的計劃B減少了。 7月份,C計劃的價格上漲。

要獲得計劃的當前價格,查詢是這樣的:

select dp.Price 
from DailyPricing dp 
where dp.ID = 'A' 
    and dp.Effdate =(
     select Max(dp2.EffDate) 
     from DailyPricing dp2 
     where dp2.ID = dp.ID 
      and dp2.EffDate >= :DateOfInterest); 

DateOfInterest變量將被加載當前的日期/時間。該查詢返回當前有效的一個價格。在這種情況下,2015年1月1日設定的價格自從生效以來從未改變過。如果搜索是針對B計劃的,則2016年1月1日設定的價格將被退回,C計劃則是2016年7月1日設定的價格。這些是針對每個計劃設定的最新價格;也就是目前的價格。

這樣的查詢更有可能在與發票表的連接中,因此您可以執行價格計算。

select ... 
from Invoices i 
join DailyPricing dp 
    on dp.ID = i.ID 
    and dp.Effdate =(
     select Max(dp2.EffDate) 
     from DailyPricing dp2 
     where dp2.ID = dp.ID 
      and dp2.EffDate >= i.InvoiceDate) 
where i.ID = 1234; 

這比簡單的查詢稍微複雜一點,但您要求更復雜的數據(或者更復雜的數據視圖)。但是,此計算可能只會執行一次,並將最終價格存回發票數據或其他地方。

只有在客戶進行了一些更改或您正在審覈審覈後重新檢查計算的準確性時,纔會再次進行計算。

然而,注意到一些微妙但非常重要的東西。如果上面的查詢是針對剛剛創建的發票執行的,那麼InvoiceDate將是當前日期,並且返回的價格將是當前價格。但是,如果查詢是作爲兩年前發票上的驗證運行的,則發票日期爲兩年前,且退貨價格將爲兩年前生效的價格。

換句話說,返回當前數據的查詢和返回過去數據的查詢是相同的查詢。

這是因爲當前數據和過去的數據保持在同一個表中,只有數據生效日期不同。我認爲,這是關於你想要做的最簡單的解決方案。