• Chris760
  • NEWBIE
  • 230 Points
  • Member since 2012

  • Chatter
    Feed
  • 5
    Best Answers
  • 2
    Likes Received
  • 1
    Likes Given
  • 26
    Questions
  • 46
    Replies

Hello,

 

I'm struggling to write an SOQL query to get all contacts which are alone on their account.

 

In other words get all accounts with only one contact and get those contacts.

 

Help would be very welcome.

 

Thanks !

  • May 14, 2013
  • Like
  • 0

Hi everyone.

 

Wow - an overwhelming amount of information.  Excellent in so many ways, a little  disconcerting for someone new. While I practically know very little about Force.com, I have an extensive background in BI, with a good understanding of tools like Informatica and Cognos. 

 

 

In a nutshell - I have an app idea (who doesn't ...), but I honestly don't know where to start.  Watched a few YouTube videos, read some posts - but still need  help.  My gut tells me that a good place to start would be a solid DB model with:

 

  • standard objects left untouched
  • standard objects repurposed (renamed etc)
  • standard objects modified (e.g. adding custom fields)
  • custom objetcs

This model would have to be based on what the app would want to accomplish, perhaps expressed as use cases initially.  I am sure that some process maps would be useful sooner than later.

 

How should I reconcile all of the above - I need some blueprint of the app before I jump into "no-coding" it.  Also, any specific tools in Force.com that would allow me to keep all these requirements in one place, mark them as complete as I implement them, divide them up in releases etc?

 

If anyone knows of a logical and comprehensive resource on architecting an app - please let me know.

 

Thanks, much appreciated!

Dan

  • May 13, 2013
  • Like
  • 0

Hello Kind SFDC Masters!

I have two custom objects, Merchant__c  and Location__c, that I sync between our main production database and our SFDC database.  They're basically clean copies of sold Accounts, and their constituent child locations.  Think Subway -- 1 Merchant, 10000 child Locations.

I have Opportunity records that can accept an unlimited number of related addresses, a related object called "LocationHolder" with standard addy fields.

My goal is to build a trigger that, upon closing an opportunity, grabs info from Opportunity to build a Merchant, then grabs  LocationHolder records and builds child Locations.  Again, Locations are children of Merchant.  LocationHolder is related to Opportunity.

I can create the Merchant without issue, thanks mostly to another forum post, but I can't

a) grab the newly created Merchant ID, or
b) iterate through the Opportunity's related LocationHolder objects, be it zero or twenty, to create any Locations.

----So Far----

trigger createMerchantFromOpportunity on Opportunity (after insert, after update) {
    
    List <Merchant__c> MerchToInsert = new List <Merchant__c> ();  
       
    for (Opportunity o : Trigger.new) {
        

        if (o.Probability == 100) {     //my criteria for the trigger
        
        Merchant__c m = new Merchant__c ();
        
        // map opportunity fields to Merchant object
        
        m.Name = o.AccountName__c;         //named the same as the Account
m.Account__c = o.AccountID; //add reference back to Account       

m.etc__c = o.etc__c;     //etc. truncated here, you get the idea.
                    
        MerchToInsert.add(m);
                
        } //end if
             
    } //end for o
    
   try {
        insert MerchToInsert;
    } catch (system.Dmlexception e) {
        system.debug (e);
    }
    
}

----END So Far----

After the insert, I should have a Merchant ID, but I don't know how to retrieve it.  I also don't know how to build, say, 5 new Location__c records if there were 5 LocationHolder related records.

Any guidance is cause for celebration!

  • May 10, 2013
  • Like
  • 0
I need to set the default/current selected dashboard value for 270 different users in our org, and it'll take me forever to do it manually by logging into each users one by one, so I'm wondering if I can do this via APEX or the SOAP Metadata API.  But does anyone even know where this value (every users currently selected dashboard) is even stored?  Is it stored in some kind of metadata/schema component?  Or in something that's directly accessible via SOQL?

Thanks.
Lets say you have an object in salesforce with 300 fields.  I then create two records, one where I only fill out 2 of the fields, and another record where I fill out all 100 of the fields.  My questions are: 1) Do both records take up the same amount of space in the database?  2) What determines the speed of a database on salesforce; the total size of how much space the database file takes up in MB?  Or is it based on the number of actual records (big or small) that are stored in the database file?

I have a salesforce org I'm working on with almost 300 fields and half a million records and it chugs like crazy (constantly times out when running queries and cant even open the tab view without timing out).  I think part of the problem is that the initial designer (a sales rep at the company) put every field he felt they could ever possibly need on the object (that only a couple records might ever use) instead of creating a seperate object to attach all these little bits and pieces of random information to.  As a result, there's always a ton of empty fields in the various records and I'm wondering if that might be a part of the problem.

Either way, any ideas or suggestions about working with objects containing millions of records would be hugely helpful.  We've already asked salesforce to add custom indexes to fields that get queried a lot, so I'm not sure what else can be done to speed things up.

Thanks.
I have a trigger that utilizes the Last Login field on the user record (you need to have logged in within a certain period of time to start getting a case load assigned to you), but I can't seem to figure out how to simulate a test user logging into salesforce on a test class.  I've tried inserting a UserLogin record manually to create the needed "Last Login" record, but no dice... the system wouldn't let me.  Is there some other way that I could simulate the act of a test user logging into salesforce after I've created that test user?

Any ideas would be welcome.
For some reason, the test class I've written is failing and I'm not sure why.  It seems to be failing as a result of one of the methods that the trigger calls.  What's weird though is that the method works fine when I'm not running it in test mode (just normally in the sandbox).  So I'm not sure if test mode disables something from working or what it might be, so any insights would be helpful.  Below is the method that the trigger is calling and failing, and the failure seems to be occuring on the third line where the records from the "Case_Assignment_Settings__c" SOQL list gets copied to the single Case_Assignment_Settings__c settings object (the test error is saying "System.ListException: List index out of bounds: 0, Class.caseAssignmentMethods: line 3, column 1,Trigger.caseTriggers: line 18, column 1: []"

Here is the caseAssignmentMethods class:
public class caseAssignmentMethods {
    public static list<Case_Assignment_Settings__c> caseSettings = [SELECT Hours_Until_Stale__c,Assignment_Timeout_Cutoff__c,Case_Match_Set_Size__c,Case_Origin_All_Match_Points__c,Case_Origin_Exact_Match_Points__c,Case_Origin_Exact_Match_Required__c,Location_All_Match_Points__c,Location_Exact_Match_Points__c,Location_Exact_Match_Required__c,Sub_Type_All_Match_Points__c,Sub_Type_Exact_Match_Points__c,Sub_Type_Exact_Match_Required__c,Tier_All_Match_Points__c,Tier_Exact_Match_Points__c,Tier_Exact_Match_Required__c,Times_Skipped_Multiplier__c,Time_Elapsed_Multiplier__c,Type_All_Match_Points__c,Type_Exact_Match_Points__c,Type_Exact_Match_Required__c,User_Type_All_Match_Points__c,User_Type_Exact_Match_Points__c,User_Type_Exact_Match_Required__c FROM Case_Assignment_Settings__c];
    Public static Case_Assignment_Settings__c settings = caseSettings[0];
    Public static Integer samples = settings.Case_Match_Set_Size__c.intValue();
    Public static list<String> filters = new list<String>{'Case_Origin','Location','Sub_Type','Type','Tier','User_Type'};
    public static datetime loginCutoff = System.Now().addHours(0-settings.Assignment_Timeout_Cutoff__c.intValue());
    public static list<Group> groups = [SELECT Id FROM Group WHERE Type = 'Queue' AND Name = 'Unassigned Queue'];
    public static Id uq = groups.get(0).Id;

    public static void sendToUnassignedQueue(list<Case> casesNeedingUQ){
        for(Case c : casesNeedingUQ){
            c.OwnerId = uq;
        }
    }
    
