• Harish Narayanan
  • NEWBIE
  • 55 Points
  • Member since 2014

  • Chatter
    Feed
  • 2
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 3
    Questions
  • 5
    Replies
Hi Community

I've got this business problem that we need to have a field on OpportunityLineItem (OLI for short) which represents it's revenue value. But first I need to give you insights on how we set up our model.

We usually have several OLIs on our Opportunities (Opp for short). We grant discounts on 3 levels:
- Difference between List- & Salesprice (= Product Discount, irrelevant here)
- Flat discount amount (= Special Discount Flat)
- Percentage based amount (applied after subtraction of Special Discount Flat, resulting in Special Discount Amount)

Because we often sell our clients packages including multiple product families and we need to get insights on revenue by product family and sales rep, we need this additional information on OLI.

So here's what I do:
On every after trigger action on OLI I recalculate the revenue values of each OLI. On after Opp update with changes in discount fields I invoke the same piece of code including only relevant records (unfinished).
I have a field on OLI that calculates it's share percentage off the Opp amount. So if my OLI would be 2'500 and my Opp amount 10'000 the Share would be 25%. Let's say, this Opportunity also has a Total Discount of 2'000 resulting in 8'000 Opp Amount. Those 2000 need to be distributed over the OLIs according to their share. So the aforementioned OLI would receive 2000 * 25% = 500 of the total discounts as a subtraction to it's value. The resulting revenue value of the OLI would then be 2'500 - 500 = 2'000.

Of course, we have a special case. One Product family may not get Opp discounts applied to unless all OLIs of the Opp are of that product family. So what I do here is gather the OLI share amounts of that product family, add it on top of the total Opp discount and redistribute that total Opp discount on all other OLIs.

I know this is really confusing to imagine so I made a google spreadsheet with a calculation example you can find here (https://docs.google.com/spreadsheets/d/1KZgGShICwAEEqreEt5CNg5ZMinAt165C1qUjOCHNjfI/edit?usp=sharing).

Now my problem is, the code works, but it generates too much inaccuracy. I know that calculating with Double values and percentages will inevitably generate some inaccuracy, but I'd never have imagined that it would generate an inaccuracy of about 3 to 10 on an amount of 7200. Funnily, the inaccuracy seems to be in junction with the Data types I use. I use double  as a main container for values and sub results. However, the Share percentage is in decimal format. I have to transform the percentage (3,15) number into a double.

A strange thing I found out is that if I add floating point zeroes to variables I declare, the revenue value changes into another inaccurate result. Being a double, the amount of zeroes added to the variable during declaration should not matter at all...

Anyway, what I find even more strange is that the google spreadsheet seems to be either more precise or is just intelligent enough to overcome the inaccuracies.

Here is my code:
private void startProcess()
{
	// Based on oppMap Ids, collect all relevant OLIs, exit if nothing to process
	newOLIs = getAllOlis(oppMap.keySet()); // newOLIs is map<Id,OpportunityLineItem>
	// Create the oppOliMap for splitting
	oppOliMap = getOppOliMap(newOlis.values()); // oppOliMap is map<OppId,list<OpportunityLineItem>>
	
	list<OpportunityLineItem> oliUpdate = new list<OpportunityLineItem>();
	
	for ( Id oppId : oppOliMap.keySet() )
	{
		Integer numMDBs = 0;
		Double discountStackMDB = 0.0;
		Double nonMDBShare = 0.0;
		Double nonMDBMultiplier = 0.0;
		
		// Get the number of MDBs and their total discount share
		for ( OpportunityLineItem oli : oppOliMap.get(oppId) )
		{
			if ( oli.ProductFamily__c.contains('MDB') || (oli.ProductFamily__c.contains('Membership') && oli.ProductFamily__c.contains('Designboom')) )
			{
				numMDBs++;
				discountStackMDB += getShareAmount(oppMap.get(oppId), oli.Share__c);
			}
			else
			{
				nonMDBShare += (oli.Share__c.doubleValue() / 100.0);
			}
		}
		
		nonMDBMultiplier = 1.0 / nonMDBShare; 
		
		if ( numMDBs == 0 || numMDBs == oppOliMap.get(oppId).size() )
		{
			for ( OpportunityLineItem oli : oppOliMap.get(oppId) )
			{
				oli.Revenue__c = oli.Salesprice_Total__c - getShareAmount(oppMap.get(oppId), oli.Share__c);
				
				if ( oli.Revenue__c <= 0.0000 && !(oli.Revenue__c == 0.0000 && oli.Salesprice_Total__c == 0.0000) )
				{
					oli.Revenue__c.addError('The System Administrator was not good enough in math and caused this error. Please forgive him and ' 
					+ 'tell him immediately');
				}
				else
				{
					oliUpdate.add(oli);
				}
			}
		}
		else
		{
			for ( OpportunityLineItem oli : oppOliMap.get(oppId) )
			{
				if ( oli.ProductFamily__c.contains('MDB') || (oli.ProductFamily__c.contains('Membership') && oli.ProductFamily__c.contains('Designboom')) )
				{
					oli.Revenue__c = oli.Salesprice_Total__c;
					
					if ( oli.Revenue__c <= 0.0000 && !(oli.Revenue__c == 0.0000 && oli.Salesprice_Total__c == 0.0000) )
					{
						oli.Revenue__c.addError('The System Administrator was not good enough in math and caused this error. Please forgive him and ' 
						+ 'tell him immediately');
					}
					else
					{
						oliUpdate.add(oli);
					}
				}
				else
				{
					oli.Revenue__c = oli.Salesprice_Total__c - getShareAmount(oppMap.get(oppId), oli.Share__c)
					- (discountStackMDB * (oli.Share__c.doubleValue() / 100.0) * nonMDBMultiplier);
					
					if ( oli.Revenue__c <= 0.0000 && !(oli.Revenue__c == 0.0000 && oli.Salesprice_Total__c == 0.0000) )
					{
						oli.Revenue__c.addError('The System Administrator was not good enough in math and caused this error. Please forgive him and ' 
						+ 'tell him immediately');
					}
					else
					{
						oliUpdate.add(oli);
					}
				}
			}
		}
	}
	
	try
	{
		update oliUpdate;
		if ( Test.isRunningTest() )
		{
			System.debug('Throwing Error intentionally');
			insert new Case();
		}
	}
	catch(System.DMLException dex)
	{
		System.debug('There was an error during the OLI Update');
	}
}
Auxiliary method used:
private static Double getShareAmount(Opportunity opp, Decimal share)
{
	Double result = 0.0;
	
	if ( opp.SpecialDiscountFlat__c != NULL )
	{
		result += opp.SpecialDiscountFlat__c;
	}
	if ( opp.Special_Discount_Amount__c != NULL )
	{
		result += opp.Special_Discount_Amount__c;
	}
	// Salesforce treats percentage fields as simple decimals: 7.68% == 7.68 and not 0.0768
	result *= (share.doubleValue() / 100.0);
	return result;
}

 
Hello Buddies,

Iam preparing for 501 exam, in many of the blogs i collected many questions. Some of the below questions am not able to answer. Will you give me the answers for these.
Q1) How can multiple Force.com developers colloborate as a team? Select Only 2options
A) Store metadata definitions in a version control system.
B) Share application source code with third parties using AppExchange publishing.
C) Create a seperate a sandbox for each developer.
D) Save historical version of every metadata component on the Force.com Servers.

