• Andrew G
  • PRO
  • 2364 Points
  • Member since 2014
  • Salesforce Learner

  • Chatter
    Feed
  • 77
    Best Answers
  • 0
    Likes Received
  • 1
    Likes Given
  • 11
    Questions
  • 488
    Replies
public with sharing class FieldnotEmptycontrl {

    public static Property__c field {get; set;}

    public FieldnotEmptycontrl(){
    field = new Property__c();

    }

    public static void fieldNotEmpty(List<Property__c> prop){

        if(field.Business__c == null || field.Contact__c == null){

            field.Business__c.addError('You must enter a value!');
            field.Contact__c.addError('You must enter a value!');

        if(field.Business__c != null && field.Contact__c != null){

            field.Business__c.addError('Cannot use two fields at the same time. Please choose only one field Business or Contact');
            field.Contact__c.addError('Cannot use two fields at the same time. Please choose only one field Business or Contact');
        }

        }
    }
}
Here is the Trigger calling the above class and method, but it shows the error • triggers/fieldNotEmpty.trigger: ERROR at line 1, column 1 - Must specify the metadata file 
trigger fieldNotEmpty on Property__c (before insert, before update, after insert) {

    if (Trigger.isBefore) {
        if(Trigger.isInsert){

            FieldnotEmptycontrl.fieldNotEmpty(Trigger.new);
          
        }
    }
}
Please help me to resolve the issue
 
The below batch class will be processing a little over 2.5 million records. The START method will be sending in the whole 2.5 million records to the execute method and the execute method does the processing on each of the 2.5 million records inside a for loop. 
Also the for loop has a SOQL inside which I believe cannot be avoided to get the right numbers. 
Is this the right way of doing this or are there any other better ways. Please help!

Also when the running the below batch class I get the First Error: Too many query rows error.
 
global class MDUSquadRawDataBatchTest implements Database.Batchable<sObject>, Database.Stateful {  
    List<Address_Master__c> addressList = new List<Address_Master__c>();
    Set<String> addresses = new Set<String>();
   
    // Start Method
    global Database.QueryLocator start(Database.BatchableContext BC) {
        return Database.getQueryLocator('SELECT Street_Address__c,City_Name__c FROM MDU_Squad_Raw_Data__c');
    }   
    
    // Execute method
    global void execute(Database.BatchableContext BC, List<MDU_Squad_Raw_Data__c> rawData) {        
        for(MDU_Squad_Raw_Data__c mduRawData: rawData) {
            List<MDU_Squad_Raw_Data__c> addressData = [SELECT Street_Address__c,City_Name__c,Province_Code__c,Postal_Code__c,Internet_Service__c,Video_Service__c,Phone_Service__c FROM MDU_Squad_Raw_Data__c WHERE Street_Address__c=:mduRawData.Street_Address__c AND City_Name__c=:mduRawData.City_Name__c];
            String fullAddress = addressData[0].Street_Address__c+' '+addressData[0].City_Name__c+' '+addressData[0].Province_Code__c+' '+addressData[0].Postal_Code__c;
            
            Address_Master__c theAddress = new Address_Master__c();
            if(!addresses.contains(fullAddress.substringBeforeLast(' '))) {
                theAddress.Name = addressData[0].Street_Address__c;
                theAddress.City_Name__c = addressData[0].City_Name__c;
                theAddress.Province_Code__c = addressData[0].Province_Code__c;
                theAddress.Postal_Code__c = addressData[0].Postal_Code__c; 
                fullAddress = addressData[0].Street_Address__c+' '+addressData[0].City_Name__c+' '+addressData[0].Province_Code__c+' '+addressData[0].Postal_Code__c;
                theAddress.Full_Address_Ext_Id__c = fullAddress;

                addresses.add(fullAddress.substringBeforeLast(' '));
                addressList.add(theAddress); 
            }                                                     
        }            
        Database.Upsert(addressList, Address_Master__c.Fields.Full_Address_Ext_Id__c, true);
    }
    // Finish Method    
    global void finish(Database.BatchableContext BC) {
        
    } 
}

I request if someone could please help me with this, as I am dealing with this for some time, with no idea on how to fix this.
Hey..

I have 4-5 workflows which do the same function on the Account object. They all put a Date Stamp based on different fileds in a picklist. Since we have 5 options in a picklist and we are tracking the date of every option, I have to create 5 different workflows. 

I have little to no experience working with Triggers. Is it possible to achieve this with 1 trigger?


Thanks 
Hey all!

With some help I wrote this custom trigger that allows our reps to list some additional contacts and their information on Lead records that then transform into Contact records on lead convert.
 
trigger CreateMoreLeadContacts on Lead (after update) {

list < Contact > listContacts = new List < Contact>();

for(Lead objLead : trigger.new) {

if(objlead.IsConverted && !trigger.oldMap.get(objLead.Id).IsConverted) {

Contact c1=New Contact(
LastName=objLead.Secondary_Lead_Contact_Name__c,
Phone=objLead.Secondary_Lead_Phone__c,
Email=objLead.Secondary_Lead_Email__c);

c1.AccountId = objLead.ConvertedAccountId;
listContacts.add(c1);

Contact c2=New Contact(
LastName=objLead.Tertiary_Lead_Contact_Name__c,
Phone=objLead.Tertiary_Lead_Phone__c,
Email=objLead.Tertiary_Lead_Email__c);

c2.AccountId = objLead.ConvertedAccountId;
listContacts.add(c2);

     }
        
    }
    
    if ( listContacts.size() > 0 )
        insert listContacts;

}
The trigger works just fine and as expected... however, i've now indentified an issue when trying to convert a Lead when no data is present in both "Secondary Contact Lead Name" & "Tertiary Contact Lead Name".

Only way to get around this with the current trigger is to list dummy Contact name data in the custom lead fields before the Lead gets converted.

What would be the best way to encapsulate the trigger so that it doesn't fire when names aren't listed / just when one additional contact is listed? 



 
The situation: I spun off a sandbox, and within that sandbox, I commented out large portions of code in order to disable a feature we're not going to use, and was linked to an installed package we wished to uninstall.  I ran the entire suit of Apex tests and everything passed with flying colors.

The problem: When I try to deploy the resulting change set into production, I get told "Dependent class is invalid and needs recompilation" for every single item of the change set.  It points to a method in one particular class as the source of the error - a method that I comment out, and I made sure every piece of code referring to that method was commented out too.

According to the help files, the solution was to recompile all Apex classes.  Very well.  Did this in Production, did this in Sandbox, started a new change set and deployment.  Still no dice, the error pops up again.  But I can't recompile any more than what I've already done, so what gives?

How am I supposed to get rid of this error and complete my deployment into production?
I have my client asking below
if an apportunity creation fails, due to any error (validation, trigger, workflow etc), then that should send some alert message or record the information somewhere.


I know flow errors can be sent, or trigger errors can be handled, but in general someone (could be any user, community user, integration user etc) tries to create a record, this fails , how do I capture and send information to specific user or an admin.

I know this can be debugged , that shows there was an error to create record, but is it possible to capture such information and record it elsewhere

thanks
aslam
I have this validation rule in status, where it has 3 values (analysis, process, completed), all the profiles can assign these 3 statuses, but once it is in the completed value you must activate the rule where only the administrator can change that value 
I have it like this:

AND(
          ISPICKVAL(Status__c, "completed"), 
          RecordType.Name = "Sales", 
          NOT( ISNEW()), 
          $Profile.Name <> "System Administrator"
)

