• BrianWK
  • NEWBIE
  • 380 Points
  • Member since 2008

  • Chatter
    Feed
  • 15
    Best Answers
  • 2
    Likes Received
  • 0
    Likes Given
  • 92
    Questions
  • 183
    Replies

I am just starting to learn about Describe methods because I think it is what I need in order to do what I need to do. I am posting here to see if there are any more skilled developers that can tell me if I'm on the right path. So, here's the deal...

 

Our Contacts are synced with an ERP via Informatica. The ERP is capable of merging Contact records, but Informatica does not seem to be capable of passing those changes down to SFDC. So, I need to make those changes with a trigger.

I have it worked out so when a Merge takes place in the ERP, Informatica will pass the SFID of the master Contact record to the Child contact record. Which I can use to trigger a yet to be written merge class in apex.

 

My first hope was that I could simply use the merge dml statement, but learned that the statement can only do 3 records at atime. In other words, you can't 'bulkify' a merge dml.

 

So, now I am faced with recreating the merge statement. It seems I could do this by simply querying for all of the existing child objects of a Contact record. The problem there is that I will have to remember to add code whenever I add a new object as a child to the Contact object.

 

So, it seemed like a good opportunity to learn about the Describe methods.

 

My question is...Is this possible? Would it be possible to get a list of Contacts from a trigger, and use the Describe methods to dynamically query for all of the child objects of each Contact, and then actually make updates to the records in those child objects?

 

Thanks,

Andy

 

Hi all - I've got a custom object for which there are two basic kinds of records, parents and children. There is a same-object Lookup field on that object that looks up to the object called Object_Self_Lookup__c. I want to use this to relate the children to the parents. 

 

The object also has an external Id called External_Id_Field__c.

 

I'm generating large batches of these records in a scheduled Apex class, and maintaining two different lists, one of parents, one of children. Each record, no matter the type, is assigned a unique value to External_Id_Field__c.

 

My goal is that I can insert the list of Parent records first, having set all their external ids, and then insert the list of children, and have the lookup to the parent record resolved by way of the external Id. I've like to avoid adding a trigger, or making a second pass to get the reference set if it's possible.

 

Is this possible? If so, what am I doing wrong here? This is simplified version of my full code, but this doesn't work either.

 

Thanks!

 

List<Custom_Object__c> parentList = new List<Custom_Object__c>();
List<Custom_Object__c> childList = new List<Custom_Object__c>();

Custom_Object__c objOne = new Custom_Object__c();
objOne.External_Id_Field__c = '1234';
parentList.add(objOne);

Custom_Object__c objTwo = new Custom_Object__c();
objTwo.Object_Self_Lookup__r = objOne;
childList.add(objTwo);

insert parentList;
insert childList;

 

Hey all,

 

So I have come to a bit of an impass in a trigger I am writting. It may be because it's early and I can't think yet, but I am just not quite sure how to logically solve this problem.

 

Here is the deal, this trigger is responsible for updating a contact associated with a task. When the task is saved, the status field is checked. If the task is completed, an associated date field on the related contact is set to the completion date on the task (if the date to be used for the update is later than the one currently existing). This is to keep track of things such as 'Last stay in touch call', 'Last meeting', etc. The tasks represent interactions with a contact, and when the task is completed they want to mark the contact so they know the last time that kind of action was performed. I have this working perfectly currently.

 

Where it gets complicated is if a task is deleted. They have decided that they want the information to 'roll back' if a task is deleted. They want the field on the contact to be 'recalculated' to find the task that is now the newest that applies to the field that just got deleted. So if the most recent task that set the 'last stay in touch call' gets deleted, they want the system to find the next most recent and use that. This is where I am a bit stuck. The only approach I can think of (while keeping it bulk friendly) is something like:

 

1) Query for all tasks associated with any contact that appeared in this list of newly deleted tasks.
 

2) Iterate over every task. Look to see if the 'Activity_Type__c' matches that of the task that just got deleted for this contact.
 

3) If it is a match on the field, check to see if it most recent than any other entry (could probably eliminate this by sorting the query by the date, and skipping duplicates in my loop). 

 

4) Using the list of tasks, continue with the trigger logic as normal.

 

The issue I have here is, what if one contact is getting multiple tasks deleted at one time? Because when I am iterating through the list of tasks for every contact, I'd have to iterate over every task for them in the trigger context, then find a matching task in the query I just ran, and... argh it gets so complicated and cumbersom. Also, this approach seems excruciatingly inefficient. Does anyone have any better ideas? Below is my code thus far so you can see where I am at. Thanks so much!

 

/**********************************************
Name: ContactActivityRecordTrigger
Author: Daniel Llewellyn
Date 3/14/2012
Description: Will update a contact related to a task when a task is completed. The contact has various date fields that may
                          be populated based on the type of task. Updates performed by the elquoa marketing tool or anyone from 
                          marketing do not fire these updates
***********************************************/                          

trigger ContactActivityRecordTrigger on Task(after insert, after undelete, after update) 
{
    
    try
    {    
        list<Task> tasks;
        if(Trigger.Isundelete)
        {
            tasks = trigger.old;
        }
        else
        {
            tasks = trigger.new;
        }
        //create map of contacts that will contain contacts to update
        map<Id,Contact> contactMap = new map<id,Contact>();
        
        //create a map of users that contain the names of the users related to the tasks.
        map<Id,User> userMap = new map<id,User>();
        
        //we will need to find the DS_Role__c field for all the contacts. So create a map of the contact id, to the contact record
        //so we can run one query, and populate them map, then get the contact details when we need them later without needing
        //to have a query in our loop.
        for (Task thisTask: tasks) 
        {
            //we are only interested in this task if it has a contact, so no contact, just skip adding an entry for this task.
            if(thisTask.WhoId != null)
            {
                contactMap.put(thisTask.WhoId,null);
            }
            if(thisTask.OwnerId != null)
            {
                 userMap.put(thisTask.OwnerId,null);
            }
        }
        
        //populate the map with the id of the contact, then the details about that contact.
        for(Contact con : [select id, DS_Role__c,Last_Meeting_Sales_Call__c,Last_Call__c,Last_Email__c,Last_Demo__c,Last_Mass_Email__c,Last_Sent_Info__c,Last_Marketing_Activity__c from contact where id in :contactMap.keySet()])
        {
            contactMap.put(con.id,con);
        }
    
        //populate the map with the id of the contact, then the details about that contact.
        for(User usr : [select id, Name from User where id in :userMap.keySet()])
        {
            userMap.put(usr.id,usr);
        }
       
       //if this is a delete trigger, the current list of tasks has actually been deleted, so we need to find
       //the task that is now the most recent for each user of the same type that just got deleted
       if(trigger.isDelete)
       {
           //find all the tasks for all the users
           list<task> allTasks = [select id, WhoId, OwnerId,Status,Activity_Type__c, ActivityDate from task where whoId in :contactMap.keySet() order by ActivityDate desc ];
           
           //so now I have to loop over all the tasks I just fetched, and then find all the tasks for the associated contact and see if there is a match and.... arg I have no idea.
           for(Task task : allTasks)
           {
           
           }
       }
       
        //iterate over every task passed in
        for (Task thisTask: tasks)     
        {
            //if this task does not have a contact related to it, then just skip this task and continue.
            if(thisTask.WhoId == null)
            {
                continue;
            }    
            
             //create a reference to the contact associated with this task that we will update
            Contact thisContact =contactMap.get(thisTask.WhoId);
    
            //create a reference to the owner associate with this task
            User thisUser = userMap.get(thisTask.OwnerId);
           
            date activityDate;
            if( thisTask.ActivityDate != null)
            {            
                activityDate = thisTask.ActivityDate;
            }
            else
            {
                activityDate = Date.newInstance(thisTask.LastModifiedDate.year(),thisTask.LastModifiedDate.month(),thisTask.LastModifiedDate.day()); 
            }
            //check if the task status is completed
            if (thisTask.Status.toLowerCase() == 'completed') 
            {                
                //make sure the owner of the task is not eloqua marketing, and make sure the contact's role is not marketing/communications
                if (thisUser.Name.toLowerCase() != 'eloqua marketing' && thisContact.DS_Role__c != 'marketing/communications') 
                {
                    if (thisTask.Activity_Type__c == 'Meeting/Sales Call' && (activityDate > thisContact.Last_Meeting_Sales_Call__c || thisContact.Last_Meeting_Sales_Call__c == null) ) 
                    {
                        thisContact.Last_Meeting_Sales_Call__c = activityDate;
                    }
                    else if (thisTask.Activity_Type__c == 'Call' && (activityDate > thisContact.Last_Call__c ||  thisContact.Last_Call__c == null))
                    {
                        thisContact.Last_Call__c = activityDate;
                    }
                    else if (thisTask.Activity_Type__c == 'Email' && (activityDate > thisContact.Last_Email__c || thisContact.Last_Email__c == null))
                    {
                        thisContact.Last_Email__c = activityDate;
                    }
                    else if (thisTask.Activity_Type__c == 'Demo' && (activityDate > thisContact.Last_Demo__c || thisContact.Last_Demo__c == null)) 
                    {
                        thisContact.Last_Demo__c = activityDate;
                    }
                    else if (thisTask.Activity_Type__c == 'Mass Email' && ( activityDate > thisContact.Last_Mass_Email__c || thisContact.Last_Mass_Email__c == null)) 
                    {
                        thisContact.Last_Mass_Email__c = activityDate;
                    }
                    else if (thisTask.Activity_Type__c == 'Sent Info' && ( activityDate > thisContact.Last_Sent_Info__c || thisContact.Last_Sent_Info__c == null ))
                    {
                        thisContact.Last_Sent_Info__c = activityDate;
                    }
                    else 
                    {
                        if (thisTask.ActivityDate > thisContact.Last_Marketing_Activity__c || thisContact.Last_Marketing_Activity__c == null) 
                        {
                            thisContact.Last_Marketing_Activity__c = activityDate;
                        }          
                    }
                }
            }
            contactMap.put(thisContact.id,thisContact);
        }
   
        //we don't need an all or nothing update, so use database.update with the all or nothing flag set to false
        if(!contactMap.values().isEmpty())
        {
            database.update(contactMap.values(),false);
        }
    }    
    catch(exception e)
    {
        system.debug('Error occured updating related contact' + e);
        
        //Send an email to the admin after an error occures
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {'Kenji776@gmail.com'};
        mail.setToAddresses(toAddresses);
        mail.setSubject('Error in ContactActivityRecordTrigger');
        mail.setPlainTextBody('An error occured while running the trigger.' + e.getMessage() + ' On Line Number ' + e.getLineNumber());
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });        
    }    
    
}

 

