What is the best relational schema (or ERD) of dynamically nested objects? - sql

I am trying to draw the table diagram of a product listing web application.
Application logic:
Admin user will create:
Categories (must be dynamically created by admin user),
Category's attributes (must be dynamically created by admin user),
Selection of Category attribute's options (must be dynamically created by admin user)
User will post a product under a specific category and must choose category attribute's option for each category attributes to successfully save the product.
Example: Admin creates category "food"
"food" has its attribute "meal_type" and "sugar".
"meal_type" has its options "breakfast", "lunch" and "dinner".
"sugar" has its options "with-sugar" and "non-sugar".
and now user can post his product "pizza" under category "food".
When user chosen "food" category, he must see its attributes "meal_type" and "suger"
and then must set those option values.
For example, "pizza"'s category is "food" and "meal_type"="breakfast", "sugar"="with-sugar".
And I want to call these option values together with product details when selecting these items.
I have made this (removed non-related fields)
but I am not sure this will work and be efficient at same time.
What is the most efficient relational schema (or ERD) for case like this?

I could help, but I don't really understand what exactly a user is supposed to do? Is he supposed to order products on the website? If so, maybe the naming of the tables should be different, eg "order_product" instead of "product"?
and as for the performance, at this stage and with this structure there should be no problems.

Related

Database design for a product-configurator

I have been asked by a customer to develop a "product configurator", and i need some inputs on how to handle the DB part of the project.
Each product can have a subset of different precreated attributes.
The minimum is 1 attribute, but there is no maximum.
Some attributes have dependencies/relationships with other attributes.
Eg. If the product is a chair, you need to choose the material (wood, plastic, metal), and you need to choose which type of legs the chair shoud have.
If the Product is a cabinet, you still need to choose a material, but instead of legs there will be different doors to choose from etc.
Each of these attributes might have subattributes. Eg. the door has a color, a size and a doorhandle.
Then the door handle has a material, a type and so on.
This ultimatly ends up in a multi-layered attribute-tree.
By itself this isnt too complicated to code, however the customer wants to be able to manage (Create, update and delete) all products, attributes and relationships between attributes, within the webapp.
So coding the relationship-part isn't a viable solution.
I have gone with a EAV model to facilitate the "potential unlimited" amount of attributes each product can have.
But i am struggling to figure out how to go about the "attribute relationships".
A simplified version of my DB design looks like this:
If each product could subscribe to groups of attributes that is legal. Then each attribute belongs to a group like "wood group".
Then the user could set the groups of attributes against a product that should need to be answered to configure a product.
With regards managing a tree, you could use a column type of hierarchyid . Or construct an outline string as key field.
An outline for example
1.
1.1.
1.1.1.
1.2.
2.
2.1.

How to set customer specific pricelists which is common in B2B

How to set customer specific pricelists which is common in B2B.
Pricelists per customer or organisation.
If this not exist out of the box, should i tag pricelists witch dynamic properties or add a custom condition, what is tag (TagsContainsCondition).
It dosnt seems to be possible to add own conditions for pricelist assignments!?
I guess this is the best method to override if you dont want to send to many pricelists to the client:
PricingServiceImpl.EvaluatePriceLists
This is already possible out of the box. Simply go to price list assignments and then add a new condition: "Tags contains". In the frontend, you'll need to populate the tags passed to the pricing engine with whatever values you'd like, for instance it can be customerid, or organization name.
You can also extend and add your own conditions as described here: http://docs.virtocommerce.com/display/vc2devguide/Composing+dynamic+conditions.

OpenERP - Add fields only to some products inside a Category

I'm setting up OpenERP v7. I know how to create modules and so on.
The problem is that not all the products will have the same fields. For example for T-shirts I would have Color, Size. But for belts I will have: Material, Length (as an example).
I know the option of using multi-variants but it's very very confusing. It creates a new column for Dimension values but then the Name of the product has also the Dimension values in it. It's very annoying.
Also, the access to the Product Templates is only accessible from the Sales module, so our Procurement department doesn't have access to it.
I would like more if a pre-defined template appears after a user selects the category of the product. Since products in same category will have the same field requirements.
I would suggest you the following.
Define all fields in your model (color, size, material etc.). Then hide the from views according to the product category.
To hide some field based on the category_id value you may try something like this:
<field name="some_field"
attrs="{'invisible': [('category_id', 'not in', [1, 2, 3])]}"/>
I found out a better way to solve it, which is by using the module product_custom_attributes, downloadable from: https://www.odoo.com/apps/7.0/product_custom_attributes/
This module let's me create sets of attributes that can be later loaded into the product, I can also filtrate the products depending on the attribute value which is cool.