Could you help me?
public class CreateCampaignfromLead {
    Public static void AddCampaignmember(list<lead>ListLead){
        list<lead>ListLd=new list<lead>();
        Id OppId;
        Date FCDate;
        Id CampId;
        list<campaignmember> cmmlist = new list<campaignmember>();
        for(Lead ld:ListLead){
            if(ld.Agent_Site_Source__c=='Re-Marketed opportunity' && ld.Referenced_Opportunity__c !=null ){
                OppId=ld.Referenced_Opportunity__c;  
            }
            List<opportunity>OppList=[select id,stagename,Future_Contact_Date__c from opportunity where 
                                      (stagename='No Solution - Not Qualified' OR 
                                       stagename='No Solution - No Experience' 
                                       OR stagename='No Solution - Age Experience' OR
                                       stagename='No Solution - Outside of quote period') AND ID=:OppId];
            
            for(opportunity Opp:OppList){
                FCDate=opp.Future_Contact_Date__c;
            }  
            if(OppList.Isempty()){
                List<opportunity>OpList=[select Id,stagename,CloseDate from opportunity where (stagename='NTU - Deal Lost' OR 
                                                                                               stagename='NTU - Too Expensive' )AND ID=:OppId];
                
                for(opportunity Opp:OpList){
                    FCDate=opp.CloseDate;
                }
            }
            list<campaign>camplist = new list<campaign>();
            camplist = [select Id , Name,Campaign_Date__c from campaign  where
                        CALENDAR_MONTH(Campaign_Date__c) = :FCDate.month() AND CALENDAR_YEAR(Campaign_Date__c) 
                        =:FCDate.YEAR()];
            for(campaign cam:camplist){
                CampId=cam.Id;
            }
            campaignmember cmm = new campaignmember();
            cmm.campaignid= CampId;
            cmm.LeadId =ld.id;
            cmmlist.add(cmm);
        }
        insert cmmlist;
    }
}
I need to avoid booking at the same time i.e one booking is at 7pm to 8pm and another one is booking at 7:30pm to 8pm.
can anyone help to resolve this
I have 5 Controllers which affect opportunities. Each has a test which provides > 90% code coverage in UAT. When I look in production, these tests provide 0% code coverage when the Controllers and related tests are identical between UAT and production. General question is what could cause these tests to fail given the success in UAT and the artifacts promote successfully to production?
Here's the formula I am using for a Validation Rule to require a specific phone number format be entered (xxx) xxx-xxxx. This formula works for me.

AND(
NOT(ISBLANK(HomePhone)),
NOT(REGEX(HomePhone, "\\([0-9]{3}\\) [0-9]{3}-[0-9]{4}"))
)

Is there anything I can add to the formula to prevent it from firing on a specific record type? Let's call it "Record Type A".

Thanks.
Hi,

current formula has 5 405 compiled size, as we know the limit is 5 000.
Do you have any idea how to reduce it?

if(OR(AND(ClientBasket__c = "B",
OR(ISPICKVAL(Owner.FLSA_Job_Title__c,"Junior Account Manager 1"),ISPICKVAL(Owner.FLSA_Job_Title__c,"Junior Account Manager 2"),ISPICKVAL(Owner.FLSA_Job_Title__c,"Account Manager"), ISPICKVAL(Owner.FLSA_Job_Title__c,"Key Account Manager")))=true,
AND(OR(ClientBasket__c = "C",
OR(ISPICKVAL(Owner.FLSA_Job_Title__c,"Senior Key Account Manager"),ISPICKVAL(Owner.FLSA_Job_Title__c,"Expert"))))),1,

if(OR(AND(ClientBasket__c="A",
OR(ISPICKVAL(Owner.FLSA_Job_Title__c,"Junior Account Manager 1"),ISPICKVAL(Owner.FLSA_Job_Title__c,"Junior Account Manager 2"),ISPICKVAL(Owner.FLSA_Job_Title__c,"Account Manager")=true)),
AND(ClientBasket__c = "B",
OR(ISPICKVAL(Owner.FLSA_Job_Title__c,"Senior Key Account Manager"),ISPICKVAL(Owner.FLSA_Job_Title__c,"Expert")))),2,

if(AND(ClientBasket__c = "A",
OR(ISPICKVAL(Owner.FLSA_Job_Title__c,"Key Account Manager"),ISPICKVAL(Owner.FLSA_Job_Title__c,"Senior Key Account Manager")))=true,3,

if(AND(ClientBasket__c = "A",ISPICKVAL(Owner.FLSA_Job_Title__c,"Expert"))=true,4,

0))))
I have written a trigger to roll up opportunity amount on quota. The code is working fine. I have a problem in line 34.
 If I add two new opportunity with amoth as 100 and 100. The roll up is 200.
Again if I edit it recaclulates and adds 200 which is euql to 400. This logic is wrong how to correct it.

trigger Roll on Opportunity (before insert,before update,after insert,after update){
    Set<Id> setOpportunityIds=new Set<Id>();
    
    for(Opportunity c:Trigger.new)
        if(c.StageName == 'Closed Won' && c.Closed_Date__c == 'January' )
        
        
        setOpportunityIds.add(c.id);
    
    
    
    List<Quota__c> ListOfAllOrgs = [select id,RecordTypeId, Actual_Amount__c,Opportunity__c,Quota_Amount__c from Quota__c];
    List<Quota__c> lstCommissionToUpdate=new List<Quota__c>();
    
    for(AggregateResult result:[Select Quota__c,SUM(Amount) From Opportunity 
                                WHERE Id IN :setOpportunityIds GROUP BY Quota__c LIMIT 1 ])
    {
        
        for(Quota__c org : ListOfAllOrgs)
            
        {
            
                    System.debug('Amount value in Org is' + Decimal.ValueOf(String.ValueOf(result.get('expr0'))));
            if(result.get('Quota__c') == org.Id && org.Actual_Amount__c == null )
            {
                if(  org.RecordTypeId == '0122v000002KFRAAA4')
                {
                    org.Actual_Amount__c = 0;
                }
                else{
                    org.Actual_Amount__c = org.Actual_Amount__c + Decimal.ValueOf(String.ValueOf(result.get('expr0'))); 
                    
                    
                    if(result.get('Quota__c') == org.Id && org.Actual_Amount__c != null )
                    {
                        if(  org.RecordTypeId == '0122v000002KFRAAA4')
                        {
                            org.Actual_Amount__c = 0;
                        }
                        else{
                            org.Actual_Amount__c = org.Actual_Amount__c + Decimal.ValueOf(String.ValueOf(result.get('expr0'))); 
                            
                            System.debug('Amount value in Org is' + Decimal.ValueOf(String.ValueOf(result.get('expr0'))));
                        }
                        
                        
                        
                        
                        lstCommissionToUpdate.add(org);
                        System.debug('Amount value in Org is' + Decimal.ValueOf(String.ValueOf(result.get('expr0'))));
                    }
                }
            }
            if(lstCommissionToUpdate.size()>0){
                
                update lstCommissionToUpdate;
                System.debug('Amount value in Org is' + Decimal.ValueOf(String.ValueOf(result.get('expr0'))));
            }
        }
    }
}
We import a csv file daily to new records in a custom object. One of those fields is a long-text area, which I will call "notes". When the notes are imported, they come in as one very long string of text, and each note is separated by "*** yyyy-dd-mm***" (three asterics surrounding the date of the note). I want my "before insert" trigger to organize the long text area, such that a new paragraph begins with each new note. Can someone please assist with writing this trigger?  Here is what I have so far but it is not working:

trigger DischargeAfterInsert on Discharge__c (after insert) {

    for (discharge__c disch : trigger.new){
        string progressnotes = disch.progress_notes__c;
        progressnotes = progressnotes.replace('. ***', '. <br> ***');
        update disch;
            }
}
I am trying to build out a trigger and trigger handler to update a record related to an Opportunity when the Opportunity is updated. We need to do this without editing the related record (Legal Agreement)

