X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FFinancial%2FForm%2FPaymentEdit.php;h=84f0a0d0de57d823e1efd8d70f549784a589c257;hb=bc17b73e442ebbec13b08acb7093f03a66495b96;hp=64cbf3129435d02a7886ef5977f94cdcc13058a2;hpb=8cb78ba15e7fb7addb4f9326531431786ac065c8;p=civicrm-core.git diff --git a/CRM/Financial/Form/PaymentEdit.php b/CRM/Financial/Form/PaymentEdit.php index 64cbf31294..84f0a0d0de 100644 --- a/CRM/Financial/Form/PaymentEdit.php +++ b/CRM/Financial/Form/PaymentEdit.php @@ -3,7 +3,7 @@ +--------------------------------------------------------------------+ | CiviCRM version 4.7 | +--------------------------------------------------------------------+ - | Copyright CiviCRM LLC (c) 2004-2017 | + | Copyright CiviCRM LLC (c) 2004-2018 | +--------------------------------------------------------------------+ | This file is a part of CiviCRM. | | | @@ -28,7 +28,7 @@ /** * * @package CRM - * @copyright CiviCRM LLC (c) 2004-2017 + * @copyright CiviCRM LLC (c) 2004-2018 */ class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form { @@ -39,6 +39,13 @@ class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form { */ protected $_id; + /** + * The id of the related contribution ID + * + * @var int + */ + protected $_contributionID; + /** * The variable which holds the information of a financial transaction * @@ -60,6 +67,7 @@ class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form { 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'])) { @@ -73,13 +81,7 @@ class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form { * @return array */ public function setDefaultValues() { - $defaults = $this->_values; - if (!empty($defaults['card_type_id'])) { - // See comments in getPaymentFields function about why this nastiness exists. - $defaults['credit_card_type'] = CRM_Core_PseudoConstant::getName('CRM_Financial_DAO_FinancialTrxn', 'card_type_id', $defaults['card_type_id']); - } - - return $defaults; + return $this->_values; } /** @@ -91,24 +93,26 @@ class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form { $paymentFields = $this->getPaymentFields(); $this->assign('paymentFields', $paymentFields); foreach ($paymentFields as $name => $paymentField) { - $this->add($paymentField['htmlType'], - $paymentField['name'], - $paymentField['title'], - $paymentField['attributes'], - TRUE - ); - if (!empty($paymentField['rules'])) { - foreach ($paymentField['rules'] as $rule) { - $this->addRule($name, - $rule['rule_message'], - $rule['rule_name'], - $rule['rule_parameters'] - ); - } + 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', @@ -122,83 +126,174 @@ class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form { )); } + /** + * 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, - 'check_number' => CRM_Utils_Array::value('check_number', $this->_submitValues), - 'pan_truncation' => CRM_Utils_Array::value('pan_truncation', $this->_submitValues), + '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')), ); - if (!empty($this->_submitValues['credit_card_type'])) { - // See comments in getPaymentFields function about why this nastiness exists. - $params['card_type_id'] = CRM_Core_PseudoConstant::getKey( - 'CRM_Financial_DAO_FinancialTrxn', - 'card_type_id', - $this->_submitValues['credit_card_type'] - ); + + $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); } - // update the financial trxn - civicrm_api3('FinancialTrxn', 'create', $params); + 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(); - $paymentInstrument = CRM_Core_PseudoConstant::getName('CRM_Financial_DAO_FinancialTrxn', 'payment_instrument_id', $this->_values['payment_instrument_id']); - if ($paymentInstrument == 'Check') { - $paymentFields['check_number'] = array( - 'htmlType' => 'text', - 'name' => 'check_number', - 'title' => ts('Check Number'), + $paymentFields = array( + 'payment_instrument_id' => array( + 'is_required' => TRUE, + 'add_field' => TRUE, + ), + 'check_number' => array( 'is_required' => FALSE, - 'attributes' => NULL, - ); - } - elseif ($paymentInstrument == 'Credit Card') { - // Ideally we would use $this->addField('card_type_id', array('entity' => 'FinancialTrxn')); - // to assign this field (& other fields on this form). However, the addCreditCardJs - // adds some 'pretty' to the credit card selection. The 'cost' of this is that because it - // was originally written to comply with front end needs (use of the word rather than the id) - // we have to do a lot of wrangling with our fields to make the BillingBlock.js code work. - // If you are reading this it means it's time to fix the BillingBlock.js to work with - // card_type_id and the pseudoconstant options & set this code free. No returns. - CRM_Financial_Form_Payment::addCreditCardJs(NULL, 'payment-edit-block'); - $paymentFields['credit_card_type'] = array( - 'htmlType' => 'select', - 'name' => 'credit_card_type', - 'title' => ts('Card Type'), - 'attributes' => array('' => ts('- select -')) + CRM_Contribute_PseudoConstant::creditCard(), - ); - $paymentFields['pan_truncation'] = array( - 'htmlType' => 'text', - 'name' => 'pan_truncation', - 'title' => ts('Last 4 digits of the card'), - 'attributes' => array( - 'size' => 4, - 'maxlength' => 4, - 'minlength' => 4, - 'autocomplete' => 'off', - ), - 'rules' => array( - array( - 'rule_message' => ts('Please enter valid last 4 digit card number.'), - 'rule_name' => 'numeric', - 'rule_parameters' => NULL, - ), - ), - ); - } - $paymentFields += array( + '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, @@ -208,6 +303,7 @@ class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form { 'htmlType' => 'text', 'name' => 'total_amount', 'title' => ts('Total Amount'), + 'is_required' => TRUE, 'attributes' => array( 'readonly' => TRUE, 'size' => 6,