• mgodsey
  • NEWBIE
  • 215 Points
  • Member since 2012

  • Chatter
    Feed
  • 5
    Best Answers
  • 4
    Likes Received
  • 0
    Likes Given
  • 69
    Questions
  • 66
    Replies
I've right justified a numerical column in an apex:pageblocktable, but it's right next to a text column that is left-justified. I want to add a bit of extra spacing between the two columns, but nothing seems to be working. Below are two things I've tried (I've only included the relevant markup) - can anyone please point out where I'm going wrong?

Thanks!
 
        .number{
            text-align: right;
        }
        .ruiColumnWidth{
            width: 15%;
        }
        .ruiMonthEven{
            background: #F5F5F5;
        }
        .ruiMonthOdd{
        }

<apex:pageBlockTable value="{!ruiWrappers}" var="wrapper" cellpadding="5">
     <apex:column headerValue="Amount" styleClass="number ruiColumnWidth {!IF(wrapper.monthType == 'Even', 'ruiMonthEven', 'ruiMonthOdd')}" headerClass="number">
          <apex:outputField value="{!wrapper.rui.RuiPipeline__c}"/>
     </apex:column>
     <apex:column headerValue="Probability" styleClass="ruiColumnWidth {!IF(wrapper.monthType == 'Even', 'ruiMonthEven', 'ruiMonthOdd')}">
            <apex:outputText value="{!wrapper.ruiProbability}"/>
     </apex:column>
</apex:pageBlockTable>
.number{
    text-align: right;
    padding-right: 5px;
}
.ruiColumnWidth{
    width: 15%;
}
.ruiMonthEven{
    background: #F5F5F5;
}
.ruiMonthOdd{
}

<apex:pageBlockTable value="{!ruiWrappers}" var="wrapper">
     <apex:column headerValue="Amount" styleClass="number ruiColumnWidth {!IF(wrapper.monthType == 'Even', 'ruiMonthEven', 'ruiMonthOdd')}" headerClass="number">
          <apex:outputField value="{!wrapper.rui.RuiPipeline__c}"/>
     </apex:column>
     <apex:column headerValue="Probability" styleClass="ruiColumnWidth {!IF(wrapper.monthType == 'Even', 'ruiMonthEven', 'ruiMonthOdd')}">
            <apex:outputText value="{!wrapper.ruiProbability}"/>
     </apex:column>
</apex:pageBlockTable>

User-added image
 
I have a project that includes the requirement for the following process: a user clicks a salesforce button, and under certain conditions, a pop-up window appears. On that window should be two, dependent picklist fields. Once they complete those fields and click "Ok", the values in those fields should be mapped to the corresponding fields in Salesforce. If they click that button again under the same conditions, the values they have already selected should default.

I know this is possible using a custom button which re-directs the user to a Visualforce page (so not quite a pop-up) and uses apex:inputFields. However, does anyone know if this would be possible using a custom button that executes JavaScript on click? I'm just not sure if it would be too much overkill to build the dependent picklists on this pop-up page or if there is an easy way to grab the information from the Salesforce fields.

I'm not really looking for the code here, just general thoughs on if this approach is even possible/worth considering.

Thanks!
I have a custom clone button on an Opportunity visualforce page that when clicked, should 1) confirm that they want to clone the Opportunity 2) check if certain records in the system exist, 3) if they do exist, have the user again click ok to confirm that they want to clone or cancel 3) if the user clicked ok, clone the Opportunity. I tried to use javascript remoting for the first time, and I think it's causing my action method to not fire.

If I click the 'Copy Opportunity without Media Plan' button, both confirmation pop-up alerts are displayed to the user, but nothing happens when they click 'OK.' If I click the 'Copy Opportunity without Media Plan 2' button, which does not have the remote action, the first confirmation pop-up is displayed, and when they click 'OK' the Opportunity clones.

Will javascript remoting not work in this scenario? It's my first time using it, so I don't understand it fully. Do I need to use action:function instead?

Thanks for the help!

Snippet Visualforce Page:
<script type="text/javascript">
        //confirm that they want to clone the Opportuntiy
        function confirmOppOnlyClone(){
            return confirm('Do you want to copy this Opportunity only?');
        }

        //check if other opportunities have been cloned from this one
        function duplicateOppsCheck(){
            var oppId = "{!opportunity.Id}";
            Visualforce.remoting.Manager.invokeAction(
                '{!$RemoteAction.OpportunityExtension.duplicateOppsCheck}',
                oppId, function(result, event) {
                    if(event.status){
                        if (result != null){
                            return confirm(result);
                        }
                    }
                }
            );
        }
    </script>

<apex:form >
    <apex:sectionHeader subtitle="{!opportunity.Name}" title="Opportunity"/>
    <apex:pageMessages />
    <apex:pageBlock >
        <apex:pageBlockButtons >

            <apex:commandButton value="Copy Opportunity without Media Plan" title="Click this to copy the Opportunity only" action="{!cloneRecord}" onClick="if(!confirmOppOnlyClone()) return false;if(!duplicateOppsCheck()) return false"/>

            <apex:commandButton value="Copy Opportunity without Media Plan 2" title="Click this to copy the Opportunity only" action="{!cloneRecord}" onClick="if(!confirmOppOnlyClone()) return false;"/>

Snippet of Controller Extension: 
@RemoteAction
    public static String duplicateOppsCheck (String opportunityId){


        String confirmMessage = 'There is an existing Opportunity that has been copied from this Opportunity. Please confirm that it is not a duplicate.\n\n';
        Boolean returnConfirmMessage = false;

        //if there are any existing opportunities that were copied from the current one, add their names and urls to the confirmation message
        for(Opportunity opp : [SELECT Id, Name FROM Opportunity WHERE ClonedFrom__c =: opportunityId]){
            confirmMessage += 'Name: '+opp.Name +'\n';
            confirmMessage += System.URL.getSalesforceBaseURL().toExternalForm()+'/'+opp.id + '\n\n';
            returnConfirmMessage = true;
        }

        if(returnConfirmMessage){
            return confirmMessage;
        }

        return null;
    }

 
I'm having a lot of issues with the developer console when checking test coverage, and I don't know if it is a bug with the console or something wrong with my code. 

1) I run the test in the developer console. The Test Run log is not actually showing up unless I completely close the developer console and then re-open it.
2) After running the test (it succeeds), in the overall code coverage box,  the class says 100%
3) I double click on the class name in the overall code coverage box and it goes to 0%
4) When I look at the drop down of tests for that class, it shows me the following:

All Tests 0%
Test_QuoteLineITemEntryExtension.testSaveMethods 52%
Test_QuoteLineItemEntryExtension.testControllerWithParameters 36%

Why would it be showing 0% for all tests if individual methods provide coverage? Also, there is no red/blue highlighting in the class to show me what is or is not covered.

Has anyone run into this before? It's driving me crazy! Would be happy to post my test class if that helps. Thanks!
Hi - is it possible to top align a cell in an apex:pageBlockTable, or am I going to have to try and build my own html table instead of using the pageBlockTable?
I'm writing a unit test where I need to assign a territory to a test user. However, DML is not allowed on the UserTerritory object. Is my only option to query for an actual user in the database?
I want to have a date field on a visualforce page that does use a calendar widget, but does not include the current date link adjacent to the input field. I tried adding the showdatePicker="false" attribute, but this gets rid of BOTH the calendar widget and current date link.

<apex:inputField value="{!s.CampaignSTARTDate__c}" style="width:70px" required="true" showdatePicker="false" />

When I then added the type="date" attribute, I got the following error message:
Attribute 'type' on component <apex:inputField> in '/apex/quoteLineItemEntryOption4' requires HTML docType version 5.0 or higher in quoteLineItemEntryOption4 at line 183 column 138

I'm not sure of the implications of changing the docType to version 5.0 and I don't like the way the field looks with that type, so I'd prefer not to do it this way. Does anyone know any other workarounds?

Thanks!
I'm trying to build a Visualforce page where as soon as a picklist value is selected/changed, the value is passed to a method in the controller to be used in a dynamic SOQL query. However, I'm having trouble getting the value passed to the controller. I've used this blog post as a starting point, http://blog.jeffdouglas.com/2010/07/13/building-a-dynamic-search-page-in-visualforce/, but I need to use apex:inputField instead because I need to keep the dependent pick lists intact.

When I change the value of TestInventoryType__c I get the alert that the doSearch() function is called, but my second alert comes back null. I would really appreciate if someone could tell me why this is coming back null, and if there is a better way to do this. How could I go about binding the value selected in the Inventory Type picklist to a property in the controller? I need all of this to happen when the picklist value changes without hitting any sort of command button. Thank you!

Here is a snippet of the VF page. The two most relevant lines are bolded:

  <apex:pageBlock title="MANAGE MEDIA PLAN FLIGHTS" mode="edit">


  <table width="100%" border="0">

  <tr>

    <td width="275" valign="top">

      <!-------This is the Search by picklist section-------------------------->

      <apex:pageBlock title="Search" mode="edit" id="criteria">



      <script type="text/javascript">

      function doSearch() {

        alert('doSearch function');

        alert(document.getElementById("creativeFamily")); //THIS COME BACK NULL

            searchServer(

            document.getElementById("creativeFamily").options[document.getElementById("creativeFamily").selectedIndex].value,

            document.getElementById("creativeTypes").options[document.getElementById("creativeTypes").selectedIndex].value,

            document.getElementById("pricingModel").options[document.getElementById("pricingModel").selectedIndex].value,

            document.getElementById("targetingOption").options[document.getElementById("targetingOption").selectedIndex].value

        );

       
      }

      </script>

     <apex:actionFunction name="searchServer" action="{!runSearch}" rerender="results,debug,errors">

          <apex:param name="creativeFamily" value="" />

          <apex:param name="creativeTypes" value="" />

          <apex:param name="pricingModel" value="" />

          <apex:param name="targetingOption" value="" />

      </apex:actionFunction>


     <apex:pageBlockSection columns="1">

         <apex:inputField value="{!Quote.TestInventoryType__c}" id="creativeFamily" onchange="doSearch();"/>
I am trying to use Jeff Douglas' post about dynamic searching and use picklists to search, but I can't get the page to re-render after I have made a selection in the picklist. I've looked through various other posts about this and haven't been able to find anything that works for me. Does anyone see what is going wrong? I think it has to do with doSearch() function not actually being called when changing a picklist value.

Any feedback is much appreciated, thank you!!

Here is my controller class:
public with sharing class quoteLineItemEntryExtensionOption4 {
   
    public Quote theQuote {get;set;}
    public Pricebook2 theBook {get;set;}
   
    private Boolean forcePricebookSelection = false;
    //the soql without the order and limit
    private String soql {get;set;}
   
    //the collection of products to display
    public List<priceBookEntry> availableProducts {get;set;}
   
    //the current sort direction. defaults to asc
    public String sortDir{
        get{
            if (sortDir == null){
                sortDir = 'asc';
            }
            return sortDir;
        }
        set;          
    }
   
    // the current field to sort by. defaults to Quote name
    public String sortField {
        get{
            if (sortField == null){
                sortField = 'Quote';
            }
            return sortField;
        }
        set;
    }
   
    // format the soql for display on the visualforce page
    public String debugSoql {
        get{
            return soql /*+ ' order by ' + sortField + ' ' + sortDir + ' limit 20'*/;
        }
        set;
    }
   
    // init the controller and display some sample data when the page loads
    public quoteLineItemEntryExtensionOption4(ApexPages.StandardController controller){
   
        //get information about the Quote being worked on
        theQuote = database.query('select Id, Pricebook2Id,Pricebook2.Name,CurrencyISOCode from Quote where Id = \'' + controller.getRecord().Id + '\' limit 1');
       
        //Check if the Opp has a pricebook associated yet
        if(theQuote.Pricebook2Id == null){
            Pricebook2[] activepbs = [select ID, Name FROM Pricebook2 WHERE isActive = true limit 2];
            if(activepbs.size() == 2){
                forcePriceBookSelection = true;
                theBook = new Pricebook2();
            } else {
                theBook = activepbs[0];
            }
        }
        else{
            theBook = theQuote.Pricebook2;       
        }
        //this soql just shows the initial results when page is loaded
        soql = 'select Id, Pricebook2Id, IsActive, Product2.Name, Product2.Segment__c, Product2.CreativeType__c, Product2.CreativeFamily__c, Product2.PricingModel__c, Product2.TargetingOptions__c, Product2.IsActive, Product2.Description, UnitPrice from PricebookEntry where IsActive=true and CurrencyISOCode = \'' + theBook.CurrencyISOCode + '\' and Product2.CreativeFamily__c != null and Pricebook2Id = \'' + theBook.Id + '\'';
        runQuery();
    }
   
    // toggles the sorting of query from asc<-->desc
    public void toggleSort() {
        // simply toggle the direction
        sortDir = sortDir.equals('asc') ? 'desc' : 'asc';
        // run the query again
        runQuery();
    }
   
    // runs the actual query
    public void runQuery() {
        try {
            availableProducts = Database.query(soql  /*+ ' order by ' + sortField + ' ' + sortDir + ' limit 20'*/);
        } catch (Exception e) {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Ooops! There are no results for this search'));
        }
    }
   
    // runs the search with parameters passed via Javascript
    public PageReference runSearch() { 

        String creativeFamily = Apexpages.currentPage().getParameters().get('creativeFamily');
        String creativeTypes = Apexpages.currentPage().getParameters().get('creativeTypes');
        String pricingModel = Apexpages.currentPage().getParameters().get('pricingModel');
        String targetingOptions = Apexpages.currentPage().getParameters().get('targetingOptions');

        soql = 'select Id, Pricebook2Id, IsActive, Product2.Name, Product2.Segment__c, Product2.CreativeType__c, Product2.CreativeFamily__c, Product2.PricingModel__c, Product2.TargetingOptions__c, Product2.IsActive, Product2.Description, UnitPrice from PricebookEntry where IsActive=true and CurrencyISOCode = \'' + theBook.CurrencyISOCode + '\' and Pricebook2Id = \'' + theBook.Id + '\'';
        if (!creativeFamily.equals(''))
            soql += ' and Product2.CreativeFamily__c LIKE (\''+creativeFamily+'\')';
        if (!creativeTypes.equals(''))
            soql += ' and Product2.CreativeType__c LIKE (\''+creativeTypes+'\')';
        if (!pricingModel.equals(''))
            soql += ' and Product2.pricingModel__c LIKE (\''+pricingModel+'\')'; 
        if (!targetingOptions.equals(''))
            soql += ' and Product2.TargetingOptions__c LIKE (\''+targetingOptions+'\')';

        // run the query again
        System.debug('[MF] running the query from runSearch method' + soql);
        runQuery();

        return null;
    }
   
    //use apex describe to build the picklist values for Creative Family
    public List<String> creativeFamily{
        get{
            if(creativeFamily == null){
                creativeFamily = new List<String>();
                Schema.DescribeFieldResult field = Product2.CreativeFamily__c.getDescribe();
               
                for(Schema.Picklistentry f : field.getPickListValues()){
                    creativeFamily.add(f.getLabel());
                }               
            }
            return creativeFamily;
        }
        set;
    }
   
    //use apex describe to build the picklist values for Creative Type
    public List<String> creativeType{
        get{
            if(creativeType == null){
                creativeType = new List<String>();
                Schema.DescribeFieldResult field = Product2.creativeType__c.getDescribe();
               
                for(Schema.Picklistentry f : field.getPickListValues()){
                    creativeType.add(f.getLabel());
                }               
            }
            return creativeType;
        }
        set;
    }
   
    //use apex describe to build the picklist values for Pricing Model
    public List<String> pricingModel{
        get{
            if(pricingModel == null){
                pricingModel = new List<String>();
                Schema.DescribeFieldResult field = Product2.pricingModel__c.getDescribe();
               
                for(Schema.Picklistentry f : field.getPickListValues()){
                    pricingModel.add(f.getLabel());
                }               
            }
            return pricingModel;
        }
        set;
    }
   
    //use apex describe to build the picklist values
    public List<String> targetingOptions{
        get{
            if(targetingOptions == null){
                targetingOptions = new List<String>();
                Schema.DescribeFieldResult field = Product2.TargetingOptions__c.getDescribe();
               
                for(Schema.PicklistEntry f : field.getPickListValues()){
                    targetingOptions.add(f.getLabel());
                }
            }
            return targetingOptions;
        }
        set;
    }

}

