how to insert cart items as individual orders in opencart - php

im building a small store using opencart. i currently allow only 1 product to be added to the cart, so when a user adds different products it replaces with the new product. but allows to change the quantity of that product.
what i need to do is once a person has successfully purchased an item with a quantity of eg; 3
the product needs to be saved as 3 different orders.
is this possible to do in OC? if yes can someone please guide me how to do it?

The solution is quite simple - when creating and confirming order instead of creating one order for a product with quantity XYZ, do a loop and store XYZ orders for just one product quantity.
Basically You'll be changing mostly catalog/model/checkout/order.php::addOrder() - here the loop will take place basically around the whole function body, e.g.:
for ($i = 0; $i < $data['products'][0]['quantity']; $i++) {
// the rest of the method, but removing
// foreach ($data['products'] as $product) - this is not needed anymore
}
Also return an array of newly created order IDs so that you can confirm them afterwards...
Then You'll need to modify all the used payment controllers as these are confirming order - You'll need to change them to confirm all of the orders (which IDs You have returned when adding them - they may be stored in a session).
Though it may take some time (depending on how many payment options You use) it is not that difficult.

Related

WooCommerce Recalculate Order, Taxes - Delete & Add Order_item + discount

I would like to briefly give you some information about our problem here: We need to correct all our Woocommerce orders from 2021 and now we are facing a big challenge. Since we have changed the tax class on the products, we can't just have the order recalculated but need to re-add the entire order line item to the order and remove the old line item.
We have now found a workaround that works:
Edit corresponding purchase order
Set purchase order from "completed" to "on hold
Update/Save
Now the order can be edited:
Check which coupon has been redeemed
Remember the product ID of the order
Delete product completely
Add new product via product ID
If voucher was used Add voucher code
Update/Save
This is exactly the process we use to correct our orders as needed. From this we have programmed a bot that goes through this process in wp-admin. Unfortunately, with tens of thousands of orders, this takes months....
Now I have come across Hooks and Functions and believe there is a simpler solution here.
For example I found this thread: How Can I remove a particular product from an completed order in woocommerce?
foreach ($order->get_items() as $item_id => $item) {
if ($item_id == 3) {
wc_delete_order_item($item_id);
}
}
Here it is explained how to remove an order-item from the order.
We would need a Function that:
Opens an order
Saves the order_item_id to itself
Deletes the order_item
adds the order_item again
checks if there was a coupon
if yes: delete old voucher & add new voucher
Does anyone have any ideas or can help us with this?
Thanks a lot!

Shopify allows to add any number of units to cart

In my Shopify website, users are able to add any number of units for a product irrespective of the inventory. The stock is only checked when users click on checkout. How can I handle this issue?
Ideally, users should be able to add only available inventory to the cart. It's annoying when someone adds multiple quantities only to know they aren't in stock.
You need to check the variant.inventory_quantity => https://shopify.dev/docs/themes/liquid/reference/objects/variant#variant-inventory_quantity
If you have no option you can get it like so product.first_available_variant.inventory_quantity.
But if you have multiply options you will need to loop all the variants and create a JS object that will store each variant inventory_quantity and perform a JS check or update the max attribute of the number input for the quantity before adding the product to the cart.

magento customize quote collectTotals to show the updated totals

hey i'm implementing a custom discount system since magento discount system does not feet my requirements so i'm trying to apply a discount on an Mage_Sales_Model_Quote_Item I've read some and I've found the following function setOriginalCustomPrice the thing is that it applies on the item, and if the user changes the quantity he will get the discount on the item with the new quantity, so i'm trying to use a different method addOption on the item and only on the cart page show the calculations based on the quantity in the option value
$item->addOption(array('code'=>'promo','value' => serialize(['amount'=>10,'qty'=>1])));
and in the cart page
$promo = $item->getOptionByCode('promo');
echo '<div class="orig-price">'.$item->getOriginalPrice().'</div>';
echo '<div class="new-price">'.$item->getOriginalPrice() - ($promo['amount'] * $promo['qty']).'</div>';
the problem is that it does'nt actually apply the new price on the product,
so i want to customize Mage_Sales_Model_Quote->collectTotals() to show my discounts
and send it to the admin back-end when order is completed
how can i achieve that?
thanks in advance
I think there is a fundamental flaw in your approach. I'm not sure what you don't like in standard discounts, and what you can't achieve with catalog or shopping cart rules, but what you're trying to do definitely breaks these features (along with my heart).
However, if you're sure about what you're trying to do, then don't customize Mage_Sales_Model_Quote->collectTotals().
This function just... well, it collects all totals: subtotal, shipping, discount, etc. And it looks like you're changing only price output, but Magento itself doesn't know anything about it.
So if you want to let Magento know that you're changing the item price, you have to either add your own total, or change one of the existing totals. After that Magento will do everything else. Since after your changes Magento outputs already calculated price instead of original one, it may be strange for customer to see the original price in the cart and the additional discount total. So it looks like you will have to change subtotal total.
To do that you have to rewrite Mage_Sales_Model_Quote_Address_Total_Subtotal class in your extension and insert your calculation in _initItem() method. Around line 111 in the original file you will see the code:
$item->setPrice($finalPrice)
->setBaseOriginalPrice($finalPrice);
And this is where Magento sets price for the item, so you can insert your calculations and change $finalPrice before that. If you have virtual products, you will have to change collect() method too.

