Unable to filter using ContentDocument id in query in trigger query not retrieving any results - salesforce

I have a requirement to make to make a file private and be available to only the user whose role name consists the name of the file for a specific custom object. For this I am trying to retrieve from Content Document Link with the custom object name LinkedEntity.Type and ContentDocumentid as filters, when I hard code the ContentDocumentid it is working fine but when I try to dynamically provide the ContentDocumentId then the query is not returning any result. I am adding a snippet of my code. Please Help!!. Thanks
List<Id> listOfConDocuId = new List<Id>();
for(ContentVersion cv: Trigger.new){
if((!cv.Title.contains('product proposal')) || (!cv.Title.contains('final')) || (!cv.Title.contains('packet')))
listOfConDocuId.add(cv.ContentDocumentId);
}
Map<Id, Project__c> mapOfProjectId = new Map<Id, Project__c>([SELECT Id FROM Project__c]);
Set<Id> setOfProjectId = mapOfProjectId.keySet();
List<ContentDocumentLink> LinkedProject = [SELECT ContentDocumentId, LinkedEntityId, ContentDocument.Title FROM ContentDocumentLink where LinkedEntityId in :setOfProjectId and LinkedEntity.Type='Project__c' and ContentDocumentId IN :listOfConDocuId];`

I don't think it's necessary to add a WHERE clause for both ID and TYPE. Id should be enough. As far as restricting files to only users with certain roles, have you tried sharing the Custom Object (Project__c) with only those users and then simply linking the files to that Custom Object record with Inferred Permission?
Read more about the sharing types and visibility of Content Document Link here:
https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_contentdocumentlink.htm

Related

Why does "Microsoft.Graph.User.AdditionalData" property contain manager information?

Within the Microsoft.Graph.User object there is a field called "AdditionalData".
It seems this can hold many values, from telling if a record is a delta record to storing manager information.
In this instance, it holds information on a users manager.
It looks like it can hold multiple records however, so I am asking what is the best way to get data from this property, to ensure I get all values it might have.
I am also unsure why manager information is in the AdditionalData property and not in the Manager property.
Yes you are correct AdditionalData may hold multiple record,You can add additionalData to your user that can hold any information based on your customization.
you can add the multiple value to additionalData using Openxtension
Trick is to add the extensions like this
extension = new OpenTypeExtension
{
ExtensionName = AzureADExtensions.UserConstants.ExtensionName,
AdditionalData = new Dictionary<string, object>
{
{"OtherEmail", externalUser.Email},
{"OtherRole" , externalUser.Roles.FirstOrDefault()}
}
};
await _graphClient.Users[user.Id].Extensions.Request()
.AddAsync(extension);
And then retrieve them like this.
user = await _graphClient
.Users[userId]
.Request()
.GetAsync();
// Note : you should be able to expand this on original request, but fails for me.
var extensions = await _graphClient.Users[user.Id].Extensions.Request().GetAsync();
user.Extensions = extensions;
Reference : Azure AD GraphServiceClient can't set AdditionalData against User
The "Additional Data" property only holds manager info if we do a delta query, if we do a regular query, we have to use extended properties to get the manager.
We are avoiding delta query for the moment in the interests of time but might come back to it at another point.
Thanks all.

Dynamic change of field value using sObject

I'm trying to use sObject to dynamically change Name field objects across while organization.
I've tried using SomeId.getSObjectType().newSObject(SomeId) to create the sObject, but when I try to change the Name field I have error
Variable does not exist: Name
Map<Id, string> idsToUpdate = new Map<Id, string>();
// Put the Id's and associated name values in the map
List<SObject> sObjectsToUpdate = new List<SObject>();
foreach(Id idToUpdate : idsToUpdate.keySet) {
SObject o1 = idToUpdate.getSObjectType().newSObject(idToUpdate);
o1.Name = idsToUpdate.get(idToUpdate);
sObjectsToUpdate.add(o1);
}
update sObjectsToUpdate;
As I can see other posts, this is the way of creation dynamic update of objects.
Any idea why this happens?
Not all objects have a name field, you should check for the existence of the name field before trying to set the field also you must use the put method
Map <String, Schema.SObjectField> fieldMap = o1.getSobjectType().getDescribe().fields.getMap();
if(fieldMap.containsKey('Name')){
o1.put('Name', 'Test');
}

getting Value of a field by its Name in apex salesforce

in my visualforce page i have some campaign object first user select an object then there is a multi picklist. in this picklist there is Label for all the fields user selects some fields then i have to show the value of these fields in the selected campaign object
for showing multiple picklist my apex function is
public List<SelectOption> getOptionalFields(){
Map <String, Schema.SObjectField> fieldMap= Campaign.sObjectType.getDescribe().fields.getMap();
List<SelectOption> fieldsName =new List<SelectOption>();
for(Schema.SObjectField sfield : fieldMap.Values())
{
schema.describefieldresult dfield = sfield.getDescribe();
fieldsName.add(new SelectOption(dfield.getName(),dfield.getLabel()));
}
but i have no idea how to show value for the the field
for exmple i have object instance like
Campaign c;
now i have to get value of any field whose Name is in string form.how to get corresponding value for that field.one solution is just write like
say
String fieldName;
and use multiple if
if(fieldName=='Name')
c.Name=
if(fieldName=='Id')
c.Id=
is there any other convenient method??please explain!!
You need to read about "dynamic apex". Every "concrete" sObject (like Account, Contact, custom objects) can be cast down to generic sObject (or you can use the methods directly).
Object o = c.get(fieldName);
String returnValue = String.valueOf(o);
There are some useful examples on dynamic get and set methods on Salesforce-dedicated site: https://salesforce.stackexchange.com/questions/8325/retrieving-value-using-dynamic-soql https://salesforce.stackexchange.com/questions/4193/update-a-records-using-generic-fields (second question is a bit more advanced)
You'll still need to somehow decide when to return it as String, when as number, when as date... Just experiment with it and either do some simple mapping or use describe methods to learn the actual field type...

Apex Trigger Context Variable

Here my code for apex trigger.
trigger LeadTrigger on Lead (after insert)
{
if(Trigger.isInsert){
for(Lead newLead: Trigger.new)
{
//newLead.RecrodTypeId //'Give value of record type id.
//newLead.RecordType.Name //'Null'
}
}
}
Why "newLead.RecordType.Name" returns null?
The lists of objects available in triggers only have values for the fields on the object the trigger is running on. No relationships are traversed, only the IDs of the lookup records are included.
Therefore, to pull in any extra information you need to from related objects needs to be queried for.
You'll want to do something like this:
trigger LeadTrigger on Lead (after insert) {
map<id, RecordType> mapRecordTypes = new map<id, RecordType>();
if(Trigger.isInsert) {
for(Lead newLead: Trigger.new) {
mapRecordTypes.put(newLead.RecordTypeId, null);
}
}
for(RecordType rt : [select Id, Name from RecordType
where Id in : mapRecordTypes.ketSet()]) {
mapRecordTypes.put(rt.Id, rt);
}
for(Lead newLead : Trigger.new) {
string recordTypeName = mapRecordTypes.get(sLead.RecordTypeId).Name;
}
}
This is probably because some of your leads that just got inserted don't have record types associated with them. This is normal. You can enforce that record type selection is mandatory through configuration, if that's what you're looking for.
[EDIT]
Now I think I understand the issue (from your comment). The reason is that since you're in a trigger, the associated RecordType referenced object is not available. The RecordTypeId will always be available since it is literally part of the trigger object as an Id. However, child objects (referenced objects) will not be available to simply reference from within a trigger. To do this you need to create a map of the referenced object in question by doing an additional SOQL call WHERE Id IN: theIdList.
From Apex, not in a trigger, you need to specifically call this field out from your SOQL like this:
List<Lead> leads = [SELECT Id, RecordType.Name FROM Lead];
What just happened there is that the child object, the RecordType in this case, was included in the query and therefore available to you. By default a trigger will not have all of your child objects pre-selected and therefore need to be selected afterwards from within the trigger or class called by the trigger:
List<Id> recIds = new List<Id>();
for(Lead l : leads)
{
recIds.add(l.RecordTypeId);
}
List<RecordType> rt = [SELECT Id, Name FROM RecordType WHERE Id IN :recIds];
Map <Id, String> idRecNameMap = new Map<Id, String>();
for(RecordType r : rt)
{
idRecNameMap.put(r.Id, r.Name);
}
// And finally...
for(Lead l : Trigger.new)
{
String tmpRecordTypeName = idRecNameMap.get(l.RecordTypeId);
}
I did not test this code but I think it look ok. Hope this makes sense.
you can't get extra information on the related objects from this trigger. if you want to get more information you need to make query for other objects.
List<RecordType> records = [SELECT Id, Name FROM RecordType WHERE Id = newLead.RecrodTypeId];
string myname = records[0].name;
but remember that you shouldn't make a query in for loop. so if you wanted to do it in the right way go for Adam's solution.
Put some system debug inside the loop and check your system debug logs for more information
system.debug('lead:' + newLead);
inside the for loop and see what is being passed in. You may find that it is null.
We cant really give you a good answer without knowint the rest of your set up.

How can I get the name of the Lead Owner in a Lead custom formula field?

I've got an application that reads Lead records from Salesforce via the API and I want to link the Lead Owner field to an attribute in the application. The Lead Owner field doesn't up in the list of available fields but all the custom fields do.
So, my first attempt at a solution was to create a custom field that displayed the Lead Owner name. In the SF formula editor, as far as I can tell, it doesn't display the actual data field but instead displays the ID string. Which is pretty meaningless in the context that I need it for.
alt text http://skinny.fire-storm.net/forposting/insertfield.JPG
Is there a way that we can get at the data in the object that the ID string references?
alt text http://skinny.fire-storm.net/forposting/havewant.JPG
I have the RED BOX but need the GREEN BOX.
EDIT: I can't change the application code that calls the API. I can only change salesforce. So, this is more of a salesforce superuser / formula-writer question, not a question about writing code that calls the SF API.
Salesforce allows access to related data through what they call relationship queries. Instead of joining, you specify the query like this:
System.debug([SELECT Owner.Name FROM Lead WHERE Id = '00QS00000037lvv'].Owner.Name);
Try running that in the system log, just replace the lead ID with one that you're looking at.
When accessing the data through the API, the principle is the same, your proxy objects should allow you to access Lead.Owner.Name.
EDIT:
I agree with eyescream, since you can't change the application code, creating an Apex trigger would be the best way to go here. Here's some code to get you started:
trigger Lead_UpdateOwner on Lead(before insert, before update)
{
Map<Id, String> ownerMap = new Map<Id, String>();
for (Lead lead : Trigger.new)
{
ownerMap.put(lead.OwnerId, null);
}
if (ownerMap.size() > 0)
{
for (User[] users : [SELECT Id, Name FROM User WHERE Id IN :ownerMap.keySet()])
{
for (Integer i=0; i<users.size(); i++)
{
ownerMap.put(users[i].Id, users[i].Name);
}
}
for (Lead lead : Trigger.new)
{
lead.OwnerName__c = ownerMap.get(lead.OwnerId);
}
}
}
lead.OwnerName__c would need to be the name of your custom field on the lead object that will hold the owner name. Type Text, length 121.
I had a similar problem, but wanted all the current and future User fields available. Since a custom lookup field to the User is not restricted by formula fields, I created one named
OwnerLookup
on the Opportunity and Account objects, then used a triggers to populate it on creation or edit. For example the Opportunity trigger is this:
trigger OpportunityTrigger on Opportunity (before insert, after insert, before update, after update) {
if(trigger.isBefore && trigger.isInsert) {
OpportunityTriggerHandler.newOpportunity(Trigger.old, Trigger.new);
}
else if(trigger.isAfter && trigger.isInsert){
//OpportunityTriggerHandler.futureUse(Trigger.new);
}
else if(trigger.isBefore && trigger.isUpdate){
OpportunityTriggerHandler.updateOpportunity(Trigger.new, Trigger.oldMap);
}
else if(trigger.isAfter && trigger.isUpdate){
//OpportunityTriggerHandler.futureUse(Trigger.new, Trigger.oldMap);
}
}
and the OpportunityTriggerHandler class (Apex code) is:
public with sharing class OpportunityTriggerHandler {
public static void newOpportunity( List<Opportunity> oldOpportunitys, List<Opportunity> newOpportunitys ) {
for (Opportunity opp: newOpportunitys) {
updateOwnerData( opp );
}
}
public static void updateOpportunity( List<Opportunity> oldOpportunitys, Map<Id, Opportunity> newOpportunitys ) {
for (Opportunity opp: oldOpportunitys) {
updateOwnerData( opp );
}
}
public static void updateOwnerData( Opportunity opp ) {
opp.OwnerLookup__c = opp.OwnerId;
}
}
I then create Formula fields on the Opportunity/Account objects to get to any of the owner (User) object fields, such as Oppty Owner Name formula field:
OwnerLookup__r.FirstName & " " & OwnerLookup__r.LastName
VLOOKUP function would be a good try, but
it's available only in validation rules, not in field definitions
it can be used only on custom objects and you need data from User
I'd say you need to query from your application for
SELECT Owner.FirstName, Owner.LastName FROM Lead
Other than that... some "after insert, after update" trigger that would populate your custom field when owner changes?
Just posting for completeness sake (and for the Google searches): The issue arises with any object that can be queued, not just Lead, since the source of it is that the owner can refer to either a user (as usual) or a queue object.
This can be resolved using a formula field instead of triggers, like below:
BLANKVALUE(Owner:Queue.QueueName, Owner:User.FirstName & " " & Owner:User.LastName)
Basically, the BLANKVALUE function in the formula checks whether the owner.queuename is blank, and if so gives the name of the user.

Resources