Here is the trigger handler class I am working with:
public class OpportunityTriggerHandler {
    public static void OpportunityTriggerHandler(){       
    	Map <Id,  Opportunity> mapOpportunity = new Map <Id, Opportunity>();
    	List<Legal_Agreements__c> listLA = new List<Legal_Agreements__c>();
    	List<Legal_Agreements__c> LAUpdate = new list <Legal_Agreements__c>();
   
    		listLA = [SELECT Id, Status__c, test__c, Opportunity_Stage__c FROM Legal_Agreements__c WHERE Opportunity__r.Id IN : mapOpportunity.keySet() ];
  			system.debug('Legal Agreement list size ' + listLA.size());
        
    		if(listLA.size() > 0) {
       			 for (Legal_Agreements__c LA : listLA ) {
           			 LA.test__c = LA.Opportunity__r.StageName;
                     LA.test__c = LA.Opportunity_Stage__c;
        		}
    		}
	}
}
And this is the trigger:
trigger OpportunityTrigger on Opportunity (before insert, before update, before delete, after insert, after update, after delete) {
      OpportunityTriggerHandler handler = new OpportunityTriggerHandler();

This is all really rough at this point, but if anyone could guide me, I'd appreciate it.
 
Hi Everyone,

I am currently reviewing the validation rules on opportunities. I've found the following lines, which I'd like to understand. Within the context of a validation rule which triggers the error only when the rule is True, what does these formulas do? Do they related to "Related Lists" child objects of the opportunity? 

Thank you.

NOT(ISBLANK($ObjectType.Live_Event_Coverage__c.Fields.Live_Event_Allotment_Opportunity__c)), /*allows Live Events to process*/
NOT(ISBLANK($ObjectType.SE_Customer_Solution__c.Fields.Opportunity__c )), /*allows SE Customer Solutions to process*/
NOT(ISBLANK( $ObjectType.Live_Event_Coverage_Timing__c.Fields.CoverageLink__c)), /*allows Live Event Timings to process*/
Hello, I hope someone might be able to provide me some guidance!

I work in an area where we provide training to school districts, and we have recently started building out a tracking system to monitor our technical assistance to the districts. We currently have it where we have an object built which stores districts as record pages, and an object to create technical assistant events as a record. It currently uses a lookup field to link a technical assistant event to the school district. We are hoping to learn how we can make it possibile to link the technical assistant event to more than one school district.  I would like to be able to still have the function of the lookup field to search the school district, but the added ability of attaching a single technical assistant event to a district.

This was if I am out training at District 1 and District 2 I can record that in the same event, not have to create two different events.

I have attached a screenshot of the current new event creation form.

Any help is appriciated, thanks!

User-added image
I created a trigger to update a custom field (Mailing County) before insert of a Contact.  The trigger takes the MailingPostalCode entered by the user and finds the County in which that zip code is found.  This is done via a custom object (Zip_Code__c) in which the Postal Codes are stored along with their respective Counties.

I would love any feedback on how to make this trigger better, but specifically I am confused because one of my test methods is not working (TestContactWithValidZip).  This particular test gets caught by my addError clause of my trigger.

Trigger:
trigger CountyLookupByZip on Contact (before insert) {
    for (Contact c : Trigger.New) {
        if(c.MailingPostalCode != null) {
        	List<Zip_Code__c> contactCounty = new List<Zip_Code__c>();
            contactCounty = [SELECT Id,
                                County__c,
                                Postal_Code__c
         				 FROM   Zip_Code__c 
        			     WHERE  Postal_Code__c = :c.MailingPostalCode];
            if(contactCounty.size() != 0){
            	c.Mailing_County__c = contactCounty[0].County__c;
            } else {
                c.MailingPostalCode.addError('Postal Code not found. Please ensure the postal code is a valid Virginia zip code.');
            }
        }
	}
}
Test Clas:
@isTest
public class TestCountyLookupByZip {

    @isTest
    public static void TestContactWithNullZip() {
        // Test data setup
        // Create a contact without a Mailing Postal Code
        // and check to ensure County is also null
        Contact contactNullZip = new Contact(LastName = 'Test');
        insert contactNullZip;
        
        // Perform Test
        System.assertEquals(contactNullZip.Mailing_County__c, null);
    }

    @isTest
    public static void TestContactWithValidZip() {

        // Test data setup
        // Create a contact with a valid VA Mailing Postal Code
        // and check to ensure County is updated correctly
        
    	Contact contactValidZip = new Contact(LastName = 'Test', MailingPostalCode = '20101');
        insert contactValidZip;
        
        // Perform Test
        System.assertEquals(contactValidZip.Mailing_County__c, 'Loudoun');
    }   
    
    @isTest
    public static void TestContactWithInvalidZip() {
        // Test data setup
        // Create a contact with an invalid Mailing Postal Code
        // and throw an error
        Test.startTest();
        try {
       		Contact contactInvalidZip = new Contact(LastName = 'Test', MailingPostalCode = '17602');
        	insert contactInvalidZip;
        // Perform Test
        } catch(Exception e) {
			System.Assert(e.getMessage().contains('FIELD_CUSTOM_VALIDATION_EXCEPTION'));
            System.Assert(e.getMessage().contains('Postal Code not found. Please ensure the postal code is a valid Virginia zip code.'));
        }
        Test.stopTest();
    }
}


 

Hi All, 

New to apex and having an issue with a trigger(below). Its firing everytime but i would like it to only fire on records that are of a certain record type.
Any assistance is appreciated.

trigger efs_DealTrigger on Deal__c (after update, after insert) {
    
    List<Deal__c> dealsToUpdate = new list<Deal__c>();
    for (Deal__c deal: trigger.new){
        if(deal.RecordTypeId == '0120Y000000ITgrQAG'){
            dealsToUpdate.add(deal);
        } 
    }
    
    
    for(Deal__c dealsInCriteria: dealsToUpdate) {
        if(trigger.isAfter && trigger.isInsert){
            efs__.EgnyteSyncQueueTrigger.onAfterInsert();
        }
        else if(trigger.isAfter && trigger.isUpdate){
            efs__.EgnyteSyncQueueTrigger.onAfterUpdate();
        }
    }
}

Thanks

Richard

I have a simple rigger that automatically creates a custom PO_Number__c record when an Opportunity is created. This PO_Number__c an Account__c lookup field and an Opportunity__c lookup field that also gets automatically populated by the trigger.

 

In my test class, my first test method singleOpp() succeeds, but I want to test a situation where a builk insert of Opportunities happens. My second test method is bulkOpps(). I'm not sure how to finish this method off to make sure that all the PO_Number__c records that were automatically created have the correct Account__c and Opportunity__c fields.

 

Any help would be greatly appreciated! Here's my code:

 

TRIGGER:
 

trigger createPurchaseOrder on Opportunity (after insert) {
    // Initialize PO Numbers to insert list
    List<PO_Number__c> ponsToInsertList = new List<PO_Number__c>();

    for (Opportunity opp : Trigger.new) {
        if (opp.Id != null && AccountId != null) {
            // Create PO Number records
            PO_Number__c pon   = new PO_Number__c();
            pon.Account__c     = opp.AccountId;
            pon.Opportunity__c = opp.Id;
            ponsToInsertList.add(pon);
        }
        if (!ponsToInsertList.isEmpty()) {
            // Insert PO Number records 
            insert ponsToInsertList;
        }
    }
}


TEST CLASS:
 
@isTest
private class CreatePurchaseOrderTest {
    @isTest static void singleOpp() {
        // Create Account
        Account acc = new Account();
        acc.Name    = 'Test Account';
        insert acc;

        // Create Opportunity
        Opportunity opp = new Opportunity();
        opp.Name        = 'Test Opp';
        opp.CloseDate   = Date.today();
        opp.StageName   = 'Initial Contact';
        opp.AccountId   = acc.Id;
        insert opp;

        // get opp
        List<Opportunity> updatedOpp = [
            SELECT Id, AccountId
              FROM Opportunity
             WHERE Id = :opp.Id
             LIMIT 1
        ];

        // check for PO Number record
        List<PO_Number__c> pon = [
            SELECT Id, Opportunity__c, Account__c
              FROM PO_Number__c
             LIMIT 1
        ];

        System.assertEquals(1, pon.size(), 'pon list size not correct');
        System.assertEquals(updatedOpp.get(0).Id, pon.get(0).Opportunity__c, 'Opportunity on PO Number not correct');
        System.assertEquals(updatedOpp.get(0).AccountId, pon.get(0).Account__c, 'Account on PO Number not correct');
    }

    @isTest static void bulkOpps() {
        // Create multiple Accounts
        List<Account> accList = new List<Account>();
        for (Integer i = 0; i < 500; i++) {
        Account myAcc = new Account();
        myAcc.Name    = 'Test Acc ' + i;
        accList.add(myAcc);
        }
        insert accList;

        // Create multiple Opps
        List<Opportunity> oppList = new List<Opportunity>();
        for (Integer i = 0; i < 500; i++) {
        Opportunity myOpp = new Opportunity();
        myOpp.Name        = 'Test Opp ' + i;
        myOpp.StageName   = 'Initial Contact';
        myOpp.CloseDate   = Date.today();
        myOpp.AccountId   = accList.get(i).Id;
        oppList.add(myOpp);
        }
        insert oppList;

        // Check for PO Number records
        List<PO_Number__c> ponList = [
            SELECT Id, Account__c, Opportunity__c
              FROM PO_Number__c
        ];

        // HOW CAN I DETERMINE IF EACH PO NUMBER HAS THE CORRECT OPPORTUNITY AND ACCOUNT ?????
        // EX: PO Number 1 has Account 1 and Opportunity 1 on it's Account__c and Opportunity__c fields
        // EX: PO Number 1 had Account 2 and Opportunity 2 on it's Account__c and Opportunity__c fields

        System.assertEquals(accList.get(0).Id, ponList.get(0).Account__c, 'Account not correct on PO Number');
        System.assertEquals(oppList.get(0).Id, ponList.get(0).Opportunity__c, 'Opportunity not correct on PO Number');
    }
}

 
Hi

I have a need to be able to create 2 different types of Cases on our Community Portal.

Basically, I have 2 global actions that each create a Case but with a different Record Type.  I have created the buttons on the home page of my community site.  I know they throw to the Create Record Page and I have created 2 x page variations, but when I try the preview and try the buttons, I get which ever page variation is set to Default.

Surely i'm not the first to try this.  Is there some documenation that clearly descibes how to do this?  Or if someone can give me some direction it would be appreciated

Regards
Andrew G
Hi

On the Visualforce page, there is a check box to select to enable the visualforce page to be available under Lightning.
User-added image

Since we use GitHub, how do I see this change in the Git Repository?  Is there an XML tag that is set to true when this check box is enabled?

Regards
Andrew
 
Hello

We are using the FSL managed package.  Needing to write some test coverage for the Maintenance Plan.  In the test class, I am trying to create the Maintenance Plan record as such:
MaintenancePlan maintPlan 
		= new MaintenancePlan( AccountId = testaccs[0].Id,
						Billing_Account__c = testaccs[0].Id,
						WorkTypeId = mpWt[0].Id,
						StartDate = tempDate,
						Customer_Purchase_Order_No__c = 'dummy data',
						Invoicing_Method__c = 'One Invoice per Work Order',
						Crew_Size__c = 2,
						Frequency = 1,
						FrequencyType = 'Months',
						GenerationTimeframe = 1,
						GenerationTimeframeType = 'Months',
						NextSuggestedMaintenanceDate = tempDate,
						WorkOrderGenerationMethod = 'One work order line item per asset',
						SvcApptGenerationMethod = 'One service appointment per work order',
						MaintenancePlanTitle = 'Dummy Title',
						Description = 'Dummy Description'
						);

But on Save, I get an error:
Result: [OPERATION FAILED]: classes/CS_WorkOrderTriggerHandler_Test.cls: Field does not exist: WorkOrderGenerationMethod on MaintenancePlan (Line: 313, Column: 5)
classes/CS_WorkOrderTriggerHandler_Test.cls: Field does not exist: SvcApptGenerationMethod on MaintenancePlan (Line: 313, Column: 5)
(bold added for highlights)
Now in my field list for Maintenance Plan I see :
Snippet showing the offending field names which error message says 'doesn't exist'

So, I've copy pasted the Names but same error.
I have check Field Level Security  - System Admin plus others are listed.
Thoughts or feedback?

Regards
Andrew
 
Hi
In the FSL managed package, from a Maintenance Plan there is an action "Generate Work Orders". 
Shows action menu for Generate Work Orders action
I have done some customisation which rely on the Work Order being generated from the Maintenance Plan.

For my test coverage, how do I invoke the "Generate Work Orders" action in a test class?

Regards
Andrew
Hi
I'm doing a trigger that is triggered from the Assigned Resource.  The trigger works in the UI, however, I'm having an issue with the Test Code.

I receive an error:
FIELD_CUSTOM_VALIDATION_EXCEPTION, Cannot change status from New to Scheduled: []

Now, if i do the same from the UI, there is no error regarding the status change.  The status change is allowed in the FSL administration.  I can assign using the dispatcher console - all good.  And I can mimic the process i'm using in the test code in the UI (editing the SA directly) with out error.  
Wondering if any one has seen this error before?
Code is included below:
@isTest static void test_AssignedResource_Insert() {
		List<AssignedResource> toInsert = new List<AssignedResource>();

		//retrieve a service resource
		List<ServiceResource> listSR = new List<ServiceResource>([SELECT Id, Name FROM ServiceResource WHERE Name = 'Technician One']);
		ServiceResource sr1 = listSR[0];

		// retrieve the Service Appointment created by test data
		List<WorkOrder> workOrders = new List<WorkOrder>([SELECT Id FROM WorkOrder WHERE Subject ='Test Subject1']);
		List<Id> woIds = new List<Id>();
		for (WorkOrder wo : workOrders ) {
			woIds.add(wo.Id);
		}
		if (woIds.size() > 0 ) {
			List<ServiceAppointment> appts = new List<ServiceAppointment> ();
			appts = [SELECT Id FROM ServiceAppointment WHERE Work_Order__c IN :woIds];
			//for all the appts - should be one - create an assigned resource
			if(appts.size()>0) {
				for( ServiceAppointment sa : appts ) {
					sa.SchedStartTime = datetime.newInstance(2019, 4, 19, 11, 00, 0);
					sa.SchedEndTime = datetime.newInstance(2019, 4, 19, 11, 30, 0);

					AssignedResource ar = new AssignedResource(ServiceAppointmentId=sa.Id,ServiceResourceId=sr1.Id);
					toInsert.add(ar);
				}
				update appts;

				insert toInsert;

				List<ServiceAppointment> assignedSA = new List<ServiceAppointment>([SELECT Id,Technician_Name__c FROM ServiceAppointment WHERE Work_Order__c IN :woIds]);
				System.assertEquals(assignedSA.size(), 1);
				System.assertEquals(assignedSA[0].Technician_Name__c,sr1.Name);

			} else {

			}


		} else {
			//exception
			System.assertNotEquals(woIds.size(), 0);
		}


	}
the error occurs on the insert of the assigned resources
insert toInsert;
IF i change the code such that I manually do the status change in the code example:
sa.SchedStartTime = datetime.newInstance(2019, 4, 19, 11, 00, 0);
sa.SchedEndTime = datetime.newInstance(2019, 4, 19, 11, 30, 0);
sa.Status = 'Scheduled';
the error is returned for the update of the service appointments.
update appts;

Feed back greatly appreciated.

Andrew




 
Hi
I'm playing with an Apex trigger for Work Order Object.   In the trigger,I have a need to reference a list of Work Types on multiple occassions, in different parts of the trigger.  The question relates to how do I minimise the number of times I do a SOQL to get those work types.
Example of Trigger
trigger cs_workorderTrigger on WorkOrder (before insert, after insert, after update) {
    if ( trigger.isBefore ) {
        if ( trigger.isInsert ) {
            CS_WorkOrderTriggerHandler.handleBeforeInsert( trigger.new );
	}
    } else {  //trigger is after
        if ( trigger.isInsert ) {
            CS_WorkOrderTriggerHandler.handleAfterInsert( trigger.new );
        } else {
            CS_WorkOrderTriggerHandler.handleAfterUpdate( trigger.new );
	}
    }
}
And my (cut down) hanlder looks like:
public with sharing class CS_WorkOrderTriggerHandler {
			
	public static void handleBeforeInsert(List<WorkOrder> newWorkOrders) {
		populateWorkOrder( newWorkOrders );
	}

	public static void handleAfterInsert(List<WorkOrder> workOrders){
		//declare some variables 
		List<Id> listWorkTypeIds = new List<Id>();

		//List of Ids where their is an auto generate feature enabled
		List<Worktype> workTypes = new List<WorkType>([SELECT Id FROM WorkType WHERE ShouldAutoCreateSvcAppt = TRUE]);

		for ( WorkOrder workOrder : workOrders ) {
			//do some stuff with work Order - like checking the work type Id
		}
	}


	public static void handleAfterUpdate(List<WorkOrder> oldWorkOrders, List<WorkOrder> workOrders, Map<Id,WorkOrder> newValues, Map<Id,WorkOrder> oldValues) {
		//declare some variables 
		List<Id> listWorkTypeIds = new List<Id>();

		//List of Ids where their is an auto generate feature enabled - HEY , THIS IS THE SAME AS THE AFTER INSERT QUERY

		for ( WorkOrder workOrder : workOrders ) {
			//do some other stuff with the work orders, and I still need the work type ids, but this work here is different to the after Insert stuff so i can't combine into a single method.
		}
	}

	public static void populateWorkOrder(List<WorkOrder>workOrders) {
		System.debug('DEBUG: populate Work Order');
		//Here I am going to do some other stuff, and I need that slightly different list of that Work Type Ids
		//something like 
		List<workType> workTypes = new List<WorkType>([SELECT Id,Customer_Type__c,Name FROM WorkType WHERE ShouldAutoCreateSvcAppt = TRUE]);
		//and play with the list a bit differently
	}

	public static void createServiceAppointments(WorkOrder workOrder, Integer saToCreate ) {
		//Create some records here
	}
	
}

I tried doing a constructor at the top of the trigger handler, but I was getting errors like "non static method can be called form static method" or something like that.  It basically broke the other methods I have within the trigger handler.

Any pointers appreciated.

Andrew G
Hello

I'm doing a bit of code where I'm checking if a Work Type Id in a Work Order is in a List for Work Type Ids, but the contains method does not seem to be detecting the match:
Code snippet 
List<ServiceAppointment> svcAppts = new List<ServiceAppointment>();

		//List of Ids where their is an auto generate feature enabled
		List<Id> listWorkTypeIds = new List<Id>();
		for ( WorkType wt : [SELECT Id FROM WorkType WHERE ShouldAutoCreateSvcAppt = TRUE] )  {
			listWorkTypeIds.add(wt.Id);
		}
		System.debug('DEBUG : Worktype count ' + listWorkTypeIds.size());

		
		for ( WorkOrder workOrder : workOrders ) {
			tempDecimal = workOrder.Crew_Size__c;
			crewSize  = tempDecimal.intValue();
			System.debug('DEBUG : crewSize: ' + crewSize);
			
			tempDecimal = workOrder.ServiceAppointmentCount;
			System.debug('DEBUG : RAW service count : ' + tempDecimal);
			System.debug('****DEBUG : list work type : ' + listWorkTypeIds[0]);
			System.debug('****DEBUG : WO work type : ' + workOrder.workTypeId);

			if (listWorkTypeIds.contains(workOrder.workTypeId)) {
				apptCount = tempDecimal.intValue() + 1;		
				System.debug('DEBUG : ADJUSTED service count : ' + tempDecimal);				
			} else {
				apptCount = tempDecimal.intValue();
				System.debug('DEBUG : SAME service count : ' + tempDecimal);
			}
Now, the debug looks like this:
08:10:49.875 (1834107162)|SOQL_EXECUTE_BEGIN|[92]|Aggregations:0|SELECT Id FROM WorkType 
08:10:49.875 (1848717624)|SOQL_EXECUTE_END|[92]|Rows:1
08:10:49.875 (1849133376)|USER_DEBUG|[95]|DEBUG|DEBUG : Worktype count 1
08:10:49.875 (1849315483)|USER_DEBUG|[101]|DEBUG|DEBUG : crewSize: 1
08:10:49.875 (1849418406)|USER_DEBUG|[104]|DEBUG|DEBUG : RAW service count : 0
08:10:49.875 (1849462073)|USER_DEBUG|[105]|DEBUG|****DEBUG : list work type : 08q0l00000001jtAAA
08:10:49.875 (1849543426)|USER_DEBUG|[106]|DEBUG|****DEBUG : WO work type : 08q0l00000001jtAAA
08:10:49.875 (1849692808)|USER_DEBUG|[113]|DEBUG|DEBUG : SAME service count : 0

So, the debug shows that the Ids are apparently the same, but the IF statement using the the contains does resolve to TRUE.

Any thoughts on what I am missing?

Regards
Andrew
 
Hello

Playing with Work Types and the Auto Create feature.  I know there is a check box to tick which will auto create the Service Appointments.
However, I have a need to generate multiple Service Appointments for a single Work Order.  The multiple appointments will have the same parameters as a crew will come together to do that particular piece of work.  (Note: the Service Crew feature in FSL does not meet the needs of the business).

Now, I have played with Process Builder to action this, but I get unusual results when the auto create feature is enabled.  (And yes, we do need the auto create feature for other business processes).
In process builder I can populate the address for the Work Order from the Case, and then address to Service Appointment from Work Order.  I can get the multiple service appointments by using the recursive feature of the Process Builder. 
However, if I set the WorkType to a type with Auto Create, I get extra Service Appointments and/or Service Appointments without addresses.

So, the question is, in the execution process of events, (i.e. before trigger, after triggers, process builder...etc), where does the Auto Create feature kick in ?  It is obviously part of the managed package and can't be viewed by us mere mortals, but it is happening, but when/where?
And a slight aside, when does the standard field Service Appointment Count (in Work Order) populate in that series of events?  As understanding that may also provide an option for a solution.

Part of the reason for asking is that I am looking to take this to a trigger, but I'm thinking i may run into the same issues there.

Regards
Andrew
Potentially silly question.

We have purchased Community Licenses and intend to have/offer our customers to use the Salesforce App to access our community page. (As well as being browser based).
With Community License there is an API limit.
The question would be "Does the Salesforce App interactions count against the API limits for the Community License?"

LIttle background - our company was considering constructing a custom App using RESTful API to interacts, and these I know would count.  Just curious if the Salesforce App operated in the same manner.

Regards
Andrew
Hello

Having an issue implementing some code which is to create a PDF document from a trigger.  I have used this as a reference/start point :
https://jungleeforce.wordpress.com/2014/06/11/generate-a-pdf-and-attach-it-to-record-from-a-trigger-in-salesforce-restful/comment-page-1/
The code:
public with sharing class SvcApptTriggerController {
	@Future(callout=true)
	public static void addPDFAttach(string sessionId, list<id> svcApptIdList){
		System.debug('@@@@@ in addPDFAttach of SvcApptTriggerController');

		HttpRequest req = new HttpRequest();
		req.setEndpoint('https://'+URL.getSalesforceBaseUrl().getHost()+'/services/apexrest/AddPDFtoSvcAppt/');
		req.setMethod('POST');
		req.setBody('{"svcApptIdList":'+JSON.serialize(svcApptIdList)+'}');
		req.setHeader('Authorization', 'Bearer '+ sessionId);
		req.setHeader('Content-Type', 'application/json');
		Http http = new Http();
		System.debug('@@@@@ before TEST if');
		if(!test.isRunningTest()){
			System.debug('@@@@@ in TEST if');
			HTTPResponse res = http.send(req);
		}
	}
}
The debug log snippet:
Error message from debug log - Unauthorised
Screenshot of remote Site settings:
Remote Site Settings

So the endpoint reported in the debug logs is in the remote site settings.
The PDF creation code works from the workbench - which obviously uses a different authentication model (name/password).

Feeling that I have missed something obvious.

Regards
Andrew
 
Hello
I am doing an inline table as a lightning component, but after the save event the button will not disappear.
I have found a post that mentions clearing the default values,
component.find("SADataTable").set("v.draftValues", null);
but playing with that line will cause the button to hide, but the table data does not reload after save.
I have also played with firing a refreshview, but no luck either
$A.get('e.force:refreshView').fire();
My component
<aura:component controller="ServiceAppointmentListController" implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="recordId" type="Id" />
    <aura:attribute name="WorkOrder" type="WorkOrder" />
    <aura:attribute name="ServiceAppointments" type="ServiceAppointment" />
	<aura:attribute name="Columns" type="List" />
    <aura:attribute name="saveDraftValues" type="Object" />
    <aura:handler name="init" value="{!this}" action="{!c.myAction}" />
    <force:recordData aura:id="workOrderRecord" recordId="{!v.recordId}" targetFields="{!v.WorkOrder}" layoutType="FULL" />
    <lightning:card title="{! 'Service Appointment List for ' + v.WorkOrder.WorkOrderNumber}">
        <!-- Service Appointment list goes here -->
        <lightning:datatable 
                aura:id="SADataTable"
                keyField="Id" 
        		data="{! v.ServiceAppointments }" 
                columns="{! v.Columns }" 
                onsave="{!c.handleSave}" />
    </lightning:card> 
</aura:component>
The JS controller
({
	myAction : function(component, event, helper) {
        component.set("v.Columns", [
            {label:"Appt Id", fieldName:"AppointmentNumber", type:"text"},
            {label:"Duration", fieldName:"Duration", type:"number", editable : 'true'},
            {label:"Duration Type", fieldName:"DurationType", type:"text", editable : 'true'}
        ]);
		var action = component.get("c.getServiceAppointments");
        action.setParams({
            recordId: component.get("v.recordId")
        });
        action.setCallback(this, function(data) {
            component.set("v.ServiceAppointments", data.getReturnValue());
        });
        $A.enqueueAction(action);
	},
    handleSave: function (component, event, helper ) {
		helper.saveDataTable(component, event, helper);
    }
})
The helper manages the save and posts toast messages.
({
    saveDataTable : function(component, event, helper) {
        var editedRecords =  component.find("SADataTable").get("v.draftValues");
        var totalRecordEdited = editedRecords.length;
        var action = component.get("c.updateServiceAppointments");
        action.setParams({
            'editedSAList' : editedRecords
        });
        action.setCallback(this,function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                //***if update is successful ***
                if(response.getReturnValue() === true){
                    helper.showToast({
                        "title": "Record Update",
                        "type": "success",
                        "message": totalRecordEdited+" Service Appointment Records Updated"
                    });
                    helper.reloadDataTable();
                } else{ //***if update failed ***
                    helper.showToast({
                        "title": "Error!!",
                        "type": "error",
                        "message": "Error in update"
                    });
                }
            }
        });
        $A.enqueueAction(action);
    },

    //*** Show toast with provided params ***
    showToast : function(params){
        var toastEvent = $A.get("e.force:showToast");
        if(toastEvent){
            toastEvent.setParams(params);
            toastEvent.fire();
        } else{
            alert(params.message);
        }
    },
    //*** reload data table ***
    reloadDataTable : function(){
    var refreshEvent = $A.get("e.force:refreshView");
        if(refreshEvent){
            refreshEvent.fire();
        }
    }
})
For completeness, my Server Side controller
public class ServiceAppointmentListController {
    @AuraEnabled
    public static List<ServiceAppointment> getServiceAppointments(Id recordId) {
       return [SELECT Id, AppointmentNumber, Duration, DurationType  FROM ServiceAppointment WHERE ParentRecordId = :recordId];
    }
    
