Style - Remove @public, @private, @protected
[civicrm-core.git] / CRM / Pledge / Form / Pledge.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
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-2014
32 * $Id$
33 *
34 */
35
36 /**
37 * This class generates form components for processing a pledge
38 *
39 */
40 class CRM_Pledge_Form_Pledge extends CRM_Core_Form {
41 public $_action;
42
43 /**
44 * The id of the pledge that we are proceessing
45 *
46 * @var int
47 */
48 public $_id;
49
50 /**
51 * The id of the contact associated with this pledge
52 *
53 * @var int
54 */
55 public $_contactID;
56
57 /**
58 * The Pledge values if an existing pledge
59 */
60 public $_values;
61
62 /**
63 * The Pledge frequency Units
64 */
65 public $_freqUnits;
66
67 /**
68 * Is current pledge pending.
69 */
70 public $_isPending = FALSE;
71
72 /**
73 * Set variables up before form is built
74 *
75 * @return void
76 * @access public
77 */
78 public function preProcess() {
79 $this->_contactID = CRM_Utils_Request::retrieve('cid', 'Positive', $this);
80 $this->_action = CRM_Utils_Request::retrieve('action', 'String',
81 $this, FALSE, 'add'
82 );
83 $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this);
84 $this->_context = CRM_Utils_Request::retrieve('context', 'String', $this);
85
86 // check for action permissions.
87 if (!CRM_Core_Permission::checkActionPermission('CiviPledge', $this->_action)) {
88 CRM_Core_Error::fatal(ts('You do not have permission to access this page.'));
89 }
90
91 $this->assign('action', $this->_action);
92 $this->assign('context', $this->_context);
93 if ($this->_action & CRM_Core_Action::DELETE) {
94 return;
95 }
96
97 $this->userDisplayName = $this->userEmail = NULL;
98 if ($this->_contactID) {
99 list($this->userDisplayName,
100 $this->userEmail
101 ) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactID);
102 $this->assign('displayName', $this->userDisplayName);
103 }
104
105 $this->setPageTitle(ts('Pledge'));
106
107 //build custom data
108 CRM_Custom_Form_CustomData::preProcess($this, NULL, NULL, 1, 'Pledge', $this->_id);
109 $this->_values = array();
110 // current pledge id
111 if ($this->_id) {
112 //get the contribution id
113 $this->_contributionID = CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_PledgePayment',
114 $this->_id, 'contribution_id', 'pledge_id'
115 );
116 $params = array('id' => $this->_id);
117 CRM_Pledge_BAO_Pledge::getValues($params, $this->_values);
118
119 $this->_isPending = (CRM_Pledge_BAO_Pledge::pledgeHasFinancialTransactions($this->_id, CRM_Utils_Array::value('status_id', $this->_values))) ? FALSE : T;
120 }
121
122 //get the pledge frequency units.
123 $this->_freqUnits = CRM_Core_OptionGroup::values('recur_frequency_units');
124
125 $this->_fromEmails = CRM_Core_BAO_Email::getFromEmail();
126 }
127
128
129 /**
130 * Set default values for the form.
131 * the default values are retrieved from the database
132 *
133 * @access public
134 *
135 * @return void
136 */
137 public function setDefaultValues() {
138 $defaults = $this->_values;
139
140 $fields = array();
141 if ($this->_action & CRM_Core_Action::DELETE) {
142 return $defaults;
143 }
144
145 if (!empty($defaults['is_test'])) {
146 $this->assign('is_test', TRUE);
147 }
148
149 if ($this->_id) {
150 $startDate = CRM_Utils_Array::value('start_date', $this->_values);
151 $createDate = CRM_Utils_Array::value('create_date', $this->_values);
152 list($defaults['start_date']) = CRM_Utils_Date::setDateDefaults($startDate);
153 list($defaults['create_date']) = CRM_Utils_Date::setDateDefaults($createDate);
154
155 if ($ackDate = CRM_Utils_Array::value('acknowledge_date', $this->_values)) {
156 list($defaults['acknowledge_date']) = CRM_Utils_Date::setDateDefaults($ackDate);
157 }
158
159 //check is this pledge pending
160 // fix the display of the monetary value, CRM-4038
161 if ($this->_isPending) {
162 $defaults['eachPaymentAmount'] = $this->_values['amount'] / $this->_values['installments'];
163 $defaults['eachPaymentAmount'] = CRM_Utils_Money::format($defaults['eachPaymentAmount'], NULL, '%a');
164 }
165 else {
166 $this->assign('start_date', $startDate);
167 $this->assign('create_date', $createDate);
168 }
169 // fix the display of the monetary value, CRM-4038
170 if (isset($this->_values['amount'])) {
171 $defaults['amount'] = CRM_Utils_Money::format($this->_values['amount'], NULL, '%a');
172 }
173 $this->assign('amount', $this->_values['amount']);
174 $this->assign('installments', $defaults['installments']);
175 }
176 else {
177 //default values.
178 list($now) = CRM_Utils_Date::setDateDefaults();
179 $defaults['create_date'] = $now;
180 $defaults['start_date'] = $now;
181 $defaults['installments'] = 12;
182 $defaults['frequency_interval'] = 1;
183 $defaults['frequency_day'] = 1;
184 $defaults['initial_reminder_day'] = 5;
185 $defaults['max_reminders'] = 1;
186 $defaults['additional_reminder_day'] = 5;
187 $defaults['frequency_unit'] = array_search('month', $this->_freqUnits);
188 $defaults['financial_type_id'] = array_search( 'Donation', CRM_Contribute_PseudoConstant::financialType() );
189 }
190
191 $pledgeStatus = CRM_Contribute_PseudoConstant::contributionStatus();
192 $pledgeStatusNames = CRM_Core_OptionGroup::values('contribution_status',
193 FALSE, FALSE, FALSE, NULL, 'name', TRUE
194 );
195 // get default status label (pending)
196 $defaultPledgeStatus = CRM_Utils_Array::value(array_search('Pending', $pledgeStatusNames),
197 $pledgeStatus
198 );
199
200 //assign status.
201 $this->assign('status', CRM_Utils_Array::value(CRM_Utils_Array::value('status_id', $this->_values),
202 $pledgeStatus,
203 $defaultPledgeStatus
204 ));
205
206 if (isset($this->userEmail)) {
207 $this->assign('email', $this->userEmail);
208 }
209
210 // custom data set defaults
211 $defaults += CRM_Custom_Form_CustomData::setDefaultValues($this);
212
213 return $defaults;
214 }
215
216 /**
217 * Build the form object
218 *
219 * @return void
220 * @access public
221 */
222 public function buildQuickForm() {
223 if ($this->_action & CRM_Core_Action::DELETE) {
224 $this->addButtons(array(
225 array(
226 'type' => 'next',
227 'name' => ts('Delete'),
228 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
229 'isDefault' => TRUE,
230 ),
231 array(
232 'type' => 'cancel',
233 'name' => ts('Cancel'),
234 ),
235 )
236 );
237 return;
238 }
239
240 if ($this->_context == 'standalone') {
241 $this->addEntityRef('contact_id', ts('Contact'), array('create' => TRUE, 'api' => array('extra' => array('email'))), TRUE);
242 }
243
244 $showAdditionalInfo = FALSE;
245 $this->_formType = CRM_Utils_Array::value('formType', $_GET);
246
247 $defaults = array();
248
249 $paneNames = array(
250 'Payment Reminders' => 'PaymentReminders',
251 );
252 foreach ($paneNames as $name => $type) {
253 $urlParams = "snippet=4&formType={$type}";
254 $allPanes[$name] = array('url' => CRM_Utils_System::url('civicrm/contact/view/pledge', $urlParams),
255 'open' => 'false',
256 'id' => $type,
257 );
258 //see if we need to include this paneName in the current form
259 if ($this->_formType == $type || !empty($_POST["hidden_{$type}"]) ||
260 CRM_Utils_Array::value("hidden_{$type}", $defaults)
261 ) {
262 $showAdditionalInfo = TRUE;
263 $allPanes[$name]['open'] = 'true';
264 }
265 $fnName = "build{$type}";
266 CRM_Contribute_Form_AdditionalInfo::$fnName($this);
267 }
268
269 $this->assign('allPanes', $allPanes);
270 $this->assign('showAdditionalInfo', $showAdditionalInfo);
271
272 if ($this->_formType) {
273 $this->assign('formType', $this->_formType);
274 return;
275 }
276
277 $this->applyFilter('__ALL__', 'trim');
278
279 //pledge fields.
280 $attributes = CRM_Core_DAO::getAttribute('CRM_Pledge_DAO_Pledge');
281
282 $this->assign('isPending', $this->_isPending);
283
284 $js = array(
285 'onblur' => "calculatedPaymentAmount( );",
286 'onkeyup' => "calculatedPaymentAmount( );",
287 );
288
289 $currencyFreeze = FALSE;
290 if ($this->_id &&
291 !$this->_isPending
292 ) {
293 $currencyFreeze = TRUE;
294 }
295
296 $element = $this->addMoney('amount', ts('Total Pledge Amount'), TRUE,
297 array_merge($attributes['pledge_amount'], $js), TRUE,
298 'currency', NULL, $currencyFreeze
299 );
300
301 if ($this->_id &&
302 !$this->_isPending
303 ) {
304 $element->freeze();
305 }
306
307 $element = &$this->add('text', 'installments', ts('To be paid in'),
308 array_merge($attributes['installments'], $js), TRUE
309 );
310 $this->addRule('installments', ts('Please enter a valid number of installments.'), 'positiveInteger');
311 if ($this->_id &&
312 !$this->_isPending
313 ) {
314 $element->freeze();
315 }
316
317 $element = &$this->add('text', 'frequency_interval', ts('every'),
318 $attributes['pledge_frequency_interval'], TRUE
319 );
320 $this->addRule('frequency_interval', ts('Please enter a number for frequency (e.g. every "3" months).'), 'positiveInteger');
321 if ($this->_id &&
322 !$this->_isPending
323 ) {
324 $element->freeze();
325 }
326
327 // Fix frequency unit display for use with frequency_interval
328 $freqUnitsDisplay = array();
329 foreach ($this->_freqUnits as $val => $label) {
330 $freqUnitsDisplay[$val] = ts('%1(s)', array(1 => $label));
331 }
332 $element = &$this->add('select', 'frequency_unit',
333 ts('Frequency'),
334 array(
335 '' => ts('- select -')) + $freqUnitsDisplay,
336 TRUE
337 );
338
339 if ($this->_id &&
340 !$this->_isPending
341 ) {
342 $element->freeze();
343 }
344
345 $element = &$this->add('text', 'frequency_day', ts('Payments are due on the'), $attributes['frequency_day'], TRUE);
346 $this->addRule('frequency_day', ts('Please enter a valid payment due day.'), 'positiveInteger');
347 if ($this->_id &&
348 !$this->_isPending
349 ) {
350 $element->freeze();
351 }
352
353 $this->add('text', 'eachPaymentAmount', ts('each'), array('size' => 10, 'style' => "background-color:#EBECE4", 'READONLY'));
354
355 //add various dates
356 if (!$this->_id || $this->_isPending) {
357 $this->addDate('create_date', ts('Pledge Made'), TRUE);
358 $this->addDate('start_date', ts('Payments Start'), TRUE);
359 }
360
361 if ($this->_id &&
362 !$this->_isPending
363 ) {
364 $eachPaymentAmount = $this->_values['original_installment_amount'];
365 $this->assign('currency', $this->_values['currency']);
366 $this->assign('eachPaymentAmount', $eachPaymentAmount);
367 $this->assign('hideCalender', TRUE);
368 }
369
370 if (CRM_Utils_Array::value('status_id', $this->_values) !=
371 array_search('Cancelled', CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'))
372 ) {
373
374 $this->addElement('checkbox', 'is_acknowledge', ts('Send Acknowledgment?'), NULL,
375 array('onclick' => "showHideByValue( 'is_acknowledge', '', 'acknowledgeDate', 'table-row', 'radio', true); showHideByValue( 'is_acknowledge', '', 'fromEmail', 'table-row', 'radio', false );")
376 );
377
378 $this->add('select', 'from_email_address', ts('Receipt From'), $this->_fromEmails);
379 }
380
381 $this->addDate('acknowledge_date', ts('Acknowledgment Date'));
382
383 $this->add('select', 'financial_type_id',
384 ts( 'Financial Type' ),
385 array(''=>ts( '- select -' )) + CRM_Contribute_PseudoConstant::financialType( ),
386 TRUE
387 );
388
389 //CRM-7362 --add campaigns.
390 CRM_Campaign_BAO_Campaign::addCampaign($this, CRM_Utils_Array::value('campaign_id', $this->_values));
391
392 $pageIds = array();
393 CRM_Core_DAO::commonRetrieveAll('CRM_Pledge_DAO_PledgeBlock', 'entity_table',
394 'civicrm_contribution_page', $pageIds, array('entity_id')
395 );
396 $pages = CRM_Contribute_PseudoConstant::contributionPage();
397 $pledgePages = array();
398 foreach ($pageIds as $key => $value) {
399 $pledgePages[$value['entity_id']] = $pages[$value['entity_id']];
400 }
401 $ele = $this->add('select', 'contribution_page_id', ts('Self-service Payments Page'),
402 array(
403 '' => ts('- select -')) + $pledgePages
404 );
405
406 $mailingInfo = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
407 'mailing_backend'
408 );
409 $this->assign('outBound_option', $mailingInfo['outBound_option']);
410
411 //build custom data
412 CRM_Custom_Form_CustomData::buildQuickForm($this);
413
414 // make this form an upload since we dont know if the custom data injected dynamically
415 // is of type file etc $uploadNames = $this->get( 'uploadNames' );
416 $this->addButtons(array(
417 array(
418 'type' => 'upload',
419 'name' => ts('Save'),
420 'js' => array('onclick' => "return verify( );"),
421 'isDefault' => TRUE,
422 ),
423 array(
424 'type' => 'upload',
425 'name' => ts('Save and New'),
426 'js' => array('onclick' => "return verify( );"),
427 'subName' => 'new',
428 ),
429 array(
430 'type' => 'cancel',
431 'name' => ts('Cancel'),
432 ),
433 )
434 );
435
436 $this->addFormRule(array('CRM_Pledge_Form_Pledge', 'formRule'), $this);
437
438 if ($this->_action & CRM_Core_Action::VIEW) {
439 $this->freeze();
440 }
441 }
442
443 /**
444 * Global form rule
445 *
446 * @param array $fields the input form values
447 * @param array $files the uploaded files if any
448 * @param $self
449 *
450 *
451 * @return true if no errors, else array of errors
452 * @access public
453 * @static
454 */
455 public static function formRule($fields, $files, $self) {
456 $errors = array();
457
458 if ($fields['amount'] <= 0) {
459 $errors['amount'] = ts('Total Pledge Amount should be greater than zero.');
460 }
461 if ($fields['installments'] <= 0) {
462 $errors['installments'] = ts('Installments should be greater than zero.');
463 }
464
465 if ($fields['frequency_unit'] != 'week') {
466 if ($fields['frequency_day'] > 31 || $fields['frequency_day'] == 0) {
467 $errors['frequency_day'] = ts('Please enter a valid frequency day ie. 1 through 31.');
468 }
469 }
470 elseif ($fields['frequency_unit'] == 'week') {
471 if ($fields['frequency_day'] > 7 || $fields['frequency_day'] == 0) {
472 $errors['frequency_day'] = ts('Please enter a valid frequency day ie. 1 through 7.');
473 }
474 }
475 return $errors;
476 }
477
478 /**
479 * Process the form submission
480 *
481 * @access public
482 *
483 * @return void
484 */
485 public function postProcess() {
486 if ($this->_action & CRM_Core_Action::DELETE) {
487 CRM_Pledge_BAO_Pledge::deletePledge($this->_id);
488 return;
489 }
490
491 //get the submitted form values.
492 $formValues = $this->controller->exportValues($this->_name);
493
494 // set the contact, when contact is selected
495 if (!empty($formValues['contact_id'])) {
496 $this->_contactID = $formValues['contact_id'];
497 }
498
499 $session = CRM_Core_Session::singleton();
500
501 //get All Payments status types.
502 $paymentStatusTypes = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
503
504 $fields = array(
505 'frequency_unit',
506 'frequency_interval',
507 'frequency_day',
508 'installments',
509 'financial_type_id',
510 'initial_reminder_day',
511 'max_reminders',
512 'additional_reminder_day',
513 'contribution_page_id',
514 'campaign_id',
515 );
516 foreach ($fields as $f) {
517 $params[$f] = CRM_Utils_Array::value($f, $formValues);
518 }
519
520 //defaults status is "Pending".
521 //if update get status.
522 if ($this->_id) {
523 $params['pledge_status_id'] = $params['status_id'] = $this->_values['status_id'];
524 }
525 else {
526 $params['pledge_status_id'] = $params['status_id'] = array_search('Pending', $paymentStatusTypes);
527 }
528 //format amount
529 $params['amount'] = CRM_Utils_Rule::cleanMoney(CRM_Utils_Array::value('amount', $formValues));
530 $params['currency'] = CRM_Utils_Array::value('currency', $formValues);
531 $params['original_installment_amount'] = ($params['amount'] / $params['installments']);
532
533 $dates = array('create_date', 'start_date', 'acknowledge_date', 'cancel_date');
534 foreach ($dates as $d) {
535 if ($this->_id && (!$this->_isPending) && !empty($this->_values[$d])) {
536 if ($d == 'start_date') {
537 $params['scheduled_date'] = CRM_Utils_Date::processDate($this->_values[$d]);
538 }
539 $params[$d] = CRM_Utils_Date::processDate($this->_values[$d]);
540 }
541 elseif (!empty($formValues[$d]) && !CRM_Utils_System::isNull($formValues[$d])) {
542 if ($d == 'start_date') {
543 $params['scheduled_date'] = CRM_Utils_Date::processDate($formValues[$d]);
544 }
545 $params[$d] = CRM_Utils_Date::processDate($formValues[$d]);
546 }
547 else {
548 $params[$d] = 'null';
549 }
550 }
551
552 if (!empty($formValues['is_acknowledge'])) {
553 $params['acknowledge_date'] = date('Y-m-d');
554 }
555
556 // assign id only in update mode
557 if ($this->_action & CRM_Core_Action::UPDATE) {
558 $params['id'] = $this->_id;
559 }
560
561 $params['contact_id'] = $this->_contactID;
562
563 //format custom data
564 if (!empty($formValues['hidden_custom'])) {
565 $params['hidden_custom'] = 1;
566
567 $customFields = CRM_Core_BAO_CustomField::getFields('Pledge');
568 $params['custom'] = CRM_Core_BAO_CustomField::postProcess($formValues,
569 $customFields,
570 $this->_id,
571 'Pledge'
572 );
573 }
574
575 //handle pending pledge.
576 $params['is_pledge_pending'] = $this->_isPending;
577
578 //create pledge record.
579 $pledge = CRM_Pledge_BAO_Pledge::create($params);
580
581 $statusMsg = NULL;
582
583 if ($pledge->id) {
584 //set the status msg.
585 if ($this->_action & CRM_Core_Action::ADD) {
586 $statusMsg = ts('Pledge has been recorded and the payment schedule has been created.<br />');
587 }
588 elseif ($this->_action & CRM_Core_Action::UPDATE) {
589 $statusMsg = ts('Pledge has been updated.<br />');
590 }
591 }
592
593 //handle Acknowledgment.
594 if (!empty($formValues['is_acknowledge']) && $pledge->id) {
595
596 //calculate scheduled amount.
597 $params['scheduled_amount'] = round($params['amount'] / $params['installments']);
598 $params['total_pledge_amount'] = $params['amount'];
599 //get some required pledge values in params.
600 $params['id'] = $pledge->id;
601 $params['acknowledge_date'] = $pledge->acknowledge_date;
602 $params['is_test'] = $pledge->is_test;
603 $params['currency'] = $pledge->currency;
604 // retrieve 'from email id' for acknowledgement
605 $params['from_email_id'] = $formValues['from_email_address'];
606
607 $this->paymentId = NULL;
608 //send Acknowledgment mail.
609 CRM_Pledge_BAO_Pledge::sendAcknowledgment($this, $params);
610
611 if (!isset($this->userEmail)) {
612 list($this->userDisplayName,
613 $this->userEmail
614 ) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactID);
615 }
616
617 $statusMsg .= ' ' . ts("An acknowledgment email has been sent to %1.<br />", array(1 => $this->userEmail));
618
619 //build the payment urls.
620 if ($this->paymentId) {
621 $urlParams = "reset=1&action=add&cid={$this->_contactID}&ppid={$this->paymentId}&context=pledge";
622 $contribURL = CRM_Utils_System::url('civicrm/contact/view/contribution', $urlParams);
623 $urlParams .= "&mode=live";
624 $creditURL = CRM_Utils_System::url('civicrm/contact/view/contribution', $urlParams);
625
626 //check if we can process credit card payment.
627 $processors = CRM_Core_PseudoConstant::paymentProcessor(FALSE, FALSE,
628 "billing_mode IN ( 1, 3 )"
629 );
630 if (count($processors) > 0) {
631 $statusMsg .= ' ' . ts("If a payment is due now, you can record <a href='%1'>a check, EFT, or cash payment for this pledge</a> OR <a href='%2'>submit a credit card payment</a>.", array(1 => $contribURL, 2 => $creditURL));
632 }
633 else {
634 $statusMsg .= ' ' . ts("If a payment is due now, you can record <a href='%1'>a check, EFT, or cash payment for this pledge</a>.", array(1 => $contribURL));
635 }
636 }
637 }
638 CRM_Core_Session::setStatus($statusMsg, ts('Payment Due'), 'info');
639
640 $buttonName = $this->controller->getButtonName();
641 if ($this->_context == 'standalone') {
642 if ($buttonName == $this->getButtonName('upload', 'new')) {
643 $session->replaceUserContext(CRM_Utils_System::url('civicrm/pledge/add',
644 'reset=1&action=add&context=standalone'
645 ));
646 }
647 else {
648 $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view',
649 "reset=1&cid={$this->_contactID}&selectedChild=pledge"
650 ));
651 }
652 }
653 elseif ($buttonName == $this->getButtonName('upload', 'new')) {
654 $session->replaceUserContext(CRM_Utils_System::url('civicrm/contact/view/pledge',
655 "reset=1&action=add&context=pledge&cid={$this->_contactID}"
656 ));
657 }
658 }
659 }
660