-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
What is your plans for this - do you need help / hints etc #99
Comments
Hi Vahid, thanks for your interest in the plugin! There are definitely areas that could be improved. It's not released (as in listed on the Grails website) but it is released to Bintray and Maven Central. If you look at the demo, the shop menu item shows a list of categories. Only the ones with "New" beside the category have products currently. The product listing and search is currently designed for full text search using the hibernate-search plugin which uses a search index. This works great when it works but has caused a lot of headaches and dependency conflicts also come up. It often fails to startup the first time for some unknown reason. I would like to replace it with something and my thought was to add full-text search to my PostgreSQL database and use that special column for searching. The complexity you see in the product search may be due to returning different results based on admin authentication. For instance if a user does a listing they will only see the primary product or a group and not all the color/size versions for instance where the admin will see all products even those after sale discontinuation date and things like that. A lot of the domains were initially modeled from a book called The Data Model Resource Book. The Apache OfBiz project uses a much more complete implementation and I've only created what I needed so far. I plan to also include things like warehouse, inventory and things like that when time allows. Currently the product category domain allows flexibility in changing hierarchies like adding one in the middle or adding a category like New Products or On Sale that might only be temporary. I'll have to review your code to get a better idea of your thoughts. Unfortunately I haven't spent enough time on documentation but I'd be glad to work on that some or answer any questions. I'm interested in the session shopping cart idea and would be interested to see how that would work. It was based on a Grails plugin at some point. You can also email me direct at carl.marcum at codebuilders.net [1] http://demo.codebuilders.net/ Best regards, |
I can email you if you like, there is a lot about this that I wouldn't personally do like you say the search causes a lot of headache and perhaps a better db struture design to look up items based on the criteria using HQL would be how I would do it. This way it is going to work going forth without the headaches of revision updates "well one would hope writing own queries" As far as your product Controller, def addToCart(Long id) {
if (!session.cart) {
session.cart = []
session.cartCounter=[:]
}
List allOfThisItem = session?.cart?.findAll{it.id == id}
Product p = Product.get(id)
if ( p.inventoryCount - (allOfThisItem?.size()?:0)>=1 ) {
session.cart << [id: id, name: p.name, listPrice: p.listPrice, inventoryCount: p.inventoryCount, shortDescription:p.shortDescription, photo:p?.mainPhoto ]
session.cartCounter[id]=session?.cart?.findAll{it.id == id}?.size()
}
render status: 200, text: ''
}
def updateCart(Long id, int qty) {
List allOfThisItem = session?.cart?.findAll{it.id == id}
Map firstItem = [:]
if (!allOfThisItem) {
Product p = Product.get(id)
allOfThisItem = [id: id, name: p.name, listPrice: p.listPrice, inventoryCount: p.inventoryCount, shortDescription:p.shortDescription, photo:p.mainPhoto ]
firstItem = allOfThisItem[0]
} else {
firstItem = allOfThisItem[0]
if (qty>firstItem.inventoryCount) {
qty = firstItem.inventoryCount
}
if (qty > allOfThisItem.size() &&(firstItem.inventoryCount - (allOfThisItem?.size()?:0)>=1)) {
int a = allOfThisItem.size()
while (a < qty) {
session.cart << firstItem
a++
}
} else if (qty < allOfThisItem.size()) {
int a = allOfThisItem.size()
while (qty < a) {
session?.cart?.remove(session.cart.find{it.id == id})
a--
}
}
}
session.cartCounter[id]=session?.cart?.findAll{it.id == id}?.size()
render status: 200, text: "success"
} I removed add and removeFrom cart and have either a select or input box which when calling update simply does remove / add in the same function, if you prefer your older way but using session instead of DB. They are commented out and I haven't updated - what is working is above... unsure of below segment it was fine at some point... //Older functions add etc
def removeFromCart(Long id) {
session.cart = session?.cart?.remove(session.cart.find{it.id == id})
render status: 200, text: 'good'
}
def removeAllFromCart(Long id) {
session?.cart?.removeAll {it.id == id}
render status: 200, text: 'good'
}
def addToCart(Long id) {
if (!session.hasProperty('cart')) {
session.cart = []
Product p = Product.get(id)
session.cart << [id: id, name: p.name, price: p.listPrice, photo:p.photos[0], qty:1 ]
} else {
def found = session.cart?.find{p-> p.id == id}
if (found) {
found.qty ++
}
}
render status: 200, text: 'success'
return
}
def removeFromCart(Long id) {
def found = session.cart.find{it.id == id}
if (found) {
found.qty --
}
render status: 200, text: 'success'
}
def removeAllFromCart(Long id) {
session?.cart?.removeAll {it.id == id}
render status: 200, text: 'success'
}
Then I think in your home controller: def index() {
def notices = noticeService.getCurrentNoticesByPage("shop")
//def feeds = rssFeedService.getFeedsByDisplay()
if (!session?.cartCounter||!session?.cart) {
session.cartCounter=[:]
session.cart=[:]
} then in gsp: <g:set var="currentlyInCart" value="${(session?.cartCounter[product?.id]?:0)}"/>
<g:set var="availableStock" value="${((product.inventoryCount)-currentlyInCart)}"/>
<div class="hover">
<g:if test="${availableStock>=1}">
<button onclick="ajaxCall('addToCart', ${product.id},${availableStock})" class="btn btn-primary btn-lg waves-effect"><i class="fa fa-plus"></i></button>
</g:if>
<button onclick="ajaxCall('checkout', ${product.id},${availableStock})" class="checkOut btn btn-primary btn-lg waves-effect"><i class="fa fa-shopping-cart"></i></button>
</div>
<div class="row text-center">
<g:message code="inCartInStock.label" args="[currentlyInCart,availableStock]"/>
</div>
<script>
function ajaxCall(method,id,available) {
if (available>=1) {
var url="${createLink(controller:'shoppingCart', action: "addToCart")}/?id="+id
$.ajax({
type: 'POST',
url: url,
success: function(data){
if (method=='addToCart') {
location.reload();
} else {
window.location.href="${createLink(controller:'shoppingCart', action: "cart")}";
e.stopPropagation();
e.preventDefault();
}
},
error: function (xhr, textStatus, error) {
$("#failSegment").html("${g.message(code:'formError.label')}"+xhr.status).addClass('has-warning').delay(10).fadeIn('normal', function () {
$(this).delay(1500);
}).hide();
}
});
} else {
if (method=='addToCart') {
location.reload();
} else {
window.location.href="${createLink(controller:'shoppingCart', action: "cart")}";
}
}
}
</script> This should do all that your existing ShoppingCart would do and would save persisting a given cart to a db. The concepts of such things and having lots of hasMany relationships is all easy and logical to follow but and the real but is headaches down the road when it comes to managing an ever growing DB. Burt Beckwith did a nice video and in it he described how or why he created the UserRole class simply due to well it's a plugin assume an end user using it ends up with 10k of elements hanging off the hasMany. Imagine if you had 10k categories would your current select box for managing categories and child categories work well ? I think trying to manage that from a select box and a simple query to list each element of a 10K would cause some issues or hanging around.. You can create your own hasMany relations and make them work how you want it , short queries wrapped around getter methods etc. I think I would probably write a lot of this differently which is why if I get time I may release a different variation To give some more ideas a product feature really hangs off the product category or its generic traits and it may have custom ones but most importantly a feature is likely to come at a cost, an example a shop selling cars, same car one has super jet engine feature which comes at £500 more for that feature if selected. The problem is all the little things that hang off a product weight vs shipping costs etc vs shipping destination and it's costs - these are also very difficult issues to consider |
@vahidhedayati I have created issue #100 and session-cart branch if you are interested in doing a PR. Otherwise I'll work on it in a week or two as I'm in the middle of a project currently. |
Hi Carl
I been going through this plugin and wondered what you planned to do with it, there is a lot about this I would change and there are things like home page component missing too ... which I guess is store front...
There is lots of stuff happening in controllers that I think could have a tidy up the product listing gives errors and that whole query I have condensed to about 70 lines locally using HQL it was very hard to follow.
Not really sure why the shoppingCart items are stored on a db I have managed to use session.cart to contain all the relevant items put in a given basket rather than physically storing on a db. Whilst I can see advantages such as a basket that can move between devices but since it was locked to session it be only valid or available so long as session.cart would be so in essence no different.
Also the product category and adding a product to all the sub categories of a given category again unsure if all that in a long run or over bigger project plans out too well...
Assume we have a new field in product category:
In ProductCategoryController where you save productCategory if you then did:
you end up setting a category path per category created and then rather than having all repeated product in so many categories you simply have a flat path and in your hql or query you can look up product and productCategory.categoryPath and then look for any items in products that matches same categorPath of let's say :
10/1/1*
this now lists anything on from there and obviously you can go back to root by substring(0,item.indexOf('/')) etc and look for anything matching10*
and so on and so on..Just some thoughts and I am still busy but perhaps when I finish what I am doing if you are looking to officially release this I can help you out or give you hints advice...
The text was updated successfully, but these errors were encountered: