I'm designing a database for our sales team to use as a quick job quoting tool. I would like some feedback on a particular aspect of the design.
A quote is basically built up by selecting a list of predefined 'assemblies' each with an agreed price. A simplified view of the main form looks like this:
+------------ --- ---+
| Assembly options |
+------------+------------+----------+------------+---+---+---+ --- +--+
| assembly ▼ | unit cost | quantity | total cost | 1 | 2 | 3 | |50|
+------------+------------+----------+------------+---+---+---+ --- +--+
| VSD55 | £10'000 | 2 | £25'500 | 1 | 1 | | | |
| RDOL2.2 | £2'000 | 1 | £1'500 | | 1 | | | |
| DOL5.0 | £1'000 | 1 | £1'200 | | | 1 | | |
+------------+------------+----------+------------+---+---+---+ --- +--+
The user selects a predefined assembly, enters the quantity and selects any 'options' required. Each assembly potentially has up to 50 available options. An option is also a predefined assembly (sub-assembly) with its own price. The 'total cost' for each line is calculated as (main assembly cost * quantity) + cost of any options.
When the user moves their cursor into an option box the name & price of that option is made known to them.
Now this is where it gets complicated. Each assembly has its own list of available options. i.e. option 1 for a 'VSD55' represents a different sub-assembly than option 1 for a DOL5.0.
As far as the assemblies go here are the simplified tables I'm using:
+-----------------+ +------------------------+ +-----------------------------+
| assembly | | assembly_option | | assembly_option_link |
+-----------------+ +------------------------+ +-----------------------------+
| assembly_id (PK)| | assembly_option_id (PK)| | assembly_option_link_id (PK)|
| assembly_name | | assembly_option_name | | assembly_id (FK) |
| unit_cost | | option_number | | assembly_option_id (FK) |
+-----------------+ | unit_cost | +-----------------------------+
+------------------------+
The table 'assembly_option_link' basically defines which options are available for each assembly.
Now for the 'quote' tables:
+-----------------+ +------------------------+
| quote | | quote_assembly |
+-----------------+ +------------------------+
| quote_id (PK) | | quote_assembly_id (PK) |
| quote_name | | assembly_id (FK) |
+-----------------+ | quantity |
+------------------------+
Now the tricky part is how to store any selected options. Should I expand the 'quote_assembly' table with all the 50 option fields even though this breaks normalisation rules. An assembly will never be selected with all 50 options so this seems very inefficient too. On the plus side, this solution allows the user entry form to map directly to the table making coding easy.
The 'normalised' solution I think would be to create another table like this:
+------------------------------+
| quote_assembly_option |
+------------------------------+
| quote_assembly_option_id (PK)|
| quote_assembly_id (FK) |
| assembly_option_id (FK) |
| quantity |
+------------------------------+
This solution means only selected options are stored. Also, rather than storing the option_number, I can store the actual 'assembly_option_id'. This then makes calculating the total quote cost simpler as I don't need to convert between 'option_number' and 'assembly_option_id' to lookup the assembly option cost. The major drawback with this solution though is that it doesn't sit well with the user entry form. I think I will need to apply some fancy coding to interface the form with the tables.
Can anyone offer any design advice here please? I hope I've explained myself well enough.
MORE INFO
The is also a detailed quotation report that expands any selected options as separate line items under the main assembly. For example:
+---------------------------------+------------+----------+------------+
| assembly | unit cost | quantity | total cost |
+---------------------------------+------------+----------+------------+
| VSD55 | £10'000 | 2 | £20'000 |
| - Seal leak protection | £ 5'000 | 1 | £ 5'000 | <-option 1
| - Motor over temp protection | £ 500 | 1 | £ 500 | <-option 2
+---------------------------------+------------+----------+------------+
| | | | £25'500 |
+---------------------------------+------------+----------+------------+