Hi all,

 

I'm trying to get my Siteforce page to connect to a custom object in Salesforce. I've added a repeater and a repeater element, and I'd like to get the repeater element to display data from a custom field on my custom object. However, the only fields which show up for connecting are the standard and system fields on the object.

 

The same is true for the repeater itself, when setting up a Filter, and also for Custom Code elements - only standard fields, not custom. Surely there's a way of doing this that I'm missing?

 

Thanks,

Hetty

Hopefully that subject makes sense.

 

I'm having a puzzling issue. This issue cannot be reproduced on purpose and my debug logs haven't shown anything to hint what's going on. Here's the scenario:

 

I have a visualforce page that is intended to build up a series of Sobjects and then insert those Sobjects with a single DML. The user enters each item in called "NewProduct" which is then added to the list<sobjects>. The new Product is then "reset" for the user to enter a new one -- based on the previous values.


The goal is to give the user the capability to enter a new record, have the system perform a series of client side (javascript) calculations, add the records to a "product cart" and then save the whole cart to the server.

 

This works... most of the time. Every now and then the list of sobjects - or my "product cart" - has one of the items in the list over-written by the incoming "NewProduct." It doesn't happen all the time. I can't reproduce it, and I'm not sure what I'm doing wrong in my code that could cause this problem.

 

