How to map newest records from the list by each id? - class

I have a method in apex class that will get attachments (ContentDocument) from e-mail of case and will add it to another case. There are 2 questions below in order to finish my code:
How to create logic to get list of e-mails where I need only the newest e-mail for each case?
How can I create logic to get list of srID passed in this method?
Both questions are mentioned in the proper part of the code below:
public static void AttFromParenttoClonedCaseList(list<ID>srID){
list< ContentDocumentLink> attchlist2=new list< ContentDocumentLink>();
Map<Id, Case> mapCasess = new Map<Id, Case>();
Map<Id, EmailMessage> mapEmail = new map<Id, EmailMessage>();
Map<Id, EmailMessage> mapemailmessageId = new Map<Id, EmailMessage>();
List<String> externalIdCases = new List<String>();
List<String> casesID = new List<String>();
List<Case> ListCaseNumber = new List<Case>([SELECT ID, External_ID__c From Case WHERE ID IN :srID]);
for (Case mpC : ListCaseNumber){
mapCasess.put(mpC.id, mpC);
}
for (Case Listcase : ListCaseNumber) {
externalIdCases.add(Listcase.External_ID__c);
}
List<Case> ListCaseID = new List<Case>([SELECT ID From Case WHERE ID IN :externalIdCases]);
for (Case listIdcases : ListCaseID) {
casesId.add(listIdcases.id);
}
Map<id, EmailMessage> listEmailMessage = new Map<id, EmailMessage>([SELECT parentID, ID From EmailMessage WHERE parentID IN :casesId order by parentid, createddate desc]);
\\How to create logic to get list of e-mails where I need only the newest e-mail for each case (base on list listEmailMessage above)?
List<ContentDocumentLink> contentdocumentId = new List<ContentDocumentLink>([SELECT ID, ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId IN :/*list of emailmessages*/]);
for (ContentDocumentLink links : contentdocumentId){
ContentDocumentLink linkAtt = new ContentDocumentLink();
linkAtt.LinkedEntityId = \\how can I create logic to get list of srID passed in this method?
linkAtt.ContentDocumentId = links.ContentDocumentId;
linkAtt.ShareType = 'V';
linkAtt.Visibility = 'AllUsers';
attchlist2.add(linkAtt);
}
if (attchlist2.size() > 0)
insert attchlist2;
}

How to create logic to get list of e-mails where I need only the
newest e-mail for each case?
Something like this should be a good start
SELECT Id, CaseNumber, Subject,
(SELECT Id, FromAddress, ContentDocumentIds
FROM EmailMessages
WHERE Incoming = true
ORDER BY CreatedDate DESC
LIMIT 1)
FROM Case
LIMIT 10
It's simpler to treat it as "parent + related list, filtered, sorted" than "give me all emails for this parent, I'll build a Map or something with them, manually loop through them, compare dates to pick most recent...". I haven't worked with Emails for a while so you might need more filters but it's a good start.
how can I create logic to get list of srID passed in this method?
Not sure I understand. You want to re-link attachments from old case's emails to new case? See if that ContentDocumentIds is enough to build new links. If not - loop through results of my query, collect all EmailMessage Ids and query ContentDocumentLinks WHERE LinkedEntityId IN :emailMessageIds?
Check if this compiles?
// I don't really need it as a Map, list seems to be fine. But looks like you wanted Maps so I went with map.
// Map might be useful if External_ID__c is not a lookup.
// If you want a list (or set) of Ids from a query the very easy trick is to do
// Set<Id> myIds = new Map<Id, Account>([SELECT Id FROM Account LIMIT 5]).keyset();
// Anyway.
// "External_ID__c" is a lookup to Case or something else? Assuming it's just a lookup, bit like "ParentId".
Map<Id, Case> originals = new Map<Id, Case>([SELECT Id, CaseNumber, External_ID__c, External_ID__r.CaseNumber,
(SELECT Id, FromAddress, ContentDocumentIds
FROM EmailMessages
WHERE Incoming = true
ORDER BY CreatedDate DESC
LIMIT 1)
FROM Case
WHERE Id IN :srId AND External_ID__c != null]);
List<ContentDocumentLink> links = new List<ContentDocumentLink>();
for(Case original : originals.values()){
System.debug('source: ' + original);
System.debug('target: ' + original.External_ID__r.CaseNumber);
if(!original.EmailMessages.isEmpty()){
List<String> documentIds = original.EmailMessages[0].ContentDocumentIds;
for(String i : documentIds){
links.add(new ContentDocumentLink(
LinkedEntityId = original.External_ID__c,
ContentDocumentId = i,
ShareType = 'V',
Visibility = 'AllUsers'
));
}
}
}
insert links;

Related

Map to avoid Duplicate records

I have a Holiday Custom object,it contains Unique Dates based on
country based How to retrieve the value in Map
I have tried:
List<Holiday__c> holidays = new List<Holiday__c>([Select id, Date__c,Country__c from Holiday__c]);
Map<date, Holiday__c> mapOfHolidays = new Map<date, Holiday__c>();
for (Holiday__c holiday: holidays) mapOfHolidays.put(holiday.Date__c , holiday);
Suppose date for example 3/8/17 is for country france and Italy,If i put Key Value as Date__c,Map does not contain Key as duplicates,But for each country unique Dates are there
So what i have to use Key and Value in Map,I want to retrieve the date using Map,please anyone Help for me the answer
trigger ignoreweekends on order (before insert,before update) {
Set<id> accountIds = new Set<Id>();
for (order ord : Trigger.new) {
accountids.add(ord.AccountId);
}
map<id, account> mapOfAccounts = new map<id, account>([select id,JDE_Date_Delivery_Offset__c from account where id IN: accountIds]);
List<Holiday__c> holidays = new List<Holiday__c>([Select id, Date__c from Holiday__c]);
Map<date, Holiday__c> mapOfHolidays = new Map<date, Holiday__c>();
for (Holiday__c holiday: holidays) mapOfHolidays.put(holiday.Date__c , holiday);
for (order so : Trigger.new) {
Account acc = mapOfAccounts.get(so.AccountId);
for(integer i=0;i<=acc.JDE_Date_Delivery_Offset__c;i++) {
Datetime dt = DateTime.newInstance(Date.today() +acc.JDE_Date_Delivery_Offset__c.longvalue(), Time.newInstance(0, 0, 0, 0));
String dayOfWeek=dt.format('EEEE');
if(dayOfWeek == 'saturday' || dayOfWeek == 'sunday'|| mapOfHolidays.containskey(mapOfHolidays.Date__c))
acc.JDE_Date_Delivery_Offset__c = acc.JDE_Date_Delivery_Offset__c+ 1;
so.JDE_Synchronization_Date__c = Date.today().addDays(acc.JDE_Date_Delivery_Offset__c.intValue());
}
}
}
If I understood correctly, for one unique date you have multiple countries.
For this you can create a map of Date as key and List as value instead of creating a Map of Date and Holiday_c.
For example :
Map<Date, List<Holiday__c>> mapofHolidays = new HashMap<Date, List<Holiday__c>>();
After that you can retrieve all countries for a unique date and do the required processing.

Apex code to update new Opportunity with values from related object

What would be the proper method to update a list of new Opportunities with the values from a related record.
for (Opportunity opps:Trigger.new){
[SELECT Id, CorpOwner__r, Contact__r,(SELECT Id, AccountLocation from Account)]
o.CorpOwner__r =Account.Id; o.AccountLocation = opps.Account.AccountLocation;
insert opps
Do you call the lookup fields by the __r suffix? Could you do a before insert operation and still look up the Opportunity.CorpOwner__r relationship to values in the CorpOwner__r Account record, or does that relationship not exist since the record has not been created? What would be a proper batchified way to go about it?
Here's a possibility that demonstrates a number of concepts:
trigger UpdateOpptyWithAccountInfo on Opportunity (before insert) {
// Keep this SOQL query out of the FOR loop for better efficiency/batching
Map<Id, Account> relatedAccounts = new Map<Id, Account>(
[SELECT Id, AccountLocation__c
FROM Account
WHERE Id IN
(SELECT AccountId
FROM Opportunity
WHERE Id = :Trigger.new)
]
);
for (Opportunity o : Trigger.new) {
/* Find each opportunity's Account in the map we queried for earlier
* Note: there's probably a more efficient way to use a Map of Opportunity IDs to Account objects...
* This works fine and could be more readable.
*/
for (Account a : relatedAccounts.values()) {
if (a.Id == o.AccountId) {
// Once you've found the account related to this opportunity, update the values
o.CorpOwner__c = a.Id;
o.AccountLocation__c = a.AccountLocation__c;
}
}
}
// We're still inside an `insert` trigger, so no need to call `insert` again.
// The new fields will be inserted along with everything else.
}
If you're establishing the relationship between objects, use the __c suffix:
o.CorpOwner__c = a.Id; // Associate Account `a` as Opportunity `o`'s CorpOwner
If you're looking up a field on a related object, then you would use __r:
System.debug(o.CorpOwner__r.Name); // Print Opportunity `o`'s CorpOwner's name

Query regarding trigger?

I am having following requirement:
1) To get list of all the users for whome profile has been changed.
2) Then query on FRUP (It is a custom object) to retrieve all the records which are associated with the user whose profile is changed.(FRUP object will contain the list of all the records created by all the users on all the objects say Account, Opportunity)
3) Update FRUP.
For achieving this I wrote one trigger through which i am able to fetch list of all the users whose profile has changed which is as follows:
Trigger UserProfileTrigger on User (before update) {
List<User> usr = new List<User>();
Map<String,String> userMap = new Map<String,String>();
for(User u: Trigger.new){
//Create an old and new map so that we can compare values
User oldOpp = Trigger.oldMap.get(u.ID);
User newOpp = Trigger.newMap.get(u.ID);
//Retrieve the old and new profile
string oldProfileId = oldOpp.profileId;
string newProfileId = newOpp.profileId;
//If the fields are different, the profile has changed
if(oldProfileId != newProfileId){
System.debug('Old:'+oldProfileId);
System.debug('New :'+newProfileId);
usr.add(u);
System.debug('User :'+usr);
}
}
}
Also Following are the fields on custom object FRUP:
1)Owner
2)Name
3)Record ID
4)Folder ID
5)Created By
6)Last Modified By
any help/suggestions??
I'm not sure what field on the FRUP references the user Id it relates to, but you can loop through the FRUP object with something like this:
List<FRUP> frupToUpdate = new List<FRUP>();
for (FRUP f : [
Select
OwnerId,
Name, //etc.
UserId //the field that references the user Id
from FRUP
where userId = : usr]) {
//update field on FRUP, e.g. f.Name = 'New Name';
frupToUpdate.add(f);
}
This selects the FRUP records that relate to the users with changed profiles. It then updates a field on the record and adds the record to a list for updating. Note that this should be after your loop for(User u: Trigger.new). Then update the FRUP records that have changed:
update frupToUpdate;

