Proyecto de datos / presupuesto / order / factura

Actualmente estoy trabajando en un proyecto pequeño en el que necesito modelar el siguiente escenario:

Guión

  1. Llamadas de clientes, quiere una cotización para un automobile nuevo.
  2. Representante de ventas Registre la información del cliente.
  3. Representante de ventas cree una cotización en el sistema y agregue un artículo a la cotización (el automobile).
  4. Representante de ventas envíe la cotización al cliente por correo electrónico.
  5. El cliente acepta la cotización, y la cotización ya no es una cotización sino una order.
  6. Representante de ventas verifica el pedido, todo está bien y él factura el pedido. El pedido ya no es un pedido, sino una factura.

Pensamientos

Necesito un poco de ayuda para encontrar la forma ideal de modelar esto, pero tengo algunas ideas.

  1. Estoy pensando que tanto el borrador / cita / factura es básicamente un pedido.
  2. Draft / quote / invoice necesita numbers separados únicos (id's) así que no estoy pensando en tablas separadas para todos ellos.

Modelo

Este es mi model de datos v.1.0, por favor déjame saber lo que piensas.

Modelo de datos v.1.0 Preocupaciones

Sin embargo, tengo algunas preocupaciones con respecto a este model:

  1. Draft / quote / invoice puede tener diferentes artículos y precios en las líneas de pedido. En este model, todo borrador / cita / factura está conectado al mismo pedido y también ordera líneas, lo que hace imposible tener líneas de presupuesto / líneas de giro / líneas de factura separadas. Quizás deba crear nuevas tablas para esto, pero básicamente la misma información se almacenará en varias tablas, y eso tampoco es bueno.
  2. A veces, dos o más citas se convierten en una factura, ¿cómo se encargaría este model de esto?

Si tiene algún consejo sobre cómo modelar esto mejor, ¡por favor hágamelo saber!

EDITAR: model de datos v.1.4 enter image description here

Parece que ha modelado cada una de estas cosas (presupuesto, order, borrador, factura) como estructuralmente idénticas a todas las demás. Si ese es el caso, entonces puede "empujar" todos los attributes similares hacia arriba en una sola tabla.

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) ); 

Creo que funcionará para el model que ha descrito, pero creo que será mejor servirlo a largo ploop modelando estos como un supertipo / subtipo. Las columnas comunes a todos los subtypes son empujadas "hacia arriba" hacia el supertipo; cada subtipo tiene una tabla separada para los attributes exclusivos de ese subtipo.

Esta pregunta SO y su respuesta aceptada (y comentarios) ilustran un layout de supertipo / subtipo para comentarios de blog. Otra pregunta se relaciona con individuos y organizaciones. Otro más relacionado con el personal y los numbers de teléfono.

Luego . . .

Esto no está completo, pero estoy fuera de time. Sé que no incluye líneas de pedido. Podría haberse perdido algo más.

 -- "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); 

Debería haber una tabla "quotelines", que sería similar a "líneas de pedido". Del mismo modo, debe tener una tabla 'facticelines'. Todas estas tablas deben tener un campo 'precio' (que nominalmente será el precio pnetworkingeterminado de la parte) junto con un campo 'descuento'. También puede agregar un campo 'descuento' a las tablas 'cotizaciones', 'órdenes' y 'facturas', para manejar cosas como descuentos en efectivo u ofertas especiales. A pesar de lo que escriba, es bueno tener tablas separadas, ya que el monto y el precio de la cotización pueden no coincidir con los pedidos reales del cliente, y de nuevo puede no ser la misma cantidad que usted realmente proporciona.

No estoy seguro de cuál es la tabla del 'borrador' – probablemente podría combinar las tablas 'borrador' y 'facturas' ya que contienen la misma información, con un campo que contiene el estado de la factura, borrador o final. Es importante separar los datos de su factura de los datos de la order, ya que presumiblemente pagará impuestos de acuerdo con sus ingresos (facturas).

'Cotizaciones', 'Pedidos' y 'Facturas' deberían tener un campo (key externa) que contenga el valor del representante de ventas; este campo apuntaría a la tabla 'SalesRep' inexistente. También podría agregar un campo 'salesrep' en la tabla 'clientes', que apunta al representante pnetworkingeterminado para el cliente. Este valor se copyría en la tabla de 'cotizaciones', aunque podría cambiarse si un representante diferente del valor pnetworkingeterminado entregara la cotización. Del mismo modo, este campo debe copyrse cuando se realiza un pedido a partir de un presupuesto y una factura de un pedido.

Probablemente podría agregar mucho más, pero todo depende de cuán complejo y detallado sea el sistema que desee. Es posible que necesite agregar alguna forma de 'list de materiales' si los autos están configurados de acuerdo con sus opciones y tienen un precio acorde.