I make bracelets and place them in my opencart store. Each bracelet is unique, so I have 1 in stock. But customer has to let me know the size of his/her wrist so I can adapt it.
Options ask me for quantities. So, I can not use them because I must enter a number or the option does not become visible.
What I need is:
bracelet B ---> tell me your wrist´s size: (here a drop down or a text box to let the customer choose or write).
Order will reads: Bracelet B... Size: 18cm.... xx $
Then, when the customer pays, Bracelt B is out of stock.
Now, I can do all that, but any time a customer adds an option, the bracelet keeps available. So Order reads: Bracelet B ... Size: 18cm... xx$ Bracelet B ... Size: 19cm... xx$ etc
function addToCart(product_id, quantity) {
quantity = typeof(quantity) != 'undefined' ? quantity : 1;
$.ajax({
url: 'index.php?route=checkout/cart/add',
type: 'post',
data: 'product_id=' + product_id + '&quantity=' + quantity,
dataType: 'json',
success: function(json) {
$('.success, .warning, .attention, .information, .error').remove();
if (json['redirect']) {
location = json['redirect'];
}
if (json['success']) {
$('#notification').html('<div class="success" style="display: none;">' + json['success'] + '<img src="catalog/view/theme/default/image/close.png" alt="" class="close" /></div>');
$('.success').fadeIn('slow');
$('#cart-total').html(json['total']);
$('html, body').animate({ scrollTop: 0 }, 'slow');
}
/*adding Shadyyx solution*/
if (json['error']) {
$('#notification').html('<div class="error" style="display: none;">' + json['error'] + '<img src="catalog/view/theme/default/image/close.png" alt="" class="close" /></div>');
$('html, body').animate({ scrollTop: 0 }, 'slow');
$('.error').fadeIn('slow');
}
/*end adding*/
}
});
}
In default OC You have the ability to disable ordering of out of stock products.
Simply go to the administration -> System -> Settings, click edit on Your store and navigate to the Options tab. Then scroll down to the Stock section and notice the Stock Checkout: option. If You select No and save the users won't be able to order the products that are not in stock.
This means that if You create a bracelet product with 1 piece in stock, add an option to it with one piece in stock and somebody order this one, it's stock will be immediately set to Not in stock and nobody will be able to order it again.
If You'd like to hide all the products that are not in stock after they are ordered, You have two options - either do this manually by disabling the product or You'd need to implement few modifications in to the getProducts()
method for the product model to load only those products that are still in stock.
UPDATE regarding the comment: You are misunderstaning the options in OpenCart. One option for which You have the stock 1 piece is the size option, which may have different values, e.g. 15cm, 16cm, 17cm, 18cm, etc. All these values contained in one single size option for one single stock item mean that if I select any of them, after ordering the bracelet there will no more pieces left.
What You are telling is creating one option for 15cm with 1pcs stock, another option for 16cm with 1pcs stock, etc., thus having 1 piece in stock for each size - this is incorrect (i.e. misuse of product options). Nevertheless, even in this case, when different sizes have all one piece but the product itself has only one piece, after ordering first it should be out of the stock even there are options with stock left...
Step by step walkthrough:
Let me know if there is something that I missed (or if it still doesn't work).
UPDATE:
Here is one possible solution (not tested but I believe it will work out of the box or maybe there is only simple bug You may fix Yourself):
Open up the catalog/controller/checkout/cart.php
and find this line (should be at 543):
$this->cart->add($this->request->post['product_id'], $quantity, $option);
and before this line directly add this code (You may want to do this via vQmod extension):
if ($product_info['quantity'] == 1 && $product_info['subtract'] == 1) {
$products = $this->cart->getProducts();
$already_added = false;
foreach ($products as $product) {
if ($product['product_id'] == $this->request->post['product_id']) {
$already_added = true;
break;
}
}
if ($already_added) {
return $this->response->setOutput(json_encode(array(
'error' => $this->language->get('text_product_already_added')
)));
}
}
Then open up this file catalog/language/english/checkout/cart.php
and add this to the end:
$_['text_product_already_added'] = 'This product has allowed quantity of 1 piece and is already added to a cart. Remove it from the cart to be able to add it (e.g. with different size).';
This is all only as an example, You may edit the error message to meet Your requirements.
Warning: this is only a simple solution not letting the same user (or within the same session) to add the same product twice or more times into the cart but it won't prevent the same product being added and ordered at the very same time by two different users (or one user using two browsers, for example). For this edge case You'd need to implement some kind of product locking - after it is added to cart this is saved to a DB and nobody else would be able to add the same product into the cart. In this case it would be nice to store also the datetime when it was locked and have a cron job that will unlock this product (also with removing from the cart) so that the product is not locked for ever and is orderable by other users again...
EDIT for JS part:
Open up this file catalog/view/javascript/common.js
and search for method function addToCart(product_id, quantity) {
- in this file find this part:
if (json['success']) {
...
}
and after this one add this code:
if (json['error']) {
$('#notification').html('<div class="error" style="display: none;">' + json['error'] + '<img src="catalog/view/theme/default/image/close.png" alt="" class="close" /></div>');
$('html, body').animate({ scrollTop: 0 }, 'slow');
$('.error').fadeIn('slow');
}
This should be enough.
UPDATE XYZ:
In PHP find this code what have we added:
return $this->response->setOutput(json_encode(array(
'error' => $this->language->get('text_product_already_added')
)));
and change it to this (then try):
$this->response->setOutput(json_encode(array(
'error' => $this->language->get('text_product_already_added')
)));
return;
The point is to see in console where the request is done to index.php?route=checkout/cart/add
the response with either success
or error
message in response. Try for both cases to make sure You are looking at the correct request (in success You can see the success message on the top of page so You may be sure it was done) and then try again to receive error (for the same product) message - it should be contained in the response the same way as the success message is. If still doesn't work, try to change return;
to exit;
...