Programmatically invoice a single product off of an order
Question
How could I go about programmatically invoicing a single product off of a sales order of more than one product?
I.E Order X has three products, SKU1, SKU2 & SKU3. I only want to create an invoice for SKU1.
I've looked into
\app\code\core\Mage\Adminhtml\controllers\Sales\Order\InvoiceController.php
Though I get a little stuck when I see the _getItemQtys()
method.
Could really use some advice.
Solution 2
The solution is setting up an array with the key being the order's item_id (note that this is not the same as product_id, it is a unique identifier).
Let's say you have an order $increment_id (order number):
$order = Mage::getModel('sales/order')->loadByIncrementId($increment_id);
$items = $order->getItemsCollection();
$qtys = array(); //this will be used for processing the invoice
foreach($items as $item){
$qty_to_invoice = x; //where x is the amount you wish to invoice
<!-- please note that if you don't want to invoice this product, set this value to 0 -->
$qtys[$item->getId()] = $qty_to_invoice;
<!-- Note that the ->getId() method gets the item_id on the order, not the product_id -->
}
$invoice = Mage::getModel('sales/service_order', $order)->prepareInvoice($qtys);
<!-- The rest is only required when handling a partial invoice as in this example-->
$amount = $invoice->getGrandTotal();
$invoice->register()->pay();
$invoice->getOrder()->setIsInProcess(true);
$history = $invoice->getOrder()->addStatusHistoryComment(
'Partial amount of $' . $amount . ' captured automatically.', false
);
$history->setIsCustomerNotified(true);
$order->save();
Mage::getModel('core/resource_transaction')
->addObject($invoice)
->addObject($invoice->getOrder())
->save();
$invoice->save();
$invoice->sendEmail(true, ''); //set this to false to not send the invoice via email
OTHER TIPS
$order = Mage::getModel('sales/order')->loadByIncrementId($increment_id);
$items = $order->getAllItems();
$qtys = array(); //this will be used for processing the invoice
foreach($items as $item){
if ($item->getSku() == 'SKU1') {
$qty_to_invoice = $item->getQtyOrdered(); // now gets order quantity of item
} else {
$qty_to_invoice = 0;
}
$qtys[$item->getId()] = $qty_to_invoice;
<!-- Note that the ->getId() method gets the item_id on the order, not the product_id -->
}
$invoice = Mage::getModel('sales/service_order', $order)->prepareInvoice($qtys);
Enhanced the answer so it's more clear when you want only a specific SKU
Try this one...
<?php
$orderID = "145000010"; //order increment id
$orderDetails = Mage::getModel('sales/order')->loadByIncrementId($orderID);
if($orderDetails->canInvoice() and $orderDetails->getIncrementId())
{
//$order = Mage::getModel('sales/order')->loadByIncrementId($order_id);
$orderItems = $orderDetails->getAllItems();
$invoiceItems = array();
foreach ($orderItems as $_eachItem) {
$opid = $_eachItem->getId();
$opdtId = $_eachItem->getProductId();
$itemss = Mage::getModel('catalog/product')->load($opdtId);
$psku = $itemss->getSku(); // get product attribute which is used your condition
if($psku=='Test product1'){
$qty = $_eachItem->getQtyOrdered();
} else {
$qty = 0;
}
$itemsarray[$opid] = $qty;
}
if($orderDetails->canInvoice()) {
echo $invoiceId = Mage::getModel('sales/order_invoice_api')
->create($orderDetails->getIncrementId(), $itemsarray ,'Partially create Invoice programatically' ,0,0);
}
}
?>
For more info
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange