7 Replies Latest reply on Sep 10, 2018 5:53 PM by Sanford Whiteman

    Which opportunity does an opp-email scripting token pull from?

    Erin Casner

      Hi all,

      So we know that a person can have more than one opportunity, and that not everyone has the same amount of opportunities. When creating a velocity scripting token to pull from the opportunity, how do I tell it to pull from the most recent opportunity?

      - I am trying to pull the opportunity owner's name and information for the signature of an email.

       

      $OpportunityList.get(0).Oppty_Owner_License__c
      

       

      I believe the .get(0) references the opportunity but which one!?

      Any help is much appreciated!!

        • Re: Which opportunity does an opp-email scripting token pull from?
          Sanford Whiteman
          $someList.get(0) 
          

           

          is the same as

           

          $someList[0]
          

           

          They both get the first element in the list, in insertion order. (List indexes start from 0.)

           

          If you want to get the first element in the list according to some other criteria, first sort the list, for example sorting it by a date property in descending order:

           

          #set( $sortedList = $sorter.sort($someList, "createdAt:desc") )
          

           

          Now

           

          $sortedList[0]
          

           

          will be the "latest" element.

           

          Note you need to have createdAt checked off in the tree in Script Editor in order to sort by that property.

            • Re: Which opportunity does an opp-email scripting token pull from?
              Erin Casner

              Thanks Sanford,

               

              I took what you said and also incorporated learnings from your blog https://blog.teknkl.com/sorting-objects-and-lists-in-velocity/  to sort with more than one element.

               

              Here is my final version for others to learn from:

               

              #set( $sortedList = $sorter.sort( $OpportunityList,["IsClosed:asc","ExternalCreatedDate:desc"]))
              $OpportunityList[0].Opportunity_Owner_Mobile_Phone__c
              
              
                • Re: Which opportunity does an opp-email scripting token pull from?
                  Erin Casner

                  Sanford,

                  How can I wrap the last statement in the .isEmpty clause? $OpportunityList[0].Opportunity_Owner_Mobile_Phone__c is populating in the email when the field is bland. I can't seem to find the right statement.

                  #if( !$OpportunityList[0].Opportunity_Owner_Mobile_Phone__c.isEmpty() )
                  #set( $sortedList = $sorter.sort( $OpportunityList,["IsClosed:asc","ExternalCreatedDate:desc"]))
                  $OpportunityList[0].Opportunity_Owner_Mobile_Phone__c
                  #end
                  
                  
                    • Re: Which opportunity does an opp-email scripting token pull from?
                      Sanford Whiteman

                      The logic there doesn't make sense.

                       

                      You want to sort the list no matter what.

                       

                      Then check if the property empty before outputting. And you need to keep targeting the sorted list, not the original list!

                       

                      #set( $sortedList = $sorter.sort($OpportunityList, ["IsClosed:asc","ExternalCreatedDate:desc"]) )
                      #if( !$sortedList[0].Opportunity_Owner_Mobile_Phone__c.isEmpty() )   
                      ${sortedList[0].Opportunity_Owner_Mobile_Phone__c}
                      #end
                      

                       

                      Of course if you just want to save the extra space if it's empty, use silent notation:

                       

                      #set( $sortedList = $sorter.sort( $OpportunityList,["IsClosed:asc","ExternalCreatedDate:desc"]) )
                      $!{sortedList[0].Opportunity_Owner_Mobile_Phone__c}##
                      
                        • Re: Which opportunity does an opp-email scripting token pull from?
                          Erin Casner

                          Hey Sanford,

                          How do you sort the list based on a Boolean field? I want to sort so the opportunity that "closed"=false and "created date" descending is at the top.

                           

                          Your help is much appreciated!

                            • Re: Which opportunity does an opp-email scripting token pull from?
                              Sanford Whiteman

                              How do you sort the list based on a Boolean field? I want to sort so the opportunity that "closed"=false and "created date" descending is at the top.

                              This is actually 3 different questions, though you probably don't realize it.  The questions all happen to have the same answer, but that's largely a coincidence!

                               

                              The questions are:

                               

                              1. How do you sort objects on a Person Boolean field that's exported into the Velocity context as an empty String "" or numeric String "1"?
                              2. How do you sort objects on an Opportunity Boolean field that's exported into the Velocity context as a numeric String "0" or numeric String "1"?
                              3. How do you sort objects on a Custom Object Boolean field that's exported into the Velocity context as a real Boolean true or false?

                               

                              The answer for every case happens to be the same, since the explicitly defined order of all the possible representations always ends up putting the false one first:

                               

                              Boolean false representing original false value, first

                               

                              Boolean true representing original true value, second

                               

                              or

                               

                              Empty String "" representing original false value, first

                               

                              String "1" representing original true value, second

                              or

                               

                              String "0" representing original false value, first

                               

                              String "1" for original true value, second

                               

                              So to sort by the property BooleanOrBooleanLikeString, you do:

                               

                                $sorter.sort( $myList, "BooleanOrBooleanLikeString" )
                              

                               

                              Since ascending order is the default, this is the same as the explicit :asc notation:

                               

                                $sorter.sort( $myList, "BooleanOrBooleanLikeString:asc" )
                              

                               

                              But realize that is in fact coincidental that Velocity (actually Java) happens to sort all 3 sorts of falsy values before all 3 sorts of truthy values!

                               

                              While sorting the empty string "" before the numeric string "1" isn't exactly surprising, you should still think of it as something to learn as opposed to something to expect in any language. Yes, lexicographical sorting puts empty strings before non-empty strings. And lexicographical sorting always puts ASCII/Unicode 48 , the character "0", before ASCII/Unicode 49, the character "1". Yet there's no specific reason that you should expect Velocity's SortTool.sort to use lexicographical sorting (well, other than that it's the most common form of sorting found in programming). The only way to actually know what it does is to look at the docs.  And in fact, SortTool.sort doesn't do strict lex sorting -- which would sort ["a","B","c","D"] as ["B","D","a","c"] per the ASCII table -- but rather uses a tweaked version that ignores the case of letters.  This tweak doesn't affect the sorting of "0" and "1" but my point is you have to set expectations first based on the docs, then if there's a doc bug you can work from there.

                               

                              Similarly, when sorting real Booleans (true or false) Velocity defers entirely to Java's rule for sorting Booleans. Which happens to be that false sorts before true in ascending order. But this doesn't come from the real world in a specific, guessable way -- the Java rule could just as well be the other way around.  It's an arbitrary choice (but well-documented by the people who created Java) and it happens to go along with the way the Boolean-like Strings get sorted. And not to get too deep in the weeds, but this last thing doesn't extrapolate to other languages: in JavaScript, Booleans false and true are sorted by first converting them to Strings "false" and "true" and then doing a lexicographical sort -- which happens to end up with false before true but only because "f" alphabetizes before "t"!  Again, it's coincidence that the false values end up first. There's no global rule that false/falsy is smaller than true/truthy.

                               

                              Erin