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
AnetaAneta 

Trigger on Custom Object to update field on Opportuntiy

Hi - I am new to Apex programming and triggers and have a simple question.  We are tracking proposals which are a child to an opportunity.  We may have multiple revisions of a proposal - the most recent is the one we should be using. We have approval process set up on the proposal.
 
I have a custom field - "Proposal Status" on the Proposal (New, Pending, Approved, or Rejected  - updated through Approval Process field updates). I would like to copy the value from this field from the latest proposal to a correlating field on the Opportunity when the Proposal Status changes. Note: we can have multiple revisions of the same proposal and I want to use the latest one.
 
I've tried this with roll-up summaries and workflow rules but it doesn't work. Called SFDC support and told that I need a trigger to do this. Can you please help me? I already spent hours on this and I'm about to give up. Nothing seems to work. Please help! Thank you! :)
Best Answer chosen by Admin (Salesforce Developers) 
Naidu PothiniNaidu Pothini
Trigger UpdateProposalStatusOnOpty on Proposal__c(after insert, after update)
{
	List<Id> OppIds = new List<Id>();
List<Proposal__c> pbList = new List<Proposal__c>(); List<Opportunity> OppList = new List<Opportunity>(); if(trigger.oldMap <> null) { for(Proposal__c PB : Trigger.new) { if(PB.Proposal_Status__c <> trigger.oldMap.get(PB.Id).Proposal_Status__c) { OppIds.add(PB.Opportunity_Name__c)
pbList.add(pb); } } } else { for(Proposal__c PB : Trigger.new) { OppIds.add(PB.Opportunity_Name__c);
pbList.add(pb); } } Map<Id, Opportunity> oppMap = new Map<Id, Opportunity>([SELECT Id, Latest_Proposal_Approval_Status__c FROM Opportunity WHERE Id IN :OppIds]);
for(Proposal__c pb: pbList) { Opportunity Opp = oppMap.get(pb.Opportunity__c); Opp.Latest_Proposal_Approval_Status__c = pb.Proposal_Status__c; OppList.add(Opp); } update OppList; }

 try this.

All Answers

AnetaAneta

Update:

I was able to put together the following trigger, but need help to modify. I need it to check if the value changes in the "Proposal_Status__c" field on the Proposal and if it does, to copy it the "Latest_Proposal_Approval_Status__c" field in the related Opportunity.

My trigger works when the value changes to "Approved" and it should work for any proposal status change (pending, rejected, etc.)

Thank you in advance for your help with this!

 

trigger UpdateProposalStatusOnOpty on Proposal__c (after update, after  insert) {
Set<ID> oppIds = new Set<ID>();
for(Proposal__c PB : Trigger.new)

if(PB.Proposal_Status__c=='Approved')
{
oppIds.add(PB.Opportunity_Name__c);
}
List<Opportunity> UpdateOpp = [SELECT ID, Latest_Proposal_Approval_Status__c FROM Opportunity WHERE Opportunity.id IN : oppIds];
for(Opportunity ol: UpdateOpp)
{ol.Latest_Proposal_Approval_Status__c='Approved';}
update UpdateOpp;
}

 

Naidu PothiniNaidu Pothini
Trigger UpdateProposalStatusOnOpty on Proposal__c(after insert, after update)
{
	List<Id> OppIds = new List<Id>();
List<Proposal__c> pbList = new List<Proposal__c>(); List<Opportunity> OppList = new List<Opportunity>(); if(trigger.oldMap <> null) { for(Proposal__c PB : Trigger.new) { if(PB.Proposal_Status__c <> trigger.oldMap.get(PB.Id).Proposal_Status__c) { OppIds.add(PB.Opportunity_Name__c)
pbList.add(pb); } } } else { for(Proposal__c PB : Trigger.new) { OppIds.add(PB.Opportunity_Name__c);
pbList.add(pb); } } Map<Id, Opportunity> oppMap = new Map<Id, Opportunity>([SELECT Id, Latest_Proposal_Approval_Status__c FROM Opportunity WHERE Id IN :OppIds]);
for(Proposal__c pb: pbList) { Opportunity Opp = oppMap.get(pb.Opportunity__c); Opp.Latest_Proposal_Approval_Status__c = pb.Proposal_Status__c; OppList.add(Opp); } update OppList; }

 try this.

This was selected as the best answer
Prady01Prady01

