diff --git a/CRM/Contribute/Import/Parser/Contribution.php b/CRM/Contribute/Import/Parser/Contribution.php index 6ee91c40ef6de7d8057a847bfc19a528992da121..9aacd34faefab680ca6abdb081d34650cc4051c4 100644 --- a/CRM/Contribute/Import/Parser/Contribution.php +++ b/CRM/Contribute/Import/Parser/Contribution.php @@ -258,8 +258,7 @@ class CRM_Contribute_Import_Parser_Contribution extends CRM_Contribute_Import_Pa if (!empty($paramValues['pledge_payment'])) { $paramValues['onDuplicate'] = $onDuplicate; } - require_once 'CRM/Utils/DeprecatedUtils.php'; - $formatError = _civicrm_api3_deprecated_formatted_param($paramValues, $formatted, TRUE, $onDuplicate); + $formatError = $this->deprecatedFormatParams($paramValues, $formatted, TRUE, $onDuplicate); if ($formatError) { array_unshift($values, $formatError['error_message']); @@ -588,7 +587,7 @@ class CRM_Contribute_Import_Parser_Contribution extends CRM_Contribute_Import_Pa /** * Format input params to suit api handling. * - * Over time all the parts of _civicrm_api3_deprecated_formatted_param + * Over time all the parts of deprecatedFormatParams * and all the parts of the import function on this class that relate to * reformatting input should be moved here and tests should be added in * CRM_Contribute_Import_Parser_ContributionTest. @@ -600,7 +599,7 @@ class CRM_Contribute_Import_Parser_Contribution extends CRM_Contribute_Import_Pa $customDataType = !empty($params['contact_type']) ? $params['contact_type'] : 'Contribution'; $customFields = CRM_Core_BAO_CustomField::getFields($customDataType); // @todo call formatDateFields & move custom data handling there. - // Also note error handling for dates is currently in _civicrm_api3_deprecated_formatted_param + // Also note error handling for dates is currently in deprecatedFormatParams // we should use the error handling in formatDateFields. foreach ($params as $key => $val) { // @todo - call formatDateFields instead. @@ -631,4 +630,415 @@ class CRM_Contribute_Import_Parser_Contribution extends CRM_Contribute_Import_Pa } } + /** + * take the input parameter list as specified in the data model and + * convert it into the same format that we use in QF and BAO object + * + * @param array $params + * Associative array of property name/value. + * pairs to insert in new contact. + * @param array $values + * The reformatted properties that we can use internally. + * ' + * + * @param bool $create + * @param null $onDuplicate + * + * @return array|CRM_Error + */ + private function deprecatedFormatParams($params, &$values, $create = FALSE, $onDuplicate = NULL) { + require_once 'CRM/Utils/DeprecatedUtils.php'; + // copy all the contribution fields as is + require_once 'api/v3/utils.php'; + $fields = CRM_Contribute_DAO_Contribution::fields(); + + _civicrm_api3_store_values($fields, $params, $values); + + require_once 'CRM/Core/OptionGroup.php'; + $customFields = CRM_Core_BAO_CustomField::getFields('Contribution', FALSE, FALSE, NULL, NULL, FALSE, FALSE, FALSE); + + foreach ($params as $key => $value) { + // ignore empty values or empty arrays etc + if (CRM_Utils_System::isNull($value)) { + continue; + } + + // Handling Custom Data + if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) { + $values[$key] = $value; + $type = $customFields[$customFieldID]['html_type']; + if ($type == 'CheckBox' || $type == 'Multi-Select') { + $mulValues = explode(',', $value); + $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); + $values[$key] = []; + foreach ($mulValues as $v1) { + foreach ($customOption as $customValueID => $customLabel) { + $customValue = $customLabel['value']; + if ((strtolower($customLabel['label']) == strtolower(trim($v1))) || + (strtolower($customValue) == strtolower(trim($v1))) + ) { + if ($type == 'CheckBox') { + $values[$key][$customValue] = 1; + } + else { + $values[$key][] = $customValue; + } + } + } + } + } + elseif ($type == 'Select' || $type == 'Radio' || + ($type == 'Autocomplete-Select' && + $customFields[$customFieldID]['data_type'] == 'String' + ) + ) { + $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); + foreach ($customOption as $customFldID => $customValue) { + $val = CRM_Utils_Array::value('value', $customValue); + $label = CRM_Utils_Array::value('label', $customValue); + $label = strtolower($label); + $value = strtolower(trim($value)); + if (($value == $label) || ($value == strtolower($val))) { + $values[$key] = $val; + } + } + } + } + + switch ($key) { + case 'contribution_contact_id': + if (!CRM_Utils_Rule::integer($value)) { + return civicrm_api3_create_error("contact_id not valid: $value"); + } + $dao = new CRM_Core_DAO(); + $qParams = []; + $svq = $dao->singleValueQuery("SELECT is_deleted FROM civicrm_contact WHERE id = $value", + $qParams + ); + if (!isset($svq)) { + return civicrm_api3_create_error("Invalid Contact ID: There is no contact record with contact_id = $value."); + } + elseif ($svq == 1) { + return civicrm_api3_create_error("Invalid Contact ID: contact_id $value is a soft-deleted contact."); + } + + $values['contact_id'] = $values['contribution_contact_id']; + unset($values['contribution_contact_id']); + break; + + case 'contact_type': + // import contribution record according to select contact type + require_once 'CRM/Contact/DAO/Contact.php'; + $contactType = new CRM_Contact_DAO_Contact(); + $contactId = CRM_Utils_Array::value('contribution_contact_id', $params); + $externalId = CRM_Utils_Array::value('external_identifier', $params); + $email = CRM_Utils_Array::value('email', $params); + //when insert mode check contact id or external identifier + if ($contactId || $externalId) { + $contactType->id = $contactId; + $contactType->external_identifier = $externalId; + if ($contactType->find(TRUE)) { + if ($params['contact_type'] != $contactType->contact_type) { + return civicrm_api3_create_error("Contact Type is wrong: $contactType->contact_type"); + } + } + } + elseif ($email) { + if (!CRM_Utils_Rule::email($email)) { + return civicrm_api3_create_error("Invalid email address $email provided. Row was skipped"); + } + + // get the contact id from duplicate contact rule, if more than one contact is returned + // we should return error, since current interface allows only one-one mapping + $emailParams = ['email' => $email, 'contact_type' => $params['contact_type']]; + $checkDedupe = _civicrm_api3_deprecated_duplicate_formatted_contact($emailParams); + if (!$checkDedupe['is_error']) { + return civicrm_api3_create_error("Invalid email address(doesn't exist) $email. Row was skipped"); + } + else { + $matchingContactIds = explode(',', $checkDedupe['error_message']['params'][0]); + if (count($matchingContactIds) > 1) { + return civicrm_api3_create_error("Invalid email address(duplicate) $email. Row was skipped"); + } + elseif (count($matchingContactIds) == 1) { + $params['contribution_contact_id'] = $matchingContactIds[0]; + } + } + } + elseif (!empty($params['contribution_id']) || !empty($params['trxn_id']) || !empty($params['invoice_id'])) { + // when update mode check contribution id or trxn id or + // invoice id + $contactId = new CRM_Contribute_DAO_Contribution(); + if (!empty($params['contribution_id'])) { + $contactId->id = $params['contribution_id']; + } + elseif (!empty($params['trxn_id'])) { + $contactId->trxn_id = $params['trxn_id']; + } + elseif (!empty($params['invoice_id'])) { + $contactId->invoice_id = $params['invoice_id']; + } + if ($contactId->find(TRUE)) { + $contactType->id = $contactId->contact_id; + if ($contactType->find(TRUE)) { + if ($params['contact_type'] != $contactType->contact_type) { + return civicrm_api3_create_error("Contact Type is wrong: $contactType->contact_type"); + } + } + } + } + else { + if ($onDuplicate == CRM_Import_Parser::DUPLICATE_UPDATE) { + return civicrm_api3_create_error("Empty Contribution and Invoice and Transaction ID. Row was skipped."); + } + } + break; + + case 'receive_date': + case 'cancel_date': + case 'receipt_date': + case 'thankyou_date': + if (!CRM_Utils_Rule::dateTime($value)) { + return civicrm_api3_create_error("$key not a valid date: $value"); + } + break; + + case 'non_deductible_amount': + case 'total_amount': + case 'fee_amount': + case 'net_amount': + if (!CRM_Utils_Rule::money($value)) { + return civicrm_api3_create_error("$key not a valid amount: $value"); + } + break; + + case 'currency': + if (!CRM_Utils_Rule::currencyCode($value)) { + return civicrm_api3_create_error("currency not a valid code: $value"); + } + break; + + case 'financial_type': + require_once 'CRM/Contribute/PseudoConstant.php'; + $contriTypes = CRM_Contribute_PseudoConstant::financialType(); + foreach ($contriTypes as $val => $type) { + if (strtolower($value) == strtolower($type)) { + $values['financial_type_id'] = $val; + break; + } + } + if (empty($values['financial_type_id'])) { + return civicrm_api3_create_error("Financial Type is not valid: $value"); + } + break; + + case 'payment_instrument': + require_once 'CRM/Core/PseudoConstant.php'; + $values['payment_instrument_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', $value); + if (empty($values['payment_instrument_id'])) { + return civicrm_api3_create_error("Payment Instrument is not valid: $value"); + } + break; + + case 'contribution_status_id': + require_once 'CRM/Core/PseudoConstant.php'; + if (!$values['contribution_status_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $value)) { + return civicrm_api3_create_error("Contribution Status is not valid: $value"); + } + break; + + case 'soft_credit': + // import contribution record according to select contact type + // validate contact id and external identifier. + $value[$key] = $mismatchContactType = $softCreditContactIds = ''; + if (isset($params[$key]) && is_array($params[$key])) { + foreach ($params[$key] as $softKey => $softParam) { + $contactId = CRM_Utils_Array::value('contact_id', $softParam); + $externalId = CRM_Utils_Array::value('external_identifier', $softParam); + $email = CRM_Utils_Array::value('email', $softParam); + if ($contactId || $externalId) { + require_once 'CRM/Contact/DAO/Contact.php'; + $contact = new CRM_Contact_DAO_Contact(); + $contact->id = $contactId; + $contact->external_identifier = $externalId; + $errorMsg = NULL; + if (!$contact->find(TRUE)) { + $field = $contactId ? ts('Contact ID') : ts('External ID'); + $errorMsg = ts("Soft Credit %1 - %2 doesn't exist. Row was skipped.", + [1 => $field, 2 => $contactId ? $contactId : $externalId]); + } + + if ($errorMsg) { + return civicrm_api3_create_error($errorMsg); + } + + // finally get soft credit contact id. + $values[$key][$softKey] = $softParam; + $values[$key][$softKey]['contact_id'] = $contact->id; + } + elseif ($email) { + if (!CRM_Utils_Rule::email($email)) { + return civicrm_api3_create_error("Invalid email address $email provided for Soft Credit. Row was skipped"); + } + + // get the contact id from duplicate contact rule, if more than one contact is returned + // we should return error, since current interface allows only one-one mapping + $emailParams = ['email' => $email, 'contact_type' => $params['contact_type']]; + $checkDedupe = _civicrm_api3_deprecated_duplicate_formatted_contact($emailParams); + if (!$checkDedupe['is_error']) { + return civicrm_api3_create_error("Invalid email address(doesn't exist) $email for Soft Credit. Row was skipped"); + } + else { + $matchingContactIds = explode(',', $checkDedupe['error_message']['params'][0]); + if (count($matchingContactIds) > 1) { + return civicrm_api3_create_error("Invalid email address(duplicate) $email for Soft Credit. Row was skipped"); + } + elseif (count($matchingContactIds) == 1) { + $contactId = $matchingContactIds[0]; + unset($softParam['email']); + $values[$key][$softKey] = $softParam + ['contact_id' => $contactId]; + } + } + } + } + } + break; + + case 'pledge_payment': + case 'pledge_id': + + // giving respect to pledge_payment flag. + if (empty($params['pledge_payment'])) { + continue; + } + + // get total amount of from import fields + $totalAmount = CRM_Utils_Array::value('total_amount', $params); + + $onDuplicate = CRM_Utils_Array::value('onDuplicate', $params); + + // we need to get contact id $contributionContactID to + // retrieve pledge details as well as to validate pledge ID + + // first need to check for update mode + if ($onDuplicate == CRM_Import_Parser::DUPLICATE_UPDATE && + ($params['contribution_id'] || $params['trxn_id'] || $params['invoice_id']) + ) { + $contribution = new CRM_Contribute_DAO_Contribution(); + if ($params['contribution_id']) { + $contribution->id = $params['contribution_id']; + } + elseif ($params['trxn_id']) { + $contribution->trxn_id = $params['trxn_id']; + } + elseif ($params['invoice_id']) { + $contribution->invoice_id = $params['invoice_id']; + } + + if ($contribution->find(TRUE)) { + $contributionContactID = $contribution->contact_id; + if (!$totalAmount) { + $totalAmount = $contribution->total_amount; + } + } + else { + return civicrm_api3_create_error('No match found for specified contact in pledge payment data. Row was skipped.'); + } + } + else { + // first get the contact id for given contribution record. + if (!empty($params['contribution_contact_id'])) { + $contributionContactID = $params['contribution_contact_id']; + } + elseif (!empty($params['external_identifier'])) { + require_once 'CRM/Contact/DAO/Contact.php'; + $contact = new CRM_Contact_DAO_Contact(); + $contact->external_identifier = $params['external_identifier']; + if ($contact->find(TRUE)) { + $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $contact->id; + } + else { + return civicrm_api3_create_error('No match found for specified contact in pledge payment data. Row was skipped.'); + } + } + else { + // we need to get contribution contact using de dupe + $error = _civicrm_api3_deprecated_check_contact_dedupe($params); + + if (isset($error['error_message']['params'][0])) { + $matchedIDs = explode(',', $error['error_message']['params'][0]); + + // check if only one contact is found + if (count($matchedIDs) > 1) { + return civicrm_api3_create_error($error['error_message']['message']); + } + else { + $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $matchedIDs[0]; + } + } + else { + return civicrm_api3_create_error('No match found for specified contact in contribution data. Row was skipped.'); + } + } + } + + if (!empty($params['pledge_id'])) { + if (CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_Pledge', $params['pledge_id'], 'contact_id') != $contributionContactID) { + return civicrm_api3_create_error('Invalid Pledge ID provided. Contribution row was skipped.'); + } + $values['pledge_id'] = $params['pledge_id']; + } + else { + // check if there are any pledge related to this contact, with payments pending or in progress + require_once 'CRM/Pledge/BAO/Pledge.php'; + $pledgeDetails = CRM_Pledge_BAO_Pledge::getContactPledges($contributionContactID); + + if (empty($pledgeDetails)) { + return civicrm_api3_create_error('No open pledges found for this contact. Contribution row was skipped.'); + } + elseif (count($pledgeDetails) > 1) { + return civicrm_api3_create_error('This contact has more than one open pledge. Unable to determine which pledge to apply the contribution to. Contribution row was skipped.'); + } + + // this mean we have only one pending / in progress pledge + $values['pledge_id'] = $pledgeDetails[0]; + } + + // we need to check if oldest payment amount equal to contribution amount + require_once 'CRM/Pledge/BAO/PledgePayment.php'; + $pledgePaymentDetails = CRM_Pledge_BAO_PledgePayment::getOldestPledgePayment($values['pledge_id']); + + if ($pledgePaymentDetails['amount'] == $totalAmount) { + $values['pledge_payment_id'] = $pledgePaymentDetails['id']; + } + else { + return civicrm_api3_create_error('Contribution and Pledge Payment amount mismatch for this record. Contribution row was skipped.'); + } + break; + + default: + break; + } + } + + if (array_key_exists('note', $params)) { + $values['note'] = $params['note']; + } + + if ($create) { + // CRM_Contribute_BAO_Contribution::add() handles contribution_source + // So, if $values contains contribution_source, convert it to source + $changes = ['contribution_source' => 'source']; + + foreach ($changes as $orgVal => $changeVal) { + if (isset($values[$orgVal])) { + $values[$changeVal] = $values[$orgVal]; + unset($values[$orgVal]); + } + } + } + + return NULL; + } + } diff --git a/CRM/Utils/DeprecatedUtils.php b/CRM/Utils/DeprecatedUtils.php index 5d8e0e1bec20e1108a278f0c5a8a2c94ed9556c0..3ed6d8f86235bb08c643aa066dedccf50c6022cb 100644 --- a/CRM/Utils/DeprecatedUtils.php +++ b/CRM/Utils/DeprecatedUtils.php @@ -40,416 +40,6 @@ require_once 'api/v3/utils.php'; -/** - * take the input parameter list as specified in the data model and - * convert it into the same format that we use in QF and BAO object - * - * @param array $params - * Associative array of property name/value. - * pairs to insert in new contact. - * @param array $values - * The reformatted properties that we can use internally. - * ' - * - * @param bool $create - * @param null $onDuplicate - * - * @return array|CRM_Error - */ -function _civicrm_api3_deprecated_formatted_param($params, &$values, $create = FALSE, $onDuplicate = NULL) { - // copy all the contribution fields as is - - $fields = CRM_Contribute_DAO_Contribution::fields(); - - _civicrm_api3_store_values($fields, $params, $values); - - require_once 'CRM/Core/OptionGroup.php'; - $customFields = CRM_Core_BAO_CustomField::getFields('Contribution', FALSE, FALSE, NULL, NULL, FALSE, FALSE, FALSE); - - foreach ($params as $key => $value) { - // ignore empty values or empty arrays etc - if (CRM_Utils_System::isNull($value)) { - continue; - } - - // Handling Custom Data - if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) { - $values[$key] = $value; - $type = $customFields[$customFieldID]['html_type']; - if ($type == 'CheckBox' || $type == 'Multi-Select') { - $mulValues = explode(',', $value); - $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); - $values[$key] = []; - foreach ($mulValues as $v1) { - foreach ($customOption as $customValueID => $customLabel) { - $customValue = $customLabel['value']; - if ((strtolower($customLabel['label']) == strtolower(trim($v1))) || - (strtolower($customValue) == strtolower(trim($v1))) - ) { - if ($type == 'CheckBox') { - $values[$key][$customValue] = 1; - } - else { - $values[$key][] = $customValue; - } - } - } - } - } - elseif ($type == 'Select' || $type == 'Radio' || - ($type == 'Autocomplete-Select' && - $customFields[$customFieldID]['data_type'] == 'String' - ) - ) { - $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); - foreach ($customOption as $customFldID => $customValue) { - $val = CRM_Utils_Array::value('value', $customValue); - $label = CRM_Utils_Array::value('label', $customValue); - $label = strtolower($label); - $value = strtolower(trim($value)); - if (($value == $label) || ($value == strtolower($val))) { - $values[$key] = $val; - } - } - } - } - - switch ($key) { - case 'contribution_contact_id': - if (!CRM_Utils_Rule::integer($value)) { - return civicrm_api3_create_error("contact_id not valid: $value"); - } - $dao = new CRM_Core_DAO(); - $qParams = []; - $svq = $dao->singleValueQuery("SELECT is_deleted FROM civicrm_contact WHERE id = $value", - $qParams - ); - if (!isset($svq)) { - return civicrm_api3_create_error("Invalid Contact ID: There is no contact record with contact_id = $value."); - } - elseif ($svq == 1) { - return civicrm_api3_create_error("Invalid Contact ID: contact_id $value is a soft-deleted contact."); - } - - $values['contact_id'] = $values['contribution_contact_id']; - unset($values['contribution_contact_id']); - break; - - case 'contact_type': - // import contribution record according to select contact type - require_once 'CRM/Contact/DAO/Contact.php'; - $contactType = new CRM_Contact_DAO_Contact(); - $contactId = CRM_Utils_Array::value('contribution_contact_id', $params); - $externalId = CRM_Utils_Array::value('external_identifier', $params); - $email = CRM_Utils_Array::value('email', $params); - //when insert mode check contact id or external identifier - if ($contactId || $externalId) { - $contactType->id = $contactId; - $contactType->external_identifier = $externalId; - if ($contactType->find(TRUE)) { - if ($params['contact_type'] != $contactType->contact_type) { - return civicrm_api3_create_error("Contact Type is wrong: $contactType->contact_type"); - } - } - } - elseif ($email) { - if (!CRM_Utils_Rule::email($email)) { - return civicrm_api3_create_error("Invalid email address $email provided. Row was skipped"); - } - - // get the contact id from duplicate contact rule, if more than one contact is returned - // we should return error, since current interface allows only one-one mapping - $emailParams = ['email' => $email, 'contact_type' => $params['contact_type']]; - $checkDedupe = _civicrm_api3_deprecated_duplicate_formatted_contact($emailParams); - if (!$checkDedupe['is_error']) { - return civicrm_api3_create_error("Invalid email address(doesn't exist) $email. Row was skipped"); - } - else { - $matchingContactIds = explode(',', $checkDedupe['error_message']['params'][0]); - if (count($matchingContactIds) > 1) { - return civicrm_api3_create_error("Invalid email address(duplicate) $email. Row was skipped"); - } - elseif (count($matchingContactIds) == 1) { - $params['contribution_contact_id'] = $matchingContactIds[0]; - } - } - } - elseif (!empty($params['contribution_id']) || !empty($params['trxn_id']) || !empty($params['invoice_id'])) { - // when update mode check contribution id or trxn id or - // invoice id - $contactId = new CRM_Contribute_DAO_Contribution(); - if (!empty($params['contribution_id'])) { - $contactId->id = $params['contribution_id']; - } - elseif (!empty($params['trxn_id'])) { - $contactId->trxn_id = $params['trxn_id']; - } - elseif (!empty($params['invoice_id'])) { - $contactId->invoice_id = $params['invoice_id']; - } - if ($contactId->find(TRUE)) { - $contactType->id = $contactId->contact_id; - if ($contactType->find(TRUE)) { - if ($params['contact_type'] != $contactType->contact_type) { - return civicrm_api3_create_error("Contact Type is wrong: $contactType->contact_type"); - } - } - } - } - else { - if ($onDuplicate == CRM_Import_Parser::DUPLICATE_UPDATE) { - return civicrm_api3_create_error("Empty Contribution and Invoice and Transaction ID. Row was skipped."); - } - } - break; - - case 'receive_date': - case 'cancel_date': - case 'receipt_date': - case 'thankyou_date': - if (!CRM_Utils_Rule::dateTime($value)) { - return civicrm_api3_create_error("$key not a valid date: $value"); - } - break; - - case 'non_deductible_amount': - case 'total_amount': - case 'fee_amount': - case 'net_amount': - if (!CRM_Utils_Rule::money($value)) { - return civicrm_api3_create_error("$key not a valid amount: $value"); - } - break; - - case 'currency': - if (!CRM_Utils_Rule::currencyCode($value)) { - return civicrm_api3_create_error("currency not a valid code: $value"); - } - break; - - case 'financial_type': - require_once 'CRM/Contribute/PseudoConstant.php'; - $contriTypes = CRM_Contribute_PseudoConstant::financialType(); - foreach ($contriTypes as $val => $type) { - if (strtolower($value) == strtolower($type)) { - $values['financial_type_id'] = $val; - break; - } - } - if (empty($values['financial_type_id'])) { - return civicrm_api3_create_error("Financial Type is not valid: $value"); - } - break; - - case 'payment_instrument': - require_once 'CRM/Core/PseudoConstant.php'; - $values['payment_instrument_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', $value); - if (empty($values['payment_instrument_id'])) { - return civicrm_api3_create_error("Payment Instrument is not valid: $value"); - } - break; - - case 'contribution_status_id': - require_once 'CRM/Core/PseudoConstant.php'; - if (!$values['contribution_status_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $value)) { - return civicrm_api3_create_error("Contribution Status is not valid: $value"); - } - break; - - case 'soft_credit': - // import contribution record according to select contact type - // validate contact id and external identifier. - $value[$key] = $mismatchContactType = $softCreditContactIds = ''; - if (isset($params[$key]) && is_array($params[$key])) { - foreach ($params[$key] as $softKey => $softParam) { - $contactId = CRM_Utils_Array::value('contact_id', $softParam); - $externalId = CRM_Utils_Array::value('external_identifier', $softParam); - $email = CRM_Utils_Array::value('email', $softParam); - if ($contactId || $externalId) { - require_once 'CRM/Contact/DAO/Contact.php'; - $contact = new CRM_Contact_DAO_Contact(); - $contact->id = $contactId; - $contact->external_identifier = $externalId; - $errorMsg = NULL; - if (!$contact->find(TRUE)) { - $field = $contactId ? ts('Contact ID') : ts('External ID'); - $errorMsg = ts("Soft Credit %1 - %2 doesn't exist. Row was skipped.", - [1 => $field, 2 => $contactId ? $contactId : $externalId]); - } - - if ($errorMsg) { - return civicrm_api3_create_error($errorMsg); - } - - // finally get soft credit contact id. - $values[$key][$softKey] = $softParam; - $values[$key][$softKey]['contact_id'] = $contact->id; - } - elseif ($email) { - if (!CRM_Utils_Rule::email($email)) { - return civicrm_api3_create_error("Invalid email address $email provided for Soft Credit. Row was skipped"); - } - - // get the contact id from duplicate contact rule, if more than one contact is returned - // we should return error, since current interface allows only one-one mapping - $emailParams = ['email' => $email, 'contact_type' => $params['contact_type']]; - $checkDedupe = _civicrm_api3_deprecated_duplicate_formatted_contact($emailParams); - if (!$checkDedupe['is_error']) { - return civicrm_api3_create_error("Invalid email address(doesn't exist) $email for Soft Credit. Row was skipped"); - } - else { - $matchingContactIds = explode(',', $checkDedupe['error_message']['params'][0]); - if (count($matchingContactIds) > 1) { - return civicrm_api3_create_error("Invalid email address(duplicate) $email for Soft Credit. Row was skipped"); - } - elseif (count($matchingContactIds) == 1) { - $contactId = $matchingContactIds[0]; - unset($softParam['email']); - $values[$key][$softKey] = $softParam + ['contact_id' => $contactId]; - } - } - } - } - } - break; - - case 'pledge_payment': - case 'pledge_id': - - // giving respect to pledge_payment flag. - if (empty($params['pledge_payment'])) { - continue; - } - - // get total amount of from import fields - $totalAmount = CRM_Utils_Array::value('total_amount', $params); - - $onDuplicate = CRM_Utils_Array::value('onDuplicate', $params); - - // we need to get contact id $contributionContactID to - // retrieve pledge details as well as to validate pledge ID - - // first need to check for update mode - if ($onDuplicate == CRM_Import_Parser::DUPLICATE_UPDATE && - ($params['contribution_id'] || $params['trxn_id'] || $params['invoice_id']) - ) { - $contribution = new CRM_Contribute_DAO_Contribution(); - if ($params['contribution_id']) { - $contribution->id = $params['contribution_id']; - } - elseif ($params['trxn_id']) { - $contribution->trxn_id = $params['trxn_id']; - } - elseif ($params['invoice_id']) { - $contribution->invoice_id = $params['invoice_id']; - } - - if ($contribution->find(TRUE)) { - $contributionContactID = $contribution->contact_id; - if (!$totalAmount) { - $totalAmount = $contribution->total_amount; - } - } - else { - return civicrm_api3_create_error('No match found for specified contact in pledge payment data. Row was skipped.'); - } - } - else { - // first get the contact id for given contribution record. - if (!empty($params['contribution_contact_id'])) { - $contributionContactID = $params['contribution_contact_id']; - } - elseif (!empty($params['external_identifier'])) { - require_once 'CRM/Contact/DAO/Contact.php'; - $contact = new CRM_Contact_DAO_Contact(); - $contact->external_identifier = $params['external_identifier']; - if ($contact->find(TRUE)) { - $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $contact->id; - } - else { - return civicrm_api3_create_error('No match found for specified contact in pledge payment data. Row was skipped.'); - } - } - else { - // we need to get contribution contact using de dupe - $error = _civicrm_api3_deprecated_check_contact_dedupe($params); - - if (isset($error['error_message']['params'][0])) { - $matchedIDs = explode(',', $error['error_message']['params'][0]); - - // check if only one contact is found - if (count($matchedIDs) > 1) { - return civicrm_api3_create_error($error['error_message']['message']); - } - else { - $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $matchedIDs[0]; - } - } - else { - return civicrm_api3_create_error('No match found for specified contact in contribution data. Row was skipped.'); - } - } - } - - if (!empty($params['pledge_id'])) { - if (CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_Pledge', $params['pledge_id'], 'contact_id') != $contributionContactID) { - return civicrm_api3_create_error('Invalid Pledge ID provided. Contribution row was skipped.'); - } - $values['pledge_id'] = $params['pledge_id']; - } - else { - // check if there are any pledge related to this contact, with payments pending or in progress - require_once 'CRM/Pledge/BAO/Pledge.php'; - $pledgeDetails = CRM_Pledge_BAO_Pledge::getContactPledges($contributionContactID); - - if (empty($pledgeDetails)) { - return civicrm_api3_create_error('No open pledges found for this contact. Contribution row was skipped.'); - } - elseif (count($pledgeDetails) > 1) { - return civicrm_api3_create_error('This contact has more than one open pledge. Unable to determine which pledge to apply the contribution to. Contribution row was skipped.'); - } - - // this mean we have only one pending / in progress pledge - $values['pledge_id'] = $pledgeDetails[0]; - } - - // we need to check if oldest payment amount equal to contribution amount - require_once 'CRM/Pledge/BAO/PledgePayment.php'; - $pledgePaymentDetails = CRM_Pledge_BAO_PledgePayment::getOldestPledgePayment($values['pledge_id']); - - if ($pledgePaymentDetails['amount'] == $totalAmount) { - $values['pledge_payment_id'] = $pledgePaymentDetails['id']; - } - else { - return civicrm_api3_create_error('Contribution and Pledge Payment amount mismatch for this record. Contribution row was skipped.'); - } - break; - - default: - break; - } - } - - if (array_key_exists('note', $params)) { - $values['note'] = $params['note']; - } - - if ($create) { - // CRM_Contribute_BAO_Contribution::add() handles contribution_source - // So, if $values contains contribution_source, convert it to source - $changes = ['contribution_source' => 'source']; - - foreach ($changes as $orgVal => $changeVal) { - if (isset($values[$orgVal])) { - $values[$changeVal] = $values[$orgVal]; - unset($values[$orgVal]); - } - } - } - - return NULL; -} - /** * Check duplicate contacts based on de-dupe parameters. *