function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Ashish KhairkarAshish Khairkar 

Creating primary records for Master-Detail relation

Suppose i have to build follwoing scenario

Two objects A & B have a master detail relationship, A being the master and B can contain many number of records

But only one record in B can be primary to A, say a Primary Flag field exist on B

When i check the Primary Flag of any new record in B, then the primary flag on old record should disappear 
Best Answer chosen by Ashish Khairkar
Alain CabonAlain Cabon
Hi, 

The Nayana's solution is excellent and I would have done the same at work.

There is an alternative "zero code" that programmers never use with an autolaunched flow and a process.

The Flow Designer is a powerful tool of Salesforce but it is little used (zero code but also not easy to "read" and verify without clicking everywhere, I will have to extract all the logic from the metadata for an automatic documentation). 

https://help.salesforce.com/articleView?id=process_action_flow.htm&language=en_US&type=0

You can pass the owner ID (reference of A) from the process to the flow.

User-added image

User-added image

User-added image

User-added image

User-added image

Salesforce have almost succeeded in "zero code" applications with powerful tools like the flow designer and the process builder but it is little used by the administrators.

Regards

All Answers

Nayana KNayana K
trigger BTrigger on B__c(after insert, after update)
{
	BtriggerHandler objHandler = new BtriggerHandler();
	if(Trigger.isAfter && Trigger.isInsert)
	{
		objHandler.onAfterInsert(Trigger.New);
	}
	
	if(Trigger.isAfter && Trigger.isUpdate)
	{
		objHandler.onAfterUpdate(Trigger.oldMap, Trigger.New);
	}
}

public class BtriggerHandler
{
	public void onAfterInsert(List<B__c> lstNewB)
	{
		setPrimary(new Map<Id, B__c>(), lstNewB);
	}
	
	public void onAfterUpdate(Map<Id, B__c> mapOldB, List<B__c> lstNewB)
	{
		setPrimary(mapOldB, lstNewB);
	}
	
	private void setPrimary(Map<Id, B__c> mapOldB, List<B__c> lstNewB)
	{
		Set<Id> setAId = new Set<Id>();
		Set<Id> setBIdExclude = new Set<Id>();
		for(B__c objB : lstNewB)
		{
			if(objB.Primary__c && 
				(Trigger.isInsert || (Trigger.isUpdate && mapOldB.get(objB.Id).Primary__c != objB.Primary__c))
			)
			{
				setAId.add(objB.A__c);
				setBIdExclude.add(objB.Id);
			}
		}
		
		if(!setAId.isEmpty())
		{
			List<B__c> lstBUpdate = new List<B__c>();
			for(B__c objB : [SELECT Id, Primary__c FROM B__c WHERE A__c IN: setAId AND Id NOT IN: setBIdExclude AND Primary__c = TRUE])
			{
				lstBUpdate.add(new B__c(Id = objB.Id, Primary__c = FALSE));
			}
			if(!lstBUpdate.isEmpty())
				update lstBUpdate;
		}
		
	}
}

 
Ashish KhairkarAshish Khairkar
Nayana, Any other method apart from trigger to achieve this
Nayana KNayana K
Without trigger I don't think this is possible. 
Alain CabonAlain Cabon
Hi, 

The Nayana's solution is excellent and I would have done the same at work.

There is an alternative "zero code" that programmers never use with an autolaunched flow and a process.

The Flow Designer is a powerful tool of Salesforce but it is little used (zero code but also not easy to "read" and verify without clicking everywhere, I will have to extract all the logic from the metadata for an automatic documentation). 

https://help.salesforce.com/articleView?id=process_action_flow.htm&language=en_US&type=0

You can pass the owner ID (reference of A) from the process to the flow.

User-added image

User-added image

User-added image

User-added image

User-added image

Salesforce have almost succeeded in "zero code" applications with powerful tools like the flow designer and the process builder but it is little used by the administrators.

Regards
This was selected as the best answer
Alain CabonAlain Cabon
The POC seems to work but it is just a test. I have done as little work as possible for getting a result that works using a less known good pratice of Salesforce.

User-added image

... moreover, these tools can rule all the problems of the governor limits automatically (should be verified).

The target audience of the flow designer and is the administrators so they have to rule all the underlying problems of the governor at the same time.

Regards
It just me!It just me!

@Nayana  

I tried your code above and its giving me a complie error.

Error: Compile Error: Missing '<EOF>' at 'public' at line 15 column 1

 

trigger BTrigger on Lease__c(after insert, after update)
{
    BtriggerHandler objHandler = new BtriggerHandler();
    if(Trigger.isAfter && Trigger.isInsert)
    {
        objHandler.onAfterInsert(Trigger.New);
    }
    
    if(Trigger.isAfter && Trigger.isUpdate)
    {
        objHandler.onAfterUpdate(Trigger.oldMap, Trigger.New);
    }
}

public class BtriggerHandler
{
    public void onAfterInsert(List<Lease__c> lstNewB)
    {
        setPrimary(new Map<Id, Lease__c>(), lstNewB);
    }
    
    public void onAfterUpdate(Map<Id, Lease__c> mapOldB, List<Lease__c> lstNewB)
    {
        setPrimary(mapOldB, lstNewB);
    }
    
    private void setPrimary(Map<Id, Lease__c> mapOldB, List<Lease__c> lstNewB)
    {
        Set<Id> setAId = new Set<Id>();
        Set<Id> setBIdExclude = new Set<Id>();
        for(Lease__c objB : lstNewB)
        {
            if(objB.Current_Lease__c && 
                (Trigger.isInsert || (Trigger.isUpdate && mapOldB.get(objB.Id).Current_Lease__c != objB.Current_Lease__c))
            )
            {
                setAId.add(objB.Space__c);
                setBIdExclude.add(objB.Id);
            }
        }
        
        if(!setAId.isEmpty())
        {
            List<Lease__c> lstBUpdate = new List<Lease__c>();
            for(Lease__c objB : [SELECT Id, Current_Lease__c FROM Lease__c WHERE Space__c IN: setAId AND Id NOT IN: setBIdExclude AND Current_Lease__c = TRUE])
            {
                lstBUpdate.add(new Lease__c(Id = objB.Id, Current_Lease__c = FALSE));
            }
            if(!lstBUpdate.isEmpty())
                update lstBUpdate;
        }
        
    }
}
Cant figure out why
Nayana KNayana K
@It Just me, the code contains trigger code and class code. Both are seperate. Make sure you first create the class and then the trigger.
Nayana KNayana K
@Alain Cabon, awesome! I will try out your solution to explore visual flow.
It just me!It just me!
@nayana  I was wondering if you can help me with a similar issue.

https://developer.salesforce.com/forums/ForumsMain?id=9060G0000005YwjQAE

Its a straight trigger without any class.  It's a primary contact apex code switch over to be used on 2 different objects.  If you can help that will be great or send some guidlines over.

thanks