Implementation restriction: FeedItem requires a filter by Id - triggers

When T tested with non-admin user this error occurred. Any possible solution for this ?
I have class which called by trigger. According to my functionality i have to calculate latest Activity's days since activity happened to current date. With the admin user all functionality runs successfully, but when tested with non-admin user error occurred on FeedItem's list.
enter image description here
`
List<FeedItem> feeditemList =[SELECT ID, CreatedDate, CreatedById, CreatedBy.Name, ParentId, Parent.Name, Body FROM FeedItem where parentId =:oppId_Set ORDER BY CreatedDate DESC limit 1];
system.debug('$$$ feeditemList: '+ feeditemList);
//FeedItem
for(FeedItem fi : feeditemList) {
if(!feeditemList.isEmpty())
{
if(fi.CreatedDate<>Null)
{
latestFeeditemDate =fi.CreatedDate;
system.debug('latestFeeditemDate in feeditem loop'+latestFeeditemDate);
}
}
}
`
Any Possible Solution for this.

Related

How to merge two leads using an apex Trigger

I'm new to salesforce and I'm trying to learn more. Currently I'm stuck at a point where I don't know what to do further. Kindly point me in the right direction. Any help is appreciated.
So what im trying to do is to compare lastnames to find duplicates when the record is being created and if a duplicate is found then instead of creating it as a new record it should be merged with existing record.
So to achieve the task I have wrote the following trigger handler:
public class LeadTriggerHandler {
public static void duplicateMerge(){
List<Lead> leadList = [SELECT Id,Name, Email, Phone, FirstName, LastName FROM Lead];
List<Lead> leadTrigger = Trigger.new;
for(Lead leadVarTrigger : leadTrigger){
for(Lead leadVar : leadList){
//System.debug(leadVar.LastName + '==' + leadVarTrigger.LastName);
if(leadVarTrigger.LastName == leadVar.LastName)
{
//System.debug(leadVar.LastName + '==' + leadVarTrigger.LastName);
//leadVarTrigger.addError('This is a duplicate record');
Database.merge(leadVar, leadVarTrigger);
System.debug('Trigger Successful');
}
}
}
}
}
the following is my trigger:
trigger LeadTrigger on Lead (after insert) {
if(Trigger.isafter && Trigger.isInsert)
{
LeadTriggerHandler.duplicateMerge();
}
}
And when I try with after insert i get the following error:
LeadTrigger: execution of AfterInsert caused by: System.DmlException: Merge failed. First exception on row 0 with id 00Q5j00000ENUGVEA5; first error: INVALID_FIELD_FOR_INSERT_UPDATE, Unable to create/update fields: Name. Please check the security settings of this field and verify that it is read/write for your profile or permission set.: [Name] Class.LeadTriggerHandler.duplicateMerge: line 18, column 1 Trigger.LeadTrigger: line 5, column 1
And if i try with before trigger i get the following error for the same code:
LeadTrigger: execution of BeforeInsert caused by: System.StringException: Invalid id at index 0: null External entry point Trigger.LeadTrigger: line 5, column 1
Actually, according to your code, you are allowing the record to be created and saved to the database by using after insert. Your before insert failed because your handler class is referencing an Id, however, if you use before logic, the record isn't saved to the database yet, meaning it doesn't have an Id. With that being said, let's try the following. :)
The Trigger (Best practice is to have one trigger with all events):
trigger TestTrigger on Lead (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
if(Trigger.isafter && Trigger.isInsert)
{
//Can't conduct DML operations with trigger.new or trigger.old
//So we will create a set and send this to our handler class
Set<Id> leadIds = Trigger.newMap.keySet();
LeadTriggerHandler.duplicateMerge(leadIds);
}
}
The Handler Class:
public class LeadTriggerHandler {
public static void duplicateMerge(Set<Id> idsFromTrigger){
//Querying the database for the records created during the trigger
List<Lead> leadTrigger = [SELECT Id, LastName FROM Lead WHERE Id IN: idsFromTrigger];
List<String> lastNames = new List<String>();
//This set is important as it prevents duplicates in our dml call later on
Set<Lead> deDupedLeads = new Set<Lead>();
List<Lead> leadsToDelete = new List<Lead>();
for (Lead l : leadTrigger){
//getting all of the Last Names of the records from the trigger
lastNames.add(l.lastName);
}
//We are querying the database for records that have the same last name as
//the records that were created during our trigger
List<Lead> leadList = [SELECT Id, Name, Email, Phone, FirstName, LastName FROM Lead WHERE LastName IN: lastNames];
for(Lead leadInTrigger : leadTrigger){
for(Lead leadInList : leadList){
if(leadInTrigger.LastName == leadInList.LastName){
//if the lead from the trigger has the same last name as a lead that
//already exists, add it to our set
deDupedLeads.add(leadInTrigger);
}
}
}
//add all duplicate leads from our set to our list and delete them
leadsToDelete.addAll(deDupedLeads);
delete leadsToDelete;
}
}
This handler has been bulkified in two ways, we removed the DML operation out of the loop and the code is able to process a scenario where someone mass inserts 1000s of leads at a time. Plus, rather than querying every lead record in your database, we only query for records that have the same last name as the records created during the insert operation. We advise using something more unique than LastName like Email or Phone as many people/leads can have the same Last Name. Hope this helps and have a blessed one.

