Visualforce: Access pricecalculation from Opportunity object - html

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!!

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)

Related

Visualforce / Apex: Access two objects with one controller

I'm forcing the problem that I have to set up a visualforce page rendered as pdf, which outputs a automatically generated invoice. Because of intern workflows this page has to be set up to the Opportunity object.
Most of the fields used are taken from the Opportunity object itself and work fine.
But I also need access to the OpportunityLineItem fields to display the products on the invoice.
How can this be realized? Do I have to write a controller extension in apex or is it possible without?
As an alternative, would this eventually be possible with cross formula fields referring from Opportunity to OpportunityLineItem? I tried this, but could not find any possibility to select OpportunityLineItem in a formula field in the Opportunity object.
Any help is much appreciated. Thanks!!
Below is a sample page accessing the OpportunityLineItems for a given Opportunity using the standard controller ammended from this doc reference.
<apex:page standardController="Opportunity">
<table border="0" >
<tr>
<th>Description</th><th>Quantity</th>
<th>Unit Price</th><th>Name</th>
</tr>
<apex:repeat var="oli" value="{!Opportunity.OpportunityLineItems}">
<tr>
<td>{!oli.Description}</td>
<td>{!oli.quantity}</td>
<td>{!oli.unitprice}</td>
<td>{!oli.Name}</td>
</tr>
</apex:repeat>
</table>
</apex:page>
With respect to formula fields, you cannot access child fields in a formula on the parent for the simple reason that it is a one to many relationship. The parent Opportunity would not know which of the children to lookup to.
The best you can do is make a regular (text or whatever) field, run a Process Builder triggered by a change to the relevant field(s) on the parent (opportunity) and trigger a Flow to loop over the children (LineItems) and make the changes to the parent based on some condition you specify.

How do I join a subrecord in a netsuite Advanced template for a sales order?

I'm trying to build a template for a packing slip list for a Netsuite Sales Order. This template needs access to the Country of Origin on the inventory details for the fulfillment item.
I've been using the netsuite records viewer.
As I understand it, a "Sales Order" has Items. Items have "Inventory Details".
According to the docs, it looks like in order to link an item and inventory details you need to do a join.
I'm brand new to netsuite and finding data has been a challenge. If I go to the item fulfillment record in netsuite I see the "inventory detail" column. I click on the icon to bring up the inventory details. I then click on the "serial/lot" number and I am presented with the data I'm looking for in the "Country of Origin" section.
If I click on that, it tells me the fieldId is "custitemnumber_cnt_country_of_origin"
I've tried every instance of this I can imagine but I'm completely stumped on what the parent of this is.
In the template I've tried:
${custitemnumber_cnt_country_of_origin}
${itemnumber.custitemnumber_cnt_country_of_origin}
${tranline.itemnumber.custitemnumber_cnt_country_of_origin}
(tranline in this case is salesorder.item as tranline)
All I'm looking to do is display the Country of Origin in this table via the template:
<#list salesorder.item as tranline><tr>
<td colspan="12"><span class="itemname"><DISPLAY COO HERE></td>
<td colspan="3">${tranline.custcol_mr_po_line_no}</td>
<td align="right" colspan="4" style="width: 72px;">${tranline.quantityordered}</td>
<td align="right" colspan="4" style="width: 84px;">${tranline.quantityremaining}</td>
<td align="right" colspan="4" style="width: 79px;">${tranline.quantity}</td>
</tr>
</#list>
It may be a different ID. Try Opening a Sales Order Saved Search and adding a Formula (text) filter. It should open the formula creator (see image). Use the Field Drop down to find your desired field and it will populate the field ID in the Formula box. formula creator

Scripting Issue with Netsuite Advanced PDF/HTML Template

