1

I have custom field Invoice Date in OpportunityLineitem when this is left blank it should show error using trigger when trying to update Opportunity with Opportunity stagename as closed won.

I tried the following way:

trigger OpportunityStageWon on Opportunity(before insert, before update) {
    set<Id> Oid = new set<id>();
    for (Opportunity o: Trigger.new) {
        Oid.add(o.id);
    }
    List<OpportunityLineItem> OLI = [Select id, name, Invoice_Date1__c from OpportunityLineItem where Opportunityid =: Oid];
    for (Opportunity o: Trigger.New) {
        for(OpportunityLineItem ol : OLI){
            if (o.StageName == 'Closed Won' && ol.Invoice_Date1__c == null) {
                o.StageName.addError('Your custom error message');
            }
        }
    }
}
4
  • and your question is?
    – Novarg
    Commented Jun 20, 2016 at 9:51
  • Given code is not complete.There could be multiple line items related to one opportunity.Specify exactly what issue you are having?
    – Mr.Frodo
    Commented Jun 20, 2016 at 9:51
  • Very true .It's not working.My question how do I achieve this? Commented Jun 20, 2016 at 9:53
  • I tried creating list<Opplineitem> Commented Jun 20, 2016 at 9:54

2 Answers 2

0

Try Below Code

trigger OpportunityStageWon on Opportunity(before insert, before update) {
    set<Id> Oid = new set<id>();
    for (Opportunity o: Trigger.new) {
        Oid.add(o.id);
    }
    List<OpportunityLineItem> OLI = [Select id, name, Invoice_Date1__c from OpportunityLineItem where Opportunityid =: Oid];
    for (Opportunity o: Trigger.New) {
        for(OpportunityLineItem ol : OLI){
            if (o.StageName == 'Closed Won' && ol.Invoice_Date1__c == null) {
                o.StageName.addError('Your custom error message');
            }
        }
    }
}

UPDATE:

You can refer below link for Trigger.New and Trigger.Old Difference

https://developer.salesforce.com/forums/?id=906F000000098JAIAY

Hope this might helps...

10
  • It helped.I have a query for you.If I use tigger.old in both loops I am getting this errr"System.FinalException: SObject row does not allow errors: Trigger.OpportunityStageWon: line 10, column 1" why? Commented Jun 20, 2016 at 10:05
  • You should take the Trigger.New only. Because you are giving the before insert and before update for the Trigger....... Trigger.Old is naturally used for the Delete Operations....
    – Subhash
    Commented Jun 20, 2016 at 10:08
  • In simple words Trigger.new returns new value of records and Trigger.old returns old value of records. Trigger.new works in case of insert and update both and Trigger.old works in case of update and delete both. For update you can use both as per your need.Clearrrrrrrrrrr Commented Jun 20, 2016 at 10:13
  • 1
    interesting.. can we get the Id in before insert ? if id is not generated then how come you get the OLI for that opportunity ?
    – Ratan Paul
    Commented Jun 20, 2016 at 10:41
  • 1
    Haha.:). No ratan... I too forgot.. Sorry
    – Subhash
    Commented Jun 20, 2016 at 10:42
1

So I guess you want to show en error when opportunity status gets changed to Closed Won and Invoice_Date1__c is empty?

Let's analyse your code line per line:

set < Id > id = new set < id > ();

You create a set of ids and call id just id. Not the best practice in my opinion, but whatever, it will compile and even work

OpportunityLineItem OL = [Select id, name, Invoice_Date1__c from OpportunityLineItem where Opportunityid =: id];

I guess your execution fails here with System.QueryException: List has no rows for assignment to SObject? You are trying to query a single OpportunityLineItem where the reference to Opportunity is an empty set. You should do this query after the next loop(and use IN operator instead of = and use a List instead of a single OLI(or add LIMIT 1 to your query)):

for (Opportunity o: Trigger.new) {
    id.add(o.id);
}

Make sure to do this before querying your OLIs.

for (Opportunity o: Trigger.old) {
    if (o.StageName == 'Closed Won' && ol.Invoice_Date1__c == null) {
        o.StageName.addError('Your custom error message');
    }
}

If you loop through Trigger.old, o.StageName will be the stageName before the update, so if you only change it from Open to Closed Won, this will never be in the check.

You should compare old to new to notice the change of the field. And you should also use list of OLIs, because there can be multiple OLIs on one Opportunity.

1
  • I have updated my question with answer ..It helped.I have a query for you.If I use tigger.old in both loops I am getting this errr"System.FinalException: SObject row does not allow errors: Trigger.OpportunityStageWon: line 10, column 1" why? Commented Jun 20, 2016 at 10:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .