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
Stéphane C.Stéphane C. 

Preventing from deleting closed won opportunities for non administrator

Hi,

I want to prevent a non administrator user to delete closed won opportunities.

I think a trigger can be a good solution.
 
trigger ClosedWonOpportunityTrigger on Opportunity (before delete) {
    for(Opportunity o: Trigger.Old)
        if($Profile.Name <> "System Administrator" && o.stagename=='Closed Won’)
        	o.addError(‘You cannot delete a Closed Won Opportunity. Please contact the Accounting Department. Thank you.’);
}

Do you think this apex can work?

Thank you.
Best Answer chosen by Stéphane C.
Manohar kumarManohar kumar

Hi Stephane,

pls try some like this

 

trigger ClosedWonOpportunityTrigger on Opportunity (before delete) {
    for(Opportunity o: Trigger.Old) {
      id id1 = userinfo.getProfileId();

string profileName = [select Name from profile where id = :id1].name;
        if(profileName == "System Administrator" && o.stagename=='Closed Won’)
        	o.addError(‘You cannot delete a Closed Won Opportunity. Please contact the Accounting Department. Thank you.’);

}
}

All Answers

v varaprasadv varaprasad
Hi Stephne,

Please use below validation rule instead of trigger.your trigger also fine.

AND($Profile.Name <> "System Administrator",ISPICKVAL(stagename, "Closed Won"))

Hope This Helps.
If it helps you please mark it as Best Answer.

Thanks
Varaprasad
 
Stéphane C.Stéphane C.
Hi,

I think I read with this method that an user can always delete an opportunity by the list view. Is it true?

Thank you.
Stéphane C.Stéphane C.
I have a new test tomorrow but I have not the result that I want with this validation rules. Try it agani.   ;-)
Manohar kumarManohar kumar

Hi Stephane,

pls try some like this

 

trigger ClosedWonOpportunityTrigger on Opportunity (before delete) {
    for(Opportunity o: Trigger.Old) {
      id id1 = userinfo.getProfileId();

string profileName = [select Name from profile where id = :id1].name;
        if(profileName == "System Administrator" && o.stagename=='Closed Won’)
        	o.addError(‘You cannot delete a Closed Won Opportunity. Please contact the Accounting Department. Thank you.’);

}
}
This was selected as the best answer
Manohar kumarManohar kumar

Hi Stephane,

sorry it should  profileName != "System Administrator".

hope it helps,

Thanks,

Manohar

Stéphane C.Stéphane C.
Thank you.

I test it but I have an issue with the code : line 5:26 no viable alternative at character '"' .
 
trigger ClosedWonOpportunityTrigger on Opportunity (before delete) {
    for(Opportunity o: Trigger.Old) {
        id userId = userinfo.getProfileId();
        string profileName = [select Name from profile where id = :userId].name;
        if(profileName != "Administrateur système" && o.stagename=='Gagné')
           o.addError(‘You cannot delete a Closed Won Opportunity. Please contact the Accounting Department. Thank you.’);
    }
}

I cannot see where it comes from? Any idea?

Thank you.
Manohar kumarManohar kumar

Hi, is it something to do with double quotes? Pls try single quotes once.

let me know if this works. 

Thanks

Stéphane C.Stéphane C.
Try this always not working :
 
trigger ClosedWonOpportunityTrigger on Opportunity (before delete) {
    for(Opportunity o: Trigger.Old) {
        id userId = userinfo.getProfileId();
        string profileName = [select Name from profile where id = :userId].name;
        if(profileName != 'Administrateur système' && o.stagename == 'Gagné')
           o.addError(‘You cannot delete a Closed Won Opportunity. Please contact the Accounting Department. Thank you.’);
    }
}

No idea?!
Stéphane C.Stéphane C.
I found the issue.
 
trigger ClosedWonOpportunityTrigger on Opportunity (before delete) {
    for(Opportunity o: Trigger.Old) {
        id userId = userinfo.getProfileId();
        string profileName = [select Name from profile where id = :userId].name;
        if(profileName != 'Administrateur système' && o.stagename == 'Gagné')
           o.addError('You cannot delete a Closed Won Opportunity. Please contact the Accounting Department. Thank you.');
    }
}

It works now.
Manohar kumarManohar kumar

Hi stephane,

can't see the diff :)

please mark my answer as a best answer if it helped.

Thanks,

Manohar 

 

Stéphane C.Stéphane C.
Hi,

Wrong quotes in the code.

Thank you.
Stéphane C.Stéphane C.
Now it's time to write the test...
Stéphane C.Stéphane C.
It seems that I have to write an Apex test class.

Any idea?
Stéphane C.Stéphane C.
Ok. Certainly something like this :
 
@isTest
private class TestClosedWonOpportunity {
    @isTest public static void TestTheTrigger() {
    //Test 
    }
}

 
Stéphane C.Stéphane C.
Ok. I try to go further :
 
@isTest
private class TestClosedWonOpportunity {
    @isTest public static void TestTheTrigger() {
        // Test data setup
        // Create an opportunity with a won stagename, and then try to delete it
        Account acct = new Account(Name='Test Account');
        insert acct;
        Opportunity opp = new Opportunity(Name=acct.Name + ' Opportunity',
                                          StageName='Gagné',
                                          CloseDate=System.today().addMonths(1),
                                          AccountId=acct.Id);
        insert opp;
        // Perform test
        Test.startTest();
        // ?
        Test.stopTest();
    }
}

 
Stéphane C.Stéphane C.
I found some help but I can achieve it :
 
@isTest
private class TestClosedWonOpportunity {
    @isTest public static void TestTheTrigger() {
        // Test data setup
        // Create an opportunity with a won stagename, and then try to delete it
        Account acct = new Account(Name='Test Account');
        insert acct;
        Opportunity opp = new Opportunity(Name=acct.Name + ' Opportunity',
                                          StageName='Gagné',
                                          CloseDate=System.today().addMonths(1),
                                          AccountId=acct.Id);
        insert opp;
        // Perform test
        Test.startTest();
        Database.DeleteResult result = Database.delete(opp, false);
        Test.stopTest();
        
        // Verify
        // In this case the deletion should have been stopped by the trigger,
        // so verify that we got back an error.
    }
}

Any idea?
Stéphane C.Stéphane C.
Ok. I'm using an example :
 
@isTest
private class TestClosedWonOpportunity {
    @isTest public static void TestTheTrigger() {
        // Test data setup
        // Create an opportunity with a won stagename, and then try to delete it
        Account acct = new Account(Name='Test Account');
        insert acct;
        Opportunity opp = new Opportunity(Name=acct.Name + ' Opportunity',
                                          StageName='Gagné',
                                          CloseDate=System.today().addMonths(1),
                                          AccountId=acct.Id);
        insert opp;
        // Perform test
        Test.startTest();
        Database.DeleteResult result = Database.delete(opp, false);
        Test.stopTest();
        
        // Verify
        // In this case the deletion should have been stopped by the trigger,
        // so verify that we got back an error.
        System.assert(!result.isSuccess());
        System.assert(result.getErrors().size() > 0);
        System.assertEquals('You cannot delete a Closed Won Opportunity. Please contact the Accounting Department. Thank you.',
                             result.getErrors()[0].getMessage());
    }
}

I cannot see what it is wrong.

Any help?
Stéphane C.Stéphane C.
I certainly have to add the profile of the user too. But I cannot see how?
v varaprasadv varaprasad
Hi Stephne,

Please use below code once and test:

 
@isTest
private class TestClosedWonOpportunity {
    @isTest public static void TestTheTrigger() {
        // Test data setup
        // Create an opportunity with a won stagename, and then try to delete it
		
		Profile p = [SELECT Id FROM Profile WHERE Name='Standard User']; 
        User u = new User(Alias = 'standt', Email='standarduser@testorg.com', 
            EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US', 
            LocaleSidKey='en_US', ProfileId = p.Id, 
            TimeZoneSidKey='America/Los_Angeles', UserName='standarduser@testorg.com');

        System.runAs(u) {
		Account acct = new Account(Name='Test Account');
        insert acct;
		
        Opportunity opp = new Opportunity(Name=acct.Name + ' Opportunity',
                                          StageName='Gagné',
                                          CloseDate=System.today().addMonths(1),
                                          AccountId=acct.Id);
        insert opp;
		
		
        // Perform test
        Test.startTest();
        Database.DeleteResult result = Database.delete(opp, false);
        Test.stopTest();
		
		
		}
       
    }
}

Thanks
Varaprasad​
Stéphane C.Stéphane C.
Whooo, it's perfect!

Do you think it is possible to test this too :
 
// Verify
        // In this case the deletion should have been stopped by the trigger,
        // so verify that we got back an error.
        System.assert(!result.isSuccess());
        System.assert(result.getErrors().size() > 0);
        System.assertEquals('You cannot delete a Closed Won Opportunity. Please contact the Accounting Department. Thank you.',
                             result.getErrors()[0].getMessage());

Thank you.
Stéphane C.Stéphane C.
Hello,

Just one more think.

Is it possible to extend it to the edit function? If I don't want a non-administrator user can edit an closed opportunity?

Thank you.
Stéphane C.Stéphane C.
Another question : is it possible to lock the edition too. I try this but I have an issue :
trigger LockClosedWonOpportunityTrigger on Opportunity (before update, before delete) {
    for(Opportunity o: Trigger.Old) {
        id userId = userinfo.getProfileId();
        string profileName = [select Name from profile where id = :userId].name;
        
        // Prevent a user to edit or to delete a closed won opportunity
        if(profileName != 'Administrateur système' && o.stagename == 'Gagné')
           o.addError('You cannot edit or delete a Closed Won Opportunity. Please contact the Accounting Department. Thank you.');
    }
}

LockClosedWonOpportunityTrigger: execution of BeforeUpdate caused by: System.FinalException: SObject row does not allow errors: Trigger.bizkor_LockBilledOpportunityTrigger: line 8, column 1

Any idea ?
Stéphane C.Stéphane C.
Hi,

Is it possible to mix "before update" and "before delete" on the same script?

I have this error : Trigger: execution of BeforeUpdate caused by: System.FinalException: SObject row does not allow errors Trigger.bizkor_LockBilledOpportunityTrigger: line 8, column 1.

Thank you for the help.
ankur koulankur koul
Validation rule only fires when a records is created or edited.
Validatipn rule will not work in this case