如何使用扩展控制器将 Visualforce 页面保存到机会页面上的文件中?

问题描述 投票:0回答:1

我是 Salesforce 的新手,这是我第一次打开开发人员控制台,所以请耐心等待,代码可能很粗糙,我感谢任何帮助。我有一个控制器和 Visualforce 页面,用于编译机会页面上产品列表中的产品,创建新的(非重复)报价编号,并将所有这些编译为带有公司徽标和所需格式的 PDF;这一切都是通过点击机会页面上的按钮来调用的。我想要在 Visualforce 页面上有一个按钮,以便在制作并显示 PDF 后,将 PDF 保存到文件中。

**Visualforce 页面(我已尝试删除 renderAs 语句):**

<apex:page controller="QuoteOppProductCtrl" extensions="QuoteOppProductCtrlExtension" applyHtmlTag="false" showHeader="false" renderAs="PDF" action="{!generateAndStoreQuoteNumber}">  
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockButtons location="TOP">
                <apex:commandButton action="{!generateAndUploadPDF}" value="Save PDF"/>
            </apex:pageBlockButtons>
        </apex:pageBlock>
    </apex:form>
    <html>
----------------the body of the content of the PDF is here -------------------------

    </html>
</apex:page>

**主控制器:**

public class QuoteOppProductCtrl {
    public Date Today { get { return Date.today(); } }
    public Opportunity opportunity { get; set; }
    public String shipToAccountName { get; set; }
    public String prosthetistName { get; set; }
    public String fittingProsthetistId { get; set; }
    public String prosthetistEmail { get; set; }
    public Decimal subtotal { get; set; }
    public Decimal quoteTotal { get; set; }
    public String quoteNumber { get; set; } // To store the generated quote number
    
    public Integer currentYear = Date.today().year();
    public String quoteNumberPrefix = 'Q-' + String.valueOf(currentYear).right(2);
    
public QuoteOppProductCtrl() {
        String opportunityId = ApexPages.currentPage().getParameters().get('id');

        // Replace the Opportunity query with the hard-coded ID
        opportunity = [SELECT Id, Name, ShipToAcct__c, Account.Name, ShipToAcct__r.ShippingStreet, ShipToAcct__r.ShippingCity,
                      ShipToAcct__r.ShippingState, ShipToAcct__r.ShippingPostalCode,
                      ShipToAcct__r.ShippingCountry, Opp_No__c, Cable__c, fitting_prosthetist__c,
                      (SELECT Quantity, UnitPrice, TotalPrice, PricebookEntry.Product2.Name, PricebookEntry.Product2.Description
                       FROM OpportunityLineItems)
                      FROM Opportunity
                      WHERE Id = :opportunityId];

        if (opportunity.ShipToAcct__c != null) {
            shipToAccountName = opportunity.Account.Name;
        }
        fittingProsthetistId = opportunity.fitting_prosthetist__c;

        if (fittingProsthetistId != null) {
            Contact fittingProsthetist = [SELECT Id, Name, Email FROM Contact WHERE Id = :fittingProsthetistId LIMIT 1];
            prosthetistName = fittingProsthetist.Name;
            prosthetistEmail = fittingProsthetist.Email;
        }

        // Calculate subtotal and quote total
        subtotal = 0;
        for (OpportunityLineItem lineItem : opportunity.OpportunityLineItems) {
            subtotal += lineItem.TotalPrice;
        }
        // tax = .1 * subtotal
        // Ship_handling = we need to figure this out
        quoteTotal = subtotal; // You can adjust this based on your tax and shipping calculations.
}

    // Check if a quote number already exists for the current year
public Boolean isQuoteNumberEmpty() {
        
        // Query for existing quote numbers for the current year
    List<Quote_Number__c> existingQuoteNumbers = [SELECT ID, Name FROM Quote_Number__c WHERE Name LIKE :quoteNumberPrefix];
        
        // If the list is empty, no quote number exists for the current year
    return existingQuoteNumbers.isEmpty();
}
    //Creates quote number, and then stores it into the opportunity page
public void generateAndStoreQuoteNumber() {

    // Query for the latest quote number for the current year
    Quote_Number__c latestQuoteNumber = [SELECT ID, Name 
                                         FROM Quote_Number__c
                                         WHERE Name LIKE :quoteNumberPrefix + '%'
                                         ORDER BY Name DESC
                                         LIMIT 1];

    if (latestQuoteNumber != null) {
        // If a quote number for the current year exists, increment it by 1
        Integer lastNumber = Integer.valueOf(latestQuoteNumber.Name.substring(quoteNumberPrefix.length())) + 1;
        String newQuoteNumber = quoteNumberPrefix + String.valueOf(lastNumber).leftPad(4,'0');
        
        Quote_Number__c quoteNumberRecord = new Quote_Number__c();
        quoteNumberRecord.Opportunity__c = opportunity.Id;
        quoteNumberRecord.Name = newQuoteNumber;
        
        insert quoteNumberRecord;
        quoteNumber = newQuoteNumber;
        } 
       else {
        // If no quote number for the current year exists, start with 0000
        String newQuoteNumber = quoteNumberPrefix + '0000';
        
        Quote_Number__c quoteNumberRecord = new Quote_Number__c();
        quoteNumberRecord.Opportunity__c = opportunity.Id;
        quoteNumberRecord.Name = newQuoteNumber;
        
        insert quoteNumberRecord;
        quoteNumber = newQuoteNumber;  
        }

       // Update the Opportunity record with the generated quote number
    opportunity.QuoteNum__c = quoteNumber;
    update opportunity;
}
}

控制器扩展 - 我认为我的问题出在这段代码中

public class QuoteOppProductCtrlExtension {
    private ApexPages.StandardController stdController;
    public Opportunity opportunity { get; set; }
    public String shipToAccountName { get; set; }
    public String prosthetistName { get; set; }
    public String fittingProsthetistId { get; set; }
    public String prosthetistEmail { get; set; }
    public Decimal subtotal { get; set; }
    public Decimal quoteTotal { get; set; }
    public String recordId {get;set;}
    
    public QuoteOppProductCtrlExtension(QuoteOppProductCtrl Maincontroller) {
      String opportunityId = ApexPages.currentPage().getParameters().get('id');
          opportunity = [SELECT Id, Name, ShipToAcct__c, Account.Name, ShipToAcct__r.ShippingStreet, ShipToAcct__r.ShippingCity,
                      ShipToAcct__r.ShippingState, ShipToAcct__r.ShippingPostalCode,
                      ShipToAcct__r.ShippingCountry, Opp_No__c, Cable__c, fitting_prosthetist__c,
                      (SELECT Quantity, UnitPrice, TotalPrice, PricebookEntry.Product2.Name, PricebookEntry.Product2.Description
                       FROM OpportunityLineItems)
                      FROM Opportunity
                      WHERE Id = :opportunityId];
         if (opportunity.ShipToAcct__c != null) {
            shipToAccountName = opportunity.Account.Name;
        }
        fittingProsthetistId = opportunity.fitting_prosthetist__c;

        if (fittingProsthetistId != null) {
            Contact fittingProsthetist = [SELECT Id, Name, Email FROM Contact WHERE Id = :fittingProsthetistId LIMIT 1];
            prosthetistName = fittingProsthetist.Name;
            prosthetistEmail = fittingProsthetist.Email;
        }

        // Calculate subtotal and quote total
        subtotal = 0;
        for (OpportunityLineItem lineItem : opportunity.OpportunityLineItems) {
            subtotal += lineItem.TotalPrice;
        }

        quoteTotal = subtotal; // You can adjust this based on your tax and shipping calculations.
        
    }
    
    public QuoteOppProductCtrlExtension(ApexPages.StandardController controller) {
       stdController =  controller;
         }
    
