Can a scheduled report be send as PDF?

hello

the reports are working fantastic,
but the users here want to have them in PDF or excel
they dont like the email formatting ā€¦

Hi,
I am sorry as per my knowledge we canā€™t specify the report format in the default REPORT module of SuiteCRM.
Please see this guide for all possiblities

https://docs.suitecrm.com/user/advanced-modules/reports/

You can purchase a paid plugin, Analytical Reporting. This plugin has this feature available. I can help you out to set this up.

Thaks

@niraleeraval, how is this related to what this user was asking for? He doesnā€™t want to upload documents into the CRM, he wants to produce Documents from it - namely, Reports.

1 Like

Is there already a function in SuiteCRM that makes this possible, or do I have to build a Logic Hook if I want this function?

Which function do you mean, grabbing a report result and turning it into a PDF to send by email?

How would you do that in a logic hook? thatā€™s quite a bit of codeā€¦

I wanted to create a Logic Hook that would be triggered when a value from a custom module changed. After the value changed, it will create a PDF document with a custom made PDF template, and after creation it will send an email with the PDF document as an attachment.

It was not that hard, you could use a lot of code from the classes ā€œgeneratePdf.phpā€ and ā€œactionSendEmail.phpā€. If anyone is interested, I can share and explain my code.

1 Like

Iā€™m actually looking to send a PDF by logic hook ā€œrelationship addā€ in Opportunities. That would be great if youā€™d share.

Okay, no problem!

  1. Create a Logic Hook for your module (path:/custom/Extension/modules/{module}/Ext/LogicHooks/logic_hooks.php).

  2. Create the action you want to trigger, in my case it was the ā€˜before_saveā€™.

$hook_array['before_save'][] = array(
    //Processing index. For sorting the array.
    3,

    //Label. A string value to identify the hook.
    'Generate PDF and send as attachment',

    //The PHP file where your class is located.
    'custom/Extension/modules/{module}/Ext/CustomFiles/test.php',

    //The class the method is in.
    'testClass',

    //The method to call.
    'generatePdfDocument'
);
  1. Create the file in the above written location (path:custom/Extension/modules/{module}/Ext/CustomFiles/test.php).

  2. Get the data from the record with a custom made PDF-template and send it to an emailaddress.

<?php

if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

class testClass
{
    public function generatePdfDocument($bean, $event, $arguments)
    {
        // Only send email if status is completed and mail not been sent yet.
        if ($bean->request_status == 'completed' && !$bean->mail_to_xxx_sent_c) {
            global $sugar_config;
            $errorLevelStored = error_reporting();
            error_reporting(0);
            require_once('modules/AOS_PDF_Templates/PDF_Lib/mpdf.php');
            require_once('modules/AOS_PDF_Templates/templateParser.php');
            require_once('modules/AOW_Actions/actions/actionSendEmail.php');
            require_once('modules/AOS_PDF_Templates/AOS_PDF_Templates.php');
            error_reporting($errorLevelStored);

            $template = BeanFactory::newBean('AOS_PDF_Templates');
            $template->retrieve('25fc9bb3-ce3b-0f1d-ffa3-635fd12b69b6'); // Set Basecone PDF-template ID.

            $search = array('/<script[^>]*?>.*?<\/script>/si',      // Strip out javascript
                '/<[\/\!]*?[^<>]*?>/si',        // Strip out HTML tags
                '/([\r\n])[\s]+/',          // Strip out white space
                '/&(quot|#34);/i',          // Replace HTML entities
                '/&(amp|#38);/i',
                '/&(lt|#60);/i',
                '/&(gt|#62);/i',
                '/&(nbsp|#160);/i',
                '/&(iexcl|#161);/i',
                '/<address[^>]*?>/si',
                '/&(apos|#0*39);/',
                '/&#(\d+);/'
            );

            $replace = array('', '', '\1', '"', '&', '<', '>', ' ', chr(161), '<br>', "'", 'chr(%1)');

            $header = preg_replace($search, $replace, $template->pdfheader);
            $footer = preg_replace($search, $replace, $template->pdffooter);
            $text = preg_replace($search, $replace, $template->description);
            $text = str_replace("<p><pagebreak /></p>", "<pagebreak />", $text);
            $text = preg_replace_callback(
                '/\{DATE\s+(.*?)\}/',
                function ($matches) {
                    return date($matches[1]);
                },
                $text
            );

            $variableName = strtolower($bean->module_dir);
            $text = str_replace("\$aos_quotes", "\$" . $variableName, $text);
            $text = str_replace("\$aos_invoices", "\$" . $variableName, $text);
            $text = str_replace("\$total_amt", "\$" . $variableName . "_total_amt", $text);
            $text = str_replace("\$discount_amount", "\$" . $variableName . "_discount_amount", $text);
            $text = str_replace("\$subtotal_amount", "\$" . $variableName . "_subtotal_amount", $text);
            $text = str_replace("\$tax_amount", "\$" . $variableName . "_tax_amount", $text);
            $text = str_replace("\$shipping_amount", "\$" . $variableName . "_shipping_amount", $text);
            $text = str_replace("\$total_amount", "\$" . $variableName . "_total_amount", $text);

            $object_arr = array();
            $object_arr[$bean->module_dir] = $bean->id;
            $converted = templateParser::parse_template($text, $object_arr);
            $header = templateParser::parse_template($header, $object_arr);
            $footer = templateParser::parse_template($footer, $object_arr);

            $printable = str_replace("\n", "<br />", $converted);

            $file_name = date("Ymd") . "_" . str_replace(" ", "_", $bean->name) . ".pdf";

            ob_clean();
            try {
                $orientation = ($template->orientation == "Landscape") ? "-L" : "";
                $pdf = new mPDF('en', $template->page_size . $orientation, '', 'DejaVuSansCondensed', $template->margin_left, $template->margin_right, $template->margin_top, $template->margin_bottom, $template->margin_header, $template->margin_footer);
                $pdf->SetAutoFont();
                $pdf->SetHTMLHeader($header);
                $pdf->SetHTMLFooter($footer);
                $pdf->WriteHTML($printable);
                $fp = fopen($sugar_config['upload_dir'] . 'attachfile.pdf', 'wb');
                fclose($fp);
                $pdf->Output($sugar_config['upload_dir'] . 'attachfile.pdf', 'F');

                $this->sendEmail($bean, $file_name);
            } catch (mPDF_exception $e) {
                echo $e;
            }

            $bean->mail_to_xxx_sent_c = true;
        }
    }