    public static void reassignStaleCases(){
        list<Case> processed = new list<Case>();
        for(Case c : [SELECT Id, OwnerId from Case where Status = 'New' AND Hours_Since_Last_Modified__c > :settings.Hours_Until_Stale__c]){
            Case nc = new Case();
            nc.Id = c.Id;
            nc.OwnerId = uq;
            processed.add(nc);
        }
		update processed;
    }
    
	public static void assignCases(){
		map<Id,map<String,Integer>> scores = new map<Id,Map<String,Integer>>();
        map<Integer,Integer> keys = new map<Integer,Integer>();
        list<Case> cases = new list<Case>();
        list<Case> processed = new list<Case>();
        Integer totCases = 0;
        Boolean process = false;
        Boolean query = true;
        System.debug('samples: '+samples);

        for(User u : [SELECT Id, Name, Email, Type__c, Sub_Type__c, User_Type__c, Case_Origin__c, Tier__c, Location__c, Profile.Name, LastLoginDate FROM User WHERE LastLoginDate != null AND LastLoginDate > :loginCutoff AND Id NOT IN (SELECT OwnerId FROM CASE WHERE (Status = 'In Progress' OR Status = 'New') AND OwnerId != null) ORDER BY LastLoginDate DESC NULLS LAST]){
            
            String finalQuery = buildCaseQuery(u);
            cases = Database.query(finalQuery);
            totCases = cases.size();
            System.debug('totCases: '+totCases);
            if(totCases != 0){
                process=true;
            }
            System.debug('process: '+process);
            if(process){
                Integer i = 0;
                Integer topIdIter = -1;
                Double topScore = -1;
                while(i < samples && i < totCases){
                    Case c = cases.get(i);
                    System.debug('Case Origin: '+c.Id);
                    Double curScore = compareFields(c,u);
                    System.debug('curScore: '+curScore);
                    if(curScore >= 0 && curScore > topScore){
                        topScore = curScore;
                        topIdIter = i;
                    }
                    i++;
                }
                i = 0;
                if(topIdIter >= 0){
                    Boolean finalize = true;
                    while(i <= topIdIter && finalize && i<totCases){
                        if(i == topIdIter){
                            cases[i].inProcess__c = false;
                            cases[i].OwnerId = u.Id;
                            cases[i].Assignment_Points__c = topScore;
                            processed.add(cases.remove(i));
                            totCases--;
                            finalize = false;
                        }
                        else{
                            Integer ts = cases.get(i).Times_Skipped__c.intValue();
                            cases[i].Times_Skipped__c = ts+1;
                            cases[i].inProcess__c = true;
                        }
                        i++;
                    }
                }
                i = 0;
       		 	while(totCases > 0 && cases[i].inProcess__c == true){
            		cases[i].inProcess__c = false;
            		processed.add(cases.remove(i));
            		totCases--;
        		}
        		if(processed.size() > 0){
            		update processed;
        		}
            }
        }
        
    }
	
    public static Double compareFields(Case c,User u){
    	Double curScore = 0;
        Boolean potentialCase = true;
        for(String f : filters){
            String uf = String.valueOf(u.get(f+'__c'));
            String cf = String.valueOf(c.get(f+'__c'));
            Double exactMatchPoints = Double.valueOf(settings.get(f+'_Exact_Match_Points__c'));
            Double allMatchPoints = Double.valueOf(settings.get(f+'_All_Match_Points__c'));
            Boolean exactMatchrequired = Boolean.valueOf(settings.get(f+'_Exact_Match_Required__c'));
            if(uf !=null && cf !=null && uf.contains(cf)){
                curScore += exactMatchPoints;
            }
            else if(uf !=null && cf !=null && !uf.contains('All') && exactMatchrequired){
                potentialCase = false;
            }
            else if(uf !=null && cf !=null && uf.contains('All')){
                curScore += allMatchPoints;
            }
    	}
        curScore += c.Times_Skipped__c != null ? (c.Times_Skipped__c * settings.Times_Skipped_Multiplier__c) : 0;
        curScore += c.Hours_Old__c != null ? (c.Hours_Old__c * settings.Time_Elapsed_Multiplier__c) : 0;
        if(potentialCase){
        	return curScore;
        }
        else{
            return -1;
        }
    }
    
    public static String buildCaseQuery(User u){
        Integer i = 0;
        String queryString = 'SELECT Case_Origin__c,Hours_Old__c,inProcess__c,Assignment_Points__c,CreatedDate,Location__c,OwnerId, Status,Sub_Type__c,Tier__c,Times_Skipped__c,Type__c,User_Type__c FROM Case WHERE Status = \'New\' AND OwnerId = \''+uq+'\'';
            for(String f : filters){
            String ors = '';
            String uf = String.valueOf(u.get(f+'__c'));
            System.debug('Query: '+queryString);
            Boolean exactMatchRequired = Boolean.valueOf(settings.get(f+'_Exact_Match_Required__c'));
            if(uf != null && !uf.contains('All')){
                if(exactMatchRequired){
                    List<String> filterValues = uf.split(';',-2);
                    Integer j = 0;
                    for(String fv : filterValues){
                        if(j==0){
                        	ors+=('('+f+'__c = null OR ('+f+'__c != null AND ('+f+'__c = \''+fv+'\'');
                        }
                        else{
                            ors+=(' OR '+f+'__c = \''+fv+'\'');
                        }
                        j++;
                    }
                    ors+=(')))');
                    if(String.isNotBlank(ors)){
                        queryString+= ' AND '+ors;
                    }
                }
            }
        }
        queryString += ' ORDER BY CreatedDate ASC NULLS LAST LIMIT '+samples;
        System.debug('Query: '+queryString);
        return queryString;
    }
}

Here's the trigger that calls the above methods:

trigger caseTriggers on Case (before update, before insert, after insert, after update) {
    list<Case> cases = trigger.new;
    list<Case> assignedCases = new list<Case>();
    set<Id> userIds = new set<Id>();
    for(Case c : cases){
        userIds.add(c.OwnerId);
    }
    map<Id,User> userMap = new map<Id,User>([SELECT Id, Tier__c FROM User WHERE Id IN :userIds]);
    Boolean caseChanged = false;
    for(Case c : cases){
        if((c.Status == 'New' && (trigger.isInsert && trigger.isBefore || (trigger.isUpdate && trigger.isBefore && c.OwnerId == Trigger.oldMap.get(c.Id).OwnerId))) || (trigger.isUpdate && trigger.isBefore && c.isClosed == false && c.Tier__c != Trigger.oldMap.get(c.Id).Tier__c && !userMap.get(c.OwnerId).Tier__c.contains(c.Tier__c))){
            assignedCases.add(c);
        }
        if(trigger.isAfter){caseChanged = true;
        }
    }
    if(trigger.isBefore && !assignedCases.isEmpty()){
        caseAssignmentMethods.sendToUnassignedQueue(assignedCases);
    }
    if(true==true && triggerValidate.allowCaseUpdate && caseChanged){triggerValidate.allowCaseUpdate = false;caseAssignmentMethods.assignCases();triggerValidate.allowCaseUpdate = true;
    }
}

And lastly, here's my test class:

@isTest 
public class testAllCaseTrigger{

    static testMethod void testInactivityMethod() { 
    List<RecordType> rtypes = [Select Id From RecordType where Name='Person Account' and isActive=true];
    List<Account> accounts = new List<Account>{}; 
    List<Case> cases = new List<Case>{}; 
    
    test.startTest(); 
    
    for(Integer i = 0; i < 1; i++){ 
    Account newAcct = new Account(LastName='TestAcct'+ i,Phone='111',RecordTypeID=rtypes[0].ID);  
    accounts.add(newAcct); 
    } 
    
    insert accounts; 
    
    for(Integer i = 0; i < 1; i++){ 
    Case newCase = new Case(SuppliedName='TestAcct'+ i,Subject='111');  
    cases.add(newCase); 
    } 
    
    insert cases; 
    
    
    test.stopTest(); 
    
    }
    
