Skip to content

Commit

Permalink
CRM-38: Show Recurring Contributions on Membership Modal View
Browse files Browse the repository at this point in the history
Currently, when viewing a membership from contact's detailed view (on
memberships tab), it is hard to tell if a membership has any recurring
contributions associated to it, even though you can see all payments done for
the membership.

Added a recurring contributions section below the contributions table
currently being shown, by loading recurring contributions using ajax call to
load list of recurring contributions.

Added recurring contributionslist to membership edit view using ajax call.
  • Loading branch information
MiyaNoctem committed May 10, 2018
1 parent 421e9a1 commit 6e3ba0b
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 20 deletions.
6 changes: 6 additions & 0 deletions CRM/Contribute/xml/Menu/Contribute.xml
Original file line number Diff line number Diff line change
Expand Up @@ -329,4 +329,10 @@
<page_callback>CRM_Contribute_Page_ContributionRecurPayments</page_callback>
<access_arguments>access CiviContribute</access_arguments>
</item>
<item>
<path>civicrm/membership/recurring-contributions</path>
<title>Membership Recurring Contributions</title>
<page_callback>CRM_Member_Page_RecurringContributions</page_callback>
<access_arguments>access CiviContribute</access_arguments>
</item>
</menu>
52 changes: 40 additions & 12 deletions CRM/Member/Form/MembershipView.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@