Hello there, Just consider opportunities as time cards in the below code, Hope it helps

Object name: Field Name.
Time_Card__c: Text_update_from_Proposal__c(Text) Proposal__c: Proposal_Status__c(Picklist)
Trigger updateTimecard on Proposal__c(before insert, before update){ List<Time_Card__c> TimeCardId = new List<Time_Card__c>(); map<Id, String> ProposalMaptimecard = new map<id,String>(); for(Proposal__c pro: Trigger.new){ ProposalMaptimecard.put(pro.Time_Card__c,pro.Proposal_Status__c); } List<Time_Card__c> tc = [select id,name,Text_update_from_Proposal__c from Time_Card__c where Id in: ProposalMaptimecard.keySet() order by LastModifiedDate desc]; for(Time_Card__c tcc: tc){ if(ProposalMaptimecard.containsKey(tcc.id)){ tcc.Text_update_from_Proposal__c = ProposalMaptimecard.get(tcc.id); TimeCardId.add(tcc); } else{ system.debug('Errooooo0000rrrrrrrr!!'); } } update TimeCardId; }

 Thanks

Prady

AnetaAneta

This worked perfect! Thank you so much for your help. Couldn't have done it without you!!!

AnetaAneta

I have a follow-up question - is there an way to easily modify this trigger to address a possible situation where the proposal record is deleted and the Opportunity displays the Proposal Status from the Proposal that doesn't exist anymore?

Naidu PothiniNaidu Pothini

Is there any specific status when the proposal is to be deleted on?

AnetaAneta

"New" & "Recalled" only.

I have the following statuses defined: New, Pending, Approved, Rejected, Recalled

 

In theory the regular user should not and will not be able to delete a proposal once he/she submits it for approval and it goes to Pending status, and then to Approved or Rejected. But in situations where the Proposal was not yet submitted for approval or was recalled it could pottentialy be deleted. Does this make sense?

Naidu PothiniNaidu Pothini

So you want to set the opportunity status to proposal status when ever a proposal with status "New / Recalled" is deleted. right?

AnetaAneta

Ideally I would like to check to see how many proposals exist on the Opportunity.

If one and it gets deleted then I would like to update the Proposal Status to blank to indicate that no proposals exist.

If more then one, and the last one (new/recalled) is deleted, then i would like to display a Proposal status from the most recent proposal. Hope it makes sense - let me know if you need more clarification.

 

Naidu PothiniNaidu Pothini

Now What happens If there is an opportunity test_Opp, and it has a Proposals and the staus is new, so opp status is new.

 

now if they change the proposal status to Pending, then the opportunity status changes to pending, now if they create another proposal with status new, opp status changes to new.

 

Is this a valid scenario?

 

Can opportunity have multiple Proposal and based on what proposal we set the status of the opportunity?

 

I worked on a similar scenario, where an opportunity can have more than one child and based on both the child records, we set the status of the opportunity..

 

eg: Opp has child1 and child2... if child1 is approved, and child2 is new.... status on opp is partially approved.... if child2 is approved...then opp status is fully approved...

 

 

AnetaAneta

Yes, that is a valid scenario and I guess it could get pretty complicated.... but we would base the Opportunity Proposal status on the proposal with the most current update/proposal status change. So if we had 2 proposals - one pending and one new, then the opty proposal status should be set to the satus of the last modified proposal. If in the meanitime the pending proposal would get approved then the opportunity would show as approved. Then if the new one would get submitted and changed to pending, it would change to pending again.

 

Naidu PothiniNaidu Pothini

so what if the pending proposal is recalled, then opp status is recalled... and if the recalled proposal is deleted, then you need to change the opp status to the one we have ( approved).... right...??

 

but what if the recalled proposal is not deleted?? still the opp status should be recalled??

AnetaAneta

Yes, and yes :) and I thought this was going to be a simple trigger :) can we fix it or is it going to be a nightmare to address all the different possible situations?

