Salesforce- retrieve Contact.opportunites - salesforce

Here is snippet I am using in my anonymous window . Purpose is to retrieve Opportunities of a contact. Even after adding opportunity contact role , contact.Opportunities.size is resulting in zero (last debug line). Am I missing something ? you may use the below code directly.
Update: able to get size now but same logic doesn't work for code coverage in test class . details listed below:
Only 'if' part of controller is covered and 'else' part is never covered even though size of contact.opportunities is more than 0.
Controller method :
public PageReference sendingEmail() {
//contact1 has query records
sizeVar = contact1.Opportunities.size();
if(contact1.npo02__OppAmountLastYear__c>0 ) {
if(sizeVar==0) {
// if size is 0 then navigate to a particular vf page
PageReference pr = Page.NoDonationOrNoEmail;
pr.getParameters().put('id',(String)contact1.id);
pr.setRedirect(true);
return pr;
}
else
{ //when contact.opportunities size is more than 0 then navigate to
other vf page.
PageReference pr1 = Page.NoPrint;
pr1.getParameters().put('id',(String)contact1.id);
pr1.setRedirect(true);
return pr1;
}
} return null;
}
Test Class:
//creating account
Account a = new Account();
a.Name = 'Test Co.';
a.BillingStreet = '298 S. Ringo Street';
a.BillingCity = 'Little Rock';
insert a;
//Creating contact
Contact contact1 = new Contact();
contact1.FirstName = 'Paul';
contact1.LastName = 'Test';
contact1.AccountId = a.id;
contact1.npo02__OppAmountLastYear__c=100;
insert contact1;
//creating opportunity
Opportunity o = new Opportunity();
o.RecordType = [SELECT Id, Name, DeveloperName FROM RecordType
WHERE Name = 'Membership' LIMIT 1];
o.Name = 'New Record';
o.StageName = 'Posted';
o.AccountId = contact1.AccountId;
o.CloseDate = Date.today();
o.Description = 'Test Record';
insert o;
//creating opportunity contact role
OpportunityContactRole ocr = new OpportunityContactRole();
ocr.ContactId = contact1.Id;
ocr.OpportunityId = o.Id;
ocr.IsPrimary = TRUE;
ocr.Role = 'Decision Maker';
insert ocr;
System.debug('created opportunity contact role for primary');
Update o;
contact1 = [SELECT Id, Name,(SELECT id FROM opportunities) FROM
Contact WHERE Id=:contact1.Id];
PageReference pr = Page.NoPrint;
pr.getParameters().put('id', String.valueOf(contact1.id));
Test.setCurrentPage(pr);
ApexPages.StandardController cont5 = new
ApexPages.StandardController(contact1);
BulkEmailController testAccPlan = new
BulkEmailController(cont5);
testAccPlan.sendingEmail();

When you create and insert a record, you don't get formula fields nor you can navigate lookup. The same goes with child relationship.
You have to query the fields you need.
Change Update contact1; to contact1 = [SELECT Id, (SELECT Id FROM Opportunities) FROM Contact WHERE Id = :contact1.Id]; and the last debug line will print 1.

Related

Can someone help in Bulkifying the below Apex code. The purpose here is to Remove Product Sharing When user is removed from AccountTeamMember

The purpose here is to Remove Product Sharing When user is removed from AccountTeamMember.
List<AccountTeamMember> acctmListProd = [Select id,UserId, AccountId, TeamMemberRole FROM
AccountTeamMember WHERE Id In:acctmList and
TeamMemberRole IN:Roles]
Map<Id,Id> accToUserIdList = new Map<Id,Id>();
for(AccountTeamMember At: acctmListProd)
{
accToUserIdList.put(At.AccountId, At.UserId);
}
List<Product__Share> DelProdShareRecords = new List<Product__Share>();
Set<Id> productIds = new Set<Id>();
for(Id accId: accToUserIdList.keySet())
{
List<Product__c> prodList = [Select id,Account__c from Product__c where
Account__c=accId];
for(Product__c prod: prodList)
{
productIds.add(prod.Id);
}
List<Product__Share> prodShareRecords = [Select id,ParentId,UserOrGroupId from
Product__Share where ParentId IN:productIds AND
UserOrGroupId=accToUserList.get(accId)
];
DelProdShareRecords.addAll(prodShareRecords);
}
if(!DelProdShareRecords.isEmpty())
{
Database.deleteResult[] result = Database.delete(DelProdShareRecords, false);
}
https://ideas.salesforce.com/s/idea/a0B8W00000GdgUVUAZ/allow-global-security-and-sharing-rules-settings-on-products
Product__Share isn't a thing. This code looks like it was never compiled or tested in an org.

Restrict more then 2 contacts that saved on Account object

