Add test for Mapping form validation, contribution import
authorEileen McNaughton <emcnaughton@wikimedia.org>
Mon, 5 Sep 2022 02:13:39 +0000 (14:13 +1200)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Mon, 5 Sep 2022 02:13:39 +0000 (14:13 +1200)
CRM/Import/DataSource.php
tests/phpunit/CRM/Contribute/Import/Parser/ContributionTest.php
tests/phpunit/CRMTraits/Custom/CustomDataTrait.php
tests/phpunit/CiviTest/CiviUnitTestCase.php

index 17fdcefbfa9574405917e4fbc762ecb7ff389d16..bed5e651d8d1b93acf2a5de4e016fcbc514c5a48 100644 (file)
@@ -276,9 +276,10 @@ abstract class CRM_Import_DataSource {
    *
    * The array has all values.
    *
+   * @param array $statuses
+   *
    * @return int
    *
-   * @throws \API_Exception
    * @throws \CRM_Core_Exception
    */
   public function getRowCount(array $statuses = []): int {
index 1d0a26c311ddd3b1d223629e0b265ad2dd77c55c..5e28e86c1ccb88a1586b73979a09ffb4a26adb2f 100644 (file)
@@ -6,6 +6,8 @@
 
 use Civi\Api4\Contribution;
 use Civi\Api4\ContributionSoft;
+use Civi\Api4\DedupeRule;
+use Civi\Api4\DedupeRuleGroup;
 use Civi\Api4\Email;
 use Civi\Api4\Note;
 use Civi\Api4\OptionValue;
@@ -38,6 +40,9 @@ class CRM_Contribute_Import_Parser_ContributionTest extends CiviUnitTestCase {
     $this->quickCleanUpFinancialEntities();
     $this->quickCleanup(['civicrm_user_job', 'civicrm_queue', 'civicrm_queue_item'], TRUE);
     OptionValue::delete()->addWhere('name', '=', 'random')->execute();
+    DedupeRule::delete()
+      ->addWhere('rule_table', '!=', 'civicrm_email')
+      ->addWhere('dedupe_rule_group_id.name', '=', 'IndividualUnsupervised')->execute();
     parent::tearDown();
   }
 
@@ -50,7 +55,7 @@ class CRM_Contribute_Import_Parser_ContributionTest extends CiviUnitTestCase {
    *
    * @param string $thousandSeparator
    *
-   * @throws \Exception
+   * @throws \CRM_Core_Exception
    */
   public function testImportParserWithSoftCreditsByExternalIdentifier(string $thousandSeparator): void {
     $this->setCurrencySeparators($thousandSeparator);
@@ -332,6 +337,55 @@ class CRM_Contribute_Import_Parser_ContributionTest extends CiviUnitTestCase {
     $this->assertEquals($anthony, $contribution['contact_id']);
   }
 
+  /**
+   * Test import parser will consider a rule valid including a custom field.
+   *
+   * @dataProvider validateData
+   */
+  public function testValidateMappingWithCustomDedupeRule($data): void {
+    $this->addToDedupeRule();
+    // First we try to create without total_amount mapped.
+    // It will fail in create mode as total_amount is required for create.
+    $mappings = [
+      ['name' => 'financial_type_id'],
+      ['name' => 'total_amount'],
+    ];
+    foreach ($data['fields']  as $field) {
+      $mappings[] = ['name' => $field === 'custom' ? $this->getCustomFieldName() : $field];
+    }
+    $this->submitDataSourceForm('contributions.csv', ['onDuplicate' => CRM_Import_Parser::DUPLICATE_SKIP]);
+    $form = $this->getMapFieldForm([
+      'onDuplicate' => CRM_Import_Parser::DUPLICATE_SKIP,
+      'mapper' => $this->getMapperFromFieldMappings($mappings),
+      'contactType' => CRM_Import_Parser::CONTACT_INDIVIDUAL,
+    ]);
+    $form->setUserJobID($this->userJobID);
+    $form->buildForm();
+    $this->assertEquals($data['valid'], $form->validate(), print_r($form->_errors, TRUE));
+  }
+
+  /**
+   * Get data to test validation on.
+   *
+   * Enough is email or any combo of first_name, last_name, custom field.
+   *
+   * @return array
+   */
+  public function validateData(): array {
+   return [
+     'email_first_name_last_name' => [['fields' => ['email', 'first_name', 'last_name'], 'valid' => TRUE]],
+     'email_last_name' => [['fields' => ['email', 'last_name'], 'valid' => TRUE]],
+     'email_first_name' => [['fields' => ['email', 'first_name',], 'valid' => TRUE]],
+     'first_name_last_name' => [['fields' => ['first_name', 'last_name'], 'valid' => TRUE]],
+     'email' => [['fields' => ['email'], 'valid' => TRUE]],
+     'first_name' => [['fields' => ['first_name'], 'valid' => FALSE]],
+     'last_name' => [['fields' => ['last_name'], 'valid' => FALSE]],
+     'last_name_custom' => [['fields' => ['last_name', 'custom'], 'valid' => TRUE]],
+     'first_name_custom' => [['fields' => ['first_name', 'custom'], 'valid' => TRUE]],
+     'custom' => [['fields' => ['first_name', 'custom'], 'valid' => FALSE]],
+   ];
+  }
+
   /**
    * Test that a trxn_id is enough in update mode to void the total_amount requirement.
    *
@@ -618,4 +672,36 @@ class CRM_Contribute_Import_Parser_ContributionTest extends CiviUnitTestCase {
     return new CRM_Import_DataSource_CSV($this->userJobID);
   }
 
+  /**
+   * Enhance field such that any combo of the custom field & first/last name is enough.
+   *
+   * @noinspection PhpUnhandledExceptionInspection
+   */
+  protected function addToDedupeRule(): void {
+    $this->createCustomGroupWithFieldOfType(['extends' => 'Contact']);
+    $dedupeRuleGroupID = DedupeRuleGroup::get()
+      ->addWhere('name', '=', 'IndividualUnsupervised')
+      ->addSelect('id')
+      ->execute()
+      ->first()['id'];
+    $this->callAPISuccess('Rule', 'create', [
+      'dedupe_rule_group_id' => $dedupeRuleGroupID,
+      'rule_weight' => 5,
+      'rule_table' => $this->getCustomGroupTable(),
+      'rule_field' => $this->getCustomFieldColumnName('text'),
+    ]);
+    $this->callAPISuccess('Rule', 'create', [
+      'dedupe_rule_group_id' => $dedupeRuleGroupID,
+      'rule_weight' => 5,
+      'rule_table' => 'civicrm_contact',
+      'rule_field' => 'first_name',
+    ]);
+    $this->callAPISuccess('Rule', 'create', [
+      'dedupe_rule_group_id' => $dedupeRuleGroupID,
+      'rule_weight' => 5,
+      'rule_table' => 'civicrm_contact',
+      'rule_field' => 'last_name',
+    ]);
+  }
+
 }
index 72ffc40df455665b55bbe801041be87878786339..5d1f0786fa63839c611fd596e6cb1f77c1395d17 100644 (file)
@@ -176,7 +176,7 @@ trait CRMTraits_Custom_CustomDataTrait {
    * @noinspection PhpDocMissingThrowsInspection
    * @noinspection PhpUnhandledExceptionInspection
    */
-  protected function getCustomFieldName(string $key, $version = 3): string {
+  protected function getCustomFieldName(string $key = 'text', int $version = 3): string {
     if ($version === 4) {
       $field = CustomField::get(FALSE)->addWhere('id', '=', $this->getCustomFieldID($key))
         ->addSelect('name', 'custom_group_id.name')->execute()->first();
index f818e0327153527dcec309d88a3b3ac0eb55a1a2..38c7b1e736dd5a76ee050fccde8beb4915f63d3e 100644 (file)
@@ -3366,7 +3366,7 @@ class CiviUnitTestCase extends PHPUnit\Framework\TestCase {
    *
    * @param string $thousandSeparator
    */
-  protected function setCurrencySeparators($thousandSeparator) {
+  protected function setCurrencySeparators(string $thousandSeparator): void {
     Civi::settings()->set('monetaryThousandSeparator', $thousandSeparator);
     Civi::settings()->set('monetaryDecimalPoint', ($thousandSeparator === ',' ? '.' : ','));
   }