Here is my VF page:
<apex:page standardController="Quote" extensions="quoteLineItemEntryExtensionOption4" sidebar="false">

  <apex:form >
  <apex:pageMessages id="errors" />

  <apex:pageBlock title="MANAGE MEDIA PLAN FLIGHTS" mode="edit">

  <table width="100%" border="0">
  <tr> 
    <td width="200" valign="top">

      <apex:pageBlock title="Search" mode="edit" id="criteria">

      <script type="text/javascript">
      function doSearch() {
        searchServer(
          document.getElementById("creativeFamily").options[document.getElementById("creativeFamily").selectedIndex.]value,
          document.getElementById("creativeTypes").options[document.getElementById("creativeTypes").selectedIndex.]value,
          document.getElementById("pricingModel").options[document.getElementById("pricingModel").selectedIndex.]value,
          document.getElementById("targetingOptions").options[document.getElementById("targetingOptions").selectedIndex].value
          );
      }
      </script>

      <apex:actionFunction name="searchServer" action="{!runSearch}" rerender="results,debug,errors">
          <apex:param name="creativeFamily" value="" />
          <apex:param name="creativeTypes" value="" />
          <apex:param name="pricingModel" value="" />
          <apex:param name="targetingOptions" value="" />
      </apex:actionFunction>

      <table cellpadding="2" cellspacing="2">
      <tr>
        <td style="font-weight:bold;">Creative Family<br/>
          <select id ="creativeFamily" onchange="doSearch();">
            <option value=""></option>
            <apex:repeat value="{!creativeFamily}" var="cFamily">
              <option value="{!cFamily}">{!cFamily}</option>
            </apex:repeat>
          </select>       
        </td>
      </tr>
      <tr>
        <td style="font-weight:bold;">Creative Type<br/>
          <select id ="creativeType" onchange="doSearch();">
            <option value=""></option>
            <apex:repeat value="{!creativeType}" var="cType">
              <option value="{!cType}">{!cType}</option>
            </apex:repeat>
          </select>       
        </td>
      </tr>
      <tr>
        <td style="font-weight:bold;">Pricing Model<br/>
          <select id ="Pricing Model" onchange="doSearch();">
            <option value=""></option>
            <apex:repeat value="{!pricingModel}" var="pm">
              <option value="{!pm}">{!pm}</option>
            </apex:repeat>
          </select>       
        </td>
      </tr>
      <tr>
        <td style="font-weight:bold;">Targeting Options<br/>
          <select id="targetingOptions" onchange="doSearch();">
            <option value=""></option>
            <apex:repeat value="{!targetingOptions}" var="targeting">
              <option value="{!targeting}">{!targeting}</option>
            </apex:repeat>
          </select>
        </td>
      </tr>
      </table>

      </apex:pageBlock>

    </td>
    <td valign="top">

    <apex:pageBlock title="Available Products To Add" mode="edit" id="results">

        <apex:pageBlockTable value="{!availableProducts}" var="product">
            <apex:column >
                <apex:facet name="header">
                    <apex:commandLink value="Product Name" action="{!toggleSort}" reRender="results,debug">
                        <apex:param name="sortfield" value="Product2.Name" assignTo="{!sortField}"/>
                    </apex:commandLink>
                </apex:facet>
                <apex:outputField value="{!product.Product2.Name}"/>
            </apex:column>

            <apex:column >
                <apex:facet name="header">
                    <apex:commandLink value="Creative Family" action="{!toggleSort}" rerender="results,debug">
                        <apex:param name="sortField" value="Product2.creativeFamily__c" assignTo="{!sortField}"/>
                    </apex:commandLink>
                </apex:facet>
                <apex:outputField value="{!product.Product2.CreativeFamily__c}"/>
            </apex:column>

            <apex:column >
                <apex:facet name="header">
                    <apex:commandLink value="Creative Type" action="{!toggleSort}" rerender="results,debug">
                        <apex:param name="sortField" value="Product2.creativeType__c" assignTo="{!sortField}"/>
                    </apex:commandLink>
                </apex:facet>
                <apex:outputField value="{!product.Product2.CreativeType__c}"/>
            </apex:column>

            <apex:column >
                <apex:facet name="header">
                    <apex:commandLink value="Pricing Model" action="{!toggleSort}" rerender="results,debug">
                        <apex:param name="sortField" value="Product2.pricingModel__c" assignTo="{!sortField}"/>
                    </apex:commandLink>
                </apex:facet>
                <apex:outputField value="{!product.Product2.PricingModel__c}"/>
            </apex:column>

            <apex:column >
                <apex:facet name="header">
                    <apex:commandLink value="Targeting Options" action="{!toggleSort}" rerender="results,debug">
                        <apex:param name="sortField" value="Product2.targetingOptions" assignTo="{!sortField}"/>
                    </apex:commandLink>
                </apex:facet>
                <apex:outputField value="{!product.Product2.TargetingOptions__c}"/>
            </apex:column>

        </apex:pageBlockTable>

    </apex:pageBlock>

    </td>
  </tr>
  </table>
 
  <apex:pageBlock title="Selected Products">
 
  </apex:pageBlock>


  <apex:pageBlock title="Debug - SOQL" id="debug">
      <apex:outputText value="{!debugSoql}" />          
  </apex:pageBlock>   

  </apex:pageBlock>

  </apex:form>

