_action = CRM_Core_Action::UPDATE; parent::preProcess(); $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this); $this->assign('id', $this->_id); $this->_contributionID = CRM_Utils_Request::retrieve('contribution_id', 'Positive', $this); $this->_values = civicrm_api3('FinancialTrxn', 'getsingle', array('id' => $this->_id)); if (!empty($this->_values['payment_processor_id'])) { CRM_Core_Error::statusBounce(ts('You cannot update this payment')); } } /** * Set default values. * * @return array */ public function setDefaultValues() { return $this->_values; } /** * Build quickForm. */ public function buildQuickForm() { CRM_Utils_System::setTitle(ts('Update Payment details')); $paymentFields = $this->getPaymentFields(); $this->assign('paymentFields', $paymentFields); foreach ($paymentFields as $name => $paymentField) { if (!empty($paymentField['add_field'])) { $attributes = array( 'entity' => 'FinancialTrxn', 'name' => $name, ); $this->addField($name, $attributes, $paymentField['is_required']); } else { $this->add($paymentField['htmlType'], $name, $paymentField['title'], $paymentField['attributes'], $paymentField['is_required'] ); } } $this->assign('currency', CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_Currency', $this->_values['currency'], 'symbol', 'name')); $this->addFormRule(array(__CLASS__, 'formRule'), $this); $this->addButtons(array( array( 'type' => 'submit', 'name' => ts('Update'), 'isDefault' => TRUE, ), array( 'type' => 'cancel', 'name' => ts('Cancel'), ), )); } /** * Global form rule. * * @param array $fields * The input form values. * @param array $files * The uploaded files if any. * @param $self * * @return bool|array * true if no errors, else array of errors */ public static function formRule($fields, $files, $self) { $errors = array(); // if Credit Card is chosen and pan_truncation is not NULL ensure that it's value is numeric else throw validation error if (CRM_Core_PseudoConstant::getName('CRM_Financial_DAO_FinancialTrxn', 'payment_instrument_id', $fields['payment_instrument_id']) == 'Credit Card' && !empty($fields['pan_truncation']) && !CRM_Utils_Rule::numeric($fields['pan_truncation']) ) { $errors['pan_truncation'] = ts('Please enter a valid Card Number'); } return $errors; } /** * Process the form submission. */ public function postProcess() { $params = array( 'id' => $this->_id, 'payment_instrument_id' => $this->_submitValues['payment_instrument_id'], 'trxn_id' => CRM_Utils_Array::value('trxn_id', $this->_submitValues), 'trxn_date' => CRM_Utils_Array::value('trxn_date', $this->_submitValues, date('YmdHis')), ); $paymentInstrumentName = CRM_Core_PseudoConstant::getName('CRM_Financial_DAO_FinancialTrxn', 'payment_instrument_id', $params['payment_instrument_id']); if ($paymentInstrumentName == 'Credit Card') { $params['card_type_id'] = CRM_Utils_Array::value('card_type_id', $this->_submitValues); $params['pan_truncation'] = CRM_Utils_Array::value('pan_truncation', $this->_submitValues); } elseif ($paymentInstrumentName == 'Check') { $params['check_number'] = CRM_Utils_Array::value('check_number', $this->_submitValues); } $this->submit($params); CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url(CRM_Utils_System::currentPath())); } /** * Wrapper function to process form submission * * @param array $submittedValues * */ protected function submit($submittedValues) { // if payment instrument is changed then // 1. Record a new reverse financial transaction with old payment instrument // 2. Record a new financial transaction with new payment instrument // 3. Add EntityFinancialTrxn records to relate with corresponding financial item and contribution if ($submittedValues['payment_instrument_id'] != $this->_values['payment_instrument_id']) { $previousFinanciaTrxn = $this->_values; $newFinancialTrxn = $submittedValues; unset($previousFinanciaTrxn['id'], $newFinancialTrxn['id']); $previousFinanciaTrxn['trxn_date'] = CRM_Utils_Array::value('trxn_date', $submittedValues, date('YmdHis')); $previousFinanciaTrxn['total_amount'] = -$previousFinanciaTrxn['total_amount']; $previousFinanciaTrxn['net_amount'] = -$previousFinanciaTrxn['net_amount']; $previousFinanciaTrxn['fee_amount'] = -$previousFinanciaTrxn['fee_amount']; $previousFinanciaTrxn['contribution_id'] = $newFinancialTrxn['contribution_id'] = $this->_contributionID; $newFinancialTrxn['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount($submittedValues['payment_instrument_id']); foreach (array('total_amount', 'fee_amount', 'net_amount', 'currency', 'is_payment', 'status_id') as $fieldName) { $newFinancialTrxn[$fieldName] = $this->_values[$fieldName]; } foreach (array($previousFinanciaTrxn, $newFinancialTrxn) as $financialTrxnParams) { civicrm_api3('FinancialTrxn', 'create', $financialTrxnParams); $trxnParams = array( 'total_amount' => $financialTrxnParams['total_amount'], 'contribution_id' => $this->_contributionID, ); $contributionTotalAmount = CRM_Core_DAO::getFieldValue('CRM_Contribute_BAO_Contribution', $this->_contributionID, 'total_amount'); CRM_Contribute_BAO_Contribution::assignProportionalLineItems($trxnParams, $submittedValues['id'], $contributionTotalAmount); } } else { // simply update the financial trxn civicrm_api3('FinancialTrxn', 'create', $submittedValues); } self::updateRelatedContribution($submittedValues, $this->_contributionID); } /** * Wrapper for unit testing the post process submit function. * * @param array $params */ public function testSubmit($params) { $this->_id = $params['id']; $this->_contributionID = $params['contribution_id']; $this->_values = civicrm_api3('FinancialTrxn', 'getsingle', array('id' => $params['id'])); $this->submit($params); } /** * Function to update contribution's check_number and trxn_id by * concatenating values from financial trxn's check_number and trxn_id respectively * * @param array $params * @param int $contributionID */ public static function updateRelatedContribution($params, $contributionID) { $contributionDAO = new CRM_Contribute_DAO_Contribution(); $contributionDAO->id = $contributionID; $contributionDAO->find(TRUE); foreach (array('trxn_id', 'check_number') as $fieldName) { if (!empty($params[$fieldName])) { if (!empty($contributionDAO->$fieldName)) { $values = explode(',', $contributionDAO->$fieldName); // if submitted check_number or trxn_id value is // already present then ignore else add to $values array if (!in_array($params[$fieldName], $values)) { $values[] = $params[$fieldName]; } $contributionDAO->$fieldName = implode(',', $values); } } } $contributionDAO->save(); } /** * Get payment fields */ public function getPaymentFields() { $paymentFields = array( 'payment_instrument_id' => array( 'is_required' => TRUE, 'add_field' => TRUE, ), 'check_number' => array( 'is_required' => FALSE, 'add_field' => TRUE, ), // @TODO we need to show card type icon in place of select field 'card_type_id' => array( 'is_required' => FALSE, 'add_field' => TRUE, ), 'pan_truncation' => array( 'is_required' => FALSE, 'add_field' => TRUE, ), 'trxn_id' => array( 'add_field' => TRUE, 'is_required' => FALSE, ), 'trxn_date' => array( 'htmlType' => 'datepicker', 'name' => 'trxn_date', 'title' => ts('Transaction Date'), 'is_required' => TRUE, 'attributes' => array( 'date' => 'yyyy-mm-dd', 'time' => 24, ), ), 'total_amount' => array( 'htmlType' => 'text', 'name' => 'total_amount', 'title' => ts('Total Amount'), 'is_required' => TRUE, 'attributes' => array( 'readonly' => TRUE, 'size' => 6, ), ), ); return $paymentFields; } }