关于sql:数据建模草稿/报价/订单/发票

Data modelling draft/quote/order/invoice

我目前正在一个小项目中工作,在这个项目中我需要模拟以下场景:

脚本

  • 客户打电话来,他想要一辆新车的报价。
  • 销售代表登记客户信息。
  • 销售代表。在系统中创建报价,并将项目添加到报价(汽车)。
  • 销售代表。通过电子邮件将报价发送给客户。
  • 客户接受报价,现在报价不再是报价而是订单。
  • 销售代表检查订单,一切正常,他给订单开发票。现在订单不再是订单,而是发票。
  • 思想

    我需要一点帮助,找到一个理想的模型,但我有一些想法。

  • 我认为汇票/报价单/发票基本上都是订单。
  • 汇票/报价单/发票需要单独的唯一编号(ID),所以我想为所有这些单独的表格。
  • 模型

    这是我的1.0版数据模型,请告诉我你的想法。

    Data model v.1.0。关注

    但是,我对这个模型有一些担心:

  • 汇票/报价单/发票在订单行上可能有不同的项目和价格。在此模型中,所有草稿/报价/发票都与同一订单和订单行相连,因此不可能有单独的报价行/草稿行/发票行。也许我应该为此创建新的表,但基本上相同的信息会存储在多个表中,这也不好。
  • 有时两个或多个报价会变成一张发票,这个模型将如何处理这个问题?
  • 如果您对如何更好地建模有任何建议,请告诉我!

    编辑:数据模型V.1.4氧化镁


    看起来你已经把这些东西中的每一个——报价单、订单、汇票、发票——建模为在结构上与所有其他东西相同的模型。如果是这样,那么您可以将所有类似的属性"推"到一个表中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    CREATE TABLE statement (
        stmt_id INTEGER PRIMARY KEY,
        stmt_type CHAR(1) NOT NULL CHECK (stmt_type IN ('d', 'q', 'o', 'i')),
        stmt_date DATE NOT NULL DEFAULT CURRENT_DATE,
        customer_id INTEGER NOT NULL  -- references customer (customer_id)
    );

    CREATE TABLE statement_line_items (
        stmt_id INTEGER NOT NULL REFERENCES statement (stmt_id),
        line_item_number INTEGER NOT NULL,
        -- other columns for line items
        PRIMARY KEY (stmt_id, line_item_number)
    );

    我认为这对于您所描述的模型是可行的,但我认为从长远来看,通过将这些模型建模为超类型/子类型,可以更好地为您服务。所有子类型通用的列都被"向上"推送到父类型中;每个子类型都有一个单独的表,用于显示该子类型特有的属性。

    这个问题及其接受的答案(和注释)说明了博客注释的超类型/子类型设计。另一个问题涉及个人和组织。另一个与员工和电话号码有关。

    稍后。…

    这还不完整,但我没时间。我知道它不包括行项目。可能错过了别的东西。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    --"Supertype". Comments appear above the column they apply to.
    CREATE TABLE statement (
      -- Autoincrement or serial is ok here.
      stmt_id INTEGER PRIMARY KEY,    
      stmt_type CHAR(1) UNIQUE CHECK (stmt_type IN ('d','q','o','i')),
      -- Guarantees that only the order_st table can reference rows having
      -- stmt_type = 'o', only the invoice_st table can reference rows having
      -- stmt_type = 'i', etc.
      UNIQUE (stmt_id, stmt_type),
      stmt_date DATE NOT NULL DEFAULT CURRENT_DATE,
      cust_id INTEGER NOT NULL -- references customers (cust_id)
    );

    -- order"subtype"
    CREATE TABLE order_st (
      stmt_id INTEGER PRIMARY KEY,
      stmt_type CHAR(1) NOT NULL DEFAULT 'o' CHECK (stmt_type = 'o'),
      -- Guarantees that this row references a row having stmt_type = 'o'
      -- in the table"statement".
      UNIQUE (stmt_id, stmt_type),
      -- Don't cascade deletes. Don't even allow deletes. Every order given
      -- an order number must be maintained for accountability, if not for
      -- accounting.
      FOREIGN KEY (stmt_id, stmt_type) REFERENCES statement (stmt_id, stmt_type)
        ON DELETE RESTRICT,
      -- Autoincrement or serial is *not* ok here, because they can have gaps.
      -- Database must account for each order number.
      order_num INTEGER NOT NULL,  
      is_canceled BOOLEAN NOT NULL
        DEFAULT FALSE
    );

    -- Write triggers, rules, whatever to make this view updatable.
    -- You build one view per subtype, joining the supertype and the subtype.
    -- Application code uses the updatable views, not the base tables.    
    CREATE VIEW orders AS
    SELECT t1.stmt_id, t1.stmt_type, t1.stmt_date, t1.cust_id,
           t2.order_num, t2.is_canceled
    FROM statement t1
    INNER JOIN order_st t2 ON (t1.stmt_id = t2.stmt_id);


    应该有一个类似于"orderlines"的"Quotelines"表。同样,您应该有一个"invoicelines"表。所有这些表都应该有一个"价格"字段(名义上将是零件的默认价格)和一个"折扣"字段。您还可以在"报价"、"订单"和"发票"表中添加"折扣"字段,以处理现金折扣或特别优惠等事项。尽管你写了什么,但最好有单独的表格,因为报价单中的金额和价格可能与客户实际订购的不匹配,而且可能与你实际供应的金额不同。

    我不确定"草稿"表是什么-您可以将"草稿"表和"发票"表结合起来,因为它们包含相同的信息,其中一个字段包含发票的状态-草稿或最终。将发票数据与订单数据分开是很重要的,因为您可能会根据收入(发票)纳税。

    "Quotes"、"Orders"和"Invoices"都应该有一个保存销售代表值的字段(外键);此字段将指向不存在的"Salesrep"表。您还可以在"客户"表中添加一个"Salesrep"字段,该字段指向客户的默认代表。该值将被复制到"Quotes"表中,但如果默认值的另一个rep给出了报价,则可能会更改该值。同样,当从报价单和订单发票中生成订单时,应复制此字段。

    我可能会添加更多,但这一切都取决于您想要建立的系统有多复杂和详细。如果汽车是根据选项配置的,并且相应地定价,那么您可能需要添加某种形式的"物料清单"。