I need help with the Freemarker format for Netsuite (Advanced PDF/HTML Templates)
There are 3 important data values pulled for this records;
${item.quantity} *Order Value*
${item.fulfilled} *Fulfilled Value*
${item.backordered} *Backorder Value*
Basically, what I try to accomplish is, to only show items that are "on backorder"
However this task seems to be a much harder than I have the time and skill for.
So, my plan B is using a separate template for the backorders (which is working well so far!)
The problem is that if I came across an item which is a NON-INVENTORY item, Netsuite does not calculate any qty for ${item.backordered}
SO
Is there any way I can "calculate" the backorder value with scripting in the template?
Can I use an arithmetic function (like below)?
item.quantity - item.fulfilled = item.backordered
Here is the basic format of the text surrounding this query;
<#if record.item?has_content>
<table><#list record.item as item><#if item_index==0>
<thead>
<tr>
<th> QTY </th>
</tr>
</thead>
</#if>
<tr>
<td> ${item.backordered} </td>
</tr>
</#list></table>
</#if>
I have a basic understanding of HTML and CSS, but scripting is still very new to me, so please only constructive criticism.
Try adding the following Freemarker helper function to your template:
<#function toNumber val>
<#if val?has_content && val?length gt 0 >
<#return val?html?replace('[^0-9.]','','r')?number >
<#else>
<#return 0 >
</#if>
</#function>
This will ensure that all fields are correctly parsed as numbers, and you should be able to perform mathematical calculations on the fields without errors.
So you can replace:
<td> ${item.backordered} </td>
with:
<td> ${toNumber(item.quantity) - toNumber(item.fulfilled)} </td>
See the answer to suitescript set custom column value netsuite for an example that uses arithmetic on line item values.
So I believe the root problem lays with the Java JAR NetSuite is using. It appears it has a null pointer bug with empty int/number type values.
I would recommend adding a UserEvent script to change the values to zero that are empty. This will prevent the error you are getting. You should be able to catch the PRINT type on the before load event. If the zero value is not carried over to the template, you can add a custom column field that is not stored and push the value there.

Obtaining site's HTML after GET that returns JSON

