/**
  * Get product final price
  * Extended to return subscription price when product is a subscription product
  * When configured that catalog prices are including tax and subscription pricee excluding tax,
  * the subscription item prices of new orders change when tax percentage is changed
  *
  * @param float|null $qty
  * @param Mage_Catalog_Model_Product $product
  * @return float
  */
 public function getFinalPrice($qty = null, $product)
 {
     if ($subscriptionItem = $this->_helper()->getSubscriptionItem($product)) {
         $subscription = $subscriptionItem->getSubscription();
         // @todo Performance
         $store = $product->getStore();
         $configCatalogInclTax = Mage::getModel('tax/config')->priceIncludesTax($store);
         $useSubscriptionPricesIncTax = Mage::helper('adyen_subscription/config')->getPriceIncludesTax($store);
         if ($configCatalogInclTax && $useSubscriptionPricesIncTax) {
             return $subscriptionItem->getPriceInclTax();
         }
         if (!$configCatalogInclTax && !$useSubscriptionPricesIncTax) {
             return $subscriptionItem->getPrice();
         }
         if ($configCatalogInclTax && !$useSubscriptionPricesIncTax) {
             $priceExclTax = $subscriptionItem->getPrice();
             $customerPercent = Mage::helper('adyen_subscription/quote')->getCustomerTaxPercent($subscription, $product);
             $customerTax = Mage::getSingleton('tax/calculation')->calcTaxAmount($priceExclTax, $customerPercent, false, false);
             $customerPriceInclTax = $store->roundPrice($priceExclTax + $customerTax);
             return $customerPriceInclTax;
         }
         if (!$configCatalogInclTax && $useSubscriptionPricesIncTax) {
             $message = 'Please fix the tax settings;' . ' it\'s not possible to set catalog prices to excl. tax and subscription prices to incl. tax';
             Adyen_Subscription_Exception::throwException($message);
         }
     }
     if ($subscription = $this->_helper()->getProductSubscription($product)) {
         $basePrice = $subscription->getPrice();
         $finalPrice = $basePrice;
         $finalPrice += $this->getTotalConfigurableItemsPrice($product, $finalPrice);
         $finalPrice += $this->_applyOptionsPrice($product, $qty, $basePrice) - $basePrice;
         return $finalPrice;
     }
     return parent::getFinalPrice($qty, $product);
 }
 public function setBillingAgreement(Mage_Sales_Model_Billing_Agreement $billingAgreement, $validate = false)
 {
     if ($validate) {
         $billingAgreement->isValid();
         $billingAgreement->verifyToken();
         if ($billingAgreement->getStatus() !== $billingAgreement::STATUS_ACTIVE) {
             Adyen_Subscription_Exception::throwException(Mage::helper('adyen_subscription')->__('Billing Agreement %s not active', $billingAgreement->getReferenceId()));
         }
     }
     $this->setBillingAgreementId($billingAgreement->getId());
     $this->setData('_billing_agreement', $billingAgreement);
     return $this;
 }
 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()));
     }
 }
 /**
  * @cron adyen_subscription_create_orders
  * @return string
  */
 public function createOrders()
 {
     Mage::helper('adyen_subscription')->logOrderCron("Start order cronjob");
     $subscriptionCollection = Mage::getResourceModel('adyen_subscription/subscription_collection');
     $subscriptionCollection->addPlaceOrderFilter();
     if ($subscriptionCollection->count() <= 0) {
         Mage::helper('adyen_subscription')->logOrderCron("There are no subscriptions that have quotes and a schedule date in the past");
         return '';
     }
     $successCount = 0;
     $failureCount = 0;
     $skippedCount = 0;
     foreach ($subscriptionCollection as $subscription) {
         /** @var Adyen_Subscription_Model_Subscription $subscription */
         // If the subscription has an error status check in config if it should be retried
         $retryOnError = Mage::getStoreConfigFlag('adyen_subscription/subscription/retry_on_error');
         if (in_array($subscription->getStatus(), [Adyen_Subscription_Model_Subscription::STATUS_QUOTE_ERROR, Adyen_Subscription_Model_Subscription::STATUS_ORDER_ERROR, Adyen_Subscription_Model_Subscription::STATUS_SUBSCRIPTION_ERROR]) && !$retryOnError) {
             continue;
         }
         if ($subscription->getStatus() == Adyen_Subscription_Model_Subscription::STATUS_PAYMENT_ERROR) {
             $retryFailedPayment = Mage::getStoreConfigFlag('adyen_subscription/subscription/retry_failed_payment');
             // If setting 'retry payment failed' is off do not try to create order again
             if (!$retryFailedPayment) {
                 Mage::helper('adyen_subscription')->logOrderCron(sprintf("Subscription (#%s) is in status " . Adyen_Subscription_Model_Subscription::STATUS_PAYMENT_ERROR . " so do not create order from quote because setting 'Retry failed payment' is set to no", $subscription->getId()));
                 $skippedCount++;
                 continue;
             }
             // setting that indicates how many times a failed payment is allowed to try again
             $numberOfFailedPaymentsAllowed = Mage::getStoreConfig('adyen_subscription/subscription/number_retry_failed_payment');
             // setting that indicates what the time
             $timeBetweenPaymentFailed = Mage::getStoreConfig('adyen_subscription/subscription/time_between_retry_failed_payment');
             if ($numberOfFailedPaymentsAllowed != "" || $timeBetweenPaymentFailed != "") {
                 // get history of payment errors
                 $subscriptionHistoryCollection = Mage::getResourceModel('adyen_subscription/subscription_history_collection');
                 $subscriptionHistoryCollection->getPaymentHistoryErrors($subscription);
                 // check how many times the payment is failed. And check if this is less then the chosen failed payments allowed settting
                 if ($numberOfFailedPaymentsAllowed != "") {
                     $numberOfPaymentErrors = $subscriptionHistoryCollection->getSize();
                     if ($numberOfPaymentErrors > $numberOfFailedPaymentsAllowed) {
                         Mage::helper('adyen_subscription')->logOrderCron(sprintf("Subscription (#%s) is in status " . Adyen_Subscription_Model_Subscription::STATUS_PAYMENT_ERROR . " you have configured to do not execute this if this happened more then %s times this is the %s time.", $subscription->getId(), $numberOfFailedPaymentsAllowed, $numberOfPaymentErrors));
                         $skippedCount++;
                         continue;
                     }
                 }
                 if ($timeBetweenPaymentFailed != "") {
                     $now = new DateTime('now');
                     // -2 hours
                     $lastPaymentErrorDate = $subscriptionHistoryCollection->getLastItem()->getDate();
                     // -2 hours
                     $nextTry = new DateTime($lastPaymentErrorDate);
                     $nextTry->add(new DateInterval('PT' . $timeBetweenPaymentFailed . 'H'));
                     if ($now < $nextTry) {
                         // do not update
                         Mage::helper('adyen_subscription')->logOrderCron(sprintf("Subscription (#%s) is in status " . Adyen_Subscription_Model_Subscription::STATUS_PAYMENT_ERROR . " you have configured that the next time is %s hours after last payment error this is not yet the case. Next try will be at %s", $subscription->getId(), $timeBetweenPaymentFailed, $nextTry->format('Y-m-d H:i:s')));
                         $skippedCount++;
                         continue;
                     }
                 }
             }
         }
         try {
             $quote = $subscription->getActiveQuote();
             if (!$quote) {
                 Adyen_Subscription_Exception::throwException('Can\'t create order: No quote created yet.');
             }
             Mage::getSingleton('adyen_subscription/service_quote')->createOrder($subscription->getActiveQuote(), $subscription);
             $successCount++;
         } catch (Exception $e) {
             Mage::helper('adyen_subscription')->logOrderCron($e->getMessage());
             Adyen_Subscription_Exception::logException($e);
             $failureCount++;
         }
     }
     $result = Mage::helper('adyen_subscription')->__('Quotes created, %s successful, %s failed, %s skipped', $successCount, $failureCount, $skippedCount);
     Mage::helper('adyen_subscription')->logOrderCron($result);
     return $result;
 }
 /**
  * @param Mage_Sales_Model_Quote $quote
  * @return Adyen_Payment_Model_Billing_Agreement
  */
 public function getBillingAgreement(Mage_Sales_Model_Quote $quote)
 {
     $billingAgreement = $quote->getPayment()->getMethodInstance()->getBillingAgreement();
     if (!$billingAgreement) {
         Adyen_Subscription_Exception::throwException('Could not find billing agreement for quote ' . $quote->getId());
     }
     Mage::dispatchEvent('adyen_subscription_quote_getbillingagreement', array('billingAgreement' => $billingAgreement, 'quote' => $quote));
     return $billingAgreement;
 }
 /**
  * @param Mage_Sales_Model_Order $order
  * @return Mage_Sales_Model_Billing_Agreement
  */
 protected function _getBillingAgreement(Mage_Sales_Model_Order $order)
 {
     /** @var Mage_Core_Model_Resource $resource */
     $resource = Mage::getSingleton('core/resource');
     $connection = $resource->getConnection('core_read');
     $select = $connection->select();
     $select->from($resource->getTableName('sales/billing_agreement_order'));
     $select->reset(Zend_Db_Select::COLUMNS);
     $select->columns('agreement_id');
     $select->where('order_id = ?', $order->getId());
     $billingAgreementId = $connection->fetchOne($select);
     if (!$billingAgreementId) {
         Adyen_Subscription_Exception::logException(new Adyen_Subscription_Exception('Could not find billing agreement for order ' . $order->getIncrementId()));
         return false;
     }
     $billingAgreement = Mage::getModel('sales/billing_agreement')->load($billingAgreementId);
     Mage::dispatchEvent('adyen_subscription_order_getbillingagreement', array('billingAgreement' => $billingAgreement, 'order' => $order));
     return $billingAgreement;
 }
 public function editQuoteAction()
 {
     $subscriptionId = $this->getRequest()->getParam('id');
     $subscription = Mage::getModel('adyen_subscription/subscription')->load($subscriptionId);
     if (!$subscription->getId()) {
         Adyen_Subscription_Exception::throwException('Can\'t create order: No quote created yet.');
         $this->_redirectReferer();
     }
     $this->_editSubscription($subscription);
 }
 /**
  * @param Mage_Sales_Model_Order $order
  * @return Mage_Sales_Model_Billing_Agreement
  */
 protected function _getBillingAgreementId(Mage_Sales_Model_Order $order)
 {
     /** @var Mage_Core_Model_Resource $resource */
     $resource = Mage::getSingleton('core/resource');
     $connection = $resource->getConnection('core_read');
     $select = $connection->select();
     $select->from($resource->getTableName('sales/billing_agreement_order'));
     $select->reset(Zend_Db_Select::COLUMNS);
     $select->columns('agreement_id');
     $select->where('order_id = ?', $order->getId());
     $select->order(array('agreement_id DESC'));
     // important to get last agreement_id
     $billingAgreementId = $connection->fetchOne($select);
     if (!$billingAgreementId) {
         Adyen_Subscription_Exception::logException(new Adyen_Subscription_Exception('Could not find billing agreement for order ' . $order->getIncrementId()));
         return null;
     }
     return $billingAgreementId;
 }