You need to sign in to do that
Don't have an account?
Holly Havelka 10
Help with Apex Sharing Trigger on Custom Object
Hi all,
I have the below trigger, which is throwing this error: First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Contact, User/Group]: [Contact, User/Group]: Trigger.AffiliationMakePublicContactTrigger: line 64, column 1
I want to share the contact (contact lookup) from the affiliation record with a specified public group whether that happens on insert or on update.
Any thoughts on what I am missing?
I have the below trigger, which is throwing this error: First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Contact, User/Group]: [Contact, User/Group]: Trigger.AffiliationMakePublicContactTrigger: line 64, column 1
trigger AffiliationMakePublicContactTrigger on npe5__Affiliation__c (before insert) { // Get the Account Name Details Set<Id> AcctId = new Set<Id>(); List<Account> AccountLists = new List<Account>(); Map<Id,String> AccountNameMap = new Map<Id,String>(); for(npe5__Affiliation__c aff : trigger.new) { if(aff.npe5__Organization__r != null) { AcctId.add(aff.npe5__Organization__r.Id); } } if(AcctId.size() > 0) { AccountLists = [select Id,name from Account where Id IN: AcctId]; } for(Account acc :AccountLists ) { AccountNameMap.put(acc.id,acc.Name); } // Get the Group Details List<Group> groups = [SELECT Email,Id,Name FROM Group]; Map<String,Id> GroupMap = new MAp<String,Id>(); for( Group grp:groups) { if(grp.Name != null && grp.Name != '') { GroupMap.put(grp.Name,grp.Id); } } // inserting new records if (Trigger.isInsert) { List<ContactShare> sharesToCreate = new List<ContactShare>(); for (npe5__Affiliation__c affiliation : Trigger.new) { if (affiliation.Make_Public__c == true) { // create the new share for group ContactShare cs = new ContactShare(); cs.ContactAccessLevel = 'Edit'; cs.ContactId = affiliation.npe5__Contact__r.Id; system.debug(cs.ContactId); if(GroupMap.containsKey(AccountNameMap.get(affiliation.npe5__Organization__r.Id))) cs.UserOrGroupId = GroupMap.get(AccountNameMap.get(affiliation.npe5__Organization__r.Id)); sharesToCreate.add(cs); } } // do the DML to create shares if (!sharesToCreate.isEmpty()) insert sharesToCreate; // updating existing records } else if (Trigger.isUpdate) { List<ContactShare> sharesToCreate = new List<ContactShare>(); List<ID> shareIdsToDelete = new List<ID>(); for (npe5__Affiliation__c affiliation : Trigger.new) { // if the record was public but is now private -- delete the existing share if (Trigger.oldMap.get(affiliation.Id).Make_Public__c == true && affiliation.Make_Public__c == false) { shareIdsToDelete.add(affiliation.Id); // if the record was private but now is public -- create the new share for the group } else if (Trigger.oldMap.get(affiliation.Id).Make_Public__c == false && affiliation.Make_Public__c == true) { // create the new share with read/write access ContactShare cs = new ContactShare(); cs.ContactAccessLevel = 'Edit'; cs.ContactId = affiliation.npe5__Contact__r.Id; if(GroupMap.containsKey(AccountNameMap.get(affiliation.npe5__Organization__r.Id))) cs.UserOrGroupId = GroupMap.get(AccountNameMap.get(affiliation.npe5__Organization__r.Id)); sharesToCreate.add(cs); } } // do the DML to delete shares if (!shareIdsToDelete.isEmpty()) delete [select id from ContactShare where ContactId IN :shareIdsToDelete and RowCause = 'Manual']; // do the DML to create shares if (!sharesToCreate.isEmpty()) insert sharesToCreate; } }I have the affiliation object (from NPSP), and it creates the following records with these fields: organization affiliation (account lookup), contact (contact lookup) and 'make public' field.
I want to share the contact (contact lookup) from the affiliation record with a specified public group whether that happens on insert or on update.
Any thoughts on what I am missing?
All Answers
Here is my updated code, which is still throwing the same error:
Validation Errors While Saving Record(s)
There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Apex trigger AffiliationMakePublicContactTrigger caused an unexpected exception, contact your administrator: AffiliationMakePublicContactTrigger: execution of BeforeDelete caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.AffiliationMakePublicContactTrigger: line 8, column 1".
Is this because the trigger is trying to execute all of the logic before the isDelete section?
I changed it to 'before delete' and I fixed the '// if the record was public but is now private -- delete the existing share' line as it was not pulling in the contact id to remove the sharing if the 'Make Public' was removed.
- Affiliation 1 - Test Organization A, Make Public = True, Test Contact
- Contact share record created for Test Organization A (Public Group)
- Affiliation 2 - Test Organization B, Make Public = True, Test Contact
- Contact share record created for Test Organization B (Public Group)
When I delete the record for Affiliation 1, I want the trigger to also delete the contact share record for Test Organization A (Public Group), but leave the contact share record for Test Organization B (Public Group) untouched.My suggestion would be to have a new object, a junction object to link contactshare and affiliation.
This would require the trigger to be updated such that this junction object is created in the insert, updated in the update and deleted in the delete.
Use this junction object to stage/store the relationship. Then on delete you would reference that custom object to do the lookup for the affilation and contactshare, and delete the specific contactshare.
This presupposes that a ContactShare can be uniquely identified by UserorGroupId and ContactId. If so, you are right on the money.
The code looks fine to me (disclaimer: it is 23:58 hours over here).
There are (2) affiliations created for (1) contact:
- Affiliation 1 - Test Organization A, Make Public = True, Test Contact
- Contact share record created for Test Organization A (Public Group)
- Affiliation 2 - Test Organization A, Make Public = True, Test Contact
- Contact share record already created because of Affiliation 1 record above
When I delete the record for Affiliation 1, I want the trigger to only delete the contact share record IF no other affiliation records exists for the test organization. Meaning there is no other reason to continue sharing the record with that organization. So, for the example above, I want the trigger to run but stop when it sees that Affiliation 2 exists.