    @AuraEnabled
    public static boolean updateServiceAppointments(List<ServiceAppointment> editedSAList) {
        try {
            update editedSAList;
            return true;
        } catch(Exception e){
            return false;
        }
    }
}

Any assistance appreciated.  I have been troubleshooting this for a day, but seem to be going around in circles.
Regards
Andrew 





 
Iam getting this error :-


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

@isTest(seealldata = true)
public class QuoteTrigger_PayTerms_GenerateDoc_Test{
             
         Static testMethod Void testMethod2(){
           
             Account acc = new Account();
             acc.Name = 'Test Account';
             acc.Website ='www.test.com';
             acc.Type='Banking';
             insert acc;
             
             Contact con = new contact();
             con.lastname='test contact';
             con.LeadSource = 'Inbound';
             con.Contact_Status__c='Open';
             con.accountid=acc.id;
             insert con;
             
             opportunity opp = new opportunity();
             opp.name ='Test Opp';
             opp.stagename='Closed Won';
             opp.Type= 'New Business';
             opp.CloseDate=system.today().addmonths(2);
             opp.Upsell_Potential__c ='No';
             opp.RenewalDate__c = system.today();
             opp.accountid=acc.id;
             opp.Contact_Name__c=con.id;
             insert opp;  
             
             OpportunityContactRole ocr = new OpportunityContactRole();
                ocr.ContactId = con.Id;
                ocr.OpportunityId = opp.Id;
                ocr.IsPrimary = TRUE;
                ocr.Role = 'Decision Maker';
                insert ocr;
             
             SBQQ__Quote__c oldquote2 = new SBQQ__Quote__c();
             oldquote2.SBQQ__Primary__c = true;
             oldquote2.SBQQ__Opportunity2__c = opp.id;
             oldquote2.SBQQ__StartDate__c = system.today();
             oldquote2.SBQQ__EndDate__c= system.today().addmonths(3);
             oldquote2.SBQQ__SubscriptionTerm__c=1;
             oldquote2.Status_Of_Approval__c='Pending';
             oldquote2.Document_Template__c= 'Auto Renew 3';
             oldquote2.SBQQ__PaymentTerms__c= 'monthly';
             oldquote2.SBQQ__BillingCountry__c ='United States';
             oldquote2.Long_Form__c=false;
             oldquote2.Logo__c = false;
             oldquote2.Attach_Terms_and_Conditions__c= 'No';
             insert oldquote2;
   //--------------------------------------------------------------------------Annual Starts here----------------
             oldquote2.Document_Template__c= 'Auto Renew';
             oldquote2.SBQQ__PaymentTerms__c= 'Annual';
             oldquote2.Logo__c = false;
             oldquote2.Attach_Terms_and_Conditions__c= 'Enterprise SaaS';
             update oldquote2;
             
             oldquote2.Document_Template__c= 'Auto Renew';
             oldquote2.SBQQ__PaymentTerms__c= 'Annual';
             oldquote2.Logo__c = true;
             oldquote2.Attach_Terms_and_Conditions__c= 'Enterprise SaaS';      
             update oldquote2;   
             
             oldquote2.Document_Template__c= 'Auto Renew';
             oldquote2.SBQQ__PaymentTerms__c= 'Monthly';
             oldquote2.Logo__c = false;
             oldquote2.Attach_Terms_and_Conditions__c= 'Enterprise SaaS';
             update oldquote2;
             
             oldquote2.Document_Template__c= 'Auto Renew';
             oldquote2.SBQQ__PaymentTerms__c= 'Monthly';
             oldquote2.Logo__c = true;
             oldquote2.Attach_Terms_and_Conditions__c= 'Enterprise SaaS';      
             update oldquote2;   
         

         }
             
               
             Static testMethod Void testMethod3(){

//----------------------------------------------Standard saas------------------------------------------------
           

             Account acc = new Account();
             acc.Name = 'Test Account';
             acc.Website ='www.test.com';
             acc.Type='Banking';
             insert acc;
             
             Contact con = new contact();
             con.lastname='test contact';
             con.LeadSource = 'Inbound';
             con.Contact_Status__c='Open';
             con.accountid=acc.id;
             insert con;
             
             opportunity opp = new opportunity();
             opp.name ='Test Opp';
             opp.stagename='Closed Won';
             opp.Type= 'New Business';
             opp.CloseDate=system.today().addmonths(2);
             opp.Upsell_Potential__c ='No';
             opp.RenewalDate__c = system.today();
             opp.accountid=acc.id;
             opp.Contact_Name__c=con.id;

             insert opp;  
             
              OpportunityContactRole ocr = new OpportunityContactRole();
              ocr.ContactId = con.Id;
              ocr.OpportunityId = opp.Id;
              ocr.IsPrimary = TRUE;
              ocr.Role = 'Decision Maker';
              insert ocr;
             
             SBQQ__Quote__c oldquote2 = new SBQQ__Quote__c();
             oldquote2.SBQQ__Primary__c = true;
             oldquote2.SBQQ__Opportunity2__c = opp.id;
             oldquote2.SBQQ__StartDate__c = system.today();
             oldquote2.SBQQ__EndDate__c= system.today().addmonths(3);
             oldquote2.SBQQ__SubscriptionTerm__c=1;
             oldquote2.Status_Of_Approval__c='Pending';
             oldquote2.Document_Template__c= 'Auto Renew';
             oldquote2.SBQQ__PaymentTerms__c= 'monthly';
             oldquote2.SBQQ__BillingCountry__c ='United States';
             oldquote2.Long_Form__c=false;
             oldquote2.Logo__c = false;
             oldquote2.Attach_Terms_and_Conditions__c= 'No';
             insert oldquote2;

             oldquote2.Document_Template__c= 'Auto Renew';
             oldquote2.SBQQ__PaymentTerms__c= 'Annual';
             oldquote2.Logo__c = false;
             oldquote2.Attach_Terms_and_Conditions__c= 'Standard SaaS';
             update oldquote2;
             
             oldquote2.Document_Template__c= 'Auto Renew';
             oldquote2.SBQQ__PaymentTerms__c= 'Annual';
             oldquote2.Logo__c = true;
             oldquote2.Attach_Terms_and_Conditions__c= 'Standard SaaS';      
             update oldquote2;   
             
             oldquote2.Document_Template__c= 'Auto Renew';
             oldquote2.SBQQ__PaymentTerms__c= 'Monthly';
             oldquote2.Logo__c = false;
             oldquote2.Attach_Terms_and_Conditions__c= 'Standard SaaS';
             update oldquote2;
             
             oldquote2.Document_Template__c= 'Auto Renew';
             oldquote2.SBQQ__PaymentTerms__c= 'Monthly';
             oldquote2.Logo__c = true;
             oldquote2.Attach_Terms_and_Conditions__c= 'Standard SaaS';      
             update oldquote2;   
         

         }
            
    
        
    }
  • March 31, 2020
  • Like
  • 0
