Codeigniter Cart: Adding an item to cart more than once replaces - codeigniter

Using CI 2.1.1 and the native Cart library
If I insert an item (with same product id, same options) more than once, it replaces instead of increasing the qty.
Could this be a bug, am I missing something, or what would be the best way to add this functionality myself?

So this was my solution, a change to System/libraries/Cart.php on line no. 233 to 244
There may be better ways to do this but it does the trick. I don't understand why the functionality isn't there already
// EDIT: added check if idential rowid/item already in cart, then just increase qty
// without this addition, it would not increase qty but simply replace the item
if (array_key_exists($rowid, $this->_cart_contents))
{
$this->_cart_contents[$rowid]['qty'] += $items['qty'];
}
else
{
// let's unset this first, just to make sure our index contains only the data from this submission
unset($this->_cart_contents[$rowid]);
// Create a new index with our new row ID
$this->_cart_contents[$rowid]['rowid'] = $rowid;
// And add the new items to the cart array
foreach ($items as $key => $val)
{
$this->_cart_contents[$rowid][$key] = $val;
}
}

It's not a bug. Look at it this way: you're telling CI that you want 1 productX in your cart. If it's already there, it stays that way. The rowid does get updated.
Editing the core libraries is not a good idea. That makes your application depend on the changes you made and it can break it when you update CI and forget to change the core again.
If you really want to be able to increase the qty every time the user clicks on Add then
I would suggest is to do something similar to what you did, but in you model.
Check if the product is already in cart, get the qty and add existing qty to the new one.
Does this make sense?

Related

Nopcommerce update customise table when check out

I am newbie for nopcommerce.
Any Idea to check and update customise table when check out?
My case is like that:
I have create a new table name as "DailyLimit" table in my db.
Table field have ID,Date,DailyLimit.
when checkout product, I need to check the "Date" of Daily limit. If daily limit <= 0, then it will pop-up a alert, else it will update to DailyLimit field.
PS:I already create a date checkout attribute and make it as session.
For the Checkout controller I have add the availableQty variable pass to model.
public ActionResult OnePageCheckout(){
//validation
var cart = _workContext.CurrentCustomer.ShoppingCartItems
.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart)
.LimitPerStore(_storeContext.CurrentStore.Id)
.ToList();
//Problem here
var availableQtyFromDB = "SELECT DailyLimit FROM deliveryTbl WHERE date =Session["DeliveryDateForDesley"]" //problem here
if (cart.Count == 0)
return RedirectToRoute("ShoppingCart");
if (!_orderSettings.OnePageCheckoutEnabled)
return RedirectToRoute("Checkout");
if ((_workContext.CurrentCustomer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed))
return new HttpUnauthorizedResult();
var model = new OnePageCheckoutModel
{
ShippingRequired = cart.RequiresShipping(),
DisableBillingAddressCheckoutStep = _orderSettings.DisableBillingAddressCheckoutStep,
availableQty = availableQtyFromDB
};
return View(model);
}
But I have no idea how to write the how to SELECT statement in this controller.
And no idea how to update the daily limit.
Interesting question. Based on your code, I assume you haven't worked much with EF framework. when i started working with nopcommerce, i was like that too. But best thing in nopcommerce is most of common problems were solved in somewhere other part of the application.
First, blindly writing SQL in controller wont help much. Good way to learn is to have a look at
.LimitPerStore(_storeContext.CurrentStore.Id)
Method and how they have done the query/selection using Entity framework. They have done that for per store. You need to do it per day. That will help you to alight your solution in line with nopcommerce architecture.
Source: Ex-nopCommerce Developer for 3 years.

How to disable products that are not assigned to a category?

Could someone assist with this issue I am having please... I need to disable all products that are not assigned to a category in Magento but the problem is there are some 10,000+ products that I will need to sort through.
I would like to ask what the best approach would be so I could at least begin to solve the problem.
Would it be possible to set all products to disabled if they are not assigned to a category using an Observer? Should I echo the list of unassigned products in a loop then set the status to disabled...
I'm not sure how to go about this one...
Best way to do this is using Magento collections.
Create a new PHP file, include Mage.php, initialize the application and make your changes.
It might take a while depending on product count.
I think you want to do something like that:
require_once('../app/Mage.php');
Mage::init();
$product = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('*');
$store_id = 1;
foreach ($product as $prod)
{
if ($prod->getCategoryIds() == NULL)
{
Mage::getModel('catalog/product_status')
->updateProductStatus($prod->getId(), $store_id, Mage_Catalog_Model_Product_Status::STATUS_DISABLED);
}
}

Codeigniter route products, categories and sub-categories

