/**
  * _apply_payment_to_registrations
  * @since 4.8
  * @param \EE_Registration[] $registrations
  */
 protected function _apply_payment_to_registrations($registrations)
 {
     //echo "\n\n " . __METHOD__ . "() \n";
     // reset reg_payment_REG_IDs
     $this->_admin_page->set_existing_reg_payment_REG_IDs();
     $available_payment = $this->_payment->amount();
     foreach ($registrations as $registration) {
         if ($registration instanceof EE_Registration) {
             if ($available_payment > 0) {
                 $owing = $registration->final_price() - $registration->paid();
                 if ($owing > 0) {
                     // don't allow payment amount to exceed the available payment amount, OR the amount owing
                     $payment_amount = min($available_payment, $owing);
                     // update $available_payment_amount
                     $available_payment = $available_payment - $payment_amount;
                     //calculate and set new REG_paid
                     $registration->set_paid($registration->paid() + $payment_amount);
                     //$registration->set_paid( $available_payment );
                     $registration->_add_relation_to($this->_payment, 'Payment', array('RPY_amount' => $this->_payment->amount()));
                     $registration->save();
                 }
             }
         }
     }
     /** @type EE_Payment $payment */
     $payment = EEM_Payment::instance()->get_one_by_ID($this->_payment->ID());
     $registration_payments = $payment->registration_payments();
     $this->assertNotEmpty($registration_payments);
 }
 /**
  * Message triggers for manual payment applied by admin
  * @param  bool     $success incoming success value
  * @param  EE_Payment $payment EE_payment object
  * @return bool              success/fail
  */
 public static function process_admin_payment($success = TRUE, EE_Payment $payment)
 {
     //we need to get the transaction object
     $transaction = $payment->transaction();
     if ($transaction instanceof EE_Transaction) {
         $data = array($transaction, $payment);
         $message_type = self::_get_payment_message_type($payment->STS_ID());
         //if payment amount is less than 0 then switch to payment_refund message type.
         $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type;
         //if payment_refund is selected, but the status is NOT accepted.  Then change message type to false so NO message notification goes out.
         $message_type = $message_type == 'payment_refund' && $payment->STS_ID() != EEM_Payment::status_id_approved ? false : $message_type;
         self::_load_controller();
         //verify this message type is present and active.  If it isn't then no message is sent.
         $active_mts = self::$_EEMSG->get_active_message_types();
         $message_type = in_array($message_type, $active_mts) ? $message_type : false;
         if ($message_type) {
             $success = self::$_EEMSG->send_message($message_type, $data);
             if (!$success) {
                 EE_Error::add_error(__('Something went wrong and the payment confirmation was NOT resent', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
             }
         } else {
             EE_Error::add_error(__('The message type for the status of this payment is not active or does not exist, so no notification was sent.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
         }
     }
     return $success;
 }
 /**
  * update registrations REG_paid field after successful payment and link registrations with payment
  *
  * @param EE_Transaction $transaction
  * @param EE_Payment $payment
  * @param EE_Registration[] $registrations
  * @throws \EE_Error
  */
 public function process_registration_payments(EE_Transaction $transaction, EE_Payment $payment, $registrations = array())
 {
     // only process if payment was successful
     if ($payment->status() !== EEM_Payment::status_id_approved) {
         return;
     }
     //EEM_Registration::instance()->show_next_x_db_queries();
     if (empty($registrations)) {
         // find registrations with monies owing that can receive a payment
         $registrations = $transaction->registrations(array(array('STS_ID' => array('IN', EEM_Registration::reg_statuses_that_allow_payment()), 'REG_final_price' => array('!=', 0), 'REG_final_price*' => array('!=', 'REG_paid', true))));
     }
     // still nothing ??!??
     if (empty($registrations)) {
         return;
     }
     // todo: break out the following logic into a separate strategy class
     // todo: named something like "Sequential_Reg_Payment_Strategy"
     // todo: which would apply payments using the capitalist "first come first paid" approach
     // todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
     // todo: which would be the socialist "everybody gets a piece of pie" approach,
     // todo: which would be better for deposits, where you want a bit of the payment applied to each registration
     $refund = $payment->is_a_refund();
     // how much is available to apply to registrations?
     $available_payment_amount = abs($payment->amount());
     foreach ($registrations as $registration) {
         if ($registration instanceof EE_Registration) {
             // nothing left?
             if ($available_payment_amount <= 0) {
                 break;
             }
             if ($refund) {
                 $available_payment_amount = $this->process_registration_refund($registration, $payment, $available_payment_amount);
             } else {
                 $available_payment_amount = $this->process_registration_payment($registration, $payment, $available_payment_amount);
             }
         }
     }
     if ($available_payment_amount > 0 && apply_filters('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', false)) {
         EE_Error::add_attention(sprintf(__('A remainder of %1$s exists after applying this payment to Registration(s) %2$s.%3$sPlease verify that the original payment amount of %4$s is correct. If so, you should edit this payment and select at least one additional registration in the "Registrations to Apply Payment to" section, so that the remainder of this payment can be applied to the additional registration(s).', 'event_espresso'), EEH_Template::format_currency($available_payment_amount), implode(', ', array_keys($registrations)), '<br/>', EEH_Template::format_currency($payment->amount())), __FILE__, __FUNCTION__, __LINE__);
     }
 }
    /**
     * 	get_payment_row_html
     *
     *  @access 	public
     *  @param 	EE_Payment	$payment
     *  @return 	string
     */
    public function get_payment_row_html($payment = NULL)
    {
        $html = '';
        if ($payment instanceof EE_Payment) {
            if ($payment->payment_method() instanceof EE_Payment_Method && $payment->payment_method()->is_off_site() && $payment->status() === EEM_Payment::status_id_failed) {
                // considering the registrant has made it to the Thank You page,
                // any failed payments may actually be pending and the IPN is just slow
                // so let's
                $payment->set_status(EEM_Payment::status_id_pending);
            }
            $payment_declined_msg = $payment->STS_ID() === EEM_Payment::status_id_declined ? '<br /><span class="small-text">' . $payment->gateway_response() . '</span>' : '';
            $html .= '
				<tr>
					<td>
						' . $payment->timestamp() . '
					</td>
					<td>
						' . ($payment->payment_method() instanceof EE_Payment_Method ? $payment->payment_method()->name() : __('Unknown', 'event_espresso')) . '
					</td>
					<td class="jst-rght">
						' . EEH_Template::format_currency($payment->amount()) . '
					</td>
					<td class="jst-rght" style="line-height:1;">
						' . $payment->pretty_status(TRUE) . $payment_declined_msg . '
					</td>
				</tr>';
            do_action('AHEE__thank_you_page_payment_details_template__after_each_payment', $payment);
        }
        return $html;
    }
 /**
  * Message triggers for manual payment applied by admin
  * @param  bool     $success incoming success value
  * @param  EE_Payment $payment EE_payment object
  * @return bool              success/fail
  */
 public function process_admin_payment($success, EE_Payment $payment)
 {
     $success = TRUE;
     //we need to get the transaction object
     $transaction = $payment->transaction();
     $data = array($transaction, $payment);
     $message_type_name = $payment->amount() < 0 ? 'payment_refund' : 'payment';
     $this->_load_controller();
     $success = $this->_EEMSG->send_message($message_type_name, $data);
     if (!$success) {
         EE_Error::add_error(__('Something went wrong and the payment confirmation was NOT resent', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
     }
     return $success;
 }
    /**
     * 	get_payment_row_html
     *
     *  @access 	public
     *  @param 	EE_Payment	$payment
     *  @return 	string
     */
    public function get_payment_row_html($payment = NULL)
    {
        $html = '';
        if ($payment instanceof EE_Payment) {
            $payment_declined_msg = $payment->STS_ID() === EEM_Payment::status_id_declined ? '<br /><span class="small-text">' . $payment->gateway_response() . '</span>' : '';
            $html .= '
				<tr>
					<td>
						' . $payment->timestamp() . '
					</td>
					<td>
						' . str_replace('_', ' ', $payment->gateway()) . '
					</td>
					<td class="jst-rght">
						' . EEH_Template::format_currency($payment->amount()) . '
					</td>
					<td class="jst-rght" style="line-height:1;">
						' . $payment->pretty_status(TRUE) . $payment_declined_msg . '
					</td>
				</tr>';
            do_action('AHEE__thank_you_page_payment_details_template__after_each_payment', $payment);
        }
        return $html;
    }
 /**
  * _build_payment_json_response
  *
  * @access public
  * @param \EE_Payment $payment
  * @param array       $REG_IDs
  * @param bool | null        $delete_txn_reg_status_change
  * @return array
  */
 protected function _build_payment_json_response(EE_Payment $payment, $REG_IDs = array(), $delete_txn_reg_status_change = null)
 {
     // was the payment deleted ?
     if (is_bool($delete_txn_reg_status_change)) {
         return array('PAY_ID' => $payment->ID(), 'amount' => $payment->amount(), 'total_paid' => $payment->transaction()->paid(), 'txn_status' => $payment->transaction()->status_ID(), 'pay_status' => $payment->STS_ID(), 'registrations' => $this->_registration_payment_data_array($REG_IDs), 'delete_txn_reg_status_change' => $delete_txn_reg_status_change);
     } else {
         $this->_get_payment_status_array();
         return array('amount' => $payment->amount(), 'total_paid' => $payment->transaction()->paid(), 'txn_status' => $payment->transaction()->status_ID(), 'pay_status' => $payment->STS_ID(), 'PAY_ID' => $payment->ID(), 'STS_ID' => $payment->STS_ID(), 'status' => self::$_pay_status[$payment->STS_ID()], 'date' => $payment->timestamp('Y-m-d', 'h:i a'), 'method' => strtoupper($payment->source()), 'PM_ID' => $payment->payment_method() ? $payment->payment_method()->ID() : 1, 'gateway' => $payment->payment_method() ? $payment->payment_method()->admin_name() : __("Unknown", 'event_espresso'), 'gateway_response' => $payment->gateway_response(), 'txn_id_chq_nmbr' => $payment->txn_id_chq_nmbr(), 'po_number' => $payment->po_number(), 'extra_accntng' => $payment->extra_accntng(), 'registrations' => $this->_registration_payment_data_array($REG_IDs));
     }
 }
 /**
  * update registrations REG_paid field after successful payment and link registrations with payment
  *
  * @param EE_Transaction $transaction
  * @param EE_Payment $payment
  * @param EE_Registration[] $registrations
  * @throws \EE_Error
  */
 public function process_registration_payments(EE_Transaction $transaction, EE_Payment $payment, $registrations = array())
 {
     // only process if payment was successful
     if ($payment->status() !== EEM_Payment::status_id_approved) {
         return;
     }
     //EEM_Registration::instance()->show_next_x_db_queries();
     if (empty($registrations)) {
         // find registrations with monies owing that can receive a payment
         $registrations = $transaction->registrations(array(array('STS_ID' => array('IN', EEM_Registration::reg_statuses_that_allow_payment()), 'REG_final_price' => array('!=', 0), 'REG_final_price*' => array('!=', 'REG_paid', true))));
     }
     // still nothing ??!??
     if (empty($registrations)) {
         return;
     }
     // todo: break out the following logic into a separate strategy class
     // todo: named something like "Sequential_Reg_Payment_Strategy"
     // todo: which would apply payments using the capitalist "first come first paid" approach
     // todo: then have another strategy class like "Distributed_Reg_Payment_Strategy"
     // todo: which would be the socialist "everybody gets a piece of pie" approach,
     // todo: which would be better for deposits, where you want a bit of the payment applied to each registration
     $refund = $payment->is_a_refund();
     // how much is available to apply to registrations?
     $available_payment_amount = abs($payment->amount());
     //EEH_Debug_Tools::printr( $available_payment_amount, '$available_payment_amount', __FILE__, __LINE__ );
     foreach ($registrations as $registration) {
         if ($registration instanceof EE_Registration) {
             // nothing left?
             if ($available_payment_amount <= 0) {
                 break;
             }
             if ($refund) {
                 $available_payment_amount = $this->process_registration_refund($registration, $payment, $available_payment_amount);
             } else {
                 $available_payment_amount = $this->process_registration_payment($registration, $payment, $available_payment_amount);
             }
         }
     }
 }
 /**
  * Message triggers for manual payment applied by admin
  * @param  EE_Payment $payment EE_payment object
  * @return bool              success/fail
  */
 public static function process_admin_payment(EE_Payment $payment)
 {
     EE_Registry::instance()->load_helper('MSG_Template');
     //we need to get the transaction object
     $transaction = $payment->transaction();
     if ($transaction instanceof EE_Transaction) {
         $data = array($transaction, $payment);
         $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID());
         //if payment amount is less than 0 then switch to payment_refund message type.
         $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type;
         //if payment_refund is selected, but the status is NOT accepted.  Then change message type to false so NO message notification goes out.
         $message_type = $message_type == 'payment_refund' && $payment->STS_ID() != EEM_Payment::status_id_approved ? false : $message_type;
         self::_load_controller();
         self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data);
         //get count of queued for generation
         $count_to_generate = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(array(EEM_Message::status_incomplete, EEM_Message::status_idle));
         if ($count_to_generate > 0 && self::$_MSG_PROCESSOR->get_queue()->get_message_repository()->count() !== 0) {
             add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true');
             return true;
         } else {
             $count_failed = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::instance()->stati_indicating_failed_sending());
             /**
              * Verify that there are actually errors.  If not then we return a success message because the queue might have been emptied due to successful
              * IMMEDIATE generation.
              */
             if ($count_failed > 0) {
                 EE_Error::add_error(sprintf(_n('The payment notification generation failed.', '%d payment notifications failed being sent.', $count_failed, 'event_espresso'), $count_failed), __FILE__, __FUNCTION__, __LINE__);
                 return false;
             } else {
                 add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true');
                 return true;
             }
         }
     } else {
         EE_Error::add_error('Unable to generate the payment notification because the given value for the transaction is invalid.', 'event_espresso');
         return false;
     }
 }