Q2) What is a best practice when writing unit tests?  Select 2 options only
A) Leverage Existing Organizational data in test execution to validate data-specific reasons.
B) Develop unit test, which cover upto 50% of classes an triggers.
C) Leverage the startTest and stopTest static methods to test governor limits.
D) Test governors for triggers by using many records when performing DML.

Q3) What is a best practice of testMethods? Only one option
A) Assert the behavior of the application on all test Scenarios.
B) Query up existing records to use in tests rather than creating new records in the testMethod.
C) Write atleast one bulk test for every functionality that tests Large data volumes for applicable use cases.
D) The testMethod should make multiple startTest and stopTest statements to start and stop multiple test scenarios.

Q4) A financial company provides financial services to individuals with high net worth.They use Salesforce CRM to track their client interactions. In a Developer Sand box, they enhanced custom businesss logic to remind their account managers about important dates, such as birthdays and anniversaries, for any client or member of a client's household.
How should the financial company roll out their Force.com application from the Developer Sandbox to the account managers?
A) by exporting the application as a .csv file.
B) by deploying the application using metadata files.
C) by publishing the application as a package.
D) by using Salesforce to Salesforce.

Q5) Which environment should be used to debug data-related issues reported in an active production organization?
A) Partial Data Sandbox
B) Developer Pro Sandbox
C) Full Sandbox
Developer Sandbox.

Q6) A Java Program running on a UNIX machine needs to access Salesforce data? What could be used to accomplish this? Only 2options
A) Force.com SOAP API
B) Visualforce pages.
C) Apex trigger
D) Custom Apex Web Services

Q7) Which environment is appropriate for developing a new Force.com application for sale or distribution? Only one option
A) Developer Sandbox
B) Salesforce Commerce edition
C) Full Sandbox
D) Partial Data Sandbox

 
Hello,

