From 0c6c47a506d4bf3a30b8ab900ba8fa1ba5429f53 Mon Sep 17 00:00:00 2001 From: eileenmcnaughton Date: Thu, 21 Jan 2016 01:02:18 +0000 Subject: [PATCH] CRM-17850 Allow payment processors to determine which edit fields are exposed --- CRM/Contribute/BAO/ContributionRecur.php | 3 + CRM/Contribute/Form/UpdateBilling.php | 12 +--- CRM/Contribute/Form/UpdateSubscription.php | 69 ++++++++++++++----- CRM/Core/Payment.php | 45 ++++++++++++ .../Contribute/Form/UpdateSubscription.tpl | 17 ++--- xml/schema/Contribute/ContributionRecur.xml | 30 ++++++++ 6 files changed, 137 insertions(+), 39 deletions(-) diff --git a/CRM/Contribute/BAO/ContributionRecur.php b/CRM/Contribute/BAO/ContributionRecur.php index 4ddab8cadf..b139c9469b 100644 --- a/CRM/Contribute/BAO/ContributionRecur.php +++ b/CRM/Contribute/BAO/ContributionRecur.php @@ -382,6 +382,9 @@ SELECT rec.id as recur_id, rec.currency, rec.campaign_id, rec.financial_type_id, + rec.next_sched_contribution_date, + rec.failure_retry_date, + rec.cycle_day, con.id as contribution_id, con.contribution_page_id, rec.contact_id, diff --git a/CRM/Contribute/Form/UpdateBilling.php b/CRM/Contribute/Form/UpdateBilling.php index 588ac72a0e..25a1e4df26 100644 --- a/CRM/Contribute/Form/UpdateBilling.php +++ b/CRM/Contribute/Form/UpdateBilling.php @@ -119,16 +119,10 @@ class CRM_Contribute_Form_UpdateBilling extends CRM_Core_Form { } /** - * This virtual function is used to set the default values of - * various form elements + * Set the default values of various form elements. * - * access public - * - * @return array - * reference to the array of default values - */ - /** * @return array + * Default values */ public function setDefaultValues() { $this->_defaults = array(); @@ -211,7 +205,7 @@ class CRM_Contribute_Form_UpdateBilling extends CRM_Core_Form { * The input form values. * @param array $files * The uploaded files if any. - * @param $self + * @param CRM_Core_Form $self * * * @return bool|array diff --git a/CRM/Contribute/Form/UpdateSubscription.php b/CRM/Contribute/Form/UpdateSubscription.php index fb61f50c46..c081d1b640 100644 --- a/CRM/Contribute/Form/UpdateSubscription.php +++ b/CRM/Contribute/Form/UpdateSubscription.php @@ -26,7 +26,6 @@ */ /** - * * @package CRM * @copyright CiviCRM LLC (c) 2004-2015 */ @@ -41,11 +40,11 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form { /** - * The recurring contribution id, used when editing the recurring contribution + * The recurring contribution id, used when editing the recurring contribution. * * @var int */ - protected $_crid = NULL; + protected $contributionRecurID = NULL; protected $_coid = NULL; @@ -57,6 +56,13 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form { public $_paymentProcessorObj = NULL; + /** + * Fields that affect the schedule and are defined as editable by the processor. + * + * @var array + */ + protected $editableScheduleFields = array(); + /** * The id of the contact associated with this recurring contribution. * @@ -71,11 +77,14 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form { */ public function preProcess() { - $this->_crid = CRM_Utils_Request::retrieve('crid', 'Integer', $this, FALSE); - if ($this->_crid) { - $this->_paymentProcessor = CRM_Contribute_BAO_ContributionRecur::getPaymentProcessor($this->_crid); + $this->contributionRecurID = CRM_Utils_Request::retrieve('crid', 'Integer', $this, FALSE); + if ($this->contributionRecurID) { + $this->_paymentProcessor = CRM_Contribute_BAO_ContributionRecur::getPaymentProcessor($this->contributionRecurID); + if (!$this->_paymentProcessor) { + CRM_Core_Error::statusBounce(ts('There is no valid processor for this subscription so it cannot be edited.')); + } $this->_paymentProcessorObj = $this->_paymentProcessor['object']; - $this->_subscriptionDetails = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($this->_crid); + $this->_subscriptionDetails = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($this->contributionRecurID); } $this->_coid = CRM_Utils_Request::retrieve('coid', 'Integer', $this, FALSE); @@ -83,13 +92,13 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form { $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getProcessorForEntity($this->_coid, 'contribute', 'info'); $this->_paymentProcessorObj = CRM_Financial_BAO_PaymentProcessor::getProcessorForEntity($this->_coid, 'contribute', 'obj'); $this->_subscriptionDetails = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($this->_coid, 'contribution'); - $this->_crid = $this->_subscriptionDetails->recur_id; + $this->contributionRecurID = $this->_subscriptionDetails->recur_id; } - elseif ($this->_crid) { - $this->_coid = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $this->_crid, 'id', 'contribution_recur_id'); + elseif ($this->contributionRecurID) { + $this->_coid = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $this->contributionRecurID, 'id', 'contribution_recur_id'); } - if ((!$this->_crid) || + if ((!$this->contributionRecurID) || ($this->_subscriptionDetails == CRM_Core_DAO::$_nullObject) ) { CRM_Core_Error::fatal('Required information missing.'); @@ -108,12 +117,27 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form { } $this->assign('self_service', $this->_selfService); - if (!$this->_paymentProcessorObj->isSupported('changeSubscriptionAmount')) { - $userAlert = ts('Updates made using this form will change the recurring contribution information stored in your CiviCRM database, but will NOT be sent to the payment processor. You must enter the same changes using the payment processor web site.'); - CRM_Core_Session::setStatus($userAlert, ts('Warning'), 'alert'); + $this->editableScheduleFields = $this->_paymentProcessorObj->getEditableRecurringScheduleFields(); + + $changeHelpText = $this->_paymentProcessorObj->getRecurringScheduleUpdateHelpText(); + if (!in_array('amount', $this->editableScheduleFields)) { + // Not sure if this is good behaviour - maintaining this existing behaviour for now. + CRM_Core_Session::setStatus($changeHelpText, ts('Warning'), 'alert'); + } + else { + $this->assign('changeHelpText', $changeHelpText); + } + $alreadyHardCodedFields = array('amount', 'installments'); + foreach ($this->editableScheduleFields as $editableScheduleField) { + if (!in_array($editableScheduleField, $alreadyHardCodedFields)) { + $this->addField($editableScheduleField, array( + 'entity' => 'ContributionRecur', + 'context' => $this->getDefaultContext(), + )); + } } - $this->assign('isChangeSupported', $this->_paymentProcessorObj->isSupported('changeSubscriptionAmount')); + $this->assign('editableScheduleFields', array_diff($this->editableScheduleFields, $alreadyHardCodedFields)); $this->assign('paymentProcessor', $this->_paymentProcessor); $this->assign('frequency_unit', $this->_subscriptionDetails->frequency_unit); $this->assign('frequency_interval', $this->_subscriptionDetails->frequency_interval); @@ -124,7 +148,7 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form { CRM_Utils_System::setTitle(ts('Update Recurring Contribution')); - // handle context redirection + // Handle context redirection. CRM_Contribute_BAO_ContributionRecur::setSubscriptionContext(); } @@ -134,13 +158,15 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form { * Note that in edit/view mode the default values are retrieved from the database. */ public function setDefaultValues() { - $this->_defaults = array(); $this->_defaults['amount'] = $this->_subscriptionDetails->amount; $this->_defaults['installments'] = $this->_subscriptionDetails->installments; $this->_defaults['campaign_id'] = $this->_subscriptionDetails->campaign_id; $this->_defaults['financial_type_id'] = $this->_subscriptionDetails->financial_type_id; $this->_defaults['is_notify'] = 1; + foreach ($this->editableScheduleFields as $field) { + $this->_defaults[$field] = $this->_subscriptionDetails->$field; + } return $this->_defaults; } @@ -169,7 +195,7 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form { CRM_Campaign_BAO_Campaign::addCampaign($this); } - if (CRM_Contribute_BAO_ContributionRecur::supportsFinancialTypeChange($this->_crid)) { + if (CRM_Contribute_BAO_ContributionRecur::supportsFinancialTypeChange($this->contributionRecurID)) { $this->addEntityRef('financial_type_id', ts('Financial Type'), array('entity' => 'FinancialType'), TRUE); } @@ -340,4 +366,11 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form { } } + /** + * Explicitly declare the form context. + */ + public function getDefaultContext() { + return 'create'; + } + } diff --git a/CRM/Core/Payment.php b/CRM/Core/Payment.php index b8792f60c7..2a94c7276d 100755 --- a/CRM/Core/Payment.php +++ b/CRM/Core/Payment.php @@ -418,6 +418,51 @@ abstract class CRM_Core_Payment { return $this->_paymentProcessor['payment_type'] == 1 ? $this->getCreditCardFormFields() : $this->getDirectDebitFormFields(); } + /** + * Get an array of the fields that can be edited on the recurring contribution. + * + * Some payment processors support editing the amount and other scheduling details of recurring payments, especially + * those which use tokens. Others are fixed. This function allows the processor to return an array of the fields that + * can be updated from the contribution recur edit screen. + * + * The fields are likely to be a subset of these + * - 'amount', + * - 'installments', + * - 'frequency_interval', + * - 'frequency_unit', + * - 'cycle_day', + * - 'next_sched_contribution_date', + * - 'end_date', + * - 'failure_retry_day', + * + * The form does not restrict which fields from the contribution_recur table can be added (although if the html_type + * metadata is not defined in the xml for the field it will cause an error. + * + * Open question - would it make sense to return membership_id in this - which is sometimes editable and is on that + * form (UpdateSubscription). + * + * @return array + */ + public function getEditableRecurringScheduleFields() { + if (method_exists($this, 'changeSubscriptionAmount')) { + return array('amount'); + } + } + + /** + * Get the help text to present on the recurring update page. + * + * This should reflect what can or cannot be edited. + * + * @return string + */ + public function getRecurringScheduleUpdateHelpText() { + if (!in_array('amount', $this->getEditableRecurringScheduleFields())) { + return ts('Updates made using this form will change the recurring contribution information stored in your CiviCRM database, but will NOT be sent to the payment processor. You must enter the same changes using the payment processor web site.'); + } + return ts('Use this form to change the amount or number of installments for this recurring contribution. Changes will be automatically sent to the payment processor. You can not change the contribution frequency.'); + } + /** * Get the metadata for all required fields. * diff --git a/templates/CRM/Contribute/Form/UpdateSubscription.tpl b/templates/CRM/Contribute/Form/UpdateSubscription.tpl index 2eb92a6b33..645af738ce 100644 --- a/templates/CRM/Contribute/Form/UpdateSubscription.tpl +++ b/templates/CRM/Contribute/Form/UpdateSubscription.tpl @@ -24,9 +24,9 @@ +--------------------------------------------------------------------+ *}
- {if $isChangeSupported} + {if $changeHelpText}
- {ts}Use this form to change the amount or number of installments for this recurring contribution. Changes will be automatically sent to the payment processor. You can not change the contribution frequency.{/ts} + {$changeHelpText}
{/if}
{include file="CRM/common/formButtons.tpl" location="top"}
@@ -37,21 +37,14 @@ {$form.installments.label}{$form.installments.html}
{ts}Total number of payments to be made. Set this to 0 if this is an open-ended commitment i.e. no set end date.{/ts} + {foreach from=$editableScheduleFields item='field'} + {$form.$field.label}{$form.$field.html} + {/foreach} {if !$self_service} {$form.is_notify.label}{$form.is_notify.html} {$form.campaign_id.label}{$form.campaign_id.html} {$form.financial_type_id.label}{$form.financial_type_id.html} {/if} - - {* Currently changes to interval, unit and cycle day are not supported. *} - {* - {$form.frequency_interval.label}{$form.frequency_interval.html}
- {ts}Number of time units for recurrence of payment.{/ts} - {$form.frequency_unit.label}{$form.frequency_unit.html}
- {ts}Time unit for recurrence of payment. For example, "month".{/ts} - {$form.cycle_day.label}{$form.cycle_day.html}
- {ts}Day in the period when the payment should be charged.{/ts} - *}
{include file="CRM/common/formButtons.tpl" location="bottom"}
diff --git a/xml/schema/Contribute/ContributionRecur.xml b/xml/schema/Contribute/ContributionRecur.xml index 9e5cfaf6be..e1dc131275 100644 --- a/xml/schema/Contribute/ContributionRecur.xml +++ b/xml/schema/Contribute/ContributionRecur.xml @@ -39,6 +39,9 @@ true Amount to be contributed or charged each recurrence. 1.6 + + Text + currency @@ -81,6 +84,9 @@ true Number of time units for recurrence of payment. 1.6 + + Text + installments @@ -88,6 +94,9 @@ int unsigned Total number of payments to be made. Set this to 0 if this is an open-ended commitment i.e. no set end date. 1.6 + + Text + start_date @@ -96,6 +105,9 @@ true The date the first scheduled recurring contribution occurs. 1.6 + + Select Date + create_date @@ -104,6 +116,9 @@ true When this recurring contribution record was created. 1.6 + + Select Date + modified_date @@ -111,6 +126,9 @@ datetime Last updated date for this record. mostly the last time a payment was received 1.6 + + Select Date + cancel_date @@ -118,6 +136,9 @@ datetime Date this recurring contribution was cancelled by contributor- if we can get access to it 1.6 + + Select Date + end_date @@ -125,6 +146,9 @@ datetime Date this recurring contribution finished successfully 1.6 + + Select Date + processor_id @@ -221,6 +245,9 @@ datetime Next scheduled date 4.4 + + Select Date + failure_count @@ -236,6 +263,9 @@ Retry Failed Attempt Date Date to retry failed attempt 1.6 + + Select Date + auto_renew -- 2.25.1