Search code examples
htmlsalesforceapexvisualforce

Visualforce: Access pricecalculation from Opportunity object


I'm forcing the problem that I have to build a automated invoice generator based on the Opportunity object.

My code is as following:

    <apex:page standardController="Opportunity" showHeader="false" Language="de" renderAs="pdf" >
<!-- Reference to Style Sheet, saved under Static Resources in Salesforce. -->
<apex:stylesheet value="{!$Resource.InvoiceCSS}" />
<div>
        <!-- Below the optional text paragraph we put the table with all the products selected as Opportunity Line Items. -->
       
        <table class="products" width="100%">
            <tr>
               <td width="100%" style="vertical-align:top;">
                    <apex:dataTable width="100%" value="{!Opportunity.OpportunityLineItems}" var="oli">
                        <apex:column width="200px" headerClass="tableheaderleft" footerClass="tablefooterleft" styleClass="tablebodyleft">
                            <apex:facet name="header">Description</apex:facet>
                            <apex:OutputField value="{!oli.Name}"/>
                            
                            
                         </apex:column>
                        <apex:column width="{!If(oli.Discount!=null,If((oli.Discount>0),"25px","15px"),"15px")}" headerClass="tableheadercenter" footerClass="tablefootercenter" styleClass="tablebodycenter">
                            <apex:facet name="header">Quantity</apex:facet>
                            <apex:OutputField value="{!oli.Quantity}"/>
                            <apex:facet name="footer"></apex:facet>
                        </apex:column>
                        <apex:column width="95px" headerClass="tableheaderright" footerClass="tablefooterright" styleClass="tablebodyright">
                            <apex:facet name="header">Amount</apex:facet>
                            <apex:OutputField value="{!oli.UnitPrice}"/>
                            <apex:facet name="footer"></apex:facet>
                        </apex:column>
                
                    </apex:dataTable>
                </td>
            </tr>
            <tr><td width="50%" headerClass="tableheaderright" footerClass="tablefooterright" styleClass="tablebodyright">Subamount</td><td width="50%">EUR XXXX,XX</td></tr>
            <tr><td>VAT</td><td>EUR XXXX,XX</td></tr>
            <tr><td>Total amount</td><td>XXXX,XX</td></tr>
        </table>
        </div>

As the listing of the products works fine so far, now I need to add fields for VAT,subtotal amount and amount and I do not know how to do that.

My Idea was to create custom formula fields that refer to the Pricebook or the Opportunity Products object, but I couldn't access these fields in the formula generator. And thats exactly where my problem is: I do not know how the relationship between these objects works and which fields I need to refer to to get this calculation done. Is there any possibility to access a standart fields for amount, VAT, and sub amount? If yes, how can I access that?

Many thanks!!


Solution

  • Entity Relationship Diagram can help: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_erd_products.htm. It's bit crappy though.

    If you have your custom bits on top of that try with Setup -> Schema Builder.

    Opportunity is in many-to-many relation to Product, via OpportunityLineItem. You don't see it on the ERD but there absolutely is a OpportunityLineItem.Product2Id lookup (foreign key).

    Relation to Pricebook is bit messier. Opportunity -> down to line items -> up to pricebook entry -> up to pricebook.

    Right, so what you could do... You could make rollup summary fields on Opportunity that take total tax as sum of tax on line items? You'd then display {!Opportunity.Amount} and {!Opportunity.TotalTax__c} or something in your PDF. I don't know how you calculate tax, is it a custom field on OppLineItem? Who decides the rate? Product? Account's country? Pricebook entry and you have diff entries / product? Or do you care only about 1 country so you slap 1 flat rate at it and job done? If it's a flat 20% of total then you already have Opportunity.Amount, make another formula on Opportunity and job done?

    If you don't want to make a field - you could add a piece of Apex as controller extension, query data, do the calculation there and display your value. This might be... not great. When I make PDFs related to accounting I try to make them as simple as possible. No calculations, just dutifully take the values calculated by something else and display them as is, maybe with bit of formatting. Users might not always spot errors in PDFs during testing. If it's a real field, something that can be reported on it's more likely to be caught. So even if the tax calculation is too messy for formulas and rollups I'd probably do it with flow/trigger; save the value to helper field, not hide it behind PDF.

    (There's also way to do it in pure Visualforce, no custom code with some clever abuse of apex:repeat and apex:variable tags... But again, I'd advise against it. Too important to have rounding errors etc in presentation layer)