top of page
Search

Save Contract As PDF And Email To Client

  • abhyash
  • Nov 5, 2022
  • 3 min read

V1 Prepared By: Abhyash Timsina – 5 November 2022


Motivation: Say you have a requirement that you need to send a formatted PDF contract to an account’s contact via email asking for their approval. This solution will make that happen with the click of a button from the Contract record page. The look of the generated PDF will change based upon Contract Status of Draft or Activated. Note – This is a personal project and not intended for financial gain.




My Technical Components



Source Code for ConvertToPDF Apex Class (with annotation starting with //)


/**
 * Created by Abhyash Timsina on 5/11/2022.
 */

global with sharing class ConvertToPDF {

// Get Set variable declaration

    public Contract con {get;set;}
    public String currentRecordId {get;set;}


    public ConvertToPDF() {

// Pass recordId from VisualForce page into SOQL query to get field data

        currentRecordId  = ApexPages.currentPage().getParameters().get('id');
        con = [SELECT Id, Name, Status, ActivatedDate, StartDate, EndDate, ContractNumber, ContractTerm, ShippingAddress, Account.Name, SpecialTerms, Pricebook2.Name FROM Contract WHERE Id =: currentRecordId];
    }

// Flow inputs for invocable method - contract recordId, contract Number, PDF Name and Recipient Email
 
    public class FlowInput {
        @InvocableVariable(Label='Contract RecordID' Description='Contract Record Id' Required=true)
        public String recordId;
        @InvocableVariable(Label='Contract Number' Description='Contract Number' Required=true)
        public String contractNumber;
        @InvocableVariable(Label='PDF Name' Description='PDF Name' Required=true)
        public String pdfName;
        @InvocableVariable(Label='Recipient Email' Description='Recipient Email' Required=true)
        public String recipientEmail;
    }

// Invocable method that gets called from the flow

    @InvocableMethod(Label='Attach PDF' Description='Attaches PDF to Contract')
    public static void attachPdf(List<FlowInput> params) {

        for ( FlowInput param : params ) {

// Declaration of page reference, to reference the VF page and pass recordId

                PageReference myPdf = Page.ContractPage;
                myPdf.getParameters().put('id', param.recordId);

// Empty blob variable to store the pdf output data

                Blob pdfBody;

// getContentAsPDF method to convert VF page to PDF

                try {
                    pdfBody = myPdf.getContentAsPDF();
                } catch (VisualforceException e) {
                    pdfBody = Blob.valueOf(' ');
                }

// Create a file with the generated PDF's blob data and relate it with the contract

                ContentVersion cv = new ContentVersion();
                cv.ContentLocation = 'S';
                cv.VersionData = pdfBody;
                cv.Title = param.pdfName;
                cv.PathOnClient = param.pdfName + '.pdf';
                insert cv;

// Create an email attachment with the body of the file created earlier

            Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
            efa.setFileName(param.pdfName + '.pdf');
            efa.setBody(pdfBody);

// Send Email function which passes the recipient email from flow input to the setToAddress. Other stuff you can manually configure like the plain text body, sender display name etc

            Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
            String[] sendingTo = new String[]{param.recipientEmail};
            message.setToAddresses(sendingTo);
            message.setSenderDisplayName('Contracts Team');
            message.saveAsActivity = false;
            message.subject = 'Contract: ' + param.contractNumber + ' - For your review';
            message.plainTextBody = 'Hi, Please find attached contract: ' + param.contractNumber + '. Please review and advise if you wish to proceed.';
            message.setFileAttachments(new Messaging.EmailFileAttachment[]{efa});
            Messaging.SingleEmailMessage[] messages = new List<Messaging.SingleEmailMessage> {message};
            Messaging.SendEmailResult[] results = Messaging.sendEmail(messages);


            }

    }

}



contractTemplate Static Resource










Source Code for ContractPage Visualforce Page (with annotation starting with //)


<!--
 - Created by Abhyash Timsina on 5/11/2022.
 -->

// Visualforce page that users above apex class as controller and renders if the Contract status is Activated or Draft. Different background image gets generated based upon the status.

<apex:page id="ContractPage" controller="ConvertToPDF" rendered="{!con.Status = 'Activated' || con.Status = 'Draft' }" >
    <body style="font-family: Arial,serif;position:relative;text-align:center; width:100%; overflow-x:hidden; overflow-y:hidden;">
    <img src="{! Case(con.Status, "Activated", $Resource.contractTemplate + '/contractTemplate/images/contract_activated.png', "Draft", $Resource.contractTemplate + '/contractTemplate/images/contract_draft.png', NULL) }" alt="Result Image"/>
    <div style="font-family: Arial, serif; font-size: 11px; position: absolute; top:1%; right: 1%; left: 1%; bottom: 1%; color: white;" >
        <br />
        <br />
        <br />
        
        // Get Todays Date
        
        <div style="font-family: Arial, serif;color: black;font-size: 30px">TODAYS DATE:</div>
        <br />
        <br />
        <apex:outputText style="font-family: Arial, serif;color: orange;font-size: 30px" value="{0, date,  dd/MM/yyyy}">
            <apex:param value="{!TODAY()}" />
        </apex:outputText>
        <br />
        <br />
        <br />
        <br />
        
        // Passing field value from Contract Account's Name
        
        <div style="font-family: Arial, serif;color: black;font-size: 30px">ACCOUNT:</div>
        <br />
        <div style="font-family: Arial, serif;color: orange; font-size: 45px">{!con.Account.Name}</div>
        <br />
        <br />
        <br />
        
        // Passing field value from Contract's Contract Number
        
        <div style="font-family: Arial, serif;color: black;font-size: 30px">CONTRACT NUMBER:</div>
        <br />
        <div style="font-family: Arial, serif;color: orange; font-size: 45px">{!con.ContractNumber}</div>

        <br />
        <br />
        <br />
        <br />
        <br />
        
      // Passing field value from Contract's Start & End Dates
                
        <div style="font-family: Arial, serif;color: black;font-size: 45px">Contract Start: <apex:outputText style="text-transform:uppercase; color: orange; " value=" {!con.StartDate}">
            </apex:outputText></div>
        <div style="font-family: Arial, serif;color: black;font-size: 45px">Contract End: <apex:outputText style="text-transform:uppercase; color: orange; " value=" {!con.EndDate}">
            </apex:outputText></div>
        <br />
        <br />
        <br />
        <br />
        
    // Passing field value from Contract's Special Terms
    
        <div style="font-family: Arial, serif;color: black;font-size: 30px">SPECIAL TERMS:</div>
        <br />
        <div style="font-family: Arial, serif;color: orange; font-size: 45px">{!con.SpecialTerms}</div>
        <br />
        <br />
        <br />
        <br />
        <br />
        <br />
        <br />
        <br />
        <br />
    </div>
    </body>

</apex:page>



Attach PDF & Send Email Action





Attach PDF To Contract Flow




  1. Get Contract



2. Get Contract Email




3. Attach PDF




4. Contract Generated Screen





Outcome




If Draft Status:




If Activated Status:



Package Link:


If you need help in installing and getting this working – please contact me on LinkedIn




 
 
 

Comments


bottom of page