How can I select in prisma the elements with a condition on a 1-N relation?

I have the following prisma schema
model User {
id Int #id #default(autoincrement())
userName string #unique
complaints Complaint[]
}
model Complaint {
id Int #id #default(autoincrement())
user User #relation(fields: [userId], references: [id])
creationTime DateTime #default(now())
userId Int
priority ComplaintPriority
}
enum ComplaintPriority {
HIGH
MEDIUM
LOW
}
I need to select the users that have last complaint (as last I mean the complaint with latest creationTime) with priority value HIGH.
In other words:
if an user has 3 complaints and the last of these complaints has high priority the user should be part of the result (ignoring previous complaints)
If an user has 8 complaints (maybe some of those with high priority) and the last one has low priority the user should not be part of the results
If the user has no complaints at all the user should not be part of the results
I didn't find the prisma syntax for this operation. Does anybody has any idea how to do it?
I looked into this a bit, unfortunately, I don't think there's a way to create a query exactly as you have in mind (as of version 3.5.0 of Prisma).
Here's a workaround that you could perhaps consider:
Fetch all user records that have at least one complaint with HIGH priority. Include complaint records and order them by creationTime.
Manually filter through the list in Node.js to keep appropriate user records.
let users = await prisma.user.findMany({
where: {
complaints: {
some: {
priority: "HIGH"
}
}
},
include: {
complaints: {
orderBy: {
creationTime: "desc"
}
}
}
})
users = users.filter(user => user.complaints[0].priority == "HIGH")
It should be noted though, this isn't perfectly optimal if there are really high number of user records. In such a case, I would consider creating a raw SQL query using rawQuery.

Trigger to prevent User From Adding more than one product to an opportunity

So i have written a trigger to prevent user from entering more than one opportunity product to the same opportunity, but the problem is when he adds more than one opportunity product at the same time, my trigger does not fire, salesforce takes it as one product.
What can i add to my trigger to fix this ?
My trigger :
trigger OpportunityLineItemBeforeInsert on OpportunityLineItem (before insert) {
Set<Id>opportunityIds = new Set<Id>();
// get all parent IDs
for(OpportunityLineItem i : trigger.new)
{
opportunityIds.add(i.OpportunityId);
}
// query for related Olis (Opportunity Line Items)
Map<Id, Opportunity> opps = new Map<Id, Opportunity>([SELECT ID,
(SELECT ID
FROM OpportunityLineItems)
FROM Opportunity
WHERE ID IN :opportunityIds]);
for(OpportunityLineItem i : trigger.new)
{
if(opps.get(i.OpportunityId).OpportunityLineItems.size()>0)
{
i.addError('Your Message');
}
}
}
Thank you in advance.
I would probably ignore anything related to the Oppty.
You want only one product created, so on creation, either the number of LI is 0 and you can create exactly one, or it' snot 0 and you can't create any.
I would just create a rollup field on the Oppty, count the products. If the count != 0, then fail the validation. If count = 0, then count the Olis in trigger.new and if !=1, fail.
Instead of writing code to do this you should instead create a field on products that stores the id of the parent opportunity, make that field unique, and populate the value via workflow or process builder with the id of the parent opportunity. That way if a second product gets added the unique constraint would fire and prevent the record from being inserted.
Another option would be to create a rollup on opportunity to count the number of opportunity products, then add a validation rule that show an error if the number of products > 1. The advantage of doing it this way is that you get to set the error message as opposed to the generic duplicate error message with the first option.

Querying Laravel Relationship