So with no further ado - here's the method in the controller that is "adding" the product to the cart:

    public void AddProduct()
    {       
        //values of current New Product
        system.debug('Starting Values of NewProduct!');
        
        system.debug('UQ: ' + NewProduct.Unit_Quantity__c);		
        system.debug('UP: ' + NewProduct.Unit_Price__c );
        system.debug('TAP: ' + NewProduct.Total_Amount_Paid__c );
        system.debug('SD: ' + NewProduct.Start_Date__c);         
        system.debug('ED: ' + NewProduct.End_Date__c );
        system.debug('ARRT: ' + NewProduct.Annualized_Rec_Rev_Term__c);
        system.debug('MRP: ' + NewProduct.Monthly_Recurring_Price__c );
        system.debug('ARP: ' + NewProduct.Annual_Recurring_Price__c );        
        system.debug('OTP: ' + NewProduct.One_Time_Price__c);
        
        ID UIProd = NewProduct.Contract_Product__c;
        date StartDate = NewProduct.Start_Date__c;
        date EndDate =   NewProduct.End_Date__c;
		integer UQ = integer.valueof(NewProduct.Unit_Quantity__c);		
        decimal UP = NewProduct.Unit_Price__c ;
        decimal TAP = NewProduct.Total_Amount_Paid__c;
        decimal CA = NewProduct.Capped_Amount__c;
         
        UpdatedField = 'All';

        system.debug('Size after variable: ' + prods.size());
        system.debug('NewProduct to Add: ' + NewProduct);
 
        if(Schedule =='Month')
        {
            //NewProduct.Annual_Price__c = (getPriceBookOpp().Amount / NewProduct.Quantity__c);
        }
        prods.add(NewProduct);      
		/* Add NewProduct into ProductCart */
		ProductCart.add(new cProd(NewProduct));
        for(cProd cp :ProductCart)
        {
            if(cp.vname == 'changeme')
            {
                cp.vname = string.valueof(counter)+ string.valueof(NewProduct.Contract_Product__c);
            }
        }
        counter = counter+1;
        ID AccountID = NewProduct.Account__c;
        ID ProductID = NewProduct.Contract_Product__c;

        boolean NewClient = NewProduct.New_Client__c;
		/* Next 3 lines Clone Product to "Reset" new product with same values */
        Contract_Product__c TempProduct = NewProduct.clone(false,true,false, false);
        NewProduct = new Contract_Product__c(); 
        NewProduct = TempProduct.clone(false,true,false, false);          

    }   

/*Wrapper Class and Product Cart Methods */
    
    public class cProd
    {
        public Contract_Product__c Prod {get; set;}
        public Boolean cSelected {get; set;}
        public string vName {get; set;}
        
        public cProd(Contract_Product__c p)
        {
            Prod = p; //Contract Product object
            cSelected = false; //Selected Checkbox
            vname='changeme';                        
        }
    }   
    private list<cProd> ProductCart {get;set;}  
    
    public list<cProd> getProductCart()
    {           
        system.debug('This is the getProductCart: ' +ProductCart);
        return ProductCart;
    }

 

Anyone see what I'm doing wrong here to cause my problem? Anyone have suggestions on how to make this better?

Hey folks, I'm having some real difficulty here.

 

Here's what I'm trying to do. My goal is to have very quick client-side "warnings and errors" messages display on a VF page. Going to controller and back everytime users are entering data simply takes way too long.

 

I'm already using Javascript on that page to handle some client-side calculation. So I'm planning on also using Javascript to Identify when a data error has occured and then display text within a output panel. I want this text red, bold and centered on the page.

 

I've been able to get the text to display in an output panel, be bold and red - but I can never get it to be centered.

 

Here's a slimmed down version of what I got.

 

<apex:page standardcontroller="Contract_Product__c" extensions="Contract_Product_Add_Extension_jquery" id="page">
	<apex:form rendered="{!Master.AccountID != null && Master.Lock_Status__c != 'Locked' || $Profile.Name == 'System Administrator'}" id="ProductForm">
		<apex:outputpanel id="SelectContractProducts" layout="none">
			<apex:pageblock id="ContractProductsBlock" title="Select Contract Products"  rendered="{!Display}">
				<apex:outputpanel id="Warnings" >
					<table width="100%" id="WarningsTable">
						<tr id="WarningsRow">
							<td id="WarningsCells">
							</td>
						</tr>
					</table>
				</apex:outputpanel>
			</apex:pageblock>
		</apex:ouputpanel>
	</apex:form>
</apex:page>

 

If I remove the WarningsTable (and all chidlren) I can update the OutputPanel "Warnings" succesfully with

document.getElementById('{!$Component.page.ProductForm.ContractProductsBlock.Warnings}').innerHTML

 However trying to update the table I've been unsuccessful in getting the Table, Row, or Cell IDs. The only reason I'm using a table is to get the text to be centered.

 