/**
* This class generates form components for Payment-Instrument
*
*/
class CRM_Member_Form_MembershipView extends CRM_Core_Form {

Expand All @@ -46,6 +45,20 @@ class CRM_Member_Form_MembershipView extends CRM_Core_Form {
*/
static $_links = NULL;

/**
* The id of the membership being viewed.
*
* @var int
*/
private $membershipID;

/**
* Contact's ID.
*
* @var int
*/
private $contactID;

/**
* Add context information at the end of a link.
*
Expand Down Expand Up @@ -148,16 +161,16 @@ public function relAction($action, $owner) {
* @return void
*/
public function preProcess() {

$values = array();
$id = CRM_Utils_Request::retrieve('id', 'Positive', $this);
$this->membershipID = CRM_Utils_Request::retrieve('id', 'Positive', $this);
$this->contactID = CRM_Utils_Request::retrieve('cid', 'Positive', $this);

// Make sure context is assigned to template for condition where we come here view civicrm/membership/view
$context = CRM_Utils_Request::retrieve('context', 'String', $this);
$this->assign('context', $context);

if ($id) {
$params = array('id' => $id);
if ($this->membershipID) {
$params = array('id' => $this->membershipID);
CRM_Member_BAO_Membership::retrieve($params, $values);
if (CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()) {
$finTypeId = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $values['membership_type_id'], 'financial_type_id');
Expand All @@ -181,12 +194,12 @@ public function preProcess() {
$this->assign('accessContribution', FALSE);
if (CRM_Core_Permission::access('CiviContribute')) {
$this->assign('accessContribution', TRUE);
CRM_Member_Page_Tab::associatedContribution($values['contact_id'], $id);
CRM_Member_Page_Tab::associatedContribution($values['contact_id'], $this->membershipID);
}

//Provide information about membership source when it is the result of a relationship (CRM-1901)
$values['owner_membership_id'] = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership',
$id,
$this->membershipID,
'owner_membership_id'
);

Expand Down Expand Up @@ -375,12 +388,12 @@ public function preProcess() {

CRM_Member_Page_Tab::setContext($this, $values['contact_id']);

$memType = CRM_Core_DAO::getFieldValue("CRM_Member_DAO_Membership", $id, "membership_type_id");
$memType = CRM_Core_DAO::getFieldValue("CRM_Member_DAO_Membership", $this->membershipID, "membership_type_id");

$groupTree = CRM_Core_BAO_CustomGroup::getTree('Membership', NULL, $id, 0, $memType);
CRM_Core_BAO_CustomGroup::buildCustomDataView($this, $groupTree, FALSE, NULL, NULL, NULL, $id);
$groupTree = CRM_Core_BAO_CustomGroup::getTree('Membership', NULL, $this->membershipID, 0, $memType);
CRM_Core_BAO_CustomGroup::buildCustomDataView($this, $groupTree, FALSE, NULL, NULL, NULL, $this->membershipID);

$isRecur = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $id, 'contribution_recur_id');
$isRecur = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $this->membershipID, 'contribution_recur_id');

$autoRenew = $isRecur ? TRUE : FALSE;
}
Expand All @@ -389,7 +402,7 @@ public function preProcess() {
$values['membership_type'] .= ' (test) ';
}

$subscriptionCancelled = CRM_Member_BAO_Membership::isSubscriptionCancelled($id);
$subscriptionCancelled = CRM_Member_BAO_Membership::isSubscriptionCancelled($this->membershipID);
$values['auto_renew'] = ($autoRenew && !$subscriptionCancelled) ? 'Yes' : 'No';

//do check for campaigns
Expand All @@ -401,6 +414,21 @@ public function preProcess() {
$this->assign($values);
}

/**
* This method returns the links that are given for recur search row.
* currently the links added for each row are:
* - View
* - Edit
* - Cancel
*
* @param bool $id
*
* @return array
*/
private function recurLinks($id) {
return CRM_Contribute_Page_Tab::recurLinks($id, 'contribution');
}

/**
* Build the form object.
*
Expand Down
155 changes: 155 additions & 0 deletions CRM/Member/Page/RecurringContributions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php

/**
* Shows list of recurring contributions related to membership.
*/
class CRM_Member_Page_RecurringContributions extends CRM_Core_Page {

/**
* ID of the membership for which we need to see related recurring contributions.
*
* @var int
*/
private $membershipID = NULL;

/**
* ID of the contact owner of the membership.
*
* @var int
*/
public $contactID = NULL;

/**
* Builds list of recurring contributions associated to membership.
*
* @return null
*/
public function run() {
$this->membershipID = CRM_Utils_Request::retrieve('membershipID', 'Positive', $this);
$this->contactID = CRM_Utils_Request::retrieve('cid', 'Positive', $this, TRUE);

$this->loadRecurringContributions();

return parent::run();
}

/**
* Loads recurring contributions and assigns them to the form, to be used on
* the template.
*/
private function loadRecurringContributions() {
$recurringContributions = $this->getRecurContributions($this->membershipID);

if (!empty($recurringContributions)) {
$this->assign('recurRows', $recurringContributions);
$this->assign('recur', TRUE);
}
}

/**
* Obtains list of recurring contributions associated to a membership.
*
* @param int $membershipID
*
* @return array
*/
private function getRecurContributions($membershipID) {
$result = civicrm_api3('MembershipPayment', 'get', array(
'sequential' => 1,
'contribution_id.contribution_recur_id.id' => ['IS NOT NULL' => TRUE],
'options' => ['limit' => 0],
'return' => array(
'contribution_id.contribution_recur_id.id',
'contribution_id.contribution_recur_id.contact_id',
'contribution_id.contribution_recur_id.start_date',
'contribution_id.contribution_recur_id.end_date',
'contribution_id.contribution_recur_id.next_sched_contribution_date',
'contribution_id.contribution_recur_id.amount',
'contribution_id.contribution_recur_id.currency',
'contribution_id.contribution_recur_id.frequency_unit',
'contribution_id.contribution_recur_id.frequency_interval',
'contribution_id.contribution_recur_id.installments',
'contribution_id.contribution_recur_id.contribution_status_id',
'contribution_id.contribution_recur_id.is_test',
'contribution_id.contribution_recur_id.payment_processor_id',
),
'membership_id' => $membershipID,
));
$recurringContributions = array();
$contributionStatuses = CRM_Contribute_PseudoConstant::contributionStatus();

foreach ($result['values'] as $payment) {
$recurringContributionID = $payment['contribution_id.contribution_recur_id.id'];
$alreadyProcessed = isset($recurringContributions[$recurringContributionID]);

if ($alreadyProcessed) {
continue;
}

foreach ($payment as $field => $value) {
$key = strtr($field, array('contribution_id.contribution_recur_id.' => ''));
$recurringContributions[$recurringContributionID][$key] = $value;
}

$contactID = $recurringContributions[$recurringContributionID]['contact_id'];
$contributionStatusID = $recurringContributions[$recurringContributionID]['contribution_status_id'];

$recurringContributions[$recurringContributionID]['id'] = $recurringContributionID;
$recurringContributions[$recurringContributionID]['contactId'] = $contactID;
$recurringContributions[$recurringContributionID]['contribution_status'] = CRM_Utils_Array::value($contributionStatusID, $contributionStatuses);

$this->setActionsForRecurringContribution($recurringContributionID, $recurringContributions[$recurringContributionID]);
}
return $recurringContributions;
}

/**
* Calculates and assigns the actions available for given recurring
* contribution.
*
* @param int $recurID
* @param array $recurringContribution
*/
private function setActionsForRecurringContribution($recurID, &$recurringContribution) {
$action = array_sum(array_keys($this->recurLinks($recurID)));
// no action allowed if it's not active
$recurringContribution['is_active'] = ($recurringContribution['contribution_status_id'] != 3);
if ($recurringContribution['is_active']) {
$details = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($recurringContribution['id'], 'recur');
$hideUpdate = $details->membership_id & $details->auto_renew;
if ($hideUpdate || empty($details->processor_id)) {
$action -= CRM_Core_Action::UPDATE;
}
$recurringContribution['action'] = CRM_Core_Action::formLink(
$this->recurLinks($recurID),
$action,
array(
'cid' => $this->contactID,
'crid' => $recurID,
'cxt' => 'contribution',
),
ts('more'),
FALSE,
'contribution.selector.recurring',
'Contribution',
$recurID
);
}
}

/**
* This method returns the links that are given for recur search row.
* currently the links added for each row are:
* - View
* - Edit
* - Cancel
*
* @param bool $id
*
* @return array
*/
private function recurLinks($id) {
return CRM_Contribute_Page_Tab::recurLinks($id, 'contribution');
}

}
6 changes: 3 additions & 3 deletions Civi/Test/Api3TestTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public function callAPISuccess($entity, $action, $params, $checkAgainst = NULL)
* @param string $entity
* @param array $params
* @param null $count
* @throws Exception
* @throws \Exception
* @return array|int
*/
public function callAPISuccessGetCount($entity, $params, $count = NULL) {
Expand All @@ -170,7 +170,7 @@ public function callAPISuccessGetCount($entity, $params, $count = NULL) {
);
$result = $this->civicrm_api($entity, 'getcount', $params);
if (!is_int($result) || !empty($result['is_error']) || isset($result['values'])) {
throw new Exception('Invalid getcount result : ' . print_r($result, TRUE) . " type :" . gettype($result));
throw new \Exception('Invalid getcount result : ' . print_r($result, TRUE) . " type :" . gettype($result));
}
if (is_int($count)) {
$this->assertEquals($count, $result, "incorrect count returned from $entity getcount");
Expand All @@ -193,7 +193,7 @@ public function callAPISuccessGetCount($entity, $params, $count = NULL) {
* - array
* - object
*
* @throws Exception
* @throws \Exception
* @return array|int
*/
public function callAPISuccessGetSingle($entity, $params, $checkAgainst = NULL) {
Expand Down
28 changes: 27 additions & 1 deletion templates/CRM/Member/Form/Membership.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,33 @@
{if $accessContribution and $action eq 2 and $rows.0.contribution_id}
<div class="crm-accordion-wrapper">
<div class="crm-accordion-header">{ts}Related Contributions{/ts}</div>
<div class="crm-accordion-body">{include file="CRM/Contribute/Form/Selector.tpl" context="Search"}</div>
<div class="crm-accordion-body">
{include file="CRM/Contribute/Form/Selector.tpl" context="Search"}
<script type="text/javascript">
var membershipID = {$entityID};
var contactID = {$contactId};
{literal}
CRM.$(function($) {
CRM.loadPage(
CRM.url(
'civicrm/membership/recurring-contributions',
{
reset: 1,
membershipID: membershipID,
cid: contactID
},
'back'
),
{
target : '#membership-recurring-contributions',
dialog : false
}
);
});
{/literal}
</script>
<div id="membership-recurring-contributions"></div>
</div>
</div>
{/if}
{if $softCredit}
Expand Down
38 changes: 34 additions & 4 deletions templates/CRM/Member/Form/MembershipView.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,41 @@

{include file="CRM/Custom/Page/CustomDataView.tpl"}

{if $accessContribution and $rows.0.contribution_id}
<div class="crm-accordion-wrapper">
<div class="crm-accordion-header">{ts}Related Contributions{/ts}</div>
<div class="crm-accordion-body">{include file="CRM/Contribute/Form/Selector.tpl" context="Search"}</div>
{if $accessContribution}
<div class="crm-accordion-wrapper">
<div class="crm-accordion-header">
{ts}Related Contributions and Recurring Contributions{/ts}
</div>
<div class="crm-accordion-body">
{if $rows.0.contribution_id}
{include file="CRM/Contribute/Form/Selector.tpl" context="Search"}
{/if}
<script type="text/javascript">
var membershipID = {$id};
var contactID = {$contactId};
{literal}
CRM.$(function($) {
CRM.loadPage(
CRM.url(
'civicrm/membership/recurring-contributions',
{
reset: 1,
membershipID: membershipID,
cid: contactID
},
'back'
),
{
target : '#membership-recurring-contributions',
dialog : false
}
);
});
{/literal}
</script>
<div id="membership-recurring-contributions"></div>
</div>
</div>
{/if}
{if $softCredit}
Expand Down
6 changes: 6 additions & 0 deletions templates/CRM/Member/Page/RecurringContributions.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{if $recur}
<div class="solid-border-top">
<br /><label>{ts 1=$displayName}Recurring Contributions{/ts}</label>
</div>
{include file="CRM/Contribute/Page/ContributionRecur.tpl" action=16}
{/if}

0 comments on commit 6e3ba0b

Please sign in to comment.