You need to sign in to do that
Don't have an account?
Trigger Approval Process for an Opportunity
Hi all,
I am new to writing triggers and I am having a little trouble writing the test class code for the trigger. The trigger is suppose to fire when several Oppportunity fields met a certain criteria. Below is the criteria:
- Product Line = Non-Standard
- Products = YES
- Stage = Propose
- Opportunity Record Type is not "Active Client : Renewal", "Active Client : Services Only", or "New Client : Services Only"
Now I was not sure how to modifiy the trigger code to look at the Opportunity Record Type field (kept getting an error message saying something about SObject), so instead I created a formula field that puts the Opportunity Record Type field into text (called it Oppty Record Type). The trigger works great when I manually test it out but when I wrote the test class code I get an error message saying
Error: Compile Error: Field is not writeable: Opportunity.Oppty_Record_Type__c at line 12 column 9 |
So iam assuming that I am getting this error message because it is a formula field, maybe? Is it possible for someone to tell me how to use the Opportunity Record Type as a criteria field in the trigger code or how to modify the test class code?
Below is both the trigger and the test class
Trigger
trigger OpportunitySubmitForApproval on Opportunity (after update) {
list<Opportunity>updateOpps = new list<Opportunity>();
for (Opportunity opp : trigger.new) {
if (opp.StageName == 'Propose' && opp.Products__c == 'YES' && opp.Product_Line__c == 'Non-Standard' &&
(opp.Oppty_Record_Type__c != 'Active_Client_Renewal' && opp.Oppty_Record_Type__c != 'Active_Client_Services_Only' && opp.Oppty_Record_Type__c != 'New_Client_Services_Only')) {
// create the new approval request to submit
Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
req.setComments('Submitted for approval. Please approve.');
req.setObjectId(opp.id);
// submit the approval request for processing
Approval.ProcessResult result = Approval.process(req);
// display if the request was successful
System.debug('Submitted for approval successfully: '+result.isSuccess());
}
}
}
Test Class
@isTest
private class TestOpportunitySubmitForApproval {
static testMethod void testApprovalSuccess() {
Opportunity opp = new Opportunity();
opp.Name = 'Non-Standard Approval test';
opp.StageName = 'Demonstrate';
opp.Product_Line__c = 'Non-Standard';
opp.CloseDate = Date.today();
opp.LeadSource = 'Other';
opp.Oppty_Record_Type__c = 'New_Client_New_System';
// insert the new opp
insert opp;
// change the probability of the opp so the trigger submits it for approval
opp.StageName = 'Propose';
// update the opp which should submit it for approval
update opp;
// ensure that the opp was submitted for approval
List<ProcessInstance> processInstances = [select Id, Status from ProcessInstance where TargetObjectId = :opp.id];
System.assertEquals(processInstances.size(),1);
}
}
Thank you!
record type is an object . you need to create a new record type and then reference the id of the record type to the record type id of your opportunity in the test class.
Thanks,
Sandeep peddireddy
Hi,
Yes as mentioned above Record type is like object.
Include below statements in your test method.
Now your code looks like
Here
RecordType[] RecID = [Select id from RecordType where name = 'New_Client_New_System'];
In above statement change the name "New_Client_New_System" with your correct Record type name.
Yes your assumption is right, as it is formula field you can't write value into it.
Let me know if you still face any problem.
Thank you for that!
However, I am getting other error message now
Error MessageSystem.AssertException: Assertion Failed: Expected: 0, Actual: 1
Stack TraceClass.TestOpportunity11xSubmitForApproval.testApprovalSuccess: line 23, column 1
Not sure what that means.
Sorry my bad forgot to add that second line but i am still receiving an error message
Error MessageSystem.ListException: List index out of bounds: 0
Stack TraceClass.TestOpportunity11xSubmitForApproval.testApprovalSuccess: line 14, column 1
Hi,
Here you are not using any List here in 14 line.
Why you are getting this. Might be from some other class (by seeing the Error message).
Try to check condition like list.size()>0 before using the list in your classes.
if you still have problem post complete code and confirm what is 14 line.
Unfortunately, I am still getting the error message. (the name of the Approval Process is NonStandard)
Here is the whole error message
Here is the trigger code
Here is the test class code
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private class TestOpportunity11xSubmitForApproval {
static testMethod void testApprovalSuccess() {
RecordType[] RecID = [Select id from RecordType where name = 'New_Client_New_System'];
Opportunity opp = new Opportunity();
opp.Name = 'Non-Standard Approval test';
opp.StageName = 'Demonstrate';
opp.Product_Line__c = '11x Non-Standard';
opp.CloseDate = Date.today();
opp.LeadSource = 'Other';
opp.RecordTypeId = RecID[0].Id;
// insert the new opp
insert opp;
// change the probability of the opp so the trigger submits it for approval
opp.StageName = 'Propose';
// update the opp which should submit it for approval
update opp;
// ensure that the opp was submitted for approval
List<ProcessInstance> processInstances = [select Id, Status from ProcessInstance where TargetObjectId = :opp.id];
System.assertEquals(processInstances.size(),1);
}
}
If I manually create an opportunity with the criteria listed in the test code and then move it to propose it works so I am a little confused on why the test class is failing.
Thank you very much for all your help!!!!
Sorry I didnt realize the trigger code was getting cut off
here it is:
trigger Opportunity11xSubmitForApproval on Opportunity (after update) {
list<Opportunity>updateOpps = new list<Opportunity>();
for (Opportunity opp : trigger.new) {
if (opp.StageName == 'Propose' && opp.Products__c == 'YES' && opp.Product_Line__c == '11x Non-Standard' &&
(opp.Oppty_Record_Type__c != 'Active_Client_Renewal' && opp.Oppty_Record_Type__c != 'Active_Client_Services_Only' && opp.Oppty_Record_Type__c != 'New_Client_Services_Only')) {
// create the new approval request to submit
Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
req.setComments('Submitted for approval. Please approve.');
req.setObjectId(opp.id);
// submit the approval request for processing
Approval.ProcessResult result = Approval.process(req);
// display if the request was successful
System.debug('Submitted for approval successfully: '+result.isSuccess());
}
}
}
Hi,
Here you did simple mistake,
You didn’t read clearly what I wrote in my post.
Do small change in this line
RecordType [] RecID = [Select id from RecordType where name = 'New_Client_New_System'];
Replace New_Client_New_System with the your record type name. I just gave it as sample.
The problem y ur getting error is there is not record type with the name New_Client_New_System.
And you are assuming that list has some rows and trying to get id from list.
Ok. Now I am getting the same error message but at line 24.
here is the error message
here is the code
trigger Opportunity11xSubmitForApproval on Opportunity (after update) {
list<Opportunity>updateOpps = new list<Opportunity>();
for (Opportunity opp : trigger.new) {
if (opp.StageName == 'Propose' && opp.Products__c == 'YES' && opp.Product_Line__c == '11x Non-Standard' &&
(opp.Oppty_Record_Type__c != 'Active_Client_Renewal' && opp.Oppty_Record_Type__c != 'Active_Client_Services_Only' && opp.Oppty_Record_Type__c != 'New_Client_Services_Only')) {
// create the new approval request to submit
Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
req.setComments('Submitted for approval. Please approve.');
req.setObjectId(opp.id);
// submit the approval request for processing
Approval.ProcessResult result = Approval.process(req);
// display if the request was successful
System.debug('Submitted for approval successfully: '+result.isSuccess());
}
}
}
here is the test class code
@isTest
private class TestOpportunity11xSubmitForApproval {
static testMethod void testApprovalSuccess() {
RecordType[] RecID = [Select id from RecordType where name = 'New Client : New System'];
Opportunity opp = new Opportunity();
opp.Name = 'Non-Standard Approval test';
opp.StageName = 'Demonstrate';
opp.Product_Line__c = '11x Non-Standard';
opp.CloseDate = Date.today();
opp.LeadSource = 'Other';
opp.RecordTypeId = RecID[0].Id;
// insert the new opp
insert opp;
// change the probability of the opp so the trigger submits it for approval
opp.StageName = 'Propose';
// update the opp which should submit it for approval
update opp;
// ensure that the opp was submitted for approval
List<ProcessInstance> processInstances = [select Id, Status from ProcessInstance where TargetObjectId = :opp.id];
System.assertEquals(processInstances.size(),1);
}
}
Ok,
This happens because your trigger didn't submit any record for approval process.
means your IF condition is not satisfies with the test data you have given.
if (opp.StageName == 'Propose' && opp.Products__c == 'YES' && opp.Product_Line__c == '11x Non-Standard' &&
(opp.Oppty_Record_Type__c != 'Active_Client_Renewal' && opp.Oppty_Record_Type__c != 'Active_Client_Services_Only' && opp.Oppty_Record_Type__c != 'New_Client_Services_Only')) {
Please try to understand how test method will execute.
Your if condition will only be satisfies when
1) opp.StageName == 'Propose'--------- > but you gave opp.StageName = 'Demonstrate';
Then how it will satisfies the IF condition.
I hope you understood, try to give data like it satisfies if condition and then run the test.
for now comment the system.assert statement to make 0 test failures, so that you can understood which part is covered and which is not.
OK,
Modify your test class like below and try.
Let me know any test failures, if not let me know the coverage and which lines are not covered.
the after you can uncomment the system. Assert statement.
Ok. So I think I know what the issue is. The Products__c field is other formula field. What it is meant to do is see if there are any products listed in the opportunity, if so the field = 'YES' (if not it = 'NO'). Now I am trying to figure out how to just use the SFDC standard object field "HasLineItems', I am not too sure how to replace the Products__c field in the trigger code with this object field nor modify the test code. Do I really have to insert a quote too in the test code or is there a way to have the haslineitems = true?
Hi,
Ok,
As Products__c is formula field you cann't insertdata from Test method as above.
You have to insert data such that it will be calculated as YES.
What is the formula in it?
Are you talking about HasOpportunityLineItem field in Opportunity Object?
You can’t give data for that also directly.
Below description will be useful for you.
HasOpportunityLineItem
Read-only field that indicates whether the opportunity has associated line items. A value of true means that Opportunity line items have been created for the opportunity. An opportunity can have opportunity line items only if the opportunity has a price book. The opportunity line items must correspond to PricebookEntry objects that are listed in the opportunity Pricebook2. However, you can insert opportunity line items on an opportunity that does not have an associated Pricebook2. For the first opportunity line item that you insert on an opportunity without a Pricebook2, the API automatically sets the Pricebook2Id field, if the opportunity line item corresponds to a PricebookEntryin an active Pricebook2 that has a CurrencyIsoCode field that matches the CurrencyIsoCode field of the opportunity. If the Pricebook2 is not active or theCurrencyIsoCode fields do not match, then the API returns an error. You can’t update the Pricebook2Id or PricebookId fields if opportunity line items exist on theOpportunity. You must delete the line items before attempting to update the PricebookId field.
http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_opportunity.htm
Any ways try to make/insert data such that Products__c will be calculated as YES.