• Martha V
  • NEWBIE
  • 305 Points
  • Member since 2016
  • Salesforce Administrator/Admin Assistant
  • Daring Adventures

  • Chatter
    Feed
  • 6
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 15
    Questions
  • 77
    Replies
public class wv6_ContactTriggerHandler {

    public static FINAL String STR_PreventDeleteWithoutMerge_ERROR = Label.PreventDeleteWithoutMerge;
    
    public static FINAL Boolean hasPermission = FeatureManagement.checkPermission('Allow_Contact_Deletes');

    public static void checkDeletePermissions(List<Contact> contactList, Map<Id,Contact> oldContactMap){
        
        if(hasPermission) // user is authorized to delete without using Merge
            return;
        
        for(Contact c : oldContactMap.values()){
            if(!Test.isRunningTest() && c.MasterRecordId == null){
                c.addError(STR_PreventDeleteWithoutMerge_ERROR);                  
            }
        }
        
    }
}
Hi,

I have a field 'Site' on Users, which gets mapped to Opportunity once the user from that site creates an opportunity.

So , lets say if a user from Site A creates an opportunity , Opportunity will be stamped with Site A.


Now sometimes, there are transfers, so user from Site A gets transferred to Site B, I want to write an apex trigger , whenver a user gets transfferd from Site A to Site B. for All the opportunites created by him  , oppotunity owner should change to Site A manager..( sort of handover)  , Site A store managers role is "Site A".

How can we achieve this
Hello developers

Need to admit that I have no developer knowledge and I thought that this "project" was a good idea...

Despite the project showing as complete in trailhead I have encountered the following error.

The trailhead section - use events to center the app is working when it is running on the browser but when I include the click event handler to the markers
L.marker(latLng, {account: account}).addTo(map).on('click', function(event) {
    helper.navigateToDetailsView(event.target.options.account.Id);
});


Thus changing the AccountMapControler from

({
    jsLoaded: function(component, event, helper) {
        var map = L.map('map', {zoomControl: false, tap: false}).setView([37.784173, -122.401557], 14);
        L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}',
            {
                attribution: 'Tiles © Esri'
            }).addTo(map);
        component.set("v.map", map);
    },
    accountsLoaded: function(component, event, helper) {
        // Add markers
        var map = component.get('v.map');
        var accounts = event.getParam('accounts');
        for (var i=0; i<accounts.length; i++) {
            var account = accounts[i];
            var latLng = [account.Location__Latitude__s, account.Location__Longitude__s];
            L.marker(latLng, {account: account}).addTo(map);
        }  
    },
    accountSelected: function(component, event, helper) {
        // Center the map on the account selected in the list
        var map = component.get('v.map');
        var account = event.getParam("account");
        map.panTo([account.Location__Latitude__s, account.Location__Longitude__s]);
    }
})


To the following

({
    jsLoaded: function(component, event, helper) {
        var map = L.map('map', {zoomControl: false, tap: false}).setView([37.784173, -122.401557], 14);
        L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}',
            {
                attribution: 'Tiles © Esri'
            }).addTo(map);
        component.set("v.map", map);
    },
    accountsLoaded: function(component, event, helper) {
        // Add markers
        var map = component.get('v.map');
        var accounts = event.getParam('accounts');
        for (var i=0; i<accounts.length; i++) {
            var account = accounts[i];
            var latLng = [account.Location__Latitude__s, account.Location__Longitude__s];
            L.marker(latLng, {account: account}).addTo(map).on('click', function(event) {
    helper.navigateToDetailsView(event.target.options.account.Id);
});
        }  
    },
    accountSelected: function(component, event, helper) {
        // Center the map on the account selected in the list
        var map = component.get('v.map');
        var account = event.getParam("account");
        map.panTo([account.Location__Latitude__s, account.Location__Longitude__s]);
    }
})
When clicking on a marker from within the web browser tab from where I am running the application, I receive the following error

Uncaught TypeError: Cannot read property 'setParams' of undefined throws at https://cunning-otter-goe27l-dev-ed.lightning.force.com/c/components/c/AccountMap.js:40:15

While if I open the tab in the salesforce 1 and salesforce I receive the below error

Error in $A.getCallback() [helper.reportErrorSafely is not a function]
Object.loadContent()@https://cunning-otter-goe27l-dev-ed.lightning.force.com/components/laf/pageHost.js:18:417
Object.eval()@https://cunning-otter-goe27l-dev-ed.lightning.force.com/components/laf/pageHost.js:14:374


Any help will be much appreciated

With regards
Dimitrios
I created a Visualforce page and Apex controller to clone a record. What I need now is to have the Save and Cancel button redirect back to the originating record. I have no experience with Apex or VF and was able to create this with the help of this developer forum. Can anyone help me with what code to add and where to put it, to get the Save Button and Cancel Button to redirect back to the original record? 

Here's the vf page code: 

<apex:page standardController="OpportunityLineItem" extensions="customcloneOpportunityLineItem">
<apex:form >
<apex:pageBlock title="Opportunity Product details">
<apex:pageBlockSection title="Opportunity Prodcut Edit" columns="1">
<apex:inputfield value="{!OpportunityLineItem.OpportunityId}"/>
<apex:inputField value="{!OpportunityLineItem.Product2Id}" />
<apex:inputField value="{!OpportunityLineItem.Quantity}" />
<apex:inputField value="{!OpportunityLineItem.Unit_List_Price__c}" />
<apex:inputfield value="{!OpportunityLineItem.Unit_Sales_Price__c}"/>
<apex:inputfield value="{!OpportunityLineItem.Unit_Cost__c}"/>
<apex:inputfield value="{!OpportunityLineItem.ProductCode}"/>
<apex:inputfield value="{!OpportunityLineItem.Product_Family__c}"/>
</apex:pageBlockSection>
<apex:pageBlockButtons >
<apex:commandButton action="{!cloneopportunitylineitem}" value="Save" />
<apex:commandButton action="{!cloneopportunitylineitem}" value="Cancel" />
</apex:pageBlockButtons>
        </apex:pageBlock>
</apex:form>
</apex:page>

Here's the Apex Class: 

public class customcloneOpportunityLineItem
{private opportunitylineitem l;
public customcloneOpportunityLineItem(apexpages.standardcontroller std){
this.l = (opportunitylineitem)std.getrecord();
}

public void cloneOpportunityLineItem(){
opportunitylineitem l1 = new OpportunityLineItem();
l1 =l.clone();
insert l1; 
}
}
 
Hello,

Would like to ask on how to create a testdatafactory and test class for the following code below?

Trigger Handler:
public class OpportunityTriggerHandler {
    public static void onBeforeUpdate(List<Opportunity> oppList, Map<Id, Opportunity> oldStageMap){
        oppNewStage(oppList, oldStageMap);
    }
	
    public static void oppNewStage(List<Opportunity> oppList, Map<Id, Opportunity> oldStageMap){
        for(Opportunity opp : oppList){
            //Compare the old stage status and new stage status.
            Opportunity oldOppID = oldStageMap.get(opp.Id);           
                if(oldOppID.StageName !=opp.StageName){
                    if(opp.StageName == 'Closed Won'){
                        opp.Description = 'This Opportunity is Closed Won.';
                    }                    
                }           
        }
    }
}
And Trigger is:
trigger OpportunityTrigger on Opportunity (before update) {
    if(Trigger.isBefore)
    {        
        if(Trigger.isUpdate){
            OpportunityTriggerHandler.onBeforeUpdate(Trigger.new, Trigger.oldMap);
        }
    }
}

Thank you!
 
I am trying to implement a Remember Me button in a custom login aura component. I've tried using window.localStorage to store values to retrieve later. But the component is just freezing and not showing any errors. Has anyone been able to implement something like this? BTW my sandbox is running Summer '20 release.
I have a repeat in a visualforce page that displays the fieds in a fieldset. I want the fields to display in two columns (like the standard detail pages), but they would only display all in one cell when using apex:pageBlockSection. 

I tried to add a span to wrap the repeat to add style of width: 50% and display:inline.
It is displaying in two columns, but there seems to be a line break after each field.

Here is the code
<apex:pageBlockSection title="Information" columns="2">
                <apex:inputField value="{!Projects__c.Name}" label="Project Name" required="true"/>
                <apex:outputField value="{!Projects__c.OwnerId}" />
                <span style="display:inline; width:50%;">                
                    <apex:repeat value="{!$ObjectType.Projects__c.FieldSets.projectFieldSet}" var="f"> 
                        <span style="display:inline; width:50%;">
                            <apex:inputField value="{!Projects__c[f.fieldPath]}" label="{!f.Label}" required="{!OR(f.required, f.dbrequired)}"/>
                        </span>
                    </apex:repeat> 
                </span>                                             
            </apex:pageBlockSection>

and here is what I am getting
visualforce page preview

I want to get rid of all the vertical spaces in between the fields. Any ideas?
I am stuck in this step. My tests are running and I have 100% coverage, but there is something Trailhead is not liking. Do you know what can it be?

Here is my OrderTests class:
@IsTest
private class OrderTests {
    
	   
    @testSetup static void SetupTestData(){
        TestDataFactory.InsertTestData(5);
    }

    
    @isTest static void OrderUpdate_UnitTest(){
        //retrieve the orders saved by TestDataFactory
        Map<Id, Order> orders= new Map<Id, Order>([SELECT Id, Status FROM Order]);
        //save the original Product2 record in a map
        Map<Id, Product2> originalProductMap = new Map<Id, Product2>();
        //Loop through a query of OrderItems related to the orders
        List<OrderItem> items = [SELECT Id, Product2Id, Product2.Quantity_Ordered__c, Quantity
                                 FROM OrderItem
                                 WHERE OrderId IN :orders.keySet()];
        //ToDo: Populate the map with the Id of the related Product2 as the key and Product2 record as the value
        for ( OrderItem oi : items){
            Product2 p = oi.Product2;
            if (!originalProductMap.containsKey(p.Id)) {
                originalProductMap.put(p.Id, p);
            } 
        }
        //update the Status of the orders
        List<Order> updatedOrders = new List<Order>();
        for (Order order : orders.values()) {
            order.Status = Constants.ACTIVATED_ORDER_STATUS;
            updatedOrders.add(order);
        }
        //get the amounts to be order for each Product
        //declare a map to save the Amounts for each product
        Map<Id, Integer> prodAmounts = new Map<Id, Integer>();
        //get the aggregated amounts by product id
        AggregateResult[] groupedResults  = [SELECT Product2Id, SUM(Quantity) FROM OrderItem
                                             WHERE Product2Id IN :originalProductMap.keySet() 
                                             GROUP BY Product2Id];
        for (AggregateResult ar : groupedResults)  {
             prodAmounts.put(String.valueOf(ar.get('Product2Id')),Integer.valueOf(ar.get('expr0')));
        }                                     
        //update the orders in the DB
        update updatedOrders;
        //retrieve the products affected by the orders update
        Map<Id, Product2> updatedProductMap = new Map<Id, Product2>([SELECT id, Quantity_Ordered__c 
                                                                     FROM Product2 WHERE
                                                                     id IN :originalProductMap.keySet()]);
        for (Product2 origProd : originalProductMap.values()) {
            TestDataFactory.VerifyQuantityOrdered(origProd,updatedProductMap.get(origProd.Id), prodAmounts.get(origProd.Id));
        }
    }

}

and my TestDataFactory
 
/**
 * @name TestDataFactory
 * @description Contains methods to construct and/or validate commonly used records
**/
public with sharing class TestDataFactory {

    /**
     * @name ConstructCollaborationGroup
     * @description
    **/
    public static CollaborationGroup ConstructCollaborationGroup(){
        //ToDo: Ensure this method returns a single Chatter CollaborationGroup
        //    whose Name starts with 'TEST' followed by the INVENTORY_ANNOUNCEMENTS constant
        //    and configured so anyone can join, see and post updates.
        return (new CollaborationGroup(Name = 'TEST' + Constants.INVENTORY_ANNOUNCEMENTS,
                                       CollaborationType = 'Public'));        
    }

    /**
     * @name CreateProducts
     * @description Constructs a list of Product2 records for unit tests
    **/
    public static List<Product2> ConstructProducts(Integer cnt){
        for (Schema.PicklistEntry fam : Constants.PRODUCT_FAMILY){

        }
        //ToDo: Ensure this method returns a list, of size cnt, of uniquely named Product2 records
        //  with all the required fields populated
        //  and IsActive = true
        //  an Initial Inventory set to 10
        //  and iterating through the product family picklist values throughout the list.
        List<Product2> products = new List<Product2>();
        Integer i = 0;
        for (Integer x = 0; x < cnt; x++ ){
            if (i > Constants.PRODUCT_FAMILY.size() -1 ) i = 0;            
            Product2 p = new Product2(Name = 'product' + x,
                                      Initial_Inventory__c = 10,
                                      IsActive = true,
                                      Family = Constants.PRODUCT_FAMILY[i].getLabel());
            i++;                          
            products.add(p);
        }
        return products;
    }

    /**
     * @name CreatePricebookEntries
     * @description Constructs a list of PricebookEntry records for unit tests
    **/
    public static List<PricebookEntry> ConstructPricebookEntries(List<Product2> prods){

        //ToDo: Ensure this method returns a corresponding list of PricebookEntries records
        //  related to the provided Products
        //  with all the required fields populated
        //  and IsActive = true
        //  and belonging to the standard Pricebook
        List<PricebookEntry> pbentries = new List<PricebookEntry>();
        for (Product2 p : prods){
            PricebookEntry pb = new PricebookEntry(IsActive = true,
                                       UnitPrice = 10,
                                       Pricebook2Id = Constants.STANDARD_PRICEBOOK_ID,
                                       Product2Id = p.Id);
            pbentries.add(pb);                           
        }
        return pbentries;
    }

    /**
     * @name CreateAccounts
     * @description Constructs a list of Account records for unit tests
    **/
    public static List<Account> ConstructAccounts(Integer cnt){
        //ToDo: Ensure this method returns a list of size cnt of uniquely named Account records
        //  with all of the required fields populated.
        List<Account> accounts = new List<Account>();
        for (Integer x=0; x<cnt; x++) {
            Account acc = new Account(Name = 'account ' + x);
            accounts.add(acc);
        }
        return accounts;
    }

    /**
     * @name CreateContacts
     * @description Constructs a list of Contacxt records for unit tests
    **/
    public static List<Contact> ConstructContacts(Integer cnt, List<Account> accts){
        //ToDo: Ensure this method returns a list, of size cnt, of uniquely named Contact records
        //  related to the provided Accounts
        //  with all of the required fields populated.
        List<Contact> contacts = new List<Contact>();
        Integer y = 0;
        for (Integer x = 0; x < cnt; x++){
            if (y > accts.size() - 1) y = 0;
            Contact c = new Contact(FirstName = 'cont'+y,
                                    LastName = 'Last ' + y,
                                    AccountId = accts[y].Id );
            contacts.add(c);                        
            y++;
        }
        return contacts;
    }

    /**
     * @name CreateOrders
     * @description Constructs a list of Order records for unit tests
    **/
    public static List<Order> ConstructOrders(Integer cnt, List<Account> accts){
        //ToDo: Ensure this method returns a list of size cnt of uniquely named Order records
        //  related to the provided Accounts
        //  with all of the required fields populated.
        Integer y = 0;
        List<Order> orders = new List<Order>();
        for (Integer x = 0; x < cnt; x++) {
            if (! (y < accts.size())) y = 0;
            Order ord = new Order(AccountId = accts[y].Id,
                                  PriceBook2Id = Constants.STANDARD_PRICEBOOK_ID,
									Name = 'order '+ x,
                                    Status = Constants.DRAFT_ORDER_STATUS,
                                    EffectiveDate = date.today());
            orders.add(ord); 
            y++;               
        }
        return orders;
    }

    /**
     * @name CreateOrderItems
     * @description Constructs a list of OrderItem records for unit tests
    **/
    public static List<OrderItem> ConstructOrderItems(integer cnt, list<pricebookentry> pbes, list<order> ords){
        //ToDo: Ensure this method returns a list of size cnt of OrderItem records
        //  related to the provided Pricebook Entries
        //  and related to the provided Orders
        //  with all of the required fields populated.
        //  Hint: Use the DEFAULT_ROWS constant for Quantity as it will be used in the next challenge
        List<OrderItem> orditems = new List<OrderItem>();
        Integer y = 0;
        for (Integer x = 0; x < cnt; x++) {
            if (y > pbes.size() - 1) y = 0;
            OrderItem oi = new OrderItem(OrderId = ords[y].Id,
                                            PricebookEntryId = pbes[y].Id,
                                            Quantity = Constants.DEFAULT_ROWS,
                                            UnitPrice = 1);
            orditems.add(oi);
            y++;
        }
        return orditems;
    }

    /**
     * @name SetupTestData
     * @description Inserts accounts, contacts, Products, PricebookEntries, Orders, and OrderItems.
    **/
    public static void InsertTestData(Integer cnt){
        //ToDo: Ensure this method calls each of the construct methods
        //  and inserts the results for use as test data.
        CollaborationGroup cg = ConstructCollaborationGroup();
        insert cg;
        system.debug('inserted CollaborationGroup');
        List<Product2> prods = ConstructProducts(cnt);
        insert prods;
        system.debug('inserted products');
        List<PricebookEntry> pbes = ConstructPricebookEntries(prods);
        try {
            insert pbes;
            system.debug('inserted PriceBookEntries');
        } catch (Exception e) {
            system.debug('exception: ' + e.getMessage());
        }
        List<Account> accts = ConstructAccounts(cnt);
        insert accts;
        system.debug('inserted Accounts');
        List<Contact> conts = ConstructContacts(cnt, accts);
        insert conts;
        system.debug('inserted Contacts');
        List<Order> orders = ConstructOrders(cnt,accts);
        insert orders;
        system.debug('inserted orders');
        List<OrderItem> ordItems = ConstructOrderItems(cnt, pbes, orders);
        insert ordItems;
        system.debug('inserted OrderItems');
    }
    
    public static void VerifyQuantityOrdered(Product2 originalProduct, Product2 updatedProduct, Integer qtyOrdered) {
        system.debug('Original Product.quantity = ' + originalProduct.Quantity_Ordered__c);
        system.debug('qtyOrdered = '+ qtyOrdered);
        system.debug('updated product.quantity = ' + updatedProduct.Quantity_Ordered__c);
        
        system.assertEquals(qtyOrdered, updatedProduct.Quantity_Ordered__c - originalProduct.Quantity_Ordered__c );
    }

}

 
This is in Step 5 of the Superbadge. here is my test class
@isTest
private class OrderTests {
	@TestSetup   
    static void SetupTestData(){
        TestDataFactory.InsertTestData(5);
    }

