Skip to content

Commit

Permalink
[REF] extract internals of Payment.create into function on BAO class.
Browse files Browse the repository at this point in the history
This is a partial of civicrm#13330 - trying
to separate out the main code move from the changes. My only change was to change the name to
addPayment since that is what we are doing but here are some additionaly thoughts.

1) I'm inclined to put the class onto a new pseudo-bao CRM_Finanial_BAO_Payment. We already have this
pseudo-entity on the api level & it gives us a way to build up a place for the functions we are migrating
towards.

2) I think we should consider changing the input parameters to this function to be
- contributionID, total_amount & line_items or in some way limiting the parameters tha
t get passed through. We have historically gotten ourselves in trouble by
having people hacking in another parameter to go through whereas the strength of the api
is clear inputs & outputs. I note the api will need to support
'is_email_receipt' as will this fn & the CRM_Contribute_Form_AdditionalPayment::emailReceipt
should be moved off the form layer - possibly to our new BAO

3) I think the exceptions need to be CRM_Core_Exceptions if thrown in the BAO although this is kinda cosmetic
  • Loading branch information
eileenmcnaughton committed Dec 31, 2018
1 parent 0e35e2a commit cd6621a
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 68 deletions.
86 changes: 86 additions & 0 deletions CRM/Contribute/BAO/Contribution.php
Original file line number Diff line number Diff line change
Expand Up @@ -4477,6 +4477,92 @@ public static function isSingleLineItem($id) {
return ($lineItemCount == 1);
}

/**
* Function to process additional payment for partial and refund contributions.
*
* This function is called via API payment.create function. All forms that add payments
* should use this.
*
* @param array $params
* - contribution_id
* - total_amount
* - line_item
* @return \CRM_Financial_DAO_FinancialTrxn
*
* @throws \API_Exception
* @throws \CRM_Core_Exception
*/
public static function addPayment($params) {
$contribution = civicrm_api3('Contribution', 'getsingle', ['id' => $params['contribution_id']]);
$contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus($contribution['contribution_status_id'], 'name');
if ($contributionStatus != 'Partially paid'
&& !($contributionStatus == 'Pending' && $contribution['is_pay_later'] == TRUE)
) {
throw new API_Exception('Please select a contribution which has a partial or pending payment');
}
else {
// Check if pending contribution
$fullyPaidPayLater = FALSE;
if ($contributionStatus == 'Pending') {
$cmp = bccomp($contribution['total_amount'], $params['total_amount'], 5);
// Total payment amount is the whole amount paid against pending contribution
if ($cmp == 0 || $cmp == -1) {
civicrm_api3('Contribution', 'completetransaction', ['id' => $contribution['id']]);
// Get the trxn
$trxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contribution['id'], 'DESC');
$ftParams = ['id' => $trxnId['financialTrxnId']];
$trxn = CRM_Core_BAO_FinancialTrxn::retrieve($ftParams, CRM_Core_DAO::$_nullArray);
$fullyPaidPayLater = TRUE;
}
else {
civicrm_api3('Contribution', 'create',
[
'id' => $contribution['id'],
'contribution_status_id' => 'Partially paid',
]
);
}
}
if (!$fullyPaidPayLater) {
$trxn = CRM_Core_BAO_FinancialTrxn::getPartialPaymentTrxn($contribution, $params);
if (CRM_Utils_Array::value('line_item', $params) && !empty($trxn)) {
foreach ($params['line_item'] as $values) {
foreach ($values as $id => $amount) {
$p = ['id' => $id];
$check = CRM_Price_BAO_LineItem::retrieve($p, $defaults);
if (empty($check)) {
throw new API_Exception('Please specify a valid Line Item.');
}
// get financial item
$sql = "SELECT fi.id
FROM civicrm_financial_item fi
INNER JOIN civicrm_line_item li ON li.id = fi.entity_id and fi.entity_table = 'civicrm_line_item'
WHERE li.contribution_id = %1 AND li.id = %2";
$sqlParams = [
1 => [$params['contribution_id'], 'Integer'],
2 => [$id, 'Integer'],
];
$fid = CRM_Core_DAO::singleValueQuery($sql, $sqlParams);
// Record Entity Financial Trxn
$eftParams = [
'entity_table' => 'civicrm_financial_item',
'financial_trxn_id' => $trxn->id,
'amount' => $amount,
'entity_id' => $fid,
];
civicrm_api3('EntityFinancialTrxn', 'create', $eftParams);
}
}
}
elseif (!empty($trxn)) {
CRM_Contribute_BAO_Contribution::assignProportionalLineItems($params, $trxn->id, $contribution['total_amount']);
}
}
}
return $trxn;

}

