• isalew
  • NEWBIE
  • 145 Points
  • Member since 2013
  • Customer Engagement Consultant
  • Slalom


  • Chatter
    Feed
  • 3
    Best Answers
  • 1
    Likes Received
  • 18
    Likes Given
  • 12
    Questions
  • 31
    Replies
Hi All,
How to create page block sections in lighting components 
Thanks 
Sai
  • March 21, 2016
  • Like
  • 0
I am building two lightning components, one which iterates inside of a parent component. When I fire the "e.force:navigateToSObject" action based on a record Id contained in the parent component attributes, it successfully opens the record. However, when I fire the "e.force:navigateToSObject" action based on a record Id contained in the child component attributes, I receive the following error:

"You can't view this page, either because you don't have permission or because the page isn't supported on mobile devices."

I tried firing the "navigateToSObject" event directly from the child component, and also tried using a custom event to feed the recordId parameter to the parent component to throw the "navigateToSObject" event (see code sample below). Does anyone have any ideas how to resolve this?

Parent Component
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes">

  <!-- Attributes -->
  <aura:attribute name="account" type="Account" default="{'sobjectType':'Account'}"></aura:attribute>
  <aura:attribute name="products" type="ControllerClass.ProductPrice[]"></aura:attribute>

  <!-- Events -->
  <aura:handler name="openProduct" event="c:OpenProductEvt" action="c.openProduct"></aura:handler>

  <!-- PRODUCT LIST -->
  <aura:iteration items="{!v.products}" var="product">
    <c:CPQ_SSG_ContractPriceLookupItem product="{!product}"></c:CPQ_SSG_ContractPriceLookupItem>
  </aura:iteration>
  <!-- / PRODUCT LIST -->

</aura:component>

Parent Component Controller
({
	openProduct : function(cmp,evt,hlp)
	{
	  console.log('in c.openProduct');
		var recordId = evt.getParam('recordId');
		var slideDevName = evt.getParam('slideDevName');
		var navEvt = $A.get("e.force:navigateToSObject");
		navEvt.setParams({
			"recordId": recordId,
			"slideDevName": slideDevName
		});
		navEvt.fire();
	},
})

Child Component
<aura:component>

  <!-- Attributes -->
  <aura:attribute name="product" type="ControllerClass.ProductPrice" default="{'sObjectType':'ControllerClass.ProductPrice'}" description="ProductPrice container to hold Product2 and External Pricing information"></aura:attribute>

  <!-- Events -->
  <aura:registerEvent name="openProduct" type="c:OpenProductEvt" description="Notifies parent listeners to open record in list"></aura:registerEvent>

  <!-- Markup -->
  <tr class="slds-hint-parent">
    <td data-label="Product Name">
      <ui:outputURL aura:id="theProductLink" value="#" label="{!v.product.productName}" click="{!c.openUrl}"></ui:outputURL>
    </td>
  </tr>

</aura:component>

Child Component Controller
({
	openUrl: function(cmp,evt,hlp)
	{
		var product = cmp.get("v.product");
		var openEvent = cmp.getEvent("openProduct");
		openEvent.setParams({
			"recordId" : product.productId,
			"slideDevName" : "detail"
		}).fire();
	},
})

Event
<aura:event type="COMPONENT" description="Record for navigation">
  <aura:attribute name="recordId" type="String" description="Id of record to navigate to"></aura:attribute>
  <aura:attribute name="slideDevName" type="String" default="detail" description="record layout to open"></aura:attribute>
</aura:event>
  • April 05, 2016
  • Like
  • 0
The Lightning Components Developer Guide warns about using the same name for client and server controller actions:
Use unique names for client-side and server-side actions in a component. A JavaScript function (client-side action) with the same name as a server-side action (Apex method) can lead to hard-to-debug issues.
I was unlucky enough to miss this tip before I debugged one of those hard-to-debug issues. To prevent others from making the same mistake, I wanted to share my debug path in case you miss the memo about naming conventions and run into similar symptoms:

PricingTool.cmp
My component contains a button that runs a client controller action named "c.getPricing"

<pre>
<aura:component controller="ServerController">
  <aura:attribute name="products" type="ServerController.ProductPrice[]"></aura:attribute>
  <ui:button aura:id="buttonGetPricing" label="Get Pricing" press="{!c.getPricing}"></ui:button>
</aura:component>
</pre>

PricingToolController.js
The controller action calls a helper action with the same name: "hlp.getPricing"

<pre>
({
    getPricing: function(cmp,evt,hlp){
        console.log('in c.getPricing');
        hlp.getPricing(cmp,hlp);
    }
})
</pre>

PricingToolHelper.js
My helper attempts to call a server-side action "c.getPricing", which is the same name as the client-side action "c.getPricing"

<pre>
({
    getPricing : function(cmp,hlp)
    {
        console.log('in hlp.getPricing');
        var action = cmp.get('c.getPricing');
        var products = cmp.get('v.products');
        action.setParams({productList : products});
        action.setCallback(this,function(res){
            console.log('in hlp.getPricing callback');
            var state = res.getState();
            console.log('hlp.getPricing ' + state);
            if (state === "SUCCESS") {
                var pricing = JSON.parse(res.getReturnValue().body);
                console.log(pricing);
            }
        });
        $A.enqueueAction(action);
    },
})
</pre>

ServerController.cls
The server code successfully passes unit testing, but when launched from my Lightning Component helper class, no "/aura" logs are created on the server, indicating the server code is never touched.

<pre>
public class ServerController{

    @AuraEnabled
    public static Response getPricing(List<ProductPrice> productList) {...}
}
</pre>

Back To The Client...
So the server action is never run, and my javascript console is growing a fearsome loop of the following log lines:
 
in c.getPricing             # client controller action triggered
in hlp.getPricing           # helper action triggered
in hlp.getPricing callback  # callout to "c.getPricing" triggered
hlp.getPricing SUCCESS      # callout successfully returned
undefined                   # the results of res.getReturnValue() are empty
in c.getPricing
in hlp.getPricing
in hlp.getPricing callback
hlp.getPricing SUCCESS
undefined

The Moral of this Story
When the helper attempts to "get" a server action from the component, it receives the client action instead, because they use the same name. This causes an endless loop on the client, where the controller executes itself again and again via the helper's action call. The callback won't throw any errors and happly continues with a "SUCCESS" state.

The fix to this all, of course, is quite simple.

ServerController.cls
First change the name of the server controller action:

<pre>
// public static Response getPricing(...) {...}
public static Response getServerPricing(...){...}
</pre>

PricingToolHelper.js
Then update the helper reference to the server controller:

<pre>
// var action = cmp.get('c.getPricing');
var action = cmp.get('c.getServerPricing');
</pre>

Happy Lightning Development!
  • March 27, 2016
  • Like
  • 0
I'm in a dev org and building a lightning component exposed through a lightning tab. I recently received this error string, but with no helpful information.

I tweaked some field references and then I received a different Error ID: 398773595-167529 (-1631740258)

Would anywone form Salesforce be able to provide more detail around these error Ids?
  • March 23, 2016
  • Like
  • 0
Trying to implement a mobile action but having difficulties using Visualforce or Lightning.

Requirements
  • Create a new record via mobile action from an Account or Opportunity record
  • On action, create, save, and display the record for editing
  • On cancel, delete the record
  • On save, update the record
  • NOTE: This record is created differently than standard records. It must be created and saved, then displayed for editing. If the user cancels this interaction, then the record is deleted. This differs from the standard Salesforce create action, where no record is created until saved.
Implementation Attempts

Attempt #1: Visualforce Page Redirect
  • On action, creates and displays record with standard “Cancel” and “Save” actions
  • On cancel, returns to action page, which creates a second record
  • On save, returns to action page, which creates a second record
  • Cannot override standard Cancel and Save actions
This means I cannot use a simple Visualforce page redirect because I cannot override the standard “Cancel” and “Save” buttons.

Attempt #2: Lightning Standalone App
  • On open from lightning tab, creates and displays record (but no parent record, since launched from tab menu)
  • On cancel, deletes the record, returns to originating record
  • On save, updates the record, redirects to new record
This works, except I cannot launch this page from a parent Account or Opportunity record via mobile action. This also creates an extra global menu item when a mobile action is much better UX.

Attempt #3: Lightning Component Embedded in Visualforce Page via Lighting Out
  • On action, creates and displays record (but displays without formatting, so lookups don’t work)
  • On cancel, deletes the record, returns to originating record
  • On save, updates the record, redirects to new record
The actions on this page work, but the page formatting breaks, so the user cannot enter critical data, such as lookups. The page is using the <force:recordEdit/> component to display the record details, so manual override of all input element styling is not feasible. Manually recreating the standard edit page with custom input fields is not sustainable either. Adding the <apex:includeLightning/> tag doesn't change any styling either.

Conclusion
I’m finding that Lightning components / apps do not officially support being launched via mobile action, so you have to embed Lightning components inside a visual force page via Lightning Out. This would work, except the automatic formatting typically provided to a lightning page when launched from a standalone Lightning App tab is stripped away when embedded in Visualforce, thereby breaking functionality like lookup fields.

Does anyone have a recommendation on how to navigate this kind of record create scenario in mobile? Is there a trick to using Visualforce? Or is there a way to include default styling via Lightning Out?
  • March 21, 2016
  • Like
  • 0
I'm building a trigger handler that references multiple objects to update the OpportunityLineItem object. I want to use dot notation as much as possible to eliminate SOQL queries.

The following loop shows an example of one cross-object reference that returns null, but I do not understand why:
for(OpportunityLineItem oli :olis){
    System.debug('Revenue Type: ' + oli.PriceBookEntry.Revenue_Type__c);
}

The following cookbook recipe (http://developer.force.com/cookbook/recipe/using-relationship-queries) suggests I can access these fields with dot notation:
SELECT Id, Name, Account.Name,
       (SELECT Quantity, UnitPrice, TotalPrice,
               PricebookEntry.Name,
               PricebookEntry.Product2.Family
        FROM OpportunityLineItems)
FROM Opportunity

Why am I unable to access this field with dot notation? How would I write things differently?
Thank you all for your help!
  • September 03, 2014
  • Like
  • 0
I have a custom object LeadCompany__c to associate related leads.

Can I use dot notation to pull a list of all leads associated with my custom object, rather than use an SOQL query?

Currently, I must use the following query:

List<Lead> Lds = [SELECT ID FROM Lead WHERE LC_Lead_Company__c = :ld.LC_Lead_Company__c];

Would it be possible to get this information without an SOQL query in the following manner:

List<Lead> leads = ld.LC_Lead_Company__c.Leads;
 
  • December 30, 2014
  • Like
  • 1
I wrote some Apex to manage multiple leads from the same company through a custom object, LeadCompany__c. The Apex works great on the surface, but there are a few serious flaws:

1. All the code is in a Trigger, not a class with methods.
2. I am using too many SOQL queries to perform cross-object manipulations.

Bulkifying code and building classes are a little beyond me, so I have two requests:
  • Can anyone show me how to bulkify these triggers?
  • Can anyone show me how to convert these triggers into classes/methods?
Any help would be greatly appreciated.
  • December 26, 2013
  • Like
  • 0
I have built a trigger that creates a custom object when a Lead record meets certain criteria. They are then associated by a lookup relationship.
By manual testing, the trigger works, but how do I write the apex test?

Currently, my code is as follows:

------------------------------------------------------------
@isTest

private without sharing class LC_TestClass{

    static testmethod void CRED_Test(){

    //Insert LD1
    Lead LD1 = new Lead(
        LastName = 'LD1',
        Email = 'LD1@LCA.com',
        Company = 'LCA',
        Status = 'Open - Not Contacted'
    );
    insert LD1;

    //Verify LCA
    LD1 = [SELECT ID, Company, LC_Lead_Company__c, Status, LC_Status__c, OwnerID FROM Lead WHERE ID = :LD1.id];
    LCA = [SELECT ID, Name, OwnerID, Status__c, Lead_Count__c, Domain__c FROM LeadCompay__c WHERE Domain__c = :LD1.LC_Email_Domain__c];

    System.assertEquals( LD1.LC_Company__c,   LCA.Id);
    System.assertEquals( LD1.OwnerId ,     LCA.OwnerId );
    System.assertEquals( 'LCA' ,      LCA.Name );
    System.assertEquals( 'Open - Not Contacted' ,  LCA.Status__c );
    System.assertEquals( '1' ,       LCA.Lead_Count__c );
------------------------------------------------------------

Unfortunately, the developer console gives me the following error from line 18:

sObject type 'LeadCompany__c' is not supported. If you are attempting to use a custom object, be sure to append the '__c' after the entity name...

Any help?
  • December 23, 2013
  • Like
  • 0

I built a trigger and class to count activities on leads and contacts. These counters are not updating when a user mass emails, however. Is there something I'm missing in this trigger?

 

 

trigger TP_TaskUpdateTouchPoints on Task (after delete, after insert, after undelete, after update) {

    Set<ID> ldIds = new Set<ID>();
    Set<ID> ctIds = new Set<ID>();

    //We only care about tasks linked to leads and contacts.
    String ldprefix = TP_CountsAndActivities.ldPrefix;
    String ctprefix = TP_CountsAndActivities.ctPrefix;
    
    //Add any lead or contact ids coming from the new data
    if (Trigger.new != null) {
        for (Task t : Trigger.new) {
            if (t.WhoId != null && String.valueOf(t.whoId).startsWith(ldprefix) ) {
                ldIds.add(t.whoId);
            }
            if (t.WhoId != null && String.valueOf(t.whoId).startsWith(ctPrefix)) {
                ctIds.add(t.whoId);
            }
        }
    }

    //Also add any lead or contact ids coming from the old data (deletes, moving an activity)
    if (Trigger.old != null) {
        for (Task t : Trigger.old) {
            if (t.WhoId != null && String.valueOf(t.whoId).startsWith(ldprefix) ) {
                ldIds.add(t.whoId);
            }
            if (t.WhoId != null && String.valueOf(t.whoId).startsWith(ctPrefix)) {
                ctIds.add(t.whoId);
            }

        }
    }
    
    // Only run trigger if there are records to update
    if (ldIds.size() > 0){
        TP_CountsAndActivities.updateLdCountsAndActivities(ldIds);
    }
    if (ctIds.size() > 0) {
        TP_CountsAndActivities.updateCtCountsAndActivities(ctIds);
    }
}

 

 

 

 

  • November 21, 2013
  • Like
  • 0

 

Does anyone know a good way to prevent users from taking ownership of records from a queue when they reach a certain record count?

 

For example, a user is allowed to pull leads from the queue, but once they own 2,500 leads, they should be unable to take more.

 

I'm thinking I could create two fields on the user object:

  • User.Max_Lead_Count (Number)
  • User.Current_Lead_Count (Number)

And then create a validation rule preventing ownership when the current lead count is equal to the max lead count.

 

My question is what kind of apex should I write to populate a lead count field on the user object?

  • October 15, 2013
  • Like
  • 0

I built some Apex for activities (Tasks/Events) on the lead object, but the apex class fails for several records. The error message reads:

 

Execution of AfterUpdate caused by: System.NullPointerException: Attempt to de-reference a null object

 

The stack trace mentions this line:

 

for (Task T : l.Tasks) {
    //This line is the one with an issue
     Date ActivityDate = date.newinstance(t.ActivityDate.year(),t.ActivityDate.month(),t.ActivityDate.day());

 

Any ideas?

  • October 04, 2013
  • Like
  • 0

SF Admin new to Apex.

 

I am trying to create a field on the Lead object (and eventually contact/account objects) to display the subject field from the last activity. I have already figured out how to display the last activity date, but I'm stuck on how to display the last activity subject. The field should pull from both Task & Event records.

 

Any suggestions?

  • September 18, 2013
  • Like
  • 0
I have a custom object LeadCompany__c to associate related leads.

Can I use dot notation to pull a list of all leads associated with my custom object, rather than use an SOQL query?

Currently, I must use the following query:

List<Lead> Lds = [SELECT ID FROM Lead WHERE LC_Lead_Company__c = :ld.LC_Lead_Company__c];

Would it be possible to get this information without an SOQL query in the following manner:

List<Lead> leads = ld.LC_Lead_Company__c.Leads;
 
  • December 30, 2014
  • Like
  • 1

Im tring to replicate some of the Content Library features in my custom app so Im usgint the REST API to achive this. I successfully managed to add  Library features features like 
View Files in Folder (Inside a library)
Download a File 
Rename File
But when I try to Upload a file it says

[{"errorCode":"INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY","message":"Cannot move a file into a folder you do not have access to."}]
Im sending a post request to https://ap1.salesforce.com/services/data/v40.0/connect/folders/07H900000008W0MEAU/items

However if I use the same API to upload to a sync folder I dont have any issues, it works.

Also if i upload a file from the browser it works, so defiantly I have the permission, I have double checked in the permission settings as well I have all permissions to upload a file. 


Doesn anyone know whats the possible reason ?


 
I'm constantly unable to complete tests because of this error in our sandboxes. If I keep running them over and over they usually complete normally eventually, but it can waste a half hour of my time to get them to complete so I have an accurate test coverage percentage on the class in question.

This has been a problem for over a year, but has been getting worse in the last few months.
Challenge - Create a form to enter new items and display the list of items entered. To make our camping list look more appealing, change the campingHeader component to use the SLDS. Similar to the unit, style the Camping List H1 inside the slds-page-header. Modify the campingList component to contain an input form and an iteration of campingListItem components for displaying the items entered.
The component requires an attribute named items with the type of an array of camping item custom objects.
The component requires an attribute named newItem of type Camping_Item__c with default quantity and price values of 0.
The component displays the Name, Quantity, Price, and Packed form fields with the appropriate input component types and values from the newItem attribute.
The JavaScript controller checks to ensure that the Name, Quantity and Price values submitted are not null.
If the form is valid, the JavaScript controller pushes the newItem onto the array of existing items, triggers the notification that the items value provider has changed, and resets the newItem value provider with a blank sObjectType of Camping_Item__c.


My answer - 
<aura:component >
<aura:attribute name="items" type="Camping_Item__c[]"/>
<aura:attribute name="newitem" type="Camping_Item__c[]"  default="{ 'sobjectType': 'Camping_Item__c',
                   'Quantity__c'=0, 'Price__c'=0}"/>
 <p>Name:
        <ui:inputText value="{!v.newitem.name}"/>
    </p>    
  <p>Packed:
        <ui:inputCheckbox value="{!v.newitem.Packed__c}"/>
     
    </p>    
  <p>Price:
        <ui:inputCurrency value="{!v.newitem.Price__c}"/>
    </p>
    <p>Quantity:
        <ui:inputNumber value="{!v.newitem.Quantity__c}"/>
    </p>
</aura:component>


Error -

Challenge Not yet complete... here's what's wrong: 
The campingList component isn't iterating the array of 'items' and creating 'campingListItem' components.

Please share the correct solution.
I'm in a dev org and building a lightning component exposed through a lightning tab. I recently received this error string, but with no helpful information.

I tweaked some field references and then I received a different Error ID: 398773595-167529 (-1631740258)

Would anywone form Salesforce be able to provide more detail around these error Ids?
  • March 23, 2016
  • Like
  • 0
Hi All,
How to create page block sections in lighting components 
Thanks 
Sai
  • March 21, 2016
  • Like
  • 0
Hello, I am trying to use "force:inputField" to create type-specific input component implementation based on the data type to Create Account Record. 

Here is what I did : 

In cmp file : 

<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<aura:attribute name="account" type="Account" default="{ sobjectType: 'Account' }"/>
 <force:inputField value="{!v.account.Name}" />

In Controller :
doInit: function(component, evt, helper) {
         var action = component.get("c.getAccount");
        action.setCallback(this, function(a) {
            console.log(a.getReturnValue());
                component.set("v.account", a.getReturnValue());
            
        });
        $A.enqueueAction(action);
    },

I can see the v.account value if I use ui:inputText, so it is not the problem of javascript or apex code. I did not got any error,  only a blank page with nothing in html markup, the javascript function is not event executed. 

Please help me ! Thanks a lot 
Can anyone actually get this trailhead to work?
https://developer.salesforce.com/trailhead/project/slds-lightning-components-workshop/slds-lc-4

​I've been trying to learn lightning / lds and maybe i'm missing something?

Component Code:
<aura:component >
  <aura:attribute name="class" type="String" description="CSS classname for the SVG element" />
  <aura:attribute name="xlinkHref" type="String" description="SLDS icon path. Ex: /assets/icons/utility-sprite/svg/symbols.svg#download" />
  <aura:attribute name="ariaHidden" type="String" default="true" description="aria-hidden true or false. defaults to true" />
</aura:component>
Render code:
({
	//Overwrite default render function for svg component
	render: function(component, helper){
		var classname = component.get("v.class");
		var xlinkhref = component.get("v.xlinkHref");
		var ariaHidden = component.get("v.ariaHidden");

		var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
		svg.setAttribute('class', classname);
		svg.setAttribute('aria-hidden', ariaHidden);
		svg.innerHTML = '<use xlink:href="'+ xlinkhref +'"></use>';
		return svg;
	}
})
App Code
<aura:application >
  <div class="slds">
    <ltng:require styles="/resource/SLDS0120/assets/styles/salesforce-lightning-design-system-ltng.css" />
    <span class="slds-icon__container slds-icon-standard-account">
      <c:svg class="slds-icon" xlinkHref="/resource/SLDS0120/assets/icons/standard-sprite/svg/symbols.svg#account" />
        <span class="slds-assistive-text">Account Icon</span>
    </span>
  </div>
</aura:application>
Error:
Error during init : Object doesn't support property or method 'replace'

​Also, enabling debug on lightning components doesn't seem to make a difference, no error is thrown in console so I'm not sure really how to even find my JS in the console sources.
 
I can't get my app to work when I include a force:outputField component in it. For example, if I have the following then it's OK and I get the correct value rendered in my app:
<ui:outputText aura:id="pcode" value="{!v.product.productCode}"/>
...but if I change it to use force:outputField like so:
<force:outputField aura:id="pcode" value="{!v.product.productCode}"/>
...then I get the following failure when the app tries to render the component where I have the outputField:

"Assertion Failed!: Abstract component without provider def cannot be instantiated : markup://force:outputField : undefined. Please try again."

Is there something I am missing? This outputField component does exist in the developer reference (https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/aura_compref_force_outputField.htm). 
Receiving this error when editing a visualforce page in sandbox through developer console or third party IDE.  This page has been working in production for some time. Both page and controller are set to version 32 in sandbox and production. 
The page can be edited directly through Develop->Pages.

Here's a very simplified version of the page which produces the error
 
<apex:page standardController="User" extensions="SalesRepGoalController2"> 

<b>Hello World!</b>
</apex:page>
and controller
 
public with sharing class SalesRepGoalController2{
private String userID = '' ; 	
public SalesRepGoalController2(ApexPages.StandardController c)
	{
		userID = c.getId(); 
	}
}

Java 1.7 was installed, but has been uninstalled.

Windows 8 Enterprise,  64bit
IE 10
JRE none

 
  • July 20, 2015
  • Like
  • 1
When doing the challenge in the "Setting up Lightning Connect" step of the Lightning Connect trailhead (https://developer.salesforce.com/trailhead/lightning_connect/lightning_connect_setup), I get a persisting issue with the "Phone Plan" external object (everything is OK with the "Phone" object).

Displayed message is : 
External Object Error
We encountered an error while querying the external data. Contact your administrator about this error. Error received: For input string: "99.99" 

This message appears as soon as I try to add the "cost" field in the default "all" tab list view and systematically on the object detail view (whatever the set of actually displayed fields) for the only ""monthly" record.

When checking the challenge on the trailhead page, no isue is raised band I got a "completed" challenge (but the issue is still there).

Any clue ?  Where can we find logs for "lightning connect" issues ?

Thanks.

P-E
I'm building a trigger handler that references multiple objects to update the OpportunityLineItem object. I want to use dot notation as much as possible to eliminate SOQL queries.

The following loop shows an example of one cross-object reference that returns null, but I do not understand why:
for(OpportunityLineItem oli :olis){
    System.debug('Revenue Type: ' + oli.PriceBookEntry.Revenue_Type__c);
}

The following cookbook recipe (http://developer.force.com/cookbook/recipe/using-relationship-queries) suggests I can access these fields with dot notation:
SELECT Id, Name, Account.Name,
       (SELECT Quantity, UnitPrice, TotalPrice,
               PricebookEntry.Name,
               PricebookEntry.Product2.Family
        FROM OpportunityLineItems)
FROM Opportunity

Why am I unable to access this field with dot notation? How would I write things differently?
Thank you all for your help!
  • September 03, 2014
  • Like
  • 0
I wrote some Apex to manage multiple leads from the same company through a custom object, LeadCompany__c. The Apex works great on the surface, but there are a few serious flaws:

1. All the code is in a Trigger, not a class with methods.
2. I am using too many SOQL queries to perform cross-object manipulations.

Bulkifying code and building classes are a little beyond me, so I have two requests:
  • Can anyone show me how to bulkify these triggers?
  • Can anyone show me how to convert these triggers into classes/methods?
Any help would be greatly appreciated.
  • December 26, 2013
  • Like
  • 0
I have built a trigger that creates a custom object when a Lead record meets certain criteria. They are then associated by a lookup relationship.
By manual testing, the trigger works, but how do I write the apex test?

Currently, my code is as follows:

------------------------------------------------------------
@isTest

private without sharing class LC_TestClass{

    static testmethod void CRED_Test(){

    //Insert LD1
    Lead LD1 = new Lead(
        LastName = 'LD1',
        Email = 'LD1@LCA.com',
        Company = 'LCA',
        Status = 'Open - Not Contacted'
    );
    insert LD1;

    //Verify LCA
    LD1 = [SELECT ID, Company, LC_Lead_Company__c, Status, LC_Status__c, OwnerID FROM Lead WHERE ID = :LD1.id];
    LCA = [SELECT ID, Name, OwnerID, Status__c, Lead_Count__c, Domain__c FROM LeadCompay__c WHERE Domain__c = :LD1.LC_Email_Domain__c];

    System.assertEquals( LD1.LC_Company__c,   LCA.Id);
    System.assertEquals( LD1.OwnerId ,     LCA.OwnerId );
    System.assertEquals( 'LCA' ,      LCA.Name );
    System.assertEquals( 'Open - Not Contacted' ,  LCA.Status__c );
    System.assertEquals( '1' ,       LCA.Lead_Count__c );
------------------------------------------------------------

Unfortunately, the developer console gives me the following error from line 18:

sObject type 'LeadCompany__c' is not supported. If you are attempting to use a custom object, be sure to append the '__c' after the entity name...

Any help?
  • December 23, 2013
  • Like
  • 0

Today we’re excited to announce the new Salesforce Developers Discussion Forums. We’ve listened to your feedback on how we can improve the forums.  With Chatter Answers, built on the Salesforce1 Platform, we were able to implement an entirely new experience, integrated with the rest of the Salesforce Developers site.  By the way, it’s also mobile-friendly.

We’ve migrated all the existing data, including user accounts. You can use the same Salesforce account you’ve always used to login right away.  You’ll also have a great new user profile page that will highlight your community activity.  Kudos have been replaced by “liking” a post instead and you’ll now be able to filter solved vs unsolved posts.

This is, of course, only the beginning  and because it’s built on the Salesforce1 Platform, we’re going to be able to bring you more features faster than ever before.  Be sure to share any feedback, ideas, or questions you have on this forum post.

Hats off to our development team who has been working tirelessly over the past few months to bring this new experience to our community. And thanks to each of you for helping to build one of the most vibrant and collaborative developer communities ever.
 

I built a trigger and class to count activities on leads and contacts. These counters are not updating when a user mass emails, however. Is there something I'm missing in this trigger?

 

 

trigger TP_TaskUpdateTouchPoints on Task (after delete, after insert, after undelete, after update) {

    Set<ID> ldIds = new Set<ID>();
    Set<ID> ctIds = new Set<ID>();

    //We only care about tasks linked to leads and contacts.
    String ldprefix = TP_CountsAndActivities.ldPrefix;
    String ctprefix = TP_CountsAndActivities.ctPrefix;
    
    //Add any lead or contact ids coming from the new data
    if (Trigger.new != null) {
        for (Task t : Trigger.new) {
            if (t.WhoId != null && String.valueOf(t.whoId).startsWith(ldprefix) ) {
                ldIds.add(t.whoId);
            }
            if (t.WhoId != null && String.valueOf(t.whoId).startsWith(ctPrefix)) {
                ctIds.add(t.whoId);
            }
        }
    }

    //Also add any lead or contact ids coming from the old data (deletes, moving an activity)
    if (Trigger.old != null) {
        for (Task t : Trigger.old) {
            if (t.WhoId != null && String.valueOf(t.whoId).startsWith(ldprefix) ) {
                ldIds.add(t.whoId);
            }
            if (t.WhoId != null && String.valueOf(t.whoId).startsWith(ctPrefix)) {
                ctIds.add(t.whoId);
            }

        }
    }
    
    // Only run trigger if there are records to update
    if (ldIds.size() > 0){
        TP_CountsAndActivities.updateLdCountsAndActivities(ldIds);
    }
    if (ctIds.size() > 0) {
        TP_CountsAndActivities.updateCtCountsAndActivities(ctIds);
    }
}

 

 

 

 

  • November 21, 2013
  • Like
  • 0

We have created a flow that creates an Opportunity and we want the "finishlocation" of the flow, where they end up when they click "Finish", to be the newly created Opportunity. I know that we will have to create a VF page and controller to pass the OpptyID (once created) back to the VF page and set as the finishlocation, but can't figure out how to do it. Any ideas?

I'm constantly unable to complete tests because of this error in our sandboxes. If I keep running them over and over they usually complete normally eventually, but it can waste a half hour of my time to get them to complete so I have an accurate test coverage percentage on the class in question.

This has been a problem for over a year, but has been getting worse in the last few months.
On this documentation link: https://developer.salesforce.com/trailhead/lightning_components/lightning_components_events_handle

it says, a component can also handle its own event. Simply include an aura:registerEvent and aura:handler in that component.

Let's say I have a list of accounts and on clicking the account name, I want to display its contact list.

<aura:iteration items="{!v.accounts}" var="acc">    
        <div onclick="{!c.showContacts}" class="row primary">{!acc.Name}</div>     
    </aura:iteration>

In the showContacts controller action, how do I set the parameter to the event which takes an account object?
// How do I set acct below?
var updateEvent = component.getEvent("showContacts");
      updateEvent.setParams({ "account": acct }).fire();

var acct = component.get("v.acc.id");
this doesn't work.

I know how to do this via a sub-component that shows the account name, register the onclick event and handle it in the main component. Just wondering how you do this in the component itself since the logic is really simple and do not want to use a subcomponent for that one line of code.

Please advise.


 
Hello, I am trying to use "force:inputField" to create type-specific input component implementation based on the data type to Create Account Record. 

Here is what I did : 

In cmp file : 

<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<aura:attribute name="account" type="Account" default="{ sobjectType: 'Account' }"/>
 <force:inputField value="{!v.account.Name}" />

In Controller :
doInit: function(component, evt, helper) {
         var action = component.get("c.getAccount");
        action.setCallback(this, function(a) {
            console.log(a.getReturnValue());
                component.set("v.account", a.getReturnValue());
            
        });
        $A.enqueueAction(action);
    },

I can see the v.account value if I use ui:inputText, so it is not the problem of javascript or apex code. I did not got any error,  only a blank page with nothing in html markup, the javascript function is not event executed. 

Please help me ! Thanks a lot 
When doing the challenge in the "Setting up Lightning Connect" step of the Lightning Connect trailhead (https://developer.salesforce.com/trailhead/lightning_connect/lightning_connect_setup), I get a persisting issue with the "Phone Plan" external object (everything is OK with the "Phone" object).

Displayed message is : 
External Object Error
We encountered an error while querying the external data. Contact your administrator about this error. Error received: For input string: "99.99" 

This message appears as soon as I try to add the "cost" field in the default "all" tab list view and systematically on the object detail view (whatever the set of actually displayed fields) for the only ""monthly" record.

When checking the challenge on the trailhead page, no isue is raised band I got a "completed" challenge (but the issue is still there).

Any clue ?  Where can we find logs for "lightning connect" issues ?

Thanks.

P-E
I'm unable to open logs in the developer console. Every time I try to open a log, I receive the following error message:

Unable to Access Page
You are missing information needed by the page you have attempted to access. If you believe this is an error, please refresh your screen. If the error persists, please report it to our Customer Support team and provide the URL of the page you were requesting as well as any other related information. 

Error message screenshot

This issue is similar to this forum post (https://developer.salesforce.com/forums?id=906F0000000AtUNIA0), but I have attempted its solution and receive the same results.

Logs aren't showing in the "Logs" tab.
Double-clicking test logs from the "tests" tab produces the above error message.
 
Goal:
For cases created from Salesforce for Outlook (i.e. non-service personnel), we want to track entitlements based on when an email was received, not when it was logged into Salesforce.

Sample Use Case:
A sales rep receives an email from a customer about an issue. They create a case from the email, but the case is logged 24 hours after it was received. Salesforce shows the email as received on the date/time the sales rep enters it into salesforce, not when they received the email. Furthermore, there is no way to extract the original date/time of when it entered their inbox.

Attempts:
  • "Create Cases" Button in Salesforce for Outlook (Sets email date/time to date created in Salesforce, not date received)
  • Global "New Case" Action in Salesforce for Outlook (Brings email body, but not header, into case description)
  • "Add Email" button on Case listed in Salesforce for Outlook (Again, timestamp is on moment created and only places email body in description, not timestamp)
Anyone have a suggestion (apart from voting for the idea)?
 
When I make a chatter content post via desktop, Process Builder can access that post's FeedItem.Id field.
However, when I make the same post via mobile, Process Builder is unable to access the FeedItem.Id field.

Create flow in Process Builder:
  • Object: FeedItem
  • Logic: FeedItem.Type = ContentPost
  • Result: Post to user's wall in Chatter containing FeedItem.Id
Test On Desktop:
  • Use “file” publisher action on case feed to upload a document and comment.
  • Process makes post on user's wall with FeedItem.Id
Test On Mobile:
  • Use “file” publisher action on case to upload a document and comment.
  • Process does not make post on user's wall because it can't access FeedItem.Id.
Does anyone know what's happening here and how I can get consistent behavior between mobile and desktop?
I am building an email with Messaging.SingleEmailMessage. The email should include TXT, HTML, and ICS versions and be received by an Outlook recipient as a calendar invite (not as an email with an attachment). The key is in setting the ICS attachment as an option in the same "content-type: multipart/alternative" section as the TXT and HTML versions. However, when I build the email with setPlainTextBody, setHtmlBody, and setFileAttachments, it sets the ICS attachment in its own "content-type" section.

How can I write my code to bring the .ICS file into the "Content-type: multipart/alternative" block with the TXT & HTML?

My current code:
public static void sendEventInviteICS(String bodyTXT, String bodyHTML, String subject, String fromAddress, String displayName, List<String> toAddress, List<String> ccAddress){
    //Create Message
    Messaging.SingleEmailMessage msg = new Messaging.SingleEmailMessage();
    msg.setReplyTo(fromAddress);
    msg.setSenderDisplayName(displayName);
    msg.setToAddresses(toAddress);
    msg.setCcAddresses(ccAddress);
    msg.setSubject(subject);
    //Create TXT Version
    msg.setPlainTextBody(bodyTXT);
    //Create HTML Version
    msg.setHTMLBody(bodyHTML);
    //Create ICS Attachment
    Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
    efa.setFileName('Meeting Invite.ics');
    efa.setContentType('text/calendar');
    Blob b = buildICSAttachment();
    efa.setBody(b);
    msg.setFileAttachments(new Messaging.EmailFileAttachment[]{efa});
    //Send the Email
    Messaging.sendEmail(new Messaging.SingleEmailMessage[]{msg});
}
MIME result from current code:
Date: Tue, 9 Dec 2014 21:16:26 +0000
From: Isaac Lewis <ilewis@afs.net>
Reply-To: <djillumine@gmail.com>
To: "ilewis@afs.net" <ilewis@afs.net>
Subject: Sandbox: This is the subject
MIME-Version: 1.0
Content-type: multipart/mixed;
	boundary="B_3500983009_1157947"

> This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

--B_3500983009_1157947
Content-type: multipart/alternative;
	boundary="B_3500983009_1123381"


--B_3500983009_1123381
Content-type: text/plain;
	charset="US-ASCII"
Content-transfer-encoding: 7bit

This is the text body


--B_3500983009_1123381
Content-type: text/html;
	charset="US-ASCII"
Content-transfer-encoding: quoted-printable

<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8">
</head>
<body>
<i>This is the html body</i>
</body>
</html>


--B_3500983009_1123381--


--B_3500983009_1157947
Content-type: text/calendar; name="Attachment Name.ics"
Content-disposition: attachment;
	filename="Attachment Name.ics"
Content-transfer-encoding: base64

QkVHSU46VkNBTEVOREFSDQpNRVRIT0Q6UkVRVUVTVA0KUFJPRElEOk1pY3Jvc29mdCBFeGNo=

--B_3500983009_1157947--
Desired MIME Result (boundaries around ICS have been moved to be part of the "Content-type: multipart/alternative" block):
Date: Tue, 9 Dec 2014 21:16:26 +0000
From: Isaac Lewis <ilewis@afs.net>
Reply-To: <djillumine@gmail.com>
To: "ilewis@afs.net" <ilewis@afs.net>
Subject: Sandbox: This is the subject
MIME-Version: 1.0
Content-type: multipart/mixed;
	boundary="B_3500983009_1157947"

> This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

--B_3500983009_1157947
Content-type: multipart/alternative;
	boundary="B_3500983009_1123381"


--B_3500983009_1123381
Content-type: text/plain;
	charset="US-ASCII"
Content-transfer-encoding: 7bit

This is the text body


--B_3500983009_1123381
Content-type: text/html;
	charset="US-ASCII"
Content-transfer-encoding: quoted-printable

<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8">
</head>
<body>
<i>This is the html body</i>
</body>
</html>

--B_3500983009_1123381
Content-type: text/calendar; name="Attachment Name.ics"
Content-disposition: attachment;
	filename="Attachment Name.ics"
Content-transfer-encoding: base64

QkVHSU46VkNBTEVOREFSDQpNRVRIT0Q6UkVRVUVTVA0KUFJPRElEOk1pY3Jvc29mdCBFeGNo=

--B_3500983009_1123381--

--B_3500983009_1157947--




 
Hello everyone,

I need quick help from you guys regarding Service Console application.

I have created a console app as well as a custom app. Both of these apps are assigned to one of my custom profile, called Customer Support profile where I have set console app as a default app.

What I am facing is that when any of the user logs into the system, then they see Service Console app as deault app, Home page layout as default layout, but "Back to Service Console" tab as the only single tab.

When I click on this tab, it redirects me to the actual Home tab of Console app.

I want actual Home tab as a default tab, as it should be.

If I select another application (another custom application assigned to this profile), and come back to this Console app, then it is showing me actual home tab. I am expecting the same behavior for all users when they logged into the system.

Both of the snapshots are attached. (Issue / requirement)

Please help!!


User-added image

User-added image

I'm trying to prevent multiple SOQL queries in my method by creating a static list outside of the method.
The list is pulling from custom settings, so they should be static when the class runs.
Unfortunately, when I run the test for this class, the debug log shows nothing.
Am I putting this list in the wrong place?

Class
public class modeRanges{

    public static List<ModeRange__c> ModeRanges = [SELECT Mode_Type__c, Spend_Picklist_Value__c, Volume_Picklist_Value__c FROM ModeRange__c];

    public static void setSpendRangeFromVolumeRange(List<Mode__c> Modes){
	System.debug('ModeRanges: ' + ModeRanges);
        for(Mode__c m :Modes){
            for(ModeRange__c r: ModeRanges){
                if(m.Type__c == r.Mode_Type__c && m.Est_Volume__c == r.Volume_Picklist_Value__c){
                    m.Est_Spend__c = r.Spend_Picklist_Value__c;
                }
            }
        }
    }    
}

Debug Log
15:45:01:042 USER_DEBUG [12]|DEBUG|ModeRanges: ()


I am building a trigger to automatically associate a custom Account child object with a custom Opportunity child object. My trigger works fine and tests perfectly, except when I went to upload a bunch of records to the new object, I received the following error on every item:

System.LimitException: Apex CPU time limit exceeded

I found a helpful article here:
http://salesforce.stackexchange.com/questions/22223/how-to-code-more-efficient-to-avoid-apex-cpu-time-limit-exceeded

But I'm still not sure what I'm doing wrong. Does anyone have any ideas?

Here is the trigger code:

<pre>
trigger associateOppChildtoAccChild on OppChild__c (before insert, before update) {

    Set<Id> OppSet = new Set<Id>();
    for(OppChild__c OppChild :Trigger.new){
        OppSet.add(OppChild.Opportunity__c);
    }
   
    Map<ID,ID> OPP_ACC = new Map<ID,ID>();
    Set<Id> AccSet = new Set<Id>();
    for(Opportunity OPP:[SELECT Id, AccountId from Opportunity where Id in :OppSet]){
        OPP_ACC.put(OPP.Id, OPP.AccountId);
        AccSet.add(OPP.AccountId);       
    }

    Map<ID,ID> ACC_OppChild = new Map<ID,ID>();
    for(OppChild__c OppChild :Trigger.new){
        for(ID OPP :OPP_ACC.keyset()){
            if(OPP == OppChild.Opportunity__c){
                ACC_OppChild.put(OPP_ACC.get(OPP), OppChild.Id);
            }
        }
    }
   
    List<AccChild__c> AccChildList = [SELECT Id, Account__c, Type__c, Annual_Spend__c, Number_of_Shipment_Transactions__c FROM AccChild__c WHERE Account__c in :AccSet];
   
    for(OppChild__c OppChild :Trigger.new){
        for(AccChild__c m: AccChildList){
            if(m.Type__c == OppChild.AccChild_Type__c){
                for(ID ACC :ACC_OppChild.keyset()){
                    if(ACC == m.Account__c){
                        OppChild.AccChild__c = m.Id;
                        System.debug('OppChild AccChild = ' + OppChild.AccChild__c);
                        OppChild.Annual_Spend__c = m.Annual_Spend__c;
                        OppChild.Number_of_Shipment_Transactions__c = m.Number_of_Shipment_Transactions__c;
                    } else {
                        OppChild.adderror(OppChild.AccChild_Type__c + ' AccChild must exist on Account to add OppChild');
                    }
                }
            }
        }
    }  
}
</pre>

I run the tests and my set and map both come back null. Can anyone spot what I'm missing here?

<pre>
trigger associatePMRtoMode on PMR__c (before insert, before update) {

    Set<ID> AccountIds = new Set<ID>();
    Map<ID,ID> ACC_PMR = new Map<ID,ID>();
   
    for (PMR__c PMR :Trigger.new){
        AccountIds.add(PMR.Opportunity__r.AccountId);
        ACC_PMR.put(PMR.Opportunity__r.AccountId, PMR.Id);
    }

    System.debug('AccountIds = ' + AccountIds);
    System.debug('ACC_PMR = ' + ACC_PMR);
}
</pre>

I am adding a trigger to default a Contact owner to the Account owner. It works fine and passes the test I wrote for it. HOWEVER, it fails a test from another piece of apex, telling me:

System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, reassignCtOwnerToAcOwner: data changed by trigger for field Owner ID: owner cannot be blank: []

Here is the trigger I'm trying to deploy:

trigger reassignCtOwnerToAcOwner on Contact (before insert, before update) {

    List<Id> accountIds = new List<Id>();
    Map<Id, Id> accountOwnerIdMap = new Map<Id, Id>();

    // all the accounts whose owner ids to look up
    for ( Contact c : Trigger.new ) {
        accountIds.add( c.accountId );
    }
   
    // look up each account owner id
    for ( Account acct : [ SELECT id, ownerId FROM account WHERE id IN :accountIds ] ) {
        accountOwnerIdMap.put( acct.id, acct.ownerId );
    }
   
    // change contact owner to its account owner
    for ( Contact c : Trigger.new ) {
        c.ownerId = accountOwnerIdMap.get( c.accountId );
    }
}

Here is the test class for the OTHER trigger that fails when I try to insert a contact:

public static testMethod void validateContactCountsAndActivities() {

        //Create Account
  Account ac = new Account(
   Name='Test Account',
   Initial_Lead_Source__c='Cold Call',
   Initial_Lead_Source_Detail__c='Cold Call',
   Account_Type__c='Prospect',
   Account_Status__c='Not Contacted'   );
  insert ac;

        //Create Contact
        Contact ct = new Contact(
                LastName='Test Contact',
                Email='testcontact@email.com',
                Account= ac);
        insert ct;




I am working on an apex trigger/class to display the next activity subject & date on the account object. The code works fine, and a manual test will work, but when I run my apex tests, it says something isn't working. Have I written my test code wrong?

Here is the method:

public static void updateAcCountsAndActivities(Set<ID> accountIds){

     //Query all records and related activities
     List<Account> Accounts = [SELECT
   Id,
   TP_NextActivityDate__c,
   TP_NextActivitySubject__c,
         (SELECT Id, Subject, ActivityDate FROM OpenActivities WHERE ActivityDate >= TODAY AND ActivityDate <> NULL order by ActivityDate Desc LIMIT 1)
         FROM Account WHERE ID IN :AccountIds];

     List<Account> updateAccounts = new List<Account>();

     for (Account a : Accounts) {

   //Prepare comparison variables
   String NextActivitySubject = a.TP_NextActivitySubject__c;
   Date NextActivityDate = a.TP_NextActivityDate__c;

   //Compare variables with record
         if (a.OpenActivities.size() > 0) {
             for (OpenActivity act : a.OpenActivities) {
      NextActivityDate = act.ActivityDate;
      NextActivitySubject = act.Subject;
    }
   } else {
    NextActivityDate = null;
    NextActivitySubject = null;
   }

   //Update fields to match variables
         if ( a.TP_NextActivityDate__c != NextActivityDate || a.TP_NextActivitySubject__c != NextActivitySubject){
                 a.TP_NextActivityDate__c = NextActivityDate;
                 a.TP_NextActivitySubject__c = NextActivitySubject;
                 updateAccounts.add(a);
    }
     }

     //Commit the changes
     if(updateAccounts.size()>0) {
         try{
             update updateAccounts;
         }
             catch (Exception e) {
         }
     }
}

Here is a failing test:

public static testMethod void validateAccountCountsAndActivities() {

        //Create Account
  Account ac = new Account(
   Name='Test Account',
   Initial_Lead_Source__c='Cold Call',
   Initial_Lead_Source_Detail__c='Cold Call',
   Account_Type__c='Prospect',
   Account_Status__c='Not Contacted'
   );
  insert ac;

        //Create Contact
        Contact ct = new Contact(
                LastName='Test Contact',
                Email='testcontact@email.com',
                Account= ac
    );
        insert ct;

  // Verify
  ac = [SELECT ID, TP_NextActivityDate__c FROM Account Where ID = :ac.id];
        System.assertEquals(null,ac.TP_NextActivityDate__c);

  //Insert E1
        Event e1 = new Event(
            subject='Event One',
            whoId = ct.id,
            whatId = ac.id,
            startDateTime = Datetime.now().adddays(2),
            endDateTime = Datetime.now().adddays(2)
   );
        insert e1;

  // Verify
  ac = [SELECT ID, TP_NextActivityDate__c FROM Account Where ID = :ac.id];
        System.assertEquals(date.newinstance(e1.EndDateTime.year(),e1.EndDateTime.month(),e1.EndDateTime.day()),ac.TP_NextActivityDate__c);

    }

Error Message:
System.AssertException: Assertion Failed: Expected: 2014-01-24 00:00:00, Actual: null
I have created two triggers, one on the Lead object, the other on a related custom object called 'LeadCompany__c.' When a lead is edited, it should update the related LeadCompany__c object, and when the LeadCompany__c object is updated, it should update all related leads.

My problem is that I am consistently running into the infamous "Attempt to de-reference a null object" error. For example, when I update the Lead "Company" field, it should update the LeadCompany__c.Name field, but it gives the following error: "Attempt to de-reference a null object Trigger.LD_Update_LC: line 82, column 1: []: Trigger.LC_Update_LD: line 93, column 1"

Here is the code for your review. Does anyone see how I can fix this?

//--------------------------------------------------------------------------------------------------------//
// LeadCompany__c Trigger
//--------------------------------------------------------------------------------------------------------//

trigger LC_Update_LD on LeadCompany__c (before insert, before update, after update){

List<Lead> ldList = [SELECT Id, OwnerID, Company, LC_Lead_Company__c, Status, IsConverted FROM Lead WHERE LC_Lead_Company__C in :Trigger.new];
List<Lead> ldUpdate = new List<Lead>();
    List<Database.LeadConvert> leadConversions = new List<database.LeadConvert>();
LeadStatus convertStatus = [SELECT Id, MasterLabel, IsConverted FROM LeadStatus WHERE IsConverted=true limit 1];

Map<String, Integer> status_value = new Map<String, Integer>{
     'Open - Not Contacted' => 2,
     'Working - Contacted' => 3,
     'Working - Initial Meeting Scheduled' => 4,
     'Closed - Qualified' => 5,
     'Closed - Unqualified' =>1,
     null => 0
};

Map<Integer, String> status_name = new Map<Integer, String>{
     2 => 'Open - Not Contacted',
     3 => 'Working - Contacted',
     4 => 'Working - Initial Meeting Scheduled',
     5 => 'Closed - Qualified',
     1 => 'Closed - Unqualified',
     0 => null
};

//Updates Lead Count & Status
if(Trigger.isBefore){
  for (LeadCompany__c lc: Trigger.new){
   lc.Lead_Count__c = 0;
   Integer LC_Stat_Val = status_value.get(lc.Status__c);
   Integer LD_Stat_Vals = 0;
  
   for(Lead ld: ldList){
    if(ld.lc_Lead_Company__c == lc.Id){
     //Add to Lead Count
     Trigger.newMap.get(ld.LC_Lead_Company__c).Lead_Count__c++;
     //Compare Lead Status
     Integer LD_Stat_Value = status_value.get(ld.Status);
     if(LD_Stat_Value > LD_Stat_Vals){
      LD_Stat_Vals = LD_Stat_Value;
     }
    }
   }

   //Set Company Status
   if(LC_Stat_Val != LD_Stat_Vals){
    lc.Status__c = status_name.get(LD_Stat_Vals);
   }
  }
}

if(Trigger.isAfter){
  for (LeadCompany__c lc: Trigger.new) {
         LeadCompany__c oldLC = Trigger.oldMap.get(LC.ID);

            if(LC.Lead_Count__c != null){
    if(lc.ConvertedAccountId__c != null){
                   
                    for(Lead ld: LdList){
      if(ld.isConverted == False){
       Database.LeadConvert ldc = new Database.LeadConvert();
       ldc.setLeadId(ld.id);
       ldc.setAccountId(lc.ConvertedAccountId__c);
       ldc.setDoNotCreateOpportunity(TRUE);
                ldc.setConvertedStatus(convertStatus.MasterLabel);                   
       leadconversions.add(ldc);
      }
     }
    }

          if(LC.OwnerID != oldLC.OwnerID || LC.Name != oldLC.Name) {
              for(Lead ld: LdList){
            // Update Lead Owners
      if(ld.OwnerId != lc.OwnerId){
       ld.OwnerID = LC.OwnerID;
      }
            // Update Lead Company Names
      if(ld.Company != lc.Name){
                      ld.Company = LC.Name;
      }
      ldUpdate.add(ld);      
              }
          }
   }
  }
}

if(leadConversions.size()>0){
        List<Database.LeadConvertResult> results = Database.convertLead(leadConversions);
}
if(ldUpdate.size()>0){
  Update ldUpdate;
}
}

//--------------------------------------------------------------------------------------------------------//
// Lead Trigger
//--------------------------------------------------------------------------------------------------------//

trigger LD_Update_LC on Lead (before insert, before update, after delete, after insert, after update){

//Initialization
Map<Id, LeadCompany__c> updateCompanies = new Map<Id, LeadCompany__c>{};
List<Lead> associateLeads = new List<Lead>{};
List<Lead> convertLeads = new List<Lead>{};

List<Blacklist_Domain__c> Blacklist = [SELECT Name FROM Blacklist_Domain__c];
set<string> Blackset = new set<string>();
for (Blacklist_Domain__c bl: Blacklist){
  Blackset.add(bl.name);
}

Map<String, Integer> status_value = new Map<String, Integer>{
     'Open - Not Contacted' => 2,
     'Working - Contacted' => 3,
     'Working - Initial Meeting Scheduled' => 4,
     'Closed - Qualified' => 5,
     'Closed - Unqualified' =>1,
     null => 0
};

Map<Integer, String> status_name = new Map<Integer, String>{
     2 => 'Open - Not Contacted',
     3 => 'Working - Contacted',
     4 => 'Working - Initial Meeting Scheduled',
     5 => 'Closed - Qualified',
     1 => 'Closed - Unqualified',
     0 => null
};

//Start Trigger
if(Trigger.isBefore){

  //Isolate leads to associate
  if(Trigger.isInsert){
   for (Lead ld: Trigger.new){
    associateLeads.add(ld);
   }
  }
  if(Trigger.isUpdate){
   for (Lead ld: Trigger.new){
    Lead oldLd = Trigger.oldMap.get(ld.Id);
    if(oldLd.LC_Email_Domain__c != Ld.LC_Email_Domain__c){
     associateLeads.add(ld);
     if(oldLd.LC_Lead_Company__c != null){
      updateCompanies.put(oldLd.LC_Lead_Company__c, new LeadCompany__c(Id=oldLd.LC_Lead_Company__c));
     }
    }
   }
  }
}

if(Trigger.isAfter){

  //Update Company after Lead delete
  if(Trigger.isDelete){
   for (Lead ld: Trigger.old){
    if(ld.LC_Lead_Company__c != null){
     updateCompanies.put(ld.LC_Lead_Company__c, new LeadCompany__c(Id=ld.LC_Lead_Company__c));
    }
   }
  }

  if(Trigger.isUpdate){
   for (Lead ld: Trigger.new){
    //Convert all Company leads
    if(Ld.IsConverted == True && ld.LC_Lead_Company__c != null){
     ld.LC_Lead_Company__r.ConvertedAccountId__c = ld.ConvertedAccountId;
     updateCompanies.put(ld.LC_Lead_Company__c, new LeadCompany__c(Id=ld.LC_Lead_Company__c));
    }
    //Check for Lead value changes
    else {
     Lead oldLd = Trigger.oldMap.get(Ld.ID);
     //Set LC OwnerId
     if(Ld.OwnerID != oldLd.OwnerID){
      ld.LC_Lead_Company__r.OwnerId = Ld.OwnerId;
      updateCompanies.put(ld.LC_Lead_Company__c, new LeadCompany__c(Id=ld.LC_Lead_Company__c));
     }
     //Set LC Name
     if(Ld.Company != oldLd.Company){
      ld.LC_Lead_Company__r.Name = Ld.Company;
      updateCompanies.put(ld.LC_Lead_Company__c, new LeadCompany__c(Id=ld.LC_Lead_Company__c));
     }
     //Set LC Status
     if(Ld.Status != oldLd.Status){
      if(Ld.Status != Ld.LC_Status__c){
       Integer LC_Stat_Value = status_value.get(ld.LC_Lead_Company__r.Status__c);
       Integer LD_Stat_Value = status_value.get(ld.Status);

          if(LD_Stat_Value > LC_Stat_Value){
        ld.LC_Lead_Company__r.Status__c = status_name.get(LD_Stat_Value);
        updateCompanies.put(ld.LC_Lead_Company__c, new LeadCompany__c(Id=ld.LC_Lead_Company__c));
          }
      }
     }
    }
   }
  }
}

//Perform Updates

//Associate Leads to Companies
if(associateLeads.size()>0){
  for (Lead ld: associateLeads){
   //Validate Email
   if (ld.LC_Email_Domain__c != null && Blackset.contains(ld.LC_Email_Domain__c) == FALSE){
    //Search for existing company
    List<LeadCompany__c> lcMatch = [SELECT Id, OwnerId FROM LeadCompany__c WHERE Domain__c = :ld.LC_Email_Domain__c];
    // If existing, associate lead
    if (lcMatch.size() >0) {
     for( LeadCompany__c lc :lcMatch){
      // Associate Lead to Company
      ld.LC_Lead_Company__c = lc.Id;
      // Change Lead Owner to Company Owner
      ld.OwnerID = lc.ownerid;
      updateCompanies.put(lc.Id, new LeadCompany__C(Id=lc.Id));
     }
    }
    // If no existing, create new
    else {
     // Create new company
        LeadCompany__c nlc = new LeadCompany__c (
            Domain__c = ld.LC_Email_Domain__c,
            Name = ld.Company,
            OwnerId = ld.OwnerId,
            Status__c = ld.Status
        );
        insert nlc;

     // Associate new lead to new company
        ld.LC_Lead_Company__c = nlc.id;
     updateCompanies.put(nlc.Id, new LeadCompany__c(Id=nlc.Id));
    }
   }
   //Remove association
   else {
    ld.LC_Lead_Company__c = null;
   }
  }
}

//Trigger New & Old Company Updates (Owner, Name, Count Status etc)
if(updateCompanies.size()>0){
  Update updateCompanies.values();
}
}

Working on a trigger to update the lead object. The field displays a count of activities completed within 30 days from the Lead record's CreatedDate.

 

I can't find a clean way to limit my SOQL subquery based on the parent object's CreatedDate field.

 

Any ideas?

 

    public static String ldPrefix =  Lead.sObjectType.getDescribe().getKeyPrefix();
    public static void updateLeadCounts30days(Set<ID> leadIds) {

        List<Lead> Leads = [SELECT ID, CreatedDate, TP_First_30_Days__c, (SELECT ID, ActivityDate FROM Tasks), (SELECT ID, ActivityDate FROM Events) FROM Lead WHERE ID IN :leadIds];
        List<Lead> updateLeads = new List<Lead>();

        for (Lead l : Leads) {

		Date InitDate = l.CreatedDate;
		Date InitDate30 = l.CreatedDate + 30;

		Integer ThirtyTaskCount = [SELECT COUNT() FROM Tasks WHERE ActivityDate <= :InitDate30];            	
		Integer ThirtyEventCount = [SELECT COUNT() FROM Events WHERE ActivityDate <= :InitDate30];
		Integer FirstThirtyDays = ThirtyTaskCount + ThirtyEventCount;

		if (l.TP_First_30_Days__c != FirstThirtyDays) {
			l.TP_First_30_Days__c = FirstThirtyDays;
		}	
		updateLeads.add(l);
	}

 

Hello,

 

I'm a new user with a devil of a problem - I need to create a bit of code that wil allow me to send meeting requests to non-Salesforce users that will put my Salesforce meetings in their diaries, Outlook or other.

 

I put full details of my request on the General board, thinking it could be done from within the custom HTML email templates.  I now realise it's more of an Apex issue.  

 

Would you be so kind as to take a look?  The thread is http://boards.developerforce.com/t5/General-Development/sending-an-ICS-Outlook-compatible-calendar-request-with-workflow/td-p/658603.

 

Best regards,

 

Alex.

Of course for Primary Campaign, we have the field "Opportunity.Campaign", which is a lookup(Campaign) field on Opportunity. But there is also a related list for the Opportunity record detail page called "Campaign Influence", which can be populated in a couple of ways, including manual button-click to "Add" an Opportunity Campaign Influence record. This appears to be like a many-to-many relationship, implying that any opportunity can be linked to any campaign, non-exclusively so. That seems to imply a junction object.

 

I suspected something like OpportunityCampaign or something, but no such object exists.

 

Where are these relationships stored? How can they be created/modified via API or Apex (or even workflow)?

 

 

  • September 07, 2011
  • Like
  • 1

I can't deploy my trigger because there is an error in an Apex class and its corresponding test class. Actually it may just be in the test class.  In fact, I can't deploy anything but I want to change the test class so that it won't get an error!

 

I have been using the Eclpse IDE to deploy.  This really isn't a matter of deploying from the "sandbox" to the Production environment since this already exits in Production.  I am not sure where to begin.

I was wondering if anyone has had experience with this one. Is there a way to set the MIME type of an email sent via APEX? Additionally, I'll want to generate and attach an ICS file with meeting invite details. The ICS file is pretty much a txt file so that shouldn't be that tricky. Has anyone tried this before?
  • June 05, 2009
  • Like
  • 1