X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FContribute%2FBAO%2FContribution.php;h=fde8e741e67d224f747121fe397a66556b3fa19e;hb=8cf01b22ec5c8a58c2837e0ce8355d9cad715cc1;hp=a80ac0fef646db1a92b395f6a6afcd827cc27ea2;hpb=f63cf758c88444f9dfe45a0a7f11b8ae623a948a;p=civicrm-core.git diff --git a/CRM/Contribute/BAO/Contribution.php b/CRM/Contribute/BAO/Contribution.php index a80ac0fef6..fde8e741e6 100644 --- a/CRM/Contribute/BAO/Contribution.php +++ b/CRM/Contribute/BAO/Contribution.php @@ -1,9 +1,9 @@ copyValues($params); @@ -161,7 +181,7 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { $contribution->currency = $config->defaultCurrency; } - if ($contributionID) { + if ($contributionID && $setPrevContribution) { $params['prevContribution'] = self::getValues(array('id' => $contributionID), CRM_Core_DAO::$_nullArray, CRM_Core_DAO::$_nullArray); } @@ -218,6 +238,31 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { return NULL; } + /** + * Get the number of terms for this contribution for a given membership type + * based on querying the line item table and relevant price field values + * Note that any one contribution should only be able to have one line item relating to a particular membership + * type + * @param int $membershipTypeID + * + * @return int + */ + public function getNumTermsByContributionAndMembershipType($membershipTypeID) { + if (!is_numeric($membershipTypeID)) { + //precautionary measure - this is being introduced to a mature release hence adding extra checks that + // might be removed later + return 1; + } + $numTerms = CRM_Core_DAO::singleValueQuery(" + SELECT membership_num_terms FROM civicrm_line_item li + LEFT JOIN civicrm_price_field_value v ON li.price_field_value_id = v.id + WHERE contribution_id = %1 AND membership_type_id = %2", + array(1 => array($this->id, 'Integer') , 2 => array($membershipTypeID, 'Integer')) + ); + // default of 1 is precautionary + return empty($numTerms) ? 1 : $numTerms; + } + /** * takes an associative array and creates a contribution object * @@ -228,7 +273,7 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { * @access public * @static */ - static function &create(&$params, $ids = array()) { + static function create(&$params, $ids = array()) { $dateFields = array('receive_date', 'cancel_date', 'receipt_date', 'thankyou_date'); foreach ($dateFields as $df) { if (isset($params[$df])) { @@ -247,7 +292,7 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { $params['contribution_id'] = $contribution->id; - if (CRM_Utils_Array::value('custom', $params) && + if (!empty($params['custom']) && is_array($params['custom']) ) { CRM_Core_BAO_CustomValueTable::store($params['custom'], 'civicrm_contribution', $contribution->id); @@ -255,7 +300,7 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { $session = CRM_Core_Session::singleton(); - if (CRM_Utils_Array::value('note', $params)) { + if (!empty($params['note'])) { $noteParams = array( 'entity_table' => 'civicrm_contribution', 'note' => $params['note'], @@ -270,7 +315,7 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { } // make entry in batch entity batch table - if (CRM_Utils_Array::value('batch_id', $params)) { + if (!empty($params['batch_id'])) { // in some update cases we need to get extra fields - ie an update that doesn't pass in all these params $titleFields = array( 'contact_id', @@ -307,12 +352,15 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { } // Handle soft credit and / or link to personal campaign page - list($type, $softIDs) = CRM_Contribute_BAO_ContributionSoft::getSoftCreditType($contribution->id); + $softIDs = CRM_Contribute_BAO_ContributionSoft::getSoftCreditIds($contribution->id); + + //Delete PCP against this contribution and create new on submitted PCP information + $pcpId = CRM_Contribute_BAO_ContributionSoft::getSoftCreditIds($contribution->id, TRUE); + if ($pcpId) { + $deleteParams = array('id' => $pcpId); + CRM_Contribute_BAO_ContributionSoft::del($deleteParams); + } if ($pcp = CRM_Utils_Array::value('pcp', $params)) { - if (!empty($type) && $type == 'soft') { - $deleteParams = array('contribution_id' => $contribution->id); - CRM_Contribute_BAO_ContributionSoft::del($deleteParams); - } $softParams = array(); $softParams['contribution_id'] = $contribution->id; $softParams['pcp_id'] = $pcp['pcp_made_through_id']; @@ -324,9 +372,10 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { $softParams['pcp_display_in_roll'] = CRM_Utils_Array::value('pcp_display_in_roll', $pcp); $softParams['pcp_roll_nickname'] = CRM_Utils_Array::value('pcp_roll_nickname', $pcp); $softParams['pcp_personal_note'] = CRM_Utils_Array::value('pcp_personal_note', $pcp); + $softParams['soft_credit_type_id'] = CRM_Core_OptionGroup::getValue('soft_credit_type', 'pcp', 'name'); CRM_Contribute_BAO_ContributionSoft::add($softParams); } - elseif (CRM_Utils_Array::value('soft_credit', $params)) { + if (isset($params['soft_credit'])) { $softParams = $params['soft_credit']; if (!empty($softIDs)) { @@ -341,10 +390,10 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { foreach ($softParams as $softParam) { $softParam['contribution_id'] = $contribution->id; $softParam['currency'] = $contribution->currency; - $softParam['pcp_id'] = 'null'; - $softParam['pcp_display_in_roll'] = 'null'; - $softParam['pcp_roll_nickname'] = 'null'; - $softParam['pcp_personal_note'] = 'NULL'; + //case during Contribution Import when we assign soft contribution amount as contribution's total_amount by default + if (empty($softParam['amount'])) { + $softParam['amount'] = $contribution->total_amount; + } CRM_Contribute_BAO_ContributionSoft::add($softParam); } } @@ -352,7 +401,7 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { $transaction->commit(); // do not add to recent items for import, CRM-4399 - if (!CRM_Utils_Array::value('skipRecentView', $params)) { + if (empty($params['skipRecentView'])) { $url = CRM_Utils_System::url('civicrm/contact/view/contribution', "action=view&reset=1&id={$contribution->id}&cid={$contribution->contact_id}&context=home" ); @@ -476,6 +525,9 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { * scheme. Adding weight is super important and should be done in the * next week or so, before this can be called complete. * + * @param string $contactType + * @param bool $status + * * @return array array of importable Fields * @access public * @static @@ -543,6 +595,9 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { return self::$_importableFields; } + /** + * @return array + */ static function &exportableFields() { if (!self::$_exportableFields) { if (!self::$_exportableFields) { @@ -586,8 +641,35 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { ) ); + $softCreditFields = array( + 'contribution_soft_credit_name' => array( + 'name' => 'contribution_soft_credit_name', + 'title' => 'Soft Credit For', + 'where' => 'civicrm_contact_d.display_name', + 'data_type' => CRM_Utils_Type::T_STRING + ), + 'contribution_soft_credit_amount' => array( + 'name' => 'contribution_soft_credit_amount', + 'title' => 'Soft Credit Amount', + 'where' => 'civicrm_contribution_soft.amount', + 'data_type' => CRM_Utils_Type::T_MONEY + ), + 'contribution_soft_credit_type' => array( + 'name' => 'contribution_soft_credit_type', + 'title' => 'Soft Credit Type', + 'where' => 'contribution_softcredit_type.label', + 'data_type' => CRM_Utils_Type::T_STRING + ), + 'contribution_soft_credit_contribution_id' => array( + 'name' => 'contribution_soft_credit_contribution_id', + 'title' => 'Soft Credit For Contribution ID', + 'where' => 'civicrm_contribution_soft.contribution_id', + 'data_type' => CRM_Utils_Type::T_INT + ), + ); + $fields = array_merge($impFields, $typeField, $contributionStatus, $optionField, $expFieldProduct, - $expFieldsContrib, $contributionNote, $contributionRecurId, $extraFields, $financialAccount, + $expFieldsContrib, $contributionNote, $contributionRecurId, $extraFields, $softCreditFields, $financialAccount, CRM_Core_BAO_CustomField::getFieldsForImport('Contribution') ); @@ -597,6 +679,13 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution { return self::$_exportableFields; } + /** + * @param null $status + * @param null $startDate + * @param null $endDate + * + * @return array|null + */ static function getTotalAmountAndCount($status = NULL, $startDate = NULL, $endDate = NULL) { $where = array(); switch ($status) { @@ -648,8 +737,9 @@ INNER JOIN civicrm_contact contact ON ( contact.id = civicrm_contribution.conta /** * Delete the indirect records associated with this contribution first * - * @return $results no of deleted Contribution on success, false otherwise - * @access public + * @param $id + * + * @return mixed|null $results no of deleted Contribution on success, false otherwise@access public * @static */ static function deleteContribution($id) { @@ -719,9 +809,12 @@ INNER JOIN civicrm_contact contact ON ( contact.id = civicrm_contribution.conta /** * Check if there is a contribution with the same trxn_id or invoice_id * - * @param array $params (reference ) an assoc array of name/value pairs - * @param array $duplicates (reference ) store ids of duplicate contribs + * @param $input + * @param array $duplicates (reference ) store ids of duplicate contribs * + * @param null $id + * + * @internal param array $params (reference ) an assoc array of name/value pairs * @return boolean true if duplicate, false otherwise * @access public * static @@ -827,50 +920,26 @@ INNER JOIN civicrm_contact contact ON ( contact.id = civicrm_contribution.conta */ static function getSpecialContributionFields() { $extraFields = array( - 'honor_contact_name' => array( - 'name' => 'honor_contact_name', - 'title' => 'Honor Contact Name', - 'headerPattern' => '/^honor_contact_name$/i', - 'where' => 'civicrm_contact_c.display_name', - ), - 'honor_contact_email' => array( - 'name' => 'honor_contact_email', - 'title' => 'Honor Contact Email', - 'headerPattern' => '/^honor_contact_email$/i', - 'where' => 'honor_email.email', - ), - 'honor_contact_id' => array( - 'name' => 'honor_contact_id', - 'title' => 'Honor Contact ID', - 'headerPattern' => '/^honor_contact_id$/i', - 'where' => 'civicrm_contribution.honor_contact_id', - ), - 'honor_type_label' => array( - 'name' => 'honor_type_label', - 'title' => 'Honor Type Label', - 'headerPattern' => '/^honor_type_label$/i', - 'where' => 'honor_type.label', - ), - 'soft_credit_name' => array( - 'name' => 'soft_credit_name', + 'contribution_soft_credit_name' => array( + 'name' => 'contribution_soft_credit_name', 'title' => 'Soft Credit Name', 'headerPattern' => '/^soft_credit_name$/i', 'where' => 'civicrm_contact_d.display_name', ), - 'soft_credit_email' => array( - 'name' => 'soft_credit_email', + 'contribution_soft_credit_email' => array( + 'name' => 'contribution_soft_credit_email', 'title' => 'Soft Credit Email', 'headerPattern' => '/^soft_credit_email$/i', 'where' => 'soft_email.email', ), - 'soft_credit_phone' => array( - 'name' => 'soft_credit_phone', + 'contribution_soft_credit_phone' => array( + 'name' => 'contribution_soft_credit_phone', 'title' => 'Soft Credit Phone', 'headerPattern' => '/^soft_credit_phone$/i', 'where' => 'soft_phone.phone', ), - 'soft_credit_contact_id' => array( - 'name' => 'soft_credit_contact_id', + 'contribution_soft_credit_contact_id' => array( + 'name' => 'contribution_soft_credit_contact_id', 'title' => 'Soft Credit Contact ID', 'headerPattern' => '/^soft_credit_contact_id$/i', 'where' => 'civicrm_contribution_soft.contact_id', @@ -880,6 +949,11 @@ INNER JOIN civicrm_contact contact ON ( contact.id = civicrm_contribution.conta return $extraFields; } + /** + * @param $pageID + * + * @return array + */ static function getCurrentandGoalAmount($pageID) { $query = " SELECT p.goal_amount as goal, sum( c.total_amount ) as total @@ -903,44 +977,6 @@ GROUP BY p.id } } - /** - * Function to create is honor of - * - * @param array $params associated array of fields (by reference) - * @param int $honorId honor Id - * @param array $honorParams any params that should be send to the create function - * - * @return contact id - */ - static function createHonorContact(&$params, $honorId = NULL, $honorParams = array()) { - $honorParams = array_merge( - array( - 'first_name' => $params['honor_first_name'], - 'last_name' => $params['honor_last_name'], - 'prefix_id' => $params['honor_prefix_id'], - 'email-Primary' => $params['honor_email'], - ), - $honorParams - ); - if (!$honorId) { - $honorParams['email'] = $params['honor_email']; - - $dedupeParams = CRM_Dedupe_Finder::formatParams($honorParams, 'Individual'); - $dedupeParams['check_permission'] = FALSE; - $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual'); - - // if we find more than one contact, use the first one - $honorId = CRM_Utils_Array::value(0, $ids); - } - - $contactID = CRM_Contact_BAO_Contact::createProfileContact( - $honorParams, - CRM_Core_DAO::$_nullArray, - $honorId - ); - return $contactID; - } - /** * Function to get list of contribution In Honor of contact Ids * @@ -953,22 +989,27 @@ GROUP BY p.id */ static function getHonorContacts($honorId) { $params = array(); - $honorDAO = new CRM_Contribute_DAO_Contribution(); - $honorDAO->honor_contact_id = $honorId; + $honorDAO = new CRM_Contribute_DAO_ContributionSoft(); + $honorDAO->contact_id = $honorId; $honorDAO->find(); - $status = CRM_Contribute_PseudoConstant::contributionStatus($honorDAO->contribution_status_id); $type = CRM_Contribute_PseudoConstant::financialType(); while ($honorDAO->fetch()) { - $params[$honorDAO->id]['honorId'] = $honorDAO->contact_id; - $params[$honorDAO->id]['display_name'] = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $honorDAO->contact_id, 'display_name'); - $params[$honorDAO->id]['type'] = $type[$honorDAO->financial_type_id]; - $params[$honorDAO->id]['type_id'] = $honorDAO->financial_type_id; - $params[$honorDAO->id]['amount'] = CRM_Utils_Money::format($honorDAO->total_amount, $honorDAO->currency); - $params[$honorDAO->id]['source'] = $honorDAO->source; - $params[$honorDAO->id]['receive_date'] = $honorDAO->receive_date; - $params[$honorDAO->id]['contribution_status'] = CRM_Utils_Array::value($honorDAO->contribution_status_id, $status); + $contributionDAO = new CRM_Contribute_DAO_Contribution(); + $contributionDAO->id = $honorDAO->contribution_id; + + if ($contributionDAO->find(TRUE)) { + $params[$contributionDAO->id]['honor_type'] = CRM_Core_OptionGroup::getLabel('soft_credit_type', $honorDAO->soft_credit_type_id, 'value'); + $params[$contributionDAO->id]['honorId'] = $contributionDAO->contact_id; + $params[$contributionDAO->id]['display_name'] = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contributionDAO->contact_id, 'display_name'); + $params[$contributionDAO->id]['type'] = $type[$contributionDAO->financial_type_id]; + $params[$contributionDAO->id]['type_id'] = $contributionDAO->financial_type_id; + $params[$contributionDAO->id]['amount'] = CRM_Utils_Money::format($contributionDAO->total_amount, $contributionDAO->currency); + $params[$contributionDAO->id]['source'] = $contributionDAO->source; + $params[$contributionDAO->id]['receive_date'] = $contributionDAO->receive_date; + $params[$contributionDAO->id]['contribution_status'] = CRM_Contribute_PseudoConstant::contributionStatus($contributionDAO->contribution_status_id); + } } return $params; @@ -995,6 +1036,11 @@ WHERE civicrm_contribution.contact_id = civicrm_contact.id return CRM_Core_DAO::singleValueQuery($query, CRM_Core_DAO::$_nullArray); } + /** + * @param $contactID + * + * @return array + */ static function annual($contactID) { if (is_array($contactID)) { $contactIDs = implode(',', $contactID); @@ -1165,11 +1211,14 @@ LEFT JOIN civicrm_option_value contribution_status ON (civicrm_contribution.cont /** * Function to create address associated with contribution record. - * @param array $params an associated array - * @param int $billingID $billingLocationTypeID * - * @return address id - * @static + * @param array $params an associated array + * @param $billingLocationTypeID + * + * @internal param int $billingID $billingLocationTypeID + * + * @return address id + * @static */ static function createAddress(&$params, $billingLocationTypeID) { $billingFields = array( @@ -1202,8 +1251,11 @@ LEFT JOIN civicrm_option_value contribution_status ON (civicrm_contribution.cont /** * Delete billing address record related contribution * - * @param int $contact_id contact id - * @param int $contribution_id contributionId + * @param null $contributionId + * @param null $contactId + * + * @internal param int $contact_id contact id + * @internal param int $contribution_id contributionId * @access public * @static */ @@ -1346,7 +1398,7 @@ LEFT JOIN civicrm_contribution contribution ON ( componentPayment.contribution_ } } - if (CRM_Utils_Array::value('contact_id', $componentDetails)) { + if (!empty($componentDetails['contact_id'])) { $componentDetails['contact_id'] = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'contact_id' @@ -1354,11 +1406,7 @@ LEFT JOIN civicrm_contribution contribution ON ( componentPayment.contribution_ } // do check for required ids. - if (!CRM_Utils_Array::value('membership', $componentDetails) && - !CRM_Utils_Array::value('participant', $componentDetails) && - !CRM_Utils_Array::value('pledge_payment', $componentDetails) || - !CRM_Utils_Array::value('contact_id', $componentDetails) - ) { + if (empty($componentDetails['membership']) && empty($componentDetails['participant']) && empty($componentDetails['pledge_payment']) || empty($componentDetails['contact_id'])) { return $updateResult; } @@ -1546,7 +1594,9 @@ LEFT JOIN civicrm_contribution contribution ON ( componentPayment.contribution_ $dates['end_date'], $dates['join_date'], 'today', - TRUE + TRUE, + $membership->membership_type_id, + (array) $membership ); $formattedParams = array( @@ -1622,7 +1672,7 @@ LEFT JOIN civicrm_contribution contribution ON ( componentPayment.contribution_ 'contribution_status_id', 'non_deductible_amount', 'receipt_date', 'check_number', ); foreach ($fields as $field) { - if (!CRM_Utils_Array::value($field, $params)) { + if (empty($params[$field])) { continue; } $contributionParams[$field] = $params[$field]; @@ -1691,7 +1741,13 @@ LEFT JOIN civicrm_contribution contribution ON ( componentPayment.contribution_ return $componentDetails; } - static function contributionCount($contactId, $includeSoftCredit = TRUE, $includeHonoree = TRUE) { + /** + * @param $contactId + * @param bool $includeSoftCredit + * + * @return null|string + */ + static function contributionCount($contactId, $includeSoftCredit = TRUE) { if (!$contactId) { return 0; } @@ -1701,11 +1757,6 @@ LEFT JOIN civicrm_contribution contribution ON ( componentPayment.contribution_ FROM civicrm_contribution contribution WHERE contribution.is_test = 0 AND contribution.contact_id = {$contactId} "; - $contactHonoreeContributionsSQL = " - SELECT contribution.id - FROM civicrm_contribution contribution - WHERE contribution.is_test = 0 AND contribution.honor_contact_id = {$contactId} "; - $contactSoftCreditContributionsSQL = " SELECT contribution.id FROM civicrm_contribution contribution INNER JOIN civicrm_contribution_soft softContribution @@ -1719,11 +1770,6 @@ LEFT JOIN civicrm_contribution contribution ON ( componentPayment.contribution_ $query .= $contactSoftCreditContributionsSQL; } - if ($includeHonoree) { - $query .= " UNION "; - $query .= $contactHonoreeContributionsSQL; - } - $query .= ") x"; return CRM_Core_DAO::singleValueQuery($query); @@ -1848,6 +1894,15 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac * @param boolean $loadAll - load all related objects - even where id not passed in? (allows API to call this) * Note that the unit test for the BaseIPN class tests this function */ + /** + * @param $input + * @param $ids + * @param bool $required + * @param bool $loadAll + * + * @return bool + * @throws Exception + */ function loadRelatedObjects(&$input, &$ids, $required = FALSE, $loadAll = false) { if($loadAll){ $ids = array_merge($this->getComponentDetails($this->id),$ids); @@ -1951,7 +2006,7 @@ WHERE contribution_id = %1 "; ); } //fail to load payment processor id. - elseif (!CRM_Utils_Array::value('pledge_payment', $ids)) { + elseif (empty($ids['pledge_payment'])) { $loadObjectSuccess = TRUE; if ($required) { throw new Exception("Could not find contribution page for contribution record: " . $this->id); @@ -2020,6 +2075,15 @@ WHERE contribution_id = %1 "; * function doing emails / pdfs with it * @return array $messageArray - messages */ + /** + * @param $input + * @param $ids + * @param $values + * @param bool $recur + * @param bool $returnMessageText + * + * @throws Exception + */ function composeMessageArray(&$input, &$ids, &$values, $recur = FALSE, $returnMessageText = TRUE) { if (empty($this->_relatedObjects)) { $this->loadRelatedObjects($input, $ids); @@ -2072,7 +2136,7 @@ WHERE contribution_id = %1 "; } else { $values['contribution_id'] = $this->id; - if (CRM_Utils_Array::value('related_contact', $ids)) { + if (!empty($ids['related_contact'])) { $values['related_contact'] = $ids['related_contact']; if (isset($ids['onbehalf_dupe_alert'])) { $values['onbehalf_dupe_alert'] = $ids['onbehalf_dupe_alert']; @@ -2093,7 +2157,7 @@ WHERE contribution_id = %1 "; if (!empty($this->_relatedObjects['membership'])) { foreach ($this->_relatedObjects['membership'] as $membership) { if ($membership->id) { - $values['membership_id'] = $membership->id; + $values['isMembership'] = TRUE; // need to set the membership values here $template->assign('membership_assign', 1); @@ -2149,6 +2213,13 @@ WHERE contribution_id = %1 "; * * NB don't add direct calls to the function as we intend to change the signature */ + /** + * @param $input + * @param $values + * @param array $ids + * + * @return mixed + */ function _gatherMessageValues($input, &$values, $ids = array()) { // set display address of contributor if ($this->address_id) { @@ -2201,7 +2272,7 @@ WHERE contribution_id = %1 "; $this->contact_id ); // if this is onbehalf of contribution then set related contact - if (CRM_Utils_Array::value('individual_id', $relatedContact)) { + if (!empty($relatedContact['individual_id'])) { $values['related_contact'] = $ids['related_contact'] = $relatedContact['individual_id']; } } @@ -2256,6 +2327,14 @@ WHERE contribution_id = %1 "; * function & breaking it down into manageable chunks. Eventually it will be refactored into something else * Note we send directly from this function in some cases because it is only partly refactored * Don't call this function directly as the signature will change + * + * @param $values + * @param $input + * @param $template CRM_Core_SMARTY + * @param bool $recur + * @param bool $returnMessageText + * + * @return mixed */ function _assignMessageVariablesToTemplate(&$values, $input, &$template, $recur = FALSE, $returnMessageText = True) { $template->assign('first_name', $this->_relatedObjects['contact']->first_name); @@ -2264,28 +2343,35 @@ WHERE contribution_id = %1 "; if (!empty($values['lineItem']) && !empty($this->_relatedObjects['membership'])) { $template->assign('useForMember', true); } - //assign honor infomation to receiptmessage - $honorID = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', - $this->id, - 'honor_contact_id' - ); - if (!empty($honorID)) { + //assign honor information to receipt message + $softRecord = CRM_Contribute_BAO_ContributionSoft::getSoftContribution($this->id); - $honorDefault = $honorIds = array(); - $honorIds['contribution'] = $this->id; - $idParams = array('id' => $honorID, 'contact_id' => $honorID); - CRM_Contact_BAO_Contact::retrieve($idParams, $honorDefault, $honorIds); - $honorType = CRM_Core_PseudoConstant::get('CRM_Contribute_DAO_Contribution', 'honor_type_id'); + if (isset($softRecord['soft_credit'])) { + //if id of contribution page is present + if (!empty($values['id'])) { + $values['honor'] = array( + 'honor_profile_values' => array(), + 'honor_profile_id' => CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFJoin', $values['id'], 'uf_group_id', 'entity_id'), + 'honor_id' => $softRecord['soft_credit'][1]['contact_id'], + ); + $softCreditTypes = CRM_Core_OptionGroup::values('soft_credit_type'); - $template->assign('honor_block_is_active', 1); - if (CRM_Utils_Array::value('prefix_id', $honorDefault)) { - $prefix = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'prefix_id'); - $template->assign('honor_prefix', $prefix[$honorDefault['prefix_id']]); + $template->assign('soft_credit_type', $softRecord['soft_credit'][1]['soft_credit_type_label']); + $template->assign('honor_block_is_active', CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFJoin', $values['id'], 'is_active', 'entity_id')); + } + else { + //offline contribution + $softCreditTypes = $softCredits = array(); + foreach ($softRecord['soft_credit'] as $key => $softCredit) { + $softCreditTypes[$key] = $softCredit['soft_credit_type_label']; + $softCredits[$key] = array( + 'Name' => $softCredit['contact_name'], + 'Amount' => CRM_Utils_Money::format($softCredit['amount'], $softCredit['currency']) + ); + } + $template->assign('softCreditTypes', $softCreditTypes); + $template->assign('softCredits', $softCredits); } - $template->assign('honor_first_name', CRM_Utils_Array::value('first_name', $honorDefault)); - $template->assign('honor_last_name', CRM_Utils_Array::value('last_name', $honorDefault)); - $template->assign('honor_email', CRM_Utils_Array::value('email', $honorDefault['email'][1])); - $template->assign('honor_type', $honorType[$this->honor_type_id]); } $dao = new CRM_Contribute_DAO_ContributionProduct(); @@ -2432,6 +2518,8 @@ WHERE contribution_id = %1 "; * * @param int $contributionId contribution id * + * @param bool $isNotCancelled + * * @return boolean * @access public * @static @@ -2488,11 +2576,15 @@ WHERE contribution_id = %1 "; * @param array $params contribution object, line item array and params for trxn * * + * @param array $financialTrxnValues + * + * @return null|object * @access public * @static */ - static function recordFinancialAccounts(&$params) { - $skipRecords = $update = FALSE; + static function recordFinancialAccounts(&$params, $financialTrxnValues = NULL) { + $skipRecords = $update = $return = $isRelatedId = FALSE; + $additionalParticipantId = array(); $contributionStatuses = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); @@ -2501,26 +2593,72 @@ WHERE contribution_id = %1 "; $entityTable = 'civicrm_participant'; $additionalParticipantId = CRM_Event_BAO_Participant::getAdditionalParticipantIds($entityId); } + elseif (!empty($params['membership_id'])) { + //so far $params['membership_id'] should only be set coming in from membershipBAO::create so the situation where multiple memberships + // are created off one contribution should be handled elsewhere + $entityId = $params['membership_id']; + $entityTable = 'civicrm_membership'; + } else { $entityId = $params['contribution']->id; $entityTable = 'civicrm_contribution'; } + if (CRM_Utils_Array::value('contribution_mode', $params) == 'membership') { + $isRelatedId = TRUE; + } + $entityID[] = $entityId; if (!empty($additionalParticipantId)) { $entityID += $additionalParticipantId; } // prevContribution appears to mean - original contribution object- ie copy of contribution from before the update started that is being updated - if (!CRM_Utils_Array::value('prevContribution', $params)) { + if (empty($params['prevContribution'])) { $entityID = NULL; } else { $update = TRUE; } + $statusId = $params['contribution']->contribution_status_id; + // CRM-13964 partial payment + if (CRM_Utils_Array::value('contribution_status_id', $params) == array_search('Partially paid', $contributionStatuses) + && !empty($params['partial_payment_total']) && !empty($params['partial_amount_pay'])) { + $partialAmtPay = $params['partial_amount_pay']; + $partialAmtTotal = $params['partial_payment_total']; + + $relationTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Accounts Receivable Account is' ")); + $fromFinancialAccountId = CRM_Contribute_PseudoConstant::financialAccountType($params['financial_type_id'], $relationTypeId); + $statusId = CRM_Core_OptionGroup::getValue('contribution_status', 'Completed', 'name'); + $params['total_amount'] = $partialAmtPay; + + $balanceTrxnInfo = CRM_Core_BAO_FinancialTrxn::getBalanceTrxnAmt($params['contribution']->id, $params['financial_type_id']); + if (empty($balanceTrxnInfo['trxn_id'])) { + // create new balance transaction record + $relationTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Accounts Receivable Account is' ")); + $toFinancialAccount = CRM_Contribute_PseudoConstant::financialAccountType($params['financial_type_id'], $relationTypeId); + + $balanceTrxnParams['total_amount'] = $partialAmtTotal; + $balanceTrxnParams['to_financial_account_id'] = $toFinancialAccount; + $balanceTrxnParams['contribution_id'] = $params['contribution']->id; + $balanceTrxnParams['trxn_date'] = date('YmdHis'); + $balanceTrxnParams['fee_amount'] = CRM_Utils_Array::value('fee_amount', $params); + $balanceTrxnParams['net_amount'] = CRM_Utils_Array::value('net_amount', $params); + $balanceTrxnParams['currency'] = $params['contribution']->currency; + $balanceTrxnParams['trxn_id'] = $params['contribution']->trxn_id; + $balanceTrxnParams['status_id'] = $statusId; + $balanceTrxnParams['payment_instrument_id'] = $params['contribution']->payment_instrument_id; + $balanceTrxnParams['check_number'] = CRM_Utils_Array::value('check_number', $params); + if (!empty($params['payment_processor'])) { + $balanceTrxnParams['payment_processor_id'] = $params['payment_processor']; + } + CRM_Core_BAO_FinancialTrxn::create($balanceTrxnParams); + } + } + // build line item array if its not set in $params - if (!CRM_Utils_Array::value('line_item', $params) || $additionalParticipantId) { - CRM_Price_BAO_LineItem::getLineItemArray($params, $entityID, str_replace('civicrm_', '', $entityTable)); + if (empty($params['line_item']) || $additionalParticipantId) { + CRM_Price_BAO_LineItem::getLineItemArray($params, $entityID, str_replace('civicrm_', '', $entityTable), $isRelatedId); } if (CRM_Utils_Array::value('contribution_status_id', $params) != array_search('Failed', $contributionStatuses) && @@ -2531,10 +2669,10 @@ WHERE contribution_id = %1 "; $relationTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Accounts Receivable Account is' ")); $params['to_financial_account_id'] = CRM_Contribute_PseudoConstant::financialAccountType($params['financial_type_id'], $relationTypeId); } - elseif (CRM_Utils_Array::value('payment_processor', $params)) { + elseif (!empty($params['payment_processor'])) { $params['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getFinancialAccount($params['payment_processor'], 'civicrm_payment_processor', 'financial_account_id'); } - elseif (CRM_Utils_Array::value('payment_instrument_id', $params)) { + elseif (!empty($params['payment_instrument_id'])) { $params['to_financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount($params['payment_instrument_id']); } else { @@ -2544,9 +2682,10 @@ WHERE contribution_id = %1 "; } $totalAmount = CRM_Utils_Array::value('total_amount', $params); - if (!isset($totalAmount) && CRM_Utils_Array::value('prevContribution', $params)) { + if (!isset($totalAmount) && !empty($params['prevContribution'])) { $totalAmount = $params['total_amount'] = $params['prevContribution']->total_amount; } + //build financial transaction params $trxnParams = array( 'contribution_id' => $params['contribution']->id, @@ -2557,27 +2696,43 @@ WHERE contribution_id = %1 "; 'net_amount' => CRM_Utils_Array::value('net_amount', $params), 'currency' => $params['contribution']->currency, 'trxn_id' => $params['contribution']->trxn_id, - 'status_id' => $params['contribution']->contribution_status_id, + 'status_id' => $statusId, 'payment_instrument_id' => $params['contribution']->payment_instrument_id, 'check_number' => CRM_Utils_Array::value('check_number', $params), ); - if (CRM_Utils_Array::value('payment_processor', $params)) { + if (!empty($params['payment_processor'])) { $trxnParams['payment_processor_id'] = $params['payment_processor']; } + + if (isset($fromFinancialAccountId)) { + $trxnParams['from_financial_account_id'] = $fromFinancialAccountId; + } + + // consider external values passed for recording transaction entry + if (!empty($financialTrxnValues)) { + $trxnParams = array_merge($trxnParams, $financialTrxnValues); + } + $params['trxnParams'] = $trxnParams; - if (CRM_Utils_Array::value('prevContribution', $params)) { + if (!empty($params['prevContribution'])) { $params['trxnParams']['total_amount'] = $trxnParams['total_amount'] = $params['total_amount'] = $params['prevContribution']->total_amount; $params['trxnParams']['fee_amount'] = $params['prevContribution']->fee_amount; $params['trxnParams']['net_amount'] = $params['prevContribution']->net_amount; $params['trxnParams']['trxn_id'] = $params['prevContribution']->trxn_id; $params['trxnParams']['status_id'] = $params['prevContribution']->contribution_status_id; - $params['trxnParams']['payment_instrument_id'] = $params['prevContribution']->payment_instrument_id; - $params['trxnParams']['check_number'] = $params['prevContribution']->check_number; + + + if (!(($params['prevContribution']->contribution_status_id == array_search('Pending', $contributionStatuses) + || $params['prevContribution']->contribution_status_id == array_search('In Progress', $contributionStatuses)) + && $params['contribution']->contribution_status_id == array_search('Completed', $contributionStatuses))) { + $params['trxnParams']['payment_instrument_id'] = $params['prevContribution']->payment_instrument_id; + $params['trxnParams']['check_number'] = $params['prevContribution']->check_number; + } //if financial type is changed - if (CRM_Utils_Array::value('financial_type_id', $params) && + if (!empty($params['financial_type_id']) && $params['contribution']->financial_type_id != $params['prevContribution']->financial_type_id) { $incomeTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Income Account is' ")); $oldFinancialAccount = CRM_Contribute_PseudoConstant::financialAccountType($params['prevContribution']->financial_type_id, $incomeTypeId); @@ -2590,7 +2745,7 @@ WHERE contribution_id = %1 "; } else { $lastFinancialTrxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($params['prevContribution']->id, 'DESC'); - if (CRM_Utils_Array::value('financialTrxnId', $lastFinancialTrxnId)) { + if (!empty($lastFinancialTrxnId['financialTrxnId'])) { $params['trxnParams']['to_financial_account_id'] = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialTrxn', $lastFinancialTrxnId['financialTrxnId'], 'to_financial_account_id'); } } @@ -2605,7 +2760,7 @@ WHERE contribution_id = %1 "; //Update contribution status $params['trxnParams']['status_id'] = $params['contribution']->contribution_status_id; - if (CRM_Utils_Array::value('contribution_status_id', $params) && + if (!empty($params['contribution_status_id']) && $params['prevContribution']->contribution_status_id != $params['contribution']->contribution_status_id) { //Update Financial Records self::updateFinancialAccounts($params, 'changedStatus'); @@ -2665,18 +2820,19 @@ WHERE contribution_id = %1 "; } if (!$update) { - //records finanical trxn and entity financial trxn - $financialTxn = CRM_Core_BAO_FinancialTrxn::create($trxnParams); + // records finanical trxn and entity financial trxn + // also make it available as return value + $return = $financialTxn = CRM_Core_BAO_FinancialTrxn::create($trxnParams); $params['entity_id'] = $financialTxn->id; } } // record line items and finacial items - if (!CRM_Utils_Array::value('skipLineItem', $params)) { + if (empty($params['skipLineItem'])) { CRM_Price_BAO_LineItem::processPriceSet($entityId, CRM_Utils_Array::value('line_item', $params), $params['contribution'], $entityTable, $update); } // create batch entry if batch_id is passed - if (CRM_Utils_Array::value('batch_id', $params)) { + if (!empty($params['batch_id'])) { $entityParams = array( 'batch_id' => $params['batch_id'], 'entity_table' => 'civicrm_financial_trxn', @@ -2686,18 +2842,19 @@ WHERE contribution_id = %1 "; } // when a fee is charged - if (CRM_Utils_Array::value('fee_amount', $params) && (!CRM_Utils_Array::value('prevContribution', $params) - || $params['contribution']->fee_amount != $params['prevContribution']->fee_amount) && $skipRecords) { + if (!empty($params['fee_amount']) && (empty($params['prevContribution']) || $params['contribution']->fee_amount != $params['prevContribution']->fee_amount) && $skipRecords) { CRM_Core_BAO_FinancialTrxn::recordFees($params); } - if (CRM_Utils_Array::value('prevContribution', $params) && $entityTable == 'civicrm_participant' + if (!empty($params['prevContribution']) && $entityTable == 'civicrm_participant' && $params['prevContribution']->contribution_status_id != $params['contribution']->contribution_status_id) { $eventID = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Participant', $entityId, 'event_id'); $feeLevel[] = str_replace('', '', $params['prevContribution']->amount_level); CRM_Event_BAO_Participant::createDiscountTrxn($eventID, $params, $feeLevel); } unset($params['line_item']); + + return $return; } /** @@ -2707,6 +2864,8 @@ WHERE contribution_id = %1 "; * * @param string $context update scenarios * + * @param null $skipTrxn + * * @access public * @static */ @@ -2748,7 +2907,7 @@ WHERE contribution_id = %1 "; elseif ($context == 'changePaymentInstrument') { if ($params['trxnParams']['total_amount'] < 0) { $lastFinancialTrxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($params['prevContribution']->id, 'DESC'); - if (CRM_Utils_Array::value('financialTrxnId', $lastFinancialTrxnId)) { + if (!empty($lastFinancialTrxnId['financialTrxnId'])) { $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; } @@ -2807,7 +2966,7 @@ WHERE contribution_id = %1 "; } $financialAccount = $prevfinancialItem->financial_account_id; - if (CRM_Utils_Array::value('financial_account_id', $params)) { + if (!empty($params['financial_account_id'])) { $financialAccount = $params['financial_account_id']; } @@ -2815,7 +2974,7 @@ WHERE contribution_id = %1 "; if ($params['contribution']->currency) { $currency = $params['contribution']->currency; } - if (CRM_Utils_Array::value('is_quick_config', $params)) { + if (!empty($params['is_quick_config'])) { $amount = $itemAmount; if (!$amount) { $amount = $params['total_amount']; @@ -2823,7 +2982,8 @@ WHERE contribution_id = %1 "; } else { $diff = 1; - if ($context == 'changeFinancialType' || $params['contribution']->contribution_status_id == array_search('Cancelled', $contributionStatus)) { + if ($context == 'changeFinancialType' || $params['contribution']->contribution_status_id == array_search('Cancelled', $contributionStatus) + || $params['contribution']->contribution_status_id == array_search('Refunded', $contributionStatus)) { $diff = -1; } $amount = $diff * $fieldValues['line_total']; @@ -2855,11 +3015,12 @@ WHERE contribution_id = %1 "; * * @param array $errors list of errors * + * @return bool * @access public * @static */ static function checkStatusValidation($values, &$fields, &$errors) { - if (CRM_Utils_System::isNull($values) && CRM_Utils_Array::value('id', $fields)) { + if (CRM_Utils_System::isNull($values) && !empty($fields['id'])) { $values['contribution_status_id'] = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $fields['id'], 'contribution_status_id'); if ($values['contribution_status_id'] == $fields['contribution_status_id']) { return FALSE; @@ -2903,8 +3064,10 @@ WHERE contribution_id = %1 "; * @see CRM_Core_DAO::buildOptions * * @param String $fieldName - * @param String $context: @see CRM_Core_DAO::buildOptionsContext - * @param Array $props: whatever is known about this dao object + * @param String $context : @see CRM_Core_DAO::buildOptionsContext + * @param Array $props : whatever is known about this dao object + * + * @return Array|bool */ public static function buildOptions($fieldName, $context = NULL, $props = array()) { $className = __CLASS__; @@ -2933,6 +3096,9 @@ WHERE contribution_id = %1 "; * * @param integer $financialTypeId Financial Type id * + * @param string $relationName + * + * @return array|bool * @access public * @static */ @@ -2945,6 +3111,335 @@ WHERE contribution_id = %1 "; } return FALSE; } -} + /* + * Function to record additional payment for partial and refund contributions + * + * @param integer $contributionId : is the invoice contribution id (got created after processing participant payment) + * @param array $trxnData : to take user provided input of transaction details. + * @param string $paymentType 'owed' for purpose of recording partial payments, 'refund' for purpose of recording refund payments + */ + /** + * @param $contributionId + * @param $trxnsData + * @param string $paymentType + * @param null $participantId + * + * @return null|object + */ + static function recordAdditionalPayment($contributionId, $trxnsData, $paymentType = 'owed', $participantId = NULL) { + $statusId = CRM_Core_OptionGroup::getValue('contribution_status', 'Completed', 'name'); + $getInfoOf['id'] = $contributionId; + $defaults = array(); + $contributionDAO = CRM_Contribute_BAO_Contribution::retrieve($getInfoOf, $defaults, CRM_Core_DAO::$_nullArray); + + if ($paymentType == 'owed') { + // build params for recording financial trxn entry + $params['contribution'] = $contributionDAO; + $params = array_merge($defaults, $params); + $params['skipLineItem'] = TRUE; + $params['partial_payment_total'] = $contributionDAO->total_amount; + $params['partial_amount_pay'] = $trxnsData['total_amount']; + $trxnsData['trxn_date'] = !empty($trxnsData['trxn_date']) ? $trxnsData['trxn_date'] : date('YmdHis'); + + // record the entry + $financialTrxn = CRM_Contribute_BAO_Contribution::recordFinancialAccounts($params, $trxnsData); + $relationTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Accounts Receivable Account is' ")); + $toFinancialAccount = CRM_Contribute_PseudoConstant::financialAccountType($contributionDAO->financial_type_id, $relationTypeId); + + $trxnId = CRM_Core_BAO_FinancialTrxn::getBalanceTrxnAmt($contributionId, $contributionDAO->financial_type_id); + if (!empty($trxnId)) { + $trxnId = $trxnId['trxn_id']; + } + elseif (!empty($contributionDAO->payment_instrument_id)) { + $trxnId = CRM_Financial_BAO_FinancialTypeAccount::getInstrumentFinancialAccount($contributionDAO->payment_instrument_id); + } + else { + $relationTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('financial_account_type', NULL, " AND v.name LIKE 'Asset' ")); + $queryParams = array(1 => array($relationTypeId, 'Integer')); + $trxnId = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_financial_account WHERE is_default = 1 AND financial_account_type_id = %1", $queryParams); + } + + // update statuses + // criteria for updates contribution total_amount == financial_trxns of partial_payments + $sql = "SELECT SUM(ft.total_amount) as sum_of_payments +FROM civicrm_financial_trxn ft +LEFT JOIN civicrm_entity_financial_trxn eft + ON (ft.id = eft.financial_trxn_id) +WHERE eft.entity_table = 'civicrm_contribution' + AND eft.entity_id = {$contributionId} + AND ft.to_financial_account_id != {$toFinancialAccount} + AND ft.status_id = {$statusId} +"; + $sumOfPayments = CRM_Core_DAO::singleValueQuery($sql); + + // update statuses + if ($contributionDAO->total_amount == $sumOfPayments) { + // update contribution status and + // clean cancel info (if any) if prev. contribution was updated in case of 'Refunded' => 'Completed' + $contributionDAO->contribution_status_id = $statusId; + $contributionDAO->cancel_date = 'null'; + $contributionDAO->cancel_reason = NULL; + $netAmount = !empty($trxnsData['net_amount']) ? $trxnsData['net_amount'] : $trxnsData['total_amount']; + $contributionDAO->net_amount = $contributionDAO->net_amount + $netAmount; + $contributionDAO->save(); + + //Change status of financial record too + $financialTrxn->status_id = $statusId; + $financialTrxn->save(); + + // note : not using the self::add method, + // the reason because it performs 'status change' related code execution for financial records + // which in 'Partial Paid' => 'Completed' is not useful, instead specific financial record updates + // are coded below i.e. just updating financial_item status to 'Paid' + + if ($participantId) { + // update participant status + $participantStatuses = CRM_Event_PseudoConstant::participantStatus(); + $ids = CRM_Event_BAO_Participant::getParticipantIds($contributionId); + foreach ($ids as $val) { + $participantUpdate['id'] = $val; + $participantUpdate['status_id'] = array_search('Registered', $participantStatuses); + CRM_Event_BAO_Participant::add($participantUpdate); + } + } + + // update financial item statuses + $financialItemStatus = CRM_Core_PseudoConstant::get('CRM_Financial_DAO_FinancialItem', 'status_id'); + $paidStatus = array_search('Paid', $financialItemStatus); + + $baseTrxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contributionId); + $sqlFinancialItemUpdate = " +UPDATE civicrm_financial_item fi + LEFT JOIN civicrm_entity_financial_trxn eft + ON (eft.entity_id = fi.id AND eft.entity_table = 'civicrm_financial_item') +SET status_id = {$paidStatus} +WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']}) +"; + CRM_Core_DAO::executeQuery($sqlFinancialItemUpdate); + } + } + elseif ($paymentType == 'refund') { + // build params for recording financial trxn entry + $params['contribution'] = $contributionDAO; + $params = array_merge($defaults, $params); + $params['skipLineItem'] = TRUE; + $trxnsData['trxn_date'] = !empty($trxnsData['trxn_date']) ? $trxnsData['trxn_date'] : date('YmdHis'); + $trxnsData['total_amount'] = - $trxnsData['total_amount']; + + $relationTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Accounts Receivable Account is' ")); + $trxnsData['from_financial_account_id'] = CRM_Contribute_PseudoConstant::financialAccountType($contributionDAO->financial_type_id, $relationTypeId); + $trxnsData['status_id'] = CRM_Core_OptionGroup::getValue('contribution_status', 'Refunded', 'name'); + // record the entry + $financialTrxn = CRM_Contribute_BAO_Contribution::recordFinancialAccounts($params, $trxnsData); + + // note : not using the self::add method, + // the reason because it performs 'status change' related code execution for financial records + // which in 'Pending Refund' => 'Completed' is not useful, instead specific financial record updates + // are coded below i.e. just updating financial_item status to 'Paid' + $contributionDetails = CRM_Core_DAO::setFieldValue('CRM_Contribute_BAO_Contribution', $contributionId, 'contribution_status_id', $statusId); + + // add financial item entry + $financialItemStatus = CRM_Core_PseudoConstant::get('CRM_Financial_DAO_FinancialItem', 'status_id'); + $getLine['entity_id'] = $contributionDAO->id; + $getLine['entity_table'] = 'civicrm_contribution'; + $lineItemId = CRM_Price_BAO_LineItem::retrieve($getLine, CRM_Core_DAO::$_nullArray); + if (!empty($lineItemId->id)) { + $addFinancialEntry = array( + 'transaction_date' => $financialTrxn->trxn_date, + 'contact_id' => $contributionDAO->contact_id, + 'amount' => $financialTrxn->total_amount, + 'status_id' => array_search('Paid', $financialItemStatus), + 'entity_id' => $lineItemId->id, + 'entity_table' => 'civicrm_line_item' + ); + $trxnIds['id'] = $financialTrxn->id; + CRM_Financial_BAO_FinancialItem::create($addFinancialEntry, NULL, $trxnIds); + } + if ($participantId) { + // update participant status + $participantStatuses = CRM_Event_PseudoConstant::participantStatus(); + $ids = CRM_Event_BAO_Participant::getParticipantIds($contributionId); + foreach ($ids as $val) { + $participantUpdate['id'] = $val; + $participantUpdate['status_id'] = array_search('Registered', $participantStatuses); + CRM_Event_BAO_Participant::add($participantUpdate); + } + } + } + + // activity creation + if (!empty($financialTrxn)) { + if ($participantId) { + $inputParams['id'] = $participantId; + $values = array(); + $ids = array(); + $component = 'event'; + $entityObj = CRM_Event_BAO_Participant::getValues($inputParams, $values, $ids); + $entityObj = $entityObj[$participantId]; + } + $activityType = ($paymentType == 'refund') ? 'Refund' : 'Payment'; + + self::addActivityForPayment($entityObj, $financialTrxn, $activityType, $component, $contributionId); + } + return $financialTrxn; + } + + /** + * @param $entityObj + * @param $trxnObj + * @param $activityType + * @param $component + * @param $contributionId + * + * @throws CRM_Core_Exception + */ + static function addActivityForPayment($entityObj, $trxnObj, $activityType, $component, $contributionId) { + if ($component == 'event') { + $date = CRM_Utils_Date::isoToMysql($trxnObj->trxn_date); + $paymentAmount = CRM_Utils_Money::format($trxnObj->total_amount, $trxnObj->currency); + $eventTitle = CRM_Core_DAO::getFieldValue('CRM_Event_BAO_Event', $entityObj->event_id, 'title'); + $subject = "{$paymentAmount} - Offline {$activityType} for {$eventTitle}"; + $targetCid = $entityObj->contact_id; + // source record id would be the contribution id + $srcRecId = $contributionId; + } + + // activity params + $activityParams = array( + 'source_contact_id' => $targetCid, + 'source_record_id' => $srcRecId, + 'activity_type_id' => CRM_Core_OptionGroup::getValue('activity_type', + $activityType, + 'name' + ), + 'subject' => $subject, + 'activity_date_time' => $date, + 'status_id' => CRM_Core_OptionGroup::getValue('activity_status', + 'Completed', + 'name' + ), + 'skipRecentView' => TRUE, + ); + + // create activity with target contacts + $session = CRM_Core_Session::singleton(); + $id = $session->get('userID'); + if ($id) { + $activityParams['source_contact_id'] = $id; + $activityParams['target_contact_id'][] = $targetCid; + } + CRM_Activity_BAO_Activity::create($activityParams); + } + + /** + * function to get list of payments displayed by Contribute_Page_PaymentInfo + * + * @param $id + * @param $component + * @param bool $getTrxnInfo + * @param bool $usingLineTotal + * + * @return mixed + */ + static function getPaymentInfo($id, $component, $getTrxnInfo = FALSE, $usingLineTotal = FALSE) { + if ($component == 'event') { + $entity = 'participant'; + $entityTable = 'civicrm_participant'; + $contributionId = CRM_Core_DAO::getFieldValue('CRM_Event_BAO_ParticipantPayment', $id, 'contribution_id', 'participant_id'); + + if (!$contributionId) { + if ($primaryParticipantId = CRM_Core_DAO::getFieldValue('CRM_Event_BAO_Participant', $id, 'registered_by_id')) { + $contributionId = CRM_Core_DAO::getFieldValue('CRM_Event_BAO_ParticipantPayment', $primaryParticipantId, 'contribution_id', 'participant_id'); + $id = $primaryParticipantId; + } + } + } + $total = CRM_Core_BAO_FinancialTrxn::getBalanceTrxnAmt($contributionId); + $baseTrxnId = !empty($total['trxn_id']) ? $total['trxn_id'] : NULL; + $isBalance = NULL; + if ($baseTrxnId) { + $isBalance = TRUE; + } + else { + $baseTrxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contributionId); + $baseTrxnId = $baseTrxnId['financialTrxnId']; + $isBalance = FALSE; + } + if (empty($total) || $usingLineTotal) { + // for additional participants + if ($entityTable == 'civicrm_participant') { + $ids = CRM_Event_BAO_Participant::getParticipantIds($contributionId); + $total = 0; + foreach ($ids as $val) { + $total += CRM_Price_BAO_LineItem::getLineTotal($val, $entityTable); + } + } + else { + $total = CRM_Price_BAO_LineItem::getLineTotal($id, $entityTable); + } + } + else { + $baseTrxnId = $total['trxn_id']; + $total = $total['total_amount']; + } + + $paymentBalance = CRM_Core_BAO_FinancialTrxn::getPartialPaymentWithType($id, $entity, FALSE, $total); + $contributionIsPayLater = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'is_pay_later'); + + $feeRelationTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Expense Account is' ")); + $financialTypeId = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $contributionId, 'financial_type_id'); + $feeFinancialAccount = CRM_Contribute_PseudoConstant::financialAccountType($financialTypeId, $feeRelationTypeId); + + if ($paymentBalance == 0 && $contributionIsPayLater) { + $paymentBalance = $total; + } + + $info['total'] = $total; + $info['paid'] = $total - $paymentBalance; + $info['balance'] = $paymentBalance; + $info['id'] = $id; + $info['component'] = $component; + $info['payLater'] = $contributionIsPayLater; + $rows = array(); + if ($getTrxnInfo && $baseTrxnId) { + // Need to exclude fee trxn rows so filter out rows where TO FINANCIAL ACCOUNT is expense account + $sql = " +SELECT ft.total_amount, con.financial_type_id, ft.payment_instrument_id, ft.trxn_date, ft.trxn_id, ft.status_id, ft.check_number +FROM civicrm_contribution con + LEFT JOIN civicrm_entity_financial_trxn eft ON (eft.entity_id = con.id AND eft.entity_table = 'civicrm_contribution') + LEFT JOIN civicrm_financial_trxn ft ON ft.id = eft.financial_trxn_id AND ft.to_financial_account_id != {$feeFinancialAccount} +WHERE con.id = {$contributionId} +"; + + // conditioned WHERE clause + if ($isBalance) { + // if balance trxn exists don't include details of it in transaction info + $sql .= " AND ft.id != {$baseTrxnId} "; + } + $resultDAO = CRM_Core_DAO::executeQuery($sql); + + $statuses = CRM_Contribute_PseudoConstant::contributionStatus(); + $financialTypes = CRM_Contribute_PseudoConstant::financialType(); + while($resultDAO->fetch()) { + $paidByLabel = CRM_Core_PseudoConstant::getLabel('CRM_Core_BAO_FinancialTrxn', 'payment_instrument_id', $resultDAO->payment_instrument_id); + $paidByName = CRM_Core_PseudoConstant::getName('CRM_Core_BAO_FinancialTrxn', 'payment_instrument_id', $resultDAO->payment_instrument_id); + $val = array( + 'total_amount' => $resultDAO->total_amount, + 'financial_type' => $financialTypes[$resultDAO->financial_type_id], + 'payment_instrument' => $paidByLabel, + 'receive_date' => $resultDAO->trxn_date, + 'trxn_id' => $resultDAO->trxn_id, + 'status' => $statuses[$resultDAO->status_id], + ); + if ($paidByName == 'Check') { + $val['check_number'] = $resultDAO->check_number; + } + $rows[] = $val; + } + $info['transaction'] = $rows; + } + return $info; + } +}