• Learn Salesforce 36
  • NEWBIE
  • 55 Points
  • Member since 2018

  • Chatter
    Feed
  • 1
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 2
    Questions
  • 8
    Replies
I am trying to create a wrapper class to hold the JSON response in my apex class. But I am getting the error ' Inner types are not allowed to have inner types '. Below is my wrapper class.
 
public class GetTheDetails {

// Wrapper class

public class fromJSON{
    public String spreadsheetId;    
    public List<valueRanges> valueRanges ;
    public class valueRanges {
        public String range;    
        public String majorDimension;   
        public List<values> values;
    }
    public class values {
        public String Id;           //Id
        public String AccountID;    //AccountId
        public String CreatedById;  //CreatedById
        public String Name;         //Name
        public String StageName;    //StageName
        public String CloseDate;    //CloseDate
    }
    public fromJSON parse(String json){
        return (fromJSON) System.JSON.deserialize(json, fromJSON.class);
    }
    
} }

Can anybody help me in identifying the error ? I am not able to find any syntax error in defining wrapper class here.
Getting below error while calling apex method from lwc
Value provided is invalid for action parameter 'fileBlob' of type 'Blob

PFB lwc js code:
saveFile() {
    console.log('blob type: '+typeof this.blob);
    uploadFile({fileBlob : this.blob, accessToken : this.accessToken}).then(result => {
      if (result == '200') {
        alert('File is saved successfully in your Google Drive');
        this.blob = null;
        this.downloadUrl = null;
      }
      else {
        alert('There is some problem saving the file to Google Drive');
      }
    }).catch(error => {console.log('error in save file : '+JSON.stringify(error))});
  }

saveByteArray(pdfName, byte) {
      this.blob = new Blob([byte], {type : "application/pdf"});      
  }
PFB Apex Method:
 
@AuraEnabled
    public static String uploadFile(Blob fileBlob, String accessToken){
        String url = 'https://www.googleapis.com/upload/drive/v2/files?uploadType=media';
        String authorizationHeader = 'Bearer '+accessToken;
        Integer contentSize = fileBlob.size();
        HttpRequest req = new HttpRequest();
        req.setHeader('Authorization',authorizationHeader);
        req.setHeader('Content-Length',String.valueOf(contentSize));
        req.setHeader('Content-Type','PDF');
        req.setMethod('POST');
        req.setEndpoint(url);
        req.setBodyAsBlob(fileBlob);
        Http h = new Http();
        HttpResponse resp = h.send(req);        
        return String.valueOf(resp.getStatusCode());
    }


​​​​​​​
Getting error on below line 
gapi.load('client', () => {});
Error is below
gapi load error TypeError: Cannot read properties of undefined (reading 'error')

Below is the js code for reference:
import { LightningElement, track } from 'lwc';
import pdflib from '@salesforce/resourceUrl/pdflib';
import driveapi from '@salesforce/resourceUrl/driveapi';
import driveclient from '@salesforce/resourceUrl/driveclient';
import driveClientId from '@salesforce/label/c.drive_client_id';
import driveApiKey from '@salesforce/label/c.drive_api_key';
import { loadScript } from 'lightning/platformResourceLoader';
export default class Resumebuilder extends LightningElement {
    @track name;
    @track contact;
    @track email;
    @track downloadUrl;    
    renderedCallback() {
      loadScript(this, pdflib).then(() => {});  
      loadScript(this, driveclient).then(() => {
        console.log('drive client loaded');
        google.accounts.oauth2.initTokenClient({
         client_id: driveClientId,
         scope: 'https://www.googleapis.com/auth/drive.file'         
       });

       loadScript(this, driveapi).then(() => {
        console.log('load drive api'+gapi);
        try{
          gapi.load('client', () => {
            console.log('in load client');            
          });
        } catch (e){
          console.log('gapi load error '+e);  //getting the error here
        }       
    });
      }).catch(e => {
        console.log('client load error '+e);
      });      
    }

Note: This lwc is added in experience site page.
Getting error on below line 
gapi.load('client', () => {});
Error is below
gapi load error TypeError: Cannot read properties of undefined (reading 'error')

Below is the js code for reference:
import { LightningElement, track } from 'lwc';
import pdflib from '@salesforce/resourceUrl/pdflib';
import driveapi from '@salesforce/resourceUrl/driveapi';
import driveclient from '@salesforce/resourceUrl/driveclient';
import driveClientId from '@salesforce/label/c.drive_client_id';
import driveApiKey from '@salesforce/label/c.drive_api_key';
import { loadScript } from 'lightning/platformResourceLoader';
export default class Resumebuilder extends LightningElement {
    @track name;
    @track contact;
    @track email;
    @track downloadUrl;    
    renderedCallback() {
      loadScript(this, pdflib).then(() => {});  
      loadScript(this, driveclient).then(() => {
        console.log('drive client loaded');
        google.accounts.oauth2.initTokenClient({
         client_id: driveClientId,
         scope: 'https://www.googleapis.com/auth/drive.file'         
       });

       loadScript(this, driveapi).then(() => {
        console.log('load drive api'+gapi);
        try{
          gapi.load('client', () => {
            console.log('in load client');            
          });
        } catch (e){
          console.log('gapi load error '+e);  //getting the error here
        }       
    });
      }).catch(e => {
        console.log('client load error '+e);
      });      
    }

Note: This lwc is added in experience site page.
I have created Printablle view Button, user needs see the print preview  button open in a new browser window which contains all Detail fields visible and related list fields to be visible. can someone suggest/help for code. Thanks!
I am trying to create a wrapper class to hold the JSON response in my apex class. But I am getting the error ' Inner types are not allowed to have inner types '. Below is my wrapper class.
 
public class GetTheDetails {

// Wrapper class

public class fromJSON{
    public String spreadsheetId;    
    public List<valueRanges> valueRanges ;
    public class valueRanges {
        public String range;    
        public String majorDimension;   
        public List<values> values;
    }
    public class values {
        public String Id;           //Id
        public String AccountID;    //AccountId
        public String CreatedById;  //CreatedById
        public String Name;         //Name
        public String StageName;    //StageName
        public String CloseDate;    //CloseDate
    }
    public fromJSON parse(String json){
        return (fromJSON) System.JSON.deserialize(json, fromJSON.class);
    }
    
} }

Can anybody help me in identifying the error ? I am not able to find any syntax error in defining wrapper class here.
Scenario
I am a non for profit and the sequence of opportunities of a contact (donations) is important.

Goal
I want to set the order of donation for each opportunity (grouped by donor).
So, if we have 
opportunity,contact,date
1,John,01/01/2020
2,Mary,02/01/2020
3,John,02/01/2020
4,Mary,05/01/2020

I would like to create a field Sequence No in Opportunity which contains:
opportunity,contact,date,Sequence No
1,John,01/01/2020,1
2,Mary,02/01/2020,1
3,John,02/01/2020,2
4,Mary,05/01/2020,2

I can think that we may have 
List <Contact> allAlive = [SELECT Id FROM Contact WHERE Deceased = 0 LIMIT 100];
 

For ( Contact currentContact : allAlive){
   sequence = 1;
   List <Opportunity> allOpp = [SELECT Id FROM Opportunity WHERE PrimaryContactId = " + currentContact + "] order by CreatedDate";
   For ( Opportunity currentOpportunity : allOpps )
  {
    currentOpportunity.SequenceNo = sequence;
    sequence = sequence + 1;
    update currentOpportunity;
  }
}
(I limited for 100 contact because I am worried about CPU TIME LIMIT, and APEX limits)

(I realized that this code is not going to work:
  * the next time it runs it will probably take the same 100 records, therefore no progress is going to happen)

So, afterwards, what would be the best way to enumerate the order of opportunities that a contact have done saving that in the opportunity?

Hi,
Iam new to apex. this is one of the trigger scenario bothering me.
Please help me with this.

I have a status checkbox field on accounts.
status picklist field with "open","closed" on contacts.
1) if status="closed" in all the related contacts then checkbox on account should be true.
2) if status="open" in any one of the related contacts then checkbox on account should be false.  
-------------------------------------------------------------------------------------------
Trigger:
trigger contactTrigg on contact(after insert, after update, after delete, after undelete){
    if(trigger.isInsert || trigger.isUpdate){
        accProgress.method1(trigger.new,trigger.old);
    }
}

-------
Handler:
public class accProgress{
    public static void method1(list<contact> newInsert, list<contact> oldInsert){
        
        set<id> conSet = new set<id>();
        
        for(contact con1 : newInsert){
            if(con1.Accountid != null){
                conSet.add(con1.accountid);
            }
        }
 for(contact con2 : oldInsert){
                conSet.add(con2.accountid);
        }

        List<account> accList =[SELECT id, progress_field__c,(SELECT id, progress_field_contacts__c FROM contacts) FROM account WHERE id IN :conSet];
        if(accList != null){
            for(account acc : accList){
                for(contact con : acc.contacts){
                    
                    if(con.progress_field_contacts__c == 'open' ){
                        acc.progress_field__c = false;
                    }
                    else{
                        acc.progress_field__c = true;
                    }
                }
            }
            update accList;
        }
    }
---------------------------------------------------------------------------------------------
1st one is working. i.e, whenever i make all related contacts "close" . the check box is getting checked(true).
2nd one is where iam failing. when i'm changing any contacts picklist values to open the account status checkbox is not unchecking(false).
please help me.
Hi, I am facing error - Ensure that you implement the Queueable interface in the AnnouncementQueueable class. 

I am getting proper response....and implemented trigger, Product2Helper and AnnouncementQueable class as per the trailhead 



Follwoing is my code -
product2Trigger --->
trigger product2Trigger on Product2 (after update) {
   Product2Helper.AfterUpdate((List<Product2>)trigger.new,(List<Product2>)trigger.old);
   
}

Product2Helper Class ---->
public class Product2Helper {

