Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

GP-46001 Detect addresses that changed after TM selection #31

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
89 changes: 88 additions & 1 deletion CRM/Streetimport/GP/Handler/GPRecordHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
| http://www.systopia.de/ |
+--------------------------------------------------------------*/

use Civi\Api4;

/**
* Abstract class bundle common GP importer functions
*
Expand Down Expand Up @@ -559,7 +561,7 @@ public function isContributionRecurActive($contribution_recur) {
* - else: if new data wouldn't replace ALL the data of the old address -> create ticket (activity) for manual processing
* - else: update address
*/
public function createOrUpdateAddress($contact_id, $address_data, $record) {
public function createOrUpdateAddress($contact_id, $address_data, $record, $parent_activity_id = NULL) {
if (empty($address_data)) return;

// check if address is complete
Expand Down Expand Up @@ -1138,4 +1140,89 @@ protected function isDeletedContact($contact_id) {
]) == 1;
}

/**
* Check if there has been a change since a specified date
*
* @param $contact_id
* @param $minimum_date
* @param $record
*
* @return bool
*/
public function addressChangeRecordedSince($contact_id, $minimum_date, $record) {
$logging = new CRM_Logging_Schema();

// Assert that logging is enabled
if (!$logging->isEnabled()) {
$this->logger->logDebug("Logging not enabled, cannot determine whether records have changed.", $record);
return FALSE;
}

// Determine the name of the logging database
$dsn_database = (
defined('CIVICRM_LOGGING_DSN')
? DB::parseDSN(CIVICRM_LOGGING_DSN)
: DB::parseDSN(CIVICRM_DSN)
)['database'];

// The following address attributes will be used for comparison
$relevant_attributes = [
'city',
'country_id',
'is_primary',
'postal_code',
'street_address',
'supplemental_address_1',
'supplemental_address_2',
];

$attribute_list = implode(', ', $relevant_attributes);

// Determine the primary address of the contact at the time of $minimum_date
$prev_addr_query = CRM_Core_DAO::executeQuery("
SELECT $attribute_list
FROM $dsn_database.log_civicrm_address
WHERE
contact_id = $contact_id
AND is_primary = 1
AND log_action != 'Delete'
AND log_date < '$minimum_date'
ORDER BY log_date DESC
LIMIT 1
");

if (!$prev_addr_query->fetch()) return TRUE;

// Discard DB query metadata, keep only relevant attributes
$previous_address = CRM_Streetimport_Utils::selectKeys(
(array) (clone $prev_addr_query),
$relevant_attributes
);

// Get the current primary address of the contact
$current_address = Api4\Address::get(FALSE)
->addSelect(...$relevant_attributes)
->addWhere('contact_id', '=', $contact_id)
->addWhere('is_primary', '=', TRUE)
->setLimit(1)
->execute()
->first();

if (is_null($current_address)) {
$this->logger->logDebug("Contact #$contact_id has no current primary address", $record);
return TRUE;
}

foreach ($relevant_attributes as $attribute) {
if ($previous_address[$attribute] == $current_address[$attribute]) continue;

// A relevant attribute has changed
$this->logger->logDebug("Address attribute '$attribute' changed", $record);
return TRUE;
}

// No relevant changes have been detected
return FALSE;
}

}
91 changes: 16 additions & 75 deletions CRM/Streetimport/GP/Handler/PostalReturn/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,71 +162,6 @@ protected function findLastRTS($contact_id, $record, $search_frame = NULL, $cate
*/
abstract protected function getCategory($record);

/**
* Check if there has been a change since
*
* @param $contact_id
* @param $minimum_date
* @param $record
*
* @return bool
*/
protected function addressChangeRecordedSince($contact_id, $minimum_date, $record) {
// check if logging is enabled
$logging = new CRM_Logging_Schema();
if (!$logging->isEnabled()) {
$this->logger->logDebug("Logging not enabled, cannot determine whether records have changed.", $record);
return FALSE;
}

// query the logging DB
$dsn = defined('CIVICRM_LOGGING_DSN') ? DB::parseDSN(CIVICRM_LOGGING_DSN) : DB::parseDSN(CIVICRM_DSN);
$relevant_attributes = array('id','is_primary','street_address','supplemental_address_1','supplemental_address_2','city','postal_code','country_id','log_date');
$attribute_list = implode(',', $relevant_attributes);
$current_status = array();
$query = CRM_Core_DAO::executeQuery("SELECT {$attribute_list} FROM {$dsn['database']}.log_civicrm_address WHERE contact_id={$contact_id}");
while ($query->fetch()) {
// generate record
$record = array();
$record_id = $query->id;
foreach ($relevant_attributes as $attribute) {
$record[$attribute] = $query->$attribute;
}

// process record
if (!isset($current_status[$record_id])) {
// this is a new address
$current_status[$record_id] = $record;

} else {
// compare with the old record
$old_record = $current_status[$record_id];
$changed = FALSE;
foreach ($relevant_attributes as $attribute) {
if ($attribute == 'log_date') continue; // that doesn't matter
if ($old_record[$attribute] != $record[$attribute]) {
$this->logger->logDebug("Address attribute '{$attribute}' changed (on {$record['log_date']})", $record);
$changed = TRUE;
break;
}
}

// this is the new current
$current_status[$record_id] = $record;

if ($changed) {
// there is a change, check if it's in the time frame we're looking for
if (strtotime($record['log_date']) >= strtotime($minimum_date)) {
$this->logger->logDebug("Address change relevant (date range)", $record);
return TRUE;
}
}
}
}

return FALSE;
}

/**
* Get the correct subject for the activity
*
Expand Down Expand Up @@ -401,20 +336,26 @@ protected function addressChanged(array $originalAddress, array $returnAddress)
* @throws \CiviCRM_API3_Exception
*/
protected function processReturn($record) {
$contact_id = $this->getContactID($record);
$contact_id = (int) $this->getContactID($record);
$campaign_id = (int) $this->getCampaignID($record);
$category = $this->getCategory($record);
$primary_address = $this->getPrimaryAddress($contact_id, $record);
// whether to increase RTS counter where appropriate
$increaseCounter = TRUE;
// find parent activity
$parent_activity = $this->getParentActivity(
(int) $this->getContactID($record),
$this->getCampaignID($record),
[
'media' => ['letter_mail'],
'exclude_activity_types' => ['Response'],
]
);
$parent_activity = $this->getParentActivity($contact_id, $campaign_id, [
'exclude_activity_types' => ['Response'],
'media' => ['letter_mail'],
]);

// Also include webshop orders in the search
if (empty($parent_activity)) {
$parent_activity = $this->getParentActivity($contact_id, $campaign_id, [
'activity_types' => ['Webshop Order'],
'media' => ['back_office', 'web'],
]);
}

if (empty($parent_activity)) {
// no parent activity found, continue with last RTS activity
$parent_activity = $this->findLastRTS($contact_id, $record);
Expand All @@ -425,7 +366,7 @@ protected function processReturn($record) {
$increaseCounter = FALSE;
}
}
elseif (!empty($parent_activity) && $this->addressChangeRecordedSince($contact_id, $parent_activity['activity_date_time'], $record)) {
elseif (!empty($parent_activity) && $this->addressChangeRecordedSince($contact_id, $parent_activity['created_date'], $record)) {
$this->logger->logDebug("Skipping RTS increase due to logged address change for contact [{$contact_id}].", $record);
$increaseCounter = FALSE;
}
Expand Down
Loading