/**
  * Set refunded reward amount order and update reward points balance if need
  *
  * @param Varien_Event_Observer $observer
  * @return Enterprise_Reward_Model_Observer
  */
 public function creditmemoSaveAfter(Varien_Event_Observer $observer)
 {
     /* @var $creditmemo Mage_Sales_Model_Order_Creditmemo */
     $creditmemo = $observer->getEvent()->getCreditmemo();
     /* @var $order Mage_Sales_Model_Order */
     $order = $creditmemo->getOrder();
     /* @var $helper Enterprise_Reward_Helper_Data */
     $helper = Mage::helper('enterprise_reward');
     $allowRewardPointsRefund = true;
     if ($creditmemo->getAutomaticallyCreated()) {
         if ($helper->isAutoRefundEnabled()) {
             $creditmemo->setRewardPointsBalanceToRefund($creditmemo->getRewardPointsBalance());
         } else {
             $allowRewardPointsRefund = false;
         }
     }
     if ($creditmemo->getBaseRewardCurrencyAmount() && $allowRewardPointsRefund) {
         $order->setRewardPointsBalanceRefunded($order->getRewardPointsBalanceRefunded() + $creditmemo->getRewardPointsBalance());
         $order->setRewardCurrencyAmountRefunded($order->getRewardCurrencyAmountRefunded() + $creditmemo->getRewardCurrencyAmount());
         $order->setBaseRewardCurrencyAmountRefunded($order->getBaseRewardCurrencyAmountRefunded() + $creditmemo->getBaseRewardCurrencyAmount());
         $order->setRewardPointsBalanceToRefund($order->getRewardPointsBalanceToRefund() + $creditmemo->getRewardPointsBalanceToRefund());
         if ((int) $creditmemo->getRewardPointsBalanceToRefund() > 0) {
             Mage::getModel('enterprise_reward/reward')->setCustomerId($order->getCustomerId())->setStore($order->getStoreId())->setPointsDelta((int) $creditmemo->getRewardPointsBalanceToRefund())->setAction(Enterprise_Reward_Model_Reward::REWARD_ACTION_CREDITMEMO)->setActionEntity($order)->save();
         }
     }
     // Void reward points granted for refunded amount if there was any
     $customerId = $order->getCustomerId();
     $websiteId = Mage::app()->getStore($order->getStoreId())->getWebsiteId();
     // @var $rewardHistoryCollection Enterprise_Reward_Model_Resource_Reward_History_Collection
     $rewardHistoryCollection = Mage::getModel('enterprise_reward/reward_history')->getCollection();
     $rewardHistoryCollection->addCustomerFilter($customerId)->addWebsiteFilter($websiteId)->addFilter('main_table.is_expired', 0)->addFilter('main_table.action', Enterprise_Reward_Model_Reward::REWARD_ACTION_ORDER_EXTRA);
     $isOrderRewardedWithPoints = false;
     /* @var $rewardHistoryRecord Enterprise_Reward_Model_Reward */
     foreach ($rewardHistoryCollection as $rewardHistoryRecord) {
         $additionalData = $rewardHistoryRecord->getAdditionalData();
         if (isset($additionalData['increment_id']) && $additionalData['increment_id'] == $order->getIncrementId() && isset($additionalData['rate']['direction']) && $additionalData['rate']['direction'] == Enterprise_Reward_Model_Reward_Rate::RATE_EXCHANGE_DIRECTION_TO_POINTS && isset($additionalData['rate']['points']) && isset($additionalData['rate']['currency_amount'])) {
             $isOrderRewardedWithPoints = true;
             break;
         }
     }
     unset($rewardHistoryCollection);
     if ($isOrderRewardedWithPoints) {
         /*
          * Calculating amount of funds from total refunded amount for which reward points were acquired
          * @see Enterprise_Reward_Model_Action_OrderExtra::getPoints()
          */
         $rewardedAmountForWholeOrder = $order->getBaseGrandTotal() - $order->getBaseTaxAmount() - $order->getBaseShippingAmount();
         $rewardedAmountRefunded = $order->getBaseTotalRefunded() - $order->getBaseTaxRefunded() - $order->getBaseShippingRefunded();
         $rewardedAmountAfterRefund = $rewardedAmountForWholeOrder - $rewardedAmountRefunded;
         /**
          * Modify amount for which reward points should not be voided at refund
          */
         $result = new Varien_Object();
         $result->setRewardedAmountAfterRefund($rewardedAmountAfterRefund);
         Mage::dispatchEvent('rewarded_amount_after_refund_calculation', array('creditmemo' => $creditmemo, 'result' => $result));
         $rewardedAmountAfterRefund = $result->getRewardedAmountAfterRefund();
         /**
          * Calculating amount of points to void considering reward points exchange rate when they were granted
          * @see Enterprise_Reward_Model_Reward_Rate::calculateToPoints()
          */
         $estimatedRewardPointsAfterRefund = (int) ((string) $rewardedAmountAfterRefund / (string) $additionalData['rate']['currency_amount']) * $additionalData['rate']['points'];
         $rewardPointsVoided = $rewardHistoryRecord->getPointsVoided();
         $acquiredRewardPointsAvailableForVoid = $rewardHistoryRecord->getPointsDelta() - $rewardPointsVoided;
         /*
          * It's not allowed to void more points then were granted per this order.
          * Used points at current history record are not taken into consideration -
          * allowed to void from total amount if it's needed to void more then left at selected history record.
          */
         if ($acquiredRewardPointsAvailableForVoid > $estimatedRewardPointsAfterRefund) {
             $rewardPointsAmountToVoid = $acquiredRewardPointsAvailableForVoid - $estimatedRewardPointsAfterRefund;
         } else {
             $rewardPointsAmountToVoid = 0;
         }
         if ($rewardPointsAmountToVoid > 0) {
             /* @var $reward Enterprise_Reward_Model_Reward */
             $reward = Mage::getModel('enterprise_reward/reward')->setWebsiteId($websiteId)->setCustomerId($order->getCustomerId())->loadByCustomer();
             $rewardPointsBalance = $reward->getPointsBalance();
             if ($rewardPointsBalance > 0) {
                 // It's not allowed to void more points then is available for current customer
                 if ($rewardPointsAmountToVoid > $rewardPointsBalance) {
                     $rewardPointsAmountToVoid = $rewardPointsBalance;
                 }
                 if ($helper->getGeneralConfig('deduct_automatically')) {
                     $reward->setPointsDelta(-$rewardPointsAmountToVoid)->setAction(Enterprise_Reward_Model_Reward::REWARD_ACTION_CREDITMEMO_VOID)->setActionEntity($order)->updateRewardPoints();
                     if ($reward->getRewardPointsUpdated()) {
                         $order->addStatusHistoryComment($helper->__('%s was deducted because of refund.', $helper->formatReward($rewardPointsAmountToVoid)));
                     }
                 }
                 /*
                  * Config option deduct_automatically is not considered here because points for refunded amount that
                  * were not been voided automatically need to be counted in possible future automatic deductions.
                  */
                 $rewardHistoryRecord->getResource()->updateHistoryRow($rewardHistoryRecord, array('points_voided' => $rewardPointsVoided + $rewardPointsAmountToVoid));
             }
         }
     }
     return $this;
 }