Anyone provide some guidance? I either need to get the text centered in the output panel so it's centered within the pageblock or I need to get to the TD value so I can add and delete warnings.

Last night, we started having tests fail in our dev environment.  We have the following methods (shortened)

 



public static void updateTargetDate(...) {
     Set<Id> futureIds = new Set<Id>();
     ...
     // Add Ids
     ...
     if (!futureIds.isEmpty()) {
          updateTargetDateFromMilestone(futureIds);
     }
}

@future
public static void updateTargetDateFromMilestone(Set<Id> caseIds) {
     ...
}

 

Yesterday at noon (we run all tests in dev at noon and midnight) all the tests were running without error.  At midnight most of our tests were failing with the following error:

 

System.TypeException: Invalid conversion from runtime type SET<String> to SET<Id>

 

with a referral to the method of updateTargetDateFromMilestone(Set<Id> caseIds).  This file has not been updated since June 24th 2011.

 

So the question is, has anyone else seen this error crop up?  I know that in Apex Strings and Id "should" be interchangeable, however, it doesn't matter in this case since the Set being made is of type Id and the Set parameter for the calling method is of type Id.

Ok, so I am trying to do the following but I am very limited on HTML coding.

 

I have two SFDC instances (1 & 2) - On the web to lead form there are multiple product intrest to select from(A,B,C).

 

If product "A" is selected, I want it to go to instance "1", if product "B or C" is selected, go to instance "2". Lets say I just used a standard pick list so only one option could be selected.

 

Is the above even possible?

 

Now what if I used multiple pick list and a customer chose A & B, could I have it create a lead in both instances?

 

Or should I just do SFDC to SFDC?

 

Thanks for you Help!!!

PB

 

I have a batch class that accepts a query string.

 

I"m testing the function and want to pass over a query to the batch for very specific records that I can test. I would like to pass over either a single id or a set.

 

Can I format a query string to include the single quotes necessary when formatting a filter for a single ID? I know I could modify the class to include another variable but I would rather not. I'm only doing this as a test and wouldn't actually use that variable ever again after the test.

 

For example:

 

I want: 
Select MyFied__c from Contract where id = '8003000000021gz';

but as a string literal:

string q = 'select MyField__c from Contract where id =' .... 

 

I must be doing something very simply stupid.

 

I have two JS Functions, one takes a single variable and a second JS function that takes two variables.

 

All of these variables are in my Apex Controller and updated based on user input. I can't just call the variable directly in the function because it only get's set on the page load and not when a user makes an update.

 

For my first JS function with only 1 varilable I call using an ActionFunction that calls the PageReference to update the variable in the Controller and then calls my JS Function oncomplete and passes the variable to the JS Function.

 

Like this:

  <apex:actionFunction name="DurationCalculate" action="{!CalDuration}" rerender="Rec_Rev_Term,PanelTesting" oncomplete="setARRT({!duration})" >
  </apex:actionFunction>

<script type="text/javascript">
	function setARRT(duration)
	{		
		var months = duration;
		
		//set ARRT data
		document.getElementById('{!$Component.page.ProductForm.ContractProductsBlock.pbs.pbsiARRT.OutputARRT_m}').innerHTML = months;
	}
</script>

 This works perfectly!

 

So I tried doing this with my function that takes two variables. The actionfunction gets called but the actual JS function isn't.

 

  <apex:actionFunction name="CalPriceType"  rerender="PanelTesting" oncomplete="setPrices({!duration},{!Price_Type})" >  																				 
  </apex:actionFunction>	

<script type="text/javascript">
	function setPrices(duration,PriceType)
	{
		if(PriceType == 'Recurring')
		{
			.... do this
		}
		return false;
	}
</script>

 What am I doing wrong? Both {! duration } and {! Price_Type} can change base on the user input. The values are set correctly in the controller.

Okay,

 

I'm feeling incredibly stupid here. I've been using a Apex Class to handle a lot of the calculations for a page. This works and it also incredibly slow. There are multiple inputs with each one requiring a series of calculations and partial page re-renders. This causes a lot of slow down with all the client -> server communication.

 

