CRM-17718 add Financial type to recur form
[civicrm-core.git] / CRM / Contribute / Form / UpdateSubscription.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2015
32 */
33
34 /**
35 * This class generates form components generic to recurring contributions
36 *
37 * It delegates the work to lower level subclasses and integrates the changes
38 * back in. It also uses a lot of functionality with the CRM API's, so any change
39 * made here could potentially affect the API etc. Be careful, be aware, use unit tests.
40 */
41 class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form {
42
43 /**
44 * The recurring contribution id, used when editing the recurring contribution
45 *
46 * @var int
47 */
48 protected $_crid = NULL;
49
50 protected $_coid = NULL;
51
52 protected $_subscriptionDetails = NULL;
53
54 protected $_selfService = FALSE;
55
56 public $_paymentProcessor = NULL;
57
58 public $_paymentProcessorObj = NULL;
59
60 /**
61 * The id of the contact associated with this recurring contribution.
62 *
63 * @var int
64 */
65 public $_contactID;
66
67 public function preProcess() {
68
69 $this->_crid = CRM_Utils_Request::retrieve('crid', 'Integer', $this, FALSE);
70 if ($this->_crid) {
71 $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getProcessorForEntity($this->_crid, 'recur', 'info');
72 $this->_paymentProcessorObj = CRM_Financial_BAO_PaymentProcessor::getProcessorForEntity($this->_crid, 'recur', 'obj');
73 $this->_subscriptionDetails = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($this->_crid);
74 }
75
76 $this->_coid = CRM_Utils_Request::retrieve('coid', 'Integer', $this, FALSE);
77 if ($this->_coid) {
78 $this->_paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getProcessorForEntity($this->_coid, 'contribute', 'info');
79 $this->_paymentProcessorObj = CRM_Financial_BAO_PaymentProcessor::getProcessorForEntity($this->_coid, 'contribute', 'obj');
80 $this->_subscriptionDetails = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($this->_coid, 'contribution');
81 $this->_crid = $this->_subscriptionDetails->recur_id;
82 }
83 elseif ($this->_crid) {
84 $this->_coid = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $this->_crid, 'id', 'contribution_recur_id');
85 }
86
87 if ((!$this->_crid) ||
88 ($this->_subscriptionDetails == CRM_Core_DAO::$_nullObject)
89 ) {
90 CRM_Core_Error::fatal('Required information missing.');
91 }
92
93 if ($this->_subscriptionDetails->membership_id && $this->_subscriptionDetails->auto_renew) {
94 CRM_Core_Error::fatal(ts('You cannot update the subscription.'));
95 }
96
97 if (!CRM_Core_Permission::check('edit contributions')) {
98 $userChecksum = CRM_Utils_Request::retrieve('cs', 'String', $this, FALSE);
99 if (!CRM_Contact_BAO_Contact_Utils::validChecksum($this->_subscriptionDetails->contact_id, $userChecksum)) {
100 CRM_Core_Error::fatal(ts('You do not have permission to update subscription.'));
101 }
102 $this->_selfService = TRUE;
103 }
104 $this->assign('self_service', $this->_selfService);
105
106 if (!$this->_paymentProcessorObj->isSupported('changeSubscriptionAmount')) {
107 $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.');
108 CRM_Core_Session::setStatus($userAlert, ts('Warning'), 'alert');
109 }
110
111 $this->assign('isChangeSupported', $this->_paymentProcessorObj->isSupported('changeSubscriptionAmount'));
112 $this->assign('paymentProcessor', $this->_paymentProcessor);
113 $this->assign('frequency_unit', $this->_subscriptionDetails->frequency_unit);
114 $this->assign('frequency_interval', $this->_subscriptionDetails->frequency_interval);
115
116 if ($this->_subscriptionDetails->contact_id) {
117 list($this->_donorDisplayName, $this->_donorEmail) = CRM_Contact_BAO_Contact::getContactDetails($this->_subscriptionDetails->contact_id);
118 }
119
120 CRM_Utils_System::setTitle(ts('Update Recurring Contribution'));
121
122 // handle context redirection
123 CRM_Contribute_BAO_ContributionRecur::setSubscriptionContext();
124 }
125
126 /**
127 * Set default values for the form.
128 *
129 * Note that in edit/view mode the default values are retrieved from the database.
130 */
131 public function setDefaultValues() {
132
133 $this->_defaults = array();
134 $this->_defaults['amount'] = $this->_subscriptionDetails->amount;
135 $this->_defaults['installments'] = $this->_subscriptionDetails->installments;
136 $this->_defaults['campaign_id'] = $this->_subscriptionDetails->campaign_id;
137 $this->_defaults['financial_type_id'] = $this->_subscriptionDetails->financial_type_id;
138 $this->_defaults['is_notify'] = 1;
139
140 return $this->_defaults;
141 }
142
143 /**
144 * Actually build the components of the form.
145 */
146 public function buildQuickForm() {
147 // CRM-16398: If current recurring contribution got > 1 lineitems then make amount field readonly
148 $amtAttr = array('size' => 20);
149 $lineItems = CRM_Price_BAO_LineItem::getLineItemsByContributionID($this->_coid);
150 if (count($lineItems) > 1) {
151 $amtAttr += array('readonly' => TRUE);
152 }
153 $this->addMoney('amount', ts('Recurring Contribution Amount'), TRUE, $amtAttr,
154 TRUE, 'currency', $this->_subscriptionDetails->currency, TRUE
155 );
156
157 $this->add('text', 'installments', ts('Number of Installments'), array('size' => 20), FALSE);
158
159 if ($this->_donorEmail) {
160 $this->add('checkbox', 'is_notify', ts('Notify Contributor?'));
161 }
162
163 if (CRM_Core_Permission::check('edit contributions')) {
164 CRM_Campaign_BAO_Campaign::addCampaign($this);
165 }
166
167 if (CRM_Contribute_BAO_ContributionRecur::supportsFinancialTypeChange($this->_crid)) {
168 $this->addEntityRef('financial_type_id', ts('Financial Type'), array('entity' => 'FinancialType'), TRUE);
169 }
170
171 $type = 'next';
172 if ($this->_selfService) {
173 $type = 'submit';
174 }
175
176 // define the buttons
177 $this->addButtons(array(
178 array(
179 'type' => $type,
180 'name' => ts('Save'),
181 'isDefault' => TRUE,
182 ),
183 array(
184 'type' => 'cancel',
185 'name' => ts('Cancel'),
186 ),
187 )
188 );
189 }
190
191 /**
192 * Called after the user submits the form.
193 */
194 public function postProcess() {
195 // store the submitted values in an array
196 $params = $this->exportValues();
197
198 if ($this->_selfService && $this->_donorEmail) {
199 // for self service force notify
200 $params['is_notify'] = 1;
201 }
202
203 // if this is an update of an existing recurring contribution, pass the ID
204 $params['id'] = $this->_subscriptionDetails->recur_id;
205 $message = '';
206
207 $params['subscriptionId'] = $this->_subscriptionDetails->subscription_id;
208 $updateSubscription = TRUE;
209 if ($this->_paymentProcessorObj->isSupported('changeSubscriptionAmount')) {
210 $updateSubscription = $this->_paymentProcessorObj->changeSubscriptionAmount($message, $params);
211 }
212 if (is_a($updateSubscription, 'CRM_Core_Error')) {
213 CRM_Core_Error::displaySessionError($updateSubscription);
214 $status = ts('Could not update the Recurring contribution details');
215 $msgTitle = ts('Update Error');
216 $msgType = 'error';
217 }
218 elseif ($updateSubscription) {
219 // save the changes
220 $result = CRM_Contribute_BAO_ContributionRecur::add($params);
221 $status = ts('Recurring contribution has been updated to: %1, every %2 %3(s) for %4 installments.',
222 array(
223 1 => CRM_Utils_Money::format($params['amount'], $this->_subscriptionDetails->currency),
224 2 => $this->_subscriptionDetails->frequency_interval,
225 3 => $this->_subscriptionDetails->frequency_unit,
226 4 => $params['installments'],
227 )
228 );
229
230 $msgTitle = ts('Update Success');
231 $msgType = 'success';
232 $msg = ts('Recurring Contribution Updated');
233 $contactID = $this->_subscriptionDetails->contact_id;
234
235 if ($this->_subscriptionDetails->amount != $params['amount']) {
236 $message .= "<br /> " . ts("Recurring contribution amount has been updated from %1 to %2 for this subscription.",
237 array(
238 1 => CRM_Utils_Money::format($this->_subscriptionDetails->amount, $this->_subscriptionDetails->currency),
239 2 => CRM_Utils_Money::format($params['amount'], $this->_subscriptionDetails->currency),
240 )) . ' ';
241 if ($this->_subscriptionDetails->amount < $params['amount']) {
242 $msg = ts('Recurring Contribution Updated - increased installment amount');
243 }
244 else {
245 $msg = ts('Recurring Contribution Updated - decreased installment amount');
246 }
247 }
248
249 if ($this->_subscriptionDetails->installments != $params['installments']) {
250 $message .= "<br /> " . ts("Recurring contribution installments have been updated from %1 to %2 for this subscription.", array(
251 1 => $this->_subscriptionDetails->installments,
252 2 => $params['installments'],
253 )) . ' ';
254 }
255
256 $activityParams = array(
257 'source_contact_id' => $contactID,
258 'activity_type_id' => CRM_Core_OptionGroup::getValue('activity_type',
259 'Update Recurring Contribution',
260 'name'
261 ),
262 'subject' => $msg,
263 'details' => $message,
264 'activity_date_time' => date('YmdHis'),
265 'status_id' => CRM_Core_OptionGroup::getValue('activity_status',
266 'Completed',
267 'name'
268 ),
269 );
270 $session = CRM_Core_Session::singleton();
271 $cid = $session->get('userID');
272
273 if ($cid) {
274 $activityParams['target_contact_id'][] = $activityParams['source_contact_id'];
275 $activityParams['source_contact_id'] = $cid;
276 }
277 CRM_Activity_BAO_Activity::create($activityParams);
278
279 if (!empty($params['is_notify'])) {
280 // send notification
281 if ($this->_subscriptionDetails->contribution_page_id) {
282 CRM_Core_DAO::commonRetrieveAll('CRM_Contribute_DAO_ContributionPage', 'id',
283 $this->_subscriptionDetails->contribution_page_id, $value, array(
284 'title',
285 'receipt_from_name',
286 'receipt_from_email',
287 )
288 );
289 $receiptFrom = '"' . CRM_Utils_Array::value('receipt_from_name', $value[$this->_subscriptionDetails->contribution_page_id]) . '" <' . $value[$this->_subscriptionDetails->contribution_page_id]['receipt_from_email'] . '>';
290 }
291 else {
292 $domainValues = CRM_Core_BAO_Domain::getNameAndEmail();
293 $receiptFrom = "$domainValues[0] <$domainValues[1]>";
294 }
295
296 list($donorDisplayName, $donorEmail) = CRM_Contact_BAO_Contact::getContactDetails($contactID);
297
298 $tplParams = array(
299 'recur_frequency_interval' => $this->_subscriptionDetails->frequency_interval,
300 'recur_frequency_unit' => $this->_subscriptionDetails->frequency_unit,
301 'amount' => CRM_Utils_Money::format($params['amount']),
302 'installments' => $params['installments'],
303 );
304
305 $tplParams['contact'] = array('display_name' => $donorDisplayName);
306 $tplParams['receipt_from_email'] = $receiptFrom;
307
308 $sendTemplateParams = array(
309 'groupName' => 'msg_tpl_workflow_contribution',
310 'valueName' => 'contribution_recurring_edit',
311 'contactId' => $contactID,
312 'tplParams' => $tplParams,
313 'isTest' => $this->_subscriptionDetails->is_test,
314 'PDFFilename' => 'receipt.pdf',
315 'from' => $receiptFrom,
316 'toName' => $donorDisplayName,
317 'toEmail' => $donorEmail,
318 );
319 list($sent) = CRM_Core_BAO_MessageTemplate::sendTemplate($sendTemplateParams);
320 }
321 }
322
323 $session = CRM_Core_Session::singleton();
324 $userID = $session->get('userID');
325 if ($userID && $status) {
326 CRM_Core_Session::setStatus($status, $msgTitle, $msgType);
327 }
328 elseif (!$userID) {
329 if ($status) {
330 CRM_Utils_System::setUFMessage($status);
331 }
332 // keep result as 1, since we not displaying anything on the redirected page anyway
333 return CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contribute/subscriptionstatus',
334 "reset=1&task=update&result=1"));
335 }
336 }
337
338 }