• SF Dev Ceno
  • NEWBIE
  • 10 Points
  • Member since 2017

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 3
    Questions
  • 3
    Replies
All,
I'm trying to update a field value on the Account based off a value on a related object called License. The batch job seems to ignore the Days Remaining field and changing all the Accounts the initial query captures. It should only change the Relationship Type field on the Account if the Days Remaining on the License is less than 0. Please see code below:
 
// Briceno: ALCHEMISTS-1806 : Set Former Partner & Customer
// Update Account Relationship Type based on Account Type and License Days Remaining < 0


global class WR_SetFormerCustomerAndPartnerBatch implements Database.Batchable<sObject> {
    //License_Setting__c settings = License_Setting__c.getInstance();
    //Decimal updateLookback = settings.Update_Lookback_Value__c;
    //Date dateScope = System.today().addDays(Integer.valueOf(-updateLookback));
    String CURRENTCUSTOMER = 'Current Customer';
    String CURRENTPARTNER = 'Current Partner';

    global final String query;

    global WR_SetFormerCustomerAndPartnerBatch(){
        query = 'SELECT Id, Relationship_Type__c, Type, RecordTypeId FROM Account WHERE Relationship_Type__c LIKE :CURRENTCUSTOMER OR Relationship_Type__c LIKE :CURRENTPARTNER';
    }

    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext bc, List<Account> scope) {

        // Direct Licenses
    	List<License__c> lst_AccountLicenses = new List<License__c>();
        	lst_AccountLicenses = [SELECT Id, Days_Remaining__c, Account__c, Capability_Type__c  FROM License__c WHERE Account__c IN :scope AND Capability_Type__c = 'Full'];

      	// Indirect Licenses
    	List<License__c> lst_AccountRelatedLicenses = new List<License__c>();
        	lst_AccountRelatedLicenses = [SELECT Id, Days_Remaining__c, Opportunity__r.Reseller_Account__c, Opportunity__r.Distributor_Account__c, Capability_Type__c FROM License__c WHERE (Opportunity__r.Reseller_Account__c IN :scope OR Opportunity__r.Distributor_Account__c IN :scope ) AND Capability_Type__c = 'Full'];

        List<Account> lst_Account = new List<Account>();
        if(scope.size() > 0){
            lst_Account = [SELECT Id, RecordTypeId, Type, Relationship_Type__c FROM Account WHERE Id IN: scope];
        }

        Map<Id, Account> accMap = new Map<Id, Account>();
        	accMap.putAll(lst_Account);
	        if(!accMap.isEmpty()){
	        	update accMap.values();
	        }

        if(!accMap.isEmpty()){
            List<License__c> lst_License = new List<License__c>();
        	
        	/**for(Account s : scope){
        		Account acct = (Account) s;**/

        	for(Account acct : accMap.values()){
	        	
	            if(acct.Type.equals('Business')){
	                lst_License.addAll(lst_AccountLicenses);
	                lst_License.addAll(lst_AccountRelatedLicenses);
	            }

	            if(acct.Type.equals('Consumer')){
	                lst_License.addAll(lst_AccountLicenses);
	                lst_License.addAll(lst_AccountRelatedLicenses);
	            }

	            if(acct.Type.equals('MSP')){
	                lst_License.addAll(lst_AccountLicenses);
	            }
	            
	            if(acct.Type.equals('MSSP')){
	                lst_License.addAll(lst_AccountLicenses);
	            }
	            
	            if(acct.Type.equals('Platform')){
	                lst_License.addAll(lst_AccountLicenses);
	            }

	            if(acct.Type.equals('MSP/Reseller Hybrid')){
	                lst_License.addAll(lst_AccountLicenses);
	                lst_License.addAll(lst_AccountRelatedLicenses);
	            }

	            if(acct.Type.equals('Reseller') || acct.Type.equals('Distributor')){
	                lst_License.addAll(lst_AccountRelatedLicenses);
	            }

	            if(lst_License.size() > 0){
	                for(License__c license: lst_License){
	                    if(license.Days_Remaining__c < 0){
                    		// Record Type of End User (Types Include: Consumer, Business)
	                        if(acct.RecordTypeId == '01261000000Xtcz' && acct.Relationship_Type__c == 'Current Customer')
	                            acct.Relationship_Type__c = 'Former Customer';
	                            //accMap.put(acct.Id, acct);
	                            break;
	                    } else {
	                    	// Record Type of Partner (Types Include: MSP, MSP/Reseller Hybrid, MSSP, Reseller, Distributor, Platform, OEM, IoT, MSSP, Fraud, Retail)
	                    	if(acct.RecordTypeId == '01261000000Xtcu' && acct.Relationship_Type__c == 'Current Partner')
	                            acct.Relationship_Type__c = 'Former Partner';
	                            //accMap.put(acct.Id, acct);
	                        
	                    }
	                }
	            }
		    }

		    update accMap.values();
        }

    }

    global void finish(Database.BatchableContext bc) {
        AsyncApexJob a = [Select Id, ApexClassId, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email, ExtendedStatus, CompletedDate
                          From AsyncApexJob
                          Where Id = :bc.getJobId()
                          Order by CompletedDate];

        // Send the email to the job submitter
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {a.CreatedBy.Email};
        mail.setToAddresses(toAddresses);
        mail.setSenderDisplayName('WR_SetFormerCustomerAndPartnerBatch: Batch Results');
        mail.setSubject('Status: ' + a.Status);
        mail.setPlainTextBody( 'Job ID ' +a.ApexClassId +
                               ' processed ' + a.TotalJobItems +
                               ' batches with ' +a.JobItemsProcessed +
                               ' Job Items Processed, ' + a.NumberOfErrors + 
                               ' Failures, and Extended Status of: ' + a.ExtendedStatus);
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });

    }
}

 
All,
I have written two methods on Account for validation rules based on related Opportunity field values. My debug log is returning values in both lists in the methods when it should only return values in one method. Basically, both methods are firing and therefore it's just defaulting to second method's error messages. This means that my conditions for the related Opportunity fields are returning false. Can someone see why?
Line 26 and 60
public with sharing class WR_AccountValidationRules {
    Map<Id, Account> oldAccts;
    Map<Id, Account> newAccts;
    Set<Id> acctIds = new Set<Id>();

    public WR_AccountValidationRules(Map<Id, Account> oldTriggerAccts, Map<Id, Account> newTriggerAccts) {
      oldAccts = oldTriggerAccts;
      newAccts = newTriggerAccts;
    }

    public void executeOrderProvValidation(){
        Map<Id, Account> acctMapToUpdate = new Map<Id, Account>();
        Map<Id, Opportunity> oppByAccId = new Map<Id, Opportunity>([Select Id, AccountId, Order_Provisioning_Status__c, StageName From Opportunity]);
        for(Opportunity opp : oppByAccId.values()){
            if(opp.StageName != '5. Closed-Won'&& (opp.Order_Provisioning_Status__c == 'Provisioning And Billing - In Progress' ||
                                                   opp.Order_Provisioning_Status__c == 'Order Entry - Complete')){
                acctIds.add(opp.AccountId);
            }
        }

        System.debug('!= Stage 5 size acctIds '+ acctIds.size());

        Map<Id, Account> acctMap = new Map<Id, Account>([Select Id, Name, Type, RecordTypeId From Account Where Id in :acctIds]);

        System.debug('!= Stage 5 size acctMap '+ acctMap.size());

        for(Id oppId : oppByAccId.keySet()){
            Id acctId = oppByAccId.get(oppId).AccountId;
            acctMapToUpdate.put(oppId, acctMap.get(acctId));
        }

        System.debug('!= Stage 5 size acctMapToUpdate '+ acctMapToUpdate.size());

        for(Account a : newAccts.values()){
            if(oldAccts.get(a.Id).Type != newAccts.get(a.Id).Type){
                a.addError('Account Type cannot be modified while a related Opportunity has an Order Provisioning Status of Provisioning And Billing - In Progress OR Order Entry - Complete.');
            }

            else if(oldAccts.get(a.Id).RecordTypeId != newAccts.get(a.Id).RecordTypeId){
                a.addError('Account Record Type cannot be modified while a related Opportunity has an Order Provisioning Status of Provisioning And Billing - In Progress OR Order Entry - Complete.');
            }
        }
    }

    public void executeStage5Validation(){
        Map<Id, Account> acctMapToUpdate = new Map<Id, Account>();
        Map<Id, Opportunity> oppByAccId = new Map<Id, Opportunity>([Select Id, AccountId, Order_Provisioning_Status__c, StageName From Opportunity]);
        for(Opportunity opp : oppByAccId.values()){
            if(opp.Id != null && opp.StageName == '5. Closed-Won' && (opp.Order_Provisioning_Status__c == 'Order Entry – In Progress' || 
                                                                      opp.Order_Provisioning_Status__c == 'Order Entry – On Hold' ||
                                                                      opp.Order_Provisioning_Status__c == 'Order Entry – Complete')){
                acctIds.add(opp.AccountId);
            }
        }
        System.debug('== Stage 5 size acctIds '+ acctIds.size());


        Map<Id, Account> acctMap = new Map<Id, Account>([Select Id, Name, Type, RecordTypeId From Account Where Id in :acctIds]);

        System.debug('== Stage 5 size acctMap '+ acctMap.size());

        for(Id oppId : oppByAccId.keySet()){
            Id acctId = oppByAccId.get(oppId).AccountId;
            acctMapToUpdate.put(oppId, acctMap.get(acctId));
        }

        System.debug('== Stage 5 size acctMapToUpdate '+ acctMapToUpdate.size());

        for(Account a : newAccts.values()){
            if(oldAccts.get(a.Id).Type != newAccts.get(a.Id).Type){
                a.addError('Account Type cannot be modified while a related Opportunity is in Stage 5 and has an Order Provisioning Status of Order Entry – In Progress, Order Entry – On Hold, or Order Entry – Complete.');
            }
            else if(oldAccts.get(a.Id).RecordTypeId != newAccts.get(a.Id).RecordTypeId){
                a.addError('Account Record Type cannot be modified while a related Opportunity is in Stage 5 and has an Order Provisioning Status of Order Entry – In Progress, Order Entry – On Hold, or Order Entry – Complete.');
            }
        }
    }
}
Trigger:
trigger WR_MasterAccountTrigger on Account (
  before insert, after insert, 
  before update, after update, 
  before delete, after delete) {

    // to exclude data migration
    if(Utility_Class.isDM()){
      return;
    }

    if(system.isBatch() || system.isFuture())
      return;

  if (Trigger.isBefore) {
    if (Trigger.isInsert) {
      // Call class logic here!
    }

    if (Trigger.isUpdate) {
      // Call class logic here!
      new WR_AccountValidationRules(trigger.oldMap, trigger.newMap).executeOrderProvValidation();
      new WR_AccountValidationRules(trigger.oldMap, trigger.newMap).executeStage5Validation();
    }

    if (Trigger.isDelete) {
      // Call class logic here!
    }
  }

  if (Trigger.IsAfter) {
    if (Trigger.isInsert) {
      // Call class logic here!
    }

    if (Trigger.isUpdate) {
      // Call class logic here!

    }

    if (Trigger.isDelete) {
      // Call class logic here!
    }
  }
}
All,
I'm attempting to simply invoke my apex class from a trigger instead of the process builder. How do I invoke the following class in my trigger? It doesn't fire, yet my debug log shows the objIds.size() = 1.

