You need to sign in to do that
Don't have an account?
Customized Quote pdf quote and attach to quotedocument
Because of particular integration I have to leave certain line items out of the quote based on a checkbox. Because of this I can't use the default quote templates unless anyone else knows how to exclude quotelineitems from a quote. What I did was model it after Jeff Douglas attaching a pdf to an object. I have a custom button called 'Create PDF'. The button goes to the VF page below. On it is a commandlink which references the viewPDF method in the QuoteConsultingExtension to view the PDF before saving. This works great and I can view the PDF no problem with all the quote fields.
However when I click the savePDF button. I get "SObject row was retrieved via SOQL without querying the requested field:" on all the quote standard fields. I even tried to write my own SOQL query which references all the default quote fields and it then throws an error SObject row was retrieved via SOQL without querying the requested field: User.LastName when I'm not even referencing User.LastName on my VF page. This is crazy?? Can anyone help me with this or provide a better solution?
Thanks heaps
Dahveed
<apex:page standardController="Quote" showHeader="true" extensions="QuoteConsultingExtension" > <apex:sectionHeader title="Create and attach a quote for signing" subtitle="Attach a PDF" description="You must attach a PDF quote for use with docusign"/> <apex:form > <apex:pageBlock title="PDF Input"> <apex:pageBlockButtons > <apex:commandLink action="{!viewPDF}" value="View PDF" target="_blank" /> <apex:commandButton action="{!savePDF}" value="Save"/> <apex:commandButton action="{!Cancel}" value="Cancel"/> </apex:pageBlockButtons> <apex:pageMessages /> <apex:pageBlockSection > <apex:pageBlockSectionItem > <apex:outputLabel value="File Name" for="pdfName"/> <!-- <apex:inputText value="{!pdfName}" id="pdfName"/> --> </apex:pageBlockSectionItem> <apex:pageBlockSectionItem > <apex:outputLabel value="Account ID" for="id"/> <!-- <apex:inputText value="{!parentId}" id="id"/> --> </apex:pageBlockSectionItem> </apex:pageBlockSection> </apex:pageBlock> </apex:form>
public class QuoteConsultingExtension { private List<QuoteLineItem> conLineItems; private decimal conTotal; public final Quote myQuote; public QuoteConsultingExtension(ApexPages.StandardController stdController) { this.myQuote = (Quote)stdController.getRecord(); } public List<QuoteLineItem> consultingLineItems{ get{ if(conLineItems == null) conLineItems = new List<QuoteLineItem>(); conLineItems = [SELECT Id,Product_CodeF__c, Product_NameF__c,Quantity, ListPrice,Discount,UnitPrice,TotalPrice, isConsultingF__c, isGlobalProductF__c FROM QuoteLineItem WHERE isConsultingF__c = true AND isGlobalProductF__c = false]; return conLineItems; } set; } public decimal consultingTotal{ get{ conTotal=0; for(QuoteLineItem qli: conLineItems){ conTotal += qli.Quantity * qli.UnitPrice; } return conTotal; } set; } public PageReference viewPDF() { string quoteId = ApexPages.currentPage().getParameters().get('id'); PageReference thePDF = Page.Consulting_Services_Quote; thePDF.getParameters().put('id',quoteId); thePDF.setRedirect(true); return thePDF; } public PageReference savePDF() { string qId = ApexPages.currentPage().getParameters().get('id'); System.debug(qId); PageReference thePDF = Page.Consulting_Services_Quote; thePDF.getParameters().put('id',qId); thePDF.setRedirect(true); quotedocument qd = new quotedocument(); qd.document = thePDF.getContentAsPDF(); qd.quoteId = qId; insert qd; PageReference quotePage = new PageReference('/'+ qId); quotePage.setRedirect(true); return quotePage; } }
I assume that is the page being referenced by Page.Consulting_Services_Quote.
Ignore the below in the PDF as I was hoping initially to be able to put a button on the pdf as in the standard quoting system.
In that second VF page that renders as a PDF, what is qQuote? Makes me wonder if that's a search and replace gone awry and should really be Quote.ExpirationDate, etc.
<apex:outputText value="Date: {!TODAY()} "/><br></br>
<apex:outputText value="Offer Expires: {!qQuote.ExpirationDate}"/><br></br>
<apex:outputText value="From: {!qQuote.Opportunity.Owner.FirstName} {!qQuote.Opportunity.Owner.LastName} "/><br></br>
<apex:outputText value="Reference: {!qQuote.Opportunity}"/>
</apex:panelGroup>
</apex:panelGrid>
I posted that before I changed things back. The qQuote was my attempt to write a custom SOQL query on the Quote object to place data in the fields it was saying that I was calling on the Quote sObject without a SOQL query.
I am seeing more an issue like this I not i'm not emailing.
http://salesforce.stackexchange.com/questions/5432/object-not-found-issue-in-pdf-attachment-visualforce-page-for-an-email
and
http://boards.developerforce.com/t5/Apex-Code-Development/Error-on-getContentAsPDF-PDF-preview-page/td-p/228835
This is where I am at now. I put in a try catch and the attachment now works however I cannot view it. It's as if the Quote standard controller isn't running but my quote line item is. This is my current code. Sorry about the qQoute. I'm asking for help and not giving the exact problem. I promise this is accurate. Thank you for looking at it.
I think maybe I should try making separate extensions instead of using one?
Yes!! I think it was a transaction issue with the way salesforce executes Apex. Once I separated the two controllers it worked fine. Thanks for your help.
Glad you got it working.
One question: have you written unit tests for this extension? Creating those in tandem with your classes (as opposed to at the very end) can make debugging a whole lot easier and helps to ensure that all subsequent changes don't break previously working functionality.
That's a great suggestion. I usually write them after the fact because I get so consumed with finding if my logic is even correct. I haven't been coding for very long(if you can't tell) so I think as my confidence builds so will the time when I write my unit tests. I used to create unit tests pretty quickly once I ran into problems but this slowed as soon as I saw I could run my user in debug mode and find which values are getting passed to variables using the System.Debug().
I also wasn't finding any documentation on the QuoteDocument object and started trying to attach it via Attachments. Is there a good place or way to find more information on those lesser documented things in salesforce like QuoteDocument?
Thanks for taking the time :-)
Dahveed
Writing the tests first helps verify your logic and also tends to make for better design since it forces you to think first about your interfaces. It's called test-driven development. I'm relatively new to Apex and OOP in general but this way of coding has changed my world.
I highly recommend this book which introduced me to this way of programming: http://www.amazon.ca/Software-Development-Principles-Patterns-Practices/dp/0135974445
Afraid I don't have any good resources for lesser documented parts of Salesforce. I use the Nonprofit Start Pack and have never touched the Quote object.
Best of luck!