</apex:page>

I am trying to write a trigger that will create an activity when an opportunity reaches a certain stage.  I want the activity to be assigned to the owner of the opportunity and to be related to the opportunity, but when I try to assign values to the appropriate fields I get 'Field is not writeable' errors.  Here is the code with these fields commented out:

 

--------------------------------------------------------------------------------

trigger CreateActivityAfterClosedWon on Opportunity (after insert, after update) {
 
    List<Task> NewTasks = new List<Task>();
    for (Opportunity opp: Trigger.new){
        if (opp.StageName == '100 - Closed Won - Booked'){
                NewTasks.add(new Task(
                    ActivityDate = Date.today(),
                    //What = opp.Id,
                    //Owner = opp.Owner,
                    Status = 'Closed',
                    Activity_Type__c = 'Project Won',
                    Priority = 'Normal',
                    Subject = opp.Name));
        }
    }

    insert NewTasks;
}

--------------------------------------------------------------------------------------------

 

With these fields commented out, the trigger runs in the sand box and creates activities, but the activities are not related to any object and are assigned to me (because the code ran under my account).

 

Can anybody suggest a solution?


Thanks & Regards,

Jeff

I am using a standard controller extension to custom clone Opportunities. It will allow Opportunities to be cloned with their Opportunity Teams (among other objects). However, I'm having trouble getting the access level for the team member to clone as well. From looking at the community boards I know that I need to insert an OpportunityShare record as well, but that hasn't helped. Even if the team member had Read/Write access on the original Opp, on the clone they just have Read access.

 