Introduction
The main question is way down, but I guess it'd help to have some background in this case
Ok, so I'd like to start by saying that this is actually my first question on stackoverflow - I have been using this site for ages, and I basically learned everything I know about coding from it, but that also means I have huge gaps in my knowledge - a lot of the methods I use are chosen just because they are the only ones I know - if you have any suggestion how I can improve the process described below, do not hesitate to share them with me. I would also like to apologize in advance if my request is in any way unclear, I'll try to elaborate in any such case.
Method
I am trying to crawl individual players' performance in UEFA Champions League matches (I'm actually building a Fantasy Football app, a project I reckon I'll have many questions about in the future as well). My source are the UEFA statistics sites, e.g. "http://www.uefa.com/uefachampionsleague/season=2016/matches/live/index.html?day=2&session=1&match=2015684". There, about in the middle you can choose "PLAYER" statistics, and see a "table" (actually it's a div with lists) where (by default) statistics concerning given (single) match are presented. When fully loaded in HTML there are two divs, one for match stats, one for overall, some elements of the lists are hidden (based on the position of the player for example), but all are there. The part that I'm interested in looks like this:
<div id="matchTab" class="tab-panel rounded-down scrollable ui-tabs-panel ui-widget-content ui-corner-bottom" aria-labelledby="ui-id-7" role="tabpanel" aria-expanded="true" aria-hidden="false">
<div class="tab-content">
<div class="col-stats">
<ul class="goals-table stats">
<li style="display: list-item;">
Goals scored
<span class="value goals-scored">1</span>
</li>
<li style="display: none;">
<li class="bg-highlight" style="display: none;">
<li style="display: none;">
<li class="bg-highlight" style="display: none;">
</ul>
<ul class="attempts-table stats" style="display: block;">
<ul class="passes-attempt-table stats">
<ul class="fouls-table fouls-table-gk stats">
</div>
<div class="col-stats">
</div>
</div>
(Most of the code is collapsed)
Right now I am using WinHTTPRequest in VBA, hoping to populate an Excel range with data, but in the end I will move the project to VB.NET and use SQL. The problem is that I don't seem to be able to obtain the date presented in the list. Using:
whReq.Open "GET", "http://www.uefa.com/uefachampionsleague/season=2016/matches/live/index.html?day=2&session=1&match=2015684"
Returns only the main structure of the side, not the data from the "table". I therefore used FireBug, and then WireShark to inspect the data that's being transferred when a player is changed in the selection. One packet is general stats about the player, his age, name, etc. - useless. The second one looks like this:
GET /livecommon/match-centre/cup=1/season=2016/round=2000634/player=103697/overall.json?v=1448115572662
(The "v" parameter is actually useless, works the same way without it)
which actually does return a bunch of data. Apparently it's in the form of JSON, and looks for example like this:
{"Players":null,"OverallStat":{"250021048":{"PlayerId":250021048,"TeamId":0,"MatchesPlayed":3,"MinutesPlayed":188,"GoalsScored":0,"GoalsConceded":0,"GoalsByMinute":0,"GoalsByAttempts":0,"TotalAttempts":2,"Assist":0,"Saves":0,"SavesOnAttempts":0,"SavesByMinutes":0,"FoulsCommitted":3,"FoulsCommittedByMinute":63,"FoulsSuffered":0,"FoulsSufferedByMinute":0,"FoulsPenalty":0,"FoulsSuffPenalty":0,"YellowCard":0,"RedCard":0,"Passes":149,"PassingDistribution":0,"PassesCompleted":68,"PassesAttempted":81,"PassingAccuracy":84,"Delivery":0,"Run":2,"AttempsOn":0,"AttempsOff":2,"Offside":1,"ShotHittingPost":0,"HittingBar":0,"ShotBlocked":2,"Corners":0,"Attacks":0,"BigChance":0,"BallPossession":0,"DistanceCovered":18655,"ClearancesAttempted":4,"ClearancesCompleted":3,"Blocked":0,"TackleCompleted":0,"TackleWrong":0}},"LastUpdatedCET":"05 November 2015, 11:47 CET","LastUpdateDay":5,"LastUpdateMonth":11,"LastUpdateYear":2015,"LastUpdateHour":11,"LastUpdateMinute":47}
And this it the kind of response that is obtained whenever a player is changed, no matter whether single match statistics or overall are chosen (of course one does not have to actually be on the site, no cookies are needed, just "http://www.uefa.com/livecommon/match-centre/cup=1/season=2016/round=2000634/player=250021048/overall.json" and there you have the statistics)
The thing is, those are overall statistics. I could understand there is some kind of code that calculates statistics for individual match (I can actually do with that myself, just refresh data after each match to calculate the statistics from individual matches). Nevertheless, they tend to update the statistics irregularly, so I would really prefer to be able to retrieve stats from individual matches. So:
Question
Given the above, is there a way to obtain the html of the site after the another GET for player statistics, using WinHTTPRequest? If not, what could be the best way? I did try working with InternetExplorer object, but was unable to produce any results at all (I actually had the same problem at work, where I needed to access our company's site - I couldn't even check for readystate, over site's worked, but I guess it's a topic for another question)
Thanks in advance, and again, sorry if anything I wrote is unclear.

How can I support rule definition from a user for my business logic processing?

I have a case where I have an existing method that does a specific kind of processing. I have setup a database table that it checks and if a specific value in a column exists it uses the value in one of the columns.
Example: let's say that I have a method that charges a user. And I have in the table a row that has a column for the country and a column for reduction percentage. So while I am processing the user if the user's country exists in the table I use the value of the column to reduce the price. So far so good.
My question is how could I enhance my design in order to add more general/complex rules?
E.g. I would like to support some kind of interface that the user specifies rules e.g. a user's age or a product weight etc and based on this rules my code processing can figure out how to apply them?
I mean how could I extend my simple table and business logic processing with the country/percentage values to a small rule based setup?
I don't need really complex rules. Just the ability to be let the define a rule if needed
You have to support a certain set of operators, as well as possible fields to be checked against the rule and certain events when the rule is fullfilled.
I would suggest something like this: jsFiddle
<table>
<tr>
<td>Field</td>
<td>
<select><option>Country</option><option>Age</option></select>
</td>
</tr>
<tr>
<td>Operator</td>
<td><select><option>greater than</option><option>smaller than</option><option>not empty</option></select>
</td>
</tr>
<tr>
<td>Value</td>
<td><input id="value" type="text" /></td>
</tr>
<tr>
<td>action</td>
<td><select><option>10% discount</option><option>other stuff</option><option>other stuff 2</option></select></td>
</tr>
</table>
That's just a very quick example of how it could look. You can add any operators and actions you want. You could also include a target field for example. But what's actually in the dropdowns depends on your requirements.