You need to sign in to do that
Don't have an account?
Not able to specify access level while inserting Account Team member
Hi All,
I have a requirement to insert Account Team member when there is an update on account. While inserting the Account Team member I am not able to specify access level for Account. I am getting the below error -
Field is not writeable: AccountTeamMember.AccountAccessLevel.
Below is my code:
trigger AccountTeam on Account (after update) { for(Account a:trigger.new) { AccountTeamMember Teammemberad=new AccountTeamMember(); Teammemberad.AccountId=a.id; Teammemberad.UserId='00580000001nhJT'; Teammemberad.TeamMemberRole = 'Account Manager'; Teammemberad.AccountAccessLevel= 'Read'; insert Teammemberad; } }
Also I need to specify access levels for Contact, Opportunity and Cases for which I am not able to find out.
Any suggestion on this will be of great help!!!
Thanks in advance!!
You actually need to specify the access level from the share object. So, for example, with the account team, you need to add the user to the account team, and then add a record to the AccountShare table with the appropriate access.
Also, to make your trigger more effecient and bulk safe, I would recommend you create a list of items to add, then add them in one DML statement.
Something like this:
trigger AccountTeam on Account (after update) { AccountTeamMember[] newmembers = new AccountTeamMember[]{}; //list of new team members to add AccountShare[] newShare = new AccountShare[]{}; //list of new shares to add for(Account a:trigger.new){ AccountTeamMember Teammemberad=new AccountTeamMember(); Teammemberad.AccountId=a.id; Teammemberad.UserId='00580000001nhJT'; Teammemberad.TeamMemberRole = 'Account Manager'; newmembers.add(Teammemberad); } Database.SaveResult[] lsr = Database.insert(newmembers,false);//insert any valid members then add their share entry if they were successfully added Integer newcnt=0; for(Database.SaveResult sr:lsr){ if(!sr.isSuccess()){ Database.Error emsg =sr.getErrors()[0]; system.debug('\n\nERROR ADDING TEAM MEMBER:'+emsg); }else{ newShare.add(new AccountShare(UserOrGroupId=newmembers[newcnt].UserId, AccountId=newmembers[newcnt].Accountid, AccountAccessLevel='Read',OpportunityAccessLevel='Read')); } newcnt++; } Database.SaveResult[] lsr0 =Database.insert(newShare,false); //insert the new shares Integer newcnt0=0; for(Database.SaveResult sr0:lsr0){ if(!sr0.isSuccess()){ Database.Error emsg0=sr0.getErrors()[0]; system.debug('\n\nERROR ADDING SHARING:'+newShare[newcnt0]+'::'+emsg0); } newcnt0++; } }
All Answers
You actually need to specify the access level from the share object. So, for example, with the account team, you need to add the user to the account team, and then add a record to the AccountShare table with the appropriate access.
Also, to make your trigger more effecient and bulk safe, I would recommend you create a list of items to add, then add them in one DML statement.
Something like this:
trigger AccountTeam on Account (after update) { AccountTeamMember[] newmembers = new AccountTeamMember[]{}; //list of new team members to add AccountShare[] newShare = new AccountShare[]{}; //list of new shares to add for(Account a:trigger.new){ AccountTeamMember Teammemberad=new AccountTeamMember(); Teammemberad.AccountId=a.id; Teammemberad.UserId='00580000001nhJT'; Teammemberad.TeamMemberRole = 'Account Manager'; newmembers.add(Teammemberad); } Database.SaveResult[] lsr = Database.insert(newmembers,false);//insert any valid members then add their share entry if they were successfully added Integer newcnt=0; for(Database.SaveResult sr:lsr){ if(!sr.isSuccess()){ Database.Error emsg =sr.getErrors()[0]; system.debug('\n\nERROR ADDING TEAM MEMBER:'+emsg); }else{ newShare.add(new AccountShare(UserOrGroupId=newmembers[newcnt].UserId, AccountId=newmembers[newcnt].Accountid, AccountAccessLevel='Read',OpportunityAccessLevel='Read')); } newcnt++; } Database.SaveResult[] lsr0 =Database.insert(newShare,false); //insert the new shares Integer newcnt0=0; for(Database.SaveResult sr0:lsr0){ if(!sr0.isSuccess()){ Database.Error emsg0=sr0.getErrors()[0]; system.debug('\n\nERROR ADDING SHARING:'+newShare[newcnt0]+'::'+emsg0); } newcnt0++; } }
Hey Jim,
The solution worked great!!!!
Thanks a ton!!
Jim, nice code. I am having trouble changing this to add the current user as Account Team member. Can you help?
Also, what about the idea proposed in this message: http://community.salesforce.com/sforce/board/message?board.id=apex&view=by_date_ascending&message.id=24696#M24696
Upon insert, add creator to acct team but transfer ownership to another (fixed) use?
thanks!
Here is a modified version that adds the current user modifying the Account to the account team.
trigger AccountTeam on Account (after update) { AccountTeamMember[] newmembers = new AccountTeamMember[]{}; //list of new team members to add AccountShare[] newShare = new AccountShare[]{}; //list of new shares to add ID uid = UserInfo.getUserId(); //get the user id of the user running the trigger, anyone that changes the Account will added to the account team for(Account a:trigger.new){ AccountTeamMember Teammemberad=new AccountTeamMember(); Teammemberad.AccountId=a.id; Teammemberad.UserId=uid; Teammemberad.TeamMemberRole = 'Account Modifier'; newmembers.add(Teammemberad); } Database.SaveResult[] lsr = Database.insert(newmembers,false);//insert any valid members then add their share entry if they were successfully added Integer newcnt=0; for(Database.SaveResult sr:lsr){ if(!sr.isSuccess()){ Database.Error emsg =sr.getErrors()[0]; system.debug('\n\nERROR ADDING TEAM MEMBER:'+emsg); }else{ newShare.add(new AccountShare(UserOrGroupId=newmembers[newcnt].UserId, AccountId=newmembers[newcnt].Accountid, AccountAccessLevel='Read',OpportunityAccessLevel='Read')); } newcnt++; } Database.SaveResult[] lsr0 =Database.insert(newShare,false); //insert the new shares Integer newcnt0=0; for(Database.SaveResult sr0:lsr0){ if(!sr0.isSuccess()){ Database.Error emsg0=sr0.getErrors()[0]; system.debug('\n\nERROR ADDING SHARING:'+newShare[newcnt0]+'::'+emsg0); } newcnt0++; } }
For your on insert, this is a bit more tricky, because the Account ID doesn't exist until after the commit happens. You have to be cautious you don't get into a looping situation. I will have to think about that one, unless someone else jumps in first.
Tried to assign user Department to the Acct Team Role but get a
Teammemberad.TeamMemberRole = User.Department;
User.department is a field name. You would need to query the user object for this data, then get a string out, and then you could use it:
Here is a modified version of the code:
trigger AccountTeam on Account (after update) { AccountTeamMember[] newmembers = new AccountTeamMember[]{}; //list of new team members to add AccountShare[] newShare = new AccountShare[]{}; //list of new shares to add User currentuser = [select id,name,department from user where id=:UserInfo.getUserId() LIMIT 1]; //get the user running the trigger, anyone that changes the Account will added to the account team ID uid=currentuser.id; String dept=currentuser.department; for(Account a:trigger.new){ AccountTeamMember Teammemberad=new AccountTeamMember(); Teammemberad.AccountId=a.id; Teammemberad.UserId=uid; Teammemberad.TeamMemberRole = dept; newmembers.add(Teammemberad); } Database.SaveResult[] lsr = Database.insert(newmembers,false);//insert any valid members then add their share entry if they were successfully added Integer newcnt=0; for(Database.SaveResult sr:lsr){ if(!sr.isSuccess()){ Database.Error emsg =sr.getErrors()[0]; system.debug('\n\nERROR ADDING TEAM MEMBER:'+emsg); }else{ newShare.add(new AccountShare(UserOrGroupId=newmembers[newcnt].UserId, AccountId=newmembers[newcnt].Accountid, AccountAccessLevel='Read',OpportunityAccessLevel='Read')); } newcnt++; } Database.SaveResult[] lsr0 =Database.insert(newShare,false); //insert the new shares Integer newcnt0=0; for(Database.SaveResult sr0:lsr0){ if(!sr0.isSuccess()){ Database.Error emsg0=sr0.getErrors()[0]; system.debug('\n\nERROR ADDING SHARING:'+newShare[newcnt0]+'::'+emsg0); } newcnt0++; } }
Jim, thanks.
I just tested this, worked fine. Changed it to an "after insert" and also worked!
I have combined the above with this trigger below:
trigger testChangeOwnerTrigger on Account (before insert) { for(Account newAccount : Trigger.New){ newAccount.OwnerId ='00530000000iMRl'; } }
in my sandbox and upon create I get both to work - the account is transferred to the designated owner and the creator is added to account team with role based on department.
I am not skilled enough to write test methods but i bet this could be deployed through change sets.Are there any issues that jump out about using these?
Have not fully decided to implement but like the possibilities.
Thanks gain Jim.
OK, now I am trying to rework that trigger to add a certtain user to a Case team upon creation of a case of a certain record type but am running into some issues...
trigger CaseTeamCreator on Case (after insert) {
CaseTeamMember[] newmembers = new CaseTeamMember[]{}; //list of new team members to add
CaseShare[] newShare = new CaseShare[]{}; //list of new shares to add
User currentuser = [select id,name,department from user where id=:UserInfo.getMemberId() LIMIT 1]; //get the user running the trigger, anyone that changes the Case will added to the Case team
ID uid=currentuser.id;
String dept=currentuser.Department;
for(Case a:trigger.new){
CaseTeamMember Teammemberad=new CaseTeamMember();
Teammemberad.ParentId=a.id;
Teammemberad.MemberId=uid;
Teammemberad.TeamRoleId = dept;
newmembers.add(Teammemberad);
}
Database.SaveResult[] lsr = Database.insert(newmembers,false);//insert any valid members then add their share entry if they were successfully added
Integer newcnt=0;
for(Database.SaveResult sr:lsr){
if(!sr.isSuccess()){
Database.Error emsg =sr.getErrors()[0];
system.debug('\n\nERROR ADDING TEAM MEMBER:'+emsg);
}else{
newShare.add(new CaseShare(UserOrGroupId=newmembers[newcnt].MemberId, CaseId=newmembers[newcnt].Caseid, CaseAccessLevel='Full'));
}
newcnt++;
}
Database.SaveResult[] lsr0 =Database.insert(newShare,false); //insert the new shares
Integer newcnt0=0;
for(Database.SaveResult sr0:lsr0){
if(!sr0.isSuccess()){
Database.Error emsg0=sr0.getErrors()[0];
system.debug('\n\nERROR ADDING SHARING:'+newShare[newcnt0]+'::'+emsg0);
}
newcnt0++;
}
}
Looks like your only error is that you are using a method "getMemberID()" on the UserInfo, and that doesn't appear to exist.
You should use getUserID(), like we did on the account trigger.
It appears, what your code would do is after a case is created, it would add the creator to the case team (with the change I suggested). It you want something to do both creation and update, you would need to change your trigger to (after insert, after update) Otherwise, it would only fire when the case is inserted.
Right, what I'd like would be one that only on certain cases, adds a speciic user id, not current user, but am not able to put that in, running into syntax errors. Setting specified text... a role, etc.
So, to add a specific user, that is not the running user, you would need to add a second query to the code to get that user object record, you will need to update the query to find the user correctly. Then you could add it to the teammember list and it would get added with the rest.
I am getting an error on this line:
Teammemberad.TeamRoleId = dept;
Apex trigger CaseTeamCreator caused an unexpected exception, contact your administrator: CaseTeamCreator: execution of AfterInsert caused by: System.StringException: Invalid id: ELX Support: Trigger.CaseTeamCreator: line 14, column 11
It looks like what I need is the SFID of the Case Team Role, right?
I think I can cut out the running user that gets added, will work for me and simplify the trigger...
Yes, it appears you need the id. I don't have this type of Case trigger implemented, as we don't use cases that way, so my code was all theoretical. If you are somehow mapping the user's department to a case team role, you will probably have to create a map of all of the case team roles, with the name as the key field and the ID as a value in the map, then search for it by looping through the map. IF the department doesn't exist, you will need to either have error handling or a default role you want to use.
Hah, yes, it works when I put the role ID into users' Dept field, but that's not a real solution...
So I got it to do only the standing user:
trigger CaseTeamCreator on Case (after insert) {
CaseTeamMember[] newmembers = new CaseTeamMember[]{}; //list of new team members to add
CaseShare[] newShare = new CaseShare[]{}; //list of new shares to add
User standinguser = [select id,name,department from user where name = 'Joe Smith' LIMIT 1];//new common user that always gets added
ID stid =standinguser.id;
String stddept = standinguser.department;
for(Case a:trigger.new){
CaseTeamMember stTeammemberad=new CaseTeamMember();
stTeammemberad.ParentId=a.id;
stTeammemberad.MemberId=stid;
stTeammemberad.TeamRoleId = stddept;
newmembers.add(stTeammemberad);
But need to change dept to the Role id, fixed. and add the "where case Record type = ..."
Just want Role Id fixed, since it's one Record Type of cases and want to add one user, always...
Jim, thanks for your help. I got to set it to a defined role for standing user. Can yuo asist me with building a test method so I can deploy?
This should get you started.
Hey Jim, great stuff here, going back to the original CaseTeamCreator trigger that adds the currentuser to the case team when a case is created, can you help with out with an apex class so I can deploy the trigger?
Something like this should work:
Thanks Jim. If I wanted to limit the trigger to only occur on certain Case Record Types, how would I represent that in the trigger?
YOu would need to modify the loop on the Trigger.new to use an "If" condition.
OK thanks. I really appreciate your help on this.
Reviving an old post that helped me out a lot in the past -
thoughts on making the new teamMember's access to Opportunity still private? I have a larger code piece that inserts acct teams and chatter subscriptions upon creation of a new custom object matching account coverage from an internal system, but am not quite able to get Read Only access to stick. Inserting a new opportunity share object wouldn't work b/c there's no opportunity to reference. Thoughts? thanks