/**
  * Update subscription based on given quote
  *
  * @param Mage_Sales_Model_Quote $quote
  * @param Adyen_Subscription_Model_Subscription $subscription
  * @return Adyen_Subscription_Model_Subscription $subscription
  */
 public function updateSubscription(Mage_Sales_Model_Quote $quote, Adyen_Subscription_Model_Subscription $subscription)
 {
     Mage::dispatchEvent('adyen_subscription_quote_updatesubscription_before', array('subscription' => $subscription, 'quote' => $quote));
     $term = $termType = $stockId = null;
     foreach ($quote->getItemsCollection() as $quoteItem) {
         /** @var Mage_Sales_Model_Quote_Item $quoteItem */
         $productSubscription = $this->_getProductSubscription($quoteItem);
         if (!$productSubscription) {
             // No product subscription found, no subscription needs to be created
             continue;
         }
         if (is_null($stockId)) {
             $stockId = $quoteItem->getStockId();
         }
         if (is_null($term)) {
             $term = $productSubscription->getTerm();
         }
         if (is_null($termType)) {
             $termType = $productSubscription->getTermType();
         }
         if ($term != $productSubscription->getTerm() || $termType != $productSubscription->getTermType()) {
             Adyen_Subscription_Exception::throwException('Adyen Subscription options of products in quote have different terms');
         }
     }
     $billingAgreement = $this->getBillingAgreement($quote);
     $this->updateQuotePayment($quote, $billingAgreement);
     if (!$quote->getShippingAddress()->getShippingMethod()) {
         Adyen_Subscription_Exception::throwException('No shipping method selected');
     }
     // Update subscription
     $subscription->setStatus(Adyen_Subscription_Model_Subscription::STATUS_ACTIVE)->setStockId($stockId)->setBillingAgreementId($billingAgreement->getId())->setTerm($term)->setTermType($termType)->setShippingMethod($quote->getShippingAddress()->getShippingMethod())->setUpdatedAt(now())->save();
     // Create subscription addresses
     Mage::getModel('adyen_subscription/subscription_address')->getSubscriptionAddress($subscription, self::ADDRESS_TYPE_BILLING)->initAddress($subscription, $quote->getBillingAddress())->save();
     Mage::getModel('adyen_subscription/subscription_address')->getSubscriptionAddress($subscription, self::ADDRESS_TYPE_SHIPPING)->initAddress($subscription, $quote->getShippingAddress())->save();
     // Delete current subscription items
     foreach ($subscription->getItemCollection() as $subscriptionItem) {
         /** @var Adyen_Subscription_Model_Subscription_Item $subscriptionItem */
         $subscriptionItem->delete();
     }
     $i = 0;
     // Create new subscription items
     foreach ($quote->getItemsCollection() as $quoteItem) {
         /** @var Mage_Sales_Model_Quote_Item $quoteItem */
         /** @var Adyen_Subscription_Model_Product_Subscription $productSubscription */
         $productSubscription = $this->_getProductSubscription($quoteItem);
         if (!$productSubscription) {
             // No product subscription found, no subscription needs to be created
             continue;
         }
         $productOptions = array('info_buyRequest' => unserialize($quoteItem->getOptionByCode('info_buyRequest')->getValue()), 'additional_options' => unserialize($quoteItem->getOptionByCode('additional_options')->getValue()));
         /** @var Adyen_Subscription_Model_Subscription_Item $subscriptionItem */
         $subscriptionItem = Mage::getModel('adyen_subscription/subscription_item')->setSubscriptionId($subscription->getId())->setStatus(Adyen_Subscription_Model_Subscription_Item::STATUS_ACTIVE)->setProductId($quoteItem->getProductId())->setProductOptions(serialize($productOptions))->setSku($quoteItem->getSku())->setName($quoteItem->getName())->setLabel($productSubscription->getLabel())->setPrice($quoteItem->getPrice())->setPriceInclTax($quoteItem->getPriceInclTax())->setQty($quoteItem->getQty())->setOnce(0)->setCreatedAt(now())->save();
         Mage::dispatchEvent('adyen_subscription_quote_updatesubscription_add_item', array('subscription' => $subscription, 'item' => $subscriptionItem));
         $i++;
     }
     if ($i <= 0) {
         Adyen_Subscription_Exception::throwException('No subscription products in the subscription');
     }
     Mage::dispatchEvent('adyen_subscription_quote_updatesubscription_after', array('subscription' => $subscription, 'quote' => $quote));
     return $subscription;
 }
 public function updateQuotePayment(Adyen_Subscription_Model_Subscription $subscription, Mage_Sales_Model_Quote $quote)
 {
     Mage::dispatchEvent('adyen_subscription_service_updatequotepayment_before', array('subscription' => $subscription, 'quote' => $quote));
     // Set payment method
     $methodInstance = $subscription->getBillingAgreement()->getPaymentMethodInstance();
     if (!method_exists($methodInstance, 'initBillingAgreementPaymentInfo')) {
         Mage::helper('adyen_subscription')->logQuoteCron(sprintf('Payment method %s does not support Adyen_Subscription', $methodInstance->getCode()));
         Adyen_Subscription_Exception::throwException(Mage::helper('adyen_subscription')->__('Payment method %s does not support Adyen_Subscription', $methodInstance->getCode()));
     }
     // Set billing agreement data
     /* @noinspection PhpUndefinedMethodInspection */
     try {
         /* @noinspection PhpUndefinedMethodInspection */
         $methodInstance->initBillingAgreementPaymentInfo($subscription->getBillingAgreement(), $quote->getPayment());
         // importan $quote->save() will not update payment object so use this:
         $quote->getPayment()->save();
         Mage::dispatchEvent('adyen_subscription_service_updatequotepayment_after', array('subscription' => $subscription, 'quote' => $quote));
     } catch (Mage_Core_Exception $e) {
         Mage::helper('adyen_subscription')->logQuoteCron(sprintf('Failed to set billing agreement data %s', $e->getMessage()));
         $subscription->setErrorMessage($e->getMessage());
         $subscription->setStatus($subscription::STATUS_QUOTE_ERROR);
         Mage::getModel('core/resource_transaction')->addObject($quote)->addObject($subscription)->save();
         Mage::dispatchEvent('adyen_subscription_service_updatequotepayment_fail', array('subscription' => $subscription, 'status' => $subscription::STATUS_QUOTE_ERROR, 'error' => $e->getMessage()));
     }
 }
 /**
  * Update subscription based on given quote
  *
  * @param Mage_Sales_Model_Quote $quote
  * @param Adyen_Subscription_Model_Subscription $subscription
  * @return Adyen_Subscription_Model_Subscription $subscription
  */
 public function updateSubscription(Mage_Sales_Model_Quote $quote, Adyen_Subscription_Model_Subscription $subscription)
 {
     Mage::dispatchEvent('adyen_subscription_quote_updatesubscription_before', array('subscription' => $subscription, 'quote' => $quote));
     try {
         $subscription->getResource()->beginTransaction();
         $term = $termType = $stockId = null;
         foreach ($quote->getItemsCollection() as $quoteItem) {
             /** @var Mage_Sales_Model_Quote_Item $quoteItem */
             $productSubscription = $this->_getProductSubscription($quoteItem);
             if (!$productSubscription) {
                 // No product subscription found, no subscription needs to be created
                 continue;
             }
             if (is_null($stockId)) {
                 $stockId = $quoteItem->getStockId();
             }
             if (is_null($term)) {
                 $term = $productSubscription->getTerm();
             }
             if (is_null($termType)) {
                 $termType = $productSubscription->getTermType();
             }
             if ($term != $productSubscription->getTerm() || $termType != $productSubscription->getTermType()) {
                 Adyen_Subscription_Exception::throwException('Adyen Subscription options of products in quote have different terms');
             }
         }
         $billingAgreement = $this->getBillingAgreement($quote);
         $this->updateQuotePayment($quote, $billingAgreement, $subscription->getData('payment'));
         if (!$quote->getShippingAddress()->getShippingMethod()) {
             Adyen_Subscription_Exception::throwException('No shipping method selected');
         }
         // Update subscription
         $subscription->setStatus(Adyen_Subscription_Model_Subscription::STATUS_ACTIVE)->setStockId($stockId)->setBillingAgreementId($billingAgreement->getId())->setTerm($term)->setTermType($termType)->setShippingMethod($quote->getShippingAddress()->getShippingMethod())->setUpdatedAt(now())->save();
         // Create subscription addresses
         $billingAddress = $quote->getBillingAddress();
         $billingAddress->setCustomerAddressId($subscription->getData('billing_customer_address_id'))->setSaveInAddressBook($subscription->getData('billing_address_save_in_address_book'));
         Mage::getModel('adyen_subscription/subscription_address')->getSubscriptionAddress($subscription, self::ADDRESS_TYPE_BILLING)->initAddress($subscription, $billingAddress)->save();
         $shippingAddress = $quote->getShippingAddress();
         $shippingAddress->setCustomerAddressId($subscription->getData('shipping_customer_address_id'))->setSaveInAddressBook($subscription->getData('shipping_address_save_in_address_book'))->setSameAsBilling($billingAddress->getSaveInAddressBook() && $subscription->getData('shipping_as_billing'));
         Mage::getModel('adyen_subscription/subscription_address')->getSubscriptionAddress($subscription, self::ADDRESS_TYPE_SHIPPING)->initAddress($subscription, $shippingAddress)->save();
         // Save addresses at customer when 'Save in address book' is selected
         if ($billingAddress->getCustomerAddressId() && $billingAddress->getSaveInAddressBook()) {
             $customerBillingAddress = Mage::getModel('customer/address')->load($billingAddress->getCustomerAddressId());
             Mage::helper('core')->copyFieldset('sales_convert_quote_address', 'to_customer_address', $billingAddress, $customerBillingAddress);
             $customerBillingAddress->save();
         }
         if (!$subscription->getBillingAddress() instanceof Mage_Customer_Model_Address) {
             $quote->getBillingAddress()->setCustomerAddressId(null)->save();
         }
         if ($shippingAddress->getCustomerAddressId() && $shippingAddress->getSaveInAddressBook()) {
             $customerShippingAddress = Mage::getModel('customer/address')->load($shippingAddress->getCustomerAddressId());
             Mage::helper('core')->copyFieldset('sales_convert_quote_address', 'to_customer_address', $shippingAddress, $customerShippingAddress);
             $customerShippingAddress->save();
         }
         if (!$subscription->getShippingAddress() instanceof Mage_Customer_Model_Address) {
             $quote->getShippingAddress()->setCustomerAddressId(null)->save();
         }
         // Delete current subscription items
         foreach ($subscription->getItemCollection() as $subscriptionItem) {
             /** @var Adyen_Subscription_Model_Subscription_Item $subscriptionItem */
             $subscriptionItem->delete();
         }
         $i = 0;
         // Create new subscription items
         foreach ($quote->getItemsCollection() as $quoteItem) {
             /** @var Mage_Sales_Model_Quote_Item $quoteItem */
             /** @var Adyen_Subscription_Model_Product_Subscription $productSubscription */
             $productSubscription = $this->_getProductSubscription($quoteItem);
             if (!$productSubscription || $quoteItem->getParentItemId()) {
                 // No product subscription found, no subscription needs to be created
                 // or item is child of bundle/configurable
                 continue;
             }
             $productOptions = array('info_buyRequest' => unserialize($quoteItem->getOptionByCode('info_buyRequest')->getValue()), 'additional_options' => unserialize($quoteItem->getOptionByCode('additional_options')->getValue()));
             /** @var Adyen_Subscription_Model_Subscription_Item $subscriptionItem */
             $subscriptionItem = Mage::getModel('adyen_subscription/subscription_item')->setSubscriptionId($subscription->getId())->setStatus(Adyen_Subscription_Model_Subscription_Item::STATUS_ACTIVE)->setProductId($quoteItem->getProductId())->setProductOptions(serialize($productOptions))->setSku($quoteItem->getSku())->setName($quoteItem->getName())->setProductSubscriptionId($productSubscription->getId())->setLabel($productSubscription->getLabel())->setPrice($quoteItem->getPrice())->setPriceInclTax($quoteItem->getPriceInclTax())->setQty($quoteItem->getQty())->setOnce(0)->setCreatedAt(now())->save();
             Mage::dispatchEvent('adyen_subscription_quote_updatesubscription_add_item', array('subscription' => $subscription, 'item' => $subscriptionItem));
             $i++;
         }
         if ($i <= 0) {
             Adyen_Subscription_Exception::throwException('No subscription products in the subscription');
         }
         $subscription->getResource()->commit();
         Mage::helper('adyen_subscription')->logOrderCron(sprintf("Successfully updated subscription (%s) from quote (%s)", $subscription->getId(), $quote->getId()));
     } catch (Exception $e) {
         // 1. rollback everything
         $subscription->getResource()->rollBack();
         // 2. log the error to the debuglog
         Mage::helper('adyen_subscription')->logOrderCron(sprintf("Error while updating subscription (%s) from quote (%s) error is: %s", $subscription->getId(), $quote->getId(), $e->getMessage()));
         // 3. save the error on the subscription
         $subscription->setErrorMessage($e->getMessage());
         $subscription->setStatus($subscription::STATUS_SUBSCRIPTION_ERROR);
         $subscription->save();
         // 4. dispatch the failure event
         Mage::dispatchEvent('adyen_subscription_quote_updatesubscription_fail', array('subscription' => $subscription, 'quote' => $quote, 'status' => $subscription->getStatus(), 'error' => $e->getMessage()));
         throw $e;
     }
     Mage::dispatchEvent('adyen_subscription_quote_updatesubscription_after', array('subscription' => $subscription, 'quote' => $quote));
     return $subscription;
 }