    static testMethod void testCaseAssignment() {
        list<Profile> profiles = [SELECT Id FROM Profile WHERE Name = 'Service Rep'];
        Id profile = profiles[0].Id;        
        
      	User u = new User();
        u.LastName = 'Test';
        u.FirstName = 'Test';
        u.Email = 'abc13@123.com';
        u.ProfileId = profile;
        u.Tier__c = 'Tier 1';
        u.Username = 'abc13@123.com';
        u.Alias = 'Test1';
        u.CommunityNickname = 'TestNick';
        u.TimeZoneSidKey = 'America/Los_Angeles';
        u.LocaleSidKey = 'en_US';
        u.EmailEncodingKey = 'ISO-8859-1';
        u.LanguageLocaleKey = 'en_US';
        Insert u;
        
        User u2 = new User();
        u2.LastName = 'Test2';
        u2.FirstName = 'Test2';
        u2.Email = 'abcd2@123.com';
        u2.ProfileId = profile;
        u2.Tier__c = 'Tier 2';
        u2.Username = 'abcd2@123.com';
        u2.Alias = 'Test2';
        u2.CommunityNickname = 'TestNick2';
        u2.TimeZoneSidKey = 'America/Los_Angeles';
        u2.LocaleSidKey = 'en_US';
        u2.EmailEncodingKey = 'ISO-8859-1';
        u2.LanguageLocaleKey = 'en_US';
        Insert u2;
        
        test.startTest(); 
        
        Case c = new Case();
        c.OwnerId = u.Id;
      	c.Status = 'New';
      	c.Tier__c = 'Tier 1';
   		Insert c;
        
        c.Status = 'In Progress';
        Update c;
        
        c.Tier__c = 'Tier 2';
        Update c;
        test.stopTest(); 
        
   	}

}

Thanks.

Lets say I wrote the following on the Account chatter feed: "@[Bob Jones] thanks for all the help you gave to @[Debbie Johnson] yesterday!  I'll make sure that @[John Smith] follows up with you guys tomorrow."

Where (or how) does chatter actually store the @[User] information for all the users mentioned in that post?  When I go to the FeedComment or FeedItem objects in the developers workbench (depending on whether the post is the first in a thread or not), the "Body" field in both objects always shows the above post as "@Bob Jones thanks for all the help you gave to @Debbie Johnson yesterday!  I'll make sure that @John Smith follows up with you guys tomorrow."

It appears that, when it gets saved to the database, it takes off the brackets.  But if I were to save either version of that post directly to salesforce using APEX (with or without the brackets), it somehow breaks the feature that allows the various users profiles (Bobs, Debbies, and Johns) to pop up when you mouse over their user hashtag.

So what I'm trying to figure out (with not much luck) is, how does the system store or create the relationship between the user hashtags in a message, and the users whom those hashtags reference?  My end goal is to be able to insert chatter posts via apex where I can add the @[User] hashtags and those users will actually have those posts show up in their chatter feeds.

I'm trying to figure out how to write a SOQL query to display the newest opportunity associated with every account, using the MIN() SOQL aggregate function.  Unfortunately, I can't seem to wrap my head around how to structure this since aggregate queries only let you include the field that you're grouping by and the field you're aggregating [Example: AccountId, MIN(CreatedDate) from Opportunity], however I also need to know the Id of each resulting opportunity so that I can utilize it in the trigger.  How would I need to structure the query so that I can also extract the opportunity ID?  Thanks!

I have a regular old PDF file on my desktop, and that same PDF file is attached to a record in Salesforce.  Now, when I change the PDF's extension on my computer to ".txt", I can then open it and read the texttual data that makes up the file.  I need to extract some data at the beginning of the ".txt" version of the file that details how many pages the PDF consists of, but I need to do this for many PDF files that are already in Salesforce.

I discovered the "String pdf = System.EncodingUtil.base64Encode(a.Body)" method, which apparently converts the base64 blob representation of the file into an unencoded string... but when I looked at the actual output, I realized that it was totally different compared to the ".txt" version of the PDF on my desktop.  It seems that I'm not encoding/decoding the attachment Body blob to the correct format, but I'm totally clueless as to what to convert it to, or what method I would need to use to convert it.

Does anyone have any ideas as to how I would convert the PDF data to whatever format it gets converted to when I just change the extension on my computer and view it in notepad?

Thanks!


We have a free app installed in our org from the app exchange that has a "Settings" tab that loads a visualforce page with various fields denoting different settings.  These settings can all be accessed again by going to that tab, which loads the visualforce page, which loads all the saved settings from... somewhere in the org.

 

My question is... how do I locate the "somewhere" that the settings get stored in?  I initially assumed that the settings must get stored in one of the custom objects that get created when the app is installed, but I used the Workbench to view every single record in the org with the package prefix, and none of the settings get saved to any of those objects... that I *KNOW* of.

 

That then leads into my second question (and this is probably my main question)... is it possible for a custom settings object or a custom object to be configured so that even the system administrator can't view the records contained in that object (like maybe some kind of special setting that you can only setup when making an app for the app exchange)?

 

Any ideas would be hugely appreciated!

Since programming in APEX, I've learned to use maps (as opposed to nested FOR loops) on pretty much everything.  But there's one scenario where I've never been able to figure out a "map" based solution and I wanted to get feedback from some of you more experience gurus about how you would approcah the following problem and see if I'm going about this situation in totally the wrong way.

 

So the problem occurs when I'm dealing with multiple *dynamic* filters in a given query.  Here's a real life example I'm dealing with right now...

 

I'm currently working on an insurance companies system where every time a doctor authorizes a patient to receive treatment but *doesn't* fax in the patents records along with the authorization, I need to query the database to look for past medical records for that patient where the patient ID (on the faxed authorization) matches the patient ID in the database, and the doctor ID on the authorization, matches the doctor ID in the database, and the number of times medicated per day, is a number that's greater than or equal to the number of times medicated on the patient record in the database.

 

In other words, unlike most situations where you'd just say "[select ID, Patient__c, Doctor__c, Times_Treated_Daily__c from Records__c where Patient__c IN: patientsWithRecords.keySet()]", the filters in this case are multiple, and different for every record being queried.  So (and PLEASE correct me if I'm wrong) if I wrote "select Id, Patient__c, Doctor__c, Times_Treated_Daily__c from Records__c where Patient__c IN: patientsWithRecords.keySet() and Doctor__c IN: doctorsWithRecords.keySet() and Times_Treated_Daily__c IN: (or >= ?) timesTreatedDaily.keySet()" (essentially doing a FOR loop to extract my filters into individual keysets ahead of time), the resulting query would be useless because a patient could have multiple matching doctors, a doctor can have multiple matching patients, and the times treated could be grater or less than anyone in the keyset.  So simply throwing the 3 filters that I need to query against (Patient, Doctor, and Times Treated Daily) into 3 maps/keysets and querying against it, won't necessarily return records that I could bind with because the "IN:" part of the query means that records could easily "mix and match" with a variety of doctors, patients, and times treated daily.

 

As a result, I'll make the 3 keySets, but then I'll still iterate through the records to do the final matching since I feel like there's no way to know if record X is actually the patient, doctor and times treated daily for the specific record I'm querying for.  Am I going about this in a totally wrong way and there's actually a way simpler way to do this?  Or do maps automatically somehow compensate for this when you map multiple variables?  Or is there a way to write your SOQL in order to account for multiple variables like that?  Or are nested FOR loops basically the only way?

 

I'm so curious to know how other people would tackle this problem.  Any ideas or experiences with it would be hugely apprecited.  Thanks!

In the standard salesforce view, you can use URL variables to populate certain list views on an tab.  For example, if you wanted to populate a certain list view on the Account, you'd set the URL to be "/001?fcf={List View Salesforce ID}.  As most on here know, you can use URL variables to select and prepopulate all kinds of things on list views and on records.

 

Then there's the standard Salesforce Console.  The Console seems to consist of a page called "DesktopPage", which is embedded with 3 iFrame windows (a list view, a main view, and a mini view).  Unfortunately, unlike the normal tab views, I can't seem to make the console do ANYTHING using URL variables.  Specifically, I'm trying to change the Tab/Object dropdown list to a specific object, and change the List View dropdown to a specific record.

 

Does anyone know of any URL variables or (if not URL variables) some kind of a way to accomplish the act of selecting the dropdowns you want when first opening the console?  If not, does anyone know of a way to execute a javascript "Mass Action" console button, or some other way to execute javascript on the console when the page first loads?

 

Any ideas or thoughts at all would be hugely appreciated.

I often times run into scenarios where I need to extract phone, fax, or mobile numbers from phone or string fields and then get rid of everything but the numbers (for verification/comparison purposes, deduping, or to run other automation that wont accept non-numbers).  Currently, I do a PhoneNumber.replace('(','').replace(')','').replace('.','').replace('-','').replace(' ','').replace('+','') etc etc type of thing to get rid of every charachter I can think of that might muck up the trigger, but it's obviously not very efficient because not only is it long, but people still throw in charachters occasionally that I didn't account for.

 

Is there some kind of method in Apex that can automatically extract all the numbers in a string, in the same order that they appear in the string?  Or can anyone think of another apex method (or approach) that might act as a nice little shortcut?

 

Any ideas from more experienced programmers would be really appreciated.  Thanks.

I have an After Update trigger that updates the fields on a parent object, and that object has several validation rules that have the potential to fire if they're met when the After Update trigger runs.

 

Instead of the normal DML exception though where it reads like gibberish and sends me an error email and leaves the user scratching their head, how would I display a custom error message, prevent the DML insert, and have the system NOT clog my email with exception messages?

 

The section of my code that triggers the DML is as follows:

 

    try{
    update processedOpportunitiesList;
    } catch(DMLException e){
        if(e.getMessage().contains('FIELD_CUSTOM_VALIDATION_EXCEPTION, Please enter Shipping Address, City, State and Zip')){
            e.addError('You can\'t select this stage until you first enter the Shipping Address info on the opportunity.');
        }
    }

 In the above code, I'm trying to say that, if running the DML update with the list "processedOpportunitiesList" results in a DML exception that contains the sentence "FIELD_CUSTOM_VALIDATION_EXCEPTION, Please enter Shipping Address, City, State and Zip", then I want to instead display "You can't select this stage until you first enter the Shipping Address info on the opportunity." to the user, prevent salesforce from inserting the record, and have it not email me about the exception.

 

However, I seem to not be grasping how this particular class is structured or how I'm supposed to write it.  I keep getting "Method does not exist or incorrect signature" errors as I fiddle around with the code and I'm realizing that I'm not "getting" this and I should probably ask on here for help.  Can someone please tell me how I would need to write or structure this trigger properly?

 

Thanks.

When you create a custom button that pre-populates various fields with values, you have to specify the salesforce record ID of the field itself in your button parameters and then put "=" (equals), and then follow that up with your merge field to specify the value of that parameter.

 

Normally I get the record ID by just using Google Chrome, right clicking on the field while in Edit view, clicking "Inspect Element" (which gives me the salesforce ID) and then pasting that ID in my button code as the parameter needing to be populated.  I know that other people go a longer route by going to the object in question, clicking on the field name itself, and copying the salesforce ID from the URL (after the "salesforce.com/" part) to extract the custom field salesforce ID.

 

Both of these methods seem rediculously inefficient.  More importantly though, you're hard-coding the field ID into the button itself.  That means, if your company ever moves orgs, OR if you're creating a packaged app, your button will essentially "break" once it's installed in a new org, because the field ID's in your button parameters will no longer match the ID's that salesforce assignes to those fields once you install that package somewhere else.

 

So my question is this... is there some special trick, either using the "URLFOR" function or something else (formula functon, action, etc), that allows you to dynamically generate the salesforce ID of a field that you need to include in your parameters?

 

Essentially, it would allow your buttons to look something like the following (this example would be a list button for Contacts, placed on the Account page layout):

 

{!URLFOR($Action.Contact.New,Account.Id,[FIELDID($ObjectType.Contact,"Contact_Status__c")="New",retURL=Account.Id],true)}

 

So in the above example, I invented a functon called "FIELDID", which takes the Sobject type and API name of the field on that object, does a DescribeSobject() call in the background, and spits out the salesforce ID of that particular field, as opposed to hard coding it perminantly.  No hunting around for salesforce ID's, no hacks, just using the tools available in the Custom Button section.

 

So... that being said, is there some way to do pretty much that, using the button functions available to salesforce users?  If not, then what is the "official" way that Salesforce recommends you use to go about extracting field ID's for the parameters you use in your custom buttons?

So, the "Add Email" button dissapeared from one of our employees computers a few weeks back.  On Thursday, I followed the instructions here: http://help.salesforce.com/apex/HTViewSolution?id=000003640&language=en_US to resolve the issue.  Unfortunately, the problem still persisted, so I found the additional article here: https://help.salesforce.com/apex/HTViewSolution?urlname=Salesforce-for-Outlook-Add-Email-button-issues-1327108647257&language=en_US.

 

I followed all the steps in that article too, step by step to the very last one, and not only is the "Add Email" button still not visible in outlook, but now I have a new problem... Salesforce for Outlook doesn't open *at all*.  I've tried reinstalling it 4 times, constantly updating little things after each reinstall, hoping something would help, but nothing.

 

One slight detail (I'm not sure if it matters) -- but the computer in question is running Windows 8 with Office 2010 -- where as a lot of these instructions seem to be geared towards Windows 7.  I know they're very similar OS's, so I didn't think it would matter much, but could anyone give me any ideas on what to try next?  Does anyone know by chance where the Salesforce for Outlook setup files are saved?  There seems to be *something* that's left over on Windows 8 that's not getting reinstalled, and preventing Salesforce for Outlook from running, even though it says all the pre-requesite files are installed.  I'm really dumbfounded as to why the program won't even open at all now.

Does anyone know if there's any plan to make an updated version of the Force IDE for Eclipse that will work with Java 7?  I have to always downgrade Java 7 to Java 6 on any machine I install the Force IDE on, along with Eclipse 3.6 (a much older version) or else it wont work.  Do most people use Eclipse?  Or am I missing something as to why it's such a pain to get up and running using desktop apps to edit your apex code?

I have an extremely basic trigger that is designed to delete any task with a blank subject when it's created:

 

trigger deleteBlankSubjects on Task (after insert){

  list<Task> records = trigger.new;
  list<Task> deletable = new list<Task>();
		
    for(Task t : records){
      if(t.Subject == null || isBlank(t.Subject)){
        deletable.add(t);					
      }
    }
  delete deletable;		
}

 

For some reason though, whenever I write out the isBlank() method, I get the error, "Save error: Method does not exist or incorrect signature: isBlank(String)".  

 

I've tried writing it a bunch of different ways now, and every time I get the same error.  What's worse, is that I can't seem to find any examples of people using the APEX .isBlank() method on google (where I usually turn when I'm stuck), even though the APEX Handbook says it's perfectly allowable.  What am I doing wrong here???  Totally confused.

 

I'm using Eclipse if it's of any help.  Any insight from any guru's out there would be HUGELY appreciated.

Hi,

 

So here's the scenario I'm dealing with...  I have a graphic design company who needs to keep track of and use (in merge programs) several terrebytes of JPEG images.  Most of the images are under a MB in size, but they just have WAY too many images to actually store them in their actual salesforce org.  So I've developed an easy way of tracking and searching their images in salesforce by importing links and descriptions to the files (that are stored on their servers) and I've used the "IMAGE" formula function to display a clickable preview of the files in the salesforce records (as well as the list views) to aid them when searching for specific themed images.

 

The problem I'm having now though is this... how can I use APEX to pull that image into a custom class, in order to use the image for a slew of automated actions?  Is there some kind of getImage() method or something that's capable of doing that?  Any ideas as to how I can accomplish this would be a huge help.

 

Thanks!

So a little background... I have a master-detail relationship established between Opportunities (Master) and Invoices (Detail).  On the Invoices object, I have a number field called "Amount Due", a date field called "Due Date" and a checkbox called "Overdue".

 

So I have a timed workflow setup where, when Today = Due Date, a timed workflow is supposed to perform a field update on the Invoices object where the "Overdue" checkbox gets checked.

 

I then have a rollup field to the master (Opportunity) object that totals the "Amount Due" field on any Invoices where "Overdue" is checked.  So once the workflow triggers and checks the "Overdue" checkbox on the invoice, it should rollup the amount that's due on that invoice, to the "Amount Overdue" field on the Opportunity.

 

So it seems pretty straitforward to me... but for some odd reason, when the timed workflow is supposed to fire, nothing happens.  Instead, it just sits in the Time-Based Workflows queue for a few hours before it finally dissapears, like the system finally gave up and purged it.  When I create it as an immediate workflow, it works prefectly.  It's only when I create it as a timed workflow that it falls apart.  Also, when I create it as a timed workflow that checks another "Test" checkbox that's unrelated to the rollup, it work perfectly.  So it's just when it's a timed workflow that checks a checkbox that's needed to make a rollup work that everything seems to go haywire.

 

Does anyone know if there's some wierd criteria at play, where you're not allowed to make time-based workflows that set the required criteria for a rollup field?  If so, what's the work-around for that?  I'm really at a loss here.

So I have a timed workflow setup where...

 

When: Invoice.dueDate == TODAY

//It triggers a field update:

Invoice.overdueCheckbox = TRUE)

 Then I had a rollup on the parent object (the opportunity) that sums the total of the amount overdue for that account.

 

Strangely though, the timed workflow doesn't want to fire.  It will just sit in the the Time-Based Workflow Queue for hours and hours after it hits its scheduled date-time, and then it will finally just dissapear... like the system finally gave up and purged it.

 

When I tried making a time-based workflow that updates another checkbox that doesn't trigger the rollup, it DOES work (almost imediately), so it's aparently some kind of weird evaluation criteria related to rollup fields that I'm not familiar with.  I checked out the "Time Based Workflow Considerations" page, but didn't see anything in there about rollup fields preventing time-based workflows from firing.

 

I've tried combining it with apex to see if I could work around it (by triggering an After Update to update the rollup checkbox after the time based workflow updates the non-rollup checkbox) but, once again, the workflow just hangs out in the queue after it's been triggered until the system finally purges it.

 

I've even tried using the @future method to initiate the update that way, but once again, the field update just hangs out in the Time-Based Workflows queue before it finally gets purged.  I'm so stumped right now that my head literally hurts.  What am I missing?  Does anyone have any ideas as to how to work around this or what evaluation criteria will cause a workflow to purge without firing?  Is scheduled apex the only way?  I'd really like to use some of the standard salesforce automation features before resorting to that, but I'm kind of running out of ideas here.  Any thoughts at all would be a huge help... I'm totally all ears.

 

Thanks guys.

Does anyone know how I would go about creating the type of combo "Address" fields that you see on the Account (Billing Address & Shipping Address) as well as the Contact (Mailing Address and Other Address) where all the fields of the address display at the same time in one clean box?  

 

How easy would it be to create the needed elements so that I could just drop it on the page layout as an S-Control, without resorting to overriding the entire page as a Visualforce page?  Any ideas would be a major help as my background is more in Apex as opposed to Visualforce (so I'm admittedly a bit dumb in the VF department).

 

Thanks!

Lets say I wrote the following on the Account chatter feed: "@[Bob Jones] thanks for all the help you gave to @[Debbie Johnson] yesterday!  I'll make sure that @[John Smith] follows up with you guys tomorrow."

Where (or how) does chatter actually store the @[User] information for all the users mentioned in that post?  When I go to the FeedComment or FeedItem objects in the developers workbench (depending on whether the post is the first in a thread or not), the "Body" field in both objects always shows the above post as "@Bob Jones thanks for all the help you gave to @Debbie Johnson yesterday!  I'll make sure that @John Smith follows up with you guys tomorrow."

It appears that, when it gets saved to the database, it takes off the brackets.  But if I were to save either version of that post directly to salesforce using APEX (with or without the brackets), it somehow breaks the feature that allows the various users profiles (Bobs, Debbies, and Johns) to pop up when you mouse over their user hashtag.

So what I'm trying to figure out (with not much luck) is, how does the system store or create the relationship between the user hashtags in a message, and the users whom those hashtags reference?  My end goal is to be able to insert chatter posts via apex where I can add the @[User] hashtags and those users will actually have those posts show up in their chatter feeds.
I have a regular old PDF file on my desktop, and that same PDF file is attached to a record in Salesforce.  Now, when I change the PDF's extension on my computer to ".txt", I can then open it and read the texttual data that makes up the file.  I need to extract some data at the beginning of the ".txt" version of the file that details how many pages the PDF consists of, but I need to do this for many PDF files that are already in Salesforce.

I discovered the "String pdf = System.EncodingUtil.base64Encode(a.Body)" method, which apparently converts the base64 blob representation of the file into an unencoded string... but when I looked at the actual output, I realized that it was totally different compared to the ".txt" version of the PDF on my desktop.  It seems that I'm not encoding/decoding the attachment Body blob to the correct format, but I'm totally clueless as to what to convert it to, or what method I would need to use to convert it.

Does anyone have any ideas as to how I would convert the PDF data to whatever format it gets converted to when I just change the extension on my computer and view it in notepad?

Thanks!


Lets say you have an object in salesforce with 300 fields.  I then create two records, one where I only fill out 2 of the fields, and another record where I fill out all 100 of the fields.  My questions are: 1) Do both records take up the same amount of space in the database?  2) What determines the speed of a database on salesforce; the total size of how much space the database file takes up in MB?  Or is it based on the number of actual records (big or small) that are stored in the database file?

I have a salesforce org I'm working on with almost 300 fields and half a million records and it chugs like crazy (constantly times out when running queries and cant even open the tab view without timing out).  I think part of the problem is that the initial designer (a sales rep at the company) put every field he felt they could ever possibly need on the object (that only a couple records might ever use) instead of creating a seperate object to attach all these little bits and pieces of random information to.  As a result, there's always a ton of empty fields in the various records and I'm wondering if that might be a part of the problem.

Either way, any ideas or suggestions about working with objects containing millions of records would be hugely helpful.  We've already asked salesforce to add custom indexes to fields that get queried a lot, so I'm not sure what else can be done to speed things up.

Thanks.
I have a trigger that utilizes the Last Login field on the user record (you need to have logged in within a certain period of time to start getting a case load assigned to you), but I can't seem to figure out how to simulate a test user logging into salesforce on a test class.  I've tried inserting a UserLogin record manually to create the needed "Last Login" record, but no dice... the system wouldn't let me.  Is there some other way that I could simulate the act of a test user logging into salesforce after I've created that test user?

Any ideas would be welcome.
Hi everyone,
I need your help on the below.

I have got a requirment where I need to generate a report that should capture the total login time of users i.e.; Login Time - LogOut Time = total login hours.

Is there anyway we can achieve this, Please help. Thank You
For some reason, the test class I've written is failing and I'm not sure why.  It seems to be failing as a result of one of the methods that the trigger calls.  What's weird though is that the method works fine when I'm not running it in test mode (just normally in the sandbox).  So I'm not sure if test mode disables something from working or what it might be, so any insights would be helpful.  Below is the method that the trigger is calling and failing, and the failure seems to be occuring on the third line where the records from the "Case_Assignment_Settings__c" SOQL list gets copied to the single Case_Assignment_Settings__c settings object (the test error is saying "System.ListException: List index out of bounds: 0, Class.caseAssignmentMethods: line 3, column 1,Trigger.caseTriggers: line 18, column 1: []"

