2

Criteria:

  • Obj A is MASTER to Obj B

  • Obj B has 3 fields... Obj B.a [long text area], Obj B.b [Long text area], Obj B.c [Checkbox].

  • Obj A has 1 field... Field X[Picklist]

  • Field Obj A.X CANNOT / NOT EQUAL To "COMPLETED" ... IF( Obj B.a && Obj B.b && Obj B.c = null)

Error should be display at Obj A level...

Please help asap... Should it trigger or Workflow [WF - I have tried this bt no luck ]

4
  • Can there be many B's for a given A ? Commented Mar 8, 2016 at 6:52
  • trigger. WF is for update field or email. WF is not equals for validation rule. Commented Mar 8, 2016 at 7:42
  • trigger should help you out. Bec you need to check this when you update or insert records in obj A (right).
    – Anu
    Commented Mar 8, 2016 at 7:45
  • @Anu Exactlyy .. any sample code appreciated
    – Gidy
    Commented Mar 8, 2016 at 15:50

1 Answer 1

1

Object A is the parent of Object B => there can be multiple records of B under a record of A. You also did mention that the error needs to be displayed at the level of A. Hence we need to add this "validation"(I didn't say rule) at the object A level - only then would this validation be checked whenever we are updating a record of object A. We would be needing this check only on the update of record of object A because at the time of its creation, child records of B does not exist.

This is a scenario for accessing the children record values from the parent. This can be done using only a trigger not a validation rule or workflow. This is so because, there can be multiple children under a parent and hence it is not possible to manage accessing their values through validation rules or workflows, which actually do allowing traversing up the ladder(child to parent - because there is always one parent to a child but not vice versa). We would need querying into the database, hence trigger it is.

Update: The code as requested

    /** NAMING CONVENTION
ObjectA__c - Parent object
ObjectB__c - Child object
Each field is named as per your suggestion, adding a __c to its name, asuming they are custom fields
So the fields are
ObjectB :
1.a__c
2.b__c
3.c__c

ObjectA :
1.x__c
CHILD RELATIONSHIP NAME of ObjectB from ObjectA is assumed to be ObjectB__r. To see the exact name, navigate to the lookup/MD field on ObjectB that looks upto ObjectA. See 'Child RelationShip Name' value, append an '__r'
LOGIC ASSUMPTION: Considering all the child records of B under A , not using any filter.
*/

trigger testTrigger on objectA__c(before update){

    if(trigger.isBefore){//Checks if this is a before trigger instance
        if(trigger.isUpdate){//Checks if this is a before update trigger instance

            //Consider all the records being updated and pass them along into a method that will take care of the rest
            //trigger.new is a context variable that contains the newer values of all the records that are being updates
            //trigger.new can contain upto 200 records
            TestTriggerHandler.validateRecords(trigger.new, trigger.oldMap);
        }
    }
}




public class TestTriggerHandler{

    //This method will validate the records of A that have been updated to see if it is okay to change their x__c picklist field to 'completed'
    public static void validateRecords(List<ObjectA__c> InputList, Map<id,ObjectA__c> OldRecMap){

        //Filter out only those ObjectA records whose x__c field has been changes into 'Completed'
        //Since in this methid we are validating only for such records
        List<ObjectA__c> FilteredInputList = new List<ObjectA__c>();
        for(ObjectA__c Arec: InputList){
            if(Arec.x__c != OldRecMap.get(Arec.id).x__c){   //Checks if the value in the x__c field has changed in this update, then only proceed
                if(Arec.x__c == 'Completed'){ //Checks if the updated value of x__c is equal to 'Completed', then only proceed
                    FilteredInputList.add(Arec);    //Add that particulat ObjectA record to the list
                }
            }
        }

        //Collect the IDs of all the ObjectA records involved in the update transaction, into a set
        Set<ID> ObjectAIDSet = (new Map<ID,ObjectA__c>(FilteredInputList)).keySet();

        //Query all the records and their corresponding child records from the database
        //The below query gives a list of ObjectA. Each element of the list is a record of ObjectA and its fields can be accessed.
        //From a record of objectA on the list, its children objectB records can also be accessed as a list of ObjectB
        //The query is used in the constructor of a map
        //In this map, the objectA record ID will be the key, while the ObjectA record will be the value. And the list of children ObjectB records for each ObjectA record can be accessed
        Map<id,ObjectA__c> ObjectAMap = new Map<Id,ObjectA__c>([SELECT id,x__c,(SELECT id,a__c,b__c,c__c FROM ObjectB__r) FROM ObjectA__c WHERE id IN :ObjectAIDSet]);

        //Now we check for each record of interest in the transaction i.e. x__c field has ben changed to 'Completed' kind of records
        //Check if the objectA record is qualified for its x__c to be updated to 'Completed'
        for(ObjectA__c Arec: FilteredInputList){
            List<ObjectB__c> ChildBRecords = Arec.ObjectB__r; //Note that I used the child relationship name
            //Instantiating the boolean deciding variable to false
            Boolean StopDMLForRecord = false;

            //Looping through the children ObjectB records to see, if the parent ObjectA record is eligible to have its x__c field set to 'Completed'
            for(ObjectB__c BRec : ChildBRecords){
                //Checking if all the 3 fields are null
                //Recommended to do more detailed "blank" checks on the fields too
                if(BRec.a__c == null  && BRec.c__c == null  && BRec.c__c == null){
                    //All the 3 fields are null in this child ObjectB record then the ObjectA record shouldn't be updated
                    //Set the flag to true
                    StopDMLForRecord = true;
                }
            }

            //Checked if the ObjectA record is eligible to be updated based on the field null checks of its children 
            //Based on its result selectively block ineligible ObjectA records from being successfully updated
            if(StopDMLForRecord){
                //The below method will halt the DML for the particular record and provide the error message
                //Recommended to store this message in a custom label
                Arec.addError('This x__c value cannot be COMPLETED');
            }
        }

    }
}
6
  • Hi Stygon, I'm actually new to salesforce ... any similar trigger code is appreciated please...
    – Gidy
    Commented Mar 8, 2016 at 13:38
  • @Gidy sure, give me some time and I will include it in the question
    – Prajith
    Commented Mar 8, 2016 at 13:47
  • @ Stygon, Will it be better if I provide you the fields and the actual object name??
    – Gidy
    Commented Mar 8, 2016 at 15:51
  • Sure @gidy . that will be better
    – Prajith
    Commented Mar 8, 2016 at 15:55
  • @Gidy Added the code sample. There might be some simple compilation errors. Do get back to me for anything regarding this :) . Hope this helps and Welcome to SFDC
    – Prajith
    Commented Mar 8, 2016 at 18:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .