Well, I have a rambling set of vague ideas, but I think your architecture question isn’t really usability yet, and might also need to sit over in Programming somewhere (since we don’t seem to have a place for architecture questions). Below is my completely uninformed opinion spew.
I don’t think you should be doing many if-elses and stuff. I believe the product objects should determine everything whenever they are asked (called from the db) such as when a product page is called. Your front-end template would be checking these things… for example our products, we’d have something like this:
{% if product.variants %}
(if there are variants of this product, otherwise none of this HTML gets rendered)
<table>
…blah blah…
{% for v in product.variants %}
<tr>
<td>{{ v.name }}</td>
<td>{{ v.whatever }}</td>
<td>{{ v.whatever else }}</td>
{% endfor %}
</tr>
etc…
</table>
{% endif %}
This table may be inside a form and we may have, for example, checkboxes with product and variant id’s attached in the table cells.
So the form knows nothing, the template adds more formy-stuff to the form depending on what the object’s information has, in the DB.
I suppose where you store each product object on the back end, those products will have individual “requires” lists attached to them. These “requires” are themselves other objects, and so would also have their own “requires” lists as well. A nice webby mess.
If the optional objects are truly optional but have related use to the main object, then possibly each object not only has a “requires” list but also an “options” list. Again each object in the “options” list would have its “requires” list.
Obviously a part of one sort like a wheel would have an empty requires list: it is more likely itself listed in many other objects as a required thing. So someone requesting just that one object would only get that one object. Maybe if that one object only fits certain other things then it need a list of “matches” like you get with ink cartridges. So while each printer object has in its requires list at least two ink cartridges of certain models, the individual ink cartridges themselves have a list of who lists them in their requires lists.
I would think these needs, options and matches lists are intrinsic parts of each object (thing you can buy) and so I don’t think the forms or the session should have to determine these things. Just like a product may have an attribute like being red or having screw holes of a certain size, the “requires” is also an attribute.
So when you have groups of product-objects like kits, I suppose they would come in two forms: complete kits (where every object member of the kit also has its requires list of objects also as part of the kit) and complete kits + options lists (and whenever an option is selected, its “requires” list of fellow-objects gets included). Everything else is an individual part with its own requires and options list.
It sounds like if you have a normal (relational) database you’ll have lots of many2many tables and an ORM that knows which tables to add which objects to. If you have an object database then basically every object has attributes which are lists (I guess these lists would use the unique name/number to reference things).
Seems if all this is part of your products in the back end, the front end will merely be meeting requirements and showing what is required based on the client request. Your forms (or front-end template) will be stupid and will simply be told “this product HasRequireds and HasOptions so add the form chunks that would contain those”. That way what shows on the screen has only everything to do with the intrinsic knowledge coming from the requested object and nobody else needs to know diddly squat.
I think the only way a customer would be able to see a total price is after they have dealt with each selections’ “requireds”. They can see the individual part-price, but not the “full” price. Only after that can you decide things like coupons, shipping, etc.
If you have a page listing all these products, parts, and kits all together, I don’t think you can fairly state the prices listed there are “full” prices and would have to have text near the top of the page stating this… unless the thing you’re showing is
- a complete kit where all requireds of objects inside are included in the kit
- a part with no requireds of its own.
Everything else can only show a base price at best.
I suppose I need a flow chart type of order where the user picks the main items and they are offered options.
In our db’s we have all the info on each particular product. When a user goes to a product page, everything known about that product is called from teh DB (actually usually from our cache-index and then the DB). So in your case the information on the product on the product page would have these requireds, options and matches lists.
Product -> shows product info, requireds list, options list, matches list. If product has empty requireds, add an add-to-cart form. If there is a requireds list, there can be a form but it now must list more products with their own checkboxes to add-to-cart.
Product: a Foobar
type: part
requireds:
options:
matches: [model1, model2, model15]
variants:
price: price.
Clicking on a Foobar from your total catalog brings up a Foobar product page with the above listed and an option to add to the cart. Its price is stable unless you have discounts, coupons, etc.
Product: a Group Thingamajig
type: Machine
There are two versions of this Thingamajig: the basic and the extra-large.
requireds: [power supply model x, batteries model y, antenna model a]
options: [special alloy wheels models d or b, remote control models b or d, plastic flashing models a, g, and h]
matches:
variants: [green, blue, red, yellow]
price: [base price: price, othermodel: otherprice]
This page does not allow an add-to-cart, because there are two sorts. This is an intermediate product page IF your products are set up this way. Ours are not, btw: we would consider basic and extra-large versions of a product to be two completely separate products who fall under the same rubriek (so if users search under the rubriek, both these elements appear in the product listing of course). However I don’t know how your customer is doing this. So if you’re doing like the above then the user must first choose a version. They choose “basic”.
Product: a Thingamajig
type: Machine
version basic
requireds: [power supply model x, batteries model y, antenna model a]
options: [special alloy wheels models d, remote control models d, plastic flashing models a, h]
matched:
variants: [green, blue, red, yellow]
price: price
Users get presented with a price, but like on a clothing shop, this page (which has a form because it has an add-to-cart button) lets the options->plastic flashing models a or h be chosen (or left blank). Since these options are products themselves, they will have their own lists. If they choose nothing, they can add to cart. Otherwise they may choose an option. This would call another product (maybe the same page) and show everything about this product, since it might have requireds. It probably doesn’t have options. It probably does have matches, and Thingamajig version basic is in its matches list.
Depending on how much configuration there is, it could get very nested very quickly. The Back button should be able to bring users back to earlier forms. The session should only keep track of what has been viewed, and separately what has been added to the cart (and therefore what the current running total is), but it should not keep track of requireds for things added to cart.
You could maybe have it that if a user tried to go further in the cart (go actually order these things) that each item’s requireds lists are checked that they are also in the in-cart list, and if not either stop the user or give them a warning and let them choose not to fulfill all requirements (who knows what users actually plan to do with this stuff).
Well anyway that’s my go at it, and I probably made a lot of assumptions that don’t match your setup.