Skip to content

Commit

Permalink
Merge pull request #28730 from eileenmcnaughton/recur_cancel_api_2
Browse files Browse the repository at this point in the history
Stop bypassing hooks on ContributionRecur.cancel
  • Loading branch information
colemanw authored Dec 30, 2023
2 parents 07b5205 + 7f4af29 commit 64de539
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 72 deletions.
117 changes: 48 additions & 69 deletions CRM/Contribute/BAO/ContributionRecur.php
Original file line number Diff line number Diff line change
Expand Up @@ -275,82 +275,61 @@ public static function deleteRecurContribution($recurId) {
* Recur contribution params
*
* @return bool
* @throws \CRM_Core_Exception
* @internal
*
*/
public static function cancelRecurContribution($params) {
if (is_numeric($params)) {
CRM_Core_Error::deprecatedFunctionWarning('You are using a BAO function whose signature has changed. Please use the ContributionRecur.cancel api');
$params = ['id' => $params];
}
$recurId = $params['id'];
if (!$recurId) {
public static function cancelRecurContribution(array $params): bool {
if (!$params['id']) {
return FALSE;
}
$activityParams = [
'subject' => !empty($params['membership_id']) ? ts('Auto-renewal membership cancelled') : ts('Recurring contribution cancelled'),
'details' => $params['processor_message'] ?? NULL,
];

$cancelledId = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_ContributionRecur', 'contribution_status_id', 'Cancelled');
$recur = new CRM_Contribute_DAO_ContributionRecur();
$recur->id = $recurId;
$recur->whereAdd("contribution_status_id != $cancelledId");

if ($recur->find(TRUE)) {
$transaction = new CRM_Core_Transaction();
$recur->contribution_status_id = $cancelledId;
$recur->cancel_reason = $params['cancel_reason'] ?? NULL;
$recur->cancel_date = date('YmdHis');
$recur->save();

// @fixme https://lab.civicrm.org/dev/core/issues/927 Cancelling membership etc is not desirable for all use-cases and we should be able to disable it
$dao = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($recurId);
if ($dao && $dao->recur_id) {
$details = $activityParams['details'] ?? NULL;
if ($dao->auto_renew && $dao->membership_id) {
// its auto-renewal membership mode
$membershipTypes = CRM_Member_PseudoConstant::membershipType();
$membershipType = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $dao->membership_id, 'membership_type_id');
$membershipType = $membershipTypes[$membershipType] ?? NULL;
$details .= '
$transaction = new CRM_Core_Transaction();
ContributionRecur::update(FALSE)
->addWhere('id', '=', $params['id'])
->setValues([
'contribution_status_id:name' => 'Cancelled',
'cancel_reason' => $params['cancel_reason'] ?? NULL,
'cancel_date' => $params['cancel_date'] ?? 'now',
])->execute();

// @todo - all of this should be moved to the post hook.
// It seems to just create activities.
$dao = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($params['id']);
if ($dao && $dao->recur_id) {
$details = $params['processor_message'] ?? NULL;
if ($dao->auto_renew && $dao->membership_id) {
// its auto-renewal membership mode
$membershipTypes = CRM_Member_PseudoConstant::membershipType();
$membershipType = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $dao->membership_id, 'membership_type_id');
$membershipType = $membershipTypes[$membershipType] ?? NULL;
$details .= '
<br/>' . ts('Automatic renewal of %1 membership cancelled.', [1 => $membershipType]);
}
else {
$details .= '<br/>' . ts('The recurring contribution of %1, every %2 %3 has been cancelled.', [
1 => $dao->amount,
2 => $dao->frequency_interval,
3 => $dao->frequency_unit,
]);
}
$activityParams = [
'source_contact_id' => $dao->contact_id,
'source_record_id' => $dao->recur_id,
'activity_type_id' => 'Cancel Recurring Contribution',
'subject' => CRM_Utils_Array::value('subject', $activityParams, ts('Recurring contribution cancelled')),
'details' => $details,
'status_id' => 'Completed',
];

$cid = CRM_Core_Session::singleton()->get('userID');
if ($cid) {
$activityParams['target_contact_id'][] = $activityParams['source_contact_id'];
$activityParams['source_contact_id'] = $cid;
}
civicrm_api3('Activity', 'create', $activityParams);
}

$transaction->commit();
return TRUE;
}
else {
// if already cancelled, return true
$recur->whereAdd();
$recur->whereAdd("contribution_status_id = $cancelledId");
if ($recur->find(TRUE)) {
return TRUE;
else {
$details .= '<br/>' . ts('The recurring contribution of %1, every %2 %3 has been cancelled.', [
1 => $dao->amount,
2 => $dao->frequency_interval,
3 => $dao->frequency_unit,
]);
}
$activityParams = [
'source_contact_id' => $dao->contact_id,
'source_record_id' => $dao->recur_id,
'activity_type_id' => 'Cancel Recurring Contribution',
'subject' => !empty($params['membership_id']) ? ts('Auto-renewal membership cancelled') : ts('Recurring contribution cancelled'),
'details' => $details,
'status_id' => 'Completed',
];

$cid = CRM_Core_Session::singleton()->get('userID');
if ($cid) {
$activityParams['target_contact_id'][] = $activityParams['source_contact_id'];
$activityParams['source_contact_id'] = $cid;
}
civicrm_api3('Activity', 'create', $activityParams);
}

return FALSE;
$transaction->commit();
return TRUE;
}

/**
Expand Down
22 changes: 19 additions & 3 deletions api/v3/ContributionRecur.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
* @package CiviCRM_APIv3
*/

use Civi\Api4\ContributionRecur;

/**
* Create or update a ContributionRecur.
*
Expand Down Expand Up @@ -64,11 +66,25 @@ function civicrm_api3_contribution_recur_get($params) {
* @param array $params
* Array containing id of the recurring contribution.
*
* @return bool
* @return array
* returns true is successfully cancelled
* @throws \CRM_Core_Exception
*/
function civicrm_api3_contribution_recur_cancel($params) {
return CRM_Contribute_BAO_ContributionRecur::cancelRecurContribution($params) ? civicrm_api3_create_success() : civicrm_api3_create_error(ts('Error while cancelling recurring contribution'));
function civicrm_api3_contribution_recur_cancel(array $params): array {
$params['check_permissions'] = $params['check_permissions'] ?? FALSE;
$existing = ContributionRecur::get($params['check_permissions'])
->addWhere('id', '=', $params['id'])
->addSelect('contribution_status_id:name')
->execute()->first();
if (!$existing) {
throw new CRM_Core_Exception('record not found');
}
if ($existing['contribution_status_id:name'] === 'Cancelled') {
return civicrm_api3_create_success([$existing['id'] => $existing]);
}

CRM_Contribute_BAO_ContributionRecur::cancelRecurContribution($params);
return civicrm_api3_create_success();
}

/**
Expand Down

0 comments on commit 64de539

Please sign in to comment.