Skip to content

Commit

Permalink
Merge pull request #10982 from eileenmcnaughton/trxn_currency
Browse files Browse the repository at this point in the history
CRM-21187 Fix handling of currency when updating a contribution to be…
  • Loading branch information
monishdeb authored Sep 19, 2017
2 parents b7a8da9 + 8a40179 commit 787baa1
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
16 changes: 16 additions & 0 deletions CRM/Contribute/BAO/Contribution.php
Original file line number Diff line number Diff line change
Expand Up @@ -3467,6 +3467,9 @@ public static function recordFinancialAccounts(&$params, $financialTrxnValues =
* @param array $params
* Contribution object, line item array and params for trxn.
*
* @todo stop passing $params by reference. It is unclear the purpose of doing this &
* adds unpredictability.
*
* @param string $context
* Update scenarios.
*
Expand Down Expand Up @@ -3494,13 +3497,15 @@ public static function updateFinancialAccounts(&$params, $context = NULL) {
return;
}
if ($context == 'changedAmount' || $context == 'changeFinancialType') {
// @todo we should stop passing $params by reference - splitting this out would be a step towards that.
$params['trxnParams']['total_amount'] = $params['trxnParams']['net_amount'] = ($params['total_amount'] - $params['prevContribution']->total_amount);
}
if ($context == 'changedStatus') {
if ($previousContributionStatus == 'Completed'
&& (self::isContributionStatusNegative($params['contribution']->contribution_status_id))
) {
$isARefund = TRUE;
// @todo we should stop passing $params by reference - splitting this out would be a step towards that.
$params['trxnParams']['total_amount'] = -$params['total_amount'];
if (empty($params['contribution']->creditnote_id) || $params['contribution']->creditnote_id == "null") {
$creditNoteId = self::createCreditNoteId();
Expand All @@ -3514,6 +3519,7 @@ public static function updateFinancialAccounts(&$params, $context = NULL) {
$arAccountId = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($financialTypeID, 'Accounts Receivable Account is');

if ($currentContributionStatus == 'Cancelled') {
// @todo we should stop passing $params by reference - splitting this out would be a step towards that.
$params['trxnParams']['to_financial_account_id'] = $arAccountId;
$params['trxnParams']['total_amount'] = -$params['total_amount'];
if (is_null($params['contribution']->creditnote_id) || $params['contribution']->creditnote_id == "null") {
Expand All @@ -3522,6 +3528,7 @@ public static function updateFinancialAccounts(&$params, $context = NULL) {
}
}
else {
// @todo we should stop passing $params by reference - splitting this out would be a step towards that.
$params['trxnParams']['from_financial_account_id'] = $arAccountId;
}
}
Expand All @@ -3539,8 +3546,13 @@ public static function updateFinancialAccounts(&$params, $context = NULL) {
// & this can be removed
return;
}
// @todo we should stop passing $params by reference - splitting this out would be a step towards that.
// This is an update so original currency if none passed in.
$params['trxnParams']['currency'] = CRM_Utils_Array::value('currency', $params, $params['prevContribution']->currency);

self::recordAlwaysAccountsReceivable($params['trxnParams'], $params);
$trxn = CRM_Core_BAO_FinancialTrxn::create($params['trxnParams']);
// @todo we should stop passing $params by reference - splitting this out would be a step towards that.
$params['entity_id'] = self::$_trxnIDs[] = $trxn->id;
$query = "UPDATE civicrm_financial_item SET status_id = %1 WHERE entity_id = %2 and entity_table = 'civicrm_line_item'";
$sql = "SELECT id, amount FROM civicrm_financial_item WHERE entity_id = %1 and entity_table = 'civicrm_line_item'";
Expand Down Expand Up @@ -3574,6 +3586,7 @@ public static function updateFinancialAccounts(&$params, $context = NULL) {
}

$trxn = CRM_Core_BAO_FinancialTrxn::create($params['trxnParams']);
// @todo we should stop passing $params by reference - splitting this out would be a step towards that.
$params['entity_id'] = $trxn->id;
if ($context != 'changePaymentInstrument') {
$itemParams['entity_table'] = 'civicrm_line_item';
Expand All @@ -3590,6 +3603,7 @@ public static function updateFinancialAccounts(&$params, $context = NULL) {
$financialAccount = self::getFinancialAccountForStatusChangeTrxn($params, CRM_Utils_Array::value('financial_account_id', $prevFinancialItem));

$currency = $params['prevContribution']->currency;
// @todo we should stop passing $params by reference - splitting this out would be a step towards that.
if ($params['contribution']->currency) {
$currency = $params['contribution']->currency;
}
Expand All @@ -3606,6 +3620,7 @@ public static function updateFinancialAccounts(&$params, $context = NULL) {
'entity_id' => $lineItemDetails['id'],
);
$financialItem = CRM_Financial_BAO_FinancialItem::create($itemParams, NULL, $trxnIds);
// @todo we should stop passing $params by reference - splitting this out would be a step towards that.
$params['line_item'][$fieldId][$fieldValueId]['deferred_line_total'] = $itemParams['amount'];
$params['line_item'][$fieldId][$fieldValueId]['financial_item_id'] = $financialItem->id;

Expand Down Expand Up @@ -3634,6 +3649,7 @@ public static function updateFinancialAccounts(&$params, $context = NULL) {
}
}
if ($context == 'changeFinancialType') {
// @todo we should stop passing $params by reference - splitting this out would be a step towards that.
$params['skipLineItem'] = FALSE;
foreach ($params['line_item'] as &$lineItems) {
foreach ($lineItems as &$line) {
Expand Down
6 changes: 3 additions & 3 deletions CRM/Core/BAO/FinancialTrxn.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,18 @@ public function __construct() {
*
* @return CRM_Core_BAO_FinancialTrxn
*/
public static function create(&$params) {
public static function create($params) {
$trxn = new CRM_Financial_DAO_FinancialTrxn();
$trxn->copyValues($params);

if (!CRM_Utils_Rule::currencyCode($trxn->currency)) {
if (empty($params['id']) && !CRM_Utils_Rule::currencyCode($trxn->currency)) {
$trxn->currency = CRM_Core_Config::singleton()->defaultCurrency;
}

$trxn->save();

// We shoudn't proceed further to record related entity financial trxns if it's update.
if (!empty($params['id'])) {
// For an update entity financial transaction record will already exist. Return early.
return $trxn;
}

Expand Down
42 changes: 41 additions & 1 deletion tests/phpunit/api/v3/ContributionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,7 @@ public function testCreateContributionPayLaterOnline() {
* Function tests that additional financial records are created for online contribution with pending option.
*/
public function testCreateContributionPendingOnline() {
$paymentProcessor = CRM_Financial_BAO_PaymentProcessor::create($this->_processorParams);
CRM_Financial_BAO_PaymentProcessor::create($this->_processorParams);
$contributionPage = $this->callAPISuccess('contribution_page', 'create', $this->_pageParams);
$this->assertAPISuccess($contributionPage);
$params = array(
Expand Down Expand Up @@ -1747,6 +1747,46 @@ public function testCompleteTransaction() {
$this->revertTemplateToReservedTemplate();
}

/**
* Test completing a transaction via the API with a non-USD transaction.
*/
public function testCompleteTransactionEuro() {
$mut = new CiviMailUtils($this, TRUE);
$this->swapMessageTemplateForTestTemplate();
$this->createLoggedInUser();
$params = array_merge($this->_params, array('contribution_status_id' => 2, 'currency' => 'EUR'));
$contribution = $this->callAPISuccess('contribution', 'create', $params);

$this->callAPISuccess('contribution', 'completetransaction', array(
'id' => $contribution['id'],
));

$contribution = $this->callAPISuccess('contribution', 'getsingle', array('id' => $contribution['id']));
$this->assertEquals('SSF', $contribution['contribution_source']);
$this->assertEquals('Completed', $contribution['contribution_status']);
$this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($contribution['receipt_date'])));

$entityFinancialTransactions = $this->getFinancialTransactionsForContribution($contribution['id']);
$entityFinancialTransaction = reset($entityFinancialTransactions);
$financialTrxn = $this->callAPISuccessGetSingle('FinancialTrxn', array('id' => $entityFinancialTransaction['financial_trxn_id']));
$this->assertEquals('EUR', $financialTrxn['currency']);

$mut->checkMailLog(array(
'email:::anthony_anderson@civicrm.org',
'is_monetary:::1',
'amount:::100.00',
'currency:::EUR',
'receive_date:::' . date('Ymd', strtotime($contribution['receive_date'])),
"receipt_date:::\n",
'contributeMode:::notify',
'title:::Contribution',
'displayName:::Mr. Anthony Anderson II',
'contributionStatus:::Completed',
));
$mut->stop();
$this->revertTemplateToReservedTemplate();
}

/**
* Test to ensure mail is sent on chosing pay later
*/
Expand Down

0 comments on commit 787baa1

Please sign in to comment.