Class:
global class WR_UpdateGeo {
   @InvocableMethod
   
   public static void getAccountIds(List<Id> objIds) {
     
      //Get the sObject token from the first ID
      Schema.SObjectType token = objIds[0].getSObjectType();
      Schema.DescribeSObjectResult dr = token.getDescribe();
       
      String Scountry = 'country';   
      if (dr.getName() == 'account')
         Scountry = 'BillingCountry';  
      
      // Construct query dynamically.
      String queryString = 'SELECT id, ' + Scountry + ' FROM ' + dr.getName() + ' WHERE ';
      for(ID objId : objIds) {
            queryString += 'Id=\'' + objId + '\' OR ';
          }  
            
      queryString = queryString.subString(0, queryString.length() - 4);
      sObject[] objDBList = Database.query(queryString);
       
       // GEO
       String geo = '';
        List<Country_GEO_Mapping__c> lst_countryGeoMapping = [SELECT Country_Name__c, GEO_Name__c FROM Country_GEO_Mapping__c ];
        Map<String, String> map_countryGeoMapping = new Map<String, String>();
      
        for(Country_GEO_Mapping__c    cg: lst_CountryGeoMapping){
            map_countryGeoMapping.put(cg.Country_Name__c, cg.GEO_Name__c);
          }
            
       // Update the GEO on the sObjects
       for(Integer i = 0; i < objDBList.size(); i++) {
          
          if (dr.getName() == 'account') {
              if(map_countryGeoMapping.containsKey(String.valueOf(objDBList[i].get('BillingCountry')))) {
                 geo = map_countryGeoMapping.get(String.valueOf(objDBList[i].get('BillingCountry'))); }
                 objDBList[i].put('GEO__c', geo);
               }
              //geo = 'APAC';}
             //objDBList[i].put('GEO__c', Utility_Class.FindGeoFromCountry(String.valueOf(objDBList[i].get('BillingCountry'))));
           
          else {
             if(map_countryGeoMapping.containsKey(String.valueOf(objDBList[i].get('country')))) {
                 geo = map_countryGeoMapping.get(String.valueOf(objDBList[i].get('country')));  }
                 objDBList[i].put('GEO__c', geo);
               }
             //objDBList[i].put('GEO__c', Utility_Class.FindGeoFromCountry(String.valueOf(objDBList[i].get('country')))); 
        }       
        
       Database.SaveResult[] srList = Database.update(objDBList, false);
    }
}

Trigger:
trigger WR_BeforeLead on Lead (before insert, before update) {
    List<Id> objIds = new List<Id>();

    if (Trigger.isBefore && Trigger.isUpdate) {
        for(Lead l : Trigger.New){
			if(l.Id != null) {
				objIds.add(l.Id);
			}
		}

		if(objIds.size() > 0){
			System.debug(objIds.size());
			WR_UpdateGeo.getAccountIds(objIds);
		}
	}
}

All,
I'm attempting to simply invoke my apex class from a trigger instead of the process builder. How do I invoke the following class in my trigger? It doesn't fire, yet my debug log shows the objIds.size() = 1.

Class:
global class WR_UpdateGeo {
   @InvocableMethod
   
   public static void getAccountIds(List<Id> objIds) {
     
      //Get the sObject token from the first ID
      Schema.SObjectType token = objIds[0].getSObjectType();
      Schema.DescribeSObjectResult dr = token.getDescribe();
       
      String Scountry = 'country';   
      if (dr.getName() == 'account')
         Scountry = 'BillingCountry';  
      
      // Construct query dynamically.
      String queryString = 'SELECT id, ' + Scountry + ' FROM ' + dr.getName() + ' WHERE ';
      for(ID objId : objIds) {
            queryString += 'Id=\'' + objId + '\' OR ';
          }  
            
      queryString = queryString.subString(0, queryString.length() - 4);
      sObject[] objDBList = Database.query(queryString);
       
       // GEO
       String geo = '';
        List<Country_GEO_Mapping__c> lst_countryGeoMapping = [SELECT Country_Name__c, GEO_Name__c FROM Country_GEO_Mapping__c ];
        Map<String, String> map_countryGeoMapping = new Map<String, String>();
      
        for(Country_GEO_Mapping__c    cg: lst_CountryGeoMapping){
            map_countryGeoMapping.put(cg.Country_Name__c, cg.GEO_Name__c);
          }
            
       // Update the GEO on the sObjects
       for(Integer i = 0; i < objDBList.size(); i++) {
          
          if (dr.getName() == 'account') {
              if(map_countryGeoMapping.containsKey(String.valueOf(objDBList[i].get('BillingCountry')))) {
                 geo = map_countryGeoMapping.get(String.valueOf(objDBList[i].get('BillingCountry'))); }
                 objDBList[i].put('GEO__c', geo);
               }
              //geo = 'APAC';}
             //objDBList[i].put('GEO__c', Utility_Class.FindGeoFromCountry(String.valueOf(objDBList[i].get('BillingCountry'))));
           
          else {
             if(map_countryGeoMapping.containsKey(String.valueOf(objDBList[i].get('country')))) {
                 geo = map_countryGeoMapping.get(String.valueOf(objDBList[i].get('country')));  }
                 objDBList[i].put('GEO__c', geo);
               }
             //objDBList[i].put('GEO__c', Utility_Class.FindGeoFromCountry(String.valueOf(objDBList[i].get('country')))); 
        }       
        
       Database.SaveResult[] srList = Database.update(objDBList, false);
    }
}

Trigger:
trigger WR_BeforeLead on Lead (before insert, before update) {
    List<Id> objIds = new List<Id>();

    if (Trigger.isBefore && Trigger.isUpdate) {
        for(Lead l : Trigger.New){
			if(l.Id != null) {
				objIds.add(l.Id);
			}
		}

		if(objIds.size() > 0){
			System.debug(objIds.size());
			WR_UpdateGeo.getAccountIds(objIds);
		}
	}
}