• Yogesh Biyani
  • NEWBIE
  • 85 Points
  • Member since 2015

  • Chatter
    Feed
  • 0
    Best Answers
  • 3
    Likes Received
  • 0
    Likes Given
  • 68
    Questions
  • 63
    Replies
How I insert a related object using the external id field on the parent object?

I have a custom parent object License__c and related object Activation__c which have a Related_License__c lookup field to the License__c object and the relations ship name is License Activations.

License__c has l_id__c external id field. I would like to import the Activation__c object using the l_id__c field so that the parent-child relationship is automatically created.

This works using the data import wizard but fails when I try to import use the Bulk Api 1.0 

Here is the sample CVS file 

Activation_Id__c,License_Activations__r.l_id__c 
9249,1665029 
9250,1665029 
I have created a class to parse text data and want to use Static Resource (text file) to import the data for testing. How do I use test.loaddata so that it is imported as a String?  
I am currently using Apex to query an endpoint and parse the JSON result. I am making a call to an endpoint with consumer key/secret to get the access token and then using the token to query the final endpoint as shown in the code below.

I would like to convert this to External Service so that I can use it in a flow. Can someone give me detailed steps on how to convert this to external service? 

TIA.
public static void findidbyEmail(String email)
    {
        String idAPIKeyString = 'KEY:SECRET';
        
        Blob idBlob = Blob.valueof(idAPIKeyString);
        
        String idAuthorization = 'basic ' + EncodingUtil.base64Encode(idBlob);
        HttpRequest idRequest = new HttpRequest();
        
        idRequest.setEndpoint('https://api.sitename.com/token');
        idRequest.setMethod('POST');
        
        idRequest.setBody('grant_type=client_credentials');
        idRequest.setHeader('Authorization', idAuthorization);
        idRequest.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        
        Http http = new Http();
        
        HTTPResponse res = new HTTPResponse();
        
        if (Test.isRunningTest() && (mock!=null)) {
            System.debug('Mock Response');
            res = mock.respond(idRequest);
            
        } else {
            System.debug('Callout Response');
            res= http.send(idRequest);
            
        }
        
        
        System.debug(res.getBody());     
        
        
        idAuthorizationJSON2Apex objidAuthJSON2Apex = new idAuthorizationJSON2Apex(System.JSON.createParser(res.getBody()));
        System.debug(objidAuthJSON2Apex.access_token);
  
        String access_token= objidAuthJSON2Apex.access_token;
        system.debug(access_token);
        
        
        //    Get the id        
        HttpRequest req2= new HttpRequest();
        
        req2.setEndpoint('https://api.sitename.com/users?email='+email);
        req2.setMethod('GET');
        req2.setHeader('Authorization', 'bearer '+ access_token);
        
        req2.setHeader('Content-Type', 'application/json');
        
        Http http2 = new Http();
        
        HTTPResponse res2 = new HTTPResponse();
        
        if (Test.isRunningTest() && (mock!=null)) {
            res2 = mock.respond(req2);
            System.debug('Mock Response ' + res2);
        } else {
            res2= http.send(req2);
            System.debug('Callout Response '+res2);
        }
        
        
        if(res2.getBody()=='')
            System.debug('id Not found');
        else 
        {
            System.debug(res2.getBody());
            System.debug('id found');
            idJSON2Apex objidJSON2Apex = new idJSON2Apex(System.JSON.createParser(res2.getBody()));
            System.debug(objidJSON2Apex.theEmail.uniqueid);
           
        } 
    }

 
This test fails with the above message 
 
@isTest
public class AmplitudeApiCallsTest {

    @testSetup static void setup() {
        // Create common test accounts
        List<Account> testAccts = new List<Account>();
        for(Integer i=0;i<2;i++) {
            testAccts.add(new Account(Name = 'TestAcct'+i,Account_FCH_Id__c= '123456789'+i));
            
        }
        insert testAccts;        
    }

    @isTest
     public static void  AmplitudeCallOut()
    {
       
        
        String fakeAmplitudejson = '{\"novaRuntime\": 309, \"minSampleRate\": 1.0, \"throttleTime\": 2, \"partialMergedAndNewUserInformation\": false, \"timeComputed\": 1584390210280, \"wasCached\": false, \"backend\": \"novaV2\", \"realtimeDataMissing\": false, \"novaRequestDuration\": 378, \"queryIds\": [\"OwY0CjZuIC\"], \"hitChunkGroupByLimit\": false, \"prunedResult\": false, \"transformationIds\": [], \"novaCost\": 900, \"subcluster\": 3, \"timedOutRealtimeData\": false, \"data\": {\"seriesIntervals\": {}, \"seriesCollapsed\": [[{\"setId\": \"\", \"value\": 72002}]], \"xValues\": [\"2019-01-01\", \"2019-02-01\", \"2019-03-01\", \"2019-04-01\", \"2019-05-01\", \"2019-06-01\", \"2019-07-01\", \"2019-08-01\", \"2019-09-01\", \"2019-10-01\", \"2019-11-01\", \"2019-12-01\", \"2020-01-01\", \"2020-02-01\", \"2020-03-01\"], \"seriesLabels\": [0], \"series\": [[1, 2334, 6194, 9963, 13706, 16731, 20586, 23982, 27697, 32154, 34940, 36863, 44026, 48629, 43613]]}, \"cacheFreshness\": \"FRESH\"}';
        SingleRequestMock fakeAmplitudeResponse = new SingleRequestMock(200,
                                                                      'Complete',
                                                                      fakeAmplitudejson,
                                                                      null);
        Test.setMock(HttpCalloutMock.class, fakeAmplitudeResponse);
        
     
    
        List<Account> acc1=[Select id,Account_FCH_Id__c from Account Where Account_FCH_Id__c='1234567891' LIMIT 1];
		system.debug(AmplitudeApiCalls.dataForChartId(acc1[0].id));
        
        List<Account> acc2=[Select id,Account_FCH_Id__c from Account Where Account_FCH_Id__c='' LIMIT 1];
        system.debug(AmplitudeApiCalls.dataForChartId(acc2[0].id));
      
        
    }
}

 
I tried the following today in apex anonymous window and I see an unexpected behavior 
System.debug(Datetime.now());
System.debug(Datetime.now().format('YYYY-MM-DD'));
Why id the DD 84 when I use System.debug(Datetime.now().format('YYYY-MM-DD'))? 
13:09:14.1 (2508337)|USER_DEBUG|[1]|DEBUG|2020-03-24 19:09:14
13:09:14.1 (2587013)|USER_DEBUG|[2]|DEBUG|2020-03-84
Based on this (https://success.salesforce.com/answers?id=9063A000000pzg0QAA) I have created a chart LWC but I have to always resize my window for the chart to display it correctly. What am I doing wrong? TIA.

Here is the Apex Class 
public with sharing class TestData {
     @AuraEnabled(cacheable=true)
    public static Map<String,Integer> dataForChartSample() {
        
       Map<String,Integer> chartData= new Map<String,Integer>();
       for (integer i =0;i< 10; i++)
       {
           chartData.put(String.valueOf(i),Integer.valueof((math.random() * 10)));
       }
       system.debug(chartData);
       return chartData;
    }
}

Here is the component js 
 
import { LightningElement,wire,track } from "lwc";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import { loadScript } from "lightning/platformResourceLoader";
import ChartJS from "@salesforce/resourceUrl/ChartJS";
import dataForChart from "@salesforce/apex/TestData.dataForChartSample";


export default class ChartDemo extends LightningElement {
    @track mapData= [];
    cLabel=[];
    cData=[];

    @wire(dataForChart)
    wiredResult(result) { 
        if (result.data) {
            //mapData = [];
            var conts = result.data;
            for(var key in conts){
                this.cLabel.push(key);
                this.cData.push(conts[key]);
            }

        }
    }
    
    chartJSLoaded;
    chart;

    constructor() {
        super();
        this.chartJSLoaded = false;
    }

    renderedCallback() {
        if (!this.chartJSLoaded) {
            loadScript(this, ChartJS)
                .then(() => {
                    this.chartJSLoaded = true;
                    var labels1=this.cLabel;
                    var data1=this.cData;
                    console.log( "This is the Label");
                    console.log(labels1);
                    console.log( "This is the Data");
                    console.log(data1);
                    
                    this._buildChart2(labels1,data1);
                })
                .catch(error => {
                    this.dispatchEvent(
                        new ShowToastEvent({
                            title: "Error Loading Chart JS",
                            message: error.message,
                            variant: "error"
                        })
                    );
                });
        }
    }

    _buildChart2(labels1,data1) {
        let canvas = this.template.querySelector("canvas");
        let context = canvas.getContext("2d");

        this.chart = new window.Chart(context, {
            type: "bar",
            data: {
                labels: labels1,
                datasets: [
                    {
                        label: "# of activations",
                        data: data1,
                        borderWidth: 1
                    }
                ]
            },
            options: {
                scales: {
                    yAxes: [
                        {
                            ticks: {
                                beginAtZero: true
                            }
                        }
                    ]
                }
            }
        });
    }

    _buildChart() {
        let canvas = this.template.querySelector("canvas");
        let context = canvas.getContext("2d");

        this.chart = new window.Chart(context, {
            type: "bar",
            data: {
                labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
                datasets: [
                    {
                        label: "# of Votes",
                        data: [12, 19, 3, 5, 2, 3],
                        backgroundColor: [
                            "rgba(255, 99, 132, 0.2)",
                            "rgba(54, 162, 235, 0.2)",
                            "rgba(255, 206, 86, 0.2)",
                            "rgba(75, 192, 192, 0.2)",
                            "rgba(153, 102, 255, 0.2)",
                            "rgba(255, 159, 64, 0.2)"
                        ],
                        borderColor: [
                            "rgba(255, 99, 132, 1)",
                            "rgba(54, 162, 235, 1)",
                            "rgba(255, 206, 86, 1)",
                            "rgba(75, 192, 192, 1)",
                            "rgba(153, 102, 255, 1)",
                            "rgba(255, 159, 64, 1)"
                        ],
                        borderWidth: 1
                    }
                ]
            },
            options: {
                scales: {
                    yAxes: [
                        {
                            ticks: {
                                beginAtZero: true
                            }
                        }
                    ]
                }
            }
        });
    }
}

component html
<template>
    <div class="slds-theme_default">
        <canvas width="400" height="400" lwc:dom="manual"></canvas>
    </div>
</template>

compoment xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>46.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
      <target>lightning__RecordPage</target>
      <target>lightning__AppPage</target>
      <target>lightning__HomePage</target>
  </targets>
</LightningComponentBundle>

 
I have converted the following python script to apex code and I get the HTTP 405 method not allowed error. Can someone review and let me know what is wrong? 

Python  
url = 'https://amplitude.com/api/2/events/segmentation'

# json parameters for querying monthly uniques for Launched App  between dates
# Add gp: in front of custom user_property
params1 = {
    'e': '{"event_type":"Launched Application","filters":[{"subprop_type":"user","subprop_key":"gp:app_name","subprop_op":"is","subprop_value":["su-desktop"]}, \
         {"subprop_type":"user","subprop_key":"gp:sku","subprop_op":"contains","subprop_value":["PRO"]}]}',
    'm': 'uniques',
    'start': '20190101',
    'end': '20200131',
    'i':'30'
}

# Set to -300000, -3600000, 1, 7, or 30 for real-time, hourly, daily, weekly, and monthly counts,



r = requests.get(url, params = params1,  auth=(api_key, secret_key))
response = r.json()
print( response)
#print r.status_code
#print r.url
Apex
 
HttpRequest req4= new HttpRequest();
req4.setEndpoint('https://amplitude.com/api/2/events/segmentation');
req4.setMethod('GET');
Blob myBlob1 = Blob.valueof(api_key + ':'+ secret_key);
String authorizationHeader = 'Basic ' + EncodingUtil.base64Encode(myBlob1);
req4.setHeader('Authorization', authorizationHeader);

String params1='{"e": "{\"event_type\":\"Launched Application\",\"filters\":[{\"subprop_type\":\"user\",\"subprop_key\":\"gp:app_name\",\"subprop_op\":\"is\",\"subprop_value\":[\"su-desktop\"]},{\"subprop_type\":\"user\",\"subprop_key\":\"gp:sku\",\"subprop_op\":\"contains\",\"subprop_value\":[\"PRO\"]}]}","end": "20200131","i": "30","m": "uniques","start": "20190101"}';


req4.setBody(params1);

Http http4 = new Http();
HTTPResponse res4 = http4.send(req4);
System.debug(res4.getBody());
How do I convert the following python code into json body to be sent with the HTTP request? 

TIA

 
params1 = {
        'e': '{"event_type":"Launched Application","filters":[{"subprop_type":"user","subprop_key":"gp:app_name","subprop_op":"is","subprop_value":["desktop"]}, \
             {"subprop_type":"user","subprop_key":"gp:sku","subprop_op":"contains","subprop_value":["SPEC"]}]}',
        'm': 'uniques',
        'start': '20190101',
        'end': '20200131',
        'i':'30'
    }

 
We are using this toolkit to allow the customer to submit cases and are using the Attachment object to submit relevant files. Does anyone have a sample that shows how to use Salesforce Files? 
What is the SOQL to find all the subscribed/scheduled dashboards? 
I am a bit confused about the relationship between Task and EmailMessage objects.

One can find the Task from EmailMessage using ActivityId but not sure how to get the EmailMessage from Task. Can someone show how to get the EmailMessage from the Task object? 
A custom object is associated with account and contact via a lookup field.  Is it possible to find all accounts and contacts of all the custom object records which are updated using a SOQL query? 
Here is the Apex Class
public class AssignLeadsUsingAssignmentRules
{
    @InvocableMethod
    public static void LeadAssign(List<Id> LeadIds)
    {
            Database.DMLOptions dmo = new Database.DMLOptions();
            dmo.assignmentRuleHeader.useDefaultRule= true;          
            Lead Leads=[select id,OwnerId from lead where lead.id in :LeadIds];
            Leads.setOptions(dmo);
        	system.debug('Before Update Lead Details' + Leads);
         	Database.update(Leads,dmo);
        	Lead Leads2=[select id,OwnerId from lead where lead.id in :LeadIds];
        	system.debug('After Update Lead Details' + Leads2);
   }
}

Here is the test class 
@isTest 
      public class TestAssignLeadsUsingAssignmentRules{
      static testMethod void createnewlead() {
     
   //   Test.startTest();    
      Lead leadToCreate =new Lead();
      List<id> Ids= New List<Id>();
    //  leadToCreate.ownerid= userToCreate.id;
      leadToCreate.ownerid= UserInfo.getUserId();  
      leadToCreate.LastName ='Sample1';
      leadToCreate.Email='Someone@somewhere.com';
      leadToCreate.Company='OneTwo34';
      leadToCreate.LeadSource='Partner Referral';
      leadToCreate.Country='IN';
      leadToCreate.Source_Last_Lead_Source_Detail__c='Form - Contact Form';
          
      insert leadToCreate; 
      
      Ids.add(leadToCreate.id);
      AssignLeadsUsingAssignmentRules.leadAssign(Ids);
      System.assertEquals('00G1W000002RyhMUAS', leadToCreate.OwnerId, 'Something is wrong');

 	//  Test.stopTest();
      
   }
}

The test class fails as shown below User-added imageAs you can see the debug log shows the lead OwnerId has changed but the change does not persist outside the class in the test. What am I missing? 
We have some accounts with incorrect account team and the following query identifies all such accounts. Basically, accounts with two or more account team members with the Distributor role has incorrect teams.
Select AccountId, Account.Name, count(id) from AccountTeamMember WHERE TeamMemberRole ='Distributor License Share' AND UserId!='0051W000004SVNhQAO' Group BY AccountId, Account.Name HAVING count(id) >=2 LIMIT 2000
What is the easiest way to delete all such account teams? 

I am still learning Apex/SOQL; how do I collect the AccountIds from the above aggregate result and pass it to get all the AccountTeamMember IDs to delete? The following code in developer console fails with the following error

Invalid identifier ' '. Apex identifiers must start with an ASCII letter (a-z or A-Z) followed by any number of ASCII letters (a-z or A-Z), digits (0 - 9), '$', '_'.​​​​​​​
List<AggregateResult> results =  [Select  AccountId, Account.Name, count(id) from AccountTeamMember 
                      WHERE TeamMemberRole ='Distributor License Share' AND UserId!='0051W000004SVNhQAO' 
                      Group BY AccountId, Account.Name HAVING count(id) >=2 LIMIT 2000 ];

System.debug(results.size());

System.debug(results[0]);

Set<id > AccountIds = new Set<id>();
      
for(AggregateResult exp: results){
    AccountIds.add((Id)exp.get('AccountId'));
}



 
Currently, we have 8 different triggers on the opportunity class and I am refactoring the code and moving it to a helper class. I am thinking of using the switch statement as shown in this article (https://developer.salesforce.com/blogs/2018/05/summer18-rethink-trigger-logic-with-apex-switch.html). 

Here is the original trigger
 trigger OppPusher on Opportunity (before update) {
Date dNewCloseDate;
Date dOldCloseDate;
Boolean bPushed=false;
for (Opportunity oIterator : Trigger.new) { //Bulk trigger handler so that you can mass update opportunities and this fires for all'
// gets new values for updated rows
dNewCloseDate = oIterator.CloseDate; // get the new closedate
dOldCloseDate = System.Trigger.oldMap.get(oIterator.Id).CloseDate; //get the old closedate for this opportunity
//if different do something.
}
}

Here is the new trigger and class 
trigger OppTriggers  on  Opportunity (    before insert, 
                                           after insert, 
                                           before update, 
                                           after update) {

	OppTriggerHandler.handleTrigger(Trigger.new, Trigger.old, Trigger.operationType);

}

public with sharing class OppTriggerHandler { 
    
    public static void handleTrigger(List<Opportunity> workingRecords, 
                                     List<Opportunity> oldRecords, 
                                     System.TriggerOperation triggerEvent ) {
                                         
                                         
                                         switch on triggerEvent {
                                             
                                             when BEFORE_UPDATE{
                                                 Date dNewCloseDate;
                                                 Date dOldCloseDate;
                                                 Boolean bPushed=false;
                                                 
                                                 for (Opportunity oIterator : workingRecords) { //Bulk trigger handler so that you can mass update opportunities and this fires for all'
                                                     // gets new values for updated rows
                                                     dNewCloseDate = oIterator.CloseDate; // get the new closedate 
                                              	     dOldCloseDate = System.Trigger.oldMap.get(oIterator.Id).CloseDate; //get the old closedate for this opportunity
                                                    //if different do something.
                                                   
                                                 }
                                             }
                                             when AFTER_INSERT, AFTER_UPDATE {
                                                 //create related records
                                             }
                                             when BEFORE_INSERT {
                                                 //set value on record create
                                             }
                                             when AFTER_DELETE {
                                                 //prevent deletion of sensitive data
                                             }
                                             when else {
                                                 //do nothing for AFTER_UNDELETE, BEFORE_DELETE, or BEFORE_UPDATE
                                             }
                                         }
                                     }
}

And the compiler fails with 
Variable does not exist: CloseDate message.

How do I about this error message? 


 
I am trying to mass delete listviews from a test site using the workbench. Here is the destructivechanges.xml 
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <name>ListView</name>
        <members>Case.All_Open_Requests</members>
        <members>Case.All_Open_Requests_Since_2016</members>
        <members>Case.All_Request_Created_Today</members>
    </types>
    <version>44.0</version>
</Package>

Here is the package.xml 
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <version>44.0</version>
</Package>

Both of these are in a zip file changes.zip, and the workbench shows success but it is not deleted for the interface. What am I missing?
 
Here are some examples of fake contacts in our database which we would like to clean. 
User-added image
Here is the current code and as you can tell the credentials are visible to anyone accessing the code. How can we remove it from the code? 
String myString = 'somekey:somepassword';
        
        Blob myBlob = Blob.valueof(myString);
        
        String authorization1 = 'basic ' + EncodingUtil.base64Encode(myBlob);
        HttpRequest req = new HttpRequest();
        
        req.setEndpoint('https://api.somesite.com/token');
        req.setMethod('POST');
        
        req.setBody('grant_type=client_credentials');
        
        req.setHeader('Authorization', authorization1);
        
        req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        
        Http http = new Http();
        
        HTTPResponse res = http.send(req);

I reviewed Named Credentials but am thrown off with the 64 bit encoding requirement. Thanks in advance for your help.

Yogesh
SOQL statements cannot query more than 20 different child types.

So how do I merge the Contacts from two different queries? 

For eg. 
List<Contact> querychilds1 = [select id,Orphan__c ,
                                     (Select id from PrimaryContact__r ),
                                      (Select id from Attachments ),
                                      (Select id from CampaignMembers ),
                                      (Select id from Cases ),
                                      (Select id from CaseContactRoles ) 
                                         and few more totaling to twenty....
                                      from contact 
                                      WHERE id IN :listofcontacts]; 

          List<Contact> querychilds2 = [select id,Orphan__c ,
                                      (Select id from Feeds ),
                                      (Select id from Histories ),
                                      (Select id from DeclinedEventRelations ),
                                      (Select id from DuplicateRecordItems ),
                                      (Select id from EmailMessageRelations ),
                                      (Select id from FeedSubscriptionsForEntity ) 
                                      from contact 
                                      WHERE id IN :listofcontacts];


       
We would like to find all contacts without any relationships in the database and mark them for deletion.  Listing my approach below and am wondering if anyone can comment on the same.  Thank you all in advance. 

Yogesh​

Step 1 - Using the following code to identify all the relationships and the number of each
Schema.SObjectType contactSType = Contact.sObjectType;
Schema.DescribeSObjectResult dsr = contactSType.getDescribe();
string s='';
integer i=0;
for(Schema.ChildRelationship child : dsr.getChildRelationships()) {
    System.debug(i+' '+child.getChildSObject()+'--'+child.getRelationshipName()+'--'+child.getField());

        String query1='select Count_distinct('+child.getField()+ ') from '+child.getChildSObject()
 
        try 
        {   
      
            List<SObject> l=Database.Query(query1);
            integer t=(integer)l[0].get('expr0');
   
		   system.debug('r'+i+'='+ t);
 		   if(t>0)
				s+='r'+i+'='+ t+' '+child.getChildSObject()+'--'+child.getRelationshipName()+'--'+child.getField()+'; ';
       }
        
        catch(Exception e){
            
            System.debug(e.getMessage());
        }

    i++;
}

system.debug(s);

Here are the results
r0=295 AcceptedEventRelation--AcceptedEventRelations--RelationId
r1=424054 Account--Accounts_Contacts__r--Contactconnect__c
r7=112769 Attachment--Attachments--ParentId
r8=4863 CampaignMember--CampaignMembers--ContactId
r10=122885 Case--Cases--ContactId
r17=334394 ContactFeed--Feeds--ParentId
r25=107 DeclinedEventRelation--DeclinedEventRelations--RelationId
r26=1660 DuplicateRecordItem--DuplicateRecordItems--RecordId
r27=31130 EmailMessageRelation--EmailMessageRelations--RelationId
r31=2139 EntitySubscription--FeedSubscriptionsForEntity--ParentId
r32=4142 Event--Events--WhoId
r33=409 EventRelation--EventRelations--RelationId
r37=57 GoogleDoc--GoogleDocs--ParentId
r40=248704 License_With_Order__c--License_Contact__r--l_contact__c
r41=136238 License_With_Order__c--Order_B_Contact__r--o_b_contact__c
r42=245711 License_With_Order__c--Order_C_Contact__r--o_c_contact__c
r43=637 Note--Notes--ParentId
r46=13765 OpportunityContactRole--OpportunityContactRoles--ContactId
r51=8820 Quote--Quotes--ContactId
r54=892 Sertifi2_0__ContractContactJunction__c--Sertifi2_0__Signers__r--Sertifi2_0__Contact__c
r60=27768 Task--Tasks--WhoId
r61=912 TopicAssignment--TopicAssignments--EntityId
r62=239 UndecidedEventRelation--UndecidedEventRelations--RelationId
r65=740 Zendesk__Zendesk_Ticket__c--Zendesk__Zendesk_Tickets__r--Zendesk__Requester__c
r67=3828 simplesurvey__Survey__c--simplesurvey__Surveys__r--simplesurvey__Contact__c

r9=33202 CampaignMember--null--LeadOrContactId
r16=22 Contact--null--ReportsToId
r22=29 ContentVersion--null--FirstPublishLocationId
r34=6542 FeedComment--null--ParentId
r38=160901 Lead--null--ConvertedContactId
Step 2.  Create a batch process to find each record without such relationships and mark them for deletion Here is the sample code demonstrating this step using some of the relationships identified above.
List<Contact> queryResults = [select id ,(select id from AcceptedEventRelations) ,
							    (select id from PrimaryContact__r) ,
                                (select id from AccountContactRoles) ,
                                (select id from ActivityHistories),
                                (select id from Cases) from contact ORDER BY id LIMIT 10000]; 

Set<Id> resultIds = (new Map<Id,Contact>(queryResults)).keySet();
System.debug(resultIds.size());
for (Contact c : queryResults) {
 //   System.debug(c);
    if(c.Cases.size()>0||
       c.AcceptedEventRelations.size()>0||
       c.PrimaryContact__r.size()>0||
      c.AccountContactRoles.size()>0||
      c.ActivityHistories.size()>0)
    {
  /*      for (Case c1 : c.Cases) {
            System.debug(c1);
        }*/
       // System.debug('Keep');
        resultIds.remove(c.id);
    }
    else 
    {
        //System.debug('Delete1');
     
    }
        
        for (ActivityHistory c1 : c.ActivityHistories) {
         //   System.debug(c1);
        }
    
    for (Account c1 : c.PrimaryContact__r) {
       // System.debug(c1);
    }
}

System.debug(resultIds.size());

List<Lead> ls =[Select Id,ConvertedContactId from Lead where ConvertedContactId IN :resultIds];

if(ls.size()>0)
{
    for(Lead l : ls)
    {
        resultIds.remove(l.ConvertedContactId);
        system.debug('removed id '+l.ConvertedContactId);
    }
}

System.debug(resultIds.size()); // these the contacts to mark for deletion
I tried the following today in apex anonymous window and I see an unexpected behavior 
System.debug(Datetime.now());
System.debug(Datetime.now().format('YYYY-MM-DD'));
Why id the DD 84 when I use System.debug(Datetime.now().format('YYYY-MM-DD'))? 
13:09:14.1 (2508337)|USER_DEBUG|[1]|DEBUG|2020-03-24 19:09:14
13:09:14.1 (2587013)|USER_DEBUG|[2]|DEBUG|2020-03-84
Here is the Apex Class
public class AssignLeadsUsingAssignmentRules
{
    @InvocableMethod
    public static void LeadAssign(List<Id> LeadIds)
    {
            Database.DMLOptions dmo = new Database.DMLOptions();
            dmo.assignmentRuleHeader.useDefaultRule= true;          
            Lead Leads=[select id,OwnerId from lead where lead.id in :LeadIds];
            Leads.setOptions(dmo);
        	system.debug('Before Update Lead Details' + Leads);
         	Database.update(Leads,dmo);
        	Lead Leads2=[select id,OwnerId from lead where lead.id in :LeadIds];
        	system.debug('After Update Lead Details' + Leads2);
   }
}

Here is the test class 
@isTest 
      public class TestAssignLeadsUsingAssignmentRules{
      static testMethod void createnewlead() {
     
   //   Test.startTest();    
      Lead leadToCreate =new Lead();
      List<id> Ids= New List<Id>();
    //  leadToCreate.ownerid= userToCreate.id;
      leadToCreate.ownerid= UserInfo.getUserId();  
      leadToCreate.LastName ='Sample1';
      leadToCreate.Email='Someone@somewhere.com';
      leadToCreate.Company='OneTwo34';
      leadToCreate.LeadSource='Partner Referral';
      leadToCreate.Country='IN';
      leadToCreate.Source_Last_Lead_Source_Detail__c='Form - Contact Form';
          
      insert leadToCreate; 
      
      Ids.add(leadToCreate.id);
      AssignLeadsUsingAssignmentRules.leadAssign(Ids);
      System.assertEquals('00G1W000002RyhMUAS', leadToCreate.OwnerId, 'Something is wrong');

 	//  Test.stopTest();
      
   }
}

The test class fails as shown below User-added imageAs you can see the debug log shows the lead OwnerId has changed but the change does not persist outside the class in the test. What am I missing? 
I was planning to bring in data from an external database and found that it will cost us 13+GB of storage. The data has more than 7 million records across 4 tables, so at 2kb per record, the total cost would be 7000000*2/(1024*1024) = 13.4 GB. We would like to search and report on the data and add associated contacts and accounts to campaigns. What are our options?  
How I insert a related object using the external id field on the parent object?

I have a custom parent object License__c and related object Activation__c which have a Related_License__c lookup field to the License__c object and the relations ship name is License Activations.

License__c has l_id__c external id field. I would like to import the Activation__c object using the l_id__c field so that the parent-child relationship is automatically created.

This works using the data import wizard but fails when I try to import use the Bulk Api 1.0 

Here is the sample CVS file 

Activation_Id__c,License_Activations__r.l_id__c 
9249,1665029 
9250,1665029 
I have created a class to parse text data and want to use Static Resource (text file) to import the data for testing. How do I use test.loaddata so that it is imported as a String?  
I am currently using Apex to query an endpoint and parse the JSON result. I am making a call to an endpoint with consumer key/secret to get the access token and then using the token to query the final endpoint as shown in the code below.

I would like to convert this to External Service so that I can use it in a flow. Can someone give me detailed steps on how to convert this to external service? 

TIA.
public static void findidbyEmail(String email)
    {
        String idAPIKeyString = 'KEY:SECRET';
        
        Blob idBlob = Blob.valueof(idAPIKeyString);
        
        String idAuthorization = 'basic ' + EncodingUtil.base64Encode(idBlob);
        HttpRequest idRequest = new HttpRequest();
        
        idRequest.setEndpoint('https://api.sitename.com/token');
        idRequest.setMethod('POST');
        
        idRequest.setBody('grant_type=client_credentials');
        idRequest.setHeader('Authorization', idAuthorization);
        idRequest.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        
        Http http = new Http();
        
        HTTPResponse res = new HTTPResponse();
        
        if (Test.isRunningTest() && (mock!=null)) {
            System.debug('Mock Response');
            res = mock.respond(idRequest);
            
        } else {
            System.debug('Callout Response');
            res= http.send(idRequest);
            
        }
        
        
        System.debug(res.getBody());     
        
        
        idAuthorizationJSON2Apex objidAuthJSON2Apex = new idAuthorizationJSON2Apex(System.JSON.createParser(res.getBody()));
        System.debug(objidAuthJSON2Apex.access_token);
  
        String access_token= objidAuthJSON2Apex.access_token;
        system.debug(access_token);
        
        
        //    Get the id        
        HttpRequest req2= new HttpRequest();
        
        req2.setEndpoint('https://api.sitename.com/users?email='+email);
        req2.setMethod('GET');
        req2.setHeader('Authorization', 'bearer '+ access_token);
        
        req2.setHeader('Content-Type', 'application/json');
        
        Http http2 = new Http();
        
        HTTPResponse res2 = new HTTPResponse();
        
        if (Test.isRunningTest() && (mock!=null)) {
            res2 = mock.respond(req2);
            System.debug('Mock Response ' + res2);
        } else {
            res2= http.send(req2);
            System.debug('Callout Response '+res2);
        }
        
        
        if(res2.getBody()=='')
            System.debug('id Not found');
        else 
        {
            System.debug(res2.getBody());
            System.debug('id found');
            idJSON2Apex objidJSON2Apex = new idJSON2Apex(System.JSON.createParser(res2.getBody()));
            System.debug(objidJSON2Apex.theEmail.uniqueid);
           
        } 
    }

 
This test fails with the above message 
 
@isTest
public class AmplitudeApiCallsTest {

    @testSetup static void setup() {
        // Create common test accounts
        List<Account> testAccts = new List<Account>();
        for(Integer i=0;i<2;i++) {
            testAccts.add(new Account(Name = 'TestAcct'+i,Account_FCH_Id__c= '123456789'+i));
            
        }
        insert testAccts;        
    }

    @isTest
     public static void  AmplitudeCallOut()
    {
       
        
        String fakeAmplitudejson = '{\"novaRuntime\": 309, \"minSampleRate\": 1.0, \"throttleTime\": 2, \"partialMergedAndNewUserInformation\": false, \"timeComputed\": 1584390210280, \"wasCached\": false, \"backend\": \"novaV2\", \"realtimeDataMissing\": false, \"novaRequestDuration\": 378, \"queryIds\": [\"OwY0CjZuIC\"], \"hitChunkGroupByLimit\": false, \"prunedResult\": false, \"transformationIds\": [], \"novaCost\": 900, \"subcluster\": 3, \"timedOutRealtimeData\": false, \"data\": {\"seriesIntervals\": {}, \"seriesCollapsed\": [[{\"setId\": \"\", \"value\": 72002}]], \"xValues\": [\"2019-01-01\", \"2019-02-01\", \"2019-03-01\", \"2019-04-01\", \"2019-05-01\", \"2019-06-01\", \"2019-07-01\", \"2019-08-01\", \"2019-09-01\", \"2019-10-01\", \"2019-11-01\", \"2019-12-01\", \"2020-01-01\", \"2020-02-01\", \"2020-03-01\"], \"seriesLabels\": [0], \"series\": [[1, 2334, 6194, 9963, 13706, 16731, 20586, 23982, 27697, 32154, 34940, 36863, 44026, 48629, 43613]]}, \"cacheFreshness\": \"FRESH\"}';
        SingleRequestMock fakeAmplitudeResponse = new SingleRequestMock(200,
                                                                      'Complete',
                                                                      fakeAmplitudejson,
                                                                      null);
        Test.setMock(HttpCalloutMock.class, fakeAmplitudeResponse);
        
     
    
        List<Account> acc1=[Select id,Account_FCH_Id__c from Account Where Account_FCH_Id__c='1234567891' LIMIT 1];
		system.debug(AmplitudeApiCalls.dataForChartId(acc1[0].id));
        
        List<Account> acc2=[Select id,Account_FCH_Id__c from Account Where Account_FCH_Id__c='' LIMIT 1];
        system.debug(AmplitudeApiCalls.dataForChartId(acc2[0].id));
      
        
    }
}

 
I tried the following today in apex anonymous window and I see an unexpected behavior 
System.debug(Datetime.now());
System.debug(Datetime.now().format('YYYY-MM-DD'));
Why id the DD 84 when I use System.debug(Datetime.now().format('YYYY-MM-DD'))? 
13:09:14.1 (2508337)|USER_DEBUG|[1]|DEBUG|2020-03-24 19:09:14
13:09:14.1 (2587013)|USER_DEBUG|[2]|DEBUG|2020-03-84
I have converted the following python script to apex code and I get the HTTP 405 method not allowed error. Can someone review and let me know what is wrong? 

Python  
url = 'https://amplitude.com/api/2/events/segmentation'

# json parameters for querying monthly uniques for Launched App  between dates
# Add gp: in front of custom user_property
params1 = {
    'e': '{"event_type":"Launched Application","filters":[{"subprop_type":"user","subprop_key":"gp:app_name","subprop_op":"is","subprop_value":["su-desktop"]}, \
         {"subprop_type":"user","subprop_key":"gp:sku","subprop_op":"contains","subprop_value":["PRO"]}]}',
    'm': 'uniques',
    'start': '20190101',
    'end': '20200131',
    'i':'30'
}

# Set to -300000, -3600000, 1, 7, or 30 for real-time, hourly, daily, weekly, and monthly counts,



r = requests.get(url, params = params1,  auth=(api_key, secret_key))
response = r.json()
print( response)
#print r.status_code
#print r.url
Apex
 
HttpRequest req4= new HttpRequest();
req4.setEndpoint('https://amplitude.com/api/2/events/segmentation');
req4.setMethod('GET');
Blob myBlob1 = Blob.valueof(api_key + ':'+ secret_key);
String authorizationHeader = 'Basic ' + EncodingUtil.base64Encode(myBlob1);
req4.setHeader('Authorization', authorizationHeader);

String params1='{"e": "{\"event_type\":\"Launched Application\",\"filters\":[{\"subprop_type\":\"user\",\"subprop_key\":\"gp:app_name\",\"subprop_op\":\"is\",\"subprop_value\":[\"su-desktop\"]},{\"subprop_type\":\"user\",\"subprop_key\":\"gp:sku\",\"subprop_op\":\"contains\",\"subprop_value\":[\"PRO\"]}]}","end": "20200131","i": "30","m": "uniques","start": "20190101"}';


req4.setBody(params1);

Http http4 = new Http();
HTTPResponse res4 = http4.send(req4);
System.debug(res4.getBody());
How do I convert the following python code into json body to be sent with the HTTP request? 

TIA

 
params1 = {
        'e': '{"event_type":"Launched Application","filters":[{"subprop_type":"user","subprop_key":"gp:app_name","subprop_op":"is","subprop_value":["desktop"]}, \
             {"subprop_type":"user","subprop_key":"gp:sku","subprop_op":"contains","subprop_value":["SPEC"]}]}',
        'm': 'uniques',
        'start': '20190101',
        'end': '20200131',
        'i':'30'
    }

 
Here is the Apex Class
public class AssignLeadsUsingAssignmentRules
{
    @InvocableMethod
    public static void LeadAssign(List<Id> LeadIds)
    {
            Database.DMLOptions dmo = new Database.DMLOptions();
            dmo.assignmentRuleHeader.useDefaultRule= true;          
            Lead Leads=[select id,OwnerId from lead where lead.id in :LeadIds];
            Leads.setOptions(dmo);
        	system.debug('Before Update Lead Details' + Leads);
         	Database.update(Leads,dmo);
        	Lead Leads2=[select id,OwnerId from lead where lead.id in :LeadIds];
        	system.debug('After Update Lead Details' + Leads2);
   }
}

Here is the test class 
@isTest 
      public class TestAssignLeadsUsingAssignmentRules{
      static testMethod void createnewlead() {
     
   //   Test.startTest();    
      Lead leadToCreate =new Lead();
      List<id> Ids= New List<Id>();
    //  leadToCreate.ownerid= userToCreate.id;
      leadToCreate.ownerid= UserInfo.getUserId();  
      leadToCreate.LastName ='Sample1';
      leadToCreate.Email='Someone@somewhere.com';
      leadToCreate.Company='OneTwo34';
      leadToCreate.LeadSource='Partner Referral';
      leadToCreate.Country='IN';
      leadToCreate.Source_Last_Lead_Source_Detail__c='Form - Contact Form';
          
      insert leadToCreate; 
      
      Ids.add(leadToCreate.id);
      AssignLeadsUsingAssignmentRules.leadAssign(Ids);
      System.assertEquals('00G1W000002RyhMUAS', leadToCreate.OwnerId, 'Something is wrong');

 	//  Test.stopTest();
      
   }
}

The test class fails as shown below User-added imageAs you can see the debug log shows the lead OwnerId has changed but the change does not persist outside the class in the test. What am I missing? 
We have some accounts with incorrect account team and the following query identifies all such accounts. Basically, accounts with two or more account team members with the Distributor role has incorrect teams.
Select AccountId, Account.Name, count(id) from AccountTeamMember WHERE TeamMemberRole ='Distributor License Share' AND UserId!='0051W000004SVNhQAO' Group BY AccountId, Account.Name HAVING count(id) >=2 LIMIT 2000
What is the easiest way to delete all such account teams? 

I am still learning Apex/SOQL; how do I collect the AccountIds from the above aggregate result and pass it to get all the AccountTeamMember IDs to delete? The following code in developer console fails with the following error

Invalid identifier ' '. Apex identifiers must start with an ASCII letter (a-z or A-Z) followed by any number of ASCII letters (a-z or A-Z), digits (0 - 9), '$', '_'.​​​​​​​
List<AggregateResult> results =  [Select  AccountId, Account.Name, count(id) from AccountTeamMember 
                      WHERE TeamMemberRole ='Distributor License Share' AND UserId!='0051W000004SVNhQAO' 
                      Group BY AccountId, Account.Name HAVING count(id) >=2 LIMIT 2000 ];

System.debug(results.size());

System.debug(results[0]);

Set<id > AccountIds = new Set<id>();
      
for(AggregateResult exp: results){
    AccountIds.add((Id)exp.get('AccountId'));
}



 
Currently, we have 8 different triggers on the opportunity class and I am refactoring the code and moving it to a helper class. I am thinking of using the switch statement as shown in this article (https://developer.salesforce.com/blogs/2018/05/summer18-rethink-trigger-logic-with-apex-switch.html). 

Here is the original trigger
 trigger OppPusher on Opportunity (before update) {
Date dNewCloseDate;
Date dOldCloseDate;
Boolean bPushed=false;
for (Opportunity oIterator : Trigger.new) { //Bulk trigger handler so that you can mass update opportunities and this fires for all'
// gets new values for updated rows
dNewCloseDate = oIterator.CloseDate; // get the new closedate
dOldCloseDate = System.Trigger.oldMap.get(oIterator.Id).CloseDate; //get the old closedate for this opportunity
//if different do something.
}
}

Here is the new trigger and class 
trigger OppTriggers  on  Opportunity (    before insert, 
                                           after insert, 
                                           before update, 
                                           after update) {

	OppTriggerHandler.handleTrigger(Trigger.new, Trigger.old, Trigger.operationType);

}

public with sharing class OppTriggerHandler { 
    
    public static void handleTrigger(List<Opportunity> workingRecords, 
                                     List<Opportunity> oldRecords, 
                                     System.TriggerOperation triggerEvent ) {
                                         
                                         
                                         switch on triggerEvent {
                                             
                                             when BEFORE_UPDATE{
                                                 Date dNewCloseDate;
                                                 Date dOldCloseDate;
                                                 Boolean bPushed=false;
                                                 
                                                 for (Opportunity oIterator : workingRecords) { //Bulk trigger handler so that you can mass update opportunities and this fires for all'
                                                     // gets new values for updated rows
                                                     dNewCloseDate = oIterator.CloseDate; // get the new closedate 
                                              	     dOldCloseDate = System.Trigger.oldMap.get(oIterator.Id).CloseDate; //get the old closedate for this opportunity
                                                    //if different do something.
                                                   
                                                 }
                                             }
                                             when AFTER_INSERT, AFTER_UPDATE {
                                                 //create related records
                                             }
                                             when BEFORE_INSERT {
                                                 //set value on record create
                                             }
                                             when AFTER_DELETE {
                                                 //prevent deletion of sensitive data
                                             }
                                             when else {
                                                 //do nothing for AFTER_UNDELETE, BEFORE_DELETE, or BEFORE_UPDATE
                                             }
                                         }
                                     }
}

And the compiler fails with 
Variable does not exist: CloseDate message.

How do I about this error message? 


 
I am trying to mass delete listviews from a test site using the workbench. Here is the destructivechanges.xml 
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <name>ListView</name>
        <members>Case.All_Open_Requests</members>
        <members>Case.All_Open_Requests_Since_2016</members>
        <members>Case.All_Request_Created_Today</members>
    </types>
    <version>44.0</version>
</Package>

Here is the package.xml 
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <version>44.0</version>
</Package>

Both of these are in a zip file changes.zip, and the workbench shows success but it is not deleted for the interface. What am I missing?
 
Here are some examples of fake contacts in our database which we would like to clean. 
User-added image
Here is the current code and as you can tell the credentials are visible to anyone accessing the code. How can we remove it from the code? 
String myString = 'somekey:somepassword';
        
        Blob myBlob = Blob.valueof(myString);
        
        String authorization1 = 'basic ' + EncodingUtil.base64Encode(myBlob);
        HttpRequest req = new HttpRequest();
        
        req.setEndpoint('https://api.somesite.com/token');
        req.setMethod('POST');
        
        req.setBody('grant_type=client_credentials');
        
        req.setHeader('Authorization', authorization1);
        
        req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        
        Http http = new Http();
        
        HTTPResponse res = http.send(req);

I reviewed Named Credentials but am thrown off with the 64 bit encoding requirement. Thanks in advance for your help.

Yogesh
I am trying to the queries from this link into a visualforce page. Here is the controller class 
// https://salesforce.stackexchange.com/questions/118109/how-to-use-custom-date-fields-in-visualforce-page
// 
public with sharing class DisplayDriftInfluncedOpportunity{
    public static Date startDate{get;set;}
    public static Date endDate{get;set;}
    //public static List<Account> accList{get;set;}
    public boolean showResult{get;set;}
    public boolean blnNoResultFound{get;set;}
    public List<SObject> Records {get; set;}
    
    public DisplayDriftInfluncedOpportunity(){
        showResult = false;
        blnNoResultFound = false;
        Records = new List<SObject>();
        endDate=date.today();
        startDate=endDate-90;
    }
    
    
    public void searchResults(){
        List<Task> accs= [select Id, AccountId
                          from Task
                          where
                          Subject = 'Conversation in Drift' and
                          AccountId != null and
                          AccountId in (
                              Select AccountId
                              from Opportunity
                              WHERE 
                              //Calendar_Year(CreatedDate)=2018
                              DAY_ONLY(CreatedDate) >= :startDate and
                              DAY_ONLY(CreatedDate) <= :endDate
                          )]
            ;
        
        Set<Id> acca1 = new Set<Id>();
        for(Task t :accs)
            acca1.add(t.AccountId);
        
        List<SObject> r=[select AccountId accId, COUNT(Name) oCount , SUM(Amount) Total , DAY_ONLY(CreatedDate) CreatedDate  , CloseDate 
                         from Opportunity
                         where
                        // Calendar_Year(CreatedDate)=2018 and
                         DAY_ONLY(CreatedDate) >= :startDate and
                         DAY_ONLY(CreatedDate) <= :endDate and
                         AccountId in :acca1
                         group by DAY_ONLY(CreatedDate), AccountId, CloseDate];
        
        Records =r;
        
    }
}

And the corresponding visualforce page .
 
<apex:page controller="DisplayDriftInfluncedOpportunity" docType="html-5.0">
    
<center><h1>Opportunity Search Page</h1></center>
<apex:form >
   Start Date: <apex:input type="date" value="{!startDate}" required="true" />
   End Date: <apex:input type="date" value="{!endDate}" required="true" /> 
    <apex:commandButton action="{!searchResults}" value="Search" />
</apex:form> 
<apex:pageBlock title="Opportunities Influenced by Drift">
  <apex:pageBlockTable value="{!Records}" var="Record">
   <apex:column >
    <apex:facet name="header">Account id</apex:facet>
    <apex:outputlink value="/{!Record['accId']}">{!Record['accId']}</apex:outputlink>
   </apex:column>
   <apex:column >
    <apex:facet name="header">Count</apex:facet>
       <apex:outputText value="{!Record['oCount']}"/>
   </apex:column>
   <apex:column >
    <apex:facet name="header">Total</apex:facet>
       <apex:outputText value="{!Record['Total']}"/>
   </apex:column>
      
   <apex:column >
    <apex:facet name="header">CreatedDate</apex:facet>
       <apex:outputText value="{!Record['CreatedDate']}"/>
   </apex:column>
   <apex:column >
    <apex:facet name="header">CloseDate</apex:facet>
       <apex:outputText value="{!Record['CloseDate']}"/>
   </apex:column>
  </apex:pageBlockTable>
</apex:pageBlock>
    
</apex:page>
 Instead of Account Id associated with the Opportunity, I would like to show the Account Name. What do I need to change?

Yogesh
On the Opportunity record I have a quick action to create Contact roles. When I click on the quick action , I am opening a flow screen. And on that screen I need to prepopulate the Opportunity Id from where I came . What is the way ? 

I created a variable called recordID and set the type as input. Foe some reason that is not working. Any help ??
I have below JSON ,How can I send in my request using apex:

"objects":[
{
"fieldsToNull":["DefaultPaymentMethodId"],
"AccountNumber":"A00000036",
"Id":"2c92c0f95a4085a8015a41f4012d183e"
}
]
, "type":"Account"