I am trying to import the partner.wsdl in my java environment. I am using Mac OS X 10.10 and JDK 1.7 u60. I downloaded the WSC jar file from http://mvnrepository.com/artifact/com.force.api/force-wsc/33.0.3 and using it to import the wsdl file. The jar file, wsdl file are in the current directory.
When I execute the following command, I get a bunch of error messages.

java -classpath force-wsc-33.0.1.jar com.sforce.ws.tools.wsdlc partner.wsdl partner.jar

Exception in thread "main" java.lang.NoClassDefFoundError: org/stringtemplate/v4/STGroupDir
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2570)
    at java.lang.Class.getMethod0(Class.java:2813)
    at java.lang.Class.getMethod(Class.java:1663)
    at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486)
Caused by: java.lang.ClassNotFoundException: org.stringtemplate.v4.STGroupDir
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 6 more

When I googled, they point to issues in classpath, but I have referenced to the right classpath in my environment variable. 

<~/Downloads>echo ${CLASSPATH}

:/Library/Java/JavaVirtualMachines/jdk1.7.0_60.jdk/Contents/Home:/Users/harish/Downloads:/Users/harish/Coding/JM


Could someone help me with this situation? Thanks.

-Harish
I am trying to observe the technical differences between using workflow email alerts and auto-response rules for cases. I created a workflow alert which triggers on creation of new case and every subsequent edits to the case record. I also created an auto-response rule. Both the settings use different email templates.

When I create a case using OnDemand Email-to-case, it creates 2 new email records in the Email related lists for the case record. I also receive 2 different emails (one triggered by workflow and the other by auto-response rules).

Subsequently when I changed the status of the case to working, I expect to see an email sent to the case customer email and another record created in the Email related list. However, I do receive the email, but the process doesn't create a record in the Email related list. Does anybody know why such a behavior? Has anyone came across something like this.

Also, can someone please explain, under what scenario(s), does one use workflow email alerts and auto-response rules.

I have already read the explanation given here https://help.salesforce.com/HTViewHelpDoc?id=rules_differences_auto_workflow.htm&language=en_US but it isn't that helpful. They almost look the same. So please don't direct me back to the same link in your response.

Many thanks.
Dear Dev Community,

How do I associate my existing salesforce.com certifications to my developer account?

Thank you,
Harish
Hello,

I am trying to import the partner.wsdl in my java environment. I am using Mac OS X 10.10 and JDK 1.7 u60. I downloaded the WSC jar file from http://mvnrepository.com/artifact/com.force.api/force-wsc/33.0.3 and using it to import the wsdl file. The jar file, wsdl file are in the current directory.
When I execute the following command, I get a bunch of error messages.

java -classpath force-wsc-33.0.1.jar com.sforce.ws.tools.wsdlc partner.wsdl partner.jar

Exception in thread "main" java.lang.NoClassDefFoundError: org/stringtemplate/v4/STGroupDir
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2570)
    at java.lang.Class.getMethod0(Class.java:2813)
    at java.lang.Class.getMethod(Class.java:1663)
    at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486)
Caused by: java.lang.ClassNotFoundException: org.stringtemplate.v4.STGroupDir
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 6 more

When I googled, they point to issues in classpath, but I have referenced to the right classpath in my environment variable. 

<~/Downloads>echo ${CLASSPATH}

:/Library/Java/JavaVirtualMachines/jdk1.7.0_60.jdk/Contents/Home:/Users/harish/Downloads:/Users/harish/Coding/JM


Could someone help me with this situation? Thanks.

-Harish

Hi All,


I wrote a Test class for 2 Triggers in Sandbox,

Earlier it covered 92%, before refreshed my Sandbox, and again when I Run my Test It is showing 0%, even though Test is passed.

I don't know why code coverage is 0%?

Can you please help me out?

Thanks in Advance...............

Hi Community

I've got this business problem that we need to have a field on OpportunityLineItem (OLI for short) which represents it's revenue value. But first I need to give you insights on how we set up our model.

We usually have several OLIs on our Opportunities (Opp for short). We grant discounts on 3 levels:
- Difference between List- & Salesprice (= Product Discount, irrelevant here)
- Flat discount amount (= Special Discount Flat)
- Percentage based amount (applied after subtraction of Special Discount Flat, resulting in Special Discount Amount)

Because we often sell our clients packages including multiple product families and we need to get insights on revenue by product family and sales rep, we need this additional information on OLI.

