function repeatAction()
 {
     if (!$this->invoice) {
         throw new Am_Exception_InputError('No invoice found, cannot repeat');
     }
     if ($this->invoice->isPaid()) {
         throw new Am_Exception_InputError("Invoice #{$id} is already paid");
     }
     $found = false;
     foreach ($this->view->paysystems as $ps) {
         if ($ps['paysys_id'] == $this->getFiltered('paysys_id')) {
             $found = true;
             break;
         }
     }
     if (!$found) {
         return $this->indexAction();
     }
     $this->invoice->updateQuick('paysys_id', $this->getFiltered('paysys_id'));
     if ($err = $this->invoice->validate()) {
         throw new Am_Exception_InputError($err[0]);
     }
     $payProcess = new Am_Paysystem_PayProcessMediator($this, $this->invoice);
     $result = $payProcess->process();
     if ($result->isFailure()) {
         $this->view->error = $result->getErrorMessages();
         return $this->indexAction();
     }
 }
Exemple #2
0
 public function prorateInvoice(Invoice $invoice, EcheckRecord $echeck, Am_Paysystem_Result $result, $date)
 {
     /** @todo use "reattempt" config **/
     $reattempt = array_filter($this->getConfig('reattempt', array()));
     sort($reattempt);
     if (!$reattempt) {
         $invoice->updateQuick('status', Invoice::RECURRING_FAILED);
         $invoice->updateQuick('rebill_date', null);
         return;
     }
     $first_failure = $invoice->data()->get(self::FIRST_REBILL_FAILURE);
     if (!$first_failure) {
         $invoice->data()->set(self::FIRST_REBILL_FAILURE, $date)->update();
         $first_failure = $date;
     }
     $days_diff = (strtotime($date) - strtotime($first_failure)) / (24 * 3600);
     foreach ($reattempt as $day) {
         if ($day > $days_diff) {
             break;
         }
     }
     // we have found next rebill date to jump
     if ($day <= $days_diff) {
         // Several rebilling attempts failed already.
         // change status to RECURRING_FAILED;
         $invoice->updateQuick('status', Invoice::RECURRING_FAILED);
         $invoice->updateQuick('rebill_date', null);
         return;
     }
     $invoice->updateQuick('rebill_date', date('Y-m-d', strtotime($first_failure . " +{$day} days")));
     $tr = new Am_Paysystem_Transaction_Manual($this);
     if ($invoice->getAccessExpire() < $invoice->rebill_date) {
         $invoice->extendAccessPeriod($invoice->rebill_date);
     }
 }
 /**
  * Process invoice and insert necessary commissions for it
  *
  * External code should guarantee that this method with $payment = null will be called
  * only once for each user for First user invoice
  */
 public function processPayment(Invoice $invoice, InvoicePayment $payment = null)
 {
     $aff_id = $invoice->aff_id;
     /* @var $coupon Coupon */
     try {
         if (!$aff_id && ($coupon = $invoice->getCoupon())) {
             // try to find affiliate by coupon
             $aff_id = $coupon->aff_id ? $coupon->aff_id : $coupon->getBatch()->aff_id;
         }
     } catch (Am_Exception_Db_NotFound $e) {
         //coupon not found
     }
     if (empty($aff_id)) {
         $aff_id = $invoice->getUser()->aff_id;
     }
     if ($aff_id && empty($invoice->aff_id)) {
         // set aff_id to invoice for quick access next time
         $invoice->updateQuick('aff_id', $aff_id);
     }
     // run event to get plugins chance choose another affiliate
     $event = new Am_Event(Bootstrap_Aff::AFF_FIND_AFFILIATE, array('invoice' => $invoice, 'payment' => $payment));
     $event->setReturn($aff_id);
     $this->getDi()->hook->call($event);
     $aff_id = $event->getReturn();
     if (empty($aff_id)) {
         return;
     }
     // no affiliate id registered
     if ($aff_id == $invoice->getUser()->pk()) {
         return;
     }
     //strange situation
     // load affiliate and continue
     $aff = $this->getDi()->userTable->load($aff_id, false);
     if (!$aff || !$aff->is_affiliate) {
         return;
     }
     // affiliate not found
     $user = $invoice->getUser();
     if (!$user->aff_id) {
         $user->aff_id = $aff->pk();
         $user->aff_added = sqlTime('now');
         $user->data()->set('aff-source', 'invoice-' . $invoice->pk());
         $user->save();
     }
     // try to load other tier affiliate
     $aff_tier = $aff;
     $aff_tiers = array();
     $aff_tiers_exists = array($aff->pk());
     for ($tier = 1; $tier <= $this->getMaxTier(); $tier++) {
         if (!$aff_tier->aff_id || $aff_tier->pk() == $invoice->getUser()->pk()) {
             break;
         }
         $aff_tier = $this->getDi()->userTable->load($aff_tier->aff_id, false);
         if (!$aff_tier || !$aff_tier->is_affiliate || $aff_tier->pk() == $invoice->getUser()->pk() || in_array($aff_tier->pk(), $aff_tiers_exists)) {
             //already in chain
             break;
         }
         $aff_tiers[$tier] = $aff_tier;
         $aff_tiers_exists[] = $aff_tier->pk();
     }
     $isFirst = !$payment || $payment->isFirst();
     //to define price field
     $paymentNumber = is_null($payment) ? 0 : $invoice->getPaymentsCount();
     if (!$payment) {
         $tax = 0;
     } else {
         $tax = $this->getDi()->config->get('aff.commission_include_tax', false) ? 0 : doubleval($payment->tax);
     }
     $amount = $payment ? $payment->amount - $tax : 0;
     $date = $payment ? $payment->dattm : 'now';
     // now calculate commissions
     $items = is_null($payment) ? array_slice($invoice->getItems(), 0, 1) : $invoice->getItems();
     foreach ($items as $item) {
         //we do not calculate commission for free items in invoice
         $prefix = $isFirst ? 'first' : 'second';
         if (!is_null($payment) && !(double) $item->get("{$prefix}_total")) {
             continue;
         }
         $comm = $this->getDi()->affCommissionRecord;
         $comm->date = sqlDate($date);
         $comm->record_type = AffCommission::COMMISSION;
         $comm->invoice_id = $invoice->invoice_id;
         $comm->invoice_item_id = $item->invoice_item_id;
         $comm->invoice_payment_id = $payment ? $payment->pk() : null;
         $comm->receipt_id = $payment ? $payment->receipt_id : null;
         $comm->product_id = $item->item_id;
         $comm->is_first = $paymentNumber <= 1;
         $comm->_setPayment($payment);
         $comm->_setInvoice($invoice);
         $comm_tier = clone $comm;
         $rules = array();
         $topay_this = $topay = $this->calculate($invoice, $item, $aff, $paymentNumber, 0, $amount, $date, $rules);
         if ($topay > 0) {
             $comm->aff_id = $aff->pk();
             $comm->amount = $topay;
             $comm->tier = 0;
             $comm->_setAff($aff);
             $comm->insert();
             $comm->setCommissionRules(array_map(create_function('$el', 'return $el->pk();'), $rules));
         }
         foreach ($aff_tiers as $tier => $aff_tier) {
             $rules = array();
             $topay_this = $this->calculate($invoice, $item, $aff_tier, $paymentNumber, $tier, $topay_this, $date, $rules);
             if ($topay_this > 0) {
                 $comm_this = clone $comm_tier;
                 $comm_this->aff_id = $aff_tier->pk();
                 $comm_this->amount = $topay_this;
                 $comm_this->tier = $tier;
                 $comm_this->_setAff($aff_tier);
                 $comm_this->insert();
                 $comm_this->setCommissionRules(array_map(create_function('$el', 'return $el->pk();'), $rules));
             }
         }
     }
 }
 public function prorateInvoice(Invoice $invoice, CcRecord $cc, Am_Paysystem_Result $result, $date)
 {
     /** @todo use "reattempt" config **/
     $reattempt = array_filter($this->getConfig('reattempt'));
     sort($reattempt);
     if (!$reattempt) {
         return;
     }
     $first_failure = $invoice->data()->get(self::FIRST_REBILL_FAILURE);
     if (!$first_failure) {
         $invoice->data()->set(self::FIRST_REBILL_FAILURE, $date)->update();
         $first_failure = $date;
     }
     $days_diff = (strtotime($date) - strtotime($first_failure)) / (24 * 3600);
     foreach ($reattempt as $day) {
         if ($day > $days_diff) {
             break;
         }
     }
     // we have found next rebill date to jump
     if (!$day) {
         return;
     }
     $invoice->updateQuick('rebill_date', date('Y-m-d', strtotime($first_failure) + $day * 24 * 3600));
     $tr = new Am_Paysystem_Transaction_Manual($this);
     if ($invoice->getAccessExpire() < $invoice->rebill_date) {
         $invoice->extendAccessPeriod($invoice->rebill_date);
     }
 }