You need to sign in to do that
Don't have an account?
Shannon Andreas 1
Trigger not working. Test Class not working. Please help
I have a trigger and am trying to write a test class (see below). The trigger is not working...I have asked for help with no resolution. I am asking again for help with the trigger as well as test class (which is not working either). I think my issue is with the Account ID and Opportunity ID part.
All I am trying to do is have a contract created when a checkbox on the oppty is checked.
Please see previous post: https://developer.salesforce.com/forums/ForumsMain?id=906F0000000BTEhIAO
TRIGGER:
trigger CreateContract on Opportunity (after insert) {
private List<Contract> ctr = new List<Contract>();
for(Opportunity o : Trigger.new) {
if(o.Ready_for_Contract__c == true) {
Contract c = new Contract(Name = o.Name,
Status = 'Draft',
Total_Contract_Value__c = o.Total_Sales_Price_of_Products__c,
StartDate = o.Contract_Start_Date__c,
Payment_Status__c = 'Ready to Be Invoiced',
AccountId = o.AccountId,
Opportunity_Name__c = o.Id);
ctr.add(c);
}
insert ctr;
}
}
TEST Class:
@isTest
private class TestClassCreateContractTrigger
{
static testMethod void validateCreateContract()
{
Contract c = new Contract(
Name='Test Account',
Status = 'Activated',
Total_Contract_Value__c = decimal.valueof('6995'),
StartDate = System.Today(),
Payment_Status__c = 'Ready to Be Invoiced',
AccountId = Opportunity.AccountId,
Opportunity_Name__c = Opportunity.Id);
insert c;
}
}
Thanks in advance for your help!!
Shannon
All I am trying to do is have a contract created when a checkbox on the oppty is checked.
Please see previous post: https://developer.salesforce.com/forums/ForumsMain?id=906F0000000BTEhIAO
TRIGGER:
trigger CreateContract on Opportunity (after insert) {
private List<Contract> ctr = new List<Contract>();
for(Opportunity o : Trigger.new) {
if(o.Ready_for_Contract__c == true) {
Contract c = new Contract(Name = o.Name,
Status = 'Draft',
Total_Contract_Value__c = o.Total_Sales_Price_of_Products__c,
StartDate = o.Contract_Start_Date__c,
Payment_Status__c = 'Ready to Be Invoiced',
AccountId = o.AccountId,
Opportunity_Name__c = o.Id);
ctr.add(c);
}
insert ctr;
}
}
TEST Class:
@isTest
private class TestClassCreateContractTrigger
{
static testMethod void validateCreateContract()
{
Contract c = new Contract(
Name='Test Account',
Status = 'Activated',
Total_Contract_Value__c = decimal.valueof('6995'),
StartDate = System.Today(),
Payment_Status__c = 'Ready to Be Invoiced',
AccountId = Opportunity.AccountId,
Opportunity_Name__c = Opportunity.Id);
insert c;
}
}
Thanks in advance for your help!!
Shannon
Visibility of the field shouldn't matter because regardless of if you can see it or not, the data still gets populated in the SFDC database.
Your trigger is currently set as "after insert". Are you checking the box during opp creation, or are you checking the box on a pre-existing opp? If you are UPDATING an existing opp, then after insert is not going to cut it. Maybe change it to:
trigger CreateContract on Opportunity (after insert, after update) {
All Answers
There is no "error" on the trigger, just does not create the contract.
I am receiving compile errors on the test class:
[Error] Error: Compile Error: Invalid initial expression type for field Contract.AccountId, expecting: Id at line 12 column 25
When I change anything on line 12 or 13, I get errors. So if I "fix" 1 line, the other errors.
I just wrote this up really quick so it may not be 100% accurate, but you should try something like this... we first create and insert a test account, then we create and insert a test opp linked to that account, and then finally we create and insert your contract:
Would become...
Apex is also run with the permission level of whomever triggered it, so make sure that the user executing this trigger has access to create new contracts. If you are not getting errors when saving the trigger then that means the context of your trigger appears valid according to SFDC. I'm not an expert yet but I don't see anything wrong with your trigger other than the unnecessary 'private' in front of the list.
Also, as stupid as it sounds - make sure your trigger is marked as active ;)
If all else fails, go to Setup > Logs > Debug Logs and add your user as a Monitored User, and then go create an opportunity that meets your IF criteria. If a contract is not created, check the debug logs for your user - one of them will reveal some sort of error or reason why it wasn't executed.
Also to your second and third points...I did!! After racking my brain for a while, I figured I would try the simplest of causes (Ocham's razor). Unfortunately, the simple answer was not right! I already set myself up in the logs as well. Great point on user accessibility as well! Never thought about it.
Will let you know!!
Shannon
Bad News is my trigger is failing. I am pretty sure it is because of how I have the account and opportunity name set up:
System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [AccountId, Opportunity_Name__c]: [AccountId, Opportunity_Name__c]
Any help is appreciated.
Shannon
I don't use contracts so I wasn't familiar with them, but I took a look in our sandbox and I see that the "Account Name" fields API name is just "Account", rather than "AccountId". As far as Opportunity_Name__c, that's a custom field that your org created on your contracts, so double check the custom fields API name to make sure it is the exact spelling seen here. If it is a lookup field to opportunity, then o.Id should work.
Try this:
The checkbox is hidden from users because it is used as a behind the scenes trigger to start the CreateContract trigger. I can see it...could this be a problem? It is not a read only, but can only be seen by me.
Visibility of the field shouldn't matter because regardless of if you can see it or not, the data still gets populated in the SFDC database.
Your trigger is currently set as "after insert". Are you checking the box during opp creation, or are you checking the box on a pre-existing opp? If you are UPDATING an existing opp, then after insert is not going to cut it. Maybe change it to:
trigger CreateContract on Opportunity (after insert, after update) {
After Insert worked. After update gave me an error when I tried to save the opportunity.The only thing I need to figure out now is why it is not attaching to the Account record. They should all be tied together...or so I thought. There could be a delay. Also need to add billing info since there is a validation that requires entry of this information on the Contract. It's also only getting 33% coverage. I heard the same thing from other people about not "trusting" the system...
Here is the correct code:
Trigger:
trigger CreateContract on Opportunity (after insert) {
List<Contract> ctr = new List<Contract>();
for(Opportunity o : Trigger.new) {
if(o.Ready_for_Contract__c == true) {
Contract c = new Contract(Name = o.Name,
Status = 'Draft',
Total_Contract_Value__c = o.Amount,
StartDate = o.Contract_Start_Date__c,
Payment_Status__c = 'Ready to be Invoiced',
Account = o.Account,
Opportunity_Name__c = o.Id);
ctr.add(c);
}
insert ctr;
}
}
Test class:
@isTest
private class TestClassCreateContractTrigger
{
static testMethod void validateCreateContract()
{
Account a = new Account(
Name = 'Test Account');
insert a;
Opportunity o = new Opportunity(
Name = 'Test Opp',
CloseDate = System.Today(),
AccountId = a.Id,
StageName = 'Signed / Closed Sale',
Amount = decimal.valueof('6995'));
insert o;
Contract c = new Contract(
Name='Test Contract',
Status = 'Draft',
Total_Contract_Value__c = o.Amount,
StartDate = System.Today(),
Payment_Status__c = 'Ready to be Invoiced',
AccountId = o.AccountId,
Opportunity_Name__c = o.Id);
insert c;
}
}
Thank you so very much Morgan! Hopefully I will not have any more issues with adding the other fields.
Shannon
The billing information is coming from the Account object. It is not stored in the Opportunity. Is there anything special that I need to do to add that object to the trigger? Other than writing it as a.BillingCity, a.BillingState, etc?
I have a feeling I do?
Test class code coverage is determined by how much of your real code is invoked by your test class. 33% is obviously much too low, but your code isn't very complex so getting it above the required 75% should be easy.
As I mentioned originally, my test class was a loose example, so it wasn't 100% accurate to your use case. In the case of your trigger, your entire execution is based off of o.Ready_For_Contract__c being set to True, but we aren't setting that field to true on your Opp in your test class, so it's likely not executing a big chunk of it - thus, 33%.
Try just adding Ready_For_Contract__c = true (API name is case sensative, so make sure its all cased correctly), to the opportunity creation portion of your test class and let's see where that gets you with code coverage:
As for why it's not linking to the account, like I said, I'm not an expert yet - still learning myself (I just like to help when I can as I feel that it improves my knowledge while assisting others). After reviewing some code in my own org I believe I was originally incorrect in telling you to use Account instead of AccountId. Try changing Account = o.Account in your trigger back to AccountId = o.AccountId again and see if that works - there shouldn't be any delay with linking during apex triggering. it's all or nothing.
Regarding bringing in extra fields from account (Billing info), we can definitely do this, but it will add more complexity to your trigger, and also might not be an ideal scenario if you think about it long term. Let's say a customer has 3 opportunities created in their account lifecycle - but their billing address changed twice. Do you want all 3 contracts to have different billing addresses on them? OR do you want the billing address to update dynamically based on the billing address that currently exists on the account? If you want the address to be different on each, then we'd want to use a trigger to fill in the data - but if you want it to be their most recent billing info then you can remove the validation rule from contract and put it on account instead and then just use formula fields to bring in the data from account to contract once you get the lookup relationship fixed. Make sense? Let me know what you're thinking.