    /**
     * @name COLLABORATION_GROUP
     * @description List of CollaborationGroup used in both business and test logic
    **/
    static List<CollaborationGroup> COLLABORATION_GROUP = [
        SELECT Id
        FROM CollaborationGroup
        WHERE Name = :Constants.INVENTORY_ANNOUNCEMENTS 
        OR Name = :('TEST'+Constants.INVENTORY_ANNOUNCEMENTS)
        LIMIT 1
    ];

    /**
     * @name afterUpdate
     * @description called by product2 Trigger on After Update
     * @param List<Product2> newList
     * @param List<Product2> oldList
    **/
    public static void AfterUpdate(List<Product2> prodList, List<Product2> prodOldList){
        //ToDo: Declare a List of Product2 records named needsAnnouncement

        //ToDo: Declare a Map of Strings to Inventory_Setting__mdt records

        //ToDo: Loop through a query of Inventory_Setting__mdt records and populate the Map with Name as the key

        //ToDo: Loop through the Products in newList
        // Use the corresponding Inventory Setting record to determine the correct Low Quantity Alert
        // If the Product's Quantity Remaining has been changed to less than the Low Quantity Alert
        //      add it to the needsAnnouncement list

        //ToDo: Pass records to the postAlerts method
        List<Product2> needsAnnouncement = new List<Product2>();
        Map<String,Inventory_Setting__mdt> mapInventory = new Map<String,Inventory_Setting__mdt>();
        for(Inventory_Setting__mdt inv : [select id, DeveloperName, Low_Quantity_Alert__c from Inventory_Setting__mdt]){
            mapInventory.put(inv.DeveloperName,inv);
        }
        
        for(integer i=0;i<prodList.size();i++)
        {
            if(mapInventory.get(prodList[i].Family).Low_Quantity_Alert__c > prodList[i].Quantity_Remaining__c && 
                mapInventory.get(prodList[i].Family).Low_Quantity_Alert__c <= prodOldList[i].Quantity_Remaining__c)
            {
                needsAnnouncement.add(prodList[i]);
            }
        }
        PostAlerts(needsAnnouncement);
    }

    /**
     * @name postAlerts
     * @description called by product2 Trigger on After Update
     * @param List<Product2> productList
    **/
    public static void PostAlerts(List<Product2> productList){
        List<ConnectApi.AnnouncementInput> toPost = new List<ConnectApi.AnnouncementInput>();
        for ( Product2 p : productList ){
            // ToDo: Construct a new AnnouncementInput for the Chatter Group so that it:
            // expires in a day
            // does not notify users via email.
            // and has a text body that includes the name of the product followed by the INVENTORY_LEVEL_LOW constant
            ConnectApi.MessageBodyInput msgBody = new ConnectApi.MessageBodyInput();
            ConnectApi.AnnouncementInput tempPost = new ConnectApi.AnnouncementInput();
            ConnectApi.TextSegmentInput textSegment = new ConnectApi.TextSegmentInput();
            textSegment.text = p.Name +'  '+ Constants.INVENTORY_LEVEL_LOW;
            msgBody.messageSegments = new List<ConnectApi.MessageSegmentInput>();
            msgBody.messageSegments.add(textSegment);
            
            tempPost.body = msgBody;
            tempPost.expirationDate = DateTime.Now().AddDays(1);
            tempPost.parentId = COLLABORATION_GROUP[0].id;
            tempPost.sendEmails = false;
            toPost.add(tempPost);
         }
    
        // ToDo: Create and enqueue an instance of the announcementQueuable class with the list of Products
        AnnouncementQueueable annQue = new AnnouncementQueueable(toPost);
        //annQue.toPost = toPost;
        system.enqueueJob(annQue);
    }
}

AnnouncementQueueable Class ---->
/**
 * @name AnnouncementQueueable
 * @description This class posts Chatter Announcements
**/
public class AnnouncementQueueable implements Queueable{

    public List<ConnectApi.AnnouncementInput> toPost;
    
    public AnnouncementQueueable(List<ConnectApi.AnnouncementInput> annList)
    {
        toPost = annList;
    }

    //ToDo: Modify this class to implement the Queueable interface and call the postAnnouncements method
    public void execute(System.QueueableContext context){
        
        PostAnnouncements(toPost);
    }

    /**
     * @name postAnnouncements
     * @description This method is provided for you to facilitate the Super Badge
    **/
    public static void PostAnnouncements(List<ConnectApi.AnnouncementInput> announcements){
        while ( announcements.size() > 0 ){
            if ( Limits.getDMLStatements() < Limits.getLimitDMLStatements() && !test.isRunningTest() ){
                ConnectApi.AnnouncementInput a = announcements.remove(0);
                ConnectApi.Announcements.postAnnouncement('Internal', a);
            } else {
                break;
            }
        }
        if ( announcements.size() > 0 && !test.isRunningTest() ){
            AnnouncementQueueable q = new AnnouncementQueueable(announcements);
            //q.toPost = announcements;
            system.enqueueJob(q);
            //ToDo: Enqueue the above instance of announcementQueueable
        }
    }

}

Any help would be really appreciated.