I am trying to pull the data from `Opportunity` object in SalesForce using bulk API. My query looks like this:

```
opportunity = sf.bulk.Opportunity.query('SELECT Id, Name, LeadSource, Probability from Opportunity')
print(opportunity)
```
It does return the data with no issues, however, if I want to select more columns it gives me:

```
IndexError: list index out of range
```
Help! 
Our org is fairly new, 15 months and I have an Apex Trigger that auto creates a Membership record based on one day after the Expiration Date. The new Membership record is created with one day added, My question is related to the "deactivation" of the prevous record when the new reord is created. I am completely new to Apex as this is an urgent request to get this automated so we can remove the manual updates to the "older" Memberhsip records, either by individual or data load. here is my trigger. How to modify to deactivate the previous membership record?
**/
trigger MembershipTrigger on Membership__c (before insert, after insert, after update) {
    
    if(Trigger.isInsert && Trigger.isBefore) {
        MembershipHelper.SetPreviousMembership( (List<Membership__c>)Trigger.new );
    }

    if(Trigger.isAfter) {
        MembershipHelper.UpdateAccountJoinDate( (List<Membership__c>)Trigger.new );
    }
}
 
public with sharing class FieldnotEmptycontrl {

    public static Property__c field {get; set;}

    public FieldnotEmptycontrl(){
    field = new Property__c();

    }

    public static void fieldNotEmpty(List<Property__c> prop){

        if(field.Business__c == null || field.Contact__c == null){

            field.Business__c.addError('You must enter a value!');
            field.Contact__c.addError('You must enter a value!');

        if(field.Business__c != null && field.Contact__c != null){

            field.Business__c.addError('Cannot use two fields at the same time. Please choose only one field Business or Contact');
            field.Contact__c.addError('Cannot use two fields at the same time. Please choose only one field Business or Contact');
        }

        }
    }
}
Here is the Trigger calling the above class and method, but it shows the error • triggers/fieldNotEmpty.trigger: ERROR at line 1, column 1 - Must specify the metadata file 
trigger fieldNotEmpty on Property__c (before insert, before update, after insert) {

    if (Trigger.isBefore) {
        if(Trigger.isInsert){

            FieldnotEmptycontrl.fieldNotEmpty(Trigger.new);
          
        }
    }
}
Please help me to resolve the issue
 
