_contributionIds = array($id); $this->_componentClause = " civicrm_contribution.id IN ( $id ) "; $this->_single = TRUE; $this->assign('totalSelectedContributions', 1); // set the redirection after actions $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', $this, FALSE); $url = CRM_Utils_System::url('civicrm/contact/view/contribution', "action=view&reset=1&id={$id}&cid={$contactId}&context=contribution&selectedChild=contribute" ); CRM_Core_Session::singleton()->pushUserContext($url); } else { parent::preProcess(); } // check that all the contribution ids have status Completed, Pending, Refunded. $this->_contributionStatusId = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); $status = array('Completed', 'Pending', 'Refunded'); $statusId = array(); foreach ($this->_contributionStatusId as $key => $value) { if (in_array($value, $status)) { $statusId[] = $key; } } $Id = implode(",", $statusId); $query = "SELECT count(*) FROM civicrm_contribution WHERE contribution_status_id NOT IN ($Id) AND {$this->_componentClause}"; $count = CRM_Core_DAO::singleValueQuery($query); if ($count != 0) { CRM_Core_Error::statusBounce(ts('Please select only contributions with Completed, Pending, Refunded status.')); } // we have all the contribution ids, so now we get the contact ids parent::setContactIDs(); $this->assign('single', $this->_single); $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $this); $urlParams = 'force=1'; if (CRM_Utils_Rule::qfKey($qfKey)) { $urlParams .= "&qfKey=$qfKey"; } $url = CRM_Utils_System::url('civicrm/contribute/search', $urlParams); $breadCrumb = array( array( 'url' => $url, 'title' => ts('Search Results'), ) ); CRM_Utils_System::appendBreadCrumb($breadCrumb); $this->_selectedOutput = CRM_Utils_Request::retrieve('select', 'String', $this); $this->assign('selectedOutput', $this->_selectedOutput); if ($this->_selectedOutput == 'email') { CRM_Utils_System::setTitle(ts('Email Invoice')); } else { CRM_Utils_System::setTitle(ts('Print Contribution Invoice')); } } /** * Build the form object * * @access public * * @return void */ public function buildQuickForm() { $session = CRM_Core_Session::singleton(); if (CRM_Core_Permission::check('administer CiviCRM')) { $this->assign('isAdmin', 1); } $contactID = $session->get('userID'); $contactEmails = CRM_Core_BAO_Email::allEmails($contactID); $emails = array(); $fromDisplayName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactID, 'display_name' ); foreach ($contactEmails as $emailId => $item) { $email = $item['email']; if ($email) { $emails[$emailId] = '"' . $fromDisplayName . '" <' . $email . '> '; } if (isset($emails[$emailId])) { $emails[$emailId] .= $item['locationType']; if ($item['is_primary']) { $emails[$emailId] .= ' ' . ts('(preferred)'); } $emails[$emailId] = htmlspecialchars($emails[$emailId]); } } $fromEmailAddress = CRM_Core_OptionGroup::values('from_email_address'); foreach ($fromEmailAddress as $key => $email) { $fromEmailAddress[$key] = htmlspecialchars($fromEmailAddress[$key]); } $fromEmail = CRM_Utils_Array::crmArrayMerge($emails, $fromEmailAddress); $this->add('select', 'from_email_address', ts('From Email Address'), array('' => '- select -') + $fromEmail); if ($this->_selectedOutput != 'email') { $this->addElement('radio', 'output', NULL, ts('Email Invoice'), 'email_invoice'); $this->addElement('radio', 'output', NULL, ts('PDF Invoice'), 'pdf_invoice'); $this->addRule('output', ts('Selection required'), 'required'); $this->addFormRule(array('CRM_Contribute_Form_Task_Invoice', 'formRule')); } else { $this->addRule('from_email_address', ts('From Email Address is required'), 'required'); } $this->addWysiwyg('email_comment', ts('If you would like to add personal message to email please add it here. (If sending to more then one receipient the same message will be sent to each contact.)'), array( 'rows' => 2, 'cols' => 40 )); if ($this->_selectedOutput == 'email') { $this->addButtons(array( array( 'type' => 'upload', 'name' => ts('Email Invoice'), 'isDefault' => TRUE, ), array( 'type' => 'cancel', 'name' => ts('Cancel'), ), ) ); } else { $this->addButtons(array( array( 'type' => 'upload', 'name' => ts('Process Invoice(s)'), 'isDefault' => TRUE, ), array( 'type' => 'cancel', 'name' => ts('Cancel'), ), ) ); } } /** * global validation rules for the form * * @param array $values * * @return array list of errors to be posted back to the form * @static * @access public */ static function formRule($values) { $errors = array(); if ($values['output'] == 'email_invoice' && empty($values['from_email_address'])) { $errors['from_email_address'] = ts("From Email Address is required"); } return $errors; } /** * process the form after the input has been submitted and validated * * @access public * * @return void */ public function postProcess() { $params = $this->controller->exportValues($this->_name); $this->printPDF($this->_contributionIds, $params, $this->_contactIds, $this); } /** * * process the PDf and email with activity and attachment * on click of Print Invoices * * @param array $contribIDs Contribution Id * @param array $params associated array of submitted values * @param array $contactIds Contact Id * @param CRM_Core_Form $form form object * @static * */ static function printPDF($contribIDs, &$params, $contactIds, &$form) { // get all the details needed to generate a invoice $messageInvoice = array(); $invoiceTemplate = CRM_Core_Smarty::singleton(); $invoiceElements = CRM_Contribute_Form_Task_PDF::getElements($contribIDs, $params, $contactIds); // gives the status id when contribution status is 'Refunded' $contributionStatusID = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name'); $refundedStatusId = CRM_Utils_Array::key('Refunded', $contributionStatusID); // getting data from admin page $prefixValue = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings'); foreach ($invoiceElements['details'] as $contribID => $detail) { $input = $ids = $objects = array(); if (in_array($detail['contact'], $invoiceElements['excludeContactIds'])) { continue; } $input['component'] = $detail['component']; $ids['contact'] = $detail['contact']; $ids['contribution'] = $contribID; $ids['contributionRecur'] = NULL; $ids['contributionPage'] = NULL; $ids['membership'] = CRM_Utils_Array::value('membership', $detail); $ids['participant'] = CRM_Utils_Array::value('participant', $detail); $ids['event'] = CRM_Utils_Array::value('event', $detail); if (!$invoiceElements['baseIPN']->validateData($input, $ids, $objects, FALSE)) { CRM_Core_Error::fatal(); } $contribution = & $objects['contribution']; $input['amount'] = $contribution->total_amount; $input['invoice_id'] = $contribution->invoice_id; $input['receive_date'] = $contribution->receive_date; $input['contribution_status_id'] = $contribution->contribution_status_id; $input['organization_name'] = $contribution->_relatedObjects['contact']->organization_name; $objects['contribution']->receive_date = CRM_Utils_Date::isoToMysql($objects['contribution']->receive_date); $addressParams = array('contact_id' => $contribution->contact_id); $addressDetails = CRM_Core_BAO_Address::getValues($addressParams); // to get billing address if present $billingAddress = array(); foreach ($addressDetails as $key => $address) { if ((isset($address['is_billing']) && $address['is_billing'] == 1) && (isset($address['is_primary']) && $address['is_primary'] == 1) && $address['contact_id'] == $contribution->contact_id) { $billingAddress[$address['contact_id']] = $address; break; } elseif (($address['is_billing'] == 0 && $address['is_primary'] == 1) || (isset($address['is_billing']) && $address['is_billing'] == 1) && $address['contact_id'] == $contribution->contact_id) { $billingAddress[$address['contact_id']] = $address; } } if (!empty($billingAddress[$contribution->contact_id]['state_province_id'])) { $stateProvinceAbbreviation = CRM_Core_PseudoConstant::stateProvinceAbbreviation($billingAddress[$contribution->contact_id]['state_province_id']); } else { $stateProvinceAbbreviation = ''; } if ($contribution->contribution_status_id == $refundedStatusId) { $creditNoteId = CRM_Utils_Array::value('credit_notes_prefix', $prefixValue) . "" . $contribution->id; } $invoiceId = CRM_Utils_Array::value('invoice_prefix', $prefixValue) . "" . $contribution->id; //to obtain due date for PDF invoice $contributionReceiveDate = date('F j,Y', strtotime(date($input['receive_date']))); $invoiceDate = date("F j, Y"); $dueDate = date('F j ,Y', strtotime($contributionReceiveDate . "+" . $prefixValue['due_date'] . "" . $prefixValue['due_date_period'])); if ($input['component'] == 'contribute') { $eid = $contribID; $etable = 'contribution'; $lineItem = CRM_Price_BAO_LineItem::getLineItems($eid, $etable, NULL, TRUE, TRUE); } else { $eid = $contribution->_relatedObjects['participant']->id; $etable = 'participant'; $lineItem = CRM_Price_BAO_LineItem::getLineItems($eid, $etable); } //TO DO: Need to do changes for partially paid to display amount due on PDF invoice $amountDue = ($input['amount'] - $input['amount']); // retreiving the subtotal and sum of same tax_rate $dataArray = array(); $subTotal = 0; foreach ($lineItem as $entity_id => $taxRate) { if (isset($dataArray[(string) $taxRate['tax_rate']])) { $dataArray[(string) $taxRate['tax_rate']] = $dataArray[(string) $taxRate['tax_rate']] + CRM_Utils_Array::value('tax_amount', $taxRate); } else { $dataArray[(string) $taxRate['tax_rate']] = CRM_Utils_Array::value('tax_amount', $taxRate); } $subTotal += CRM_Utils_Array::value('subTotal', $taxRate); } // to email the invoice $mailDetails = array(); $values = array(); if ($contribution->_component == 'event') { $daoName = 'CRM_Event_DAO_Event'; $pageId = $contribution->_relatedObjects['event']->id; $mailElements = array( 'title', 'confirm_from_name', 'confirm_from_email', 'cc_confirm', 'bcc_confirm', ); CRM_Core_DAO::commonRetrieveAll($daoName, 'id', $pageId, $mailDetails, $mailElements); $values['title'] = CRM_Utils_Array::value('title', $mailDetails[$contribution->_relatedObjects['event']->id]); $values['confirm_from_name'] = CRM_Utils_Array::value('confirm_from_name', $mailDetails[$contribution->_relatedObjects['event']->id]); $values['confirm_from_email'] = CRM_Utils_Array::value('confirm_from_email', $mailDetails[$contribution->_relatedObjects['event']->id]); $values['cc_confirm'] = CRM_Utils_Array::value('cc_confirm', $mailDetails[$contribution->_relatedObjects['event']->id]); $values['bcc_confirm'] = CRM_Utils_Array::value('bcc_confirm', $mailDetails[$contribution->_relatedObjects['event']->id]); $title = CRM_Utils_Array::value('title', $mailDetails[$contribution->_relatedObjects['event']->id]); } elseif ($contribution->_component == 'contribute') { $daoName = 'CRM_Contribute_DAO_ContributionPage'; $pageId = $contribution->contribution_page_id; $mailElements = array( 'title', 'receipt_from_name', 'receipt_from_email', 'cc_receipt', 'bcc_receipt', ); CRM_Core_DAO::commonRetrieveAll($daoName, 'id', $pageId, $mailDetails, $mailElements); $values['title'] = CRM_Utils_Array::value('title', CRM_Utils_Array::value($contribution->contribution_page_id, $mailDetails)); $values['receipt_from_name'] = CRM_Utils_Array::value('receipt_from_name', CRM_Utils_Array::value($contribution->contribution_page_id, $mailDetails)); $values['receipt_from_email'] = CRM_Utils_Array::value('receipt_from_email', CRM_Utils_Array::value($contribution->contribution_page_id, $mailDetails)); $values['cc_receipt'] = CRM_Utils_Array::value('cc_receipt', CRM_Utils_Array::value($contribution->contribution_page_id, $mailDetails)); $values['bcc_receipt'] = CRM_Utils_Array::value('bcc_receipt', CRM_Utils_Array::value($contribution->contribution_page_id, $mailDetails)); $title = CRM_Utils_Array::value('title', CRM_Utils_Array::value($contribution->contribution_page_id, $mailDetails)); } $source = $contribution->source; $config = CRM_Core_Config::singleton(); if (!isset($params['forPage'])) { $config->doNotAttachPDFReceipt = 1; } // get organization address $domain = CRM_Core_BAO_Domain::getDomain(); $locParams = array('contact_id' => $domain->id); $locationDefaults = CRM_Core_BAO_Location::getValues($locParams); if (isset($locationDefaults['address'][1]['state_province_id'])) { $stateProvinceAbbreviationDomain = CRM_Core_PseudoConstant::stateProvinceAbbreviation($locationDefaults['address'][1]['state_province_id']); } else { $stateProvinceAbbreviationDomain = ''; } if (isset($locationDefaults['address'][1]['country_id'])) { $countryDomain = CRM_Core_PseudoConstant::country($locationDefaults['address'][1]['country_id']); } else { $countryDomain = ''; } // parameters to be assign for template $tplParams = array( 'title' => $title, 'component' => $input['component'], 'id' => $contribution->id, 'source' => $source, 'invoice_id' => $invoiceId, 'resourceBase' => $config->userFrameworkResourceURL, 'defaultCurrency' => $config->defaultCurrency, 'amount' => $contribution->total_amount, 'amountDue' => $amountDue, 'invoice_date' => $invoiceDate, 'dueDate' => $dueDate, 'notes' => CRM_Utils_Array::value('notes', $prefixValue), 'display_name' => $contribution->_relatedObjects['contact']->display_name, 'lineItem' => $lineItem, 'dataArray' => $dataArray, 'refundedStatusId' => $refundedStatusId, 'contribution_status_id' => $contribution->contribution_status_id, 'subTotal' => $subTotal, 'street_address' => CRM_Utils_Array::value('street_address', CRM_Utils_Array::value($contribution->contact_id, $billingAddress)), 'supplemental_address_1' => CRM_Utils_Array::value('supplemental_address_1', CRM_Utils_Array::value($contribution->contact_id, $billingAddress)), 'supplemental_address_2' => CRM_Utils_Array::value('supplemental_address_2', CRM_Utils_Array::value($contribution->contact_id, $billingAddress)), 'city' => CRM_Utils_Array::value('city', CRM_Utils_Array::value($contribution->contact_id, $billingAddress)), 'stateProvinceAbbreviation' => $stateProvinceAbbreviation, 'postal_code' => CRM_Utils_Array::value('postal_code', CRM_Utils_Array::value($contribution->contact_id, $billingAddress)), 'is_pay_later' => $contribution->is_pay_later, 'organization_name' => $contribution->_relatedObjects['contact']->organization_name, 'domain_organization' => $domain->name, 'domain_street_address' => CRM_Utils_Array::value('street_address', CRM_Utils_Array::value('1', $locationDefaults['address'])), 'domain_supplemental_address_1' => CRM_Utils_Array::value('supplemental_address_1', CRM_Utils_Array::value('1', $locationDefaults['address'])), 'domain_supplemental_address_2' => CRM_Utils_Array::value('supplemental_address_2', CRM_Utils_Array::value('1', $locationDefaults['address'])), 'domain_city' => CRM_Utils_Array::value('city', CRM_Utils_Array::value('1', $locationDefaults['address'])), 'domain_postal_code' => CRM_Utils_Array::value('postal_code', CRM_Utils_Array::value('1', $locationDefaults['address'])), 'domain_state' => $stateProvinceAbbreviationDomain, 'domain_country' => $countryDomain, 'domain_email' => CRM_Utils_Array::value('email', CRM_Utils_Array::value('1', $locationDefaults['email'])), 'domain_phone' => CRM_Utils_Array::value('phone', CRM_Utils_Array::value('1', $locationDefaults['phone'])), ); if (isset($creditNoteId)) { $tplParams['creditnote_id'] = $creditNoteId; } $sendTemplateParams = array( 'groupName' => 'msg_tpl_workflow_contribution', 'valueName' => 'contribution_invoice_receipt', 'contactId' => $contribution->contact_id, 'tplParams' => $tplParams, 'PDFFilename' => 'Invoice.pdf', ); $session = CRM_Core_Session::singleton(); $contactID = $session->get('userID'); $contactEmails = CRM_Core_BAO_Email::allEmails($contactID); $emails = array(); $fromDisplayName = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactID, 'display_name' ); foreach ($contactEmails as $emailId => $item) { $email = $item['email']; if ($email) { $emails[$emailId] = '"' . $fromDisplayName . '" <' . $email . '> '; } } $fromEmail = CRM_Utils_Array::crmArrayMerge($emails, CRM_Core_OptionGroup::values('from_email_address')); // from email address if (isset($params['from_email_address'])) { $fromEmailAddress = CRM_Utils_Array::value($params['from_email_address'], $fromEmail); } // condition to check for download PDF Invoice or email Invoice if ($invoiceElements['createPdf']) { list($sent, $subject, $message, $html) = CRM_Core_BAO_MessageTemplate::sendTemplate($sendTemplateParams); if (isset($params['forPage'])) { return $html; } else { $mail = array( 'subject' => $subject, 'body' => $message, 'html' => $html, ); if ($mail['html']) { $messageInvoice[] = $mail['html']; } else { $messageInvoice[] = nl2br($mail['body']); } } } elseif ($contribution->_component == 'contribute') { $email = CRM_Contact_BAO_Contact::getPrimaryEmail($contribution->contact_id); $sendTemplateParams['tplParams'] = array_merge($tplParams, array('email_comment' => $invoiceElements['params']['email_comment'])); $sendTemplateParams['from'] = $fromEmailAddress; $sendTemplateParams['toEmail'] = $email; $sendTemplateParams['cc'] = CRM_Utils_Array::value('cc_receipt', $values); $sendTemplateParams['bcc'] = CRM_Utils_Array::value('bcc_receipt', $values); list($sent, $subject, $message, $html) = CRM_Core_BAO_MessageTemplate::sendTemplate($sendTemplateParams); // functions call for adding activity with attachment $fileName = self::putFile($html); self::addActivities($subject, $contribution->contact_id, $fileName, $params); } elseif ($contribution->_component == 'event') { $email = CRM_Contact_BAO_Contact::getPrimaryEmail($contribution->contact_id); $sendTemplateParams['tplParams'] = array_merge($tplParams, array('email_comment' => $invoiceElements['params']['email_comment'])); $sendTemplateParams['from'] = $fromEmailAddress; $sendTemplateParams['toEmail'] = $email; $sendTemplateParams['cc'] = CRM_Utils_Array::value('cc_confirm', $values); $sendTemplateParams['bcc'] = CRM_Utils_Array::value('bcc_confirm', $values); list($sent, $subject, $message, $html) = CRM_Core_BAO_MessageTemplate::sendTemplate($sendTemplateParams); // functions call for adding activity with attachment $fileName = self::putFile($html); self::addActivities($subject, $contribution->contact_id, $fileName, $params); } CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Contribution', $contribution->id, 'invoice_id', $invoiceId); if ($contribution->contribution_status_id == $refundedStatusId) { CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Contribution', $contribution->id, 'creditnote_id', $creditNoteId); } $invoiceTemplate->clearTemplateVars(); } if ($invoiceElements['createPdf']) { if (isset($params['forPage'])) { return $html; } else { CRM_Utils_PDF_Utils::html2pdf($messageInvoice, 'Invoice.pdf', FALSE, array( 'margin_top' => 10, 'margin_left' => 65, 'metric' => 'px' )); // functions call for adding activity with attachment $fileName = self::putFile($html); self::addActivities($subject, $contactIds, $fileName, $params); CRM_Utils_System::civiExit(); } } else { if ($invoiceElements['suppressedEmails']) { $status = ts('Email was NOT sent to %1 contacts (no email address on file, or communication preferences specify DO NOT EMAIL, or contact is deceased).', array(1 => $invoiceElements['suppressedEmails'])); $msgTitle = ts('Email Error'); $msgType = 'error'; } else { $status = ts('Your mail has been sent.'); $msgTitle = ts('Sent'); $msgType = 'success'; } CRM_Core_Session::setStatus($status, $msgTitle, $msgType); } } /** * * This function is use for adding activity for * Email Invoice and the PDF Invoice * * @param string $subject Activity subject * @param array $contactIds Contact Id * @param string $fileName gives the location with name of the file * @param array $params for invoices * * @access public * @static */ static public function addActivities($subject, $contactIds, $fileName, $params) { $session = CRM_Core_Session::singleton(); $userID = $session->get('userID'); $config = CRM_Core_Config::singleton(); $config->doNotAttachPDFReceipt = 1; if (!empty($params['output']) && $params['output'] == 'pdf_invoice') { $activityTypeID = CRM_Core_OptionGroup::getValue('activity_type', 'Downloaded Invoice', 'name' ); } else{ $activityTypeID = CRM_Core_OptionGroup::getValue('activity_type', 'Emailed Invoice', 'name' ); } $activityParams = array( 'subject' => $subject, 'source_contact_id' => $userID, 'target_contact_id' => $contactIds, 'activity_type_id' => $activityTypeID, 'activity_date_time' => date('YmdHis'), 'attachFile_1' => array( 'uri' => $fileName, 'type' => 'application/pdf', 'location' => $fileName, 'upload_date' => date('YmdHis'), ), ); CRM_Activity_BAO_Activity::create($activityParams); } /** * * This function is use for creating the Invoice file in upload folder * for attachment * * @param $html content for pdf in html format * * return $fileName of file which is in pdf format * * @return string */ static public function putFile($html) { require_once("packages/dompdf/dompdf_config.inc.php"); spl_autoload_register('DOMPDF_autoload'); $doc = new DOMPDF(); $doc->load_html($html); $doc->render(); $html = $doc->output(); $config = CRM_Core_Config::singleton(); $fileName = $config->uploadDir . 'Invoice.pdf'; file_put_contents($fileName, $html); return $fileName; } /** * Callback to perform action on Print Invoice button. */ static function getPrintPDF() { $contributionId = CRM_Utils_Request::retrieve('id', 'Positive', CRM_Core_DAO::$_nullObject, FALSE); $contributionIDs = array($contributionId); $contactId = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, FALSE); $params = array('output' => 'pdf_invoice'); CRM_Contribute_Form_Task_Invoice::printPDF($contributionIDs, $params, $contactId, CRM_Core_DAO::$_nullObject); } }