You need to sign in to do that
Don't have an account?
Samuel Gonsalves 8
Trigger getting fired twice because of update
Hi Team,
I have 2 objects quote and invoice. Whenever quote is created and when it is updated to Approved , all data goes to invoice object and a invoice record get created.
My problem is when anytime other fields in quote is updated again the trigger runs and a new invoice gets created. i just want my trigger to run only once. This is my code.
trigger createInvoiceQuote on Quote (after update)
{
if(trigger.isAfter){
set<id> oppIds = new set<id>();
list<Invoicing__c> newInvoiceList = new list<Invoicing__c>();
list<Quote> QuoteList = new list<Quote>();
map<id,id> conRoleMap = new map<id, id>();
set<id> accSet = new set<id>();
map<id, contact> accConMap = new map<id , contact>();
QuoteList = [select id, status, name, isSyncing, opportunityId, contact.Billing_Contact__c , contactId, opportunity.Fieldwork_Stage__c, AccountId, Account.GST_Setting__c from quote where id IN: trigger.newMap.keyset()];
system.debug('QuoteList' + QuoteList);
for(Quote quo : QuoteList){
if(quo.isSyncing && quo.Status.equalsIgnoreCase('Approved')){
oppIds.add(quo.opportunityId);
accSet.add(quo.AccountId);
}
}
for(OpportunityContactRole conRole : [select id, contactId, IsPrimary, opportunityId from OpportunityContactRole where opportunityId in: oppIds AND isPrimary = true])
{
conRoleMap.put(conRole.opportunityId , conRole.contactId);
}
for(contact con : [select id, accountId, email, billing_Contact__c from contact where id in: conRoleMap.values() OR (accountId in: accSet AND Billing_Contact__c = true)])
{
accConMap.put(con.AccountId , con);
accConMap.put(con.id , con);
}
system.debug('conRoleMap ' + conRoleMap);
for(Quote quo : QuoteList){
if(quo.isSyncing && quo.Status.equalsIgnoreCase('Approved')){
Invoicing__c inv = new Invoicing__c();
inv.Quote__c = quo.Id;
inv.Invoice_Name__c = quo.Name;
inv.Status__c = quo.opportunity.Fieldwork_Stage__c;
inv.Opportunity_Name__c = quo.OpportunityId;
inv.GST_Setting__c = quo.Account.GST_Setting__c;
if(accConMap.containsKey(quo.AccountId)){
Contact secCon = accConMap.get(quo.AccountId);
if(secCon.Billing_Contact__c){
inv.Secondary_Billing_Contact__c = secCon.Id;
inv.Secondary_Billing_Contact_Email_id__c = secCon.email;
}
}
if(conRoleMap.containsKey(quo.OpportunityId)){
inv.Primary_Billing_Contact__c = conRoleMap.get(quo.OpportunityId);
if(accConMap.containsKey(conRoleMap.get(quo.OpportunityId)))
inv.Primary_Billing_Contact_Email_id__c = accConMap.get(conRoleMap.get(quo.OpportunityId)).email;
}
newInvoiceList.add(inv);
}
}
for(Invoicing__c inv : [select id, Opportunity_Name__c from Invoicing__c where Opportunity_Name__c in: oppIds]){
inv.Opportunity_Name__c = null;
newInvoiceList.add(inv);
}
upsert newInvoiceList;
}
}
Can anyone please help. Need it urgently
Thanks.
Regards,
Samuel
I have 2 objects quote and invoice. Whenever quote is created and when it is updated to Approved , all data goes to invoice object and a invoice record get created.
My problem is when anytime other fields in quote is updated again the trigger runs and a new invoice gets created. i just want my trigger to run only once. This is my code.
trigger createInvoiceQuote on Quote (after update)
{
if(trigger.isAfter){
set<id> oppIds = new set<id>();
list<Invoicing__c> newInvoiceList = new list<Invoicing__c>();
list<Quote> QuoteList = new list<Quote>();
map<id,id> conRoleMap = new map<id, id>();
set<id> accSet = new set<id>();
map<id, contact> accConMap = new map<id , contact>();
QuoteList = [select id, status, name, isSyncing, opportunityId, contact.Billing_Contact__c , contactId, opportunity.Fieldwork_Stage__c, AccountId, Account.GST_Setting__c from quote where id IN: trigger.newMap.keyset()];
system.debug('QuoteList' + QuoteList);
for(Quote quo : QuoteList){
if(quo.isSyncing && quo.Status.equalsIgnoreCase('Approved')){
oppIds.add(quo.opportunityId);
accSet.add(quo.AccountId);
}
}
for(OpportunityContactRole conRole : [select id, contactId, IsPrimary, opportunityId from OpportunityContactRole where opportunityId in: oppIds AND isPrimary = true])
{
conRoleMap.put(conRole.opportunityId , conRole.contactId);
}
for(contact con : [select id, accountId, email, billing_Contact__c from contact where id in: conRoleMap.values() OR (accountId in: accSet AND Billing_Contact__c = true)])
{
accConMap.put(con.AccountId , con);
accConMap.put(con.id , con);
}
system.debug('conRoleMap ' + conRoleMap);
for(Quote quo : QuoteList){
if(quo.isSyncing && quo.Status.equalsIgnoreCase('Approved')){
Invoicing__c inv = new Invoicing__c();
inv.Quote__c = quo.Id;
inv.Invoice_Name__c = quo.Name;
inv.Status__c = quo.opportunity.Fieldwork_Stage__c;
inv.Opportunity_Name__c = quo.OpportunityId;
inv.GST_Setting__c = quo.Account.GST_Setting__c;
if(accConMap.containsKey(quo.AccountId)){
Contact secCon = accConMap.get(quo.AccountId);
if(secCon.Billing_Contact__c){
inv.Secondary_Billing_Contact__c = secCon.Id;
inv.Secondary_Billing_Contact_Email_id__c = secCon.email;
}
}
if(conRoleMap.containsKey(quo.OpportunityId)){
inv.Primary_Billing_Contact__c = conRoleMap.get(quo.OpportunityId);
if(accConMap.containsKey(conRoleMap.get(quo.OpportunityId)))
inv.Primary_Billing_Contact_Email_id__c = accConMap.get(conRoleMap.get(quo.OpportunityId)).email;
}
newInvoiceList.add(inv);
}
}
for(Invoicing__c inv : [select id, Opportunity_Name__c from Invoicing__c where Opportunity_Name__c in: oppIds]){
inv.Opportunity_Name__c = null;
newInvoiceList.add(inv);
}
upsert newInvoiceList;
}
}
Can anyone please help. Need it urgently
Thanks.
Regards,
Samuel
Thanks for a quick response. Its not related to old and new status. Its relating to any field on quote object. The first time when i sync and Approved the quote the invoice should get created. Later after some time if any goes into the same quote and edit some other field values then again a new invoice gets created. I dont want a new invoice to be created . The trigger should run only once.
Understand that your trigger is being executed again when user update quotation record, which is not as expected.
My suggestion:
- Create a new field "Is_Invoice_Generated__c" checkbox on quotation level. Set default value unchecked.
- Create after insert trigger on Invoice. Update Quote.Is_Invoice_Generated__c to true.
- Modify your code:
for(Quote test : trigger.new){ accountmap.put(test.id,test.name); string name1= System.Trigger.oldMap.get(test.Id).name; system.debug('name1----------------'+name1);//old value system.debug('accountmap-==========='+accountmap);//new value if((test.isSyncing && !trigger.oldMap.get(test.id).isSyncing) || (test.Status.equalsIgnoreCase('Approved') && !trigger.oldmap.get(test.Id).Status.equalsIgnoreCase('Approved'))) QuoteIds.add(test.Id); }