how to show account related opportunity releted product unique record count on account object with trigger.

account -> opportunity -> product

thanks in advance.
Hello guys, I'm not sure if this is the right place to post that kind of question but I really need a light..

I was used to be a fullstack developer (C# and Java) and also mobile developer (flutter). I did some interviews and 99% of companies that looks for a mobile developer (with knowledge in flutter) also requires native knowledge (swift/kotlin).

So here I'm stucked to what should I fork.

I need some impartial opinions, I understand that this is something that I want to decide myself, but is always good to receive some advices..

1) Should I build my path in mobile development? The good thing is that I already developed some complete apps with medium/high complexity, but in this path I need also to study Kotlin/Swift

2) Should I build my path in SalesForce developer? The good thing is that I already feel very comfortable using Java and Angular (which is "cousin" of Apex and Lighting). The bad thing is that I need to studied more deeply salesforce (isnt a bad thing to be honest) but I noticed that almost ALL open jobs asks for a Salesforce developer with 1+ year of experienced, so I'm not sure how can I achieve experience if no one want a developer without it.

Have someone here already faced that kind of "carrer bifurcation"?

Thank you!
The below batch class will be processing a little over 2.5 million records. The START method will be sending in the whole 2.5 million records to the execute method and the execute method does the processing on each of the 2.5 million records inside a for loop. 
Also the for loop has a SOQL inside which I believe cannot be avoided to get the right numbers. 
Is this the right way of doing this or are there any other better ways. Please help!

Also when the running the below batch class I get the First Error: Too many query rows error.
 
global class MDUSquadRawDataBatchTest implements Database.Batchable<sObject>, Database.Stateful {  
    List<Address_Master__c> addressList = new List<Address_Master__c>();
    Set<String> addresses = new Set<String>();
   
    // Start Method
    global Database.QueryLocator start(Database.BatchableContext BC) {
        return Database.getQueryLocator('SELECT Street_Address__c,City_Name__c FROM MDU_Squad_Raw_Data__c');
    }   
    
    // Execute method
    global void execute(Database.BatchableContext BC, List<MDU_Squad_Raw_Data__c> rawData) {        
        for(MDU_Squad_Raw_Data__c mduRawData: rawData) {
            List<MDU_Squad_Raw_Data__c> addressData = [SELECT Street_Address__c,City_Name__c,Province_Code__c,Postal_Code__c,Internet_Service__c,Video_Service__c,Phone_Service__c FROM MDU_Squad_Raw_Data__c WHERE Street_Address__c=:mduRawData.Street_Address__c AND City_Name__c=:mduRawData.City_Name__c];
            String fullAddress = addressData[0].Street_Address__c+' '+addressData[0].City_Name__c+' '+addressData[0].Province_Code__c+' '+addressData[0].Postal_Code__c;
            
            Address_Master__c theAddress = new Address_Master__c();
            if(!addresses.contains(fullAddress.substringBeforeLast(' '))) {
                theAddress.Name = addressData[0].Street_Address__c;
                theAddress.City_Name__c = addressData[0].City_Name__c;
                theAddress.Province_Code__c = addressData[0].Province_Code__c;
                theAddress.Postal_Code__c = addressData[0].Postal_Code__c; 
                fullAddress = addressData[0].Street_Address__c+' '+addressData[0].City_Name__c+' '+addressData[0].Province_Code__c+' '+addressData[0].Postal_Code__c;
                theAddress.Full_Address_Ext_Id__c = fullAddress;

                addresses.add(fullAddress.substringBeforeLast(' '));
                addressList.add(theAddress); 
            }                                                     
        }            
        Database.Upsert(addressList, Address_Master__c.Fields.Full_Address_Ext_Id__c, true);
    }
    // Finish Method    
    global void finish(Database.BatchableContext BC) {
        
    } 
}

I request if someone could please help me with this, as I am dealing with this for some time, with no idea on how to fix this.
Hi All,

I am getting system.null pointer exception: attempt to de-reference a null object, when trying to insert a record with null value in date field.
How to resolve this error. Need your assistance to fix this issue.

Below is my Trigger:
Trigger:


trigger insertDailyPractices on Study_Plan__c (after insert) 
{
    System.debug('--- Inside Trigger ---');
    List<Daily_Practice__c> dplist = new List<Daily_Practice__c>();    
    
    for(Study_Plan__c sp : Trigger.New)
    {
            Integer daycount = sp.Phase_Start_Date__c.daysBetween(sp.Phase_End_Date__c); ----/// Getting error in this line.
            
System.debug('--- Inside For Loop ---' + sp.Phase_Start_Date__c);
            System.debug('--- Day Count ---' + daycount);
     
        for(integer i=0; i<=daycount; i++)
        {
            Daily_Practice__c dps = new Daily_Practice__c();
            dps.Due_Date__c = sp.Phase_Start_Date__c.addDays(i) + 1;
            dps.StudyPlan__c = sp.Id;
            dps.Status__c = 'Assigned';
            dplist.add(dps);
        }
    }
    
    if(dplist.size() > 0)
    {
        insert dplist;
    }    
    system.debug('--- Inserted Daily Practice ---'+ dplist.size());
}

Thanks
Tried using contain as per below but not sure why it is not returning correct value 
this is returning F when running it on 15.03.2020  , whereas the excepted result is T since its 3rd month and is in the list
IF((CONTAINS(TEXT(MONTH(TODAY())), "1:3:5:7:8:10:12")),"T" , "F")
Hello all. I am making a class that ensures that there is an attachment on an Opp whenever its closed won. Below is my class that actually does the logic. Below that is the test class. The logic works fine but I can only get 42% coverage though. The underlined code is what is not being covered, this is in a Lightning instance fyi. Thanks for the help!

public class OpportunityHandler {
    public static void checkOppForAttachment (List<Opportunity> oppList){
        
        for(Opportunity opp : oppList){
            if(opp.stageName == 'Closed Won' || opp.stageName == 'Closed Won (R)'){
                ContentDocumentLink cdl = null;
                List<ContentDocumentLink> cdl2 = [Select Id from ContentDocumentLink where LinkedEntityId =:opp.Id];
                   
                if (cdl2.isEmpty()){

                    opp.addError('Please ensure the contract is attached prior to closing this Opportunity');
                }
            }
        }
    }
}

Test Class
@isTest
public class OpportunityHandlerTest {
    @isTest public static void validateAttachment() {
        //Create Account and Opportunity
    List<RecordType> acctRecType = [Select Id from RecordType where developerName = 'Company' and sObjectType = 'Account'];
    List<RecordType> oppRecType  = [Select Id from RecordType where developerName = 'AM_Channel' and sObjectType = 'Opportunity'];
            Test.startTest();
        try{
    Account acct      = new Account();
    acct.name         = 'Test Account1';
    acct.RecordTypeId = acctRecType.get(0).id;
    insert acct;
        
    Opportunity opp     = new Opportunity();
        opp.Name        = 'test opp';
        opp.CloseDate   = system.today()+1;
        opp.StageName   = 'Initial Pitch/Demo';
        opp.Use_Case__c = 'Brand Tracker';
        opp.AccountId   = acct.Id;
        opp.RecordTypeId = oppRecType.get(0).id;
        insert opp;
        
    Opportunity opp2     = new Opportunity();
        opp2.Name        = 'test opp2';
        opp2.CloseDate   = system.today()+1;
        opp2.StageName   = 'Initial Pitch/Demo';
        opp2.Use_Case__c = 'Brand Tracker';
        opp2.AccountId   = acct.Id;
        opp2.RecordTypeId = oppRecType.get(0).id;
        insert opp2;
       

    ContentVersion contentVersion = new ContentVersion(
          Title          = 'a picture',
          PathOnClient   = 'Pic.jpg',
          VersionData    = Blob.valueOf('Test Content'),
          IsMajorVersion = true);
        insert contentVersion; 
        
List<ContentDocument> documents = [SELECT Id, Title, LatestPublishedVersionId FROM ContentDocument];

//create ContentDocumentLink  record 
    ContentDocumentLink cdl = New ContentDocumentLink();
        cdl.LinkedEntityId = opp.id;
        cdl.ContentDocumentId = documents[0].Id;
        cdl.shareType = 'V';
        cdl.visibility = 'AllUsers';
        insert cdl;
        
List<Opportunity> updateList = new List<Opportunity>();

List<ContentDocumentLink> cdl2 = [Select Id from ContentDocumentLink where LinkedEntityId =:opp.Id];
            List<Opportunity> oldOpp = [Select id from Opportunity where Name = 'test opp'];
                for (Opportunity runUpdate : oldOpp){
                    runUpdate.stageName = 'Closed Won (R)';
                    updateList.add(runUpdate);
                    system.debug(runUpdate.stageName);
                    update updateList;
                    System.assertEquals(documents.size(), 1);
                }
             }
        catch(Exception e){
            System.Assert(e.getMessage().contains('Please ensure the contract is attached prior to closing this Opportunity'));
        }
            test.stopTest();
    }

}
Hi,

I have 2 picklist name Practice Stage and BC Stage. I have created Text Formula Field name ''Funnel Stage''.

Values of "Practice Stage" is  - Cold, Demo Booked, Demo Completed, Interested, Not Interested. 
Values of "BC Stage" is Enabled, Disabled.

What I want is if Practice Stage is NOT equal to Cold, Demo Booked, Demo Completed, Interested, Not Interested ''Funnel Stage'' shows BC Stage value. and IF BC Stage is blank, ''Funnel Stage'' Shows ''Practice Stage'' value. 

Is this possible?
Hey all!

With some help I wrote this custom trigger that allows our reps to list some additional contacts and their information on Lead records that then transform into Contact records on lead convert.
 
trigger CreateMoreLeadContacts on Lead (after update) {

list < Contact > listContacts = new List < Contact>();

for(Lead objLead : trigger.new) {

if(objlead.IsConverted && !trigger.oldMap.get(objLead.Id).IsConverted) {

Contact c1=New Contact(
LastName=objLead.Secondary_Lead_Contact_Name__c,
Phone=objLead.Secondary_Lead_Phone__c,
Email=objLead.Secondary_Lead_Email__c);

c1.AccountId = objLead.ConvertedAccountId;
listContacts.add(c1);

Contact c2=New Contact(
LastName=objLead.Tertiary_Lead_Contact_Name__c,
Phone=objLead.Tertiary_Lead_Phone__c,
Email=objLead.Tertiary_Lead_Email__c);

c2.AccountId = objLead.ConvertedAccountId;
listContacts.add(c2);

     }
        
    }
    
    if ( listContacts.size() > 0 )
        insert listContacts;

}
The trigger works just fine and as expected... however, i've now indentified an issue when trying to convert a Lead when no data is present in both "Secondary Contact Lead Name" & "Tertiary Contact Lead Name".

Only way to get around this with the current trigger is to list dummy Contact name data in the custom lead fields before the Lead gets converted.

What would be the best way to encapsulate the trigger so that it doesn't fire when names aren't listed / just when one additional contact is listed? 



 
The situation: I spun off a sandbox, and within that sandbox, I commented out large portions of code in order to disable a feature we're not going to use, and was linked to an installed package we wished to uninstall.  I ran the entire suit of Apex tests and everything passed with flying colors.

The problem: When I try to deploy the resulting change set into production, I get told "Dependent class is invalid and needs recompilation" for every single item of the change set.  It points to a method in one particular class as the source of the error - a method that I comment out, and I made sure every piece of code referring to that method was commented out too.

According to the help files, the solution was to recompile all Apex classes.  Very well.  Did this in Production, did this in Sandbox, started a new change set and deployment.  Still no dice, the error pops up again.  But I can't recompile any more than what I've already done, so what gives?

How am I supposed to get rid of this error and complete my deployment into production?

We are happy to provide a space for you to list developer and admin openings that may be of interest to the Force.com community. Please ensure your posts are effectively titled with the position and location you're looking for, and don't forget to include instructions for applying or getting in touch with you when you post. 

 

If you are a developer looking for work, you are allowed to post that here, however you are not allowed to post the same information repeatedly (spamming). You also may not use this space for advertising your business. 

 

This board is offered as a service to our community and those found to be abusing it will be banned from posting. Examples of abuse include posting blanket generic responses to job listings & starting new topics that only serve to advertise your business.

 

I welcome your feedback and suggestions!