*/
use Civi\Api4\Activity;
+use Civi\Api4\ActivityContact;
use Civi\Api4\Contribution;
use Civi\Api4\ContributionRecur;
use Civi\Api4\PaymentProcessor;
'id' => $existingActivity['id'] ?? NULL,
], $campaignParams);
if (!$activityParams['id']) {
- // Don't set target contacts on update as these will have been
- // correctly created and we risk overwriting them with
- // 'best guess' params.
$activityParams['source_contact_id'] = (int) ($params['source_contact_id'] ?? (CRM_Core_Session::getLoggedInContactID() ?: $contribution->contact_id));
$activityParams['target_contact_id'] = ($activityParams['source_contact_id'] === (int) $contribution->contact_id) ? [] : [$contribution->contact_id];
}
+ else {
+ list($sourceContactId, $targetContactId) = self::getActivitySourceAndTarget($activityParams['id']);
+
+ if (empty($targetContactId) && $sourceContactId != $contribution->contact_id) {
+ // If no target contact exists and the source contact is not equal to
+ // the contribution contact, update the source contact
+ $activityParams['source_contact_id'] = $contribution->contact_id;
+ }
+ elseif (isset($targetContactId) && $targetContactId != $contribution->contact_id) {
+ // If a target contact exists and it is not equal to the contribution
+ // contact, update the target contact
+ $activityParams['target_contact_id'] = [$contribution->contact_id];
+ }
+ }
Activity::save(FALSE)->addRecord($activityParams)->execute();
}
return $values;
}
+ /**
+ * Get the activity source and target contacts linked to a contribution
+ *
+ * @param $activityId
+ *
+ * @return array
+ */
+ private static function getActivitySourceAndTarget($activityId): array {
+ $activityContactQuery = ActivityContact::get(FALSE)->setWhere([
+ ['activity_id', '=', $activityId],
+ ['record_type_id:name', 'IN', ['Activity Source', 'Activity Targets']],
+ ])->execute();
+
+ $sourceContactKey = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_ActivityContact', 'record_type_id', 'Activity Source');
+ $targetContactKey = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_ActivityContact', 'record_type_id', 'Activity Targets');
+
+ $sourceContactId = NULL;
+ $targetContactId = NULL;
+
+ for ($i = 0; $i < $activityContactQuery->count(); $i++) {
+ $record = $activityContactQuery->itemAt($i);
+
+ if ($record['record_type_id'] === $sourceContactKey) {
+ $sourceContactId = $record['contact_id'];
+ }
+
+ if ($record['record_type_id'] === $targetContactKey) {
+ $targetContactId = $record['contact_id'];
+ }
+ }
+
+ return [$sourceContactId, $targetContactId];
+ }
+
}
$this->assertEquals(0, $count);
}
+ /**
+ * Test activity contact is updated when contribution contact is changed
+ */
+ public function testUpdateActivityContactOnContributionContactChange(): void {
+ $contactId_1 = $this->individualCreate();
+ $contactId_2 = $this->individualCreate();
+ $contactId_3 = $this->individualCreate();
+
+ $contributionParams = [
+ 'financial_type_id' => 'Donation',
+ 'receive_date' => date('Y-m-d H:i:s'),
+ 'sequential' => TRUE,
+ 'total_amount' => 50,
+ ];
+
+ // Case 1: Only source contact, no target contact
+
+ $contribution = $this->callAPISuccess('Contribution', 'create', array_merge(
+ $contributionParams,
+ ['contact_id' => $contactId_1]
+ ))['values'][0];
+
+ $activity = $this->callAPISuccessGetSingle('Activity', ['source_record_id' => $contribution['id']]);
+
+ $activityContactParams = [
+ 'activity_id' => $activity['id'],
+ 'record_type_id' => 'Activity Source',
+ ];
+
+ $activityContact = $this->callAPISuccessGetSingle('ActivityContact', $activityContactParams);
+
+ $this->assertEquals($activityContact['contact_id'], $contactId_1, 'Check source contact ID matches the first contact');
+
+ $contribution = $this->callAPISuccess('Contribution', 'create', array_merge(
+ $contributionParams,
+ [
+ 'id' => $contribution['id'],
+ 'contact_id' => $contactId_2,
+ ]
+ ))['values'][0];
+
+ $activityContact = $this->callAPISuccessGetSingle('ActivityContact', $activityContactParams);
+
+ $this->assertEquals($activityContact['contact_id'], $contactId_2, 'Check source contact ID matches the second contact');
+
+ // Case 2: Source and target contact
+
+ $contribution = $this->callAPISuccess('Contribution', 'create', array_merge(
+ $contributionParams,
+ [
+ 'contact_id' => $contactId_1,
+ 'source_contact_id' => $contactId_3,
+ ]
+ ))['values'][0];
+
+ $activity = $this->callAPISuccessGetSingle('Activity', ['source_record_id' => $contribution['id']]);
+
+ $activityContactParams = [
+ 'activity_id' => $activity['id'],
+ 'record_type_id' => 'Activity Targets',
+ ];
+
+ $activityContact = $this->callAPISuccessGetSingle('ActivityContact', $activityContactParams);
+
+ $this->assertEquals($activityContact['contact_id'], $contactId_1, 'Check target contact ID matches first contact');
+
+ $contribution = $this->callAPISuccess('Contribution', 'create', array_merge(
+ $contributionParams,
+ [
+ 'id' => $contribution['id'],
+ 'contact_id' => $contactId_2,
+ ]
+ ))['values'][0];
+
+ $activityContact = $this->callAPISuccessGetSingle('ActivityContact', $activityContactParams);
+
+ $this->assertEquals($activityContact['contact_id'], $contactId_2, 'Check target contact ID matches the second contact');
+ }
+
}