How to structure REST resource hierarchy?

I'm new to server side web development and recently I've been reading a lot about implementing RESTful API's. One aspect of REST API's that I'm still stuck on is how to go about structuring the URI hierarchy that identifies resources that the client can interact with. Specifically I'm stuck on deciding how detailed to make the hierarchy and what to do in the case of resources being composed of other resource types.
Here's an example that hopefully will show what I mean. Imagine we have a web service that lets users buy products from other users. So in this simple case, there are two top level resources users and products. Here's how I began to structure the URI hierarchy,
For users:
/users
/{id}
/location
/about
/name
/seller_rating
/bought
/sold
For products:
/products
/{id}
/name
/category
/description
/keywords
/buyer
/seller
In both of these cases objects in each hierarchy reference a subset of the objects in the other hierarchy. For example /users/{id}/bought is a list of the products that some user has bought, which is a subset of /products. Also, /products/{id}/seller references the user that sold a specific product.
Since these URI's reference other objects, or subsets of other objects, should the API support things like this: /users/{id}/bought/id/description and /products/{id}/buyer/location? Because if those types of URI's are supported, what's to stop something like this /users/{id}/bought/{id}/buyer/bought/{id}/seller/name, or something equally convoluted? Also, in this case, how would you handle routing since the router in the server would have to interpret URI's of arbitrary length?
The goal is to build convenient resource identifiers, don't try to cross-reference everything. You don't have to repeat your database relations in URL representation :)
Links like /product/{id}/buyer should never exist, because there already is identifier for that resource: /user/{id}
Although it's ok to have /product/{id}/buyers-list because list of buyers is a property of product that does not exist in other contexts.
You should think of it in a CRUD fashion, where each entity supports Create, Read, Update, and Delete (typically using GET, POST, PUT, and DELETE HTTP verbs respectively).
This means that your endpoints will typically only go one level deep. For instance
Users
GET /users - Return a list of all users (you may not want to make this publically available)
GET /users/:id - Return the user with that id
POST /users - Create a new user. Return a 201 Status Code and the newly created id (if you want)
PUT /users/:id - Update the user with that id
DELETE /users/:id - Delete the user with that id
Going into more detail, such as /users/:id/about is likely not necessary. While it may work, it may be getting slightly overspecific.
Perhaps in your case you could add in:
GET /users/:id/bought - Array of products that the user bought
GET /users/:id/sold - Array of products that the user sold
where you could return a list of id's (which can be fetched through the products API), or you could populate the Products before sending them back if you wish. If you do choose to populate them, you probably should not then populate users referenced by each product. This will lead to circular includes and is wrong.
And for Products, in your sitation I would use:
GET /products- Return a list of all products
GET /products/:id - Return the products with that id
POST /products- Create a new product. Return a 201 Status Code and the newly created id (if you want)
PUT /products/:id - Update the product with that id
DELETE /products/:id - Delete the product with that id
GET /products/:id/buyers - Array of who bought the product
GET /products/:id/sellers - Array of everyone selling the product

NHibernate update reference

Entities
We have an entity called Product which is loaded using NHibernate.
Product has a category which NHibernate happily populates for me.
Database
In the database, Product has a foreign key for category.
Scenario
User edits this Product (via a web interface) and chooses a different category (say instead of "Fish" we select "Veg").
This is probably a dropdown list, with each category shown. When they choose a different category we get an int key.
Problem
Obviously we now want to save the changes to Product but in effect the only change is to save a new int (say 2, instead of 1).
So we retrieve the existing Product, and now comes the problem.
We don't have a "CategoryID" field on Product, we only have a Category property.
But we don't really want to retrieve the category (by id) just to assign it to the Product.
So I guess what I want to know is should we...
a) Add a CategoryID property to Product
b) Create a new category, assign it the relevant id and attach that to Product (but surely that will cause errors, or overwrite the existing category)
c) Retrieve (lookup) the category from the system (by id) and attach that to the Product
d) Do something else entirely!
It looks like you might be able to using the Session.Load(id) functionality.
Session.Load is a special method that returns a proxy with the ID until you request another property at which point it loads. It throws an error if there is no item matching the ID. Try something like:
product.Category = Session.Load<Category>(2); //2 being the new category ID
Session.SaveOrUpdate(product);
I just did a little testing and it did not seem to pull back the entire Category.
Updated: Session.Load is the correct answer
product.Category = session.Load<Category>(2);
session.Save(product);
Use NH's EnumStringType<T> to map your Category as an enum to the respective database value (which can be a string or a number). You'll find quite a few usage examples, if you google for it.
HTH!