I am using Codeigniter for my project.
I need to get URL structure like this:
Main product page
example.com/language-prefix/products/
Select products by category
example.com/language-prefix/products/category
Select products by category AND sub-category:
example.com/language-prefix/products/category/sub-category
Select specifict product under category AND sub-category:
example.com/language-prefix/products/category/sub-category/product-name
OR only under category
example.com/language-prefix/products/category/product-name
Question is - what would be a good solution for this? Because problem starts here:
example.com/language-prefix/products/category/what-ever
what-ever can be a product or a sub-category and how to decide - what data and view should be returned?
In my DB table structure I have many-to-many relationships between products and categories. It means, than one product can be assigned to many categories. Every category has a self refferecing foreign key (parent).
Maybe I need to get some restrictions for category adding for products? Or specifing a main category or what?
I have couple of ideas:
Keep every route for category/sub-category and product in DB for example:
/products/watches/for-men/
/products/watches/for-men/rolex-abc-whatever-product
And so on, and so on. But this, I have feeling could be very slow.
Make a simple route to products controller -> method view(), and in the method go trough all passed segments and when it comes to
/products/category/what-ever
then first check if there exists such product, if true, then return product_view and data, if not, check if there is such sub-category and if there is, then return the product grid or return 404 if there is not.
I assume a simple solution could be just keep all categories and sub-categories after /products/ and add category-id like
example.com/language-prefix/products/1-watches
example.com/language-prefix/products/2-for-men
But I hope there is better solution for this.
Also I cant figure out this:
example.com/language-prefix/products/category/sub-category/product-name
I need to return product with name product-name AND check if it is under those two categories so URL for example:
example.com/language-prefix/products/hello-kity/bla-bla/product-name
would NOT return that product.
Any better/other solutions?
"Keep every route for category/sub-category and product in DB"
the idea above won't work well in CI and you'll probably break the way CI routing works. remember that the route points you to a controller/function. only when you get there can you start calling the db... so this idea will be weird since you gotta' call the db first to match the routes.
"Make a simple route to products controller -> method view(), and in the method go trough all passed segments and when it comes to /products/category/what-ever"
the idea above is better, you could have a route like this $route['[a-z]{2}/products/(:any)'] = "product/index/$1"; so http://www.example.com/sg/products/gems/ruby and http://www.example.com/sg/products/gems/red/ruby will both go to the product controller's index function
segment(4) can be either "red" which is a sub-category or "ruby" which is a product. segment(3) is always going to be a category. segment(5) is either empty or a product. you must now simply decide if products or sub-categories that precedence, better still handle within your code logic that they never will collide. i.e. product and category/sub-category names cannot be duplicated.
public function test($category = NULL, $sub_category_or_product = NULL, $product = NULL)
{
echo $category.'<br />'; // segment(3) is always your category
if ($product)
{
echo $sub_category_or_product.'<br />'; // segment(4) is a sub-category
echo $product.'<br />'; // segment(5) is a product
}
else
{
echo $sub_category_or_product.'<br />'; // it's a sub-category or product
// call the db and test whether its a sub-category
// then test if its a product... or the other way around
}
}
of cuz this is just one of the many possible ways to solve it...
however if you don't have to stick with that URL structure...
i would suggest you put products/categories/sub-categories under the "/products/" namespace in the URL for "listing view". and put products under the "/p/something" namespace for the details view
www.example.com/p/ruby // product details
www.example.com/products // product listing
www.example.com/products/gems // product listing
www.example.com/products/gems/red // product listing
for example see:
http://www.beautylish.com/products
http://www.beautylish.com/p/mac-mineralize-skinfinish-natural
this way you won't have to worry about categories/sub-categories names clashing with product names
people probably want to put the cats and sub cats in the product url for seo... but if you check beautylish they got very damn good seo without choking up the url and simply putting only the product name, it's also shorter and more readable.

Magento - How to add multiple items to the cart programmatically?

