Skip to content

Instantly share code, notes, and snippets.

@rygramer
Created August 4, 2021 00:42
Show Gist options
  • Save rygramer/7d12b928b6f69f81c4cda0f0905dca49 to your computer and use it in GitHub Desktop.
Save rygramer/7d12b928b6f69f81c4cda0f0905dca49 to your computer and use it in GitHub Desktop.
Create QuickBooks Customers from Salesforce Accounts
/**
* @Name: QuickBooksCustomer
* @Author: Kicksaw
* @Date: 2021-08-04
* @Description: Create QuickBooks Customers from Salesforce Accounts
*
********************************************************* CHANGE HISTORY *********************************************************
* ModifiedBy Date Reference Num Description
* --------------------------------------------------------------------------------------------------------------------------------
* Kicksaw, Ryan Mercer 2021-08-04 1 Initial Version
**********************************************************************************************************************************/
public class QuickBooksCustomer {
/**
* @Description Create QuickBooks Customers from Salesforce Accounts
* @Param inputs - List<InputParameters>
* @Return List<OutputParameters>
*/
@InvocableMethod(
label = 'Create QuickBooks Customers from Salesforce Accounts'
description = 'Kicksaw'
callout=true
)
public static List<OutputParameters> create(List<InputParameters> inputs){
// Instantiate a new QB_Request object. The constructor instantiates List<BatchItemRequest>.
QB_Request qbReqs = new QB_Request();
for(InputParameters input : inputs){
// Loop through the inputs (ie Accounts) and instantiate new BatchItemRequest objects.
BatchItemRequest qbReq = new BatchItemRequest(input.acct);
// Add the new BatchItemRequest to the list.
qbReqs.BatchItemRequest.add(qbReq);
}
// Prepare callout.
HttpRequest request = new HttpRequest();
request.setMethod('POST');
// Information on the QuickBooks Batch object is here: https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/batch.
// This is where the Named Credential magic happens.
request.setEndpoint('callout:QuickBooks/' + system.label.QuickBooksRealmId + '/batch/');
request.setHeader('Accept', 'application/json');
request.setHeader('Content-Type', 'application/json');
// We're transforming the Apex objects to JSON here so it can be sent to QuickBooks.
// Take a look at what the objects look like as Apex objects:
system.debug('BatchItemRequest(s) pre-JSON' + qbReqs);
request.setBody(JSON.serialize(qbReqs,TRUE));
// And here's what the objects look like as JSON:
system.debug('BatchItemRequest(s) as JSON' + request.getBody());
// Do callout.
HttpResponse response = new Http().send(request);
// Same concept here, but the other way. We're transforming the JSON that QuickBooks returned to us into Apex objects.
// Take a look at what the objects looked like as JSON:
system.debug('BatchItemResponse(s) as JSON' + response.getBody());
QB_Response qbResp = (QB_Response) JSON.deserialize(response.getBody(), QB_Response.class);
// And here's what they look like as Apex objects:
system.debug(qbResp);
List<OutputParameters> outputs = new List<OutputParameters>();
List<Account> acctsToUpdate = new List<Account>();
for(BatchItemResponse resp : qbResp.BatchItemResponse){
// Instantiate a new Account.
Account acctToUpdate = new Account(
// This is why we made 'bId' the Salesforce RecordId, makes updates so much easier.
Id = resp.bId,
QuickBooksId__c = resp.Customer.Id
);
// Never perform DML in loop, add it to a list and update outside of the list.
acctsToUpdate.add(acctToUpdate);
// Prepare the OutputParameters to make the invocable look pretty.
OutputParameters output = new OutputParameters();
output.acct = acctToUpdate;
outputs.add(output);
}
// Update the Account(s), and return them to the invocable method for further processing.
update acctsToUpdate;
return outputs;
}
/**
* @Description Wrapper class for the Customer object we are sending to QuickBooks. This is the meat of the data, and can be expanded to include Phone, Address, AccountNumber, etc.
*/
public class Customer{
public String DisplayName;
public String Id;
// Constructor
public Customer(Account acct){
this.DisplayName = acct.Name;
}
}
/**
* @Description Wrapper class for the list of BatchItemRequest objects we are sending to QuickBooks.
*/
public class QB_Request{
public List<BatchItemRequest> BatchItemRequest;
// Constructor
public QB_Request(){
this.BatchItemRequest = new List<BatchItemRequest>();
}
}
/**
* @Description Wrapper class for the BatchItemRequest object we are sending to QuickBooks.
*/
public class BatchItemRequest{
public String bId;
public Customer Customer;
public String operation;
// Constructor
public BatchItemRequest(Account acct){
this.bId = acct.Id;
this.Customer = new Customer(acct);
this.operation = 'create';
}
}
/**
* @Description Wrapper class for the list of BatchItemResponse objects returned by QuickBooks.
*/
public class QB_Response{
public List<BatchItemResponse> BatchItemResponse;
// Constructor
public QB_Response(){
this.BatchItemResponse = new List<BatchItemResponse>();
}
}
/**
* @Description Wrapper class for the BatchItemResponse object returned by QuickBooks.
*/
public class BatchItemResponse{
public Customer Customer;
public String bId;
// Constructor
public BatchItemResponse(Account acct){
this.bId = acct.Id;
this.Customer = new Customer(acct);
}
}
/**
* @Description Wrapper class for input parameters. This make the invocable method pretty.
*/
public class InputParameters {
@InvocableVariable(label='Account to Create in QuickBooks'
required=true)
public Account acct;
}
/**
* @Description Wrapper class for output parameters. This makes the invocable method pretty.
*/
public class OutputParameters {
@InvocableVariable(label='Account that was Created in QuickBooks'
required=true)
public Account acct;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment