I am researching how to create a ecommerce database. After some searches, this is what I found:
The problem here is the OrderDetails is reference back to the Products table. If I edited the Product like price, sku etc, it will affected the previously added order.
I can insert the Product data (serialized, or jsonized) in a new column in OrderDetails column when the order 1st created. But the con is it will hard to query, if I want to query specific data from the product data.
My question is how to design the OrderDetails product stick to data when the order is created, so in the future if I edited the product, it will not lost that data.
The problem here is the OrderDetails is reference back to the Products table. If I edited the Product like price, sku etc, it will affected the previously added order.
Suggest you read the schema before making plainly false statements like that.
OrderDetails referring to Products is not a "problem", it's what I would expect: a Customer mustn't order a Product that doesn't exist.
And to answer my q about what's in the etc from your first version: OrderDetail includes price. That's a common structure: OrderDetail's price is taken from Product at the time of the Customer placing an Order. It's the price quoted to the Customer; so we are legally bound to charge the Customer that price. If the price subsequently changes on Product, that doesn't affect this Order.
Similarly: IDSKU, Size, Colour appear on OrderDetails, so if you "edited the Product", it won't affect "previously added order".
There's nothing "hard to query" here. If you want Product data (perhaps to place a new Order), query Product. If you want historical actual-Order data, query OrderDetails. If you want to look for discrepancies, OrderDetails INNER JOIN Product ON OrderDetails.ProductID = Product.ProductID. Now you have to be careful to dot-prefix Size, Colour for the table you want. But note that UnitPrice is distinct from Price.
My question is how to design the OrderDetails product stick to data when the order is created, so in the future if I edited the product, it will not lost that data.
You should now be able to answer your own question.
Related
I have analyzed my as below and I have two point I am confused about
1- currently when I insert an items within orders I give order_ID as a PK
so each item within the order as its own PK... and same customer_id (FK) for all Item within the order so ... in that case the invoice number is same as the customer_ID
Is that what should think goes on or there is something wrong with this work flow ?
2-in some cases I don't need to record the customer information I just want to
insert the orders without their customer info.. I don't have clear idea about how think should happen :S
3- IF I want to apply a discount on some customer orders where the discount should I allow user to able to apply on the item per orders level ?
or on the whole order ? and where the discount column should be stored
1 - This design seems fine for the problem. You are stating that for every product ordered, this is the customer line. You can pick the ID, name, tax/fiscal number, address, etc.
2 - If you don't need any kind of customer information, make the customer_id on the Orders table accept NULL. It is the cleanest way to do it.
If for some reason NULLs are not an option or you want to keep on the database some basic anonymous customer data, you can create a line on customers for anonymous users (Ex.: ID: 1 / Name: ANONYMOUS ...) and place that ID on the order line.
3 - Placing the discount per product ordered might be the better idea.
If you want to apply a discount for the complete order, you just need to place that discount on every single order line.
If you want to apply a discount for a single product, you just need to place that discount on that product line.
If you want to apply a discount for a single product with a limited ammount of quantity (Ex.: Discount of 50% but limited to 1 purchase), and the customers buys more than that limit, you just need to place 2 orders for the same product. One with the discount and max quantity and the other without discount and the rest of the quantity.
Placing this on the order level wouldn't work for single product discounts.
This were answers to your questions. I would also question your design in points like:
If the customer changes address, is your order supposed to change too? If not, you should use the normal approach for orders, which is to have a order header table, with fixed information, like the address and the foreign key to the customer, and a order line table, like your orders line, but with a foreign key to the order header. That also avoids repetition.
Are you expecting up to 2 phone numbers? If you do, the design is ok. If you don't know how many phone numbers to expect, maybe a table with phone numbers, with foreign keys to the customer might be a better approach.
I am designing an e-commerce website that has the following scenario:
A customer can purchase items and create an order.
The order may have unknown fee that will be added after the customer
pays the total amount of the items. That is, the customer pays
certain amount first. The order adds some fee and changes the total.
And the customer pays again for the difference. But the two (or
more) payments are associated with the same order.
(Optional) The customer can submit a single payment for multiple
orders.
Currently, I have an Order table and each order may consist of multiple OrderLineItems (simplified schema):
Order
=====
customer
line_items
total
status
OrderLineItem
=============
price
quantity
order
product
A payment is associated with an order (simplified schema):
Payment
=======
order
payment_account
total
result
It seems to be very hard to support the multiple payments for a single order scenario in the current implementation. I reckon that I have to introduce immutable invoices in the system, and the payment should be associated with an invoice instead of an order. However, I would need some help with the order/invoice/payment modeling for the above scenario. Some specific questions I have:
An order and an invoice look very similar to me (e.g. both have
items and totals). What is the major difference in typical
e-commerce systems?
How should I model invoices for my scenario? Should I have
OrderLineItems for an Order AND InvoiceLineItems for an Invoice?
Some preliminary thoughts: I will have multiple invoices associated
with a certain order. Whenever the order changes the total, I have
to somehow calculate the difference and send a new/immutable invoice
to the customer. Then, the customer can pay and the payment will be
associated with the invoice.
Would love to hear some advice. Much appreciated. Thanks!
There are a lot of questions here, I'll try to address as many as I can. A lot of the issues are the business model rather than the data model.
Firstly, you are right that you need an immutable invoice. Once an invoice is created you cannot alter it, the standard way of handling a change in invoice is to issue a credit note and a new invoice.
Think about the relations between the tables: the Order does not need to hold the lineItems as these are referenced the other way, i.e.
Order
=====
orderId
customerId
status
OrderLineItem
=============
orderLineItemId
orderId
product
price
quantity
So to view the order you join the tables on orderId. There's also no need to store the total as that is calculated from the join.
Try not to duplicate your data: your invoice will reference orderLineItems, but not necessarily the same ones in the order. For example, the customer orders an A and a B, but B is out of stock. You ship A and create an invoice that references orderLineItemId for A. So your invoice tables might look like:
invoice
=======
invoiceId
status
invoiceLineItem
===============
invoiceId
orderLineItemId
quantity
In other words there's no need to have the details of the item. You may be wondering why you don't just add an invoiceId to the orderLineItem table - the reason is the customer might order 10 of item A, but you only ship 8 of them, the other two will go on a subsequent invoice.
Payments are not made against orders, they are against invoices. So your payments table should reference the invoiceId.
Then you touch on reconciliation. If everything was perfect, the customer would make a payment against a particular invoice, even if a partial payment. In reality this is going to be your biggest headache. Suppose the customer has several outstanding invoices for amounts x, y and z. If they make a payment of p, which do you allocate it against? Perhaps in date order, so that if p>x the remainder is allocated against y. What if p=z? Perhaps the customer is intending to pay z now but is disputing y and has mislaid x? How you deal with these sorts of things is up to you, but I can say that most invoicing systems do it very badly indeed.
I have a database design issue. My project is about products and retailers.
Product table: product_id, product_name, product_description, category_id, quantity_per_unit
Retailer table: retailer_id, retailer_name, City
Retailer's Stock table: retailer_id, product_id, unit_price, availability
The Retailer's Stock table links each product with its seller
And also Category table with category_id,category_name,category_description
Now I want to have different sizes, colour and brands in product. How should I accommodate them in this database? I have included the price in another table then products table because different retailer can sell the same item at different prices.
Your existing database design already meets your stated requirements. Each instance of a combination of size, colour and brand in a product is a row in your Product table. This is often called a Stock Keeping Unit (SKU).
If you want to have products at a higher level, think of breaking your current Product table into two parts, like so:
ProductType ( product_type_id, product_type_name, product_type_description,
category_id )
SKU ( sku_id, quantity_per_unit, product_type_id )
Then amend your RetailersStock table to reference SKU instead of Product.
This is a common problem with stock keeping systems; different colours, sizes etc. are usually called "variants". There are other questions on StackOverflow.
There are often two questions that intertwingle here.
One is "I'm selling soap, towels and bulldozers; how do I design a schema that allows me to store and reason about the attributes of those products, when they're all different and I don't know in advance what the attributes will be?". I'm going to assume that's not your question right now.
The second question is "how do I keep track of stock, price etc. for variants?".
The classic answer for this is to have a "product" table with the attributes that are common to all attributes, and a product variant table that has the attributes specific to the variants, along with the quantity of stock and the price (if variants can have different pricing, e.g. a large pack of soap is more expensive than the small pack).
Product table: product_id, product_name, product_description, category_id, quantity_per_unit
Product_Variant table: product_variant_id, product_id(FK), size_code, colour_code
Retailer's Stock table: retailer_id, product_variant_id, unit_price, availability
You do, then, need to keep a variant for all products, even if there is only one version for the product, but it's usually a good idea to factor out the "core" of the product data from the more fleeting data like availability and price.
I need a little help designing a database that a bar would use for drinks. My app handles drink orders in 2 ways: A customer can order drinks and pay right away, or they can start a tab. This is my table relationship so far:
Table Order: Table Tabs:
------------ ------------
[PK] OrderId - 1 [PK] TabId
ItemName / TabName
QtyOrdered / Total
TabId *- PaymentType
Archive
Its setup so 1 tab can have many drinks on it. Thats great for tabs, but customers can choose not to setup a tab. My question is, how can i modify these two tables to support that? Or do I have to create a new table?
Thanks in advance.
Your "item" is the order line-item.
"My brother and I will each have a Guiness and his wife would like a gin-and-tonic."
There are three (EDIT: items, but two) line-items on that order. To identify them as part of the same order [if you should need to do so], you would need two tables:
the OrderHeader
(orderheaderid, orderdatetime, customerid)
and
the OrderDetail
(id, orderheaderid, drinkid, howmany, extendedprice, paymentamountapplied).
If you do not need to identify the drinks as belonging to the same order, you could abandon the two-table structure, but then you could have only one kind of drink per order.
ORDER
orderid, orderdatetime, customerid, drinkid, howmany, extendedprice, paymentapplied.
Extended price is howmany * the drink's price at time of the order. You store this value in your order table so you can change the price of the drink in the DRINKS table without affecting the tab amount owed (in case the tab lifetime is longer than a day -- i.e. customers can run a monthly or quarterly tab).
HowMany can default to 1. The amount owed on a drink line-item is (extendedprice - paymentamountapplied). PaymentAmountApplied defaults to 0 (i.e. default is to run a tab).
If you do not need to track the kind of drink being ordered (i.e. you don't care to use your database to discover that on Tuesday nights you sell a lot more gins-and-tonic than Guinesses, for some reason):
ORDER
orderid, orderdatetime, customerid, ordertotal, paymentapplied.
Your barkeep would simply enter the total amount of the order, calculated outside your system, without reference to a DRINKS table in the database -- maybe the barkeep would look at a chalkboard on the wall.
You need a CUSTOMERS table, a DRINKS table, an ORDERSHEADER table, an ORDERDETAIL table (each drink on the tab is a line-item). You could/should have a separate PAYMENTS table. And you would allocate payments to the line-items of the ORDERDETAIL (your tab). The "tab" is the set of all line-items on the order(s) that have no payment applied to them.
I have problem with two parts of database diagram and I need your guidance:)
database has a lot of tables that one of them is about Employee ,the other is about Customer and ... ! I have problem with two tables (Product and OrderDetail) my Product table has 3 columns (ProductID,Name,Cost) and the Other table is OrderDetail that has these columns(OrderDetailID,Cost,Quantity) I have not created this database myself I have found it like a sample database in the internet but I have problem about these two Cost which is in OrderDetail and Product tables ,what is the difference between these Cost? they are the same or not?
thanks
EDITED: sorry all I had a mistake ,the ID for the ordeDetail table is the composite of primary key of Product table and Order table which is Product ID and OrderID and the OrdeDeatil table is a weak entity. SO
OrderDeatil((ProductID,OrderID),Cost,Quantity)
I suppost that the cost in the products table is the current price of the product. On the other hand, the cost in the order details table is the price that was paid for the product for that particular order.
Product prices can go up or down, or discounts might have been given for particular orders. The field in the order details table would store this information.
UPDATE: Further to your updated question, that makes sense. It implies that each order can only list the same product once. The order details table is storing how many items of that product were ordered (quantity) and I would say that cost is the price paid for one item. It could be the total (price * quantity) but that's not a common for such table structures.
Without knowing exactly what this database is meant to capture, I couldn't say for sure, but as a rough guess I would expect that the Product tables Cost column is the cost for a single unit of that product, and the OrderDetail tables Cost column is the cost for an order of some quantity of 'something' - most likely a certain quantity of a product. Note as an interesting aside that there is nothing linking the OrderDetail table to the Product table - if these two tables are meant to be linked you would normally expect a Foreign Key in the OrderDetail table linking it to the Product table. At the moment, there is no way to match OrderDetails to Products.