I'm trying to add multiple simple products to the cart at the same time using a query string as below, however it only adds the last product to the cart instead of both:
Can someone let me know what I'm doing wrong?
http://www.domain.co.uk/checkout/cart/add?product=9916&qty=4&product=15749&qty=4
I have also tried this:
http://www.domain.co.uk/checkout/cart/add?product[]=9916&qty[]=4&product[]=15749&qty[]=4
Any help much appreciated!
Add Product To Cart With Querystring
Add simple product in shopping cart with no attribute.
http://yourserver.com/checkout/cart/add?product=PRODUCT_ID&qty=PRODUCT_QUANTITY
Here PRODUCT_ID = 'Product Id',PRODUCT_QUANTITY = 'product quantity to purchase'.
Add product into shopping cart with single custome option.
http://yourserver.com/checkout/cart/add?product=PRODUCT_ID&qty=PRODUCT_QUANTITY&super_attribute[OPTION_ID]=OPTION_VALUE
Here OPTION_ID = 'Custom attribute option id',OPTION_VALUE = 'Custom attribute option value'.
Add product into shopping cart with multipal custome option.
http://yourserver.com/checkout/cart/add?product=PRODUCT_ID&qty=PRODUCT_QUANTITY&super_attribute[OPTION_ID_1]=OPTION_VALUE_1&super_attribute[OPTION_ID_2]=OPTION_VALUE_2
Here OPTION_ID_1 & OPTION_ID_1 = 'Custom attribute option ids',OPTION_VALUE_1 & OPTION_VALUE_2 = 'Custom attribute option values'.Here add more options in `super_attribute` array
Add Extra products with mail product with only 1 quantity.
http://yourserver.com/checkout/cart/add?product=PRODUCT_ID&qty=PRODUCT_QUANTITY&related_product=PRODUCT_ID_1,PRODUCT_ID_2
Here PRODUCT_ID_1 and PRODUCT_ID_2 is other products id. add more product by id using `,` separator. Example:- &related_product=1,2,3,4.
Default magento there is not setting for add related product quantity into cart.so if you want to add this code than open app/code/core/Mage/Checkout/controllers/CartController.php find public function addAction().
if (!empty($related)) {
$cart->addProductsByIds(explode(',', $related));
}
Replace with
$rel_qty = $this->getRequest()->getParam('related_qty');
if (!empty($related)) {
$relatedproducts = explode(',', $related);
$relatedqtys = explode(',',$rel_qty);
$i = 0;
foreach($relatedproducts as $relatedproduct)
{
$cart->addProduct($relatedproduct, array('qty'=>$relatedqtys[$i]));
$i++;
}
}
Now use query string for add related products with quantity.
http://yourserver.com/cart/add?product=PRODUCT_ID&qty=PRODUCT_QUANTITY&related_product=PRODUCT_ID_1,PRODUCT_ID_2&related_qty=PRODUCT_ID_1_QUANTITY,PRODUCT_ID_2_QUANTITY
If you don't want to change any code, you can try to utilize related products functionality by adding related_product parameter to your request. So your url will look like this:
http://www.domain.co.uk/checkout/cart/add?product=9916&qty=4&related_product=15749
If you want to add more products, just list them with comma separator: related_product=1,2,3
The only drawback from that is that you actually can't specify the qty for related products.
To see how it works - Mage_Checkout_Model_Cart::addProductsByIds(array_of_ids)
If qty for subsequent products is a mandatory for you, you'll need to create your own controller, or override the Mage_Checkout_CartController::addAction method.
I found a cheeky way I found of getting around the quantity limitation of the related_products query string field noted above in other answers. If you just put the SAME ID MULTIPLE TIMES in the value of related_products, as many times as the quantity you need, then that will achieve the same effect as if there was an explicit qty field for each related product. So taking himansu's answer above and adapting it we get:
http://yourserver.com/checkout/cart/add?product=PRODUCT_ID&qty=PRODUCT_QUANTITY&related_product=PRODUCT_ID_1,PRODUCT_ID_1,PRODUCT_ID_1,PRODUCT_ID_2,PRODUCT_ID_2
This will add to the cart PRODUCT_QUANTITY of PRODUCT_ID, 3 of PRODUCT_ID_1, and 2 of PRODUCT_ID_2.
So as long as you're happy doing a little work to generate the same ID multiple times this works a treat. And no custom code changes required on your magento server.

Programmatically ship and comment single item of an order in Magento

I know there is a way to programmatically invoice, ship, and set state on an order (http://www.magentocommerce.com/boards/viewthread/74072/), but I actually need to drill down even deeper to the item level of an order. We have a situation where, depending on item type, two different items can be processed in two different locations (from the same order). I can go into the Magento back-end and "ship" one item without "shipping" the other and append comments to that one item, but I'm looking for a way to do this programmatically. Thank you in advance for your help!
Update:
Here is the code I ended up using to accomplish this:
$client = new SoapClient('http://somesite.domain/magento/index.php/api/?wsdl');
$session = $client->login('username', 'password');
function extract_item_id($items, $sku ){
foreach($items as $item ){
if ($item["sku"]==$sku) {
return $item["item_id"];
}
}
}
$orderNum = "200000052";
$oderInfo = $client->call($session, "sales_order.info", $orderNum );
$item_id = extract_item_id($oderInfo["items"], "someSKU") ;
$itemsQty = array( $item_id => "1" );
$shipment = array(
$orderNum,
$itemsQty,
"Comment associated with item shipped.",
true,
true
);
var_dump($shipment);
$nship = $client->call($session, 'sales_order_shipment.create', $shipment);
I've never done it, but it looks like the SOAP API supports creating individual shipment items. That'd be the first thing I'd check.
If that doesn't work, I'd examine the source code the the Magento admin and reverse engineer what its doing with to create a single item shipment. Specifically, start tracing at the saveAction of the admin's Shipment Controller
app/code/core/Mage/Adminhtml/controllers/Sales/Order/ShipmentController.php
The order/shipment/invoice section of Magento codebase is one of the most volatile/iterative sections, with the core objects/methods/dependencies changing subtly between versions. Finding one "right" answer for this will prove difficult, if not impossible.

Resources