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.

Was it helpful?

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
scroll top