    @isTest
    static void OrderUpdate_UnitTest(){
        //retrieve the orders saved by TestDataFactory
        Map<Id, Order> orders= new Map<Id, Order>([SELECT Id, Status FROM Order]);
        //save the original Product2 record in a map
        Map<Id, Product2> originalProductMap = new Map<Id, Product2>();
        //Loop through a query of OrderItems related to the orders
        List<OrderItem> items = [SELECT Id, Product2Id, Product2.Quantity_Ordered__c, Quantity
                                 FROM OrderItem
                                 WHERE OrderId IN :orders.keySet()];
        //ToDo: Populate the map with the Id of the related Product2 as the key and Product2 record as the value
        for ( OrderItem oi : items){
            Product2 p = oi.Product2;
            if (!originalProductMap.containsKey(p.Id)) {
                originalProductMap.put(p.Id, p);
            } 
        }
        //update the Status of the orders
        List<Order> updatedOrders = new List<Order>();
        for (Order order : orders.values()) {
            order.Status = Constants.ACTIVATED_ORDER_STATUS;
            updatedOrders.add(order);
        }
        //get the amounts to be order for each Product
        //declare a map to save the Amounts for each product
        Map<Id, Integer> prodAmounts = new Map<Id, Integer>();
        //get the aggregated amounts by product id
        AggregateResult[] groupedResults  = [SELECT Product2Id,SUM(Product2.Quantity_Ordered__c), SUM(Quantity) FROM OrderItem
                                             WHERE Product2Id IN :originalProductMap.keySet() 
                                             GROUP BY Product2Id];
        for (AggregateResult ar : groupedResults)  {
             prodAmounts.put(String.valueOf(ar.get('Product2Id')),Integer.valueOf(ar.get('expr1')));
        }                                     
        //update the orders in the DB
        update updatedOrders;
        //retrieve the products affected by the orders update
        Map<Id, Product2> updatedProductMap = new Map<Id, Product2>([SELECT id, Quantity_Ordered__c 
                                                                     FROM Product2 WHERE
                                                                     id IN :originalProductMap.keySet()]);
        for (Product2 origProd : originalProductMap.values()) {
            TestDataFactory.VerifyQuantityOrdered(origProd,updatedProductMap.get(origProd.Id), prodAmounts.get(origProd.Id));
        }
    }
}

Can anyone tell me why I am getting that error? my tests are running fine and I have enough code coverage on the extension, the order trigger and the order helper (which is what this step is about).

What am I missing? I have tried to chang @IsTest for TestMethod, but it still doesn't work.
I have two components, both working in a Record Page. The record has a master-detail relationship to a custom object.
component 1 adds a record to the object (detail)
component 2 lists all the detail records related to the RecordId.

The work separately, but when I add the PUBSUB and the extra imports (page reference & pubsub) I am getting an error when I try to deploy the code to the dev-org. 

The error says:
The component must implement at least one of lightning__RecordPage interface.
Both components have the <target>lightning__RecordPage</target> in the metadata file, and as stated above they work fine withouth the PUBSUB code.

Any one knows what might be going on?
also, the dev-org is running on v. Summer 19 
Hi, my code has passed the step 4 check, but when I try the search by boat type no boats appear on the BoatSearchResults component. I have done some debugging and found that it is not entering into the aura:iteration and can't figure out why. Hopefully someone can help me.

The string "going to AuraIteration" appears on the screen, but nothing else. The variable v.boats contains the right amount of items (I am testing it with Sailboat type and it has 2 items. It also has the right values in each object.

Here is my code: 


BoatSearchResults.cmp
<aura:component controller="BoatSearchResults">
    <aura:attribute name="boatTypeId" type="String" />
    <aura:method name="search" description="gets the boatTypeId from BoatSearch component and runs the search"
                 action="{!c.doSearch}">
        <aura:attribute name="boatTypeId" type="String" />
    </aura:method >
    <aura:attribute name="boats" type="Boat__c[]" />
    <lightning:layout multipleRows="true" verticalAlign="center" horizontalAlign="center">
        <aura:if isTrue="{!v.boats.length &gt; 0}">
            going to AuraIteration
            <aura:iteration items="{!v.boats}" var="boatItem">
                <lightning:layoutItem flexibility="grow" class="slds-m-right_small">
                    <h3>calling BoatTile</h3>
                    <c:BoatTile boat="{!boatItem}"/>
                </lightning:layoutItem>
            </aura:iteration>
            <aura:set attribute="else">
                <lightning:layoutItem class="slds-align_absolute-center" flexibility="auto">
                    <h3>No boats found</h3>
                </lightning:layoutItem>
            </aura:set>
        </aura:if>
    </lightning:layout>
</aura:component>

Also, can someone tell me how to post code so it looks like code (lined and with the option to copy, etc)

Thanks!

 
Hi, I am testing a controller that sends emails to Campaign Members. My problem is that when I insert the Campaign Members, they get inserted with the wrong Status (not the one I set up in the test). I have even tried to retrieve the records inserted and change the status again and then do an update, but again the status during the test gets recorded with the wrong value.

I thought maybe it was a trigger of some sort (I am using the NSPS package), but when I add the campaign member through the UI it is not happening. It is only happening during the test.

Does anyone knows why this is happening?




Here is some of my test code, where I insert the records
        List<contact> contacts = new List<Contact>();
        for (Integer x = 1; x < 9; x++)
        {
            Contact cont = new Contact(FirstName = 'test'+x,
                                       LastName = 'test ' + x,
                                       email = 'marthacv@gmail.com');
            if (x==8) cont.email = '';
            contacts.add(cont);
        }
        insert contacts;
        List<Campaign> campaigns = new List<Campaign>();
        for (integer x = 0; x<4; x++)
        {
            Campaign camp = new Campaign(Name = 'Campaign ' + x,
                                         Type = campaignTypes[x],
                                         StartDate = campaignDates[x],
                                         IsActive = True,
                                         Status = 'Planned',
                                         EndDate = campaignDates[x],
                                         Description = 'testing emails',
                                         RecordTypeId = '012o0000000xwhO',
                                         Fee_for_Activity__c = fee.id);
            campaigns.add(camp);
        }
        Database.SaveResult[] srList = Database.insert(campaigns, false);
       participant = new CampaignMember(ContactId = contacts[1].id,
                                         Status = 'Signed Up',
                                         CampaignId = campaigns[4].id);
        participants.add(participant);        
        insert participants;

... after the inserts I run the test with several campaigns

        List<String> returnPages = new List<String>();
        List<PageReference> pgref = new List<PageReference>();        
        ApexPages.StandardController std1 =
            new ApexPages.StandardController(campaigns[0]);
        CMSendEmails firstTest = new CMSendEmails(std1);
        pgref.add(firstTest.SendTheEmails());
        returnPages.add(pgref[0].getUrl());

 
I want to use the information from a report in a visualforce page. Can that be done? I only see the instantiate class for asynchronous reports.
Any help is appreciated.
I am a new administrator to this org. I haven't used them in any of my implementations, but the email I got from SF says the org has some. How can I find where they are?
I have an apex extension for a visualforce page that sends emails using the SignleEmailMessaging method. It sends email using an email template with merge fields from a custom object called ParticipantEmail. However, I am getting an error on the WhatId method call.

here is that part of the code:
       //the class WrapTemp has two attributes, one of type ParticipantEmail__c named tempRec and the second one is a string named type_member
        for (WrapTemp wCM : pEmails){
            Messaging.SingleEmailMessage mess = new Messaging.SingleEmailMessage();
            List<String> bccAddys = new List<String>();
            bccAddys.add(UserInfo.getUserId());
            mess.setBccAddresses(bccAddys);
            system.debug('wCM.tempRec.ContactId = ' + wCM.tempRec.ContactId__c);
            system.debug('wCM.tempRec.Id = '+wCM.tempRec.Id);
            //set the contact to be emailed
            mess.setTargetObjectId(wCM.tempRec.ContactId__c);
            system.debug('wCM.tempRec.Id = '+wCM.tempRec.Id);
            id theRecId = wCM.tempRec.Id;
            system.debug('theRecId = '+ theRecId);            
            mess.setWhatId(theRecId);
            if (wCM.type_member == 'Participant') 
                mess.setTemplateId(temp.Id);
            else 
                mess.setTemplateId(volTemp.Id);                 
            messages.add(mess);            
        }
        messaging.sendEmail(messages);

Here is what I get from the debugger:
User-added image
It says the id is a284B0000007BOiQAM

but then the error I get says this 


System.EmailException: SendEmail failed. First exception on row 0; first error: INVALID_ID_FIELD, Invalid entity type for whatId.: [whatId, a284B0000007BPf]
Error is in expression '{!SendTheEmails}' in component <apex:commandButton> in page cmsendemailsvf: Class.CMSendEmails.SendTheEmails: line 129, column 1


Does anyone see what my problem is here?  I have no idea.
We need to have a button from the Campaign detail page that will send emails (using a template) to selected campaign members.


I made a visualforce page with an extension to help with the selection of the campaign members to be emailed. Once I had that all done however I found out that SendSingEmail using a template doesn’t work with CampaignMember as a whatid(). So now, I wonder if it can be done with a visualforce template. Am I thinking on the right direction or is there a better solution for this?
Hi, I wrote a class that has no static methods (due to some public variables that I needed to use accross different methods). I tested it by making an instance of the class. My question is once I get it in production how do I call it?

Here is my code
public class ImportAZGives {
        public List<AZGives_Donor__c> donors;
        public map<String, AZGives_Donor__c> map_donors;
        public List<Opportunity> oppys;
        public List<Task> taskList;
        public Campaign theCampaign;
        public List<Contact> newContacts;
        public List<AZGives_Donor__c> annon;        

    
    public ImportAZGives(){
        annon = new List<AZGives_Donor__c>();
        theCampaign = [SELECT id, Name FROM Campaign 
                       WHERE Name = 'AZGives Main Campaign' limit 1];
        oppys = new List<Opportunity>();
        taskList = new List<Task>();
        for (Integer x=0 ; x<30; x++)
        {
            boolean done = checkWithContacts();    
            if (done) x = 31;
        }
    }
    
    public Boolean checkWithContacts() 
    {
        donors = [SELECT id, Amount__c, Transaction_Date_Time__c, Anonymous__c,
                 FirstName__c, LastName__c, Email__c, Phone_Number__c,
                 Address_1__c, Address_2__c, City__c, State__c, Country__c,
                 Zip_Code__c, Cover_Fees__c, In_Memory__c, Comments__c, Get_Involved__c,
                 Campaign_Name__c, Processed__c, Matched_Email__c, Not_Found__c 
                 FROM AZGives_Donor__c WHERE 
                 (Not_Found__c = false AND Processed__c = false AND 
                  Matched_Email__c = false) Limit 200];
        system.debug('donors.size() = '+ donors.size());
        if (donors.size()>0)
        {
            map_donors = new map<String, AZGives_Donor__c>();
            system.debug('map_donors.size() = '+ map_donors.size());
            for (AZGives_Donor__c donor : donors)
            {
                system.debug('donor = ' + donor);
                if ( ! map_donors.containsKey(donor.Email__c))
                    if (donor.Anonymous__c.contains('Fully')) annon.add(donor); 
                    else
                        map_donors.put(donor.Email__c, donor);
                }
            system.debug('map_donors.size() = '+ map_donors.size());
            SearchContacts();
            return false;
        }
        else return true;
    }
    
    public void SearchContacts(){    
        system.debug('in SearchContacts');
        List<Contact> conts = [SELECT id, FirstName, LastName, Email from Contact
                              WHERE Email IN :map_donors.keySet()];
        system.debug('conts size = '+ conts.size());
        List<AZGives_Donor__c> updatedDonors = new List<AZGives_Donor__c>();
        for (Contact c : conts){
            AZGives_Donor__c donor = map_Donors.get(c.Email);
            system.debug('contact name '+ c.FirstName +' ' + c.LastName);
            system.debug('donor First Name '+ donor.FirstName__c +
                        ' donor Last Name ' + donor.LastName__c);
            if (c.FirstName == donor.FirstName__c && c.LastName == donor.LastName__c)
            {
                oppys.add(newOppy(c, donor));
                donor.Processed__c = true;
            }
            Else
            {
                donor.Processed__c = false;
                donor.Matched_Email__c = true;
            }
            updatedDonors.add(donor);
            map_Donors.put(c.Email, donor);
        }
        If (map_Donors.size() > conts.size())
        {
            addNewContacts();        
            if (newContacts.size() > 0){
                insert newContacts;
                for (Contact newC : newContacts){  
                    system.debug('newC.id = '+ newC.id);
                    AZGives_Donor__c donor = map_Donors.get(newC.Email);

                    oppys.add(newOppy(newC, donor));
                }
            }
        }
        if (annon.size()>0) ProcessAnnonymous();        
        donors = map_Donors.values();        
        for (AZGives_Donor__c d : donors)
            if (!d.Processed__c && d.Matched_Email__c)
                d.Not_Found__c = true;
        update donors;
        insert oppys;
        insert taskList;
        
    }
    
    public void addNewContacts()
    {
        List<AZGives_Donor__c> not_Found = map_Donors.values();
        newContacts = new List<Contact>();
        For (AZGives_Donor__c d : not_Found){
            if (!d.Processed__c && !d.Matched_Email__c) {
                Contact c = new Contact(FirstName = d.FirstName__c,
                                   LastName = d.LastName__c,
                                   Email = d.Email__c,
                                           MailingStreet = d.Address_1__c,
                                           MailingCity = d.City__c,
                                           MailingState = d.State__c,
                                           MailingPostalCode = d.Zip_Code__c,
                                           Phone = d.Phone_Number__c);
                newContacts.add(c);
                d.Processed__c = true;
                map_Donors.put(d.Email__c, d);
            }
        }
    }

    public Opportunity newOppy(Contact c, AZGives_Donor__c donor){
        String stName = 'Donation '+ c.FirstName + ' ' +
                                c.LastName + '4/3/17';
        String annon1 = '';
        If (donor.Anonymous__c.contains('Partially')) 
            annon1 = 'Donor wishes to remain annonymous'; 
        Opportunity oppy = new Opportunity (Name = stName,
                                        RecordTypeId = '012o0000000xvXl',
                                        npsp__Primary_Contact__c = c.id,
                                        Amount = donor.Amount__c,
                                        CloseDate = donor.Transaction_Date_Time__c.date(),
                                        StageName = 'Closed Won',
                                        Description = annon1,
                                        CampaignId = theCampaign.Id);
        if (donor.Get_Involved__c)
            taskList.add(makeTask(c));
        return oppy;
    }
    
    public Task makeTask (Contact c)
    {
        Task contTask = new Task(ActivityDate = Date.Today() + 3,
             Description = c.FirstName + ' ' + c.LastName + ' wants to be involved with DA.',
                     Priority = 'High', Status = 'Not Started', 
                    Subject = 'Need to make CONTACT',
                    WhatId = theCampaign.Id, 
                    WhoId = c.id);
        return contTask;
    }
    
    public void ProcessAnnonymous(){
        Account acc = [SELECT id FROM Account WHERE Name = 'Anonymous' limit 1];
        if (acc == null){
            acc = new Account(Name = 'Anonymous');
            insert acc;
        }
        integer x = 1;
        for(AZGives_Donor__c d : annon){
            String str = 'Donation AZGives Anonymous ' + x;
            Opportunity oppy = new Opportunity (Name = str,
                                   AccountId = acc.id,
                                   RecordTypeId = '012o0000000xvXl',
                                   Amount = d.Amount__c,
                                   CloseDate = d.Transaction_Date_Time__c.date(),
                                   StageName = 'Closed Won',
                                   Description = 'Anonymous Donation',
                                   CampaignId = theCampaign.Id); 
            x++;
            d.Processed__c = true;
            map_Donors.put(d.Email__c, d);
            oppys.add(oppy);
        }
    }  
}
I want to add a custom button in the CampaignMembers related list in the Campaign layout. I am adding it as a URL but it seems that I can't put in the Campaign Id as an argument.

User-added image

what do I need to do?
I want to make a VF page that shows members of a campaign as well as has a searchfield to find contacts to add to the campaign. So the action for the search field will find all contacts that match and display them on a list. Then the user can select a contact and click on the name and that contact would be added to the campaign. 

My problem is that I don't know how to implement that last bit. Since the list of contats is displayed with a pageBlockTable how does the controller know which contact was selected.

Here is my VF page markup

<apex:page standardController="Campaign" extensions="showCampaignMembers">
  <apex:form >
    <apex:pageBlock title="{!campaign.name}">
      <apex:pageBlockSection title="Criteria">
      <apex:outputLabel value="Enter Name Snippet"/>
      <apex:inputText value="{!nameQuery}"/>
      <apex:commandButton action="{!executeSearch}" value="Search"/>
   </apex:pageBlockSection>
    
   <apex:pageBlockTable value="{!contacts}" var="con">
      <apex:column headerValue="Name">
         <apex:outputLink value="/{!con.id}/e?retURL={!URLENCODE('/apex/RetUrlSearchPage?query='+nameQuery)}">{!con.Name}</apex:outputLink>
      </apex:column>
      <apex:column value="{!con.Participant__c}"/>
   </apex:pageBlockTable>
   <apex:pageBlockSection title="Participants in Campaign">
     <apex:pageBlockTable value="{!participants}" var="part">
       <apex:column value="{!part.FirstName}"/>
       <apex:column value="{!part.LastName}"/>
       <apex:column value="{!part.Email}"/>
       <apex:column value="{!part.Status}"/>
                 
     </apex:pageBlockTable>
   </apex:pageBlockSection>
 </apex:pageBlock>
  </apex:form>
</apex:page>

-----------
And the controller
-----------

public class showCampaignMembers 
{
 public String nameQuery {get; set;}
 public List<Contact> contacts {get; set;}
 Public List<CampaignMember> participants {get; set;}
 private ApexPages.StandardController std;
 
 public PageReference executeSearch()
 {
  String queryStr='%' + nameQuery + '%';
  contacts=[select id, Name, Participant__c 
            from Contact 
            where name like :queryStr];
            
  return null;
 }
  
 public showCampaignMembers(ApexPages.StandardController stdCtrl)
 {
   Std = stdCtrl;
    Participants = [SELECT id, FirstName, LastName, Email, Status FROM CampaignMember
        WHERE CampaignId = :std.getId() ORDER BY FirstName];
  }

}

I appreciate any help.
I have a delete trigger to stop deletion when certain conditions are true. The trigger is working fine. I've tested it in the sandbox. The test however is giving me some problems. I have looked in the community and used some of the suggestions given, however I haven't been able to make it work.

Here is my trigger & test

trigger whenCampaignDeleted on Campaign (before delete) {
    List<Campaign> delCampaign = trigger.old;
    Boolean dontDelete = False;
    Boolean relCampaign = False;
    for (Campaign eachCampaign : delCampaign)
    {
        //If the campaign is Adventure type check to see if there are campaign members
        //with status "Attended" and if there is a related campaign: volunteer campaign
        If (eachCampaign.RecordTypeId == '012o0000000xwhO')
        {
               If (eachCampaign.Related_Campaign__c != NULL)
                 relCampaign = True;     
            List<CampaignMember> cMs = [SELECT id, status FROM CampaignMember
                               WHERE CampaignId = :eachCampaign.Id];
 
            For (CampaignMember eachCM : cMS)
            {
                 If (eachCM.Status == 'Attended')
                {dontDelete = True;}
            }
            If (dontDelete)
                eachCampaign.adderror('Cannot delete a campaign that has members with status Attended. Their status must be changed first.');
            If (relCampaign)
                eachCampaign.adderror('Before deleting the campaign you must delete the volunteer campaign associated with it.');
        }
        Else 
        //If the campaign is a volunteer campaign then retreive the Adventure campaign related to it
        //and delete the related campaign from the Adventure record
        If (eachCampaign.RecordTypeId == '012o0000001AJaa')
        {
            if (eachCampaign.Related_Campaign__c != NULL)
            {
                Campaign relCampRecord = [SELECT ID, Related_Campaign__c FROM Campaign 
                                         WHERE Id = :eachCampaign.Related_Campaign__c];
                relCampRecord.Related_Campaign__c = NULL;
                Update relCampRecord;
            }
        }
    }
}



——————  Test
After inserting a few records to test the trigger the following code performs the test (here I am just testing it with one record to single out the error, but it is set up to test a list of records).


        try
        {
            delete myCampaigns[1];
            System.assert(false);
        }
        catch (DMLException e)
        {
            // Check that the trigger interrupts the deletion
            system.assertEquals('Before deleting the campaign you must delete the volunteer campaign associated with it.', e.getMessage());
        }





When I run the test I get the following error

System.AssertException: Assertion Failed: Expected: Before deleting the campaign you must delete the volunteer campaign associated with it., Actual: Delete failed. First exception on row 0 with id 701n0000000DlUDAA0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Before deleting the campaign you must delete the volunteer campaign associated with it.: []



Can any one help? I am not sure how to change the System.assert to verify that the deletion is not done.

Thanks in advance for any help
public class wv6_ContactTriggerHandler {

    public static FINAL String STR_PreventDeleteWithoutMerge_ERROR = Label.PreventDeleteWithoutMerge;
    
    public static FINAL Boolean hasPermission = FeatureManagement.checkPermission('Allow_Contact_Deletes');

    public static void checkDeletePermissions(List<Contact> contactList, Map<Id,Contact> oldContactMap){
        
        if(hasPermission) // user is authorized to delete without using Merge
            return;
        
        for(Contact c : oldContactMap.values()){
            if(!Test.isRunningTest() && c.MasterRecordId == null){
                c.addError(STR_PreventDeleteWithoutMerge_ERROR);                  
            }
        }
        
    }
}
I have a repeat in a visualforce page that displays the fieds in a fieldset. I want the fields to display in two columns (like the standard detail pages), but they would only display all in one cell when using apex:pageBlockSection. 

I tried to add a span to wrap the repeat to add style of width: 50% and display:inline.
It is displaying in two columns, but there seems to be a line break after each field.

Here is the code
<apex:pageBlockSection title="Information" columns="2">
                <apex:inputField value="{!Projects__c.Name}" label="Project Name" required="true"/>
                <apex:outputField value="{!Projects__c.OwnerId}" />
                <span style="display:inline; width:50%;">                
                    <apex:repeat value="{!$ObjectType.Projects__c.FieldSets.projectFieldSet}" var="f"> 
                        <span style="display:inline; width:50%;">
                            <apex:inputField value="{!Projects__c[f.fieldPath]}" label="{!f.Label}" required="{!OR(f.required, f.dbrequired)}"/>
                        </span>
                    </apex:repeat> 
                </span>                                             
            </apex:pageBlockSection>

and here is what I am getting
visualforce page preview

I want to get rid of all the vertical spaces in between the fields. Any ideas?
I am stuck in this step. My tests are running and I have 100% coverage, but there is something Trailhead is not liking. Do you know what can it be?

Here is my OrderTests class:
@IsTest
private class OrderTests {
    
	   
    @testSetup static void SetupTestData(){
        TestDataFactory.InsertTestData(5);
    }

    
    @isTest static void OrderUpdate_UnitTest(){
        //retrieve the orders saved by TestDataFactory
        Map<Id, Order> orders= new Map<Id, Order>([SELECT Id, Status FROM Order]);
        //save the original Product2 record in a map
        Map<Id, Product2> originalProductMap = new Map<Id, Product2>();
        //Loop through a query of OrderItems related to the orders
        List<OrderItem> items = [SELECT Id, Product2Id, Product2.Quantity_Ordered__c, Quantity
                                 FROM OrderItem
                                 WHERE OrderId IN :orders.keySet()];
        //ToDo: Populate the map with the Id of the related Product2 as the key and Product2 record as the value
        for ( OrderItem oi : items){
            Product2 p = oi.Product2;
            if (!originalProductMap.containsKey(p.Id)) {
                originalProductMap.put(p.Id, p);
            } 
        }
        //update the Status of the orders
        List<Order> updatedOrders = new List<Order>();
        for (Order order : orders.values()) {
            order.Status = Constants.ACTIVATED_ORDER_STATUS;
            updatedOrders.add(order);
        }
        //get the amounts to be order for each Product
        //declare a map to save the Amounts for each product
        Map<Id, Integer> prodAmounts = new Map<Id, Integer>();
        //get the aggregated amounts by product id
        AggregateResult[] groupedResults  = [SELECT Product2Id, SUM(Quantity) FROM OrderItem
                                             WHERE Product2Id IN :originalProductMap.keySet() 
                                             GROUP BY Product2Id];
        for (AggregateResult ar : groupedResults)  {
             prodAmounts.put(String.valueOf(ar.get('Product2Id')),Integer.valueOf(ar.get('expr0')));
        }                                     
        //update the orders in the DB
        update updatedOrders;
        //retrieve the products affected by the orders update
        Map<Id, Product2> updatedProductMap = new Map<Id, Product2>([SELECT id, Quantity_Ordered__c 
                                                                     FROM Product2 WHERE
                                                                     id IN :originalProductMap.keySet()]);
        for (Product2 origProd : originalProductMap.values()) {
            TestDataFactory.VerifyQuantityOrdered(origProd,updatedProductMap.get(origProd.Id), prodAmounts.get(origProd.Id));
        }
    }

}

and my TestDataFactory
 
/**
 * @name TestDataFactory
 * @description Contains methods to construct and/or validate commonly used records
**/
public with sharing class TestDataFactory {

    /**
     * @name ConstructCollaborationGroup
     * @description
    **/
    public static CollaborationGroup ConstructCollaborationGroup(){
        //ToDo: Ensure this method returns a single Chatter CollaborationGroup
        //    whose Name starts with 'TEST' followed by the INVENTORY_ANNOUNCEMENTS constant
        //    and configured so anyone can join, see and post updates.
        return (new CollaborationGroup(Name = 'TEST' + Constants.INVENTORY_ANNOUNCEMENTS,
                                       CollaborationType = 'Public'));        
    }

    /**
     * @name CreateProducts
     * @description Constructs a list of Product2 records for unit tests
    **/
    public static List<Product2> ConstructProducts(Integer cnt){
        for (Schema.PicklistEntry fam : Constants.PRODUCT_FAMILY){

        }
        //ToDo: Ensure this method returns a list, of size cnt, of uniquely named Product2 records
        //  with all the required fields populated
        //  and IsActive = true
        //  an Initial Inventory set to 10
        //  and iterating through the product family picklist values throughout the list.
        List<Product2> products = new List<Product2>();
        Integer i = 0;
        for (Integer x = 0; x < cnt; x++ ){
            if (i > Constants.PRODUCT_FAMILY.size() -1 ) i = 0;            
            Product2 p = new Product2(Name = 'product' + x,
                                      Initial_Inventory__c = 10,
                                      IsActive = true,
                                      Family = Constants.PRODUCT_FAMILY[i].getLabel());
            i++;                          
            products.add(p);
        }
        return products;
    }

    /**
     * @name CreatePricebookEntries
     * @description Constructs a list of PricebookEntry records for unit tests
    **/
    public static List<PricebookEntry> ConstructPricebookEntries(List<Product2> prods){

        //ToDo: Ensure this method returns a corresponding list of PricebookEntries records
        //  related to the provided Products
        //  with all the required fields populated
        //  and IsActive = true
        //  and belonging to the standard Pricebook
        List<PricebookEntry> pbentries = new List<PricebookEntry>();
        for (Product2 p : prods){
            PricebookEntry pb = new PricebookEntry(IsActive = true,
                                       UnitPrice = 10,
                                       Pricebook2Id = Constants.STANDARD_PRICEBOOK_ID,
                                       Product2Id = p.Id);
            pbentries.add(pb);                           
        }
        return pbentries;
    }

    /**
     * @name CreateAccounts
     * @description Constructs a list of Account records for unit tests
    **/
    public static List<Account> ConstructAccounts(Integer cnt){
        //ToDo: Ensure this method returns a list of size cnt of uniquely named Account records
        //  with all of the required fields populated.
        List<Account> accounts = new List<Account>();
        for (Integer x=0; x<cnt; x++) {
            Account acc = new Account(Name = 'account ' + x);
            accounts.add(acc);
        }
        return accounts;
    }

    /**
     * @name CreateContacts
     * @description Constructs a list of Contacxt records for unit tests
    **/
    public static List<Contact> ConstructContacts(Integer cnt, List<Account> accts){
        //ToDo: Ensure this method returns a list, of size cnt, of uniquely named Contact records
        //  related to the provided Accounts
        //  with all of the required fields populated.
        List<Contact> contacts = new List<Contact>();
        Integer y = 0;
        for (Integer x = 0; x < cnt; x++){
            if (y > accts.size() - 1) y = 0;
            Contact c = new Contact(FirstName = 'cont'+y,
                                    LastName = 'Last ' + y,
                                    AccountId = accts[y].Id );
            contacts.add(c);                        
            y++;
        }
        return contacts;
    }

    /**
     * @name CreateOrders
     * @description Constructs a list of Order records for unit tests
    **/
    public static List<Order> ConstructOrders(Integer cnt, List<Account> accts){
        //ToDo: Ensure this method returns a list of size cnt of uniquely named Order records
        //  related to the provided Accounts
        //  with all of the required fields populated.
        Integer y = 0;
        List<Order> orders = new List<Order>();
        for (Integer x = 0; x < cnt; x++) {
            if (! (y < accts.size())) y = 0;
            Order ord = new Order(AccountId = accts[y].Id,
                                  PriceBook2Id = Constants.STANDARD_PRICEBOOK_ID,
									Name = 'order '+ x,
                                    Status = Constants.DRAFT_ORDER_STATUS,
                                    EffectiveDate = date.today());
            orders.add(ord); 
            y++;               
        }
        return orders;
    }

    /**
     * @name CreateOrderItems
     * @description Constructs a list of OrderItem records for unit tests
    **/
    public static List<OrderItem> ConstructOrderItems(integer cnt, list<pricebookentry> pbes, list<order> ords){
        //ToDo: Ensure this method returns a list of size cnt of OrderItem records
        //  related to the provided Pricebook Entries
        //  and related to the provided Orders
        //  with all of the required fields populated.
        //  Hint: Use the DEFAULT_ROWS constant for Quantity as it will be used in the next challenge
        List<OrderItem> orditems = new List<OrderItem>();
        Integer y = 0;
        for (Integer x = 0; x < cnt; x++) {
            if (y > pbes.size() - 1) y = 0;
            OrderItem oi = new OrderItem(OrderId = ords[y].Id,
                                            PricebookEntryId = pbes[y].Id,
                                            Quantity = Constants.DEFAULT_ROWS,
                                            UnitPrice = 1);
            orditems.add(oi);
            y++;
        }
        return orditems;
    }

    /**
     * @name SetupTestData
     * @description Inserts accounts, contacts, Products, PricebookEntries, Orders, and OrderItems.
    **/
    public static void InsertTestData(Integer cnt){
        //ToDo: Ensure this method calls each of the construct methods
        //  and inserts the results for use as test data.
        CollaborationGroup cg = ConstructCollaborationGroup();
        insert cg;
        system.debug('inserted CollaborationGroup');
        List<Product2> prods = ConstructProducts(cnt);
        insert prods;
        system.debug('inserted products');
        List<PricebookEntry> pbes = ConstructPricebookEntries(prods);
        try {
            insert pbes;
            system.debug('inserted PriceBookEntries');
        } catch (Exception e) {
            system.debug('exception: ' + e.getMessage());
        }
        List<Account> accts = ConstructAccounts(cnt);
        insert accts;
        system.debug('inserted Accounts');
        List<Contact> conts = ConstructContacts(cnt, accts);
        insert conts;
        system.debug('inserted Contacts');
        List<Order> orders = ConstructOrders(cnt,accts);
        insert orders;
        system.debug('inserted orders');
        List<OrderItem> ordItems = ConstructOrderItems(cnt, pbes, orders);
        insert ordItems;
        system.debug('inserted OrderItems');
    }
    
    public static void VerifyQuantityOrdered(Product2 originalProduct, Product2 updatedProduct, Integer qtyOrdered) {
        system.debug('Original Product.quantity = ' + originalProduct.Quantity_Ordered__c);
        system.debug('qtyOrdered = '+ qtyOrdered);
        system.debug('updated product.quantity = ' + updatedProduct.Quantity_Ordered__c);
        
        system.assertEquals(qtyOrdered, updatedProduct.Quantity_Ordered__c - originalProduct.Quantity_Ordered__c );
    }

}

 
This is in Step 5 of the Superbadge. here is my test class
@isTest
private class OrderTests {
	@TestSetup   
    static void SetupTestData(){
        TestDataFactory.InsertTestData(5);
    }

    @isTest
    static void OrderUpdate_UnitTest(){
        //retrieve the orders saved by TestDataFactory
        Map<Id, Order> orders= new Map<Id, Order>([SELECT Id, Status FROM Order]);
        //save the original Product2 record in a map
        Map<Id, Product2> originalProductMap = new Map<Id, Product2>();
        //Loop through a query of OrderItems related to the orders
        List<OrderItem> items = [SELECT Id, Product2Id, Product2.Quantity_Ordered__c, Quantity
                                 FROM OrderItem
                                 WHERE OrderId IN :orders.keySet()];
        //ToDo: Populate the map with the Id of the related Product2 as the key and Product2 record as the value
        for ( OrderItem oi : items){
            Product2 p = oi.Product2;
            if (!originalProductMap.containsKey(p.Id)) {
                originalProductMap.put(p.Id, p);
            } 
        }
        //update the Status of the orders
        List<Order> updatedOrders = new List<Order>();
        for (Order order : orders.values()) {
            order.Status = Constants.ACTIVATED_ORDER_STATUS;
            updatedOrders.add(order);
        }
        //get the amounts to be order for each Product
        //declare a map to save the Amounts for each product
        Map<Id, Integer> prodAmounts = new Map<Id, Integer>();
        //get the aggregated amounts by product id
        AggregateResult[] groupedResults  = [SELECT Product2Id,SUM(Product2.Quantity_Ordered__c), SUM(Quantity) FROM OrderItem
                                             WHERE Product2Id IN :originalProductMap.keySet() 
                                             GROUP BY Product2Id];
        for (AggregateResult ar : groupedResults)  {
             prodAmounts.put(String.valueOf(ar.get('Product2Id')),Integer.valueOf(ar.get('expr1')));
        }                                     
        //update the orders in the DB
        update updatedOrders;
        //retrieve the products affected by the orders update
        Map<Id, Product2> updatedProductMap = new Map<Id, Product2>([SELECT id, Quantity_Ordered__c 
                                                                     FROM Product2 WHERE
                                                                     id IN :originalProductMap.keySet()]);
        for (Product2 origProd : originalProductMap.values()) {
            TestDataFactory.VerifyQuantityOrdered(origProd,updatedProductMap.get(origProd.Id), prodAmounts.get(origProd.Id));
        }
    }
}

Can anyone tell me why I am getting that error? my tests are running fine and I have enough code coverage on the extension, the order trigger and the order helper (which is what this step is about).

What am I missing? I have tried to chang @IsTest for TestMethod, but it still doesn't work.
Hi,
I have a method shown below 
    @RemoteAction @ReadOnly
    public static list<SelOption> getOwner(String params){
        map<String, String> values = (Map<String, String>) JSON.deserialize(params, map<String, String>.class);
        string searchTerm = String.ValueOf(values.get('q')).trim();
        if (searchTerm.contains('*')) 
            searchTerm =  searchTerm.replace('*','%');
        if (!searchTerm.endsWith('%')) 
            searchTerm = searchTerm + '%';
        list<SelOption> retVal = new list<SelOption>();
        for (User__c avc : [SELECT Name,job_title__c,email__c,Manager_Lookup__r.Name,office_location_2__c,Employee_Number__c
                                from User__c where name like :searchTerm and salesforce_user_account__c !=:UserInfo.getUserId() and job_status__c = 'Active']){
                                    retVal.add(new SelOption(tmn));
                                }
        return retVal;
    }

Workaround: I need to change the method to global but it is not allowing to change because global methods do not support return type of List. Any sugesstions that is helpful.
Hello, I have a visualforce page:
<apex:page lightningStylesheets="true"   standardController="Contact" extensions="LCN01_ContactFoundCTI" action="{!LCN01_ContactFoundCTI1}"> 
</apex:page>
Below its apex class:
public with sharing class LCN01_ContactFoundCTI{
    String conId;
    String stdcon;
    String phone;
    public Contact con {get;set;}
    
 public LCN01_ContactFoundCTI(ApexPages.StandardController stdcon) {
        phone = ApexPages.CurrentPage().getParameters().get('phone');
     system.debug('phone '+phone);
        if (conId != null && conId != '') // if id is in url means record is for edit 
            con = (Contact) stdcon.getRecord();
        else // else you r gonna create new record
            con = new Contact();
    }
         
    public PageReference LCN01_ContactFoundCTI1(){
        string contactphone;
        string contid;
        string decode;
      
        String phone = System.currentPageReference().getParameters().get('phone');
        string UrlGeodis = label.LABS_SF_UrlGeodis;
        string UrlContactNonExistant = label.LABS_SF_LCUrlContactNonExistant;
		 String strAssumptionFloodOnlyUrl;
        system.debug('phone  '+phone);
         try {           
            contactphone= '+' +phone;           
            contactphone= contactphone.replaceAll( '\\s+', '');
            system.debug('phone2 '+contactphone);
            //Recupetation Contact Id
            list<Contact> cont = [SELECT id, Name from Contact where Phone = :contactphone or MobilePhone= :contactphone  ];  
              list<Delegue__c> Deleguee = [SELECT id, Name from Delegue__c where Telephone__c = :contactphone  ]; 
            string today = date.today().format();
            system.debug('cont  '+cont.size());
            system.debug('Deleguee  '+Deleguee.size());
			
            if (cont != null &&  cont.size() == 1 && Deleguee.size() == 0)
            {
              
               task tache = new task(); 
                tache.OwnerId= UserInfo.getUserId() ;
                tache.Subject = 'Appel Entrant ' +today;
                tache.WhoId	= cont[0].id; 
                contid = cont[0].id; 
                system.debug('contact existant');
                insert tache; 
                system.debug('tache id  '+tache.id);
                
		        strAssumptionFloodOnlyUrl =UrlGeodis + '/r/Contact/'+contid+'/view';
            } 
            else if (Deleguee != null &&  Deleguee.size() == 1 && cont.size() == 0)
            {
               
				task tache = new task(); 
                tache.OwnerId= UserInfo.getUserId() ;
                tache.Subject = 'Appel Entrant ' +today;
                tache.WhoId	= Deleguee[0].id; 
                contid = Deleguee[0].id; 
                system.debug('Deleguee existant');   
              	
	           strAssumptionFloodOnlyUrl =UrlGeodis + '/r/Delegue__c/'+contid+'/view';
				
            } 
             else if (Deleguee.size() == 0 && cont.size() == 0) {
                   system.debug('ContactNotFound');
                 strAssumptionFloodOnlyUrl= UrlContactNonExistant;
                         }
		   // si il y a plusieurs contacts ou plusieurs délégués
            else  {
                system.debug('plusieurscontacts');
                //decode   
                string decode1 ='{"componentDef":"forceSearch:searchPage","attributes":{"term":"' +phone+'","scopeMap":';
                string decode2 ='{"resultsCmp":"forceSearch:resultsTopResults","label":"Principaux résultats","type":"TOP_RESULTS","cacheable":"Y","id":"TOP_RESULTS","labelPlural":"Principaux résultats"}}}';
                
                Decode = decode1 +    decode2 ;
                system.debug('Decode '+Decode); 
                
                // create a blob from our parameter value before we send it as part of the url
                Blob beforeblob = Blob.valueOf(Decode);                
                // base64 encode the blob that contains our url param value
                string paramvalue = EncodingUtil.base64Encode(beforeblob);
                system.debug('paramvalue  '+paramvalue);
                // print out the encoded value to the debug log so we can see it before/after base64 encode
                System.debug(Decode + ' is now encoded as: ' + paramvalue);                    
               
               string Searchlabel = label.LABS_SF_Global_Search +paramvalue ;
			   strAssumptionFloodOnlyUrl= label.LABS_SF_Global_Search +paramvalue ;
               contid =  Searchlabel;              
            }				 
		          
          PageReference newFloodOnlyUrl = new PageReference(strAssumptionFloodOnlyUrl);
          newFloodOnlyUrl.setRedirect(true);
          return newFloodOnlyUrl;          
            
        }
        catch(Exception ex){ 
        system.debug('erreur  '+ex);         
        return null;          
            
        }
    }
   
 
}
I created a test class but it does not cover the class:
@isTest
public class LCN01_ContactFoundCTITest {
    public static testMethod void testContact() {   
        test.startTest();
          PageReference pageRef = Page.VF01_ContactFoundCTI;
          Account acc = new Account(Name='Abce');
          insert acc;
          
          Contact  testContact = new Contact();
          testContact.lastname='testcontact';
          testContact.AccountId=acc.id;
          testContact.phone='+33612345690';
          
           insert testContact;
           Test.setCurrentPage(pageRef);
           pageRef.getParameters().put('id',testContact.id);
           ApexPages.StandardController sc = new ApexPages.standardController(testContact);
           LCN01_ContactFoundCTI  controller = new LCN01_ContactFoundCTI(sc);
         
   
                
       test.stopTest();
        

}
    
}


Can someone help me?
Below is my requirement :

1. 1st component contains a list of records . On clicking any specific record . It should navigate to second component. (1st component is in a lightning page)

2. 2nd Component will contain some custom data as well as data of the record from which it is fired .


---In my case ,  2nd component is not opening  .Could someone please provide a solution . Thanks in Advance
Hi,
I'm using visual force page in community which was not showing for end user although admin can see it the same VF page.

Kindly share your inputs
Hi,

I have a field 'Site' on Users, which gets mapped to Opportunity once the user from that site creates an opportunity.

So , lets say if a user from Site A creates an opportunity , Opportunity will be stamped with Site A.


Now sometimes, there are transfers, so user from Site A gets transferred to Site B, I want to write an apex trigger , whenver a user gets transfferd from Site A to Site B. for All the opportunites created by him  , oppotunity owner should change to Site A manager..( sort of handover)  , Site A store managers role is "Site A".

How can we achieve this
When I change the opportunity stage to "sold" for example, I have a process set up to duplicate the opportunity to a "YOY Event". For some reason it is duplicating it and creating 2 YOY Event opportunities. 

How can I change this to only create 1 YOY Event? I have checked my process builder and do not see anything that indicates to duplicate twice. 
Hi All,
my opportunityTriggerHelper is given below:-
public without sharing class OpportunityTriggerHelper  {
    
    public static List<Opportunity> newOpportunity = new List<Opportunity>();
    public static List<Opportunity> oldOpportunity = new List<Opportunity>();
    public static Map<Id, Opportunity> newMapOpportunity = new Map<Id, Opportunity>();
    public static Map<Id, Opportunity> oldMapOpportunity = new Map<Id, Opportunity>();
    
    public static boolean runTrigger = TRUE;
     public static void populateArrDifference(){
        list<Opportunity> releventOpportunities = new list<Opportunity>();
        for( Opportunity opp : newOpportunity ){
            if( opp.Type == 'Renewal Expansion' && 
              (  trigger.isInsert || ( opp.Type != oldMapOpportunity.get( opp.Id ).Type ))){
                releventOpportunities.add( opp );
            }
        }
        try{
            set<String> oppAcceptedTypes = new set<String>
                                            { 'New Business', 'Renewal', 
                                              'Winback', 'AE Winback (>120 days post exp)' 
                                             };
            set<Id> accountIds = new set<Id>();
            if( releventOpportunities.size() > 0 ){
                for( Opportunity opp : releventOpportunities ){
                    accountIds.add( opp.AccountId );
                }
            }
            
            List<Opportunity> opportunities =  [ SELECT Id, AccountId, Name,
                                                Description, StageName,
                                                ARR_Estimation__c
                                                FROM Opportunity 
                                                WHERE AccountId IN: accountIds
                                                AND StageName = 'Closed Won'
                                                AND Type IN :oppAcceptedTypes
                                                ORDER BY CreatedDate DESC 
                                               ];
            
            map<Id, Opportunity> mapAccountIdToArrEstimation = new map<Id, Opportunity>();
            if( opportunities.size() > 0 ){
                for( Opportunity opp : opportunities ){
                    if( ! mapAccountIdToArrEstimation.containsKey( opp.AccountId ) ){
                        mapAccountIdToArrEstimation.put( opp.AccountId, opp );
                    }
                }
            }
            
            list<Opportunity> opportunityToUpdate = new list<Opportunity>();
            for( Opportunity opp : releventOpportunities ){
                if( mapAccountIdToArrEstimation.containsKey( opp.AccountId ) ){
                    opp.Recent_Closed_Won_Opportunity__c = mapAccountIdToArrEstimation.get( opp.AccountId ).Id;
                }
            }
            
        }
        catch( Exception e ){
            releventOpportunities.get(0).addError( e.getMessage() );
        }
        
    }
    }
 how to write test class for it?
 Any suggestions?
Hello,

I have a visualforce page that contains a button and I need to put the hidden button and execute the action of the button at the opening of the page.

Can someone help me.
Hello,

I am trying to increase my code coverage and I have to  test my http callouts that are located within the controller. I have been able to test http callouts if they are located in their own static method that returns an http response but I have trouble when it is anywhere else.
 
This is the method for the controller that is executed automatically on page load. I set variables equal to the response of the methods that contain the actual http callouts. 
public HTTPResonse M_AccountMatchesLastName_Brighton;
public HTTPResonse M_AccountMatchesLastName_Decatur;

public Mitchell_Account(ApexPages.StandardController controller) {   
        SF_Account =  (Account) controller.getRecord();
        SF_AccountID = ApexPages.currentPage().getParameters().get('id');
       
                
    
            M_AccountMatchesLastName_Brighton = M_SearchContacts(sAuthentication, sAPIKey, sConnectionID, 'test');
            
            M_AccountMatchesLastName_Decatur = M_SearchContacts(sAuthentication, sAPIKey, sConnectionID, 'test');                                                     
}

 I will have to test multiple variables that are equal to the http response of the method that performs the callout.

Here is the method that is called and actually performs the request:
 
public static HttpResponse M_SearchContacts(String authentication, String apiKey, String connectionId, String keyword){
       
        HttpRequest req = new HttpRequest();
       
        req.setEndpoint(sCalloutEndPoint  +''+keyword);
        req.setMethod('GET');
       
        req.setHeader('cache-control', 'no-cache');
        req.setHeader('Accept', 'application/json');
        req.setHeader('authentication', Authentication);
        req.setHeader('apiKey', apiKey);
        req.setHeader('connectionId', connectionID);
 
        Http http = new Http();
        HTTPResponse res = http.send(req);  
        return res;   
    }


 I have been able to successfully test the M_SearchContacts method by itself but I am not able to test it when setting a variable equal to its response.
 
@isTest
public class Test_Mitchell_Account{
   
 
    @isTest
    static void Test_Controller(){

  Account acct = new Account(Name='test', 
                                   Phone='test',
                                   BillingCity='test',
                                   BillingState='test',
                                   BillingStreet='test',
                                   BillingPostalCode='test',
                                   BillingCountry='test',
                                   Mitchell_ID__c='a743b6e1-6b50-4a00-be85-88811b19dd0c',
                                   Mitchell_Details__c='a743b6e1-6b50-4a00-be85-88811b19dd0c');
        insert acct;  
        

        ApexPages.currentPage().getParameters().put('id',acct.id);        
       
       
        ApexPages.StandardController sc = new ApexPages.StandardController(acct);
        Mitchell_Account Instance_Mitchell_Account = new Mitchell_Account(sc);

Test.setMock(HttpCalloutMock.class, new MockController());
       
        HttpResponse response = Instance_Mitchell_Account.M_AccountMatchesLastName_Brighton;
 
       
        String contentType = response.getHeader('Content-Type');
        System.assert(contentType == 'application/json');
        String actualValue = response.getBody();
        System.debug(response.getBody());
        String expectedValue ='I have removed the expected value as it is lengthy';
        System.assertEquals(actualValue, expectedValue);
        System.assertEquals(200, response.getStatusCode());
 
       
    }


 
 
And I try to use this mock callout class. I have the conditional statement in there since I will be performing multiple http callouts in the controller method above.
 
 
@isTest
global class MockController implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest req) {
        // Create a fake response
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setHeader('cache-control', 'no-cache');
       
                if (req.getEndpoint().startsWith(sCalloutEndPoint)) {
                    HTTPResponse res = new HTTPResponse();
                    res.setBody('I have removed the expected value as it is lengthy');
                    res.setStatusCode(200);
                    return res;
                } else if (req.getEndpoint().startsWith(sCalloutEndPoint) && req.getEndpoint().contains('/Invoice')) {
                    HTTPResponse res = new HTTPResponse();
                    res.setBody('I have removed the expected value as it is lengthy');
                    res.setStatusCode(200);
                    return res;
                } else {
                    System.assert(false, 'unexpected endpoint ' + req.getEndpoint());
                    HTTPResponse res = new HTTPResponse();
                    return res;
                }
    }
   
}


 
I am receiving the error: Methods defined as TestMethod do not support Web service callouts
 
I am not entirely sure if I am trying to test this properly or if I need to take a different approach. Please do not feel obligated to help! But any help is appreciated



Thank you for any sort of help!
I have two components, both working in a Record Page. The record has a master-detail relationship to a custom object.
component 1 adds a record to the object (detail)
component 2 lists all the detail records related to the RecordId.

The work separately, but when I add the PUBSUB and the extra imports (page reference & pubsub) I am getting an error when I try to deploy the code to the dev-org. 

The error says:
The component must implement at least one of lightning__RecordPage interface.
Both components have the <target>lightning__RecordPage</target> in the metadata file, and as stated above they work fine withouth the PUBSUB code.

Any one knows what might be going on?
also, the dev-org is running on v. Summer 19 
public class Colors {
    public string colors;
    public List<string> myList;
    public set<string> newList;
    
    public colors(){
        myList=new List<string>{'Blue','Blue violet','Red','Green','Dark Red','Light Red','Orange Red','Coral Red',
            'Forest Green','Hunter Green','Sage Green','Black','Red','Orange','Yellow','Blue violet'};
                system.debug(myList.size()); 
 newList=new set<string>();
        newList.addAll(myList);
        system.debug(newList);
}