Can anyone take a peek at my code below and let me know where I've gone wrong? Thanks!!

 

public class OpportunityCloneExtension{
     
    //Variable to hold current record
    Opportunity currentRecord;
     
    //Standard constructor method
    public OpportunityCloneExtension(ApexPages.StandardController controller){
        currentRecord = (Opportunity)controller.getRecord();
    } 
     
    public PageReference cloneRecord(){
        //Variable to hold the new record
        Opportunity newRecord;
        Savepoint sp = Database.setSavepoint();
         
        try{
            //------Cloning the Opportunity-----------
            //get all the creatable fields from the object so they can be cloned
            String oppSOQL = CSUtils.getCreatableFieldsSOQL('Opportunity',   'id=\''+currentRecord.id+'\'');
             
            //query for the current Opportunity and clone it, replacing a few field values first
            currentRecord = (Opportunity)Database.query(oppSOQL);
            newRecord = currentRecord.clone(false);
            newRecord.ApprovalStatus__c = Status.NotSubmitted;
            newRecord.Type = 'Existing Client: Campaign Renewal';
            newRecord.SalesPlanner__c = null;
            newRecord.RequestType__c = null;
            newRecord.DeliverableDueDate__c = null;
            newRecord.PORequired__c = null;
            newRecord.PONumber__c = null;
            newRecord.PrePay__c = null;
            newRecord.Campaign_Event__c = null;
            newRecord.ExistingConversionVolume__c = null;
             
            newRecord.ClonedFrom__c = currentRecord.id;
             
            insert newRecord;
          
            //--------Cloning the Opp Team Test--------
            List<OpportunityTeamMember> relatedTeamMembers = new List<OpportunityTeamMEmber>();
            for(OpportunityTeamMember tm : [SELECT OpportunityAccessLevel, OpportunityId, UserId, TeamMemberRole FROM OpportunityTeamMember WHERE OpportunityId =: CurrentRecord.id]){
                OpportunityTeamMember otm = tm.clone(false);
                otm.OpportunityID = newRecord.Id;
                relatedTeamMembers.add(otm);
            } 
            
            insert relatedTeamMembers;   
            
            List<OpportunityShare> relatedOppShare = new List<OpportunityShare>();
            for(OpportunityShare os : [SELECT OpportunityAccessLevel,OpportunityId,RowCause, UserOrGroupID FROM OpportunityShare WHERE OpportunityID =:CurrentRecord.id AND RowCause = 'Sales Team']){
                OpportunityShare nOS = os.clone(false);
                nOS.OpportunityID = newRecord.id;
                relatedOppShare.add(nOS);
                
            }
            
            insert relatedOppShare;    
           
         
        } catch(Exception e){
            Database.rollback(sp);
            ApexPages.addMessages(e);
            return null;
        }
         
        return new PageReference('/'+newRecord.id);
    }     
}

 

I have a trigger on Opportunity that updates a text field on the Opportunity called WhatChanged__c. It's comparing the values on two related Opportunities and seeing if they are different. I need to reference the Field Label in the WhatChanged__c value, and I want to make it dynamic so that if we change any field labels/api names in the future the code will automatically handle the change.

 

Here is the relevant part of trigger:

 

//continue if there are cloned Opps moving into the pending stage
    if(!pendingClonedOpps.isEmpty()){
//get all the labels for Opportunity fields and put them in a map, keyed to the field api name String objectType ='Opportunity'; Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe(); Schema.SObjectType leadSchema = schemaMap.get(objectType); Map<String, Schema.SObjectField> fieldMap = leadSchema.getDescribe().fields.getMap(); Map<String, String> fieldAPIName = new Map<String, String>(); for(String fieldName : fieldMap.keySet()){ fieldAPIName.put(fieldName, fieldMap.get(fieldName).getDescribe().getLabel()); } for(Opportunity opp : pendingClonedOpps){ //List to store all of the names of fields that have changed List<String> Changes = new List<String>(); //get the related Cloned Opportunity record Opportunity clonedFromOpp = ClonedOppIDToClonedOpp.get(opp.ClonedFrom__c); if(opp.Buyer__c != clonedFromOpp.Buyer__c){ String fieldName = 'buyer__c'; String Label = fieldAPIName.get(fieldName); String oldBuyer = clonedFromOpp.Buyer__c; Changes.add(Label+': '+oldBuyer); } opp.WhatChanged__c = CSUtils.join(Changes, ' '); }

It's working, but the part I'm not happy with is the line String fieldName = 'buyer__c'. If the API name for that field ever changes, I will need to update the fieldName variable. Is there a way to dynamically get the API name, in a similar way to how I am getting the field name? Can I create a Map that stores <Field, String>? This is my first time working with Describe.field() methods so I think I'm confusing myself!

 

Any help is much appreciated! Thanks!

I want to be able to query for all creatable fields on an object without having to hardcode each field into the SOQL query. I have a method that builds the SOQL query and it works great except for when the WHEN statement includes id in: a collection of records.

 

Here is the method:

/**
    *Returns a dynamic SOQL statement for the whole object, includes only creatable fields since we will be inserting a cloned result of this query
    */
    public static string getCreatableFieldsSOQL(String objectName, String whereClause){
        String selects = '';
        
        if(whereClause == null || whereClause == ''){
            return null;
        }
        
        //get a map of field names and field tokens
        Map<String, Schema.SObjectField> fMap = Schema.getGlobalDescribe().get(objectName.toLowerCase()).getDescribe().Fields.getMap();
        List<String> selectFields = new List<String>();
        
        if(fMap!=null){
            for(Schema.SObjectField ft : fMap.values()){ //loop through all field tokens (ft)
                Schema.DescribeFieldResult fd = ft.getDescribe(); //describe each field (fd)
                if (fd.isCreateable()){ //field is creatable
                    selectFields.add(fd.getName());
                }
            }
        }

 

Here is where I invoke the method:

String oppSOQL = CSUtils.getCreatableFieldsSOQL('Opportunity', 'id in' + clonedFromOppIDs);
        system.debug('[MF] oppSOQL: ' + oppSOQL);
        
        for(Opportunity opp : (List<Opportunity>)Database.query(oppSOQL)){
            ClonedOppIDtoClonedOpp.put(opp.id, opp);
        }

 "clonedFromOppIDs" is a set of Opportunity IDs. However, when I try to execute this code I get the error message: System.QueryException: unexpected token: '{' . This is the debug log (I removed most of the fields to make it easier to read):

 

16:56:07.493 (493363000)|USER_DEBUG|[28]|DEBUG|[MF] oppSOQL: SELECT ApprovedTerms__c,Rate_Type__c,WhatChanged__c FROM Opportunity WHERE id in{006Q000000BmT4XIAV}
16:56:07.493 (493388000)|SYSTEM_METHOD_EXIT|[28]|System.debug(ANY)
16:56:07.493 (493412000)|SYSTEM_METHOD_ENTRY|[30]|Database.query(String)
16:56:07.494 (494079000)|EXCEPTION_THROWN|[30]|System.QueryException: unexpected token: '{'

 

I've tried making the WHERE clause 'id in: ' + clonedFromOppIDs but I get the same error message. Does anyone know if there is anyway I can get around this? Or have other suggestions for how to systematically query all fields without typing each one it? Any help would be much appreciated, thank you!!

I have a VF page and Controller Extension that allows me to clone a custom object (ProposalFlight__c) record. The ProposalFlight__c record has a lookup field to another custom object, called Geo__c. Using the VF page (which overrides the custom clone button) and the Controller Extension, I am able to clone both ProposalFlight__c and Geo__c at the same time. However, I'm really struggling with creating the unit test for the controller extension.

 

VF Page:

<apex:page standardController="ProposalFlight__c" extensions="ProposalFlightCloneExtension" 
    action="{!cloneRecord}">
    <apex:pageMessages />
</apex:page>

 

Controller Extension (I've replaced the fields that are actually in the queury with (all Fields) just to make it reasier to read here):

 

public class ProposalFlightCloneExtension{
    
    //Variable to hold current record
     ProposalFlight__c currentRecord;
     
     //Standard constructor method
     public ProposalFlightCloneExtension(ApexPages.StandardController controller){
         currentRecord = (ProposalFlight__c)controller.getRecord();
     } 
     
      public PageReference cloneRecord(){
         //Variable to hold the new record
         ProposalFlight__c newRecord;
         Savepoint sp = Database.setSavepoint();
         
         try{
         
             //first clone the Geo Record
             Geo__c clonedGeo;
             
             for(Geo__c relatedGeo: [SELECT (All Fields) FROM Geo__c WHERE Id in (SELECT Geo__c FROM ProposalFlight__c WHERE id=: currentRecord.id)]){
                 Geo__c newGeo = relatedGeo.clone(false);
                 clonedGeo = newGeo;
             } 
             insert clonedGeo;
             
             //now clone the Proposal Flight
             currentRecord = [SELECT (All Fields) FROM ProposalFlight__c WHERE id=:currentRecord.id];
             newRecord = currentRecord.clone(false);
             newRecord.ApprovalStatus__c = Status.NotSubmitted;
             newRecord.ClonedFrom__c = currentRecord.id;
             newRecord.Geo__c = clonedGeo.ID;
             newRecord.GeoTargetSummary__c = clonedGeo.Text__c;
             insert newRecord;

         }catch(Exception e){
             Database.rollback(sp);
             ApexPages.addMessages(e);
             return null;
         }
         
         return new PageReference('/'+newRecord.id);
     }

}

 

 

My Unit Test so far:

 

@isTest (SeeAllData = True)
private class Test_ProposalFlightCloneExtension{
    
    static testMethod void testProposalFlightClone(){
    
        //create test data
        Account acct = UnitTestFactory.makeAccount();
        Opportunity opp = UnitTestFactory.makeMasterCPMOpp(acct.id);
        ProposalFlight__c pf = UnitTestFactory.makeCPMPF(opp.id);
        Geo__c geo = [SELECT Id FROM Geo__c WHERE Id in (SELECT Geo__c FROM ProposalFlight__c WHERE Id =: pf.Id)];
        
        //Go to Page
        Test.setCurrentPage(Page.ProposalFlightClone);
        
        //Set Parameters that would be passed in
        ApexPages.currentPage().getParameters().put('Id', pf.Id);
        
        //Instantiate a new controller with all parameters in place
        ProposalFlightCloneExtension ext = new ProposalFlightCloneExtension(new ApexPages.StandardController(pf));
        
        PageReference pageRef = Page.ProposalFlightClone;

    
    }

}

 The unit test passes, but is only covering 12% of the class. It doesn't cover any of the actual cloning logic. If anyone could point me in the right direction I would really appreciate it. Thank you!

 

Can anyone point me in the direction of any triggers that are used to automatically re-establish revenue schedules (for example, if the Opp Close Date changes). Is this even possible?

 

Thank you so much for the help!

Hi,

 

I have a visualforce page where I populate a PageBlockDataTable with a list<sObject> using StandardSetController.getRecords(). There are some fields in the table that are inputFields to allow edits. Pagination is implemented and works fine if nothing is edited.

 

I read that either cancel() or save() needs to be run before moving to another page otherwise visualforce will throw an error saying 'modified rows exist in the collection'. So when records are edited, I have a javascript that detect changes and prompts user whether to save or cancel before moving to next page, which then through calling actionFunction runs the StandardSetController's cancel() / save() and then next() / previous() / setPageNumber(x) in a method in the page's controller.

 

Problem: After running that, let's say cancel() and next(), getResultSize() becomes lesser and the collection shrunk. Although getPageNumber() appear to be working, something is wrong as there are lesser pages now in the paginated table. Debug log shows that getResultSize() has indeed become lesser after ApexPages.StandardSetController.cancel() is run.

 

Any idea what could be wrong? any feedback/solution recommended is much appreciated. Thanks.

 

 

I have functionality in a form so when the users click on the button, the button goes disabled. The only problem I have is that in a <apex:pageBlockButtons> block, where two sets of buttons are created, only the top set of buttons becomes disabled. This was put into place to prevent the users from double-clicking the buttons, however they end up double-clicking the lower set of buttons because those buttons do not become disabled.

 

         <apex:pageBlockButtons id="productButtons">
            <apex:actionStatus rendered="{!NOT(readOnly)}" id="applyButtonStatus">
               <apex:facet name="stop">
                  <apex:commandButton id="applyButtonActive" action="{!calcRevenue}" value="Apply Changes/Calculate Revenue" status="applyButtonStatus" disabled="false" rerender="productTypeSelectionBlock"/>
               </apex:facet>
               <apex:facet name="start">
                  <apex:commandButton id="applyButtonDisabled" action="{!calcRevenue}" value="Applying Changes..." status="applyButtonStatus" disabled="true" rerender="productTypeSelectionBlock"/>
               </apex:facet>
            </apex:actionStatus>
         </apex:pageBlockButtons>

 

Is there any way to get this to work inside of the pageBlockButtons block, or do I just have to create two sets of buttons? If I create two sets, then they'll disable independently of each other, which isn't ideal.