So, I'm switching to Javascript. I've had some success with all the references and websites out there. I've successfully updated all the calculations that are done on InputText and InputField components. My issue is that this doesn't seem to work on OutputText and Outputfields.

 

Here's a quick example. It's more complex than this but really simply I'm having a javascript function populate InputFields, OutputFields and OutputText after the function is called.

 

<apex:page id="thepage">
<script type="text/javascript">
	function jsUpdateFields(){
		var vnum = 10;
		var vdollar = 5;
		var vtext = 'hello';
		
		document.getElementByID('{!Component.thepage.theform.thepageblock.InputField}').value = vnum;
		document.getElementByID('{!Component.thepage.theform.thepageblock.OutputField}').value = vdollar;
		document.getElementByID('{!Component.thepage.theform.thepageblock.OutputText}').value = vtext;
		return false;
	}
</script>
	<apex:form id="theform">
		<apex:pageblock id="thepageblock"
			<apex:inputfield value="{!Myobject.MyNumber__c}" id="InputField" />
			<apex:outputfield value="{!MyObject.MyCurrency__c}" id="OutputField" />
			<apex:outputtext value="{!MyObject.CustomText__c}" id="OutputText" />
		<a href="#" onclick="jsUpdateFields()">Run Javascript</a>
		</apex:pageblock>		
	</apex:form>
</apex:page>

 What happens: The inputfields update perfectly. The outputField and OutputText have no updates. If I change those components to inputs they work fine.

Here's the thing I don't want to have those to be inputs.

 

I've also tried using an apex function that calls the javascript function and then rerenders an outputpanel where my output fields are located. This also doesn't seem to work.

help! and thank you

So I'm creating my first functions in Javascript for visualforce.

 

I started by created the script directly on the page. This works and it takes a large amount of space.

 

So instead I planned on creating a bunch of functions and uploading those as a static resource. Then have a single script on the page that calls the functions and sets the element id.

 

When everything is on the page directly it works fine. The moment I remove my functions and upload to a static resource I get a syntax error.

 

Here's a sample of a really simple function. It accepts to variables, multiples them, and returns the result.

 

<script type="text/javascript">
	function TAPCalculate(UQ, UP){		
		var P = UQ * UP;		
		return P;
	}
</script>

 

I created this .js file and then uploaded as a static resource called 'Contract_Calcs"

 

My visualforce page then has an include script:

<apex:includeScript value="{!$Resource.Contract_Calcs}"/>

 

And then I call this function from the script on my page. I don't even get to the point of calling the function and instantly get a syntax error in firebug. Firebug states my first line of the function is wrong. That's the var P = UQ * UP;

 

It works on the page -- why doesn't it work when I upload it as a static resource?

 

 

Hi all,I want to display a popup window in vvisualforce page.on click on the image need to display an popup in visual force page,.

Ok,

 

So I've been using a controller to do a bunch of math functions on Inputfields on my page. The response of the page has degraded quite a bit so I decided to move my math functions to jquery.

 

So I'm starting with my simpliest formula where I have an inputfield for Unit Quantity, Unit Price, and Total Amount Paid.  So I created this function:

 

<script type="text/javascript">
	$j = jQuery.noConflict();
	function jsCalculate(){
		var UQ = document.getElementById('{!$Component.page.theform.ContractProductsBlock.pbs.pbsiUQ.InputUQ}').value;
		var UP = document.getElementById('{!$Component.page.theform.ContractProductsBlock.pbs.pbsiUP.InputUP}').value;
		var P = UQ * UP;
		document.getElementById('{!$Component.page.theform.ContractProductsBlock.pbs.pbsiTAP.InputTAP}').value = P;
}
</script>

 

So Here's what I'm having issues with. If I set the InputTAP value to UQ or to UP i get the correct number when the function is called. However when I try to assign it to P or do the math directly in the value set (InputTtap.value = UQ * UP)

I get an "NaN" error message instead of the product.

What am I doing wrong here? The function is being called and I'm getting the right values from my input fields but the math portion seems to fail.

 

 

I'm trying to set up an approval process including approval assignment email templates.

 

In these templates I'd like to address the receiving user, however this doesn't seem to work:

 

 

The template:

 

 

 

In the mail I get this:

 

 

 

 

Anyone has an idea what might be the problem?

 

 

Thanks in advance!