Naidu PothiniNaidu Pothini
Trigger UpdateProposalStatusOnOpty on Proposal__c(After Insert, After Update, Before Detele)
{
	if(Trigger.isInsert || Trigger.isUpdate)
	{
		List<Id> OppIds = new List<Id>();
	    List<Proposal__c> pbList = new List<Proposal__c>();
		List<Opportunity> OppList = new List<Opportunity>();

		if(trigger.oldMap <> null)
		{
			for(Proposal__c PB : Trigger.new)
			{
				if(PB.Proposal_Status__c <> trigger.oldMap.get(PB.Id).Proposal_Status__c)
				{
					OppIds.add(PB.Opportunity_Name__c)
	                pbList.add(pb);
				}
			}
		}
		else
		{
			for(Proposal__c PB : Trigger.new)
			{
				OppIds.add(PB.Opportunity_Name__c);
	            pbList.add(pb);
			}
		}

		Map<Id, Opportunity> oppMap = new Map<Id, Opportunity>([SELECT Id, Latest_Proposal_Approval_Status__c FROM Opportunity WHERE Id IN :OppIds]);

		for(Proposal__c pb: pbList)
		{
			Opportunity Opp = oppMap.get(pb.Opportunity__c);
			Opp.Latest_Proposal_Approval_Status__c = pb.Proposal_Status__c;
			OppList.add(Opp);
		}
		update OppList;

	}

	if(trigger.isDelete)
	{
		List<Id> OppIds = new List<Id>();
	    List<Proposal__c> pbList = new List<Proposal__c>();
		List<Opportunity> OppList = new List<Opportunity>();

		for(Proposal__c ps : Trigger.old)
		{
			OppIds.add(ps.Opportunity__c);
		}


		Map<Id, List<Proposal__c>> OppProMap = new Map<Id, List<Proposal__c>>();

		Map<Id, Opportunity> oppMap = new Map<Id, Opportunity>([SELECT Id, Latest_Proposal_Approval_Status__c FROM Opportunity WHERE Id IN :OppIds]);

		for(Proposal ps : [SELECT Id, Name, Proposal_Status__c, Opportunity__c, LastModifiedDate FROM Proposal__c WHERE Opportunity__c IN :OppIds AND Id NOT IN :Trigger.OldMap.keySet()])
		{
			if(OppProMap.get(ps.Opportunity__c) <> null)
			{
				List<Proposal__c> ProList = OppProMap.get(ps.Opportunity__c);

				ProList.add(ps);

				OppProMap.put(ps.Opportunity__c, ProList);
			}
			else
			{
				List<Proposal__c> ProList = new List<Proposal__c>();

				ProList.add(ps);

				OppProMap.put(ps.Opportunity__c, ProList);
			}
		}

		for(Opportunity opp : OppMap.values())
		{
			if(OppProMap.get(Opp.Id) <> null)
			{
				List<Proposal__c> proList = OppProMap.get(Opp.Id);

				if(proList.size() == 1)
				{
					// If the opportunity has only one proposal, then set the proposal status to opportunity
					Opp.Latest_Proposal_Approval_Status__c = proList[0].Proposal_Status__c; 
				}
				else
				{
					//If opportunity has more than one proposal, then if there is 
					
					DateTime dte = null;
					Proposal__c latestPro = new Proposal__c();

					for(Proposal__c pro : proList)
					{
					    System.debug('--------------------------'+acc.LastModifiedDate);
					    
					    DateTime dt = pro.LastModifiedDate;
					    
					    if(dte == null)
					    {
					        dte = dt;
					        latestPro = pro;
					    }
					    else if(dte < dt)
					    {
					        dte = dt;
					        latestPro = pro;
					    }
					}

					Opp.Latest_Proposal_Approval_Status__c = latestPro.Proposal_Status__c;

				}
			}
			else
			{
				// If there are no more proposals on the Opportunity, set the status on opp to what ever you should be... 
				Opp.Latest_Proposal_Approval_Status__c = 'New';
			}

			OppList.add(Opp);
		}

		update OppList;
	}
}

 give a try to this trigger.

AnetaAneta

You are absolutely BRILIANT!!!! This works like a charm!
I got some errors but was able to fix it (especially about the Opportunity__c name - changed it to Opportunity_Name__c) and it works!

Thank you so much for your help!!! I owe you big time!

 

Here is the latest Trigger:

Trigger UpdateProposalStatusOnOpty on Proposal__c(After Insert, After Update, Before Delete)
{
    if(Trigger.isInsert || Trigger.isUpdate)
    {
        List<Id> OppIds = new List<Id>();
        List<Proposal__c> pbList = new List<Proposal__c>();
        List<Opportunity> OppList = new List<Opportunity>();

        if(trigger.oldMap <> null)
        {
            for(Proposal__c PB : Trigger.new)
            {
                if(PB.Proposal_Status__c <> trigger.oldMap.get(PB.Id).Proposal_Status__c)
                {
                    OppIds.add(PB.Opportunity_Name__c);
                    pbList.add(pb);
                }
            }
        }
        else
        {
            for(Proposal__c PB : Trigger.new)
            {
                OppIds.add(PB.Opportunity_Name__c);
                pbList.add(pb);
            }
        }

        Map<Id, Opportunity> oppMap = new Map<Id, Opportunity>([SELECT Id, Latest_Proposal_Approval_Status__c FROM Opportunity WHERE Id IN :OppIds]);

        for(Proposal__c pb: pbList)
        {
            Opportunity Opp = oppMap.get(pb.Opportunity_Name__c);
            Opp.Latest_Proposal_Approval_Status__c = pb.Proposal_Status__c;
            OppList.add(Opp);
        }
        update OppList;

    }

    if(trigger.isDelete)
    {
        List<Id> OppIds = new List<Id>();
        List<Proposal__c> pbList = new List<Proposal__c>();
        List<Opportunity> OppList = new List<Opportunity>();

        for(Proposal__c ps : Trigger.old)
        {
            OppIds.add(ps.Opportunity_Name__c);
        }


        Map<Id, List<Proposal__c>> OppProMap = new Map<Id, List<Proposal__c>>();

        Map<Id, Opportunity> oppMap = new Map<Id, Opportunity>([SELECT Id, Latest_Proposal_Approval_Status__c FROM Opportunity WHERE Id IN :OppIds]);

        for(Proposal__c ps : [SELECT Id, Name, Proposal_Status__c, Opportunity_Name__c, LastModifiedDate FROM Proposal__c WHERE Opportunity_Name__c IN :OppIds AND Id NOT IN :Trigger.OldMap.keySet()])
        {
            if(OppProMap.get(ps.Opportunity_Name__c) <> null)
            {
                List<Proposal__c> ProList = OppProMap.get(ps.Opportunity_Name__c);

                ProList.add(ps);

                OppProMap.put(ps.Opportunity_Name__c, ProList);
            }
            else
            {
                List<Proposal__c> ProList = new List<Proposal__c>();

                ProList.add(ps);

                OppProMap.put(ps.Opportunity_Name__c, ProList);
            }
        }

        for(Opportunity opp : OppMap.values())
        {
            if(OppProMap.get(Opp.Id) <> null)
            {
                List<Proposal__c> proList = OppProMap.get(Opp.Id);

                if(proList.size() == 1)
                {
                    // If the opportunity has only one proposal, then set the proposal status to opportunity
                    Opp.Latest_Proposal_Approval_Status__c = proList[0].Proposal_Status__c; 
                }
                else
                {
                    //If opportunity has more than one proposal, then if there is 
                    
                    DateTime dte = null;
                    Proposal__c latestPro = new Proposal__c();

                    for(Proposal__c pro : proList)
                    {
                        //System.debug('--------------------------'+acc.LastModifiedDate);
                        
                        DateTime dt = pro.LastModifiedDate;
                        
                        if(dte == null)
                        {
                            dte = dt;
                            latestPro = pro;
                        }
                        else if(dte < dt)
                        {
                            dte = dt;
                            latestPro = pro;
                        }
                    }

                    Opp.Latest_Proposal_Approval_Status__c = latestPro.Proposal_Status__c;

                }
            }
            else
            {
                // If there are no more proposals on the Opportunity, set the status on opp to what ever you should be... 
                Opp.Latest_Proposal_Approval_Status__c = 'New';
            }

            OppList.add(Opp);
        }

        update OppList;
    }
}

AnetaAneta

One more question - I tested it in the sandbox and it works. Will it also work in Production or do I need a test class for this? Hope not - never wrote one in my life :)

Naidu PothiniNaidu Pothini

If your org has above 75% coverage then you dont need a test class ( not a good way)... but every class should have a test class to make sure the class is working perfectly with out issues...

AnetaAneta

I appologize for my ignorance, what is coverage? as you can tell I'm brand new to triggers and development in apex, so I appologize for silly questions.

Naidu PothiniNaidu Pothini

http://wiki.developerforce.com/page/An_Introduction_to_Apex_Code_Test_Methods

 

i guess this link will guide you through the process of creating a test class.

 

Let me know if you need any help.

AnetaAneta

Thank you Naidu for the link. This looks very complicated - don't know if I'll be able to write the test class :( does that mean that I won't be able to deploy the trigger in the Production without the test class?

 

Naidu PothiniNaidu Pothini
@isTest
public class OpportunityTriggerTestClass
{
	static testMethod void OpportunityTriggerTest()
    {
        test.startTest();

        Account acct = new Account(---- required fields ----);

        insert acct;

        Opportunity Opp = new Opportunity(AccountId = acct.Id, --- required fields ----);

        insert Opp;

        Proposal__c ps = new Proposal(Opportunity_Name__c = Opp.Id, --- required fields ---, Proposal_Status__c ='new');

        insert ps;

        System.assertequals('new', opp.Latest_Proposal_Approval_Status__c);


        test.stopTest();
    }
}

 try this simple test class... let me know if you are able to run this test class.

AnetaAneta

I updated the test class with the required field info (see belwo) and I keep getting the following error:

Error Message System.AssertException: Assertion Failed: Expected: new, Actual: null Stack Trace Class.OpportunityUpdateTriggerTest.OpportunityUpdateTriggerTest: line 20, column 1

 

Not sure how to fix it.

 

@isTest
public class OpportunityUpdateTriggerTest
{
    static testMethod void OpportunityUpdateTriggerTest()
    {
        test.startTest();

        Account acct = new Account(Name = 'Test Account ');

        insert acct;

        Opportunity Opp = new Opportunity(AccountId = acct.Id, Name = 'Test Opportunity', StageName ='1- Lead Gen' , CloseDate = date.today());

        insert Opp;

        Proposal__c ps = new Proposal__c(Opportunity_Name__c = Opp.Id,  Name = 'Test Proposal', Account__c = acct.Id, Proposal_Status__c ='new');

        insert ps;

        System.assertEquals('new', Opp.Latest_Proposal_Approval_Status__c);


        test.stopTest();
    }
}

 

 

Naidu PothiniNaidu Pothini
@isTest
public class OpportunityUpdateTriggerTest
{
    static testMethod void OpportunityUpdateTriggerTest()
    {
        test.startTest();

        Account acct = new Account(Name = 'Test Account ');

        insert acct;

        Opportunity Opp = new Opportunity(AccountId = acct.Id, Name = 'Test Opportunity', StageName ='1- Lead Gen' , CloseDate = date.today());

        insert Opp;

        Proposal__c ps = new Proposal__c(Opportunity_Name__c = Opp.Id,  Name = 'Test Proposal', Account__c = acct.Id, Proposal_Status__c ='new');

        insert ps;

        test.stopTest();
    }
}

 try this...

AnetaAneta

It worked but it only gave me 28% (15/53) coverage... don't think that's sufficient, is it?

Naidu PothiniNaidu Pothini
@isTest
public class OpportunityUpdateTriggerTest
{
    static testMethod void OpportunityUpdateTriggerTest()
    {
        test.startTest();

        Account acct = new Account(Name = 'Test Account ');

        insert acct;

        Opportunity Opp = new Opportunity(AccountId = acct.Id, Name = 'Test Opportunity', StageName ='1- Lead Gen' , CloseDate = date.today());

        insert Opp;

        Proposal__c ps = new Proposal__c(Opportunity_Name__c = Opp.Id,  Name = 'Test Proposal', Account__c = acct.Id, Proposal_Status__c ='new');

        insert ps;

ps.Proposal_Status__c = 'recalled';
update ps;


Proposal__c ps2 = new Proposal__c(Opportunity_Name__c = Opp.Id, Name = 'Test Proposal 2', Account__c = acct.Id, Proposal_Status__c = 'Approved');
insert ps2;

delete ps2; test.stopTest(); } }

 try this.

 

To deploy a trigger, we need atleast 1% coverage on the trigger, so you can deploy it now... but having the coverage more than 75% is safe... 

AnetaAneta

You are ubelievable! Thank you so much, this ran perfect and gave me 71% coverage.

 

Since you're so kind and helpfull, I thought I would ask you to help me write a class test for the following trigger. It checks for the attachments in the Notes & Attachemnt section of the Proposal__c custom object and updates a checkbox Attachment _Added__c to indicate whereter attachement was added or not.

 

// Trigger to update the Attachment_Added__c custom checkbox field in Proposal__C custom object if it has any attachment.
trigger CountAttachments on Attachment (after insert, before delete, after delete) 
{  
if(trigger.isinsert){        
List<Proposal__c> co = [select id, Attachment_Added__c from Proposal__c where id =: Trigger.New[0].ParentId];          
If(co.size()>0)          
{              
co[0].Attachment_Added__c = True;              
update co;          
} 
}
if(trigger.isdelete){

List<Proposal__c> co = [select id, Attachment_Added__c from Proposal__c where id =: Trigger.old[0].ParentId]; 
        
If(co.size()>0)          
{  
List<Attachment> allChildren = [Select id from Attachment where parentid = :co[0].id]; 
if(allChildren != null && allChildren.size() == 0)            
co[0].Attachment_Added__c = false;              
update co;          
} 
}
}

 

Naidu PothiniNaidu Pothini

Did you write this trigger? you need to bulkify this code.. it works only when you insert or delete one attachment... but fails in case you insert or delete more than one attachment....

 

Did you try inserting or deleting multiple attachments at a time?

AnetaAneta

Of course not - I would not be capable of writing this :) Had another food soul helping me - here's the link to the post where I posted a question about this: http://boards.developerforce.com/t5/Apex-Code-Development/Trigger-on-Attachments/td-p/592297

 

Someone had mentioned this to me already, but it worked when I manually added the attachments one at a time. 

This whole programmig thing is cool, but only when you know what you're doing... and I'm green as you can be. Need to take some classes to get myself upto speed.

Naidu PothiniNaidu Pothini
trigger CountAttachments on Attachment (after insert, before delete) 
{
  List<Id> parentIds = new List<Id>();
  List<Proposal__c> proposals = new List<Proposal__c>();

  if(trigger.isinsert)
  {
    for(Attachment at : Trigger.new)
    {
      parentIds.add(at.ParentId);
    }
  }

  if(trigger.isDelete)
  {
    for(Attachment at : Trigger.old)
    {
      parentIds.add(at.ParentId);
    }
  }

  Map<Id, AggregateResult> arMap = new Map<Id, AggregateResult>([SELECT ParentId Id, Count() cnt 
                                                                 FROM Attachment
                                                                 WHERE ParentId IN :parentIds 
                                                                 AND Id Not IN :trigger.oldmap.keyset()]);

  for(Proposal__c ps : [SELECT Id, Attachment_Added__c FROM Proposal WHERE Id IN :ParentIds])
  {
    if(arMap.get(ps.Id) <> null)
    {
      ps.Attachment_Added__c = true;
    }
    else
    {
        ps.Attachment_Added__c = false;
    }

    proposals.add(ps);
  }

  if(proposals.size() > 0)
  {
    update proposals;
  }
}

 try this... this code is bulkified... try inserting and deleting multiple attachments... let me know how it goes...

Naidu PothiniNaidu Pothini
@isTest
public class AttachmentTriggerTest
{
    static testMethod void attTriggerTest1()
    {
        test.startTest();

        Account acct = new Account(Name = 'Test Account ');

        insert acct;

        Opportunity Opp = new Opportunity(AccountId = acct.Id, Name = 'Test Opportunity', StageName ='1- Lead Gen' , CloseDate = date.today());

        insert Opp;

        Proposal__c ps = new Proposal__c(Opportunity_Name__c = Opp.Id,  Name = 'Test Proposal', Account__c = acct.Id, Proposal_Status__c ='new');

        insert ps;

        Attachment att = new Attachment(Name='textAtt', ParentId = ps.Id, Body = 'Test', Description='TestAttachment');
        insert att;

        delete att;
        
        test.stopTest();
    }
}

 try this test class

AnetaAneta

For the trigger I'm getting this error - it's pointing to the Count() in the Select statement.

Error: Compile Error: unexpected token: ')' at line 22 column 91

AnetaAneta

For the test class, I'm getting the following error:

 

Error: Compile Error: Invalid initial expression type for field Attachment.Body, expecting: Blob at line 20 column 82

Naidu PothiniNaidu Pothini
trigger CountAttachments on Attachment (after insert, before delete) 
{
  List<Id> parentIds = new List<Id>();
  List<Proposal__c> proposals = new List<Proposal__c>();

  if(trigger.isinsert)
  {
    for(Attachment at : Trigger.new)
    {
      parentIds.add(at.ParentId);
    }
  }

  if(trigger.isDelete)
  {
    for(Attachment at : Trigger.old)
    {
      parentIds.add(at.ParentId);
    }
  }

  Map<Id, AggregateResult> arMap = new Map<Id, AggregateResult>([SELECT ParentId Id, Count(Id) cnt 
                                                                 FROM Attachment
                                                                 WHERE ParentId IN :parentIds 
                                                                 AND Id Not IN :trigger.oldmap.keyset()
                                                                 GROUP BY ParentId]);

  for(Proposal__c ps : [SELECT Id, Attachment_Added__c FROM Proposal WHERE Id IN :parentIds])
  {
    if(arMap.get(ps.Id) <> null)
    {
      ps.Attachment_Added__c = true;
    }
    else
    {
        ps.Attachment_Added__c = false;
    }

    proposals.add(ps);
  }

  if(proposals.size() > 0)
  {
    update proposals;
  }
}

Test Class:
@isTest public class AttachmentTriggerTest { static testMethod void attTriggerTest1() { test.startTest(); Account acct = new Account(Name = 'Test Account '); insert acct; Opportunity Opp = new Opportunity(AccountId = acct.Id, Name = 'Test Opportunity', StageName ='1- Lead Gen' , CloseDate = date.today()); insert Opp; Proposal__c ps = new Proposal__c(Opportunity_Name__c = Opp.Id, Name = 'Test Proposal', Account__c = acct.Id, Proposal_Status__c ='new'); insert ps; Attachment att = new Attachment(Name='textAtt', ParentId = ps.Id, Description='TestAttachment'); insert att; delete att; test.stopTest(); } }

 

AnetaAneta

I was able to fix the class - used this instead:

body = Blob.valueOf('Some Text')

 

Here's the final test class:

 

@isTest
public class AttachmentTriggerTest
{
    static testMethod void attTriggerTest1()
    {
        test.startTest();

        Account acct = new Account(Name = 'Test Account ');

        insert acct;

        Opportunity Opp = new Opportunity(AccountId = acct.Id, Name = 'Test Opportunity', StageName ='1- Lead Gen' , CloseDate = date.today());

        insert Opp;

        Proposal__c ps = new Proposal__c(Opportunity_Name__c = Opp.Id,  Name = 'Test Proposal', Account__c = acct.Id, Proposal_Status__c ='new');

        insert ps;

        Attachment att = new Attachment(Name='textAtt', ParentId = ps.Id, body = Blob.valueOf('Some Text'), Description='TestAttachment');
        insert att;

        delete att;
        
        test.stopTest();
    }
}

 

AnetaAneta

The trigger is causing some errors:

 

System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, CountAttachments: execution of AfterInsert

caused by: System.NullPointerException: Attempt to de-reference a null object

Trigger.CountAttachments: line 23, column 1: []

Naidu PothiniNaidu Pothini
trigger CountAttachments on Attachment (after insert, before delete) 
{
  List<Id> parentIds = new List<Id>();
  List<Proposal__c> proposals = new List<Proposal__c>();

  if(trigger.isinsert)
  {
    for(Attachment at : Trigger.new)
    {
      parentIds.add(at.ParentId);
    }

    for(Proposal__c ps : [SELECT Id, Attachment_Added__c FROM Proposal WHERE Id IN :parentIds])
    {
      ps.Attachment_Added__c = true;
      proposals.add(ps);
    }
  }

  if(trigger.isDelete)
  {
    for(Attachment at : Trigger.old)
    {
      parentIds.add(at.ParentId);
    }

    Map<Id, AggregateResult> arMap = new Map<Id, AggregateResult>([SELECT ParentId Id, Count(Id) cnt 
                                                                   FROM Attachment
                                                                   WHERE ParentId IN :parentIds 
                                                                   AND Id Not IN :trigger.oldmap.keyset()
                                                                   GROUP BY ParentId]);

    for(Proposal__c ps : [SELECT Id, Attachment_Added__c FROM Proposal WHERE Id IN :parentIds])
    {
      if(arMap.get(ps.Id) <> null)
      {
        ps.Attachment_Added__c = true;
      }
      else
      {
          ps.Attachment_Added__c = false;
      }

      proposals.add(ps);
    }
  }

  if(proposals.size() > 0)
  {
    update proposals;
  }
}

 my mistake.. this will work...

AnetaAneta

I said that many times already, but you are simply BRILIANT!

THANK YOU so much for all your help!!! I'm really thankfull for good people like you that will take the time to help others in need. Couldn't have done it without you!

 

Sincerely,

Aneta