diff --git a/CRM/Core/Payment/Backer.php b/CRM/Core/Payment/Backer.php index f57503dee..aa2be1993 100644 --- a/CRM/Core/Payment/Backer.php +++ b/CRM/Core/Payment/Backer.php @@ -310,7 +310,6 @@ function processContribution($jsonString, &$contributionResult) { civicrm_api('contact', 'create', $contact); } - // process recurring or contribution if ($contactId) { $contributionResult['contactId'] = $contactId; // create additional contact if needed @@ -340,49 +339,66 @@ function processContribution($jsonString, &$contributionResult) { sort($foundDupes); $additionalContactId = reset($foundDupes); } - else { - $dedupeParams = array( - 'last_name' => $params['additional']['last_name'], - 'first_name' => $params['additional']['first_name'], - ); - $dedupeParams = CRM_Dedupe_Finder::formatParams($dedupeParams, 'Individual'); - $foundDupes = CRM_Dedupe_Finder::dupesByRules( - $dedupeParams, - 'Individual', - 'Strict', - array(), - array( - array('table' => 'civicrm_contact', 'field' => 'sort_name', 'weight' => 10), - ), - 10 - ); - } if ($additionalContactId) { $params['additional']['id'] = $additionalContactId; - // only process address + $otherLocationTypeId = array_search('Other', $locationType); + $addContact = array(); + + // check addr exists $blockValue = $params['additional']['address'][0]; $blockValue['contact_id'] = $additionalContactId; CRM_Core_BAO_Address::valueExists($blockValue); if (empty($blockValue['id'])) { - $otherLocationTypeId = array_search('Other', $locationType); - $billingLocationTypeId = array_search('Billing', $locationType); - if ($otherLocationTypeId && $billingLocationTypeId) { - $existsBillingAddr = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_address WHERE location_type_id = '$billingLocationTypeId' AND contact_id = %1", array( + if ($otherLocationTypeId) { + $existsAddr = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_address WHERE contact_id = %1", array( + 1 => array($additionalContactId, 'Integer') + )); + if ($existsAddr) { + $params['additional']['address'][0]['location_type_id'] = $otherLocationTypeId; + } + } + $addContact['address'] = $params['additional']['address']; + } + + // check phone exists + $blockValue = $params['additional']['phone'][0]; + $blockValue['contact_id'] = $additionalContactId; + CRM_Core_BAO_Phone::valueExists($blockValue); + if (empty($blockValue['id'])) { + if ($otherLocationTypeId) { + $existsPhone = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_phone WHERE contact_id = %1", array( + 1 => array($additionalContactId, 'Integer') + )); + if ($existsPhone) { + $params['additional']['phone'][0]['location_type_id'] = $otherLocationTypeId; + $params['additional']['phone'][0]['is_primary'] = 0; + } + } + $addContact['phone'] = $params['additional']['phone']; + } + + // check email exists + $blockValue = $params['additional']['email'][0]; + $blockValue['contact_id'] = $additionalContactId; + CRM_Core_BAO_Email::valueExists($blockValue); + if (empty($blockValue['id'])) { + if ($otherLocationTypeId) { + $existsEmail = CRM_Core_DAO::singleValueQuery("SELECT id FROM civicrm_email WHERE contact_id = %1", array( 1 => array($additionalContactId, 'Integer') )); - if ($existsBillingAddr) { - CRM_Core_DAO::executeQuery("UPDATE civicrm_address SET location_type_id = '$otherLocationTypeId' WHERE id = %1", array( - 1 => array($existsBillingAddr, 'Integer') - )); + if ($existsEmail) { + $params['additional']['email'][0]['location_type_id'] = $otherLocationTypeId; + $params['additional']['email'][0]['is_primary'] = 0; } } - $addContact = array( - 'version' => 3, - 'id' => $additionalContactId, - 'address' => $params['additional']['address'], - 'log_data' => ts('Updated contact').'-'.ts('Backer Auto Import'), - ); - // log exists + $addContact['email'] = $params['additional']['email']; + } + + // only update contact when value different + if (!empty($addContact)) { + $addContact['id'] = $additionalContactId; + $addContact['version'] = 3; + $addContact['log_data'] = ts('Updated contact').'-'.ts('Backer Auto Import'); civicrm_api('contact', 'create', $addContact); } } @@ -394,7 +410,7 @@ function processContribution($jsonString, &$contributionResult) { $additionalContactId = $result['id']; } - if ($additionalContactId) { + if ($additionalContactId && $additionalContactId != $contactId) { $addContactParams = array( 'version' => 3, 'contact_id_a' => $contactId, @@ -578,6 +594,9 @@ public static function formatContact($json, &$params) { 2 => array($countryId, 'Integer'), )); } + + // #40812#note-10 , do not remove recipient data in form data stage + $params['additional'] = array(); $address = array( 'country' => ($json['recipient']['recipient_country'] == 'TW') ? 'Taiwan' : '', 'postal_code' => $json['recipient']['recipient_postal_code'] ? $json['recipient']['recipient_postal_code'] : '', @@ -586,47 +605,41 @@ public static function formatContact($json, &$params) { 'street_address' => $json['recipient']['recipient_address'] ? $json['recipient']['recipient_address'] : '', 'location_type_id' => array_search('Home', $locationType), ); - if (trim($json['recipient']['recipient_name']) == trim($json['user']['name'])) { - $params['address'][] = $address; + $addName = self::explodeName(trim($json['recipient']['recipient_name'])); + if ($addName === FALSE) { + $addName= array( + '', // sure name + $json['recipient']['recipient_name'], // given name + ); } - else { - $params['additional'] = array(); - $addName = self::explodeName(trim($json['recipient']['recipient_name'])); - if ($addName === FALSE) { - $addName= array( - '', // sure name - $json['recipient']['recipient_name'], // given name - ); - } - $params['additional'] = array( - 'contact_type' => 'Individual', - 'last_name' => $addName[0], - 'first_name' => $addName[1], + $params['additional'] = array( + 'contact_type' => 'Individual', + 'last_name' => $addName[0], + 'first_name' => $addName[1], + ); + if ($json['recipient']['recipient_contact_email'] && CRM_Utils_Rule::email(trim($json['recipient']['recipient_contact_email']))) { + $params['additional']['email'][0] = array( + 'email' => trim($json['recipient']['recipient_contact_email']), + 'location_type_id' => array_search('Home', $locationType), + 'is_primary' => 1, + 'append' => TRUE, ); - if ($json['recipient']['recipient_contact_email'] && CRM_Utils_Rule::email(trim($json['recipient']['recipient_contact_email']))) { - $params['additional']['email'][0] = array( - 'email' => trim($json['recipient']['recipient_contact_email']), - 'location_type_id' => array_search('Home', $locationType), - 'is_primary' => 1, - 'append' => TRUE, - ); - } - if (!empty($json['recipient']['recipient_cellphone'])) { - $params['additional']['phone'][0] = array( - 'phone' => trim($json['recipient']['recipient_cellphone']), - 'phone_type_id' => 5, // other - 'location_type_id' => array_search('Home', $locationType), - 'is_primary' => 1, - 'append' => TRUE, - ); - $addPhone = self::validateMobilePhone(trim($json['recipient']['recipient_cellphone'])); - if ($addPhone) { - $params['additional']['phone'][0]['phone_type_id'] = 2; - $params['additional']['phone'][0]['phone'] = $addPhone; - } + } + if (!empty($json['recipient']['recipient_cellphone'])) { + $params['additional']['phone'][0] = array( + 'phone' => trim($json['recipient']['recipient_cellphone']), + 'phone_type_id' => 5, // other + 'location_type_id' => array_search('Home', $locationType), + 'is_primary' => 1, + 'append' => TRUE, + ); + $addPhone = self::validateMobilePhone(trim($json['recipient']['recipient_cellphone'])); + if ($addPhone) { + $params['additional']['phone'][0]['phone_type_id'] = 2; + $params['additional']['phone'][0]['phone'] = $addPhone; } - $params['additional']['address'][0] = $address; } + $params['additional']['address'][0] = $address; } public static function formatRecurring($json, &$params) { diff --git a/tests/phpunit/CRM/Core/Payment/BackerTest.php b/tests/phpunit/CRM/Core/Payment/BackerTest.php index e62b50acf..1d21005af 100644 --- a/tests/phpunit/CRM/Core/Payment/BackerTest.php +++ b/tests/phpunit/CRM/Core/Payment/BackerTest.php @@ -536,20 +536,26 @@ function testBackerIPN(){ $this->assertEquals($formatted['phone'][0]['phone'], $result['values'][$result['id']]['phone']); } - function testBackerAdditionAddress(){ + function testBackerAdditionalContact(){ $now = time(); $contributionResult = NULL; - // prepare data + // case 1, this should create additional contact $json = json_decode($this->_json[1], TRUE); - $json['recipient']['recipient_name'] = '王小明'; + $json['transaction']['trade_no'] = CRM_Utils_String::createRandom(15); + $json['user']['id'] = mt_rand(100000, 999999); + $json['user']['email'] = 'admintest.main1@eaxmple.com'; + $json['user']['name'] = '張小弟'; + $json['user']['cellphone'] = '+886912445667'; + $json['recipient']['recipient_name'] = '張大媽'; + $json['recipient']['recipient_contact_email'] = 'admintest.other1@eaxmple.com'; + $json['recipient']['recipient_cellphone'] = '0933444555'; $json = json_encode($json); $formatted = CRM_Core_Payment_Backer::formatParams($json); - // run - $createdContributionId = $this->_processor->processContribution($json, $contributionResult); + $this->_processor->processContribution($json, $contributionResult); $createdContributionId = $contributionResult['contributionId']; - $this->assertNotEmpty($createdContributionId, "In line " . __LINE__); + $this->assertNotEmpty($createdContributionId, "Contribution not created. In line " . __LINE__); $contactId = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $createdContributionId, 'contact_id'); $params = array( @@ -561,18 +567,110 @@ function testBackerAdditionAddress(){ $this->assertAPISuccess($result); $this->assertGreaterThan(0 , $result['count'], 'Additional contact count should greater than zero. In line '.__LINE__); $additionalContact = reset($result['values']); - $additionalContactId = $additionalContact['contact_id']; + $additionalContactId1 = $additionalContact['contact_id']; $this->assertEquals($formatted['additional']['address'][0]['street_address'], $additionalContact['street_address']); + $this->assertEquals($formatted['additional']['phone'][0]['phone'], $additionalContact['phone']); + $this->assertEquals($formatted['additional']['email'][0]['email'], $additionalContact['email']); $params = array( 'version' => 3, 'contact_id_a' => $contactId, - 'contact_id_b' => $additionalContactId, + 'contact_id_b' => $additionalContactId1, 'relationship_type_id' => $this->_rtypeId, ); $relation = civicrm_api('contact', 'get', $params); $this->assertAPISuccess($relation); $this->assertGreaterThan(0 , $relation['count'], 'Relationship result should greater than zero. In line '.__LINE__); + + // duplicate case 1, won't add another contact + $formatted = CRM_Core_Payment_Backer::formatParams($json); + $this->_processor->processContribution($json, $contributionResult); + $params = array( + 'version' => 3, + 'last_name' => $formatted['additional']['last_name'], + 'first_name' => $formatted['additional']['first_name'], + ); + $result = civicrm_api('contact', 'get', $params); + $this->assertAPISuccess($result); + $this->assertEquals(1 , $result['count'], 'Additional contact count should be 1. In line '.__LINE__); + + $params = array( + 'version' => 3, + 'last_name' => $formatted['additional']['last_name'], + 'first_name' => $formatted['additional']['first_name'], + ); + $result = civicrm_api('contact', 'get', $params); + $this->assertAPISuccess($result); + $this->assertGreaterThan(0 , $result['count'], 'Additional contact count should greater than zero. In line '.__LINE__); + $additionalContact = reset($result['values']); + $additionalContactId1 = $additionalContact['contact_id']; + $this->assertEquals($formatted['additional']['address'][0]['street_address'], $additionalContact['street_address']); + $this->assertEquals($formatted['additional']['phone'][0]['phone'], $additionalContact['phone']); + $this->assertEquals($formatted['additional']['email'][0]['email'], $additionalContact['email']); + + // case 2, additional contact shouldn't be create again when missing email + $json = json_decode($this->_json[1], TRUE); + $json['transaction']['trade_no'] = CRM_Utils_String::createRandom(15); + $json['user']['id'] = mt_rand(100000, 999999); + $json['user']['email'] = 'admintest.main2@eaxmple.com'; + $json['user']['name'] = '陳小刀'; + $json['user']['cellphone'] = '+886900111222'; + $json['recipient']['recipient_name'] = '陳小刀'; + unset($json['recipient']['recipient_contact_email']); + $json['recipient']['recipient_cellphone'] = '0900111222'; + $json = json_encode($json); + $formatted = CRM_Core_Payment_Backer::formatParams($json); + + $contributionResult = NULL; + $this->_processor->processContribution($json, $contributionResult); + $createdContributionId = $contributionResult['contributionId']; + $this->assertNotEmpty($createdContributionId, "Contribution not created. In line " . __LINE__); + $contactId = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $createdContributionId, 'contact_id'); + + $params = array( + 'version' => 3, + 'last_name' => $formatted['additional']['last_name'], + 'first_name' => $formatted['additional']['first_name'], + ); + $result = civicrm_api('contact', 'get', $params); + $this->assertAPISuccess($result); + $this->assertEquals(1 , $result['count'], 'Additional contact count should be only 1. In line '.__LINE__); + $additionalContact = reset($result['values']); + $additionalContactId2 = $additionalContact['contact_id']; + $this->assertEquals($additionalContactId2, $contactId, 'Additional contact should be same contact as previous after dedupe. In line '.__LINE__); + $blockValue = $formatted['additional']['address'][0]; + $blockValue['contact_id'] = $contactId; + CRM_Core_BAO_Address::valueExists($blockValue); + $this->assertNotEmpty($blockValue['id'], "Additional address should be added to same contact. In line " . __LINE__); + + // case 3, this should dupe original contact, no additional contact should be created + $json = json_decode($this->_json[1], TRUE); + $json['transaction']['trade_no'] = CRM_Utils_String::createRandom(15); + $json['user']['id'] = mt_rand(100000, 999999); + $json['user']['email'] = 'admintest.noadd@eaxmple.com'; + $json['user']['name'] = '陳未增'; + $json['user']['cellphone'] = '+886966777888'; + $json['recipient']['recipient_name'] = '陳未增'; + $json['recipient']['recipient_contact_email'] = 'admintest.noadd@eaxmple.com'; + $json['recipient']['recipient_cellphone'] = '0977777888'; + $json = json_encode($json); + $formatted = CRM_Core_Payment_Backer::formatParams($json); + + $contributionResult = NULL; + $createdContributionId = $this->_processor->processContribution($json, $contributionResult); + $createdContributionId = $contributionResult['contributionId']; + $this->assertNotEmpty($createdContributionId, "Contribution not created. In line " . __LINE__); + $contactId = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $createdContributionId, 'contact_id'); + + $blockValue = $formatted['additional']['address'][0]; + $blockValue['contact_id'] = $contactId; + CRM_Core_BAO_Address::valueExists($blockValue); + $this->assertNotEmpty($blockValue['id'], "Additional address should be added to same contact. In line " . __LINE__); + + $blockValue = $formatted['additional']['phone'][0]; + $blockValue['contact_id'] = $contactId; + CRM_Core_BAO_Phone::valueExists($blockValue); + $this->assertNotEmpty($blockValue['id'], "Additional phone should be added to same contact. In line " . __LINE__); } function testBackerReceiptNew(){