/**
* Complete an order.
*
Expand Down
70 changes: 2 additions & 68 deletions api/v3/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,74 +132,8 @@ function civicrm_api3_payment_create(&$params) {
civicrm_api3('Payment', 'cancel', $params);
$params['total_amount'] = $amount;
}
// Get contribution
$contribution = civicrm_api3('Contribution', 'getsingle', array('id' => $params['contribution_id']));
$contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus($contribution['contribution_status_id'], 'name');
if ($contributionStatus != 'Partially paid'
&& !($contributionStatus == 'Pending' && $contribution['is_pay_later'] == TRUE)
) {
throw new API_Exception('Please select a contribution which has a partial or pending payment');
}
else {
// Check if pending contribution
$fullyPaidPayLater = FALSE;
if ($contributionStatus == 'Pending') {
$cmp = bccomp($contribution['total_amount'], $params['total_amount'], 5);
// Total payment amount is the whole amount paid against pending contribution
if ($cmp == 0 || $cmp == -1) {
civicrm_api3('Contribution', 'completetransaction', array('id' => $contribution['id']));
// Get the trxn
$trxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contribution['id'], 'DESC');
$ftParams = array('id' => $trxnId['financialTrxnId']);
$trxn = CRM_Core_BAO_FinancialTrxn::retrieve($ftParams, CRM_Core_DAO::$_nullArray);
$fullyPaidPayLater = TRUE;
}
else {
civicrm_api3('Contribution', 'create',
array(
'id' => $contribution['id'],
'contribution_status_id' => 'Partially paid',
)
);
}
}
if (!$fullyPaidPayLater) {
$trxn = CRM_Core_BAO_FinancialTrxn::getPartialPaymentTrxn($contribution, $params);
if (CRM_Utils_Array::value('line_item', $params) && !empty($trxn)) {
foreach ($params['line_item'] as $values) {
foreach ($values as $id => $amount) {
$p = array('id' => $id);
$check = CRM_Price_BAO_LineItem::retrieve($p, $defaults);
if (empty($check)) {
throw new API_Exception('Please specify a valid Line Item.');
}
// get financial item
$sql = "SELECT fi.id
FROM civicrm_financial_item fi
INNER JOIN civicrm_line_item li ON li.id = fi.entity_id and fi.entity_table = 'civicrm_line_item'
WHERE li.contribution_id = %1 AND li.id = %2";
$sqlParams = array(
1 => array($params['contribution_id'], 'Integer'),
2 => array($id, 'Integer'),
);
$fid = CRM_Core_DAO::singleValueQuery($sql, $sqlParams);
// Record Entity Financial Trxn
$eftParams = array(
'entity_table' => 'civicrm_financial_item',
'financial_trxn_id' => $trxn->id,
'amount' => $amount,
'entity_id' => $fid,
);
civicrm_api3('EntityFinancialTrxn', 'create', $eftParams);
}
}
}
elseif (!empty($trxn)) {
// Assign the lineitems proportionally
CRM_Contribute_BAO_Contribution::assignProportionalLineItems($params, $trxn->id, $contribution['total_amount']);
}
}
}
$trxn = CRM_Contribute_BAO_Contribution::addPayment($params);

$values = array();
_civicrm_api3_object_to_array_unique_fields($trxn, $values[$trxn->id]);
return civicrm_api3_create_success($values, $params, 'Payment', 'create', $trxn);
Expand Down
91 changes: 91 additions & 0 deletions tests/phpunit/CRMTraits/PCP/PCPTestTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 5 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2018 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

/**
* Trait CRMTraits_PCP_PCPTestTrait
*
* Traits for testing PCP pages.
*/
trait CRMTraits_PCP_PCPTestTrait {
/**
* Build and return pcpBlock params.
*
* Create the necessary initial objects for a pcpBlock, then return the
* params needed to create the pcpBlock.
*
*/
public function pcpBlockParams() {
$contribPage = CRM_Core_DAO::createTestObject('CRM_Contribute_DAO_ContributionPage');
$contribPageId = $contribPage->id;
$supporterProfile = CRM_Core_DAO::createTestObject('CRM_Core_DAO_UFGroup');
$supporterProfileId = $supporterProfile->id;

$params = array(
'entity_table' => 'civicrm_contribution_page',
'entity_id' => $contribPageId,
'supporter_profile_id' => $supporterProfileId,
'target_entity_id' => 1,
'is_approval_needed' => 1,
'is_tellfriend_enabled' => 1,
'tellfriend_limit' => 1,
'link_text' => 'Create your own PCP',
'is_active' => 1,
);

return $params;
}

/**
* Build and return pcp params.
*
* Create the necessary initial objects for a pcp page, then return the
* params needed to create the pcp page.
*/
public function pcpParams() {
$contact = CRM_Core_DAO::createTestObject('CRM_Contact_DAO_Contact');
$contactId = $contact->id;
$contribPage = CRM_Core_DAO::createTestObject('CRM_Contribute_DAO_ContributionPage');
$contribPageId = $contribPage->id;

$params = array(
'contact_id' => $contactId,
'status_id' => '1',
'title' => 'My PCP',
'intro_text' => 'Hey you, contribute now!',
'page_text' => 'You better give more.',
'donate_link_text' => 'Donate Now',
'page_id' => $contribPageId,
'is_thermometer' => 1,
'is_honor_roll' => 1,
'goal_amount' => 10000.00,
'is_active' => 1,
);

return $params;
}

}

0 comments on commit cd6621a

Please sign in to comment.