Pregunta

I have created a link in Magento admin to create the invoice for individual product, But while calling the function $order->prepareInvoice($qtys) it will add all the product in invoice even I am passing only one item.

I am using below code.

$order = Mage::getModel('sales/order')->load($this->getRequest()->getParam('order_id'));

$count = $order->getTotalItemCount();

$qtys = Array
    (
        [370] => 1
    );

$invoice = $order->prepareInvoice($qtys);
if (!$invoice->getTotalQty()) {
    Mage::throwException(Mage::helper('core')->__('Cannot create an invoice without products.'));
}

$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();

enter image description here

Any Suggestion ?

¿Fue útil?

Solución

The logic found in Mage_Sales_Model_Service_Order::prepareInvoice, the method which you are ultimately calling to prepare the invoice, reveals what is at play here. The following loop is employed, and the inner else-if block is where the qty is set when an array of qtys is passed in:

foreach ($this->_order->getAllItems() as $orderItem) {
    if (!$this->_canInvoiceItem($orderItem, array())) {
        continue;
    }
    $item = $this->_convertor->itemToInvoiceItem($orderItem);
    if ($orderItem->isDummy()) {
        $qty = $orderItem->getQtyOrdered() ? $orderItem->getQtyOrdered() : 1;
    } else if (!empty($qtys)) {
        if (isset($qtys[$orderItem->getId()])) {
            $qty = (float) $qtys[$orderItem->getId()];
        }
    } else {
        $qty = $orderItem->getQtyToInvoice();
    }
    $totalQty += $qty;
    $item->setQty($qty);
    $invoice->addItem($item);
}

The $qtys variable is the array which you are passing in to the prepareInvoice call. In your case, you are only passing an index for the item you wish to add to the invoice. Per the documentation (and the above loop), this should work, except for one minor problem: the above loop is not resetting the value of $qty at the top of the loop to 0. This does not pose a problem when called from the core code which processes initialization of the invoice when created from the admin via the pre-existing form, as the form which is being submitted will always contain a value for each item on the order, and in the case of only 1 item being invoiced, all others will hold a 0 qty value thus working around the failure to reset the value of $qty.

To solve your problem, try setting your $qtys variable like so (I'm assuming 370 and 371 are the two order item entity ids):

$qtys = array(
    370 => 1,
    371 => 0,
);

An alternative which I might suggest would be to simply have your "Create Invoice" link set the appropriate values in the form to invoice the individual item and then submit the form directly. This way you'll be relying on the known-to-be-working core controller for the heavy lifting. This will, of course, only work if you are not doing anything fairly customized beyond invoicing the single item. :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top