    private function sendEmail(SugarBean $relatedBean, $file_name)
    {
        require_once('modules/Emails/Email.php');
        require_once('include/SugarPHPMailer.php');
        global $sugar_config;

        $emailTo = array('email1@test.com');
        $emailObj = BeanFactory::newBean('Emails');
        $defaults = $emailObj->getSystemDefaultEmail();
        $mail = new SugarPHPMailer();

        // set the id for relationship
        $emailObj->id = create_guid();
        $emailObj->new_with_id = true;

        $mail->setMailerForSystem();
        $mail->From = $defaults['email'];
        isValidEmailAddress($mail->From);
        $mail->FromName = $defaults['name'];
        $mail->ClearAllRecipients();
        $mail->ClearReplyTos();
        $mail->Subject = from_html($relatedBean->name);
        $mail->Body = "This mail has data from project: '{$relatedBean->name}'.";
        $mail->AltBody = '';
        $mail->prepForOutbound();

        foreach ($emailTo as $to) {
            $mail->AddAddress($to);
        }

        // Create the note (attachment)
        $note = BeanFactory::newBean('Notes');
        $note->id = create_guid();
        $note->new_with_id = true;
        $note->name = 'PDF document: ' . $relatedBean->name;
        $note->parent_type = 'Emails';
        $note->parent_id = $emailObj->id;
        $note->file_mime_type = 'application/pdf';
        $note->filename = $file_name;
        $noteId = $note->save();

        if (!empty($noteId)) {
            rename($sugar_config['upload_dir'] . 'attachfile.pdf', $sugar_config['upload_dir'] . $note->id);
            $emailObj->attachNote($note);
        } else {
            $GLOBALS['log']->error('AOS_PDF_Templates: Unable to save note');
        }

        // Add the attachment to the mail
        $mail->handleAttachments(array($note));

        //now create email
        if ($mail->Send()) {
            $emailObj->to_addrs = implode(',', $emailTo);
            $emailObj->type = 'out';
            $emailObj->deleted = '0';
            $emailObj->name = $mail->Subject;
            $emailObj->description = $mail->AltBody;
            $emailObj->description_html = $mail->Body;
            $emailObj->from_addr = $mail->From;
            isValidEmailAddress($emailObj->from_addr);
            if ($relatedBean instanceof SugarBean && !empty($relatedBean->id)) {
                $emailObj->parent_type = $relatedBean->module_dir;
                $emailObj->parent_id = $relatedBean->id;
            }
            $emailObj->date_sent_received = TimeDate::getInstance()->nowDb();
            $emailObj->modified_user_id = '1';
            $emailObj->created_by = '1';
            $emailObj->status = 'sent';
            $emailObj->save();
        }
    }
}

Good luck!

2 Likes

Nice! Thank you. Iā€™m going to study and try and implement your solution. Thanks so much for that.