Separation of Concerns and OOP PHP -- Product price based on other products in cart

I'm looking to implement some e-commerce functionality that gives discounts when certain quantities are reached. The catch is, its not quantities of one sku, any number of other products in a category can trigger the quantity break when in total they reach the threshold.
So if I have a model class for a Cart_Product lets say, I would typically put the logic for getting the prices in that class as a method. But since other instances of that class in the current cart need to be considered, I'm not sure of the best way to proceed.
Do I call the "owner" Cart instance inside of the Cart_Product get_price method and then add the logic to check for the quantity break? Or is there a better design pattern to use at this step?
First of all, model is not a class or instance. Model is a layer. What you are talking about in your question actually are domain objects (assuming they are not also responsible for saving themselves, which would violate SRP.
As for applying the discount, it depends on whether each product in your cart has a separate discount of the discount is same for all the products:
if each product can have a separate discount, then the logic for that should reside in the Product domain object.
if all products get the same discount, then the discount should affect only the sum total, therefore - compute in the Cart instance.
The logic you have described is a cart-wide feature; since the cart is the logical owner of the products inside, you would implement it there:
class Cart
{
private $products; // Cart_Product[]
// ...
function calculateDiscount()
{
$totalQuantity = array_reduce($this->products, function($sum, $product) {
return $sum + $product->getQuantity();
}, 0);
if ($totalQuantity > 10) {
$this->cartDiscount = 25; // apply 25% discount on the cart
} else {
$this->cartDiscount = 0;
}
}
}
This introduces a separate entity for a global cart discount. If you don't want that, you would have to apply the discount to each individual item.
i just went through something very similar. really the only thing the cart should know about is the product id and the quantity. everything else should be for display purposes only. in other words the product object is always responsible for the price. the only reason that a price is stored in the cart is to help show it in the view. otherwise we assume that the price always has to be checked with any insert or update, to prevent fraud.
here is another scenario - you have a special on shipping, like buy $100 worth of qualifying goods and you get free shipping. there might be a separate shipping special on specific products. the only way to calculate is with all of the cart items.
so my solution - which i am not sure is optimal - is to pass the cart items to a shipping object - do the shipping calculations - optionally add messaging for specific products to display in the cart - and then return the cart items.
otherwise you are having to put shipping methods in the cart class which does not make any sense but maybe there is another way to do this.
here is another scenario - inventory control. someone orders 30 blue widgets but you only have 10 blue widgets. ok you can check for inventory when you insert item in cart. but what if they update the cart and then increase to 30? that means that we have to check inventory - for every item in the cart - every time the cart is updated. and if we are doing that then might as well get the price in case it has gone up or down.
so i take the cart items - and pass them to a product object - which checks inventory - and if necessary reduces the quantity of the items down to current inventory - optionally adds messaging explaining that stock is limited - then passes back to cart object.
finally - suggest that you have an object that owns the shopping session. and then thats where the totals would be. that way the cart is never in charge of totals - its just a container. one way is you just start an order and then store the different totals there.

Restricting customers to max of 2 purchases for a certain product in Magento

I currently have an issue trying to restrict customers to purchasing 2 of a product max.
So far, I can set the max number of the product in the cart to 2 using catalog/manage products, select the product, then inventory and adjusting the max Qty allowed in cart to 2.
However, this will not stop the user coming back another day and purchasing another 2 items.
What I would like to do is create a rule so that when the user logs in and tries to purchase the product, after already purchasing it, the code will throw an error saying that they have reached their max quantity and prevent the cart from processing the order.
I believe that I would have to edit one of the php files to run a check against the users id and the product id, but I am unsure which file will need to be edited.
Magento ver. 1.3.2.4
Links that helped me, hope it helps:
step 1
step 2
First of all create one observer checkout_cart_add_product_before
In this observer event check cart quantity of product, you can get qoute item from quote object and from quote retrieve product quantity and match with newly added product if condition satisfied then redirect customer to product details page with mesage
To support future compatibility and prevent your changes from being overwritten you should create a custom extension that hooks into the core.
You might try the hook: checkout_cart_add_product_complete or checkout_cart_add_product_before and test the number of items of each product. Based on that result you might automatically remove the item and parse an error.

Categories