So here's what I do:
On every after trigger action on OLI I recalculate the revenue values of each OLI. On after Opp update with changes in discount fields I invoke the same piece of code including only relevant records (unfinished).
I have a field on OLI that calculates it's share percentage off the Opp amount. So if my OLI would be 2'500 and my Opp amount 10'000 the Share would be 25%. Let's say, this Opportunity also has a Total Discount of 2'000 resulting in 8'000 Opp Amount. Those 2000 need to be distributed over the OLIs according to their share. So the aforementioned OLI would receive 2000 * 25% = 500 of the total discounts as a subtraction to it's value. The resulting revenue value of the OLI would then be 2'500 - 500 = 2'000.

Of course, we have a special case. One Product family may not get Opp discounts applied to unless all OLIs of the Opp are of that product family. So what I do here is gather the OLI share amounts of that product family, add it on top of the total Opp discount and redistribute that total Opp discount on all other OLIs.

I know this is really confusing to imagine so I made a google spreadsheet with a calculation example you can find here (https://docs.google.com/spreadsheets/d/1KZgGShICwAEEqreEt5CNg5ZMinAt165C1qUjOCHNjfI/edit?usp=sharing).

Now my problem is, the code works, but it generates too much inaccuracy. I know that calculating with Double values and percentages will inevitably generate some inaccuracy, but I'd never have imagined that it would generate an inaccuracy of about 3 to 10 on an amount of 7200. Funnily, the inaccuracy seems to be in junction with the Data types I use. I use double  as a main container for values and sub results. However, the Share percentage is in decimal format. I have to transform the percentage (3,15) number into a double.

A strange thing I found out is that if I add floating point zeroes to variables I declare, the revenue value changes into another inaccurate result. Being a double, the amount of zeroes added to the variable during declaration should not matter at all...

Anyway, what I find even more strange is that the google spreadsheet seems to be either more precise or is just intelligent enough to overcome the inaccuracies.

Here is my code:
private void startProcess()
{
	// Based on oppMap Ids, collect all relevant OLIs, exit if nothing to process
	newOLIs = getAllOlis(oppMap.keySet()); // newOLIs is map<Id,OpportunityLineItem>
	// Create the oppOliMap for splitting
	oppOliMap = getOppOliMap(newOlis.values()); // oppOliMap is map<OppId,list<OpportunityLineItem>>
	
	list<OpportunityLineItem> oliUpdate = new list<OpportunityLineItem>();
	
	for ( Id oppId : oppOliMap.keySet() )
	{
		Integer numMDBs = 0;
		Double discountStackMDB = 0.0;
		Double nonMDBShare = 0.0;
		Double nonMDBMultiplier = 0.0;
		
		// Get the number of MDBs and their total discount share
		for ( OpportunityLineItem oli : oppOliMap.get(oppId) )
		{
			if ( oli.ProductFamily__c.contains('MDB') || (oli.ProductFamily__c.contains('Membership') && oli.ProductFamily__c.contains('Designboom')) )
			{
				numMDBs++;
				discountStackMDB += getShareAmount(oppMap.get(oppId), oli.Share__c);
			}
			else
			{
				nonMDBShare += (oli.Share__c.doubleValue() / 100.0);
			}
		}
		
		nonMDBMultiplier = 1.0 / nonMDBShare; 
		
		if ( numMDBs == 0 || numMDBs == oppOliMap.get(oppId).size() )
		{
			for ( OpportunityLineItem oli : oppOliMap.get(oppId) )
			{
				oli.Revenue__c = oli.Salesprice_Total__c - getShareAmount(oppMap.get(oppId), oli.Share__c);
				
				if ( oli.Revenue__c <= 0.0000 && !(oli.Revenue__c == 0.0000 && oli.Salesprice_Total__c == 0.0000) )
				{
					oli.Revenue__c.addError('The System Administrator was not good enough in math and caused this error. Please forgive him and ' 
					+ 'tell him immediately');
				}
				else
				{
					oliUpdate.add(oli);
				}
			}
		}
		else
		{
			for ( OpportunityLineItem oli : oppOliMap.get(oppId) )
			{
				if ( oli.ProductFamily__c.contains('MDB') || (oli.ProductFamily__c.contains('Membership') && oli.ProductFamily__c.contains('Designboom')) )
				{
					oli.Revenue__c = oli.Salesprice_Total__c;
					
					if ( oli.Revenue__c <= 0.0000 && !(oli.Revenue__c == 0.0000 && oli.Salesprice_Total__c == 0.0000) )
					{
						oli.Revenue__c.addError('The System Administrator was not good enough in math and caused this error. Please forgive him and ' 
						+ 'tell him immediately');
					}
					else
					{
						oliUpdate.add(oli);
					}
				}
				else
				{
					oli.Revenue__c = oli.Salesprice_Total__c - getShareAmount(oppMap.get(oppId), oli.Share__c)
					- (discountStackMDB * (oli.Share__c.doubleValue() / 100.0) * nonMDBMultiplier);
					
					if ( oli.Revenue__c <= 0.0000 && !(oli.Revenue__c == 0.0000 && oli.Salesprice_Total__c == 0.0000) )
					{
						oli.Revenue__c.addError('The System Administrator was not good enough in math and caused this error. Please forgive him and ' 
						+ 'tell him immediately');
					}
					else
					{
						oliUpdate.add(oli);
					}
				}
			}
		}
	}
	
	try
	{
		update oliUpdate;
		if ( Test.isRunningTest() )
		{
			System.debug('Throwing Error intentionally');
			insert new Case();
		}
	}
	catch(System.DMLException dex)
	{
		System.debug('There was an error during the OLI Update');
	}
}
Auxiliary method used:
private static Double getShareAmount(Opportunity opp, Decimal share)
{
	Double result = 0.0;
	
	if ( opp.SpecialDiscountFlat__c != NULL )
	{
		result += opp.SpecialDiscountFlat__c;
	}
	if ( opp.Special_Discount_Amount__c != NULL )
	{
		result += opp.Special_Discount_Amount__c;
	}
	// Salesforce treats percentage fields as simple decimals: 7.68% == 7.68 and not 0.0768
	result *= (share.doubleValue() / 100.0);
	return result;
}

 
Hello Buddies,

Iam preparing for 501 exam, in many of the blogs i collected many questions. Some of the below questions am not able to answer. Will you give me the answers for these.
Q1) How can multiple Force.com developers colloborate as a team? Select Only 2options
A) Store metadata definitions in a version control system.
B) Share application source code with third parties using AppExchange publishing.
C) Create a seperate a sandbox for each developer.
D) Save historical version of every metadata component on the Force.com Servers.

Q2) What is a best practice when writing unit tests?  Select 2 options only
A) Leverage Existing Organizational data in test execution to validate data-specific reasons.
B) Develop unit test, which cover upto 50% of classes an triggers.
C) Leverage the startTest and stopTest static methods to test governor limits.
D) Test governors for triggers by using many records when performing DML.

Q3) What is a best practice of testMethods? Only one option
A) Assert the behavior of the application on all test Scenarios.
B) Query up existing records to use in tests rather than creating new records in the testMethod.
C) Write atleast one bulk test for every functionality that tests Large data volumes for applicable use cases.
D) The testMethod should make multiple startTest and stopTest statements to start and stop multiple test scenarios.

Q4) A financial company provides financial services to individuals with high net worth.They use Salesforce CRM to track their client interactions. In a Developer Sand box, they enhanced custom businesss logic to remind their account managers about important dates, such as birthdays and anniversaries, for any client or member of a client's household.
How should the financial company roll out their Force.com application from the Developer Sandbox to the account managers?
A) by exporting the application as a .csv file.
B) by deploying the application using metadata files.
C) by publishing the application as a package.
D) by using Salesforce to Salesforce.

Q5) Which environment should be used to debug data-related issues reported in an active production organization?
A) Partial Data Sandbox
B) Developer Pro Sandbox
C) Full Sandbox
Developer Sandbox.

Q6) A Java Program running on a UNIX machine needs to access Salesforce data? What could be used to accomplish this? Only 2options
A) Force.com SOAP API
B) Visualforce pages.
C) Apex trigger
D) Custom Apex Web Services

Q7) Which environment is appropriate for developing a new Force.com application for sale or distribution? Only one option
A) Developer Sandbox
B) Salesforce Commerce edition
C) Full Sandbox
D) Partial Data Sandbox

 
I am trying to observe the technical differences between using workflow email alerts and auto-response rules for cases. I created a workflow alert which triggers on creation of new case and every subsequent edits to the case record. I also created an auto-response rule. Both the settings use different email templates.

When I create a case using OnDemand Email-to-case, it creates 2 new email records in the Email related lists for the case record. I also receive 2 different emails (one triggered by workflow and the other by auto-response rules).

Subsequently when I changed the status of the case to working, I expect to see an email sent to the case customer email and another record created in the Email related list. However, I do receive the email, but the process doesn't create a record in the Email related list. Does anybody know why such a behavior? Has anyone came across something like this.

Also, can someone please explain, under what scenario(s), does one use workflow email alerts and auto-response rules.

I have already read the explanation given here https://help.salesforce.com/HTViewHelpDoc?id=rules_differences_auto_workflow.htm&language=en_US but it isn't that helpful. They almost look the same. So please don't direct me back to the same link in your response.

Many thanks.