Creating a Trigger that will create a new Opportunity Owner every time a there is a new Opportunity in Salesforce

I'm new to Salesforce and I'm trying to create a trigger that will basically update fields and create a new Opportunity owner every time a new Opportunity gets added.
For clarity, I've attached my code below:
trigger trig_Opportunity_CreateOppOwner on Opportunity (before insert, before update) {
//Opportunity OppOwner = null;
List<id>OppsID = new List<id>(); //Get the id of all new Opportunities owners
for (Opportunity Opp : Trigger.new) { //If a new Opportunity is added, then create new OppOwner, if not, then don't add.
OppsId.add(Opp.ID); //adds all new Opportunities Id's
}
List<Opportunity>OppToUpdate = [SELECT Id,
Name,
Owner__c,
OppOwner,
FROM Opportunity
WHERE Id IN: Opp.ID // Select Id, OpportunityName,
];
if Trigger.oldMap.get(opp.id).Owner__c != Trigger.oldMap.get(OppToUpdate.id).Owner__c // verify that if previous Opportunity has a matching owner.
OppsId.add(Opp.ID); //populates new oppowner with ID's of all owners.
This is basically what I'm trying to do:
Trigger(Before Update, Before Insert){
Get all Triggered Opportunities.
Verify if old opportunities already has a matching Owner.
If it's not a matching owner, update Opportunity fields and update the opportunity.
I'm not sure how to get from step 2 to step 3. Any help would be appreciated.
By the code that you provided isn't clear where it's finished, from my side seems that after couples of lines that you've provided another couples of lines exists. Could you please post all your code? If it isn't so, and code that you posted is all your code, from my point of view, this code do nothing, absolutely nothing.
Why?
no validation's errors
no DML operation
trigger trig_Opportunity_CreateOppOwner on Opportunity (before insert, before update) {
//Opportunity OppOwner = null;
/*
List<id>OppsID = new List<id>(); //Get the id of all new Opportunities owners
for (Opportunity Opp : Trigger.new) { //If a new Opportunity is added, then create new OppOwner, if not, then don't add.
OppsId.add(Opp.ID); //adds all new Opportunities Id's
}
*/
// 3 started lines might be replaced by the following one
List<id>OppsID = Trigger.newMap.getKeys();
//but the following code perform select on Opportunity object and return the same list as Trigger.new
// OppToUpdate == Trigger.new
// What for? May be you should work with this part on "after insert/update"
List<Opportunity>OppToUpdate = [SELECT Id,
Name,
Owner__c,
OppOwner,
FROM Opportunity
//WHERE Id IN: Opp.ID // Opp - isn't exist and it isn't list/set of id
WHERE Id IN OppsId // I guess you meant this
];
// 1.variable "opp" isn't exist here
// 2. "OppToUpdate.id" - you can't use list in this manner
if Trigger.oldMap.get(opp.id).Owner__c != Trigger.oldMap.get(OppToUpdate.id).Owner__c // verify that if previous Opportunity has a matching owner.
OppsId.add(Opp.ID); //populates new oppowner with ID's of all owners.

Using ObjectQuery Include and using a nested where clause

Using entity framework, I'm trying to get back a customer with order details but I want to filter out those Orders that are active.
Customer is our EntityObject which has a collection of Order EntityObjects. CustomerDetails is our ObjectContext.
The code below will attach all orders but I want to filter and only attach those that are active. (Order.active == true). How can I do this?
I know Include builds up a nested query statement (I can observe by using .ToTraceString().) I was hoping to attach a Where clause to this nested select statement or the Include.
Customer cust;
CustomerDetails custTable = new CustomerDetails();
cust = custTable.Customer
.Where("it.cust_id = " + id)
.Include("Order") // But we only want Order.active == true!!!
.ToList().First();
Untested, but might work?
var temp = custTable.Customer.Where("it.cust_id = " + id).Include("Order");
cust = (from t in temp
where t.Order.active == true
select t).ToList().First();