Question

Given an order that has been invoiced (by cash on delivery for testing) and is in state "processing", how can I create a credit memo for a given sku and quantity (in code that is outside of Magento routing; e.g. /test.php)?

Say my order has an item of sku "100-0055-BRO-S" and quantity 2, and I want to refund 1 of these. My current code looks like this:

require 'app/Mage.php';
umask(0);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
setlocale(LC_MONETARY, 'en_US');

$order = Mage::getModel('sales/order')->loadByIncrementId(1117575);
$convertor = Mage::getModel('sales/convert_order');

$refundSku = '100-0055-BRO-S';
$refundQty = 1;
$refundOi = null;
//$refundInvoice = null;

foreach($order->getAllItems() as $oi) {
    if($oi->getSku() == $refundSku) {
        $refundOi = Mage::getModel('sales/order_item')->load($oi->getId());
        break;
    }
}

$mcm = $convertor->toCreditmemo($order);
$mcmi = $convertor->itemToCreditmemoItem($refundOi);
$mcmi->setQty($refundQty);

$mcmi->setDiscountAmount($refundOi->getDiscountAmount() * ($mcmi->getQty() / $mcmi->getOrderItem()->getQtyOrdered()));
$mcmi->setBaseDiscountAmount($refundOi->getBaseDiscountAmount() * ($mcmi->getQty() / $mcmi->getOrderItem()->getQtyOrdered()));
$mcmi->setTaxAmount($refundOi->getTaxAmount() * ($mcmi->getQty() / $mcmi->getOrderItem()->getQtyOrdered()));
$mcmi->setBaseTaxAmount($refundOi->getBaseTaxAmount() * ($mcmi->getQty() / $mcmi->getOrderItem()->getQtyOrdered()));
$mcmi->setHiddenTaxAmount($refundOi->getHiddenTaxAmount() * ($mcmi->getQty() / $mcmi->getOrderItem()->getQtyOrdered()));
$mcmi->setBaseHiddenTaxAmount($refundOi->getBaseHiddenTaxAmount() * ($mcmi->getQty() / $mcmi->getOrderItem()->getQtyOrdered()));

$mcm->addItem($mcmi);
$mcm->register();

Mage::getModel('core/resource_transaction')
    ->addObject($mcm)
    ->addObject($mcm->getOrder())
    ->save();

This results in a credit memo being created on the order and showing up in the admin panel. However, the item looks like this:

Price    Qty  Subtotal   Tax Amount   Discount Amount    Row Total
$38.00    1    $0.00       $1.62           $19.00         -$17.39

I don't understand why the subtotal is 0. Maybe it has something to do with not utilizing the invoice? But I'm not sure how to go even about that. It seems like it is taking the discount amount and subtracting it from the subtotal + tax amount. Also all of the credit memo totals (subtotal, adjustment refund, adjustment fee, tax, grand total) are $0.00.

The math I'm doing to manually set the values for $mcmi (Mage Credit Memo Item) seems sketchy. I would think that Magento would set these for me given the qty I set it to, but it seems like it does not so I have to do it myself. If there is a better way to set these values, I would appreciate the help there too.

Was it helpful?

Solution

Instead of using the converter directly, it would be better to use the order service model instead:

Mage::app('admin');

$order = Mage::getModel('sales/order')->loadByIncrementId('1117575');
$orderItem = $order->getItemsCollection()->getItemByColumnValue('sku', '100-0055-BRO-S');
$service = Mage::getModel('sales/service_order', $order);
$data = array(
    'qtys' => array(
        $orderItem->getId() => 1
    )
);
$creditMemo = $service->prepareCreditmemo($data)->register()->save();

At least that worked fine for me so far.

OTHER TIPS

If you need to refund online you should use as this way:

$order = Mage::getModel('sales/order')->loadByIncrementId('1117575');
$service = Mage::getModel('sales/service_order', $order);

$creditmemo = $service->prepareInvoiceCreditmemo($invoice);
$creditmemo->setRefundRequested(true)
    ->setOfflineRequested(false) // request to refund online
    ->register();

Mage::getModel('core/resource_transaction')
    ->addObject($creditmemo)
    ->addObject($creditmemo->getOrder())
    ->addObject($creditmemo->getInvoice())
    ->save();
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top