Here is the caseAssignmentMethods class:
public class caseAssignmentMethods {
    public static list<Case_Assignment_Settings__c> caseSettings = [SELECT Hours_Until_Stale__c,Assignment_Timeout_Cutoff__c,Case_Match_Set_Size__c,Case_Origin_All_Match_Points__c,Case_Origin_Exact_Match_Points__c,Case_Origin_Exact_Match_Required__c,Location_All_Match_Points__c,Location_Exact_Match_Points__c,Location_Exact_Match_Required__c,Sub_Type_All_Match_Points__c,Sub_Type_Exact_Match_Points__c,Sub_Type_Exact_Match_Required__c,Tier_All_Match_Points__c,Tier_Exact_Match_Points__c,Tier_Exact_Match_Required__c,Times_Skipped_Multiplier__c,Time_Elapsed_Multiplier__c,Type_All_Match_Points__c,Type_Exact_Match_Points__c,Type_Exact_Match_Required__c,User_Type_All_Match_Points__c,User_Type_Exact_Match_Points__c,User_Type_Exact_Match_Required__c FROM Case_Assignment_Settings__c];
    Public static Case_Assignment_Settings__c settings = caseSettings[0];
    Public static Integer samples = settings.Case_Match_Set_Size__c.intValue();
    Public static list<String> filters = new list<String>{'Case_Origin','Location','Sub_Type','Type','Tier','User_Type'};
    public static datetime loginCutoff = System.Now().addHours(0-settings.Assignment_Timeout_Cutoff__c.intValue());
    public static list<Group> groups = [SELECT Id FROM Group WHERE Type = 'Queue' AND Name = 'Unassigned Queue'];
    public static Id uq = groups.get(0).Id;

    public static void sendToUnassignedQueue(list<Case> casesNeedingUQ){
        for(Case c : casesNeedingUQ){
            c.OwnerId = uq;
        }
    }
    
    public static void reassignStaleCases(){
        list<Case> processed = new list<Case>();
        for(Case c : [SELECT Id, OwnerId from Case where Status = 'New' AND Hours_Since_Last_Modified__c > :settings.Hours_Until_Stale__c]){
            Case nc = new Case();
            nc.Id = c.Id;
            nc.OwnerId = uq;
            processed.add(nc);
        }
		update processed;
    }
    
	public static void assignCases(){
		map<Id,map<String,Integer>> scores = new map<Id,Map<String,Integer>>();
        map<Integer,Integer> keys = new map<Integer,Integer>();
        list<Case> cases = new list<Case>();
        list<Case> processed = new list<Case>();
        Integer totCases = 0;
        Boolean process = false;
        Boolean query = true;
        System.debug('samples: '+samples);

        for(User u : [SELECT Id, Name, Email, Type__c, Sub_Type__c, User_Type__c, Case_Origin__c, Tier__c, Location__c, Profile.Name, LastLoginDate FROM User WHERE LastLoginDate != null AND LastLoginDate > :loginCutoff AND Id NOT IN (SELECT OwnerId FROM CASE WHERE (Status = 'In Progress' OR Status = 'New') AND OwnerId != null) ORDER BY LastLoginDate DESC NULLS LAST]){
            
            String finalQuery = buildCaseQuery(u);
            cases = Database.query(finalQuery);
            totCases = cases.size();
            System.debug('totCases: '+totCases);
            if(totCases != 0){
                process=true;
            }
            System.debug('process: '+process);
            if(process){
                Integer i = 0;
                Integer topIdIter = -1;
                Double topScore = -1;
                while(i < samples && i < totCases){
                    Case c = cases.get(i);
                    System.debug('Case Origin: '+c.Id);
                    Double curScore = compareFields(c,u);
                    System.debug('curScore: '+curScore);
                    if(curScore >= 0 && curScore > topScore){
                        topScore = curScore;
                        topIdIter = i;
                    }
                    i++;
                }
                i = 0;
                if(topIdIter >= 0){
                    Boolean finalize = true;
                    while(i <= topIdIter && finalize && i<totCases){
                        if(i == topIdIter){
                            cases[i].inProcess__c = false;
                            cases[i].OwnerId = u.Id;
                            cases[i].Assignment_Points__c = topScore;
                            processed.add(cases.remove(i));
                            totCases--;
                            finalize = false;
                        }
                        else{
                            Integer ts = cases.get(i).Times_Skipped__c.intValue();
                            cases[i].Times_Skipped__c = ts+1;
                            cases[i].inProcess__c = true;
                        }
                        i++;
                    }
                }
                i = 0;
       		 	while(totCases > 0 && cases[i].inProcess__c == true){
            		cases[i].inProcess__c = false;
            		processed.add(cases.remove(i));
            		totCases--;
        		}
        		if(processed.size() > 0){
            		update processed;
        		}
            }
        }
        
    }
	
    public static Double compareFields(Case c,User u){
    	Double curScore = 0;
        Boolean potentialCase = true;
        for(String f : filters){
            String uf = String.valueOf(u.get(f+'__c'));
            String cf = String.valueOf(c.get(f+'__c'));
            Double exactMatchPoints = Double.valueOf(settings.get(f+'_Exact_Match_Points__c'));
            Double allMatchPoints = Double.valueOf(settings.get(f+'_All_Match_Points__c'));
            Boolean exactMatchrequired = Boolean.valueOf(settings.get(f+'_Exact_Match_Required__c'));
            if(uf !=null && cf !=null && uf.contains(cf)){
                curScore += exactMatchPoints;
            }
            else if(uf !=null && cf !=null && !uf.contains('All') && exactMatchrequired){
                potentialCase = false;
            }
            else if(uf !=null && cf !=null && uf.contains('All')){
                curScore += allMatchPoints;
            }
    	}
        curScore += c.Times_Skipped__c != null ? (c.Times_Skipped__c * settings.Times_Skipped_Multiplier__c) : 0;
        curScore += c.Hours_Old__c != null ? (c.Hours_Old__c * settings.Time_Elapsed_Multiplier__c) : 0;
        if(potentialCase){
        	return curScore;
        }
        else{
            return -1;
        }
    }
    
    public static String buildCaseQuery(User u){
        Integer i = 0;
        String queryString = 'SELECT Case_Origin__c,Hours_Old__c,inProcess__c,Assignment_Points__c,CreatedDate,Location__c,OwnerId, Status,Sub_Type__c,Tier__c,Times_Skipped__c,Type__c,User_Type__c FROM Case WHERE Status = \'New\' AND OwnerId = \''+uq+'\'';
            for(String f : filters){
            String ors = '';
            String uf = String.valueOf(u.get(f+'__c'));
            System.debug('Query: '+queryString);
            Boolean exactMatchRequired = Boolean.valueOf(settings.get(f+'_Exact_Match_Required__c'));
            if(uf != null && !uf.contains('All')){
                if(exactMatchRequired){
                    List<String> filterValues = uf.split(';',-2);
                    Integer j = 0;
                    for(String fv : filterValues){
                        if(j==0){
                        	ors+=('('+f+'__c = null OR ('+f+'__c != null AND ('+f+'__c = \''+fv+'\'');
                        }
                        else{
                            ors+=(' OR '+f+'__c = \''+fv+'\'');
                        }
                        j++;
                    }
                    ors+=(')))');
                    if(String.isNotBlank(ors)){
                        queryString+= ' AND '+ors;
                    }
                }
            }
        }
        queryString += ' ORDER BY CreatedDate ASC NULLS LAST LIMIT '+samples;
        System.debug('Query: '+queryString);
        return queryString;
    }
}

Here's the trigger that calls the above methods:

trigger caseTriggers on Case (before update, before insert, after insert, after update) {
    list<Case> cases = trigger.new;
    list<Case> assignedCases = new list<Case>();
    set<Id> userIds = new set<Id>();
    for(Case c : cases){
        userIds.add(c.OwnerId);
    }
    map<Id,User> userMap = new map<Id,User>([SELECT Id, Tier__c FROM User WHERE Id IN :userIds]);
    Boolean caseChanged = false;
    for(Case c : cases){
        if((c.Status == 'New' && (trigger.isInsert && trigger.isBefore || (trigger.isUpdate && trigger.isBefore && c.OwnerId == Trigger.oldMap.get(c.Id).OwnerId))) || (trigger.isUpdate && trigger.isBefore && c.isClosed == false && c.Tier__c != Trigger.oldMap.get(c.Id).Tier__c && !userMap.get(c.OwnerId).Tier__c.contains(c.Tier__c))){
            assignedCases.add(c);
        }
        if(trigger.isAfter){caseChanged = true;
        }
    }
    if(trigger.isBefore && !assignedCases.isEmpty()){
        caseAssignmentMethods.sendToUnassignedQueue(assignedCases);
    }
    if(true==true && triggerValidate.allowCaseUpdate && caseChanged){triggerValidate.allowCaseUpdate = false;caseAssignmentMethods.assignCases();triggerValidate.allowCaseUpdate = true;
    }
}

And lastly, here's my test class:

@isTest 
public class testAllCaseTrigger{

    static testMethod void testInactivityMethod() { 
    List<RecordType> rtypes = [Select Id From RecordType where Name='Person Account' and isActive=true];
    List<Account> accounts = new List<Account>{}; 
    List<Case> cases = new List<Case>{}; 
    
    test.startTest(); 
    
    for(Integer i = 0; i < 1; i++){ 
    Account newAcct = new Account(LastName='TestAcct'+ i,Phone='111',RecordTypeID=rtypes[0].ID);  
    accounts.add(newAcct); 
    } 
    
    insert accounts; 
    
    for(Integer i = 0; i < 1; i++){ 
    Case newCase = new Case(SuppliedName='TestAcct'+ i,Subject='111');  
    cases.add(newCase); 
    } 
    
    insert cases; 
    
    
    test.stopTest(); 
    
    }
    
    static testMethod void testCaseAssignment() {
        list<Profile> profiles = [SELECT Id FROM Profile WHERE Name = 'Service Rep'];
        Id profile = profiles[0].Id;        
        
      	User u = new User();
        u.LastName = 'Test';
        u.FirstName = 'Test';
        u.Email = 'abc13@123.com';
        u.ProfileId = profile;
        u.Tier__c = 'Tier 1';
        u.Username = 'abc13@123.com';
        u.Alias = 'Test1';
        u.CommunityNickname = 'TestNick';
        u.TimeZoneSidKey = 'America/Los_Angeles';
        u.LocaleSidKey = 'en_US';
        u.EmailEncodingKey = 'ISO-8859-1';
        u.LanguageLocaleKey = 'en_US';
        Insert u;
        
        User u2 = new User();
        u2.LastName = 'Test2';
        u2.FirstName = 'Test2';
        u2.Email = 'abcd2@123.com';
        u2.ProfileId = profile;
        u2.Tier__c = 'Tier 2';
        u2.Username = 'abcd2@123.com';
        u2.Alias = 'Test2';
        u2.CommunityNickname = 'TestNick2';
        u2.TimeZoneSidKey = 'America/Los_Angeles';
        u2.LocaleSidKey = 'en_US';
        u2.EmailEncodingKey = 'ISO-8859-1';
        u2.LanguageLocaleKey = 'en_US';
        Insert u2;
        
        test.startTest(); 
        
        Case c = new Case();
        c.OwnerId = u.Id;
      	c.Status = 'New';
      	c.Tier__c = 'Tier 1';
   		Insert c;
        
        c.Status = 'In Progress';
        Update c;
        
        c.Tier__c = 'Tier 2';
        Update c;
        test.stopTest(); 
        
   	}

}

Thanks.

Lets say I wrote the following on the Account chatter feed: "@[Bob Jones] thanks for all the help you gave to @[Debbie Johnson] yesterday!  I'll make sure that @[John Smith] follows up with you guys tomorrow."

Where (or how) does chatter actually store the @[User] information for all the users mentioned in that post?  When I go to the FeedComment or FeedItem objects in the developers workbench (depending on whether the post is the first in a thread or not), the "Body" field in both objects always shows the above post as "@Bob Jones thanks for all the help you gave to @Debbie Johnson yesterday!  I'll make sure that @John Smith follows up with you guys tomorrow."

It appears that, when it gets saved to the database, it takes off the brackets.  But if I were to save either version of that post directly to salesforce using APEX (with or without the brackets), it somehow breaks the feature that allows the various users profiles (Bobs, Debbies, and Johns) to pop up when you mouse over their user hashtag.

So what I'm trying to figure out (with not much luck) is, how does the system store or create the relationship between the user hashtags in a message, and the users whom those hashtags reference?  My end goal is to be able to insert chatter posts via apex where I can add the @[User] hashtags and those users will actually have those posts show up in their chatter feeds.

I'm trying to figure out how to write a SOQL query to display the newest opportunity associated with every account, using the MIN() SOQL aggregate function.  Unfortunately, I can't seem to wrap my head around how to structure this since aggregate queries only let you include the field that you're grouping by and the field you're aggregating [Example: AccountId, MIN(CreatedDate) from Opportunity], however I also need to know the Id of each resulting opportunity so that I can utilize it in the trigger.  How would I need to structure the query so that I can also extract the opportunity ID?  Thanks!

I have a regular old PDF file on my desktop, and that same PDF file is attached to a record in Salesforce.  Now, when I change the PDF's extension on my computer to ".txt", I can then open it and read the texttual data that makes up the file.  I need to extract some data at the beginning of the ".txt" version of the file that details how many pages the PDF consists of, but I need to do this for many PDF files that are already in Salesforce.

I discovered the "String pdf = System.EncodingUtil.base64Encode(a.Body)" method, which apparently converts the base64 blob representation of the file into an unencoded string... but when I looked at the actual output, I realized that it was totally different compared to the ".txt" version of the PDF on my desktop.  It seems that I'm not encoding/decoding the attachment Body blob to the correct format, but I'm totally clueless as to what to convert it to, or what method I would need to use to convert it.

Does anyone have any ideas as to how I would convert the PDF data to whatever format it gets converted to when I just change the extension on my computer and view it in notepad?

Thanks!


Since programming in APEX, I've learned to use maps (as opposed to nested FOR loops) on pretty much everything.  But there's one scenario where I've never been able to figure out a "map" based solution and I wanted to get feedback from some of you more experience gurus about how you would approcah the following problem and see if I'm going about this situation in totally the wrong way.

 

So the problem occurs when I'm dealing with multiple *dynamic* filters in a given query.  Here's a real life example I'm dealing with right now...

 

I'm currently working on an insurance companies system where every time a doctor authorizes a patient to receive treatment but *doesn't* fax in the patents records along with the authorization, I need to query the database to look for past medical records for that patient where the patient ID (on the faxed authorization) matches the patient ID in the database, and the doctor ID on the authorization, matches the doctor ID in the database, and the number of times medicated per day, is a number that's greater than or equal to the number of times medicated on the patient record in the database.

 

In other words, unlike most situations where you'd just say "[select ID, Patient__c, Doctor__c, Times_Treated_Daily__c from Records__c where Patient__c IN: patientsWithRecords.keySet()]", the filters in this case are multiple, and different for every record being queried.  So (and PLEASE correct me if I'm wrong) if I wrote "select Id, Patient__c, Doctor__c, Times_Treated_Daily__c from Records__c where Patient__c IN: patientsWithRecords.keySet() and Doctor__c IN: doctorsWithRecords.keySet() and Times_Treated_Daily__c IN: (or >= ?) timesTreatedDaily.keySet()" (essentially doing a FOR loop to extract my filters into individual keysets ahead of time), the resulting query would be useless because a patient could have multiple matching doctors, a doctor can have multiple matching patients, and the times treated could be grater or less than anyone in the keyset.  So simply throwing the 3 filters that I need to query against (Patient, Doctor, and Times Treated Daily) into 3 maps/keysets and querying against it, won't necessarily return records that I could bind with because the "IN:" part of the query means that records could easily "mix and match" with a variety of doctors, patients, and times treated daily.

 

As a result, I'll make the 3 keySets, but then I'll still iterate through the records to do the final matching since I feel like there's no way to know if record X is actually the patient, doctor and times treated daily for the specific record I'm querying for.  Am I going about this in a totally wrong way and there's actually a way simpler way to do this?  Or do maps automatically somehow compensate for this when you map multiple variables?  Or is there a way to write your SOQL in order to account for multiple variables like that?  Or are nested FOR loops basically the only way?

 

I'm so curious to know how other people would tackle this problem.  Any ideas or experiences with it would be hugely apprecited.  Thanks!

In the standard salesforce view, you can use URL variables to populate certain list views on an tab.  For example, if you wanted to populate a certain list view on the Account, you'd set the URL to be "/001?fcf={List View Salesforce ID}.  As most on here know, you can use URL variables to select and prepopulate all kinds of things on list views and on records.

 

Then there's the standard Salesforce Console.  The Console seems to consist of a page called "DesktopPage", which is embedded with 3 iFrame windows (a list view, a main view, and a mini view).  Unfortunately, unlike the normal tab views, I can't seem to make the console do ANYTHING using URL variables.  Specifically, I'm trying to change the Tab/Object dropdown list to a specific object, and change the List View dropdown to a specific record.

 

Does anyone know of any URL variables or (if not URL variables) some kind of a way to accomplish the act of selecting the dropdowns you want when first opening the console?  If not, does anyone know of a way to execute a javascript "Mass Action" console button, or some other way to execute javascript on the console when the page first loads?

 

Any ideas or thoughts at all would be hugely appreciated.

Hi I am testing my triggers and getting problems to write test method for triggers as i am new to test methods. Here is my trigger. the problem that i facing is due to three different objects are used in my trigger. Please review this code for trigger that i wrote. Thanks in advance.

Trigger Code:

 

 trigger RiskConvInsert on JunctionRiskRiskSearch__c (after insert)
  {
          List<JunctionRiskSearchConvJunc__c> juncRRSCJ = new List<JunctionRiskSearchConvJunc__c>();
          for(JunctionRiskRiskSearch__c jrsc: Trigger.New)
          {
              List<Risk_Conversation__c> riskConv = [Select Id from Risk_Conversation__c where Risk_Search__c =: jrsc.Risk_Searches__c];
              for(Risk_Conversation__c riskConvRec: riskConv)
              {
                  JunctionRiskSearchConvJunc__c junRec = new JunctionRiskSearchConvJunc__c();
                  junRec.Risk_Conversations__c = riskConvRec.Id;
                  junRec.JunctionRiskSearch__c = jrsc.Id;
                  juncRRSCJ.add(junRec);
              }
              insert juncRRSCJ;
          }
      }

Is it possible to use a trigger to create a note on a object? have a text field value that I need to populate within Notes & Attachments on custom object. Any help is greatly appreciated.

When you create a custom button that pre-populates various fields with values, you have to specify the salesforce record ID of the field itself in your button parameters and then put "=" (equals), and then follow that up with your merge field to specify the value of that parameter.

 

Normally I get the record ID by just using Google Chrome, right clicking on the field while in Edit view, clicking "Inspect Element" (which gives me the salesforce ID) and then pasting that ID in my button code as the parameter needing to be populated.  I know that other people go a longer route by going to the object in question, clicking on the field name itself, and copying the salesforce ID from the URL (after the "salesforce.com/" part) to extract the custom field salesforce ID.

 

Both of these methods seem rediculously inefficient.  More importantly though, you're hard-coding the field ID into the button itself.  That means, if your company ever moves orgs, OR if you're creating a packaged app, your button will essentially "break" once it's installed in a new org, because the field ID's in your button parameters will no longer match the ID's that salesforce assignes to those fields once you install that package somewhere else.

 

So my question is this... is there some special trick, either using the "URLFOR" function or something else (formula functon, action, etc), that allows you to dynamically generate the salesforce ID of a field that you need to include in your parameters?

 

Essentially, it would allow your buttons to look something like the following (this example would be a list button for Contacts, placed on the Account page layout):

 

{!URLFOR($Action.Contact.New,Account.Id,[FIELDID($ObjectType.Contact,"Contact_Status__c")="New",retURL=Account.Id],true)}

 

So in the above example, I invented a functon called "FIELDID", which takes the Sobject type and API name of the field on that object, does a DescribeSobject() call in the background, and spits out the salesforce ID of that particular field, as opposed to hard coding it perminantly.  No hunting around for salesforce ID's, no hacks, just using the tools available in the Custom Button section.

 

So... that being said, is there some way to do pretty much that, using the button functions available to salesforce users?  If not, then what is the "official" way that Salesforce recommends you use to go about extracting field ID's for the parameters you use in your custom buttons?

I have a field OpenedTaskDate__c on Task  this is date field.

i should need to display this date on contact field (TaskTestDate__c). so i have writtened a trigger like this

trigger updateTrig on Contact (before insert,after insert , before update) {
Task T =new Task();
for(contact c:Trigger.new)
c.TaskTestDate__c= t.OpenedTaskDate__c;


but it was not displaying the task field value on contact field.

I've created a trigger to copy field value "Status" (which is picklist) from "Opportunity Products" to "Opportunities". Here is what i came up to:

 

trigger UpdateStatus on OpportunityLineItem (after insert, after update) {

    List<Opportunity> oppp = new List<Opportunity>();

    for (OpportunityLineItem oppLnItem : trigger.new)
    {  
        
        
                
        oppp.add (new Opportunity (Id=oppLnItem.Opportunity_Id__c, Status__c=oppLnItem.Status__c));

        update oppp;
         
        
    } 
    }

 

Not sure if it works, but what I DO know is that i have absolutely no idea how to create a test class for this trigger :(((. Can you help? All the things I've googled about test classes seem so complicated, and i just cant find my way around.

  • September 14, 2013
  • Like
  • 0

Hi,

 

Document generated from Third party (other than salesforce) is saved under 'Notes & Attachments' in Opportunity.

When the saved file is viewed, dark grey line is added below the image which making the image blurred.

 

Can anyone please help me in resolving this issue.

 

Thanks in advance.

 

with sharing with out sharing, Which is the default in Apex class?????????

 

please help me....

  • September 13, 2013
  • Like
  • 0

I have an extremely basic trigger that is designed to delete any task with a blank subject when it's created:

 

trigger deleteBlankSubjects on Task (after insert){

  list<Task> records = trigger.new;
  list<Task> deletable = new list<Task>();
		
    for(Task t : records){
      if(t.Subject == null || isBlank(t.Subject)){
        deletable.add(t);					
      }
    }
  delete deletable;		
}

 

For some reason though, whenever I write out the isBlank() method, I get the error, "Save error: Method does not exist or incorrect signature: isBlank(String)".  

 

I've tried writing it a bunch of different ways now, and every time I get the same error.  What's worse, is that I can't seem to find any examples of people using the APEX .isBlank() method on google (where I usually turn when I'm stuck), even though the APEX Handbook says it's perfectly allowable.  What am I doing wrong here???  Totally confused.

 

I'm using Eclipse if it's of any help.  Any insight from any guru's out there would be HUGELY appreciated.

As many of you have discovered, our developer community is awesome. The wealth of knowledge here is phenomenal. This is an all volunteer community and people who take the time to help and post answers do so totally on their own initiative. With that said when someone provides the right answer to your question please take the time to mark their answer as the accepted solution. Also give them a kudos if they've really gone the extra mile to help out. Show some love ;)