Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

WIP Refactor cancel/failed functions in baseIPN so we don't duplicate code and business logic is separated out #14397

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CRM/Contribute/BAO/Contribution.php
Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,7 @@ protected static function getRelatedMemberships($contributionID) {
* @return array
*/
protected static function cancel($processContributionObject, $memberships, $contributionId, $membershipStatuses, $updateResult, $participant, $oldStatus, $pledgePayment, $pledgeID, $pledgePaymentIDs, $contributionStatusId) {
// @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
$processContribution = FALSE;
$participantStatuses = CRM_Event_PseudoConstant::participantStatus();
if (is_array($memberships)) {
Expand Down
1 change: 1 addition & 0 deletions CRM/Contribute/BAO/ContributionRecur.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ public static function cancelRecurContribution($params) {
$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 = CRM_Utils_Array::value('details', $activityParams);
Expand Down
191 changes: 84 additions & 107 deletions CRM/Core/Payment/BaseIPN.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,98 +206,32 @@ public function loadObjects(&$input, &$ids, &$objects, $required, $paymentProces
}

/**
* Set contribution to failed.
* Handled pending contribution status.
*
* @param array $objects
* @param object $transaction
* @param array $input
* @param \CRM_Core_Transaction $transaction
*
* @return bool
*/
public function failed(&$objects, &$transaction, $input = []) {
$contribution = &$objects['contribution'];
$memberships = [];
if (!empty($objects['membership'])) {
$memberships = &$objects['membership'];
if (is_numeric($memberships)) {
$memberships = [$objects['membership']];
}
}

$addLineItems = FALSE;
if (empty($contribution->id)) {
$addLineItems = TRUE;
}
$participant = &$objects['participant'];

// CRM-15546
$contributionStatuses = CRM_Core_PseudoConstant::get('CRM_Contribute_DAO_Contribution', 'contribution_status_id', [
'labelColumn' => 'name',
'flip' => 1,
]);
$contribution->receive_date = CRM_Utils_Date::isoToMysql($contribution->receive_date);
$contribution->receipt_date = CRM_Utils_Date::isoToMysql($contribution->receipt_date);
$contribution->thankyou_date = CRM_Utils_Date::isoToMysql($contribution->thankyou_date);
$contribution->contribution_status_id = $contributionStatuses['Failed'];
$contribution->save();

// Add line items for recurring payments.
if (!empty($objects['contributionRecur']) && $objects['contributionRecur']->id && $addLineItems) {
CRM_Contribute_BAO_ContributionRecur::addRecurLineItems($objects['contributionRecur']->id, $contribution);
}

//add new soft credit against current contribution id and
//copy initial contribution custom fields for recurring contributions
if (!empty($objects['contributionRecur']) && $objects['contributionRecur']->id) {
CRM_Contribute_BAO_ContributionRecur::addrecurSoftCredit($objects['contributionRecur']->id, $contribution->id);
CRM_Contribute_BAO_ContributionRecur::copyCustomValues($objects['contributionRecur']->id, $contribution->id);
}

if (empty($input['IAmAHorribleNastyBeyondExcusableHackInTheCRMEventFORMTaskClassThatNeedsToBERemoved'])) {
if (!empty($memberships)) {
// if transaction is failed then set "Cancelled" as membership status
$membershipStatuses = CRM_Core_PseudoConstant::get('CRM_Member_DAO_Membership', 'status_id', [
'labelColumn' => 'name',
'flip' => 1,
]);
foreach ($memberships as $membership) {
if ($membership) {
$membership->status_id = $membershipStatuses['Cancelled'];
$membership->save();

//update related Memberships.
$params = ['status_id' => $membershipStatuses['Cancelled']];
CRM_Member_BAO_Membership::updateRelatedMemberships($membership->id, $params);
}
}
}

if ($participant) {
$participantParams['id'] = $participant->id;
$participantParams['status_id'] = 'Cancelled';
civicrm_api3('Participant', 'create', $participantParams);
}
}

public function pending(&$objects, &$transaction) {
$transaction->commit();
CRM_Core_Error::debug_log_message("Setting contribution status to failed");
//echo "Success: Setting contribution status to failed<p>";
Civi::log()->debug("returning since contribution status is pending");
echo "Success: Returning since contribution status is pending<p>";
return TRUE;
}

/**
* Handled pending contribution status.
* Set contribution to failed.
*
* @param array $objects
* @param object $transaction
* @param \CRM_Core_Transaction $transaction
* @param array $input
*
* @return bool
*/
public function pending(&$objects, &$transaction) {
$transaction->commit();
CRM_Core_Error::debug_log_message("returning since contribution status is pending");
echo "Success: Returning since contribution status is pending<p>";
return TRUE;
public function failed(&$objects, &$transaction, $input = []) {
$contributionStatusID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Failed');
return $this->contributionStatusChanged($contributionStatusID, $objects, $transaction, $input);
}

/**
Expand All @@ -310,27 +244,43 @@ public function pending(&$objects, &$transaction) {
* @return bool
*/
public function cancelled(&$objects, &$transaction, $input = []) {
$contributionStatusID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Cancelled');
return $this->contributionStatusChanged($contributionStatusID, $objects, $transaction, $input);
}

/**
* Process cancelled/failed payment outcome.
*
* @param int $newStatusID contribution_status_id
* @param array $objects
* @param CRM_Core_Transaction $transaction
* @param array $input
*
* @return bool
*/
protected function contributionStatusChanged($newStatusID, &$objects, &$transaction, $input = []) {
$contribution = &$objects['contribution'];
$memberships = &$objects['membership'];
if (is_numeric($memberships)) {
$memberships = [$objects['membership']];
$memberships = [];
if (!empty($objects['membership'])) {
$memberships = &$objects['membership'];
if (is_numeric($memberships)) {
$memberships = [$objects['membership']];
}
}

$participant = &$objects['participant'];
$addLineItems = FALSE;
if (empty($contribution->id)) {
$addLineItems = TRUE;
}
$contributionStatuses = CRM_Core_PseudoConstant::get('CRM_Contribute_DAO_Contribution', 'contribution_status_id', [
'labelColumn' => 'name',
'flip' => 1,
]);
$contribution->contribution_status_id = $contributionStatuses['Cancelled'];
$contribution->cancel_date = self::$_now;
$contribution->cancel_reason = CRM_Utils_Array::value('reasonCode', $input);
$contribution->contribution_status_id = $newStatusID;
$contribution->receive_date = CRM_Utils_Date::isoToMysql($contribution->receive_date);
$contribution->receipt_date = CRM_Utils_Date::isoToMysql($contribution->receipt_date);
$contribution->thankyou_date = CRM_Utils_Date::isoToMysql($contribution->thankyou_date);
if ($newStatusID == CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Cancelled')) {
$contribution->cancel_date = self::$_now;
$contribution->cancel_reason = CRM_Utils_Array::value('reasonCode', $input);
}
$contribution->save();

//add lineitems for recurring payments
Expand All @@ -347,37 +297,64 @@ public function cancelled(&$objects, &$transaction, $input = []) {

if (empty($input['IAmAHorribleNastyBeyondExcusableHackInTheCRMEventFORMTaskClassThatNeedsToBERemoved'])) {
if (!empty($memberships)) {
$membershipStatuses = CRM_Core_PseudoConstant::get('CRM_Member_DAO_Membership', 'status_id', [
'labelColumn' => 'name',
'flip' => 1,
]);
// Cancel only Pending memberships
// CRM-18688
$pendingStatusId = $membershipStatuses['Pending'];
foreach ($memberships as $membership) {
if ($membership && ($membership->status_id == $pendingStatusId)) {
$membership->status_id = $membershipStatuses['Cancelled'];
$membership->save();

//update related Memberships.
$params = ['status_id' => $membershipStatuses['Cancelled']];
CRM_Member_BAO_Membership::updateRelatedMemberships($membership->id, $params);
if ($membership) {
self::cancelMembership($membership->id, $membership->status_id);
}
}
}

if ($participant) {
$participantParams['id'] = $participant->id;
$participantParams['status_id'] = 'Cancelled';
civicrm_api3('Participant', 'create', $participantParams);
self::cancelParticipant($participant->id);
}
}
$transaction->commit();
CRM_Core_Error::debug_log_message("Setting contribution status to cancelled");
//echo "Success: Setting contribution status to cancelled<p>";
$contributionStatusLabel = CRM_Core_PseudoConstant::getLabel('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $newStatusID);
Civi::log()->debug("Setting contribution status to {$contributionStatusLabel}");
return TRUE;
}

/**
* Logic to cancel a participant record when the related contribution changes to failed/cancelled.
* @todo This is part of a bigger refactor for dev/core/issues/927 - "duplicate" functionality exists in CRM_Contribute_BAO_Contribution::cancel()
*
* @param $participantID
*
* @throws \CiviCRM_API3_Exception
*/
private static function cancelParticipant($participantID) {
// @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
$participantParams['id'] = $participantID;
$participantParams['status_id'] = 'Cancelled';
civicrm_api3('Participant', 'create', $participantParams);
}

/**
* Logic to cancel a membership record when the related contribution changes to failed/cancelled.
* @todo This is part of a bigger refactor for dev/core/issues/927 - "duplicate" functionality exists in CRM_Contribute_BAO_Contribution::cancel()
* @param $membershipID
* @param $membershipStatusID
*
* @throws \CiviCRM_API3_Exception
*/
private static function cancelMembership($membershipID, $membershipStatusID) {
// @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
// Cancel only Pending memberships CRM-18688
$pendingMembershipStatusId = CRM_Core_PseudoConstant::getKey('CRM_Member_BAO_Membership', 'status_id', 'Pending');

if ($membershipStatusID == $pendingMembershipStatusId) {
$cancelledMembershipStatusId = CRM_Core_PseudoConstant::getKey('CRM_Member_BAO_Membership', 'status_id', 'Cancelled');
$membershipParams = [
'id' => $membershipID,
'status_id' => $cancelledMembershipStatusId,
];
civicrm_api3('Membership', 'create', $membershipParams);

//update related Memberships.
CRM_Member_BAO_Membership::updateRelatedMemberships($membershipParams['id'], ['status_id' => $cancelledMembershipStatusId]);
}
}

/**
* Rollback unhandled outcomes.
*
Expand All @@ -388,7 +365,7 @@ public function cancelled(&$objects, &$transaction, $input = []) {
*/
public function unhandled(&$objects, &$transaction) {
$transaction->rollback();
CRM_Core_Error::debug_log_message("returning since contribution status: is not handled");
Civi::log()->debug("Returning since contribution status is not handled");
echo "Failure: contribution status is not handled<p>";
return FALSE;
}
Expand Down