I am trying to get one query work since morning and not able to get it working I have two tables photographers and reviews please have a look at structure and then I will ask the question at the bottom :
Reviews table :
id int(10) unsigned -> primary key
review text
user_id int(10) unsigned foreign key to users table
user_name varchar(64)
photographer_id int(10) unsigned foreign key to photographers table
Photographers table :
id int(10) unsigned -> primary key
name text
brand text
description text
photo text
logo text
featured varchar(255)
Photographers model :
class Photographer extends Model
{
public function reviews()
{
return $this->hasMany('\App\Review');
}
}
Reviews Model :
class Review extends Model
{
public function photographers()
{
return $this->belongsTo('\App\Photographer');
}
}
My logic to query the records
$response = Photographer::with(['reviews' => function($q)
{
$q->selectRaw('max(id) as id, review, user_id, user_name, photographer_id');
}])
->where('featured', '=', 'Yes')
->get();
The question is : I want to fetch all the photographers who have at least one review in the review table, also I want to fetch only one review which is the most latest, I may have more than one review for a photographer but I want only one.
I would add another relationship method to your Photogrpaher class:
public function latestReview()
{
return $this->hasOne('App\Review')->latest();
}
Then you can call:
Photographer::has('latestReview')->with('latestReview')->get();
Notes:
The latest() method on the query builder is a shortcut for orderBy('created_at', 'desc'). You can override the column it uses by passing an argument - ->latest('updated_at')
The with method loads in the latest review.
The has method only queries photographers that have at least one item of the specified relationship
Have a look at Has Queries in Eloquent. If you want to customise the has query further, the whereHas method would be very useful
If you're interested
You can add query methods to the result of a relationship method. The relationship objects have a query builder object that they pass any methods that do not exist on themselves to, so you can use the relationships as a query builder for that relationship.
The advantage of adding query scopes / parameters within a relationship method on an Eloquent ORM model is that they are :
cacheable (see dynamic properties)
eager/lazy-loadable
has-queryable
What you need is best accomplished by a scoped query on your reviews relation.
Add this to your Review model:
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Eloquent\Model;
class Review extends Model {
public function scopeLatest(Builder $query) {
// note: you can use the timestamp date for the last edited review,
// or use "id" instead. Both should work, but have different uses.
return $query->orderBy("updated_at", "desc")->first();
}
}
Then just query as such:
$photographers = Photographer::has("reviews");
foreach ($photographers as $photographer) {
var_dump($photographer->reviews()->latest());
}

Account Trigger update all contacts - Too many SOQL queries: 101

I have a trigger that runs after updating any account and it actually just updates a field (Relationship_category_r__c) in all the related contacts after few conditions.
Condition1: If we update the account type to "Member"
Condition2: If the contact doesn't have "Member" already in the (Relationship_category_r__c) field
ACTION: Update the contact Relationship_Category_r__c field to "Member - staff"
Condition2: If we update the account type to "Member - past"
ACTION: Update all the contacts Relationship_Category_r__c field to "Member - past"
The trigger works absolutely find when the account has less than 25 to 50 contacts but it generates an error when we have an account more than 55 or so contacts
ERROR: Apex trigger UpdateAllContacts caused an unexpected exception, contact your administrator: UpdateAllContacts: System.LimitException: Too many SOQL queries: 101
======================================= TRIGGER ==============================
trigger UpdateAllContacts on Account (after update) {
for ( Account acc : Trigger.New ) {
List<Contact> listCon = [Select id, Relationship_Category_r__c from Contact where AccountId =: acc.id];
for ( Contact con : listCon ) {
if ( acc.Type=='Member' ) {
if ( con.Relationship_Category_r__c != 'Member' ) {
con.Relationship_Category_r__c = 'Member - staff';
}
} else if ( acc.Type=='Member - past ' ) {
con.Relationship_Category_r__c = 'Member - past';
}
}
try {
update listCon;
}
catch (DmlException e) {}
}
}
Any help will be greatly appreciated
Thanks
Couple of things that jump out at me here:
First and foremost is the main cause of your error: a SOQL query within a loop. You need to bulkify your trigger to perform a single query, rather than querying once for each Account record in your update batch.
You have a DML operation (update listCon;) within that same loop, which will exacerbate the problem if you happen to have any SOQL queries in your Contact triggers. This update should also be bulkified, so that you are making as few inserts/updates as possible (in this case you can limit it to a single update call).
You are updating all Contact records queried regardless of whether or not they've been updated by your code. This can lead to unnecessarily long processing times, and can easily be prevented by keeping track of which records should be updated in a second list.
This may be by design, but you're suppressing any errors in your update call without even attempting to deal with them. There are many different ways to go about this depending on your implementation so I won't delve into that, but in most circumstances you would probably want to at least be aware that your update to those records was failing so you can correct the issue.
After making a few corrections to your code we are left with the following which uses a single SOQL query, single DML statement, and won't update any Contact records that haven't been modified by the trigger:
trigger UpdateAllContacts on Account (after update) {
List<Contact> updateCons = new List<Contact>();
for ( Contact con : [select Id, AccountId, Relationship_Category_r__c from Contact where AccountId in :Trigger.NewMap.keySet()] ) {
Account parentAcc = Trigger.NewMap.get(con.AccountId);
if ( parentAcc.Type == 'Member' ) {
if ( con.Relationship_Category_r__c != 'Member' ) {
con.Relationship_Category_r__c = 'Member - staff';
updateCons.add(con);
}
} else if ( parentAcc.Type == 'Member - past ' ) {
con.Relationship_Category_r__c = 'Member - past';
updateCons.add(con);
}
}
update updateCons;
}