I created a custom charges on order for some specific products, Unfortunately custom charge was not updated in order total like cash on delivery,
Is there any way to update orders totals after order created without cancel order?
I think you can do this just like you would modify any other model instance.
$item = Mage::getModel('sales/order_item')->load(id here);
$item->setPrice(40)->setBasePrice(40)->save();
then
$order = Mage::getModel('sales/order')->load(order id here);
$order->setSubtotal(70)->setBaseSubtotal(70);
$order->setDiscountAmount(7)->setBaseDiscountAmout(7);
$order->setGrandTotal(63)->setBaseGrandTotal(63);
$order->save();
You might also need to change other values like tax, subtotal_incl_tax and others.
But this is a bad practice and you should not do it. It is better just to cancel the order and create a new one.
Here I have created a solution to set custom item price and recalculate all the order totals.
We will need to calculate manually as the collectTotals will not work after an order is placed.
<?php
require_once('app/Mage.php'); //Path to Magento
umask(0);
Mage::app();
echo "<pre>";
$customProductPrice = 5; // Custom Product Price For One Quantity
$item = Mage::getModel('sales/order_item')->load(15); //Order Itemid
if($item): //Check item object exists or not
$quantity = $item->getQtyOrdered();
$rowTotal = $customProductPrice * $quantity;
# calculateTaxAmount
if (!empty($item->getTaxPercent())) {
$taxAmount = ($rowTotal * $item->getTaxPercent()) / 100;
$item->setTaxAmount($taxAmount)
->setBaseTax_amount($taxAmount);
}
# Price In Grid Update
$item->setPrice($customProductPrice)
->setBasePrice($customProductPrice);
#Subtotal On Order * Qty
$item->setRowTotal($rowTotal)
->setBaseRowTotal($rowTotal)
->setRowTotalInclTax($rowTotal)
->setBaseRowTotalInclTax($rowTotal);
# Apply Item Discounted Amount (Recaculated Discount)
if (!empty($item->getDiscountPercent())) {
$discountedAmount = $item->getRowTotal()*$item->getDiscountPercent()/100;
$item->setDiscountAmount($discountedAmount)
->setBaseDiscountAmount($discountedAmount);
}
$item->save();
$order = Mage::getModel('sales/order')->load(11); //Orderid
$orderSubTotal = 0;
$orderBaseTax = 0;
$orderDiscountAmount = 0;
foreach ($order->getAllVisibleItems() as $_item) {
$orderSubTotal += $_item->getBaseRowTotal();
$orderBaseTax += $_item->getBaseTaxAmount() + $_item->getBaseHiddenTaxAmount();
$orderDiscountAmount += $_item->getBaseDiscountAmount();
}
$grandTotal = ($orderSubTotal + $order->getShippingAmount() + $orderBaseTax) - $orderDiscountAmount;
# Update Order Totals
$order->setSubtotal($orderSubTotal)
->setBaseSubtotal($orderSubTotal)
->setDiscountAmount($orderDiscountAmount)
->setBaseDiscountAmount($orderDiscountAmount)
->setTaxAmount($orderBaseTax)
->setBaseTaxAmount($orderBaseTax)
->setGrandTotal($grandTotal)
->setBaseGrandTotal($grandTotal)
->save();
endif;
In addition to the response from Ashish, I will add these changes before the $item->save();:
$orderAllItems = $order->getAllItems();
foreach ($orderAllItems as $item) {
...
// Tax Amount
$item->setRowInvoiced($taxAmount)
->setBaseTaxInvoiced($taxAmount);
// Amount item without tax
$item->setRowInvoiced($rowTotal)
->setBaseRowInvoiced($rowTotal);
// Amount item with tax
$totalWithTax = $rowTotal + $taxAmount;
$item->setPriceInclTax($totalWithTax)
->setBasePriceInclTax($totalWithTax)
->setRowTotalInclTax($totalWithTax)
->setBaseAmountPaid($totalWithTax)
->setAmountPaid($totalWithTax)
->setBaseAmountOrdered($totalWithTax)
->setAmountOrdered($totalWithTax)
->setOriginalPrice($totalWithTax)
->setBaseOriginalPrice($totalWithTax)
;
$item->save();
...
}
...
Also these changes before the $order->save();:
...
$order->setSubtotalInvoiced($orderSubTotal)
->setBaseSubtotalInvoiced($orderSubTotal)
->setBaseTaxInvoiced($orderBaseTax)
->setTaxInvoiced($orderBaseTax)
->setTotalPaid($grandTotal)
->setBaseTotalPaid($grandTotal)
->setTotalInvoiced($grandTotal)
->setBaseSubtotalInclTax($grandTotal)
->setSubtotalInclTax($grandTotal)
->setBaseTotalInvoiced($grandTotal)
->setBaseToGlobalRate($grandTotal)
->setBaseToOrderRate($grandTotal)
->setStoreToBaseRate($grandTotal)
->setStoreToOrderRate($grandTotal)
;
$order->save();
Otherwise you could keep old amounts in your order object, then elsewhere than in the order view. For instant the creditmemo form.
So here the final code if I modify Ashish code:
<?php
require_once('app/Mage.php'); //Path to Magento
umask(0);
Mage::app();
echo "<pre>";
$customProductPrice = 5; // Custom Product Price For One Quantity
$item = Mage::getModel('sales/order_item')->load(15); //Order Itemid
if($item): //Check item object exists or not
$quantity = $item->getQtyOrdered();
$rowTotal = $customProductPrice * $quantity;
# calculateTaxAmount
if (!empty($item->getTaxPercent())) {
$taxAmount = ($rowTotal * $item->getTaxPercent()) / 100;
$item->setTaxAmount($taxAmount)
->setBaseTax_amount($taxAmount)
->setTaxInvoiced($taxAmount)
->setBaseTaxInvoiced($taxAmount);
}
# Price In Grid Update
$item->setPrice($customProductPrice)
->setBasePrice($customProductPrice);
#Subtotal On Order * Qty
$item->setRowTotal($rowTotal)
->setBaseRowTotal($rowTotal)
->setRowTotalInclTax($rowTotal)
->setBaseRowTotalInclTax($rowTotal)
->setRowInvoiced($rowTotal)
->setBaseRowInvoiced($rowTotal);
// Amount item with tax
$totalWithTax = $rowTotal + $taxAmount;
$item->setPriceInclTax($totalWithTax)
->setBasePriceInclTax($totalWithTax)
->setRowTotalInclTax($totalWithTax)
->setBaseAmountPaid($totalWithTax)
->setAmountPaid($totalWithTax)
->setBaseAmountOrdered($totalWithTax)
->setAmountOrdered($totalWithTax)
->setOriginalPrice($totalWithTax)
->setBaseOriginalPrice($totalWithTax);
# Apply Item Discounted Amount (Recaculated Discount)
if (!empty($item->getDiscountPercent())) {
$discountedAmount = $item->getRowTotal()*$item->getDiscountPercent()/100;
$item->setDiscountAmount($discountedAmount)
->setBaseDiscountAmount($discountedAmount);
}
$item->save();
$order = Mage::getModel('sales/order')->load(11); //Orderid
$orderSubTotal = 0;
$orderBaseTax = 0;
$orderDiscountAmount = 0;
foreach ($order->getAllVisibleItems() as $_item) {
$orderSubTotal += $_item->getBaseRowTotal();
$orderBaseTax += $_item->getBaseTaxAmount() + $_item->getBaseHiddenTaxAmount();
$orderDiscountAmount += $_item->getBaseDiscountAmount();
}
$grandTotal = ($orderSubTotal + $order->getShippingAmount() + $orderBaseTax) - $orderDiscountAmount;
# Update Order Totals
$order->setSubtotal($orderSubTotal)
->setBaseSubtotal($orderSubTotal)
->setSubtotalInvoiced($orderSubTotal)
->setBaseSubtotalInvoiced($orderSubTotal)
->setDiscountAmount($orderDiscountAmount)
->setBaseDiscountAmount($orderDiscountAmount)
->setTaxAmount($orderBaseTax)
->setBaseTaxAmount($orderBaseTax)
->setBaseTaxInvoiced($orderBaseTax)
->setTaxInvoiced($orderBaseTax)
->setGrandTotal($grandTotal)
->setBaseGrandTotal($grandTotal)
->setTotalPaid($grandTotal)
->setBaseTotalPaid($grandTotal)
->setTotalInvoiced($grandTotal)
->setBaseSubtotalInclTax($grandTotal)
->setSubtotalInclTax($grandTotal)
->setBaseTotalInvoiced($grandTotal)
->setBaseToGlobalRate($grandTotal)
->setBaseToOrderRate($grandTotal)
->setStoreToBaseRate($grandTotal)
->setStoreToOrderRate($grandTotal)
->save();
endif;
Cheers, Axel