• Ben Meyers
  • NEWBIE
  • 20 Points
  • Member since 2013
  • Software Engineer
  • PKWARE, Inc.

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 11
    Questions
  • 7
    Replies
I am trying to use a lookup field in the where clause of a soql query (query is below).  For some reason it errors (screen shot attached).  Weird part is I can add the lookup field to the query body without issue.  Salesforce only has an issue when its in the where clause.  Has anyone seen this before?  

User-added image

select id, description, product2id from quotelineitem where quote.quotenumber = '00032686' and product2.sales_type_id__c = 5 and ParentLineItem__r.product2.sales_type_id__c = 4
I have a VisaulForce page with a button that calls the anctionFunction afRefreshData below.  Randomly the methods reloadDt and resetSearchVariable inside afRefreshData's oncomplete call do not execute.  Rather, they are displayed on the screen as seen in the image.  Somehow the user gets logged out during the execution and is forced to relogin.  

Has anyone seen this behavior?  

 User-added image
 
<apex:actionFunction name="afRefreshData" reRender="dataPanelId" oncomplete="reloadDt(); resetSearchVariable();" status="status" />
function reloadDt(){
            var dtId = 'dataTable';
            var data = $j('body').data('data');
            var lblTotalCountId = 'totalCount';
            reloadData(dtId, data, lblTotalCountId);      
        }

function resetSearchVariable(){
            searchClicked = false;    
        }


 
I have the following three classes that are used to schedule an apex job.  Yesterday I noticed the job had 13 batches complete successfully yet only 12 actions occurred insdie KeysBatch.  Is there a good way to debug what happened or a way to alert me when a batch fails to complete or reschedule? 
public class ScheduleHandler implements ScheduledDispatcher.IScheduleDispatched 
{
	private string query = 'SELECT Quote__c, Name FROM c2g__codaInvoice__c WHERE Small_Platform_Key__c = true';
    
	public void execute(SchedulableContext sc)
    {
        system.abortJob(sc.getTriggerID());	// Always abort the job on completion
        
        system.debug('Here execute');
        
        //Run key batch
        KeysBatch batch = new KeysBatch(query);
        Database.executeBatch(batch, 1);
    } 

    public static String GetSchedulerExpression(Datetime dt) {
        return ('' + dt.second() + ' ' + dt.minute() + ' ' + dt.hour() + ' ' + dt.day() + ' ' + dt.month() + ' ? ' + dt.year());
    }

	private static Boolean ScheduledInContext = false;

    public static void StartScheduler()
    {
    	if(ScheduledInContext) return;

		ScheduledInContext = true;
    	
        List<CronTrigger> jobs = [SELECT Id, CronJobDetail.Name, State, NextFireTime
                                  FROM CronTrigger where CronJobDetail.Name='Small Platform Schedule Job'];
    	if(jobs.size()>0 && jobs[0].state!='COMPLETED' && 
           jobs[0].state!='ERROR' && jobs[0].state!='DELETED') return;	// Already running

        Set<String> activejobstates = new Set<String>{'Queued','Processing','Preparing'};
		List<AsyncApexJob> apexjobs = [Select ID, ApexClass.Name from AsyncApexJob 
                                           where ApexClass.Name = 'KeysBatch' And Status in :activejobstates];
		if(apexjobs.size()>0) return;  // The batch is running
    	
		System.schedule('Small Platform Schedule Job', 
	          GetSchedulerExpression(DateTime.Now().addMinutes(10)), 
	          new ScheduledDispatcher());
    }

}

global class KeysBatch implements Database.Batchable<sObject>, Database.AllowsCallouts
{
    private string query = '';
    
    public KeysBatch(string query)
    {
        this.query = query;
    }
    
	global Database.QueryLocator start(Database.BatchableContext BC)
    {
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext BC, List<c2g__codaInvoice__c> invoices)
    {
       for (c2g__codaInvoice__c i : invoices)
        {
                try
                {
                  }  
                catch(Exception e)
                {
                    
                }
            }
         }
    }   
    
    global void finish(Database.BatchableContext BC)
    {
        if (!Test.isRunningTest())
            ScheduleHandler.StartScheduler();
    }
    
    
}
global class ScheduledDispatcher Implements Schedulable {
	public Interface IScheduleDispatched 
    { 
        void execute(SchedulableContext sc); 
    } 
    
    global void execute(SchedulableContext sc) 
    {
        Type targettype = Type.forName('ScheduleHandler');   
        if(targettype!=null) {
            system.debug('Inside Scheduler');
            IScheduleDispatched obj = (IScheduleDispatched)targettype.NewInstance();
            obj.execute(sc);   
        } 
    } 
}

 
I use the Schedulable class to schedule apex code to run every minute.  At random times the apex is not rescheduled and the process stops. Below is the code used.  Any thoughts? 

public class ScheduleSalesInvoiceStatus implements ScheduleDispatcherSalesInvoiceStatus.IScheduleDispatchedSalesInvoiceStatus
{
    public static string query = 'select id, quote__r.status, c2g__PaymentStatus__c, quote__c, c2g__Opportunity__c from c2g__codaInvoice__c where Quote__c != null AND ((c2g__PaymentStatus__c = \'Part Paid\' and quote__r.status != \'Invoice Part Paid\') OR (quote__r.status != \'Credited\' AND quote__r.status != \'Credit Requested\' AND c2g__PaymentStatus__c = \'Paid\' AND quote__r.status != \'Invoice Paid\'))';
    
    public void execute(SchedulableContext sc)
    {
        system.abortJob(sc.getTriggerID());    // Always abort the job on completion
        
        //Run key batch
        SaleInvoiceStatusBatch batch = new SaleInvoiceStatusBatch(query);
        Database.executeBatch(batch, 1);
    }

    public static String GetSchedulerExpression(Datetime dt)
    {
        return ('' + dt.second() + ' ' + dt.minute() + ' ' + dt.hour() + ' ' + dt.day() + ' ' + dt.month() + ' ? ' + dt.year());
    }

    private static Boolean ScheduledInContext = false;

    public static void StartScheduler()
    {
        if(ScheduledInContext) return;

        ScheduledInContext = true;
        
        List<CronTrigger> jobs = [SELECT Id, CronJobDetail.Name, State, NextFireTime
                                  FROM CronTrigger where CronJobDetail.Name='Sales Invoice Status Schedule Job'];
        if(jobs.size() > 0 && jobs[0].state != 'COMPLETED' && jobs[0].state != 'ERROR' && jobs[0].state != 'DELETED')
        {
            return;    // Already running
        }

        Set<String> activejobstates = new Set<String>{'Queued','Processing','Preparing'};
        List<AsyncApexJob> apexjobs = [Select ID, ApexClass.Name from AsyncApexJob
                                           where ApexClass.Name = 'SaleInvoiceStatusBatch' And Status in :activejobstates];
        if(apexjobs.size() > 0)
        {
            return;  // The batch is running
        }
        
        System.schedule('Sales Invoice Status Schedule Job',
              GetSchedulerExpression(DateTime.Now().addMinutes(2)),
              new ScheduleDispatcherSalesInvoiceStatus());
    }

}

global class ScheduleDispatcherSalesInvoiceStatus Implements Schedulable
{
    public Interface IScheduleDispatchedSalesInvoiceStatus
    {
        void execute(SchedulableContext sc);
    }
    
    global void execute(SchedulableContext sc)
    {
        Type targettype = Type.forName('ScheduleSalesInvoiceStatus');   
        if(targettype != null)
        {
            IScheduleDispatchedSalesInvoiceStatus obj = (IScheduleDispatchedSalesInvoiceStatus)targettype.NewInstance();
            obj.execute(sc);   
        }
    }
}

global class SaleInvoiceStatusBatch implements Database.Batchable<sObject>, Database.AllowsCallouts
{
    private string query = '';
    
    public SaleInvoiceStatusBatch(string query)
    {
        this.query = query;
    }
    
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        return Database.getQueryLocator(query);
    }
    
    /*
     * Updates quote status to invoice paid, part-paid
     * */
    global void execute(Database.BatchableContext BC, List<c2g__codaInvoice__c> invoices)
    {
        Set<ID> oppIds = new Set<ID>();
        Set<Id> invoiceIds = new Set<Id>();
       
        List<Quote> quotes = new List<Quote>();
        for (c2g__codaInvoice__c i : invoices)
        {
            try
            {
                Quote q = new Quote();
                q.Id = i.quote__c;
                if (i.c2g__PaymentStatus__c == 'Paid')
                {
                    q.Status = 'Invoice Paid';
                    oppIds.add(i.c2g__Opportunity__c);
                    invoiceIds.add(i.Id);
                }
                else if (i.c2g__PaymentStatus__c == 'Part Paid')
                {
                    q.Status = 'Invoice Part Paid';
                }

                quotes.add(q);
            }
            catch(Exception e)
            {
                Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
                String[] toAddresses = new String[] {'ben.meyers@pkware.com'};
                  mail.setToAddresses(toAddresses);
                mail.setSenderDisplayName('Quote status update error');
                mail.setSubject('The following exception has occurred: ' + e.getMessage());
                mail.setPlainTextBody(e.getMessage());
                Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
            }
        }

        //List of tasks to Complete
        Map<Id, Task> tToUpdateList = new Map<Id, Task>();
        
        //List of Opportunities to update Paid Date
        List<Opportunity> oToUpdateList = new List<Opportunity>();

        // If there are any opportunities to update, then proceed.
        if (!oppIds.isEmpty())
        {
            // Get tasks on Opportunity being closed, update and close if still open
            for (Task t : [select isclosed, subject, status from task t where whatid in :oppIds and t.isclosed = false
                           and (t.type = 'AR Collection' or t.type = 'Maintenance Courtesy' or t.type = 'Maintenance Collection') for update])
            {
                // Otherwise, mark the task as completed.
                t.status = 'Completed';
                
                if (!tToUpdateList.containsKey(t.Id))
                {
                    tToUpdateList.put(t.id, t);
                }
            }
            
            //Add oppids to update list
            for (Id oppId : oppIds)
            {
                Opportunity o = new Opportunity();
                o.Id = oppId;
                o.Paid_Date__c = System.today();
                oToUpdateList.add(o);
            }
        }
        
        // If there are any invoices to update, then proceed.
        if (!invoiceIds.isEmpty())
        {
            // Get tasks on Opportunity being closed, update and close if still open
            for (Task t : [SELECT isclosed, subject, status FROM task t WHERE whatid in: invoiceIds AND t.isclosed = false
                           AND (t.type = 'AR Collection' OR t.type = 'Maintenance Courtesy' OR t.type = 'Maintenance Collection') FOR UPDATE])
            {
                // Otherwise, mark the task as completed.
                t.status = 'Completed';
                
                //update t;
                if (!tToUpdateList.containsKey(t.Id))
                {
                    tToUpdateList.put(t.id, t);
                }
            }
            
            //Open AR opportunity
            Set<ID> openAROppIds = new Set<ID>();
            for (Opportunity o : [SELECT fforce_invoice__c FROM opportunity WHERE fforce_invoice__c IN: invoiceIds])
            {
                openAROppIds.add(o.Id);
            }
            
            for (Task t : [SELECT isclosed, subject, status FROM task t WHERE whatid IN: openAROppIds AND t.isclosed = false
                           AND (t.type = 'AR Collection' OR t.type = 'Maintenance Courtesy' OR t.type = 'Maintenance Collection') FOR UPDATE])
            {
                // Otherwise, mark the task as completed.
                t.status = 'Completed';
                
                //update t;
                if (!tToUpdateList.containsKey(t.Id))
                {
                    tToUpdateList.put(t.id, t);
                }
            }
        }
        
        //Update opportunities
        if (!oToUpdateList.isEmpty())
        {
            update oToUpdateList;
        }
        
        //Update tasks
        if (!tToUpdateList.isEmpty())
        {
            update tToUpdateList.values();
        }
        
        //Update list of quotes
        if (!quotes.isEmpty())
        {
            //Set recursion flag and skip validation flag
            //Recursion.flag = true;
            //QuoteStatusActions.SetSkipValidation(true);
            
            update quotes;    
            
            //Set recursion flag and skip validation flag
            //Recursion.flag = false;
            //QuoteStatusActions.SetSkipValidation(false);
        }
    }
    
    global void finish(Database.BatchableContext BC)
    {
        if (!Test.isRunningTest())
            ScheduleSalesInvoiceStatus.StartScheduler();
    }
}
I have a linked external application which uses hyperlinks to visualforce pages.  We currently use hared-coded references (i.e. naX.salesforce.com) in these links.  With Salesforce's upcoming split and migration of servers I want to change these to relative urls (i.e. login.salesforce.com). 

In my initial testing it works perfectly for everything except visualforce pages.  For example, one hard-coded link we use is https://c.na3.visual.force.com/apex/test.  If we change this url to https://c.login.visual.force.com/apex/cpqquote or https://login.visual.force.com/apex/cpqquote it does not work.  

Any suggestion on what the relative url should be?
Since last week our code coverage has decreased by 10%.  The only changes we made were a couple classes no longer are referenced anywhere in our org.  Is this a new Salesforce setting?  I cannot understand what has happened.
I am trying to generate apex classes from a wsdl.  I removed all imports and pasted the xsd schemas and removed all soap12 references.  I still get an apex error saying Unable to find soap 1.1 address.  Any ideas?  If needed I can paste the wsdl file I am trying to import.  
My organization is utilizing a third party managed package which has a VForce page allowing our users to batch multiple records at once.  Once complete the records statuses are updated to Completed. 

I have an after insert trigger which calls an @future method when the record status is changed to Completed.  This is illegal since the installed package code is called from an @future method.  As you probably expect I am getting the dreadful error: System.AsyncException: Future method cannot be called from a future or batch method. 

The reason I utilize an @future method is because I have a callout.  Since callouts are denied inside triggers I utilized an @future method. 

Is there another way to accomplish this? 
Recently a visualforce page started running extremely slow when the developer console was open.  It ran fairly fast before, and I havn't added any additional logging.  To make things worse the performance remains slow even if I close the developer console.  The performance only increases when I close my entire browser.  Any thoughts? 
In our workflow once a quote reaches a certain status the opportunity attached to the quote and any other quotes attached to the opportunity need to be locked.  This includes fields and any related lists.  Is this possible?  I have tried page layouts but users can still edit/delete from related lists.  I have also tried validation rules but fail to get these to work on all related lists. 

Any ideas?  This seems like such a basic need and its unfathomable for Salesforce to not have this feature.
Can the email link under quote pdf related list be customized?  I have a custom visualforce page used to send emails which I need this link redirected to.  I've done this before but Quote PDF, which relates to QuoteDocument, is hidden.  Any ideas?
I have a linked external application which uses hyperlinks to visualforce pages.  We currently use hared-coded references (i.e. naX.salesforce.com) in these links.  With Salesforce's upcoming split and migration of servers I want to change these to relative urls (i.e. login.salesforce.com). 

In my initial testing it works perfectly for everything except visualforce pages.  For example, one hard-coded link we use is https://c.na3.visual.force.com/apex/test.  If we change this url to https://c.login.visual.force.com/apex/cpqquote or https://login.visual.force.com/apex/cpqquote it does not work.  

Any suggestion on what the relative url should be?
Since last week our code coverage has decreased by 10%.  The only changes we made were a couple classes no longer are referenced anywhere in our org.  Is this a new Salesforce setting?  I cannot understand what has happened.
I am trying to generate apex classes from a wsdl.  I removed all imports and pasted the xsd schemas and removed all soap12 references.  I still get an apex error saying Unable to find soap 1.1 address.  Any ideas?  If needed I can paste the wsdl file I am trying to import.  
Recently a visualforce page started running extremely slow when the developer console was open.  It ran fairly fast before, and I havn't added any additional logging.  To make things worse the performance remains slow even if I close the developer console.  The performance only increases when I close my entire browser.  Any thoughts? 
In our workflow once a quote reaches a certain status the opportunity attached to the quote and any other quotes attached to the opportunity need to be locked.  This includes fields and any related lists.  Is this possible?  I have tried page layouts but users can still edit/delete from related lists.  I have also tried validation rules but fail to get these to work on all related lists. 

Any ideas?  This seems like such a basic need and its unfathomable for Salesforce to not have this feature.