// instrument is null and now new payment instrument is added along with the payment
$params['trxnParams']['payment_instrument_id'] = $params['contribution']->payment_instrument_id;
$params['trxnParams']['check_number'] = CRM_Utils_Array::value('check_number', $params);
- if (array_key_exists('payment_instrument_id', $params)) {
- $params['trxnParams']['total_amount'] = -$trxnParams['total_amount'];
- if (CRM_Utils_System::isNull($params['prevContribution']->payment_instrument_id) &&
- !CRM_Utils_System::isNull($params['contribution']->payment_instrument_id)
- ) {
- //check if status is changed from Pending to Completed
- // do not update payment instrument changes for Pending to Completed
- if (!($params['contribution']->contribution_status_id == array_search('Completed', $contributionStatuses) &&
- in_array($params['prevContribution']->contribution_status_id, $pendingStatus))
- ) {
- // for all other statuses create new financial records
- self::updateFinancialAccounts($params, 'changePaymentInstrument');
- $params['total_amount'] = $params['trxnParams']['total_amount'] = $trxnParams['total_amount'];
- self::updateFinancialAccounts($params, 'changePaymentInstrument');
- $updated = TRUE;
- }
- }
- elseif ((!CRM_Utils_System::isNull($params['contribution']->payment_instrument_id) ||
- !CRM_Utils_System::isNull($params['prevContribution']->payment_instrument_id)) &&
- $params['contribution']->payment_instrument_id != $params['prevContribution']->payment_instrument_id
- ) {
- // for any other payment instrument changes create new financial records
- self::updateFinancialAccounts($params, 'changePaymentInstrument');
- $params['total_amount'] = $params['trxnParams']['total_amount'] = $trxnParams['total_amount'];
- self::updateFinancialAccounts($params, 'changePaymentInstrument');
- $updated = TRUE;
- }
- elseif (!CRM_Utils_System::isNull($params['contribution']->check_number) &&
- $params['contribution']->check_number != $params['prevContribution']->check_number
- ) {
- // another special case when check number is changed, create new financial records
- // create financial trxn with negative amount
- $params['trxnParams']['check_number'] = $params['prevContribution']->check_number;
- self::updateFinancialAccounts($params, 'changePaymentInstrument');
- // create financial trxn with positive amount
- $params['trxnParams']['check_number'] = $params['contribution']->check_number;
- $params['total_amount'] = $params['trxnParams']['total_amount'] = $trxnParams['total_amount'];
- self::updateFinancialAccounts($params, 'changePaymentInstrument');
- $updated = TRUE;
- }
+
+ if (self::isPaymentInstrumentChange($params, $pendingStatus)) {
+ $updated = CRM_Core_BAO_FinancialTrxn::updateFinancialAccountsOnPaymentInstrumentChange($params);
}
//if Change contribution amount
}
}
}
- elseif ($context == 'changePaymentInstrument') {
- $params['trxnParams']['net_amount'] = $params['trxnParams']['total_amount'];
- $deferredFinancialAccount = CRM_Utils_Array::value('deferred_financial_account_id', $params);
- if (empty($deferredFinancialAccount)) {
- $deferredFinancialAccount = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($params['prevContribution']->financial_type_id, 'Deferred Revenue Account is');
- }
- $lastFinancialTrxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($params['prevContribution']->id, 'DESC', FALSE, NULL, $deferredFinancialAccount);
- if (!empty($lastFinancialTrxnId['financialTrxnId'])) {
- if ($params['total_amount'] != $params['trxnParams']['total_amount']) {
- $params['trxnParams']['to_financial_account_id'] = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialTrxn', $lastFinancialTrxnId['financialTrxnId'], 'to_financial_account_id');
- $params['trxnParams']['payment_instrument_id'] = $params['prevContribution']->payment_instrument_id;
- }
- else {
- $params['trxnParams']['to_financial_account_id'] = $params['to_financial_account_id'];
- $params['trxnParams']['payment_instrument_id'] = $params['contribution']->payment_instrument_id;
- }
- }
- }
if ($context == 'changedStatus') {
if (($previousContributionStatus == 'Pending'
}
}
}
- if ($context == 'changePaymentInstrument') {
- // store financial item Proportionaly.
- $trxnParams = array(
- 'total_amount' => $trxn->total_amount,
- 'contribution_id' => $params['contribution']->id,
- );
- self::assignProportionalLineItems($trxnParams, $trxn->id, $params['prevContribution']->total_amount);
- }
+
CRM_Core_BAO_FinancialTrxn::createDeferredTrxn(CRM_Utils_Array::value('line_item', $params), $params['contribution'], TRUE, $context);
}
return 1;
}
+ /**
+ * Does this transaction reflect a payment instrument change.
+ *
+ * @param array $params
+ * @param array $pendingStatuses
+ *
+ * @return bool
+ */
+ protected static function isPaymentInstrumentChange(&$params, $pendingStatuses) {
+ $contributionStatus = CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $params['contribution']->contribution_status_id);
+
+ if (array_key_exists('payment_instrument_id', $params)) {
+ if (CRM_Utils_System::isNull($params['prevContribution']->payment_instrument_id) &&
+ !CRM_Utils_System::isNull($params['contribution']->payment_instrument_id)
+ ) {
+ //check if status is changed from Pending to Completed
+ // do not update payment instrument changes for Pending to Completed
+ if (!($contributionStatus == 'Completed' &&
+ in_array($params['prevContribution']->contribution_status_id, $pendingStatuses))
+ ) {
+ return TRUE;
+ }
+ }
+ elseif ((!CRM_Utils_System::isNull($params['contribution']->payment_instrument_id) ||
+ !CRM_Utils_System::isNull($params['prevContribution']->payment_instrument_id)) &&
+ $params['contribution']->payment_instrument_id != $params['prevContribution']->payment_instrument_id
+ ) {
+ return TRUE;
+ }
+ elseif (!CRM_Utils_System::isNull($params['contribution']->check_number) &&
+ $params['contribution']->check_number != $params['prevContribution']->check_number
+ ) {
+ // another special case when check number is changed, create new financial records
+ // create financial trxn with negative amount
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+
/**
* Assign Test Value.
*
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
- * $Id$
- *
*/
class CRM_Core_BAO_FinancialTrxn extends CRM_Financial_DAO_FinancialTrxn {
/**
civicrm_api3('FinancialTrxn', 'create', $trxnparams);
}
+ /**
+ * The function is responsible for handling financial entries if payment instrument is changed
+ *
+ * @param array $inputParams
+ *
+ */
+ public static function updateFinancialAccountsOnPaymentInstrumentChange($inputParams) {
+ $prevContribution = $inputParams['prevContribution'];
+ $currentContribution = $inputParams['contribution'];
+ // ensure that there are all the information in updated contribution object identified by $currentContribution
+ $currentContribution->find(TRUE);
+
+ $deferredFinancialAccount = CRM_Utils_Array::value('deferred_financial_account_id', $inputParams);
+ if (empty($deferredFinancialAccount)) {
+ $deferredFinancialAccount = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($prevContribution->financial_type_id, 'Deferred Revenue Account is');
+ }
+
+ $lastFinancialTrxnId = self::getFinancialTrxnId($prevContribution->id, 'DESC', FALSE, NULL, $deferredFinancialAccount);
+
+ // there is no point to proceed as we can't find the last payment made
+ if (empty($lastFinancialTrxnId['financialTrxnId'])) {
+ return FALSE;
+ }
+
+ // If payment instrument is changed reverse the last payment
+ // in terms of reversing financial item and trxn
+ $lastFinancialTrxn = civicrm_api3('FinancialTrxn', 'getsingle', array('id' => $lastFinancialTrxnId['financialTrxnId']));
+ unset($lastFinancialTrxn['id']);
+ $lastFinancialTrxn['trxn_date'] = $inputParams['trxnParams']['trxn_date'];
+ $lastFinancialTrxn['total_amount'] = -$inputParams['trxnParams']['total_amount'];
+ $lastFinancialTrxn['net_amount'] = -$inputParams['trxnParams']['net_amount'];
+ $lastFinancialTrxn['fee_amount'] = -$inputParams['trxnParams']['fee_amount'];
+ $lastFinancialTrxn['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount($currentContribution->payment_instrument_id);
+ $lastFinancialTrxn['contribution_id'] = $prevContribution->id;
+ foreach (array($lastFinancialTrxn, $inputParams['trxnParams']) as $financialTrxnParams) {
+ $trxn = CRM_Core_BAO_FinancialTrxn::create($financialTrxnParams);
+ $trxnParams = array(
+ 'total_amount' => $trxn->total_amount,
+ 'contribution_id' => $currentContribution->id,
+ );
+ CRM_Contribute_BAO_Contribution::assignProportionalLineItems($trxnParams, $trxn->id, $prevContribution->total_amount);
+ }
+
+ self::createDeferredTrxn(CRM_Utils_Array::value('line_item', $inputParams), $currentContribution, TRUE, 'changePaymentInstrument');
+
+ return TRUE;
+ }
+
}
* This function has been problematic for some time but there are now several tests via the api_v3_Contribution test
* and the Paypal & Authorize.net IPN tests so any refactoring should be done in conjunction with those.
*
- * This function needs to have the 'body' moved to the CRM_Contribution_BAO_Contribute class and to undergo
+ * This function needs to have the 'body' moved to the CRM_Contribute_BAO_Contribute class and to undergo
* refactoring to separate the complete transaction and repeat transaction functionality into separate functions with
* a shared function that updates related components.
*
$this->assertEquals(45, $lineItem['line_total']);
}
+ /**
+ * Test the submit function if only payment instrument is changed from 'Check' to 'Credit Card'
+ */
+ public function testSubmitUpdateChangePaymentInstrument() {
+ $form = new CRM_Contribute_Form_Contribution();
+
+ $form->testSubmit(array(
+ 'total_amount' => 50,
+ 'financial_type_id' => 1,
+ 'receive_date' => '04/21/2015',
+ 'receive_date_time' => '11:27PM',
+ 'contact_id' => $this->_individualId,
+ 'payment_instrument_id' => array_search('Check', $this->paymentInstruments),
+ 'check_number' => '123AX',
+ 'contribution_status_id' => 1,
+ 'price_set_id' => 0,
+ ),
+ CRM_Core_Action::ADD);
+ $contribution = $this->callAPISuccessGetSingle('Contribution', array('contact_id' => $this->_individualId));
+ $form->testSubmit(array(
+ 'total_amount' => 50,
+ 'net_amount' => 50,
+ 'financial_type_id' => 1,
+ 'receive_date' => '04/21/2015',
+ 'receive_date_time' => '11:27PM',
+ 'contact_id' => $this->_individualId,
+ 'payment_instrument_id' => array_search('Credit Card', $this->paymentInstruments),
+ 'card_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Financial_DAO_FinancialTrxn', 'card_type_id', 'Visa'),
+ 'pan_truncation' => '1011',
+ 'contribution_status_id' => 1,
+ 'price_set_id' => 0,
+ 'id' => $contribution['id'],
+ ),
+ CRM_Core_Action::UPDATE);
+ $contribution = $this->callAPISuccessGetSingle('Contribution', array('contact_id' => $this->_individualId));
+ $this->assertEquals(50, (int) $contribution['total_amount']);
+
+ $financialTransactions = $this->callAPISuccess('FinancialTrxn', 'get', array('sequential' => TRUE));
+ $this->assertEquals(3, $financialTransactions['count']);
+
+ list($oldTrxn, $reversedTrxn, $latestTrxn) = $financialTransactions['values'];
+
+ $this->assertEquals(50, $oldTrxn['total_amount']);
+ $this->assertEquals('123AX', $oldTrxn['check_number']);
+ $this->assertEquals(array_search('Check', $this->paymentInstruments), $oldTrxn['payment_instrument_id']);
+
+ $this->assertEquals(-50, $reversedTrxn['total_amount']);
+ $this->assertEquals('123AX', $reversedTrxn['check_number']);
+ $this->assertEquals(array_search('Check', $this->paymentInstruments), $reversedTrxn['payment_instrument_id']);
+
+ $this->assertEquals(50, $latestTrxn['total_amount']);
+ $this->assertEquals('1011', $latestTrxn['pan_truncation']);
+ $this->assertEquals(array_search('Credit Card', $this->paymentInstruments), $latestTrxn['payment_instrument_id']);
+ $lineItem = $this->callAPISuccessGetSingle('LineItem', array());
+ }
+
/**
* Get parameters for credit card submit calls.
*
'status_id' => 1,
);
}
- if ($context == 'paymentInstrument') {
- $compareParams += array(
- 'to_financial_account_id' => CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount(4),
- 'payment_instrument_id' => 4,
- );
- }
- else {
- $compareParams['to_financial_account_id'] = 12;
- }
- $this->assertDBCompareValues('CRM_Financial_DAO_FinancialTrxn', $trxnParams1, array_merge($compareParams, $extraParams));
- $compareParams['total_amount'] = 100;
if ($context == 'paymentInstrument') {
$compareParams['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount($instrumentId);
$compareParams['payment_instrument_id'] = $instrumentId;
else {
$compareParams['to_financial_account_id'] = 12;
}
+ $this->assertDBCompareValues('CRM_Financial_DAO_FinancialTrxn', $trxnParams1, array_merge($compareParams, $extraParams));
+ $compareParams['total_amount'] = 100;
}
$this->assertDBCompareValues('CRM_Financial_DAO_FinancialTrxn', $params, array_merge($compareParams, $extraParams));