Skip to content
Snippets Groups Projects
Unverified Commit 3533840e authored by mattwire's avatar mattwire Committed by GitHub
Browse files

Merge pull request #18881 from eileenmcnaughton/cancelb

#927 Move handling of participant.cancel from BaseIPN to  contributioncancelactions
parents c9f4ab40 a201e208
Branches
Tags
No related merge requests found
......@@ -237,6 +237,7 @@ class CRM_Core_Payment_BaseIPN {
* @throws \CiviCRM_API3_Exception|\CRM_Core_Exception
*/
public function cancelled($objects) {
CRM_Core_Error::deprecatedFunctionWarning('Use Contribution create api to cancel the contribution');
$contribution = &$objects['contribution'];
if (empty($contribution->id)) {
......@@ -270,6 +271,11 @@ class CRM_Core_Payment_BaseIPN {
}
}
}
$participant = &$objects['participant'];
if ($participant) {
$this->cancelParticipant($participant->id);
}
}
else {
Contribution::update(FALSE)->setValues([
......@@ -277,11 +283,6 @@ class CRM_Core_Payment_BaseIPN {
'contribution_status_id:name' => 'Cancelled',
])->addWhere('id', '=', $contribution->id)->execute();
}
$participant = &$objects['participant'];
if ($participant) {
$this->cancelParticipant($participant->id);
}
Civi::log()->debug("Setting contribution status to Cancelled");
return TRUE;
......@@ -309,6 +310,8 @@ class CRM_Core_Payment_BaseIPN {
* 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()
*
* @deprecated
*
* @param $participantID
*
* @throws \CiviCRM_API3_Exception
......
......@@ -9,6 +9,8 @@
+--------------------------------------------------------------------+
*/
use Civi\Api4\Contribution;
/**
*
* @package CRM
......@@ -348,7 +350,11 @@ class CRM_Core_Payment_PayPalIPN extends CRM_Core_Payment_BaseIPN {
return;
}
if ($status === 'Refunded' || $status === 'Reversed') {
$this->cancelled($objects);
Contribution::update(FALSE)->setValues([
'cancel_date' => 'now',
'contribution_status_id:name' => 'Cancelled',
])->addWhere('id', '=', $contributionID)->execute();
Civi::log()->debug("Setting contribution status to Cancelled");
return;
}
if ($status !== 'Completed') {
......
......@@ -9,6 +9,8 @@
+--------------------------------------------------------------------+
*/
use Civi\Api4\Contribution;
/**
*
* @package CRM
......@@ -327,8 +329,12 @@ class CRM_Core_Payment_PayPalProIPN extends CRM_Core_Payment_BaseIPN {
Civi::log()->debug('Returning since contribution status is Pending');
return;
}
elseif ($status === 'Refunded' || $status === 'Reversed') {
$this->cancelled($objects);
if ($status === 'Refunded' || $status === 'Reversed') {
Contribution::update(FALSE)->setValues([
'cancel_date' => 'now',
'contribution_status_id:name' => 'Cancelled',
])->addWhere('id', '=', $contribution->id)->execute();
Civi::log()->debug("Setting contribution status to Cancelled");
return;
}
elseif ($status !== 'Completed') {
......
......@@ -5,6 +5,7 @@ require_once 'contributioncancelactions.civix.php';
use CRM_Contributioncancelactions_ExtensionUtil as E;
// phpcs:enable
use Civi\Api4\LineItem;
use Civi\Api4\Participant;
/**
* Implements hook_civicrm_preProcess().
......@@ -19,25 +20,59 @@ use Civi\Api4\LineItem;
function contributioncancelactions_civicrm_post($op, $objectName, $objectId, $objectRef) {
if ($op === 'edit' && $objectName === 'Contribution') {
if ('Cancelled' === CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $objectRef->contribution_status_id)) {
// Find and cancel any pending memberships.
$connectedMemberships = (array) LineItem::get(FALSE)->setWhere([
['contribution_id', '=', $objectId],
['entity_table', '=', 'civicrm_membership'],
])->execute()->indexBy('entity_id');
if (empty($connectedMemberships)) {
return;
}
// @todo we don't have v4 membership api yet so v3 for now.
$connectedMemberships = array_keys(civicrm_api3('Membership', 'get', [
'status_id' => 'Pending',
'id' => ['IN' => array_keys($connectedMemberships)],
])['values']);
if (empty($connectedMemberships)) {
return;
}
foreach ($connectedMemberships as $membershipID) {
civicrm_api3('Membership', 'create', ['status_id' => 'Cancelled', 'id' => $membershipID, 'is_override' => 1]);
}
contributioncancelactions_cancel_related_pending_memberships((int) $objectId);
contributioncancelactions_cancel_related_pending_participant_records((int) $objectId);
}
}
}
/**
* Find and cancel any pending participant records.
*
* @param int $contributionID
* @throws CiviCRM_API3_Exception
*/
function contributioncancelactions_cancel_related_pending_participant_records($contributionID): void {
$pendingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Pending'");
$waitingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'");
$cancellableParticipantRecords = civicrm_api3('ParticipantPayment', 'get', [
'contribution_id' => $contributionID,
'participant_id.status_id' => ['IN' => array_merge(array_keys($pendingStatuses), array_keys($waitingStatuses))],
])['values'];
if (empty($cancellableParticipantRecords)) {
return;
}
Participant::update(FALSE)
->addWhere('id', 'IN', array_keys($cancellableParticipantRecords))
->setValues(['status_id:name' => 'Cancelled'])
->execute();
}
/**
* Find and cancel any pending memberships.
*
* @param int $contributionID
* @throws API_Exception
* @throws CiviCRM_API3_Exception
*/
function contributioncancelactions_cancel_related_pending_memberships($contributionID): void {
$connectedMemberships = (array) LineItem::get(FALSE)->setWhere([
['contribution_id', '=', $contributionID],
['entity_table', '=', 'civicrm_membership'],
])->execute()->indexBy('entity_id');
if (empty($connectedMemberships)) {
return;
}
// @todo we don't have v4 membership api yet so v3 for now.
$connectedMemberships = array_keys(civicrm_api3('Membership', 'get', [
'status_id' => 'Pending',
'id' => ['IN' => array_keys($connectedMemberships)],
])['values']);
if (empty($connectedMemberships)) {
return;
}
foreach ($connectedMemberships as $membershipID) {
civicrm_api3('Membership', 'create', ['status_id' => 'Cancelled', 'id' => $membershipID, 'is_override' => 1]);
}
}
......@@ -7,6 +7,9 @@ use Civi\Api4\Contact;
use Civi\Api4\MembershipType;
use Civi\Api4\RelationshipType;
use Civi\Api4\Relationship;
use Civi\Api4\Event;
use Civi\Api4\PriceField;
use Civi\Api4\Participant;
/**
* FIXME - Add test description.
......@@ -208,4 +211,51 @@ class IPNCancelTest extends \PHPUnit\Framework\TestCase implements HeadlessInter
return (int) $result['id'];
}
/**
* Test that a cancel from paypal pro results in an order being cancelled.
*
* @throws \API_Exception
* @throws \CRM_Core_Exception
*/
public function testPaypalStandardCancel() {
$this->ids['contact'][0] = Civi\Api4\Contact::create()->setValues(['first_name' => 'Brer', 'last_name' => 'Rabbit'])->execute()->first()['id'];
$event = Event::create()->setValues(['title' => 'Event', 'start_date' => 'tomorrow', 'event_type_id:name' => 'Workshop'])->execute()->first();
$order = $this->callAPISuccess('Order', 'create', [
'contact_id' => $this->ids['contact'][0],
'financial_type_id' => 'Donation',
'invoice_id' => 123,
'line_items' => [
[
'line_item' => [
[
'line_total' => 5,
'qty' => 1,
'financial_type_id' => 1,
'entity_table' => 'civicrm_participant',
'price_field_id' => PriceField::get()->addSelect('id')->addWhere('name', '=', 'contribution_amount')->execute()->first()['id'],
],
],
'params' => [
'contact_id' => $this->ids['contact'][0],
'event_id' => $event['id'],
],
],
],
]);
$ipn = new CRM_Core_Payment_PayPalIPN([
'mc_gross' => 200,
'contactID' => $this->ids['contact'][0],
'contributionID' => $order['id'],
'module' => 'event',
'invoice' => 123,
'eventID' => $event['id'],
'participantID' => Participant::get()->addWhere('event_id', '=', (int) $event['id'])->addSelect('id')->execute()->first()['id'],
'payment_status' => 'Refunded',
'processor_id' => $this->createPaymentProcessor(['payment_processor_type_id' => 'PayPal_Standard']),
]);
$ipn->main();
$this->callAPISuccessGetSingle('Contribution', ['contribution_status_id' => 'Cancelled']);
$this->callAPISuccessGetCount('Participant', ['status_id' => 'Cancelled'], 1);
}
}
......@@ -9,6 +9,8 @@
+--------------------------------------------------------------------+
*/
use Civi\Api4\Contribution;
/**
* Class CRM_Core_Payment_BaseIPNTest
* @group headless
......@@ -405,15 +407,16 @@ class CRM_Core_Payment_BaseIPNTest extends CiviUnitTestCase {
public function testThatCancellingEventPaymentWillCancelAllAdditionalPendingParticipantsAndCreateCancellationActivities() {
$this->_setUpParticipantObjects('Pending from incomplete transaction');
$this->IPN->loadObjects($this->input, $this->ids, $this->objects, FALSE, $this->_processorId);
$additionalParticipantId = $this->participantCreate([
'event_id' => $this->_eventId,
'registered_by_id' => $this->_participantId,
'status_id' => 'Pending from incomplete transaction',
]);
$transaction = new CRM_Core_Transaction();
$this->IPN->cancelled($this->objects);
Contribution::update(FALSE)->setValues([
'cancel_date' => 'now',
'contribution_status_id:name' => 'Cancelled',
])->addWhere('id', '=', $this->_contributionId)->execute();
$cancelledParticipantsCount = civicrm_api3('Participant', 'get', [
'sequential' => 1,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment