Log.add(new Cx_Trans_Log__c(
Object__c = 'Activity',
Object_Id__c = newActivity.Name,
Owner2_Id__c = newActivity.Owner1_Id__c,
I am using the above code to create a new log record when an activity is changed in salesforce.com. The Owner2_Id__c that is created from newActivity.Owner1_Id__c doesn't give me the name of the Owner1_Id__c (this is a lookup(User) field). Is there a way to get the User name that is displayed in Owner1 to Owner2?
The right way to do it is to make one query. For this example, I'll assume by activities you mean Tasks:
Set<Id> userIds = new Set<Id>();
for (Task t : Trigger.new) {
userIds.add(t.OwnerId);
}
Map<Id, User> users = new Map<Id, User>([SELECT Name FROM User WHERE Id IN :userIds]);
// then you could plug something like this into your existing code
String userName = users.get(newActivity.Onwer1_Id__c).Name;
Related
Thank you very much for helping.
Problem Statement
I have a Map containing Map a string key and Salesforce Account,
I want to insert the Account but for each account, I want to create a new Map
with the same string as key and Account Id as value.
Tried
What actually I did I iterate over the map get the value to insert into database and then if the record is successfully inserted I add value to the new map, "I am inserting the account in the For Loop which is a bad Practice may hit DML Limit"
Sudo Code
Account acc = new Account(Name ='Test');
Map<String,Id> accMapId = new Map<String,Id>();
Map<String,Account> accMap = new Map<String,Account>();
accMap.put('A13',acc);
for(String accIterate : accMap.keySet()){
Database.SaveResult rt = Database.insert(accMap.get(accIterate));
if(rt.isSuccess()){
accMapId.put(accIterate,rt.id);
}
}
Question:
How can I avoid to insert the Account Object within for Loop and Build my accMapId
Use myMap.values() to "flatten" the map into a List (in your case list of accounts), insert the whole list. Such flattening just keeps references so the original accounts in the map will be silently updated with the generated record Id.
Map<String, Account> accounts = new Map<String, Account>{
'A13' => new Account(Name ='Test'),
'B14' => new Account(Name = 'Another')
};
insert accounts.values(); // You can use Database.insert() if you want, it accepts a list too.
Map<String, Id> idsByKey = new Map<String, Id>();
for(String s : accounts.keyset()){
idsByKey.put(s, accounts.get(s).Id);
}
System.debug(idsByKey);
I set up a stats command as follows
[Command("Stats")]
public async Task StatsOther(SocketUser socketUser = null)
{
if (socketUser == null)
{
socketUser = Context.User;
}
var account = UserAccounts.GetAccount(socketUser);
await Context.Channel.SendMessageAsync($"Hey {socketUser.Mention}, You have {account.Size} long sandwhiches and {account.XP} XP.");
}
And the class UserAccounts searches if there exists in our database a socketUser with the ID property. Now say the same user in on different guild I need to store different data for him but the socketUser.ID will be the same no matter the guild. So when the user tries to use stats command he will see the same data irrespective of the guild he is in right now.
Here is where UserAccounts.GetAccount leads and does its thing,
public static UserAccount GetAccountFromID(ulong ID)
{
var result = from a in accounts
where a.ID == ID
select a;
var FoundAccount = result.FirstOrDefault();
if (FoundAccount == null)
{
FoundAccount = CreateUserAccount(ID);
}
return FoundAccount;
}
Clearly the linq query is checking for IDs and they happen to be the same for a user no matter the guild.
I tried using SocketGuildUser but sadly a socketGuildUser.ID is also independent of the guild. So I am unable to store different data for the same user from different guilds. Using the latest beta available.
How can I achieve this.
You could make use of a Dictionary implemented for each user. Where each user have its own Dictionary<GuildID, Data>.
And on the SQL side (if you are using SQL), you could have a new table, where it has a foreign key constrain on the User ID, and has a Guild ID too.
(The foreign key constrain on userID might not be needed if none of the user's stats is shared between all guilds; Aka you just have a SQL-table which you can do a SELECT stuff FROM tableName WHERE userID = ? AND guildID = ?)
I have created a trigger in Salesforce and i am fetching the result by soql query and store the result in a map, but it show the following error:
Error: Compile Error: Invalid initializer type List found for
Map: expected a Map with the same key and value types, or a
valid SObject List at line 7 column 25
trigger insertUpdateOwnerToSalesRep on Account (after insert, before update) {
if (trigger.IsAfter && trigger.IsUpdate) {
List<User> lstUser =[select id,name from User where Id in:(Trigger.NewMap).keySet()];
//Map<Id,String> ac=new Map<Id,String>([]);
Map<ID, String> m = new Map<ID, String>([select id,name from User where Id in:(Trigger.NewMap).keySet()]);
for(Account ac:Trigger.New) {
System.debug('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\t'+ac.ownerid);
if (ac.owner!=null) {
User user=ac.owner;
System.debug('!!!!!!!!!!!!!!\t'+user);
//ac.Sales_Rep__c=ac.owner.userName;
}
}
}
}
Please help, Thanks in advance.
First, You try to select users by Id, but when you call Trigger.NewMap.keySet(), you will get set of account Ids, not user (because trigger on account object). Possibly, you want to get all users related to account, so use AccountId in 'where' condition. Also I'd like to note, that you don't use 'lstUser' variable after getting.
As for getting Map from select, you should use Map<Id, User> instead of Map<Id, String>:
Map<Id, User> m = new Map<Id, User>([SELECT Id, Name FROM User where AccountId in :(Trigger.NewMap).keySet()]);
This is the challenge:
To complete this challenge, you need to add a trigger for Opportunity. The trigger will add a task to any opportunity inserted or updated with the stage of 'Closed Won'. The task's subject must be 'Follow Up Test Task'.
The Apex trigger must be called 'ClosedOpportunityTrigger'
With 'ClosedOpportunityTrigger' active, if an opportunity is inserted or updated with a stage of 'Closed Won', it will have a task created with the subject 'Follow Up Test Task'.
To associate the task with the opportunity, fill the 'WhatId' field with the opportunity ID.
This challenge specifically tests 200 records in one operation.
Here is my Code
trigger ClosedOpportunityTrigger on Opportunity (before insert, before update) {
List<Opportunity> opportunities = [SELECT Id, StageName
FROM Opportunity
WHERE Id
IN :Trigger.New];
List<Task> tasksToUpdate = new List<Task>();
System.debug('##### OPS' + opportunities);
for(Opportunity o : opportunities){
System.debug('##### ' + o.StageName);
if(o.StageName == 'Closed Won'){
Task thisTask = new Task(WhatId = o.Id, Subject = 'Follow Up Test Task');
tasksToUpdate.add(thisTask);
System.debug('##### ' + tasksToUpdate);
}
}
insert tasksToUpdate;
}
When I try to validate through trailhead, it gives a "Challenge Not yet complete... here's what's wrong:
Executing against the trigger does not work as expected." error.
I added some debug print and it seems to show that the soql statement just does not pull any results, so it does not enter the if statement. It seems a pretty straightforward soql statement to me, but I must be missing something. This happens no matter if I add or update an item.
Thanks in advance
In a Trigger context you do not need to use a SOQL query to retrieve the records that are being inserted or updated.
Also, with a before insert trigger the records won't be in the database yet, so they won't have any Id's defined. That's why the query isn't returning anything.
Instead you will want to use the Trigger Context Variables to work the the records.
In particular, you can use Trigger.new to get a collection of records being inserted or updated. Try looping over this collection instead of using a SOQL query in the trigger.
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
List<Task> taskListToInsert = new List<Task>();
for(Opportunity opp : [Select Id,StageName from Opportunity
where Id in :Trigger.New AND StageName = 'Closed Won'])
{
taskListtoInsert.add(new Task(Subject ='Follow Up Test Task',WhatId = opp.Id));
}
if(taskListtoInsert.size()>0)
{
insert taskListtoInsert;
}
}
The problem with your code is that you are running on before insert/update where the element has no ID yet. Therefore the following code:
Task thisTask = new Task(WhatId = o.Id, Subject = 'Follow Up Test Task');
Insert a task with an empty WhatId which doesn't pass the test. Just change to after insert/after update the trigger event.
All right, I was having trouble with this challenge because of the Task things, seems it's just a default object from salesforce!
Your problem is that you don't bulk enough your code as they shown in the trail.
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
List<Opportunity> closedOpp = [Select id from opportunity
where id IN :Trigger.New
AND StageName = 'Closed Won'];
List<Task> triggeredTasks = new List<Task>();
for (Opportunity o : closedOpp){
Task tache = new Task (Subject = 'Follow Up Test Task',
WhatId = o.ID);
triggeredTasks.add(tache);
}
insert triggeredTasks;
}
Here's code that worked:
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
List<Task> OpTasklist = new List<Task>();
// Iterate over opportunities that are in this trigger and have a stage of "Closed Won"
for (Opportunity op: [SELECT id FROM Opportunity
WHERE Id IN :Trigger.New AND
StageName =: 'Closed Won']) {
if ((Trigger.IsUpdate && Trigger.oldMap.get(op.Id).StageName != 'Closed Won')) OR
(Trigger.IsInsert) {
OpTaskList.add(new Task (Subject='Follow Up Test Task',
WhatId = op.Id)); }
}
If (OpTaskList.size() > 0) {
Insert OpTaskList ;
}
}
trigger ClosedOpportunityTrigger on Opportunity (after insert,after update) {
List oppty = [Select id from opportunity where id IN :Trigger.New AND StageName = 'Closed Won'];
List<Task> new_task = new List<Task>();
for (Opportunity opp : oppty){
Task thistask = new Task (Subject = 'Follow Up Test Task',WhatId = opp.ID);
new_task.add(thistask);
}
insert new_task;
}
We have two standard objects account(parent) and contact (child ). i want to write a trigger to populate the lastname field of contact with the name field of account
The trigger below performs the same task but soql query is from child to parent .
I want the trigger which performs the same work but using soql query ( relationship query ) from parent to child .
trigger trgSetLastName on Contact (after insert)
{
List<Contact> lstConUpdate = new List<Contact>();
List<Contact> lstContact = [select id,Account.Name from Contact where
id in: trigger.newmap.keyset()];
for(Contact con: lstContact)
{
con.LastName = con.Account.Name;
lstConUpdate.add(con);
}
if(lstConUpdate.size() > 0){
update lstConUpdate;
}
}
i want a trigger for this .help
Step 1.
Build a Set<id> of Account Ids:
for (Contact c : trigger.new){
acctIdSet.add(c.AccountId);
}
Step 2.
Select related Accounts into a Map<Id,Account> using:
[SELECT {fields}
FROM Account
WHERE Id IN :acctIdSet];
Step 3.
Loop through trigger.new and extract the corresponding Account from your Map.
Step 4.
Update the LastName value on contact with the value on your Account - assuming it exists.
Step 5.
Make your trigger fire before insert:
trigger trgSetLastName on Contact (before insert, before update)