The invoice database design, might look something like this...
http://www.databaseanswers.org/data_models/invoices_and_payments/index.htm
Now If the user decides to change/revise the product code/description
It will change the previous order and invoice produce code/description :(
What do you do? Copy the product code description to the invoice table instead?
You basically have two options:
either you make your Products table "time-enabled" (also known as "temporal database"), e.g. you keep the "previous" state of your individual product in your table, and you give every entry a ValidFrom / ValidTo pair of dates. That way, if you change your product, you get a new entry, and the previous one remains untouched, referenced from those invoices that used it; only the ValidTo date for the product gets updated
or:
you could copy the products (at least those bits you need for your invoice) to the invoice - that'll make sure you always know what the product looked like when you created the invoice - but this will cause lots of data duplication (not recommended)
See this other Stackoverflow question on temporal databases as another input, and also check out this article on Simple-Talk: Database Design: A Point in Time Architecture
Related
Let me describe briefly the table structures:
Customer Table
id | name | address_line_one | address_line_two | contact_no_one
SaleInvoice Table
id | id_Customer (Foreign Key) | invoice_no
If I have to print a Sale invoice, I have to use the Customer information (like name, address) from the Customer table.
Assume that after a year, some customer data changes (like name or address), and I update the new data in my customer table. Now, if the customer asks for an old invoice, it will be printed with the new customer data which shall be legally wrong.
Does that mean, I have to create
name_customer
address_line_one_customer
...
and all these fields in the Sale Invoice table too?
If yes, is there a better way to get data from these fields in Customer table to the Sale Invoice table then to write a SQL query to get the values and then set the values?
This is really up to you. In some cases, where it is a legal document, you will save all the details so that you can always bring it up the way it was created. Alternatively if you are producing pdf invoices then save them to be 100% sure.
The other alternative is to create a CustomerHistory table, so that past versions are always saved with a date range, so that you can go back to the old version.
It depends on the use cases, but those are your main options.
It sounds like a problem easily solved by placing the Employee table in version normal form (VNF). This is actually just a flavor of 2nf but done in a way that provides the ability to query current data and past data using the same query.
A datetime parameter is used to provide the distinction. When the value is set to NOW, the current data is returned. When the value is set to a specific datetime value in the past, the data that was current at that date and time is returned.
A brief discussion of the particulars can be found here. That answer also contains links to more information if you think it is something that would work for you.
The following problem comes from: https://cs.senecac.on.ca/~dbs201/pages/Normalization_Practice.htm (Exercise 3)
The unnormalized table appears like this:
To comply with First Normal Form, all repeating groups must be dealt with. In this case, multiple products could appear on a single order, so it must be given its own entity and related back to the original table:
These tables are also in Second Normal Form, because in all of the tables, each non-key attribute is dependent on the primary key in it's table.
Finally, to bring it to Third Normal Form, Customer must be given its own entity and related back to the original Order entity:
Have I properly normalized the original table into Third Normal Form? If not, please provide feedback explaining what I've done wrong.
Store some Customer's Primary details in Order Table which are available on Bill, because once customer details is changed then Bill is differ then original.
Same for Product, Store Product price in Product_Order table, because once Product price changed Bill will change.
I'm currently developing a small customer relationship and invoice management system for my client. And I have run into some small issues which I would like do discuss.
What is the best practice around orders, customers and products. Should my client be able to delete orders, customers and products?
Currently I have designed my database around the principle of relationships between order, customer and product like this:
Customer
ID
Name
...
Product
ID
Name
Price
...
Order
ID
CustomerID
OrderDate
...
Order Line
ID
OrderID
ProductID
Like this I can connect all the different tables. But what if my client delete a product, what happens when he later open a order he created months ago which had that item in it. It would be gone, since it has been deleted. Same goes for customer.
Should I just disable the products and customers when the delete button is clicked or what is the best practice?
If I lets say diable a product whenever my client decides to delete it, what happens then if he later tries to add a new product with the same product ID as a disabled product, should I just enable that item again?
Please share your wisdom :D
"If I lets say diable a product whenever my client decides to delete it, what happens then if he later tries to add a new product with the same product ID as a disabled product, should I just enable that item again?"
Depends entirely on your business scenario - what is unique in the way customers maintain it currently? (say manually?) How do they handle when an old product which was earlier discontinued suddenly reappears? (Do they treat it as a new product or start referring to the old product?) I guess there are no right or wrong answers to these questions, it depends on the functionality - it is always advisable to understand the existing processes (minus the software) already followed by the customers and then map them to the software functionality.
For eg. you could always add a 'A product with this code already exists - do you want to use that instead of creating a new one?' kind of a message. Also, the product ids that you use in your tables as foreign keys, and the ones that you use to show the customer, better be different - you dont want to get them mixed up.
Why would you want to be able to delete orders? I would think that such a system would lock orders so that you know you have a good history. Same goes for customers, why delete them? Perhaps a way to "archive" them, having to set some flag, that way they don't show up on customer lists or something.
As for disabling and then entering a new item with the same product ID - I'm not sure why you'd do that either, each product ID is unique for a reason, even if you discontinue a product, it should keep it's product ID so you have a record. But if you must, then you could put a constraint in the business rules, something to the effect of "If there is no product that is active with this product ID then allow it. If we have a product that is active and it has the same product ID, then throw an error." Thus, you only allow for one active product with that product ID - but honestly, I think this would be confusing, and on the back end you'll want to use a unique id that is unchanging for each product to link between tables.
Instead of "deleting" I would add a boolean column for IsActive. That way you won't loose historical data. For instance, if they are able to delete a customer then they won't be able to look at history regarding that customer and it may make looking at statistical data hard or impossible. For the order table you could have a column that represents something like "current", "canceled", "filled" to accomplish the same thing. That column should be a code to a lookup/codetable.
(Sorry about the vagueness of the title; I can't think how to really say what I'm looking for without writing a book.)
So in our app, we allow users to change key pieces of data. I'm keeping records of who changed what when in a log schema, but now the problem presents itself: how do I best represent that data in a view for reporting?
An example will help: a customer's data (say, billing address) changed on 4/4/09. Let's say that today, 10/19/09, I want to see all of their 2009 orders, before and after the change. I also want each order to display the billing address that was current as of the date of the order.
So I have 4 tables:
Orders (with order data)
Customers (with current customer data)
CustomerOrders (linking the two)
CustomerChange (which holds the date of the change, who made the change (employee id), what the old billing address was, and what they changed it to)
How do I best structure a view to be used by reporting so that the proper address is returned? Or am I better served by creating a reporting database and denormalizing the data there, which is what the reports group is requesting?
There is no need for a separate DB if this is the only thing you are going to do. You could just create a de-normalized table/cube...and populate and retrieve from it. If your data is voluminous apply proper indexes on this table.
Personally I would design this so you don't need the change table for the report. It is a bad practice to store an order without all the data as of the date of the order stored in a table. You lookup the address from the address table and store it with the order (same for partnumbers and company names and anything that changes over time.) You never get information on an order by joining to customer, address, part numbers, price tables etc.
Audit tables are more for fixing bad changes or looking up who made them than for reporting.
In making a pretty standard online store in .NET, I've run in to a bit of an architectural conundrum regarding my database. I have a table "Orders", referenced by a table "OrderItems". The latter references a table "Products".
Now, the orders and orderitems tables are in most aspects immutable, that is, an order created and its orderitems should look the same no matter when you're looking at the tables (for instance, printing a receipt for an order for bookkeeping each year should yield the same receipt the customer got at the time of the order).
I can think of two ways of achieving this behavior, one of which is in use today:
1. Denormalization, where values such as price of a product are copied to the orderitem table.
2. Making referenced tables immutable. The code that handles products could create a new product whenever a value such as the price is changed. Mutable tables referencing the products one would have their references updated, whereas the immutable ones would be fine and dandy with their old reference
What is your preferred way of doing this? Is there a better, more clever way of doing this?
It depends. I'm writing on a quite complex enterprise software that includes a kind of document management and auditing and is used in pharmacy.
Normally, primitive values are denormalized. For instance, if you just need a current state of the customer when the order was created, I would stored it to the order.
There are always more complex data that that need to be available of almost every point in time. There are two approaches: you create a history of them, or you implement a revision control system, which is almost the same.
The history means that every state that ever existed is stored as a separate record, in the same or another table.
I implemented a revision control system, where I split records into two tables, one for the actual item, lets say a product, and the other one for its versions. This way I can reference the product as a whole, or any specific version of it, because both have its own primary key.
This system is used for many entities. I can safely reference an object under revision control from audit trail for instance or other immutable records. At the beginning it seems to be more complex to have such a system, but at the end it is very straight forward and solves many problems at once.
Storing the price in both the Product table and the OrderItem table is NOT denormalizing if the price can change over time. Normalization rules say that every "fact" should be recorded only once in the database. But in this case, just because both numbers are called "price" doesn't make them the same thing. One is the current price, the other is the price as of the date of the sale. These are very different things. Just like "customer zip code" and "store zip code" are completely different fields; the fact that both might be called "zip code" for short does not make them the same thing. Personally, I have a strong aversion to giving fields that hold different data the same name because it creates confusion. I would not call them both "Price": I would call one "Current_Price" and the other "Sale_Price" or something like that.
Not keeping the price at the time of the sale is clearly wrong. If we need to know this -- which we almost surely do -- than we need to save it.
Duplicating the entire product record for every sale or every time the price changes is also wrong. You almost surely have constant data about a product, like description and supplier, that does not change every time the price changes. If you duplicate the product record, you will be duplicating all this data, which definately IS denormalization. This creates many potential problems. Like, if someone fixes a spelling error in the product description, we might now have the new record saying "4-slice toaster" while the old record says "4-slice taster". If we produce a report and sort on the description, they'll get separated and look like different products. Etc.
If the only data that changes about the product and that you care about is the price, then I'd just post the price into the OrderItem record.
If there's lots of data that changes, then you want to break the Product table into two tables: One for the data that is constant or whose history you don't care about, and another for data where you need to track the history. Like, have a ProductBase table with description, vendor, stock number, shipping weight, etc.; and a ProductMutable table with our cost, sale price, and anything else that routinely changes. You probably also want an as-of date, or at least an indication of which is current. The primary key of ProductMutable could then be Product_id plus As_of_date, or if you prefer simple sequential keys for all tables, fine, it at least has a reference to product_id. The OrderItem table references ProductMutable, NOT ProductBase. We find ProductBase via ProductMutable.
I think Denormalization is the way to go.
Also, Product should not have price (when it changes from time to time & when price mean different value to different people -> retailers, customers, bulk sellers etc).
You could also have a price history table where it contains ProductID, FromDate, ToDate, Price, IsActive - to maintain the price history for a product.