Okay, so here's the data model I came up with.
PRODUCT -- to store product information and maintain parent-child hierarchy
id NUMBER "Primary Key Not Null"
level_code VARCHAR2 Not Null
name VARCHAR2 Not Null
description VARCHAR2
parent_id NUMBER Foreign Key references PRODUCT(id)
ORDERS -- to store orders for products
id NUMBER "Primary Key Not Null"
prod_id NUMBER "Foreign Key references PRODUCT(id) Not Null"
order_type VARCHAR2 "Not Null Default 'Default'"
order_qty NUMBER Not Null
order_date NUMBER Foreign Key references DATE_INFO(date_key)
delivery_date NUMBER "Foreign Key references DATE_INFO(date_key)
Check delivery_date >= order_date"
FORECAST -- to store forecast value for products (store value for higher levels, store value for lower levels after disaggregation from a parent)
id NUMBER "Primary Key Not Null"
product_id NUMBER "Foreign Key references PRODUCT(id) Not Null"
forecast_value NUMBER Not Null
week NUMBER "Foreign Key references DATE_INFO(date_key) Not Null"
DISAGGREGATION_RULES -- to store which method was used for disaggregating a value from a higher level to lower level and how much percentage got distributed to lower level
id NUMBER "Primary Key Not Null"
parent_product_id NUMBER "Foreign Key id references PRODUCT(id) Not Null"
child_product_id NUMBER "Foreign Key id references PRODUCT(id) Not Null"
method VARCHAR2 Not Null
from_week NUMBER "Foreign Key references DATE_INFO(date_key) Not Null"
to_week NUMBER "Foreign Key references DATE_INFO(date_key) Not Null Check end_week >= start_week"
percent_distribution NUMBER Not Null
DATE_INFO -- date dimension, has information about start date (has to be Saturday) and end date corresponding to the week in which a particular date falls
date_key NUMBER "Primary Key
Not Null"
full_date DATE Not Null
week_begin_date DATE Not Null
week_end_date DATE Not Null
As for the bucket number .. I am calculating week start date (date on Saturday, in my case) with the following function
CREATE OR REPLACE FUNCTION get_week_start_date(v_bucket_num IN NUMBER)
RETURN DATE
IS
week_start_date DATE;
BEGIN
SELECT (TRUNC(SYSDATE+2, 'IW')-2) + ((v_bucket_num-1) * 7)
INTO week_start_date FROM dual;
RETURN week_start_date;
END;
My first IT job was in this area - basically I was involved in a "fiddle" on the part of my employer to land a big contract which involved convincing the client that we had a functioning and "intelligent" order picking system. It involved alcholic beverages and there are many complex rules about these (tax reasons).
Anyway, I just wish that Open Source had been as prevalent then as it is now - because there appear to be a plethora of high-quality projects out there in this area. A quick Google landed me here and here - search for the word "pick" on these pages.
If I were you, what I would do is examine these (and others...) packages and see which ones correspond most closely to your needs - download and install them and then check out the underlying schemas and see which bits you can borrow for your project. Or you may just decide to implement one of the systems that's already out there?
What I do know is that the logistics behind these problems are very complex (operations research, tricky mathematics &c.), so you might be able to take some of the pain out of your project by "standing on the shoulders of giants"!
[EDIT]
You might like to check out this and its parent site- it specifically mentions bin-packing and employee rostering, so it might be of interest. I remember this from studying operations research. If you work in Java, it could be of interest - although the principles obviously apply to all languages.
Best Answer
I think your main challenge is the requirement that the
Order
is in between yourUser
andCart_Item
.I am assuming you are planning on storing items put in the shopping cart in
Cart_Item
(items planned to be purchased but not currently purchased. Also there is only 1 list of items pending purchase per user). And then items actually purchased by the user (coming from he shopping cart) will land inOrder
. In my opinion, there should not be any kind of link between the "order" and the "shopping cart". If there was, you would need to store some kind ofCart_ItemId
on theOrder
table, not anorderId
onCart_Item
. If you were to keep aCart_ItemId
, you would then have to have some kind of shopping cart history, which to me, seems redundant since that data would be saved in your "order history" thoughOrder
. You may have another purpose that I am not thinking of so let me know if I am missing something.Assuming my understanding of what you are looking for is correct. I believe this below schema is much closer to giving you what you are looking for, and getting you around this
Foreign Key
issue. (I apologize, your relationship diagram was so much nicer than mine. Trying to make it work in Visio instead):Transferring data from your Cart to Your Order could look something like this:
Now if it was me, I would create
Order
andOrderItems
tables. That way you don't duplicate data like the User, or address information on each item. I know you want to limit tables that are created, but I think that will help you a lot. If that is a route you end up going, than you will have a schema a little like this:For a quick example. Lets pretend I am a user (UserID 13 because that is my favorite number). I fill out a cart with the 5 items. The records from the
Cart_Item
table looks like:When I hit the last "submit" in the check out process we would then write 1 record to
Order
and 5 rows toOrder_Item
. Those rows would look something like:A Stored Procedure to handle this might look like:
Hopefully this helps. Let me know if I need to explain something better or if this doesn't answer your question.