diff --git a/CRM/Member/DAO/MembershipType.php b/CRM/Member/DAO/MembershipType.php
index 4d1bce9cdbe1..ad5eee198db3 100644
--- a/CRM/Member/DAO/MembershipType.php
+++ b/CRM/Member/DAO/MembershipType.php
@@ -6,7 +6,7 @@
*
* Generated from xml/schema/CRM/Member/MembershipType.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:bf10593b5e20b28573e422fadfe689a7)
+ * (GenCodeChecksum:10ecb0e9e2b7693f4aeebeccce7407a3)
*/
/**
@@ -38,6 +38,17 @@ class CRM_Member_DAO_MembershipType extends CRM_Core_DAO {
*/
public static $_log = TRUE;
+ /**
+ * Paths for accessing this entity in the UI.
+ *
+ * @var string[]
+ */
+ protected static $_paths = [
+ 'add' => 'civicrm/admin/member/membershipType/add?action=add&reset=1',
+ 'update' => 'civicrm/admin/member/membershipType/add?action=update&id=[id]&reset=1',
+ 'delete' => 'civicrm/admin/member/membershipType/add?action=delete&id=[id]&reset=1',
+ ];
+
/**
* Membership ID
*
diff --git a/Civi/Api4/Service/Links/MembershipLinksProvider.php b/Civi/Api4/Service/Links/MembershipLinksProvider.php
new file mode 100644
index 000000000000..6a27c139c29b
--- /dev/null
+++ b/Civi/Api4/Service/Links/MembershipLinksProvider.php
@@ -0,0 +1,137 @@
+ 'alterMembershipLinks',
+ 'civi.api.respond' => 'alterMembershipLinksResult',
+ ];
+ }
+
+ public static function alterMembershipLinks(GenericHookEvent $e): void {
+ if ($e->entity == 'Membership') {
+ $addTemplate = [
+ 'api_action' => 'update',
+ 'ui_action' => '',
+ 'entity' => 'Membership',
+ 'path' => '',
+ 'text' => '',
+ 'icon' => 'fa-external-link',
+ 'target' => 'crm-popup',
+ ];
+ self::addLinks($e->links, $addTemplate);
+ }
+ }
+
+ public static function alterMembershipLinksResult(RespondEvent $e): void {
+ $request = $e->getApiRequest();
+ if ($request['version'] == 4 && $request->getEntityName() === 'Membership' && is_a($request, '\Civi\Api4\Action\GetLinks')) {
+ $links = (array) $e->getResponse();
+ $isUpdateBilling = $isCancelSupported = FALSE;
+
+ if (!\CRM_Core_Config::isEnabledBackOfficeCreditCardPayments()) {
+ self::unsetLinks($links, ['followup']);
+ }
+
+ $membershipId = $request->getValue('id');
+ $ownerMembershipId = $request->getValue('owner_membership_id');
+ if ($ownerMembershipId) {
+ self::unsetLinks($links, ['update', 'delete', 'renew', 'followup', 'cancelrecur', 'changebilling']);
+ }
+ elseif ($membershipId) {
+ $paymentObject = \CRM_Financial_BAO_PaymentProcessor::getProcessorForEntity($membershipId, 'membership', 'obj');
+ if (!empty($paymentObject)) {
+ $isUpdateBilling = $paymentObject->supports('updateSubscriptionBillingInfo');
+ }
+ if (!$isUpdateBilling) {
+ self::unsetLinks($links, ['changebilling']);
+ }
+ $isCancelSupported = \CRM_Member_BAO_Membership::isCancelSubscriptionSupported($membershipId);
+ if (!$isCancelSupported) {
+ self::unsetLinks($links, ['cancelrecur']);
+ }
+ }
+
+ // Unset renew and followup for deceased memberships.
+ $membershipStatus = $request->getValue('status_id:name');
+ if ($membershipStatus && $membershipStatus === 'Deceased') {
+ self::unsetLinks($links, ['renew', 'followup']);
+ }
+
+ $membershipTypeId = $request->getValue('membership_type_id');
+ if ($membershipTypeId && \CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()) {
+ $finType = \Civi\Api4\MembershipType::get(TRUE)
+ ->addSelect('financial_type_id:name')
+ ->addWhere('id', '=', $membershipTypeId)
+ ->execute()
+ ->first()['financial_type_id:name'] ?? NULL;
+ if ($finType && !\CRM_Core_Permission::check('edit contributions of type ' . $finType)) {
+ self::unsetLinks($links, ['update', 'renew', 'followup']);
+ }
+ if ($finType && !\CRM_Core_Permission::check('delete contributions of type ' . $finType)) {
+ self::unsetLinks($links, ['delete']);
+ }
+ }
+
+ $e->getResponse()->exchangeArray(array_values($links));
+ }
+ }
+
+ private static function addLinks(array &$newLinks, array $addTemplate) {
+ $actions = [
+ 'renew' => [
+ 'path' => 'civicrm/contact/view/membership?action=renew&reset=1&cid=[contact_id]&id=[id]&context=membership&selectedChild=member',
+ 'text' => ts('Renew Membership'),
+ ],
+ 'followup' => [
+ 'path' => 'civicrm/contact/view/membership?action=renew&reset=1&cid=[contact_id]&id=[id]&context=membership&selectedChild=member&mode=live',
+ 'text' => ts('Renew-Credit Card Membership'),
+ ],
+ 'cancelrecur' => [
+ 'path' => 'civicrm/contribute/unsubscribe?reset=1&cid=[contact_id]&mid=[id]&context=membership&selectedChild=member',
+ 'text' => ts('Cancel Auto-renewal'),
+ ],
+ 'changebilling' => [
+ 'path' => 'civicrm/contribute/updatebilling?reset=1&cid=[contact_id]&mid=[id]&context=membership&selectedChild=member',
+ 'text' => ts('Change Billing Details'),
+ ],
+ ];
+ foreach ($actions as $action => $values) {
+ $addTemplate['ui_action'] = $action;
+ $addTemplate['path'] = $values['path'];
+ $addTemplate['text'] = $values['text'];
+ $newLinks[] = $addTemplate;
+ }
+ }
+
+ private static function unsetLinks(array &$links, array $actions) {
+ foreach ($actions as $action) {
+ $actionLinkIndex = self::getActionIndex($links, $action);
+ if (isset($actionLinkIndex)) {
+ unset($links[$actionLinkIndex]);
+ }
+ }
+ }
+
+}
diff --git a/ext/civicrm_admin_ui/ang/afformTabMember.aff.html b/ext/civicrm_admin_ui/ang/afformTabMember.aff.html
new file mode 100644
index 000000000000..625ba920fe39
--- /dev/null
+++ b/ext/civicrm_admin_ui/ang/afformTabMember.aff.html
@@ -0,0 +1,16 @@
+
+
+
Click Add Membership to record a new membership. Click Submit Credit Card Membership to process a Membership on behalf of the member using their credit card.
+
+
+
+
Pending and Inactive Memberships
+
+
+
+
+
+
+
+
+
diff --git a/ext/civicrm_admin_ui/ang/afformTabMember.aff.php b/ext/civicrm_admin_ui/ang/afformTabMember.aff.php
new file mode 100644
index 000000000000..7114f893d135
--- /dev/null
+++ b/ext/civicrm_admin_ui/ang/afformTabMember.aff.php
@@ -0,0 +1,19 @@
+ 'search',
+ 'title' => E::ts('Memberships'),
+ 'placement' => [
+ 'contact_summary_tab',
+ ],
+ 'summary_contact_type' => [
+ 'Organization',
+ ],
+ 'summary_weight' => 30,
+ 'icon' => 'fa-id-badge',
+ 'permission' => [
+ 'access CiviCRM',
+ 'access CiviMember',
+ ],
+];
diff --git a/ext/civicrm_admin_ui/ang/afsearchTabMember.aff.html b/ext/civicrm_admin_ui/ang/afsearchTabMember.aff.html
new file mode 100644
index 000000000000..aa556bb73e1d
--- /dev/null
+++ b/ext/civicrm_admin_ui/ang/afsearchTabMember.aff.html
@@ -0,0 +1,10 @@
+
+
+
Click Add Membership to record a new membership. Click Submit Credit Card Membership to process a Membership on behalf of the member using their credit card.
+
+
+
+
Pending and Inactive Memberships
+
+
+
diff --git a/ext/civicrm_admin_ui/ang/afsearchTabMember.aff.php b/ext/civicrm_admin_ui/ang/afsearchTabMember.aff.php
new file mode 100644
index 000000000000..ec17736aff77
--- /dev/null
+++ b/ext/civicrm_admin_ui/ang/afsearchTabMember.aff.php
@@ -0,0 +1,20 @@
+ 'search',
+ 'title' => E::ts('Memberships'),
+ 'placement' => [
+ 'contact_summary_tab',
+ ],
+ 'summary_contact_type' => [
+ 'Individual',
+ 'Household',
+ ],
+ 'summary_weight' => 30,
+ 'icon' => 'fa-id-badge',
+ 'permission' => [
+ 'access CiviCRM',
+ 'access CiviMember',
+ ],
+];
diff --git a/ext/civicrm_admin_ui/managed/SavedSearch_Contact_Summary_Membership_Type.mgd.php b/ext/civicrm_admin_ui/managed/SavedSearch_Contact_Summary_Membership_Type.mgd.php
new file mode 100644
index 000000000000..6f9cc633472c
--- /dev/null
+++ b/ext/civicrm_admin_ui/managed/SavedSearch_Contact_Summary_Membership_Type.mgd.php
@@ -0,0 +1,154 @@
+ 'SavedSearch_Contact_Summary_Membership_Type',
+ 'entity' => 'SavedSearch',
+ 'cleanup' => 'unused',
+ 'update' => 'unmodified',
+ 'params' => [
+ 'version' => 4,
+ 'values' => [
+ 'name' => 'Contact_Summary_Membership_Type',
+ 'label' => E::ts('Contact Summary Membership Type'),
+ 'api_entity' => 'MembershipType',
+ 'api_params' => [
+ 'version' => 4,
+ 'select' => [
+ 'name',
+ 'period_type:label',
+ 'financial_type_id:label',
+ 'fixed_period_start_day',
+ 'minimum_fee',
+ 'duration_interval',
+ 'visibility:label',
+ ],
+ 'orderBy' => [],
+ 'where' => [
+ [
+ 'is_active',
+ '=',
+ TRUE,
+ ],
+ ],
+ 'groupBy' => [],
+ 'join' => [],
+ 'having' => [],
+ ],
+ ],
+ 'match' => [
+ 'name',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'SavedSearch_Contact_Summary_Membership_Type_SearchDisplay_Contact_Summary_Membership_Type',
+ 'entity' => 'SearchDisplay',
+ 'cleanup' => 'unused',
+ 'update' => 'unmodified',
+ 'params' => [
+ 'version' => 4,
+ 'values' => [
+ 'name' => 'Contact_Summary_Membership_Type',
+ 'label' => E::ts('Contact Summary Membership Type'),
+ 'saved_search_id.name' => 'Contact_Summary_Membership_Type',
+ 'type' => 'table',
+ 'settings' => [
+ 'description' => E::ts('The following Membership Types are associated with this organization. Click Members for a listing of all contacts who have memberships of that type. Click Edit to modify the settings for that type.'),
+ 'sort' => [],
+ 'limit' => 50,
+ 'pager' => [
+ 'hide_single' => TRUE,
+ ],
+ 'placeholder' => 5,
+ 'columns' => [
+ [
+ 'type' => 'field',
+ 'key' => 'name',
+ 'dataType' => 'String',
+ 'label' => E::ts('Name'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'period_type:label',
+ 'dataType' => 'String',
+ 'label' => E::ts('Period'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'fixed_period_start_day',
+ 'dataType' => 'Integer',
+ 'label' => E::ts('Fixed Start'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'minimum_fee',
+ 'dataType' => 'Money',
+ 'label' => E::ts('Minimum Fee'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'duration_interval',
+ 'dataType' => 'Integer',
+ 'label' => E::ts('Duration'),
+ 'sortable' => TRUE,
+ 'rewrite' => '[duration_interval] [duration_unit:label]',
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'visibility:label',
+ 'dataType' => 'String',
+ 'label' => E::ts('Visibility'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'size' => 'btn-xs',
+ 'links' => [
+ [
+ 'path' => 'civicrm/member/search?reset=1&force=1&type=[id]',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('Members'),
+ 'style' => 'default',
+ 'condition' => [],
+ 'task' => '',
+ 'entity' => '',
+ 'action' => '',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ ],
+ [
+ 'entity' => 'MembershipType',
+ 'action' => 'update',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ 'icon' => 'fa-pencil',
+ 'text' => E::ts('Edit'),
+ 'style' => 'default',
+ 'path' => '',
+ 'task' => '',
+ 'condition' => [],
+ ],
+ ],
+ 'type' => 'buttons',
+ 'alignment' => 'text-right',
+ ],
+ ],
+ 'actions' => FALSE,
+ 'classes' => [
+ 'table',
+ 'table-striped',
+ ],
+ ],
+ ],
+ 'match' => [
+ 'saved_search_id',
+ 'name',
+ ],
+ ],
+ ],
+];
diff --git a/ext/civicrm_admin_ui/managed/SavedSearch_Contact_Summary_Memberships.mgd.php b/ext/civicrm_admin_ui/managed/SavedSearch_Contact_Summary_Memberships.mgd.php
new file mode 100644
index 000000000000..ed6f1a634847
--- /dev/null
+++ b/ext/civicrm_admin_ui/managed/SavedSearch_Contact_Summary_Memberships.mgd.php
@@ -0,0 +1,493 @@
+ 'SavedSearch_Contact_Summary_Memberships',
+ 'entity' => 'SavedSearch',
+ 'cleanup' => 'unused',
+ 'update' => 'unmodified',
+ 'params' => [
+ 'version' => 4,
+ 'values' => [
+ 'name' => 'Contact_Summary_Memberships',
+ 'label' => E::ts('Contact Summary Memberships'),
+ 'api_entity' => 'Membership',
+ 'api_params' => [
+ 'version' => 4,
+ 'select' => [
+ 'id',
+ 'membership_type_id:label',
+ 'join_date',
+ 'start_date',
+ 'end_date',
+ 'status_id:label',
+ 'source',
+ 'IF(contribution_recur_id, "Yes", contribution_recur_id) AS IF_contribution_recur_id_contribution_recur_id',
+ 'IF(owner_membership_id, "(by relationship)", owner_membership_id) AS IF_owner_membership_id_owner_membership_id',
+ 'owner_membership_id',
+ ],
+ 'orderBy' => [],
+ 'where' => [],
+ 'groupBy' => [],
+ 'join' => [],
+ 'having' => [],
+ ],
+ ],
+ 'match' => [
+ 'name',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'SavedSearch_Contact_Summary_Memberships_SearchDisplay_Contact_Summary_Memberships_Active',
+ 'entity' => 'SearchDisplay',
+ 'cleanup' => 'unused',
+ 'update' => 'unmodified',
+ 'params' => [
+ 'version' => 4,
+ 'values' => [
+ 'name' => 'Contact_Summary_Memberships_Active',
+ 'label' => E::ts('Contact Summary Memberships Active'),
+ 'saved_search_id.name' => 'Contact_Summary_Memberships',
+ 'type' => 'table',
+ 'settings' => [
+ 'description' => E::ts('Active Memberships'),
+ 'sort' => [
+ [
+ 'id',
+ 'DESC',
+ ],
+ ],
+ 'limit' => 0,
+ 'pager' => FALSE,
+ 'placeholder' => 5,
+ 'columns' => [
+ [
+ 'type' => 'field',
+ 'key' => 'membership_type_id:label',
+ 'dataType' => 'Integer',
+ 'label' => E::ts('Membership'),
+ 'sortable' => TRUE,
+ 'rewrite' => '[membership_type_id:label] [IF_owner_membership_id_owner_membership_id]',
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'join_date',
+ 'dataType' => 'Date',
+ 'label' => E::ts('Member Since'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'start_date',
+ 'dataType' => 'Date',
+ 'label' => E::ts('Membership Start Date'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'end_date',
+ 'dataType' => 'Date',
+ 'label' => E::ts('Membership Expiration Date'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'status_id:label',
+ 'dataType' => 'Integer',
+ 'label' => E::ts('Status'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'source',
+ 'dataType' => 'String',
+ 'label' => E::ts('Membership Source'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'IF_contribution_recur_id_contribution_recur_id',
+ 'dataType' => 'String',
+ 'label' => E::ts('Auto-Renew'),
+ 'sortable' => TRUE,
+ 'title' => NULL,
+ 'cssRules' => [],
+ 'rewrite' => '',
+ 'icons' => [
+ [
+ 'icon' => 'fa-check',
+ 'side' => 'left',
+ 'if' => [
+ 'IF_contribution_recur_id_contribution_recur_id',
+ 'IS NOT EMPTY',
+ ],
+ ],
+ ],
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'owner_membership_id',
+ 'dataType' => 'Integer',
+ 'label' => E::ts('Related'),
+ 'sortable' => TRUE,
+ 'rewrite' => "{crmAPI var='owner_count' entity='Membership' action='getcount' owner_membership_id=[id]}\n{if \$owner_count}\n {\$owner_count} {ts}created{/ts}\n{else}\n {ts}N/A{/ts}\n{/if}",
+ ],
+ [
+ 'text' => '',
+ 'style' => 'default',
+ 'size' => 'btn-xs',
+ 'icon' => 'fa-bars',
+ 'links' => [
+ [
+ 'entity' => 'Membership',
+ 'action' => 'view',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('View Membership'),
+ 'style' => 'default',
+ 'path' => '',
+ 'task' => '',
+ 'condition' => [],
+ ],
+ [
+ 'path' => '',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('View Primary Member'),
+ 'style' => 'default',
+ 'condition' => [],
+ 'task' => '',
+ 'entity' => 'Membership',
+ 'action' => 'view',
+ 'join' => 'owner_membership_id',
+ 'target' => 'crm-popup',
+ ],
+ [
+ 'entity' => 'Membership',
+ 'action' => 'update',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ 'icon' => 'fa-pencil',
+ 'text' => E::ts('Update Membership'),
+ 'style' => 'default',
+ 'path' => '',
+ 'task' => '',
+ 'condition' => [],
+ ],
+ [
+ 'path' => '',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('Renew Membership'),
+ 'style' => 'default',
+ 'condition' => [],
+ 'task' => '',
+ 'entity' => 'Membership',
+ 'action' => 'renew',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ ],
+ [
+ 'path' => '',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('Renew-Credit Card Membership'),
+ 'style' => 'default',
+ 'condition' => [],
+ 'task' => '',
+ 'entity' => 'Membership',
+ 'action' => 'followup',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ ],
+ [
+ 'entity' => 'Membership',
+ 'action' => 'delete',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ 'icon' => 'fa-trash',
+ 'text' => E::ts('Delete Membership'),
+ 'style' => 'danger',
+ 'path' => '',
+ 'task' => '',
+ 'condition' => [],
+ ],
+ [
+ 'path' => '',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('Cancel Auto-renewal'),
+ 'style' => 'default',
+ 'condition' => [],
+ 'task' => '',
+ 'entity' => 'Membership',
+ 'action' => 'cancelrecur',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ ],
+ [
+ 'path' => '',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('Change Billing Details'),
+ 'style' => 'default',
+ 'condition' => [],
+ 'task' => '',
+ 'entity' => 'Membership',
+ 'action' => 'changebilling',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ ],
+ ],
+ 'type' => 'menu',
+ 'alignment' => 'text-right',
+ ],
+ ],
+ 'actions' => FALSE,
+ 'classes' => [
+ 'table',
+ 'table-striped',
+ ],
+ 'noResultsText' => 'No memberships have been recorded for this contact.',
+ 'toolbar' => [
+ [
+ 'action' => '',
+ 'entity' => '',
+ 'text' => E::ts('Add Membership'),
+ 'icon' => 'fa-external-link',
+ 'style' => 'default',
+ 'target' => 'crm-popup',
+ 'join' => '',
+ 'path' => 'civicrm/contact/view/membership?reset=1&action=add&cid=[contact_id]&context=membership',
+ 'task' => '',
+ 'condition' => [],
+ ],
+ [
+ 'path' => 'civicrm/contact/view/membership?reset=1&action=add&cid=[contact_id]&context=membership&mode=live',
+ 'icon' => 'fa-credit-card',
+ 'text' => E::ts('Submit Credit Card Membership'),
+ 'style' => 'default',
+ 'condition' => [],
+ 'task' => '',
+ 'entity' => '',
+ 'action' => '',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ ],
+ ],
+ ],
+ ],
+ 'match' => [
+ 'saved_search_id',
+ 'name',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'SavedSearch_Contact_Summary_Memberships_SearchDisplay_Contact_Summary_Memberships_Inactive',
+ 'entity' => 'SearchDisplay',
+ 'cleanup' => 'unused',
+ 'update' => 'unmodified',
+ 'params' => [
+ 'version' => 4,
+ 'values' => [
+ 'name' => 'Contact_Summary_Memberships_Inactive',
+ 'label' => E::ts('Contact Summary Memberships Inactive'),
+ 'saved_search_id.name' => 'Contact_Summary_Memberships',
+ 'type' => 'table',
+ 'settings' => [
+ 'description' => '',
+ 'sort' => [
+ [
+ 'id',
+ 'DESC',
+ ],
+ ],
+ 'limit' => 0,
+ 'pager' => FALSE,
+ 'placeholder' => 5,
+ 'columns' => [
+ [
+ 'type' => 'field',
+ 'key' => 'membership_type_id:label',
+ 'dataType' => 'Integer',
+ 'label' => E::ts('Membership'),
+ 'sortable' => TRUE,
+ 'rewrite' => '[membership_type_id:label] [IF_owner_membership_id_owner_membership_id]',
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'join_date',
+ 'dataType' => 'Date',
+ 'label' => E::ts('Member Since'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'start_date',
+ 'dataType' => 'Date',
+ 'label' => E::ts('Membership Start Date'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'end_date',
+ 'dataType' => 'Date',
+ 'label' => E::ts('Membership Expiration Date'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'status_id:label',
+ 'dataType' => 'Integer',
+ 'label' => E::ts('Status'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'source',
+ 'dataType' => 'String',
+ 'label' => E::ts('Membership Source'),
+ 'sortable' => TRUE,
+ ],
+ [
+ 'type' => 'field',
+ 'key' => 'IF_contribution_recur_id_contribution_recur_id',
+ 'dataType' => 'String',
+ 'label' => E::ts('Auto-Renew'),
+ 'sortable' => TRUE,
+ 'title' => NULL,
+ 'cssRules' => [],
+ 'rewrite' => '',
+ 'icons' => [
+ [
+ 'icon' => 'fa-check',
+ 'side' => 'left',
+ 'if' => [
+ 'IF_contribution_recur_id_contribution_recur_id',
+ 'IS NOT EMPTY',
+ ],
+ ],
+ ],
+ ],
+ [
+ 'text' => '',
+ 'style' => 'default',
+ 'size' => 'btn-xs',
+ 'icon' => 'fa-bars',
+ 'links' => [
+ [
+ 'entity' => 'Membership',
+ 'action' => 'view',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('View Membership'),
+ 'style' => 'default',
+ 'path' => '',
+ 'task' => '',
+ 'condition' => [],
+ ],
+ [
+ 'path' => '',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('View Primary Member'),
+ 'style' => 'default',
+ 'condition' => [],
+ 'task' => '',
+ 'entity' => 'Membership',
+ 'action' => 'view',
+ 'join' => 'owner_membership_id',
+ 'target' => 'crm-popup',
+ ],
+ [
+ 'entity' => 'Membership',
+ 'action' => 'update',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ 'icon' => 'fa-pencil',
+ 'text' => E::ts('Update Membership'),
+ 'style' => 'default',
+ 'path' => '',
+ 'task' => '',
+ 'condition' => [],
+ ],
+ [
+ 'path' => '',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('Renew Membership'),
+ 'style' => 'default',
+ 'condition' => [],
+ 'task' => '',
+ 'entity' => 'Membership',
+ 'action' => 'renew',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ ],
+ [
+ 'path' => '',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('Renew-Credit Card Membership'),
+ 'style' => 'default',
+ 'condition' => [],
+ 'task' => '',
+ 'entity' => 'Membership',
+ 'action' => 'followup',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ ],
+ [
+ 'entity' => 'Membership',
+ 'action' => 'delete',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ 'icon' => 'fa-trash',
+ 'text' => E::ts('Delete Membership'),
+ 'style' => 'danger',
+ 'path' => '',
+ 'task' => '',
+ 'condition' => [],
+ ],
+ [
+ 'path' => '',
+ 'entity' => 'Membership',
+ 'action' => 'cancelrecur',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('Cancel Auto-renewal'),
+ 'style' => 'default',
+ 'task' => '',
+ 'condition' => [],
+ ],
+ [
+ 'path' => '',
+ 'entity' => 'Membership',
+ 'action' => 'changebilling',
+ 'join' => '',
+ 'target' => 'crm-popup',
+ 'icon' => 'fa-external-link',
+ 'text' => E::ts('Change Billing Details'),
+ 'style' => 'default',
+ 'task' => '',
+ 'condition' => [],
+ ],
+ ],
+ 'type' => 'menu',
+ 'alignment' => 'text-right',
+ ],
+ ],
+ 'actions' => FALSE,
+ 'classes' => [
+ 'table',
+ 'table-striped',
+ 'disabled',
+ ],
+ 'noResultsText' => '',
+ ],
+ ],
+ 'match' => [
+ 'saved_search_id',
+ 'name',
+ ],
+ ],
+ ],
+];
diff --git a/templates/CRM/Contact/Page/View/Summary.js b/templates/CRM/Contact/Page/View/Summary.js
index a5faa0821a2b..7f7e2ece0089 100644
--- a/templates/CRM/Contact/Page/View/Summary.js
+++ b/templates/CRM/Contact/Page/View/Summary.js
@@ -409,6 +409,12 @@
CRM.tabHeader.resetTab('#tab_member');
});
+ // Changing membership may affect related contributions & activity. Ensure they are refreshed.
+ $('#contact-member').on('crmPopupFormSuccess', function() {
+ CRM.tabHeader.resetTab('#tab_contribute', true);
+ CRM.tabHeader.resetTab('#tab_activity', true);
+ });
+
onResize();
$(window).resize(onResize);
});
diff --git a/xml/schema/Member/MembershipType.xml b/xml/schema/Member/MembershipType.xml
index df82e707f464..ae0328dbfadc 100644
--- a/xml/schema/Member/MembershipType.xml
+++ b/xml/schema/Member/MembershipType.xml
@@ -9,6 +9,11 @@
true
CiviMember
name
+
+ civicrm/admin/member/membershipType/add?action=add&reset=1
+ civicrm/admin/member/membershipType/add?action=update&id=[id]&reset=1
+ civicrm/admin/member/membershipType/add?action=delete&id=[id]&reset=1
+
id
Membership Type ID