• Ross Gilbert 31
  • NEWBIE
  • 0 Points
  • Member since 2016

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 12
    Questions
  • 5
    Replies
Salesforce deprecated the ability to use javascript in hyperlink formulas.  So I need to replace what I used to be able to do declaratively with code.  Basically by I think keeping a formula field, but clicking the hyperlink formula takes the user to a visualforce page with a controller, where I can do the validation.

So the use case is: user clicks hyperlink in formula field on case x>if case x is blank in field y, the user gets a popup error message telling them they need to fill in field y>once case x field y has a saved value, clicking the hyperlink takes the user to the actual link (eg salesforce.com or whatever the link is.


I'm looking through the documentation now and trying to get something working but if anyone's run into this before and has any sample code that might get this on the right track I'd appreciate it.  Thanks a lot.
 
I've got a method called from the after update of my opportunity trigger.  I'll paste it below.  Somewhere in here there's a too many soql queries error I get when updating a particular opportunity.  The debug log shows the error at the line with this map:

 
Map<Id, Account> accMap = new Map<Id, Account>([SELECT Id, (SELECT Term_Begin_Date__c, Term_End_Date__c, Finance_Grace_Period_Date__c FROM Customer_Assets__r 
                                            WHERE Term_End_Date__c != null ORDER BY Term_End_Date__c DESC) 
                                        FROM Account WHERE Id IN: accIds]);





Here's the full code with that in it:
 
public static void createUpdateAssets(Map<ID, OpportunityLineItem> qualifiedOLIsMap){
        if(qualifiedOLIsMap.size() > 0){
          //get all the product ids from the OLIs
          Set<Id> prodIds = new Set<Id>();
          Set<Id> contractIds = new Set<Id>();
          Set<Id> accIds = new Set<Id>();
          Opportunity thisOpp;
          for(OpportunityLineItem oli : qualifiedOLIsMap.values()){
            if(thisOpp == null){
                thisOpp = oli.Opportunity;
            }
            if(oli.PriceBookEntry.Product2Id != null){
              prodIds.add(oli.PriceBookEntry.Product2Id);
            }
            if(oli.Opportunity.Contract__c != null){
              contractIds.add(oli.Opportunity.Contract__c);
            }
            if(oli.Opportunity.Contract__r.MLSA__c != null){
              contractIds.add(oli.Opportunity.Contract__r.MLSA__c);
            }
            accIds.add(oli.Opportunity.AccountId);
          }
          
          Map<Id, Product2> prodMap = new Map<Id, Product2>([SELECT Id, (SELECT Id, Name FROM Versions_Product_Junctions__r)
                                      FROM Product2 WHERE Id IN: prodIds]);
          
          //added Term_Date__c to SOQL query
          Opportunity test = [SELECT Id, RecordTypeId FROM Opportunity WHERE Id =: thisOpp.Id];
          Map<Id, Contract> contractMap = new Map<Id, Contract>([SELECT Id, StartDate, EndDate, Term_Date__c,
                                          (SELECT Term_Begin_Date__c, Term_End_Date__c, Finance_Grace_Period_Date__c FROM Taxware_Assets__r 
                                            WHERE Term_End_Date__c != null ORDER BY Term_End_Date__c DESC) 
                                        FROM Contract WHERE Id IN: contractIds]);
            
          for(Contact_Contract_Junction__c ccj : [SELECT Contact__c, Contract__c FROM Contact_Contract_Junction__c WHERE Contract__c IN: contractIds]){
            Set<Id> contactIds = contractContactMap.get(ccj.Contract__c);
            if(contactIds == null){
              contactIds = new Set<Id>(); 
            }
            contactIds.add(ccj.Contact__c);
            contractContactMap.put(ccj.Contract__c, contactIds);
          }
            
            List<OLIAssetWrapper> allOLIAssets = getOLIAssets(qualifiedOLIsMap, prodMap, contractMap);
            
            List<Customer_Asset__c> allAssetsToInsert = new List<Customer_Asset__c>();
            List<Customer_Asset__c> allAssetsToUpdate = new List<Customer_Asset__c>();
            Customer_Asset__c thisOLIAsset;
            for(OLIAssetWrapper oliAst: allOLIAssets){
                thisOLIasset = oliAst.ast;
                if(thisOLIasset.Id == null){
                    allAssetsToInsert.add(thisOLIasset);
                }else{
                    allAssetsToUpdate.add(thisOLIasset);
                }
            }
            
            update allAssetsToUpdate;
            //IR-1357
            insert allAssetsToInsert;
            Set<Id> newAssetIds = new Set<Id>();
            for(Customer_Asset__c thisAsset : allAssetsToInsert){
                newAssetIds.add(thisAsset.Id);
            }
            List<Customer_Asset__c> newAssets = new List<Customer_Asset__c>();
            newAssets = [SELECT Id, Account__c FROM Customer_Asset__c WHERE Id =: newAssetIds];
            if(test.RecordTypeId != '012f0000000D9H9'){
                List<Contract_Asset_Connection__c> conns = new List<Contract_Asset_Connection__c>();
                Contract_Asset_Connection__c thisConn;
                for(Customer_Asset__c thisAsset : newAssets){
                    thisConn = new Contract_Asset_Connection__c();
                    thisConn.Contract__c = thisOpp.Contract__c;
                    thisConn.Asset__c = thisAsset.Id;
                 thisConn.Account__c = thisAsset.Account__c;
                  if(thisConn != null)
                    conns.add(thisConn);
                }
                if(!conns.isEmpty() && test.RecordTypeId != '012i0000001AgIY' && test.RecordTypeId != '012i000000129Hi' && test.RecordTypeId != '012i0000001AgId'){
                    insert conns;
                }
            }   
            Map<Id, Account> accMap = new Map<Id, Account>([SELECT Id, (SELECT Term_Begin_Date__c, Term_End_Date__c, Finance_Grace_Period_Date__c FROM Customer_Assets__r 
                                            WHERE Term_End_Date__c != null ORDER BY Term_End_Date__c DESC) 
                                        FROM Account WHERE Id IN: accIds]);
            
            Map<Id, Entitlement> entMap = new Map<Id, Entitlement>();
            for(OpportunityLineItem oli: qualifiedOLIsMap.values()){
            //if it's an update and the order type is renewal, update the Entitlement dates
                if(oli.Opportunity.Order_Type__c == Constants.ORDER_TYPE_RENEWAL || oli.Opportunity.Order_Type__c == Constants.ORDER_TYPE_ADD_ON || oli.Opportunity.Division__c == 'Taxify'){
                  if(oli.Opportunity.Entitlement__c != null && !entMap.containsKey(oli.Opportunity.Entitlement__c)){
                    Entitlement e = new Entitlement(Id = oli.Opportunity.Entitlement__c);
                    Date oldEntStart = oli.Opportunity.Entitlement__r.StartDate;
                    
                    if(oli.Opportunity.Contract_Paper_Type__c == 'New Paper'){
                        if(oldEntStart != null){//e.StartDate == null
                            e.StartDate = oldEntStart;
                        }else{
                            e.StartDate = oli.Opportunity.Contract__r.StartDate;
                        }
                        //changed EndDate to Term_Date
                        //e.EndDate = oli.Opportunity.Contract__r.Term_Date__c;
                        Account acc = accMap.get(oli.Opportunity.AccountId);
                        Date furthest = Date.today().addYears(-1);
                        if(acc != null && acc.Customer_Assets__r != null && acc.Customer_Assets__r.size() > 0){
                            for(Customer_Asset__c ass : acc.Customer_Assets__r){
                                if(ass.Term_End_Date__c > furthest){
                                    furthest = ass.Term_End_Date__c;
                                }
                            }
                            if(furthest > Date.today()){
                                e.EndDate = furthest;
                            }
                        }
                    }else if(oli.Opportunity.Contract_Paper_Type__c == 'Old Paper'){
                        Account acc = accMap.get(oli.Opportunity.AccountId);
                        Date furthest = Date.today().addYears(-1);
                        if(acc != null && acc.Customer_Assets__r != null && acc.Customer_Assets__r.size() > 0){
                            if(oldEntStart != null){//e.StartDate == null
                                e.StartDate = oldEntStart;
                            }else{
                                e.StartDate = oli.Opportunity.Contract__r.StartDate;
                            }
                            for(Customer_Asset__c ass : acc.Customer_Assets__r){
                                if(ass.Term_End_Date__c > furthest){
                                    furthest = ass.Term_End_Date__c;
                                }
                            }
                            if(furthest > Date.today()){
                                e.EndDate = furthest;
                            }
                        }
                    }
                    //check if finance grace period applies, update entitlement end date
                    Date latestGraceDate = null;
                    Customer_Asset__c thisAsset;
                    Account thisAcc = accMap.get(oli.Opportunity.AccountId);
                    integer numAssets = thisAcc.Customer_Assets__r.size();
                    for(integer i = 0; i < numAssets; i++){
                        thisAsset = thisAcc.Customer_Assets__r.get(i);
                        if(thisAsset.Finance_Grace_Period_Date__c > latestGraceDate){
                            latestGraceDate = thisAsset.Finance_Grace_Period_Date__c;
                        }
                    }
                    if(latestGraceDate > e.endDate){
                        e.endDate = latestGraceDate;
                    }
                    entMap.put(e.Id, e);
                  }
                }
            }
            update entMap.values();
            
            
            List<OpportunityLineItem> allOLIsToUpdate = new List<OpportunityLineItem>();
            Set<ID> opptyIDs = new Set<ID>();
            for(OLIAssetWrapper oliAst: allOLIAssets){
                OpportunityLineItem oli = oliAst.oli;
                oli.Asset__c = oliAst.ast.id;
                
                allOLIsToUpdate.add(oli);
                
                opptyIDs.add(oli.OpportunityID);
            }
            update allOLIsToUpdate;
            
            List<Opportunity> allOpptysToUpdate = new List<Opportunity>();
            for(ID opptyid : opptyIDs){
                Opportunity oppty = new Opportunity(id = opptyid);
                oppty.Fulfillment_Date__c = Date.Today();
                allOpptysToUpdate.add(oppty);
            }
            update allOpptysToUpdate;
        }
    }




I don't see any queries in for loops so I'm not sure how this can be re-written to eliminate the error.  Anyone see anything wrong here?  This is really old code that never really has a problem so this seems to be an edge case/bug in the code, I just can't find it.
I understand sharing sets for communities and also sharing settings, org wide sharing settings, etc.  I understand that case visibility in a Salesforce community is controlled in Salesforce using hte Sharing Sets in the setup menu.  However the issue I have is, I want a community user to only see cases on their account where a custom field on the case is set to "true".  Cases where that flag is false should be hidden from that community user.

There is no way to do this through community sharing sets, nor through sharing settings, nor even apparently through the caseshare object and apex case sharing, because the community license is not suported for case sharing apparently.

Question: is it or is it not possible to hide a case from a community user in any way, based on that case having a checkbox field set to true.  If it is possible please point me in the direction that I can pursue to accomplish this, if you've done it, because it is looking to me to be something that cannot be done in Salesforce at this time from what I am seeing.  Thanks.
We've got maybe 5-5 currencies set up in a multi-currency org.  The exchange rates haven't changed in about 3 years which is how people want it.  However we are adding a new currency, and for this one only, the business wants to have it auto-updated on some tbd schedule (daily, monthly, whatever), but we don't want to update the other exchange rate currencies.

There are apps like s4g on appexchange that will autoupdate your exchange rates for free on some schedule, which is great, problem is they update all your excahgne rates and don't let you do specific ones.  This is no good for my situation.  I basicall ysee no apps on appexhange that solve my problem.  Does anyone else have experience with this?

The only options I see right now are 
1. do nothing except have someone manually update the exchange rate for this one currency once a month.  This seems like the best, smartest, cheapest, and easiest solution.  But I will get pushback from the business because people don't want to see the word manual...ever...even when it is a good, if not the best, option.  Which I think in this case it is, but I'm not convinced yet.

2. programmatically set something up that goes out say once a day, fetches the exchange rate for this currency from yahoo finance or something, pulls it into sf somewhere...and run a job that updates this particular currency overnight.  Not even sure this is technically possible yet.  It might not be.  Anyone know if this is even possible?  If it is impossible I don't want to waste time trying to build this.  Will SFDC let you update one exchange rate out of many automatically, and leave the rest?
I call the method below from my opportunity's before update trigger.  I'm hitting a too many soql queries error in some cases and when i run the debug log the culprit is this block of code.  I think it is because this thing has a for loop within a for loop that is causing the issue but I'm not sure.  

Anyone see anything in this piece of code that would cause too many soql queries error:
 
public static void updateProductMarket(List<Opportunity> opps) {
        Schema.DescribeFieldResult Pickvalue = Opportunity.Product_Market_s__c.getDescribe();
        List<Schema.PicklistEntry> PickListValue = Pickvalue.getPicklistValues();
        //get a list of all Ids we are updating and add them to oppIds
        set<Id> oppIds = new set<Id>();
        for(Opportunity opp : opps) {
            oppIds.add(opp.Id);
        }
        //get all Opportunity Products for all Opportunities being updated
        List<OpportunityLineItem> olis = [SELECT Product_Market__c, Opportunity.Id FROM OpportunityLineItem WHERE Opportunity.Id in:oppIds];
        for(Opportunity opp : opps) {
            //loop through each line item
            for(OpportunityLineItem oli : olis) {
                if(oli.Opportunity.Id == opp.Id) {
                    //we have a match
                    if(oli.Product_Market__c != null){
                        if(opp.Product_Market_s__c == null) {
                            opp.Product_Market_s__c = oli.Product_Market__c;
                        } else {
                            if(isNewProductMarket(opp.Product_Market_s__c.split(';'), oli.Product_Market__c)){
                                opp.Product_Market_s__c = opp.Product_Market_s__c + ';' + oli.Product_Market__c;
                            }
                        }
                    }
                }
            }
        }
    }

 
This batch job runs once a day every day at 1am.

It works fine 50% of the time and doesn't process or fails the other 50%.  When it fails, I see no error message on the job history at all.  It just fails.

I put on debug logs last week on it and when it failde I noticed it had a very, very long duration (in ms) to process.  So I'm thinking something is causing this thing to time out when it runs, sometimes.

Does anyone see anything wrong with the code and in particular the soql query that might cause a timeout/job failure?  


global class updateAssetTermDates implements Database.Batchable<sObject>, Schedulable{

    string query;
    
    global void execute(SchedulableContext SC) 
    {
        updateAssetTermDates  x = new updateAssetTermDates(); 
        database.executebatch(x);
    }

    global Database.querylocator start(Database.BatchableContext BC){
        Query = 'Select id, Entitlement__r.EndDate, Previous_Annual_Maintenance__c, Annual_Maintenance__c, Future_Annual_Maintenance__c, Term_Begin_Date__c, Term_End_Date__c, Term_Start_Date_Hidden__c, Term_End_Date_Hidden__c  FROM Customer_Asset__c WHERE Term_Start_Date_Hidden__c = TODAY AND Maintenance_Status__c = \'On Subscription\' ';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Customer_Asset__c> scope1){
        List<Customer_Asset__c> assList = new List<Customer_Asset__c>();
        Set<Id> assEntId = new Set<Id>();
        Date d;
        
            for(Customer_Asset__c ca : Scope1){
                ca.Term_Begin_Date__c = ca.Term_Start_Date_Hidden__c;
                ca.Term_End_Date__c = ca.Term_End_Date_Hidden__c;
                d= ca.Term_End_Date__c;
                if(ca.Future_Annual_Maintenance__c != NULL)
                {
                    ca.Previous_Annual_Maintenance__c = ca.Annual_Maintenance__c;
                    ca.Annual_Maintenance__c = ca.Future_Annual_Maintenance__c;
                    ca.Future_Annual_Maintenance__c = NULL;
                }
                
                assList.add(ca);
                assEntId.add(ca.Entitlement__c);
            } 
                  
        try{
                update assList;
        } catch (Exception e) {         
            Error_Log__c log = new Error_Log__c();
            log.trace__c = 'Type: ' + e.getTypeName() + '\n' + 'Cause: ' + e.getCause() + '\n' + 'Message: ' 
            + e.getMessage() + '\n' + 'Line #: ' + e.getLineNumber() + '\n' + e.getStackTraceString() + '\n';
           // + 'Some Custom Variable Information From Class: ' + myClassVariable;
            insert log;         
        }        

        List<Entitlement> entList = new List<Entitlement>();
        
        for(Entitlement e: [select id from Entitlement where ID =: assEntId]){
            e.EndDate = d;
            entList.add(e);
        }
        
        try{
                update entList;
        } catch (Exception e) {         
            Error_Log__c log = new Error_Log__c();
            log.trace__c = 'Type: ' + e.getTypeName() + '\n' + 'Cause: ' + e.getCause() + '\n' + 'Message: ' 
            + e.getMessage() + '\n' + 'Line #: ' + e.getLineNumber() + '\n' + e.getStackTraceString() + '\n';
           // + 'Some Custom Variable Information From Class: ' + myClassVariable;
            insert log;         
        }
        
    }

    global void finish(Database.BatchableContext BC){
    }
    
}

 
I've got an after update trigger on account that works fine when individual records are updated.  But when I go to do a bulk update on say 200 accounts in my sandbox the trigger is not fired.  

Here's the class that the account after update trigger calls that does the work.  Something is not bulkified in here but I can't see it.  I don't think I've got any queries in for loops which usually is the problem.  What is wrong with this code?
 
public without sharing class RelatedAccountsManager{

    public static void createRelatedAccounts(object[] newTrigger) {

        List<Account> accList = (List<Account>) newTrigger;
            List<Account> accList3 = new List<Account>();
            List<Related_Account__c> raList = new List<Related_Account__c>();
            String thisDUNS;
            Id originalAccount;
                                
            for(Account a: accList){
                thisDUNS = a.Convey_Global_Ultimate_D_U_N_S__c;
                originalAccount = a.Id;
            }
         
            List<Related_Account__c> raListCheck = [SELECT Id, Related_Account__c, Account_Connection__r.Id from Related_Account__c WHERE Account_Connection__r.Id =: originalAccount LIMIT 1];
          
            if(raListCheck.size()>0){
            }else{                
              List<Account> accList2 = [SELECT ID,Type,Convey_Global_Ultimate_D_U_N_S__c FROM Account WHERE Convey_Global_Ultimate_D_U_N_S__c =: thisDUNS AND Convey_Global_Ultimate_D_U_N_S__c != null];        
                for(Account a1: accList2){
                    if(a1.Id != originalAccount && a1.Convey_Global_Ultimate_D_U_N_S__c!= null && accList2.size()>0 && a1.Type != 'Prospect'){
                        Related_Account__c ra = new Related_Account__c();
                        ra.Account_Connection__c = originalAccount;
                        ra.Related_Account__c = a1.Id;
                        raList.add(ra);       
                        accList3.add(a1);             
                     }
                }
             }
             insert raList;  
             
             List<Account> accList4 = new List<Account>();
             
             for(Account a2: accList3){
                accList4.add(a2);
             }
             
             update accList4;
     }   
}

 
Hi,

I need a trigger that clones an attachment created on a case to the most recently created custom object on that case.

In other words, let's say I have the case object.  Let's say I have 1 custom object on the case object.  When a case is created or updated with a new attachment on it, I need that attachment to be put on that custom object as well as the attachment.

Use case:

Case is created or updated with an attachment on it.  That attachment should now be automatically added to the custom object "x", not just the case.

I'm working on this but not sure how to get it to work.  I'm thinking the trigger ought to be on the attachment object since that is where the action is happening to trigger everything.

Does anyone have any ideas?
Does anyone know why this won't work?

The following code works, wher eteh actionsupport attribute is outside the apex:repeat attribute.  When a user clicks the link in a VF page it updates the user's related contact record with a couple values:
 
<apex:form >
    <apex:outputLink value="https://www.salesforce.com" target="_blank" 
      id="theLink">www.salesforce.com           
            <apex:actionSupport event="onclick" action="{!setFTPClickedInfo}"    
               rerender="testOPP" immediate="true">
                  <apex:param name="clickLink1" assignTo="{!clickedURL}" value="Download"/>
             </apex:actionSupport>
    </apex:outputLink>                                              
<apex:repeat var="posid" value="{!assetIdToPosId[assetKey]}">

However when I just move that outputlink and its action support INSIDE the apex:repeat attribute...the action support functionality stops working.  This does not work:
 
<apex:form >
                                  
<apex:repeat var="posid" value="{!assetIdToPosId[assetKey]}">

    <apex:outputLink value="https://www.salesforce.com" target="_blank" 
      id="theLink">www.salesforce.com           
            <apex:actionSupport event="onclick" action="{!setFTPClickedInfo}"    
               rerender="testOPP" immediate="true">
                  <apex:param name="clickLink1" assignTo="{!clickedURL}" value="Download"/>
             </apex:actionSupport>
    </apex:outputLink>

Anyone know how to fix this?
I'm working on a trigger that should create multiple juntion object records when a record is inserted.  The trigger below works in that it inserts 1 juntion object record.  The problem is I need it to create multiple juntion object records when the trigger fires, and it's not happening.  Not sure why.

In words what this trigger SHOULD do: when case is inserted, create juntion object record on every PS_Project__c record that belongs to the case's account.  In other words: say I create a case on an account that already has 2 PS_Project__c object records on it.  Upon me creating the case, the trigger should fire, and create 2 juntion object records: one on each PS_Project__c object record for that account:
 
trigger CaseTrigger on Case (after insert) {
    

 Map<Id,PS_Project__c> specialMap = new Map<Id,PS_Project__c>();
            Set<Id> accSet = new Set<Id>();
            List<Case_PS_Project_Junction__c> cpsjList = new List<Case_PS_Project_Junction__c>();
           
            for(Case c: trigger.new){
                accSet.add(c.AccountId);
            }
            
            for(PS_Project__c psp : [Select Id, Account__r.Id from PS_Project__c where Account__r.Id = :accSet]){
                specialMap.put(psp.Account__r.Id,psp);
            }            
            
            for(Case c: trigger.new){       
                if(specialMap.containsKey(c.AccountId)){
           
                    Case_PS_Project_Junction__c cpsj = new Case_PS_Project_Junction__c();
                    cpsj.Case__c = c.Id;
                    cpsj.PSProject__c = specialMap.get(c.AccountId).Id;
                    cpsjList.add(cpsj);
                }
            }
                insert cpsjList;

}

 
This batch job works but the test class I'm writing for it throws this error:

System.UnexpectedException: No more than one executeBatch can be called from within a testmethod. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation.


Batch job that works:
global class UpdateUser implements Database.Batchable<sObject> {

    string query;
    
    global void execute(SchedulableContext SC) 
    {
        UpdateUser x = new UpdateUser(); 
        database.executebatch(x);
    }

    global Database.querylocator start(Database.BatchableContext BC){
        Query = 'Select id, Contact.Last_Login_to_Portal_Community__c, LastLoginDate FROM User WHERE ContactId != null AND isActive = true';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<User> scope1){
        List<Contact> cList = new List<Contact>();
        List<User> uList = new List<User>();
            for(User u : Scope1){
                u.Last_Login_Date__c = u.LastLoginDate; 
                u.Contact.Last_Login_to_Portal_Community__c = u.LastLoginDate;
                cList.add(u.Contact);
                uList.add(u);
            }       
        update uList;
        update cList;
    }

    global void finish(Database.BatchableContext BC){
    }
    
    /*
    Schedule job every 30 minutes:
    
    updateUser us = new updateUser ();
    string sch = '0 30 * * 1-12 ? *';
    system.schedule('updateUserOnTheHalfHour',sch,us); 
    
    */
}

Test class for the above job that doesn't work:
@isTest
private class TestCleanUpBatchClass {

    static testmethod void test() {
        
        //insert an account
        Account a = new Account();
        a.Name = 'test';
        insert a;
        //insert a contact
        Contact c = new Contact();
        c.LastName ='test';
        c.FirstName ='test';
        c.AccountId=a.id;
        insert c;
        //insert a user on that contact
        Profile p = [SELECT Id FROM Profile WHERE Name='Sovos Customer Community Login User - Convey'];        
        User u = new User(Alias = 'standt1', Email='standarduser1@testorg1.com', 
          EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US', 
          LocaleSidKey='en_US', ProfileId = p.Id, ContactId = c.Id, Last_Login_Date__c = System.today(),
          TimeZoneSidKey='America/Los_Angeles', UserName='standarduser1@testorg1.com');    
          insert u;    
        //run the batch
        Test.StartTest();
          UpdateUser x = new UpdateUser();
          ID batchprocessid = Database.executeBatch(x);
        Test.StopTest();        
        //confirm that the contact Last Login to Portal/Community is = to user last login
        Contact c1 = [SELECT Id, Last_Login_to_Portal_Community__c FROM Contact Where Id =: c.Id];
        User u1 = [SELECT Id, ContactId, Last_Login_Date__c FROM User Where Id =: u.Id];
        System.AssertEquals(u1.ContactId,c1.Id);
        System.AssertEquals(System.Today(),c1.Last_Login_to_Portal_Community__c);
           
   }
}

Anyone know what I'm doing wrong here to get that error?  Thanks!
If I have an integraetion user in Salesforce set up, and I freeze that user, NOT de-activate that user, will the integration that uses that user still work or will it break the integration?  I believe freezing the user just prevents UI and API logging in by the user, so I'm guessing the integration will still work.  Anyone have any experience with this?  Thanks
I understand sharing sets for communities and also sharing settings, org wide sharing settings, etc.  I understand that case visibility in a Salesforce community is controlled in Salesforce using hte Sharing Sets in the setup menu.  However the issue I have is, I want a community user to only see cases on their account where a custom field on the case is set to "true".  Cases where that flag is false should be hidden from that community user.

There is no way to do this through community sharing sets, nor through sharing settings, nor even apparently through the caseshare object and apex case sharing, because the community license is not suported for case sharing apparently.

Question: is it or is it not possible to hide a case from a community user in any way, based on that case having a checkbox field set to true.  If it is possible please point me in the direction that I can pursue to accomplish this, if you've done it, because it is looking to me to be something that cannot be done in Salesforce at this time from what I am seeing.  Thanks.
Hi
I am a 1st time poster so apologies if this is the wrong place for this question.
Also I am not that experienced with VF and Apex
 
 
Some work was done before I started with the company that uses a Hyperlink formula field with JavaScript in it.  Now Salesforce is stopping this and I am struggling to find a way to replace this functionality.
 
 
This is what the current functionality does:

On the case object there is a related list (linking to a custom object).  The Related list shows the "Add Coment" field which is the formula field in question

Related List on the Case object


When you click on the “New Comment” hyperlink it opens a new screen (with some fields pre-populated) that allows a new Case Comment record to be generated that is linked against the specific Journal Entry (and against that specific case):

Screenshot of when the hyperlink is clicked

This is accomplished by the formula/JavaScript building a URL (using multiple custom settings so hardcoding is not required).
 
The formula in question:
HYPERLINK("javascript:if(typeof(srcUp)=='function') {srcUp('/" & $Setup.CaseManagement__c.CaseCommentObject__c & "/e?" & $Setup.CaseManagement__c.CaseCommentJournalIDField__c & "=" & Name & "&" & $Setup.CaseManagement__c.CaseCommentJournalIDField__c & "_lkid=" & Id & "&" & $Setup.CaseManagement__c.CaseCommentTypeFieldID__c & "=Comment&retURL=%2F" & $Setup.CaseManagement__c.CaseCommentObject__c & "%2Fo&" & $Setup.CaseManagement__c.CaseCommentCaseIDField__c & "_lkid=" & Case__c & "&" & $Setup.CaseManagement__c.CaseCommentCaseIDField__c & "=" & Case__r.CaseNumber & "&isdtp=vw');}"+ " else {window.location.href='/" & $Setup.CaseManagement__c.CaseCommentObject__c & "/e?" & $Setup.CaseManagement__c.CaseCommentJournalIDField__c & "=" & Name & "&" & $Setup.CaseManagement__c.CaseCommentJournalIDField__c & "_lkid=" & Id & "&" & $Setup.CaseManagement__c.CaseCommentTypeFieldID__c & "=Comment&retURL=%2F" & $Setup.CaseManagement__c.CaseCommentObject__c & "%2Fo&" & $Setup.CaseManagement__c.CaseCommentCaseIDField__c & "_lkid=" & Case__c & "&" & $Setup.CaseManagement__c.CaseCommentCaseIDField__c & "=" & Case__r.CaseNumber& "'}", "New Comment", "_self" )



My initial thought was to replace this with a Visual Force page and an Apex controller – so the formula field would be:
HYPERLINK("apex/Journal_Entry_Add_Comment","New Comment")
 
The VF page code would be very basic:
<apex:page controller="Journal_Entry_Add_Comment_Controller">
    <apex:outputLink >value= "!{URL}"</apex:outputLink>
</apex:page>
 
Then the URL string would be created in the Apex controller.
 
public class Journal_Entry_Add_Comment_Controller {
      
    
	public Journal_Entry_Add_Comment_Controller()
    {  
		CaseManagement__c CS = CaseManagement__c.getOrgDefaults();      // loading custom settings so field values can be used
		id Jid = apexpages.currentPage().getparameters().get('id'); 	// get the id of the journal entry record id 
       
system.debug('PAGE ID = ' + Jid);        

        string name = apexpages.currentPage().getparameters().get('name');  
        
system.debug('NAME = ' + name);        

       
        Journal_Time__c JTrecord = [SELECT id, name, case__c, case__r.CaseNumber 
                                    FROM Journal_Time__c 
                                    WHERE id = :Jid]; 					// loads the journal time record field data into memory
        
        
		string URL;        // URL to be constructed 
        
		URL = '/' + CS.CaseCommentObject__c + '/e?' + CS.CaseCommentJournalIDField__c + '=' + JTrecord.Name + '&' + CS.CaseCommentJournalIDField__c +
            '_lkid=' + Jid + '&' + cs.CaseCommentTypeFieldID__c + '=Comment&retURL=%2F' + cs.CaseCommentObject__c + '%2Fo&' + cs.CaseCommentCaseIDField__c +
            '_lkid=' + JTrecord.Case__c + '&' + cs.CaseCommentCaseIDField__c + '=' + JTrecord.case__r.CaseNumber + '&isdtp=vw'; 
        
system.debug('URL = ' + URL);        
     
    }

}

However the following returns a null value
 
string name = apexpages.currentPage().getparameters().get('name');
 
id Jid = apexpages.currentPage().getparameters().get('id');

So when the SOQL runs looking for records with that ID - it kicks a runtime error.

 
So I thought to try and re-create the javascript in the Visual Force page in <Script> tags – however the parameters from the custom settings are not picked up (IE the URL contains “$Setup.CaseManagement__c.CaseCommentObject__c” rather than “a0s” which is what it should do.)
 
I have never written any JavaScript – so I can’t break down the URL and create functions to recreate it like I tried to do in Apex – but I guess this is an option.  
 
 
I have thought about replacing the related list altogether with an inline Visual Force page.  This would recreate the look of the related list but would use a command button (rather than hyperlink) in the second column to create the new records. 
I have passed parameters using buttons before – so I think this would be doable. 

However I have read the cons against replacing the standard related list with a Visual Force made related list and would prefer not to go down that route.
 

Does anybody have advice on how they would tackle this?
(Or maybe steer me in the correct direction on my Apex controller)


Thanks for any help/advice

Rob
 
This batch job runs once a day every day at 1am.

It works fine 50% of the time and doesn't process or fails the other 50%.  When it fails, I see no error message on the job history at all.  It just fails.

I put on debug logs last week on it and when it failde I noticed it had a very, very long duration (in ms) to process.  So I'm thinking something is causing this thing to time out when it runs, sometimes.

Does anyone see anything wrong with the code and in particular the soql query that might cause a timeout/job failure?  


global class updateAssetTermDates implements Database.Batchable<sObject>, Schedulable{

    string query;
    
    global void execute(SchedulableContext SC) 
    {
        updateAssetTermDates  x = new updateAssetTermDates(); 
        database.executebatch(x);
    }

    global Database.querylocator start(Database.BatchableContext BC){
        Query = 'Select id, Entitlement__r.EndDate, Previous_Annual_Maintenance__c, Annual_Maintenance__c, Future_Annual_Maintenance__c, Term_Begin_Date__c, Term_End_Date__c, Term_Start_Date_Hidden__c, Term_End_Date_Hidden__c  FROM Customer_Asset__c WHERE Term_Start_Date_Hidden__c = TODAY AND Maintenance_Status__c = \'On Subscription\' ';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<Customer_Asset__c> scope1){
        List<Customer_Asset__c> assList = new List<Customer_Asset__c>();
        Set<Id> assEntId = new Set<Id>();
        Date d;
        
            for(Customer_Asset__c ca : Scope1){
                ca.Term_Begin_Date__c = ca.Term_Start_Date_Hidden__c;
                ca.Term_End_Date__c = ca.Term_End_Date_Hidden__c;
                d= ca.Term_End_Date__c;
                if(ca.Future_Annual_Maintenance__c != NULL)
                {
                    ca.Previous_Annual_Maintenance__c = ca.Annual_Maintenance__c;
                    ca.Annual_Maintenance__c = ca.Future_Annual_Maintenance__c;
                    ca.Future_Annual_Maintenance__c = NULL;
                }
                
                assList.add(ca);
                assEntId.add(ca.Entitlement__c);
            } 
                  
        try{
                update assList;
        } catch (Exception e) {         
            Error_Log__c log = new Error_Log__c();
            log.trace__c = 'Type: ' + e.getTypeName() + '\n' + 'Cause: ' + e.getCause() + '\n' + 'Message: ' 
            + e.getMessage() + '\n' + 'Line #: ' + e.getLineNumber() + '\n' + e.getStackTraceString() + '\n';
           // + 'Some Custom Variable Information From Class: ' + myClassVariable;
            insert log;         
        }        

        List<Entitlement> entList = new List<Entitlement>();
        
        for(Entitlement e: [select id from Entitlement where ID =: assEntId]){
            e.EndDate = d;
            entList.add(e);
        }
        
        try{
                update entList;
        } catch (Exception e) {         
            Error_Log__c log = new Error_Log__c();
            log.trace__c = 'Type: ' + e.getTypeName() + '\n' + 'Cause: ' + e.getCause() + '\n' + 'Message: ' 
            + e.getMessage() + '\n' + 'Line #: ' + e.getLineNumber() + '\n' + e.getStackTraceString() + '\n';
           // + 'Some Custom Variable Information From Class: ' + myClassVariable;
            insert log;         
        }
        
    }

    global void finish(Database.BatchableContext BC){
    }
    
}

 
Does anyone know why this won't work?

The following code works, wher eteh actionsupport attribute is outside the apex:repeat attribute.  When a user clicks the link in a VF page it updates the user's related contact record with a couple values:
 
<apex:form >
    <apex:outputLink value="https://www.salesforce.com" target="_blank" 
      id="theLink">www.salesforce.com           
            <apex:actionSupport event="onclick" action="{!setFTPClickedInfo}"    
               rerender="testOPP" immediate="true">
                  <apex:param name="clickLink1" assignTo="{!clickedURL}" value="Download"/>
             </apex:actionSupport>
    </apex:outputLink>                                              
<apex:repeat var="posid" value="{!assetIdToPosId[assetKey]}">

However when I just move that outputlink and its action support INSIDE the apex:repeat attribute...the action support functionality stops working.  This does not work:
 
<apex:form >
                                  
<apex:repeat var="posid" value="{!assetIdToPosId[assetKey]}">

    <apex:outputLink value="https://www.salesforce.com" target="_blank" 
      id="theLink">www.salesforce.com           
            <apex:actionSupport event="onclick" action="{!setFTPClickedInfo}"    
               rerender="testOPP" immediate="true">
                  <apex:param name="clickLink1" assignTo="{!clickedURL}" value="Download"/>
             </apex:actionSupport>
    </apex:outputLink>

Anyone know how to fix this?