I want to build a trigger on contact, that accept check box. And In Account object it take 2 contacts that are active. when user assign 3rd active contact to the same account he/she will get error messege. how can it possible? i completed all codes but these limit of 2 contacts are pending. can anyone try to guide me how to do this?
trigger ContactTrigger on Contact(after insert, after update, after delete, after undelete) {
switch on Trigger.operationType {
when AFTER_INSERT {
Set<Id> accountIds = new Set<Id>();
for (Contact con : Trigger.new) {
if (String.isNotBlank(con.AccountId)) {
//write automation logic here
accountIds.add(con.AccountId);
}
}
// get aggregate result for all accounts
List<AggregateResult> results = [
SELECT AccountId, COUNT(Id) totalContacts
FROM Contact
WHERE Active__c = TRUE AND AccountId IN :accountIds
GROUP BY AccountId
];
integer var = results.size();
// build final list of accounts to update
List<Account> accountsToUpdate = new List<Account>();
for (AggregateResult result : results) {
// get account id and number of active contacts
String accId = String.valueOf(result.get('AccountId'));
Integer totalContacts = Integer.valueOf(result.get('totalContacts'));
// make sure you use Id feild in your account to update it
Account acc = new Account(Id = accId, Active_Contacts__c = totalContacts);
accountsToUpdate.add(acc);
}
// update the final list of account
update accountsToUpdate;
}
when AFTER_UPDATE {
Set<Id> accountIds = new Set<Id>();
for (Contact con : Trigger.new) {
// capture the account id only if active checkbox value is flipped
if (String.isNotBlank(con.AccountId) && Trigger.oldMap.get(con.Id).Active__c != con.Active__c) {
// write automation logic here
accountIds.add(con.AccountId);
} else if (Trigger.oldMap.get(con.Id).AccountId != con.AccountId) {
accountIds.add(con.AccountId);
accountIds.add(Trigger.oldMap.get(con.Id).AccountId);
}
}
// get aggregate result for all accounts
List<AggregateResult> results = [
SELECT AccountId, COUNT(Id) totalContacts
FROM Contact
WHERE Active__c = TRUE AND AccountId IN :accountIds
GROUP BY AccountId
];
// build final list of accounts to update
List<Account> accountsToUpdate = new List<Account>();
for (AggregateResult result : results) {
// get account id and number of active contacts
String accId = String.valueOf(result.get('AccountId'));
Integer totalContacts = Integer.valueOf(result.get('totalContacts'));
// make sure you use Id feild in your account to update it
Account acc = new Account(Id = accId, Active_Contacts__c = totalContacts);
accountsToUpdate.add(acc);
}
// update the final list of account
update accountsToUpdate;
}
}
}

How to test contentdocumentlink trigger for Salesforce Prod deployment

I am trying to deploy a trigger to prod on salesforce. I was hoping someone could help me with an example of tests for this trigger.
Here is my trigger. It does its purpose, which is to update a bool field when a new contentNote (or anything of content type) that then has collateral effects through process builder.
trigger NewNote on ContentDocumentLink (before insert) {
Set<Id> setParentId = new Set<Id>();
List<Client_Relationships__c> crlst = new List<Client_Relationships__c>();
for (ContentDocumentLink cdl : trigger.new ) {
setParentId.add(cdl.LinkedEntityId);
}
crlst = [select Id , newNote__c from Client_Relationships__c where Id IN :setParentId];
For(Client_Relationships__c e : crlst)
{
e.newNote__c = True;
}
update crlst;
}
The trigger you wrote can be more efficient by omitting the SOQL query as seen below:
trigger NewNote on ContentDocumentLink (before insert) {
List<Client_Relationships__c> crlst = new List<Client_Relationships__c>();
for (ContentDocumentLink cdl : trigger.new ) {
if(cdl.LinkedEntityId.getSObjectType().getDescribe().getName() == 'Client_Relationships__c'){
crlst.add(
new Client_Relationships__c(
Id = cdl.LinkedEntityId,
newNote__c = true
)
);
}
}
update crlst;
}
The best practice would be to add your code to a handler or utility class and to only have one trigger per object. The name of this trigger could be changed to "ContentDocumentLinkTrigger" if you adopt that practice.
The test class for that trigger is below. I could not test the compilation because I don't have the same custom object.
#IsTest
private class ContentDocumentLinkTriggerTest {
#TestSetup
static void setupTest() {
insert new ContentVersion(
Title = 'Test_Document.txt',
VersionData = Blob.valueOf('This is my file body.'),
SharingPrivacy = 'N',
SharingOption = 'A',
Origin = 'H',
PathOnClient = '/Test_Document.txt'
);
List<Client_Relationships__c> relationships = new List<Client_Relationships__c>();
for(Integer i = 0; i < 300; i++){
relationships.add(
new Client_Relationships__c(
//add required field names and values
)
);
}
insert relationships;
}
static testMethod void testInsertTrigger() {
//prepare data
List<ContentVersion> contentVersions = new List<ContentVersion>([
SELECT Id, ContentDocumentId FROM ContentVersion
]);
System.assertNotEquals(0, contentVersions.size(), 'ContentVersion records should have been retrieved');
List<Client_Relationships__c> relationships = getAllClientRelationships();
System.assertNotEquals(0, relationships.size(), 'Client Relationship records should have been retrieved.');
List<ContentDocumentLink> documentLinks = new List<ContentDocumentLink>();
for(Integer i = 0; i < 252; i++){
documentLinks.add(
new ContentDocumentLink(
ContentDocumentId = contentVersions[0].ContentDocumentId,
LinkedEntityId = relationships[i].Id,
ShareType = 'I'
)
);
}
//test functionality
Test.startTest();
insert documentLinks;
Test.stopTest();
//assert expected results
List<Client_Relationships__c> relationshipsAfterProcessing = getAllClientRelationships();
for(Client_Relationships__c relationship : relationshipsAfterProcessing){
System.assert(relationship.newNote__c, 'The newNote__c field value should be true.');
}
}
private static List<Client_Relationships__c> getAllClientRelationships(){
return new List<Client_Relationships__c>([
SELECT Id, newNote__c FROM Client_Relationship__c
]);
}
}
For setting up test data, it is helpful to have a utility class that centralizes the creation of well-formed records. This is extremely useful when your code base gets large and a validation rule affects the insertion of new data in many test classes. With a centralized method, the inserted data only needs to be altered once.