    public ApexPages.PageReference generateAndUploadPDF() {
        String recordId = ApexPages.currentPage().getParameters().get('id');
        
          
          // Generate the PDF here
       PageReference pdfPage = Page.QuoteOppProductVfp;
       pdfPage.getParameters().put('Id', recordId);
       pdfPage.setRedirect(true);


        Blob pdfBlob;
        if (Test.isRunningTest()) {
            pdfBlob = Blob.valueOf('Test PDF Content');
        } else {
            pdfBlob = pdfPage.getContentAsPDF();
        }
        Attachment attach = new Attachment(parentId = recordId, Name = 'Quote' + String.valueOf(recordId), body = pdfBlob);
        attach.IsPrivate = false; 
        insert attach;

        // Create a ContentVersion record
        ContentVersion cv = new ContentVersion(
            Title = 'Quote' + String.valueOf(recordId),
            VersionData = pdfBlob
        );
        insert cv;

        // Create a ContentDocumentLink to associate the PDF with the record
        ContentDocumentLink cdl = new ContentDocumentLink(
            ContentDocumentId = cv.ContentDocumentId,
            LinkedEntityId = recordId
        );
        insert cdl;

        // Redirect or display a success message
       PageReference successPage = new PageReference('/' + recordId);
        successPage.setRedirect(true);
        return successPage;
    }   
}
apex visualforce salesforce-lightning
1个回答
0
投票

切成2页,更容易维护。我还将使用 2 个独立的 apex 控制器,但也可能只使用一个。

首先制作你的PDF。简单,单一的关注点,让它变得漂亮即可。

public with sharing class PdfPrint {
    // This can be done with pure Visualforce but just for demo sake
    Id accountId;
    public PdfPrint(ApexPages.StandardController ctrl) {
        accountId = ctrl.getId();
    }

    public List<Opportunity> getOpps(){
        return [SELECT Id, Name, StageName, CloseDate
        FROM Opportunity
        WHERE AccountId = :accountId
        ORDER BY Name];
    }
}
<!-- I called the page AccountAndOppsPdf -->
<apex:page standardController="Account" extensions="PdfPrint" readOnly="true" renderAs="pdf">
    <!-- put logo and stuff here, make this pretty -->
    <apex:detail subject="{!Account.Id}" relatedList="false" />
    <apex:pageBlock title="Opps">
        <apex:pageBlockTable value="{!opps}" var="o">
            <apex:column value="{!o.Name}"/>
            <apex:column value="{!o.StageName}"/>
            <apex:column value="{!o.CloseDate}"/>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

一旦您对此感到满意 - 制作在 iframe 中显示第一个页面的另一个页面。

public with sharing class PdfPreview {
  Id accountId;
  public PdfPreview(ApexPages.StandardController ctrl) {
    accountId = ctrl.getId();
  }

  public Pagereference save() {
    PageReference pdfPage = Page.AccountAndOppsPdf;
    pdfPage.getParameters().put('Id', accountId);
    pdfPage.setRedirect(true);

    PageReference ret;

    try {
      Blob pdfBlob = Test.isRunningTest()
        ? Blob.valueOf('Test PDF Content')
        : pdfPage.getContentAsPDF();

      ContentVersion cv = new ContentVersion(
        Title = 'Quote ' + accountId,
        PathOnClient = 'Quote ' + accountId + '.pdf',
        VersionData = pdfBlob,
        FirstPublishLocationId = accountId
      );
      insert cv;
      ret = new ApexPages.StandardController([SELECT Id FROM ContentDocument WHERE LatestPublishedVersionId = :cv.Id]).view();
    } catch (exception e) {
      ApexPages.addMessages(e);
    }
    return ret;
  }
}
<apex:page standardController="Account" extensions="PdfPreview">
    <apex:pageMessages />
    <apex:form>
        <apex:pageBlock title="preview and save">
            <apex:pageBlockButtons>
                <apex:commandButton value="Save" action="{!save}" />
            </apex:pageBlockButtons>
            <apex:iframe src="{!URLFOR($Page.AccountAndOppsPdf, null, [id=Account.Id])}" scrolling="true" />
        </apex:pageBlock>
    </apex:form>
</apex:page>

© www.soinside.com 2019 - 2024. All rights reserved.