Testing with Community User, getNetworkId return null

#isTest
public static void TestEmptySearchQuery() {
User thisUser = [ select Id from User where Id = :UserInfo.getUserId() ];
System.runAs ( thisUser ) { // running as thisUser to Avoid Error: MIXED_DML_OPERATION
setupData(); // inside setupData, community is created successfully
generateUser(); // List of user assigned with some profile, as required for project.
list<PermissionSetAssignment> PSA = new list<PermissionSetAssignment> ();
PermissionSet ps = [SELECT Id, name FROM PermissionSet where name='Some_Access'];
system.debug('PermissionSet ' + ps);
for(user u:userList)
PSA.add(new PermissionSetAssignment(AssigneeId = u.id, PermissionSetId = ps.Id)); // all the user assgined with some_access based on requirement of project
insert PSA;
}
Test.startTest();
User usr = [select Id from User where Id = :userList[0].id];
System.runAs(usr) {
system.debug('Network ommunityId ****' + Network.getNetworkId()); //getting null
SomeClass obj = new SomeClass();
Id Nid=obj.fetchNetworkId(); // return null;
system.debug('network id ' + Nid); // null
}
Test.stopTest();
}
class SomeClass {
//some code
public id fetchNetworkId() {
system.debug('network id ' + Network.getNetworkId()); // network id null;
return Network.getNetworkId(); // return null
}
// some code
}
While running normally page, controller returns proper network id,
when try to write a test class for this, community network id always return null.
the user you use for the runAs needs to be part of a community, so you need to basically create an account, create a contact and then a user for that contact. That makes the runAS user to be part of a community

Visualforce email template unit test

I have a trigger that sends an email using a VF template. I'm trying to write a unit test for that code, but keep running into a problem when trying to create the test data.
Here is my test method:
static TestMethod void testQuestionAttachment(){
Id profileId = SYSTEM_ADMIN_PROFILE_ID;
List<User> users = TestUtils.createUsers(profileId, 1);
insert users;
string templateText = '<messaging:emailTemplate subject="{!relatedTo.Name}" recipientType="User" relatedToType="Cutom_Object__c"><messaging:htmlEmailBody ><ul><li>test content</li></ul></messaging:htmlEmailBody></messaging:emailTemplate>';
EmailTemplate template = new EmailTemplate(
developerName = 'TestEmailVFTemplate',
TemplateType= 'visualforce',
FolderId = users[0].Id,
Name = 'TestEmailVFTemplate',
IsActive = true);
template.HtmlValue = templateText;
template.Body = templateText;
System.runAs(users[0]){
insert template;
}
...
And it fails with FIELD_INTEGRITY_EXCEPTION, <messaging:emailTemplate> is required and must be the outermost tag in the markup at line 1 column 1: [Markup].
I really don't understand why this isn't working. I must be missing something...
The issue is with your TemplateType = 'Visualforce'. Instead change it to template.Markup=templateText;. Markup field can be used to assign the body of visualforce template. I tried it in my test class.
Refer below example:
static #isTest void myTest () {
Profile pf = [SELECT Id,Name FROM Profile WHERE Name = 'System Administrator' LIMIT 1];
User usr = new User(
Alias = 'usralias',
Email = 'theuser#email.com',
Emailencodingkey = 'UTF-8',
Lastname = 'user_lastname',
Languagelocalekey = 'en_US',
Localesidkey = 'en_US',
Profileid = pf.Id,
Timezonesidkey = 'America/Los_Angeles',
Username = Math.random() + 'test#testuser.com',
CompanyName = 'the company',
UserRoleId='00E28000000zqCy'
);
insert usr;
string templateText = '<messaging:emailTemplate subject="{!relatedTo.Name}" recipientType="User" relatedToType="Custom_Object__c"><messaging:htmlEmailBody ><ul><li>test content</li></ul></messaging:htmlEmailBody></messaging:emailTemplate>';
EmailTemplate template = new EmailTemplate(DeveloperName = 'TestEmailVFTemplate', TemplateType= 'Visualforce', FolderId = UserInfo.getUserId(),
Name = 'TestEmailVFTemplate',
IsActive = true);
template.Markup=templateText;
System.runAs(usr){
insert template;
}
}

Resources