• EQ Admin
  • NEWBIE
  • 20 Points
  • Member since 2019

  • Chatter
    Feed
  • 0
    Best Answers
  • 1
    Likes Received
  • 0
    Likes Given
  • 10
    Questions
  • 10
    Replies
I have a batch. Start query is working on 50k records. One more query is there in execute which also return more than 50 k records. Getting heap size error. Any suggestions would be really helpfull
Start Method : 

 global APTS_UsageInput_ValidateDataBatch(APTS_UsageInputWrapper uirecordsfromloadfile)
    {
        workid=uirecordsfromloadfile.EQ_WorkId;
        inputrecord = uirecordsfromloadfile;
    }
String str='select id,EQ_UsageSchedule__c,EQ_ValidationError__c,EQ_ProcessStatus__c,APTS_Legacy_ExternalID__c, EQ_ServiceCode__c,EQ_Account__c,EQ_AssetLineItem__c ,EQ_AccountLocation__c, EQ_IssueNumber__c, EQ_SourceSystem__c,EQ_RecordKey__c, EQ_WorkId__c, EQ_QuantityID__c, EQ_LoadMonth__c, EQ_Quantity__c from EQ_TempSSP1Data__c where EQ_WorkId__c=:workid';
    global database.QueryLocator start(Database.BatchableContext BC)
    {
      return Database.getQueryLocator(str);
   }
Execute Method : 
 global void execute(Database.BatchableContext BC, List<EQ_TempSSP1Data__c> scope)
   {
     String key;
           set<String> distinctTempSsp1DataSourceSystems = new set<String>();
           set<String> issueNumbers = new set<String>();
           set<String> serviceCodes = new set<string>();
           set<String> areAllIssueNumbersPresent = new set<String>();
           list<string> errors=new list<string>();
           Set<String> pickListValuesList= new Set<String>();
           String SourceSystem='004:Invalid Source System';
           string IssueNumber = '001:IssueNumber Does not exists';
           string DuplicatesFound = '012:Duplicate issue number service code pair record found';
           string NotValidDateRange = '006:sageData Date is not in the valid(Effective) Date range';
           string ServiceCode = '002:Fee Code Does not exists';
           string ServiceCodeIssueNumberCombo = '007:Asset doesnot exists for the Account-Fee Code'; 
           string missingAssetData = '008: every record from the load file doesnot have existing Account or AccountLocation';
           string MultipleAssetsPerFeeCode = '013: Multiple Assets for Account or Acc Location per Fee Code';
           string InactiveAccount = '003:Account is Inactive';
           list<String> duplicateSourcecode= new list<String>();
           list<String> encounterSourcecode= new list<String>();
           list<String> duplicateIssue= new list<String>();
           list<String> encounterIssue= new list<String>();
           list<EQ_SSP1Data__c> ssp1Data =new list<EQ_SSP1Data__c>();
           list<EQ_SSP1Data__c> ssp1DataRef =new list<EQ_SSP1Data__c>();
           map<string,list<EQ_TempSSP1Data__c>> tempSsp1DataIssueFeeCodeKey = new map<string,list<EQ_TempSSP1Data__c>>();
           map<string,list<EQ_SSP1Data__c>> ssp1DataAccountIdKey = new map<string,list<EQ_SSP1Data__c>>();
           map<string,list<EQ_SSP1Data__c>> ssp1DataAccountLocationIdKey = new map<string,list<EQ_SSP1Data__c>>();
           list<String> encounterList= new list<String>();
           list<String> duplicateList= new List<String>();
           list<ErrorTempSSP1Data > errorTempSection   = new list<ErrorTempSSP1Data >();
           
          system.debug(': Heap size is-1 ' + limits.getHeapSize() + ' enforced is ' + limits.getLimitHeapSize()); 
          tempSsp1Data=scope;
         system.debug('Validate Batch -Scope list contains---->'+tempSsp1Data);
           //---------------------------validation 1---------------------------------------------------------------------
         // ErrorChecker with tempSsp1Data for valid values of the fields and check SourceSystem is existing in system
         
                
           // Blank Check on records
          list<ErrorTempSSP1Data> errorTempSection_1= new list<ErrorTempSSP1Data>();
          for(EQ_TempSSP1Data__c record : tempSsp1Data)
              {
                 distinctTempSsp1DataSourceSystems.Add(record.EQ_SourceSystem__c);
                serviceCodes.add(record.EQ_ServiceCode__c);
                 list<String> nullerrors= new list<String>();
                  map<ID,list<String>> nullCheckmap= new map<ID,list<String>>();
                 nullerrors = ErrorChecker.ValidateImportData(record);
                 system.debug('Null Errors List ->'+nullerrors);
                 if(nullerrors.size()!=0)
                 {
                    if (!errorTempData.ContainsKey(String.valueof(record)))
                        {
                            ErrorTempSSP1Data ins = new ErrorTempSSP1Data();
                            ins.TempData=record;
                            ins.Errors=nullerrors;
                             nullCheckmap.put(ins.TempData.id,ins.Errors);
                             ins.mapErrors=nullCheckmap;
                             errorTempSection_1.add(ins);
                             system.debug('Null Errors if any ->'+ins.mapErrors );
                         } 
                 }
                  
              }
         if(errorTempSection_1.size()!= 0)
                {
                    for(ErrorTempSSP1Data errorTemp:errorTempSection_1)
                    {
                        key = string.valueof(errorTemp.TempData);

                        if (!errorTempData.ContainsKey(key))
                         {
                            errorTempData.put(key,errorTemp);
                         }
                    }
             }
        system.debug('errorTempData data1--->'+errorTempData.values());
       system.debug(': Heap size is--2 ' + limits.getHeapSize() + ' enforced is ' + limits.getLimitHeapSize());
       
       // Validation for duplicate IssueNumber-ServiceCode pairs in the load file
             for(EQ_TempSSP1Data__c x:tempSsp1Data)
             {
              list<String> error1= new list<String>();
              map<ID,list<String>> m1= new map<ID,list<String>>();
              if((x.EQ_IssueNumber__c!=null || x.EQ_IssueNumber__c!='')&& (x.EQ_ServiceCode__c!=null||x.EQ_ServiceCode__c!=''))
                
              {
                  String uniqueChecksum= x.EQ_IssueNumber__c + x.EQ_ServiceCode__c;
                  List<EQ_TempSSP1Data__c> entitiesForKey = tempSsp1DataIssueFeeCodeKey.get(uniqueChecksum);
                    if (entitiesForKey == null) 
                    {
                        entitiesForKey = new List<EQ_TempSSP1Data__c>();
                        tempSsp1DataIssueFeeCodeKey.put(uniqueChecksum, entitiesForKey);
                    }    
                  entitiesForKey.add(x);
                 tempSsp1DataIssueFeeCodeKey.put(uniqueChecksum,entitiesForKey);
                 if(!encounterList.contains(uniqueChecksum))
                 {
                    encounterList.add(uniqueChecksum);
                 }
                 else
                 {
                     ErrorTempSSP1Data ins = new ErrorTempSSP1Data();
                         ins.TempData=x;
                         error1.add(DuplicatesFound);
                         ins.Errors=error1;
                         m1.put(ins.TempData.id,ins.Errors);
                         ins.mapErrors=m1;
                         system.debug('Duplicate issue number service code error if any-->'+ ins.mapErrors);
                        errorTempSection.add(ins);
                 }
              }
           }       
             
           
             if(errorTempSection.size()!= 0)
                {
                    for(ErrorTempSSP1Data errorTemp :errorTempSection)
                    {
                        key = string.valueof(errorTemp.TempData);

                        if (!errorTempData.ContainsKey(key))
                        {
                            errorTempData.put(key, errorTemp);
                            
                         }

                    }
                }

  for(ErrorTempSSP1Data item:errorTempData.Values())
                {
                    for(String st:item.Errors)
                    {
                       errorsList.add(st);
                    }
                    
                }
         count=errorsList.size();
         system.debug('ErrorList^^^^^'+errorsList);
         system.debug('ErrorList count^^^^^'+count); 
          status = (count == 0)
                ? 'PegaCallbackStatus.Complete'
                : 'PegaCallbackStatus.Error';
       //-----------------------------
 //Update error field on tempssp1 records
        EQ_TempSSP1Data__c tempSsp1Record=new EQ_TempSSP1Data__c() ;
        String str='';
       list<EQ_TempSSP1Data__c> listtoupdate1 = new list<EQ_TempSSP1Data__c>();
       list<EQ_TempSSP1Data__c> tempSsp1Recordlist = new list<EQ_TempSSP1Data__c>();
       system.debug(': Heap size is--11 ' + limits.getHeapSize() + ' enforced is ' + limits.getLimitHeapSize());
        if(status=='PegaCallbackStatus.Error')
        {
           for(ErrorTempSSP1Data record:errorTempData.Values())
           {
               str='';
               list<String> listOferrors = record.mapErrors.get(record.Tempdata.id);
               if(listOferrors.size()>0)
               {
                for (integer i = 0; i < listOferrors.size() ;i++)
                    {
                        str=str+record.mapErrors.get(record.Tempdata.id);
                    }
                  
                    if(str!=null)
                    {
                         record.TempData.EQ_Errors__c =str;
                         record.TempData.EQ_ProcessStatus__c ='failure';
                         listtoupdate1.add(record.TempData);
                    }
                }
                
                
           }
            update listtoupdate1;
            
                
           }
  
   
   }


Finish :

global void finish(Database.BatchableContext BC)
   {
       
         status = (count == 0)
                ? 'PegaCallbackStatus.Complete'
                : 'PegaCallbackStatus.Error';
       
       
       validationHelper1.PegaCallbackServiceCall(status,count,workid,errorTempData);
}
 
public class PegaCallbackService 
{
private static Response res;
    public class Response {
        public  string access_token;
        public  string token_type;
        
    }
    
    
    private static string token_type;
    private static string token;
    
    public static void RequestAuthorizationToken(){
        try{
            HttpRequest request = new HttpRequest();
            HttpResponse response = new HttpResponse();
            Http http = new Http();
            String client_id = '10863622547421372260';
            String client_secret = 'DEB45EBE65B13D86D13E28F002C01D35';
            String grant_type = 'client_credentials';
            String reqbody = 'client_id='+client_id+'&client_secret='+client_secret+'&grant_type='+ grant_type;
            system.debug('req body--'+reqbody);
             
           // request.setEndpoint('https://equini-eqbill-dt1.pegacloud.net/prweb/PRRestService/oauth2/v1/token');
            request.setHeader('Content-Type','application/x-www-form-urlencoded'); 
           request.setMethod('POST');
            request.setBody(reqbody);
           	response = http.send(request);
          
            
           system.debug('--response'+response.getBody());
            res = (Response)JSON.deserialize(response.getBody(), Response.class);
			system.debug(res);
            if (response.getStatusCode() == 200) {
                System.debug('Response-' + response);
            }
        }
        catch(System.CalloutException e){
            System.debug('Error-' + e.getMessage());  
        }
    }
   @future(callout=true) 
   public static void SendValidationStatus(String json) {
        	res = new Response();
            RequestAuthorizationToken();
            HttpRequest request = new HttpRequest();
            HttpResponse response = new HttpResponse();
            Http http = new Http();
             
            request.setEndpoint('https://equini-eqbill-dt1.pegacloud.net/prweb/PRRestService/BillingUsagePackage/v1/ManageBillingUsage');
            request.setHeader('Content-Type','application/json');
       		system.debug(res);
       		request.setHeader('Authorization', res.token_type+' ' +res.access_token);
            request.setMethod('POST');
            request.setBody(json);
            response = http.send(request);
            if (response.getStatusCode() == 200) {
                System.debug('Response-' + response);
            }
        }  
  }

 
for(Apttus_Billing__Invoice__c invoice:invoiceObjectList1) // loop over invoices
              {
                  List<InvoiceLineItems> listToStoreLineItems = new List<InvoiceLineItems>();
                  APTS_InvoiceJournalWrapper invoiceJournWrapper= new APTS_InvoiceJournalWrapper();
                   countHeader=0;
                   
                   count=count+1;
                  Decimal Sum=0;
                   
                                    invoiceJournWrapper.id=String.valueof(invoice.id);
                                    invoiceJournWrapper.HeaderKey=String.valueof(count);
                                    invoiceJournWrapper.ZCurrency=(invoice.CurrencyIsoCode!=null?invoice.CurrencyIsoCode:'USD');
                                    //invoiceJournWrapper.AccountingJournal='null';
                                    invoiceJournWrapper.AccountingJournalID=String.valueOf(invoice.Name + '_' +myDate);
                                    invoiceJournWrapper.JournalNumber=String.valueOf(invoice.Name + '_' +myDate);
                                    invoiceJournWrapper.ExternalReferenceID=String.valueOf(invoice.Name);                  
                                    invoiceJournWrapper.AccountingDate=String.valueof(Date.valueof(invoice.Apttus_Billing__InvoiceDate__c));
                  //-------------------
                  list<Apttus_Billing__InvoiceLineItem__c> invlineitems=[Select id,Apttus_Billing__AssetLineItemId__r.Apttus_Config2__ProductId__r.ProductCode,Apttus_Billing__AssetLineItemId__r.Apttus_Config2__OptionId__r.ProductCode,Apttus_Billing__InvoiceId__r.Name,Apttus_Billing__ProductId__r.Name,Apttus_Billing__InvoiceId__r.CurrencyIsoCode,
                                                                      Apttus_Billing__Type__c,Apttus_Billing__InvoiceId__c,Name,Apttus_Billing__Amount__c,Apttus_Billing__SoldToAccountId__r.EQ_ClientRef__c,Apttus_Billing__LocationId__c,
                                                                      Apttus_Billing__ProductId__r.EQ_FeeCode__c,Apttus_Billing__BillToAccountId__r.EQ_ClientRef__c,Apttus_Billing__ProductId__r.ProductCode,Apttus_Billing__InvoiceId__r.EQ_TotalInvoiceAmount__c 
                                                             from Apttus_Billing__InvoiceLineItem__c where Apttus_Billing__InvoiceId__c=:invoice.id and Apttus_Billing__Type__c='Contracted' and Apttus_Billing__Amount__c!=0];
                  //----
                  //
                  //-------------
                   InvoiceLineItems FirstInvItems= new InvoiceLineItems();
                            countHeader=countHeader+1;
                            FirstInvItems.LineKey=string.valueof(countHeader);

 
I have to call a webservice hosted on Pega with below end point adress.
Need help in generati ng token and authentication part.

// Calling webservice
PegaCallbackService.SendValidationStatus(Json.Serialize(pegaResponse));

public class PegaCallbackService {
     
    @future (callout=true)
    public static void SendValidationStatus(String json) {
        try{
            HttpRequest request = new HttpRequest();
            HttpResponse response = new HttpResponse();
            Http http = new Http();
             
            request.setEndpoint('');
            request.setHeader('Content-Type','application/json'); 
            request.setMethod('POST');
            request.setBody(json);
            request.setCompressed(true);
            response = http.send(request);
            if (response.getStatusCode() == 200) {
                System.debug('Response-' + response);
            }
        }
        catch(System.CalloutException e){
            System.debug('Error-' + e.getMessage());   
        }
    }
}

I have created a basic structure but not sure how to do authentication part. How will it work.

​​​​​​​

Web Service : 

@RestResource(urlMapping='/UsageInput/') 
global class APTS_UsageInputWS {
   @HttpPost
    global static void loadUsageInputs ()
    { 
        RestRequest req =RestContext.request;
           Blob body = req.requestBody;
           String requestString = body.toString();
        APTS_UsageInputWrapper inputList = (APTS_UsageInputWrapper)JSON.deserialize(requestString,APTS_UsageInputWrapper.class);
        List<EQ_TempSSP1Data__c> tempData = new List<EQ_TempSSP1Data__c>();
        system.debug('***1');
        system.debug('%%%inputList');
        if(inputList.ValidateOnly)
        {
            validateData(inputList);
        }
        else
        {
            delete [select id from EQ_TempSSP1Data__c];
            Integer counter = 1;
            for(APTS_UsageInputWrapperData record : inputList.data)
            {
                tempData.add(new EQ_TempSSP1Data__c(EQ_WorkId__c = inputList.EQ_WorkId,
                            EQ_SourceSystem__c = record.EQ_SourceSystem,
                            EQ_IssueNumber__c = record.EQ_IssueNumber,
                            EQ_ServiceCode__c = record.EQ_ServiceCode,
                            EQ_Quantity__c = record.EQ_Quantity,
                            EQ_QuantityID__c = record.EQ_QuantityID,
                            EQ_RecordKey__c = record.EQ_RecordKey,
                            EQ_LoadMonth__c = Date.newInstance(Integer.valueOf(record.EQ_LoadMonth.left(4)), Integer.valueOf(record.EQ_LoadMonth.subString(4,5)), Integer.valueOf(record.EQ_LoadMonth.subString(6,7))),            
                            Name = counter + '-' + record.EQ_LoadMonth + '-' + record.EQ_IssueNumber));
                counter++;
            }
            insert tempData;
            system.debug('validation called%%%%');
            validateData(inputList);
        }
            
        
    }


JSON input:

{
 "EQ_Count":1,
 "EQ_WorkId":"B-080319-4",
 "ValidateOnly":False,
 "Data":
     [{"EQ_RecordKey":"ab3ff95a-42cc-4778-888d-e1f4c4beb78d",
     "EQ_LoadMonth":"20190101",
     "EQ_Quantity":32116,
     "EQ_ServiceCode":"trsactmata",
     "EQ_IssueNumber":"NW22",
     "EQ_SourceSystem":"SSP1",
     "EQ_QuantityID":"4737301"
     },
     {"EQ_RecordKey":"ab3ff95a-42cc-4778-888d-e1f4c4beb78d",
     "EQ_LoadMonth":"20190101",
     "EQ_Quantity":32116,
     "EQ_ServiceCode":"trsactmata",
     "EQ_IssueNumber":"NW22",
     "EQ_SourceSystem":"SSP1",
     "EQ_QuantityID":"4737301"
     }]
 }


While calling service from workbecnh getting error:


APEX_ERROR
message: System.JSONException: Unexpected character ('F' (code 70)): expected a valid value (number, String, array, object, 'true', 'false' or 'null') at [line:4, column:18] Class.System.JSON.deserialize: line 15, column 1 Class.APTS_UsageInputWS.loadUsageInputs: line 14, column 1

Request body :

{
    "StartDate": "2019-08-01",
    "EndDate": "2019-12-03"
}

Method : Post

Need to pass these parameters in my test class not sure how i cna do this

Test clasS:

static testMethod void testPost() {
        RestRequest req = new RestRequest(); 
        RestResponse res = new RestResponse();             
        req.requestURI = '/services/apexrest/WorkdayIntegration/';
        req.httpMethod = 'POST';
        RestContext.request = req;
        //req.requestBody=('2019/05/05','2019/06/05');
        RestContext.response= res;
        APTS_InvoiceDetailsWS.APTS_WorkdayIntegrationWrapper  results = APTS_InvoiceDetailsWS.getInvoiceDetails();
      
      
  }


Method : 
"InvoiceSourceSystem": "APTTUS",
    "ExternalCompanyId": "APTTUS",
    "FromDate": "2019-08-01",
    "ToDate": "2019-08-03",
    "TotalNumberOfInvoices": "109",
    "Invoices": [
        {
            "HeaderKey": "1",
            "AddOnly": "",
            "AutoComplete": "Y",
            "CustomerInvoiceID": "378958d7-d4af-e911-bcd0-00155d69e630",
            "Submit": "Y",
            "LockedinWorkday": "N",
            "Company": "5103",
            "Currency": "USD",
            "Customer": "EQ145959",
            "SoldToCustomer": "",
            "BillToContact": "",
            "BillToAddress": "",
            "RowID": "",
            "InvoiceNumber": "INV-000000003531",
            "InvoiceDate": "2019-07-26",
            "AccountingDate": "",
            "FromDate": "",
            "ToDate": "",
            "DueDateOverride": "2019-08-25",
            "ControlTotalAmount": "",
            "PaymentTerms": "",
            "PaymentType": "",
            "AmountDue": "20663.82",
            "IncludeCustomerWorktags": "",
            "Memo": "",
            "InvoiceLineItem": [
                {
                    "HeaderKey": "1",
                    "LineKey": "1",
                    "CustomerInvoiceLine": "",
                    "CustomerInvoiceLineReferenceID": "INV-000000003531-1",
                    "LineOrder": "",
                    "IntercompanyAffiliate": "",
                    "SalesItemIDType": "",
                    "SalesItemIDValue": "",
                    "RevenueCategory": "RC900",
                    "LineItemDescription": "Invoice total",
                    "ShipToCustomerIDType": "",
                    "ShipToCustomerIDValue": "",
                    "ShipToAddressIDType": "",
                    "ShipToAddressIDValue": "",
                    "Quantity": 1,
                    "UnitofMeasure": "EA",
                    "UnitCost": "",
                    "ExtendedAmount": "20663.82",
                    "TransactionDate": "",
                    "FromDate": "",
                    "ToDate": "",
                    "DeferredRevenue": "",
                    "RevenueRecognitionScheduleTemplate": "",
                    "Memo": "",
                    "AnalyticalAmount": "",
                    "Product": "",
                    "IssueNumber": "",
                    "IssueNumberType": "",
                    "CostCenter": ""
                },


My Code:

/*

 */
@RestResource(urlMapping='/WorkdayIntegration/') 
global class APTS_InvoiceDetailsWS
{

@HttpPost
    global static List<APTS_WorkdayIntegrationWrapper> getInvoiceDetails()
    { 
        
        String JsonString;
        RestRequest req = RestContext.request;        
        RestResponse res = RestContext.response;
         Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(RestContext.request.requestBody.toString());
        Date startDate=Date.valueOf((String)params.get('StartDate'));
        Date endDate=Date.valueOf((String)params.get('EndDate'));
        String approved='Approved';
        String query='Select id,Name,EQ_InvoiceApprovedDate__c,Apttus_billing__status__c,CurrencyIsoCode,Apttus_Billing__ShipToAccountId__r.EQ_ClientRef__c,Apttus_Billing__ShipToAccountId__r.EQ_ShippingState__c,Apttus_Billing__InvoiceDate__c,EQ_DueDateCustom__c,EQ_TotalTaxAmount__c from Apttus_Billing__Invoice__c where EQ_InvoiceApprovedDate__c>=:startDate and EQ_InvoiceApprovedDate__c<=:endDate and EQ_TotalInvoiceAmount__c > 0 and Apttus_billing__status__c=:approved'; 
            
        List<Apttus_Billing__Invoice__c> invoiceObjectList1=Database.query(query);
        List<APTS_WorkdayIntegrationWrapper> lstInvoiceHistory = new List<APTS_WorkdayIntegrationWrapper>();
        Integer count=0; 
      for(Apttus_Billing__Invoice__c invoice:invoiceObjectList1)
              {
               count=count+1;
               APTS_WorkdayIntegrationWrapper invoiceWrapper=new APTS_WorkdayIntegrationWrapper();
                invoiceWrapper.InvoiceSourceSystem='APTTUS';
                invoiceWrapper.ExternalCompanyId='APTTUS';
                invoiceWrapper.FromDate=(String)params.get('StartDate');
                invoiceWrapper.ToDate=(String)params.get('EndDate');
                invoiceWrapper.TotalNumberOfInvoices=count;
                invoiceWrapper.HeaderKey=null;
                invoiceWrapper.AddOnly='';
                invoiceWrapper.AutoComplete='Y';
                invoiceWrapper.CustomerInvoiceID=invoice.id;
                invoiceWrapper.Submit='Y';
                invoiceWrapper.LockedinWorkday='N';
                invoiceWrapper.Company='5103';
                invoiceWrapper.CurrencyISOCode=invoice.CurrencyIsoCode;
                invoiceWrapper.Customer=''; /* need to confirm accountr*/
                invoiceWrapper.SoldToCustomer='';
                invoiceWrapper.BillToContact='';
                invoiceWrapper.BillToAddress='';
                invoiceWrapper.RowID='';
                invoiceWrapper.InvoiceNumber=invoice.Name;
                invoiceWrapper.InvoiceDate=invoice.Apttus_Billing__InvoiceDate__c;
                invoiceWrapper.AccountingDate='';
                //invoiceWrapper.FromDate
                //invoiceWrapper.ToDate
                invoiceWrapper.DueDateOverride='';
                invoiceWrapper.ControlTotalAmount=invoice.EQ_TotalTaxAmount__c;
                invoiceWrapper.PaymentTerms='';
                invoiceWrapper.PaymentType='';
                invoiceWrapper.AmountDue='';
                invoiceWrapper.IncludeCustomerWorktags='';
                invoiceWrapper.Memo='';
                lstInvoiceHistory.add(invoiceWrapper);
             }
        return lstInvoiceHistory;
    }
    
    
    global class APTS_WorkdayIntegrationWrapper
    {
    
        public String InvoiceSourceSystem;
        public String ExternalCompanyId;
        public integer TotalNumberOfInvoices;
        public DecimAL HeaderKey;        
        public String AddOnly;
        public String AutoComplete;
        public String CustomerInvoiceID;
        public String Submit;
        public String LockedinWorkday;
       // public List<Invoices> Invoices;
        public String Company;
        public String CurrencyISOCode;
        public String Customer;
        public String SoldToCustomer;
        public String BillToContact;
        public String BillToAddress;
        public String RowID;
        public String InvoiceNumber;
        public DateTime InvoiceDate;
        public String AccountingDate;
        public String FromDate;
        public String ToDate;
        public String DueDateOverride;
        public Decimal ControlTotalAmount;
        public String PaymentTerms;
        public String PaymentType;
        public String AmountDue;
        public String IncludeCustomerWorktags;
        public String Memo;
        
      
    } 
     public class fromJSON
    {
        public String Parm1;    //Value1
        public String Parm2;    //Value2
    }
      
}
I am new to integration. I am writing a REST webservice which will accept dates as BODY  and use those dates in SOQL to extract the records. I am not able to get the dates in in my Webservice from body. Below is my code: 

/*

 */
@RestResource(urlMapping='/WorkdayIntegration/') 
global class APTS_InvoiceDetailsWS
{
    
@HttpPost
    global static List<APTS_WorkdayIntegrationWrapper> getInvoiceDetails()
    { 
        //Fetch an account
        RestRequest req = RestContext.request;
        String jsonBody = req.requestBody.toString(); //the body of the request
        
        
        RestResponse res = RestContext.response;
         
      List<Apttus_Billing__Invoice__c> invoiceObjectList=new List<Apttus_Billing__Invoice__c>(
          [Select id,Name,EQ_InvoiceApprovedDate__c,Apttus_billing__status__c,CurrencyIsoCode,Apttus_Billing__ShipToAccountId__r.EQ_ClientRef__c,Apttus_Billing__ShipToAccountId__r.EQ_ShippingState__c,
           Apttus_Billing__InvoiceDate__c,EQ_DueDateCustom__c,EQ_TotalTaxAmount__c
           from Apttus_Billing__Invoice__c where /*EQ_InvoiceApprovedDate__c>=:startDate and EQ_InvoiceApprovedDate__c <=: endDate */
            EQ_TotalInvoiceAmount__c > 0  and Apttus_billing__status__c= 'Approved'  limit 4]);
        
      List<APTS_WorkdayIntegrationWrapper> lstInvoiceHistory = new List<APTS_WorkdayIntegrationWrapper>(); 
      for(Apttus_Billing__Invoice__c invoice:invoiceObjectList)
              {
                APTS_WorkdayIntegrationWrapper invoiceWrapper=new APTS_WorkdayIntegrationWrapper();
                invoiceWrapper.InvoiceName=invoice.Name;
                invoiceWrapper.CountryISOCode=invoice.CurrencyIsoCode;
                invoiceWrapper.InvoiceId=invoice.id;
                invoiceWrapper.ClientReference=invoice.Apttus_Billing__ShipToAccountId__r.EQ_ClientRef__c;
                invoiceWrapper.ShippState=invoice.Apttus_Billing__ShipToAccountId__r.EQ_ShippingState__c;
                invoiceWrapper.InvoiceDate=invoice.Apttus_Billing__InvoiceDate__c;
                invoiceWrapper.InvoiceAmount= invoice.EQ_TotalTaxAmount__c;
                invoiceWrapper.InvoiceSourceSystem='APTTUS';
    invoiceWrapper.ExternalCompanyId='APTTUS';
    invoiceWrapper.FromDate= '2019-08-01';
    invoiceWrapper.ToDate= '2019-08-03';
    invoiceWrapper.TotalNumberOfInvoices= 109;
            lstInvoiceHistory.add(invoiceWrapper);
            JSON.serialize(lstInvoiceHistory);
                  
              }
        
        
        return lstInvoiceHistory;
    }
    
    
    global class APTS_WorkdayIntegrationWrapper
    {
      public String InvoiceName;
        public string InvoiceSourceSystem;
        public string ExternalCompanyId;
    public string FromDate;
    public string  ToDate;
    public decimal TotalNumberOfInvoices;
        
        public String InvoiceId;
        public String CountryISOCode;
        public String ClientReference;
        public String ShippState;
        public dateTime InvoiceDate;
        public Decimal InvoiceAmount;
        public date InvoiceDueDate;
    } 
    
}
for(Apttus_Billing__Invoice__c invoice:invoiceObjectList1) // loop over invoices
              {
                  List<InvoiceLineItems> listToStoreLineItems = new List<InvoiceLineItems>();
                  APTS_InvoiceJournalWrapper invoiceJournWrapper= new APTS_InvoiceJournalWrapper();
                   countHeader=0;
                   
                   count=count+1;
                  Decimal Sum=0;
                   
                                    invoiceJournWrapper.id=String.valueof(invoice.id);
                                    invoiceJournWrapper.HeaderKey=String.valueof(count);
                                    invoiceJournWrapper.ZCurrency=(invoice.CurrencyIsoCode!=null?invoice.CurrencyIsoCode:'USD');
                                    //invoiceJournWrapper.AccountingJournal='null';
                                    invoiceJournWrapper.AccountingJournalID=String.valueOf(invoice.Name + '_' +myDate);
                                    invoiceJournWrapper.JournalNumber=String.valueOf(invoice.Name + '_' +myDate);
                                    invoiceJournWrapper.ExternalReferenceID=String.valueOf(invoice.Name);                  
                                    invoiceJournWrapper.AccountingDate=String.valueof(Date.valueof(invoice.Apttus_Billing__InvoiceDate__c));
                  //-------------------
                  list<Apttus_Billing__InvoiceLineItem__c> invlineitems=[Select id,Apttus_Billing__AssetLineItemId__r.Apttus_Config2__ProductId__r.ProductCode,Apttus_Billing__AssetLineItemId__r.Apttus_Config2__OptionId__r.ProductCode,Apttus_Billing__InvoiceId__r.Name,Apttus_Billing__ProductId__r.Name,Apttus_Billing__InvoiceId__r.CurrencyIsoCode,
                                                                      Apttus_Billing__Type__c,Apttus_Billing__InvoiceId__c,Name,Apttus_Billing__Amount__c,Apttus_Billing__SoldToAccountId__r.EQ_ClientRef__c,Apttus_Billing__LocationId__c,
                                                                      Apttus_Billing__ProductId__r.EQ_FeeCode__c,Apttus_Billing__BillToAccountId__r.EQ_ClientRef__c,Apttus_Billing__ProductId__r.ProductCode,Apttus_Billing__InvoiceId__r.EQ_TotalInvoiceAmount__c 
                                                             from Apttus_Billing__InvoiceLineItem__c where Apttus_Billing__InvoiceId__c=:invoice.id and Apttus_Billing__Type__c='Contracted' and Apttus_Billing__Amount__c!=0];
                  //----
                  //
                  //-------------
                   InvoiceLineItems FirstInvItems= new InvoiceLineItems();
                            countHeader=countHeader+1;
                            FirstInvItems.LineKey=string.valueof(countHeader);

 
for(Apttus_Billing__Invoice__c invoice:invoiceObjectList1) // loop over invoices
              {
                  List<InvoiceLineItems> listToStoreLineItems = new List<InvoiceLineItems>();
                  APTS_InvoiceJournalWrapper invoiceJournWrapper= new APTS_InvoiceJournalWrapper();
                   countHeader=0;
                   
                   count=count+1;
                  Decimal Sum=0;
                   
                                    invoiceJournWrapper.id=String.valueof(invoice.id);
                                    invoiceJournWrapper.HeaderKey=String.valueof(count);
                                    invoiceJournWrapper.ZCurrency=(invoice.CurrencyIsoCode!=null?invoice.CurrencyIsoCode:'USD');
                                    //invoiceJournWrapper.AccountingJournal='null';
                                    invoiceJournWrapper.AccountingJournalID=String.valueOf(invoice.Name + '_' +myDate);
                                    invoiceJournWrapper.JournalNumber=String.valueOf(invoice.Name + '_' +myDate);
                                    invoiceJournWrapper.ExternalReferenceID=String.valueOf(invoice.Name);                  
                                    invoiceJournWrapper.AccountingDate=String.valueof(Date.valueof(invoice.Apttus_Billing__InvoiceDate__c));
                  //-------------------
                  list<Apttus_Billing__InvoiceLineItem__c> invlineitems=[Select id,Apttus_Billing__AssetLineItemId__r.Apttus_Config2__ProductId__r.ProductCode,Apttus_Billing__AssetLineItemId__r.Apttus_Config2__OptionId__r.ProductCode,Apttus_Billing__InvoiceId__r.Name,Apttus_Billing__ProductId__r.Name,Apttus_Billing__InvoiceId__r.CurrencyIsoCode,
                                                                      Apttus_Billing__Type__c,Apttus_Billing__InvoiceId__c,Name,Apttus_Billing__Amount__c,Apttus_Billing__SoldToAccountId__r.EQ_ClientRef__c,Apttus_Billing__LocationId__c,
                                                                      Apttus_Billing__ProductId__r.EQ_FeeCode__c,Apttus_Billing__BillToAccountId__r.EQ_ClientRef__c,Apttus_Billing__ProductId__r.ProductCode,Apttus_Billing__InvoiceId__r.EQ_TotalInvoiceAmount__c 
                                                             from Apttus_Billing__InvoiceLineItem__c where Apttus_Billing__InvoiceId__c=:invoice.id and Apttus_Billing__Type__c='Contracted' and Apttus_Billing__Amount__c!=0];
                  //----
                  //
                  //-------------
                   InvoiceLineItems FirstInvItems= new InvoiceLineItems();
                            countHeader=countHeader+1;
                            FirstInvItems.LineKey=string.valueof(countHeader);

 

Web Service : 

@RestResource(urlMapping='/UsageInput/') 
global class APTS_UsageInputWS {
   @HttpPost
    global static void loadUsageInputs ()
    { 
        RestRequest req =RestContext.request;
           Blob body = req.requestBody;
           String requestString = body.toString();
        APTS_UsageInputWrapper inputList = (APTS_UsageInputWrapper)JSON.deserialize(requestString,APTS_UsageInputWrapper.class);
        List<EQ_TempSSP1Data__c> tempData = new List<EQ_TempSSP1Data__c>();
        system.debug('***1');
        system.debug('%%%inputList');
        if(inputList.ValidateOnly)
        {
            validateData(inputList);
        }
        else
        {
            delete [select id from EQ_TempSSP1Data__c];
            Integer counter = 1;
            for(APTS_UsageInputWrapperData record : inputList.data)
            {
                tempData.add(new EQ_TempSSP1Data__c(EQ_WorkId__c = inputList.EQ_WorkId,
                            EQ_SourceSystem__c = record.EQ_SourceSystem,
                            EQ_IssueNumber__c = record.EQ_IssueNumber,
                            EQ_ServiceCode__c = record.EQ_ServiceCode,
                            EQ_Quantity__c = record.EQ_Quantity,
                            EQ_QuantityID__c = record.EQ_QuantityID,
                            EQ_RecordKey__c = record.EQ_RecordKey,
                            EQ_LoadMonth__c = Date.newInstance(Integer.valueOf(record.EQ_LoadMonth.left(4)), Integer.valueOf(record.EQ_LoadMonth.subString(4,5)), Integer.valueOf(record.EQ_LoadMonth.subString(6,7))),            
                            Name = counter + '-' + record.EQ_LoadMonth + '-' + record.EQ_IssueNumber));
                counter++;
            }
            insert tempData;
            system.debug('validation called%%%%');
            validateData(inputList);
        }
            
        
    }


JSON input:

{
 "EQ_Count":1,
 "EQ_WorkId":"B-080319-4",
 "ValidateOnly":False,
 "Data":
     [{"EQ_RecordKey":"ab3ff95a-42cc-4778-888d-e1f4c4beb78d",
     "EQ_LoadMonth":"20190101",
     "EQ_Quantity":32116,
     "EQ_ServiceCode":"trsactmata",
     "EQ_IssueNumber":"NW22",
     "EQ_SourceSystem":"SSP1",
     "EQ_QuantityID":"4737301"
     },
     {"EQ_RecordKey":"ab3ff95a-42cc-4778-888d-e1f4c4beb78d",
     "EQ_LoadMonth":"20190101",
     "EQ_Quantity":32116,
     "EQ_ServiceCode":"trsactmata",
     "EQ_IssueNumber":"NW22",
     "EQ_SourceSystem":"SSP1",
     "EQ_QuantityID":"4737301"
     }]
 }


While calling service from workbecnh getting error:


APEX_ERROR
message: System.JSONException: Unexpected character ('F' (code 70)): expected a valid value (number, String, array, object, 'true', 'false' or 'null') at [line:4, column:18] Class.System.JSON.deserialize: line 15, column 1 Class.APTS_UsageInputWS.loadUsageInputs: line 14, column 1

Request body :

{
    "StartDate": "2019-08-01",
    "EndDate": "2019-12-03"
}

Method : Post

Need to pass these parameters in my test class not sure how i cna do this

Test clasS:

static testMethod void testPost() {
        RestRequest req = new RestRequest(); 
        RestResponse res = new RestResponse();             
        req.requestURI = '/services/apexrest/WorkdayIntegration/';
        req.httpMethod = 'POST';
        RestContext.request = req;
        //req.requestBody=('2019/05/05','2019/06/05');
        RestContext.response= res;
        APTS_InvoiceDetailsWS.APTS_WorkdayIntegrationWrapper  results = APTS_InvoiceDetailsWS.getInvoiceDetails();
      
      
  }


Method : 
"InvoiceSourceSystem": "APTTUS",
    "ExternalCompanyId": "APTTUS",
    "FromDate": "2019-08-01",
    "ToDate": "2019-08-03",
    "TotalNumberOfInvoices": "109",
    "Invoices": [
        {
            "HeaderKey": "1",
            "AddOnly": "",
            "AutoComplete": "Y",
            "CustomerInvoiceID": "378958d7-d4af-e911-bcd0-00155d69e630",
            "Submit": "Y",
            "LockedinWorkday": "N",
            "Company": "5103",
            "Currency": "USD",
            "Customer": "EQ145959",
            "SoldToCustomer": "",
            "BillToContact": "",
            "BillToAddress": "",
            "RowID": "",
            "InvoiceNumber": "INV-000000003531",
            "InvoiceDate": "2019-07-26",
            "AccountingDate": "",
            "FromDate": "",
            "ToDate": "",
            "DueDateOverride": "2019-08-25",
            "ControlTotalAmount": "",
            "PaymentTerms": "",
            "PaymentType": "",
            "AmountDue": "20663.82",
            "IncludeCustomerWorktags": "",
            "Memo": "",
            "InvoiceLineItem": [
                {
                    "HeaderKey": "1",
                    "LineKey": "1",
                    "CustomerInvoiceLine": "",
                    "CustomerInvoiceLineReferenceID": "INV-000000003531-1",
                    "LineOrder": "",
                    "IntercompanyAffiliate": "",
                    "SalesItemIDType": "",
                    "SalesItemIDValue": "",
                    "RevenueCategory": "RC900",
                    "LineItemDescription": "Invoice total",
                    "ShipToCustomerIDType": "",
                    "ShipToCustomerIDValue": "",
                    "ShipToAddressIDType": "",
                    "ShipToAddressIDValue": "",
                    "Quantity": 1,
                    "UnitofMeasure": "EA",
                    "UnitCost": "",
                    "ExtendedAmount": "20663.82",
                    "TransactionDate": "",
                    "FromDate": "",
                    "ToDate": "",
                    "DeferredRevenue": "",
                    "RevenueRecognitionScheduleTemplate": "",
                    "Memo": "",
                    "AnalyticalAmount": "",
                    "Product": "",
                    "IssueNumber": "",
                    "IssueNumberType": "",
                    "CostCenter": ""
                },


My Code:

/*

 */
@RestResource(urlMapping='/WorkdayIntegration/') 
global class APTS_InvoiceDetailsWS
{

@HttpPost
    global static List<APTS_WorkdayIntegrationWrapper> getInvoiceDetails()
    { 
        
        String JsonString;
        RestRequest req = RestContext.request;        
        RestResponse res = RestContext.response;
         Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(RestContext.request.requestBody.toString());
        Date startDate=Date.valueOf((String)params.get('StartDate'));
        Date endDate=Date.valueOf((String)params.get('EndDate'));
        String approved='Approved';
        String query='Select id,Name,EQ_InvoiceApprovedDate__c,Apttus_billing__status__c,CurrencyIsoCode,Apttus_Billing__ShipToAccountId__r.EQ_ClientRef__c,Apttus_Billing__ShipToAccountId__r.EQ_ShippingState__c,Apttus_Billing__InvoiceDate__c,EQ_DueDateCustom__c,EQ_TotalTaxAmount__c from Apttus_Billing__Invoice__c where EQ_InvoiceApprovedDate__c>=:startDate and EQ_InvoiceApprovedDate__c<=:endDate and EQ_TotalInvoiceAmount__c > 0 and Apttus_billing__status__c=:approved'; 
            
        List<Apttus_Billing__Invoice__c> invoiceObjectList1=Database.query(query);
        List<APTS_WorkdayIntegrationWrapper> lstInvoiceHistory = new List<APTS_WorkdayIntegrationWrapper>();
        Integer count=0; 
      for(Apttus_Billing__Invoice__c invoice:invoiceObjectList1)
              {
               count=count+1;
               APTS_WorkdayIntegrationWrapper invoiceWrapper=new APTS_WorkdayIntegrationWrapper();
                invoiceWrapper.InvoiceSourceSystem='APTTUS';
                invoiceWrapper.ExternalCompanyId='APTTUS';
                invoiceWrapper.FromDate=(String)params.get('StartDate');
                invoiceWrapper.ToDate=(String)params.get('EndDate');
                invoiceWrapper.TotalNumberOfInvoices=count;
                invoiceWrapper.HeaderKey=null;
                invoiceWrapper.AddOnly='';
                invoiceWrapper.AutoComplete='Y';
                invoiceWrapper.CustomerInvoiceID=invoice.id;
                invoiceWrapper.Submit='Y';
                invoiceWrapper.LockedinWorkday='N';
                invoiceWrapper.Company='5103';
                invoiceWrapper.CurrencyISOCode=invoice.CurrencyIsoCode;
                invoiceWrapper.Customer=''; /* need to confirm accountr*/
                invoiceWrapper.SoldToCustomer='';
                invoiceWrapper.BillToContact='';
                invoiceWrapper.BillToAddress='';
                invoiceWrapper.RowID='';
                invoiceWrapper.InvoiceNumber=invoice.Name;
                invoiceWrapper.InvoiceDate=invoice.Apttus_Billing__InvoiceDate__c;
                invoiceWrapper.AccountingDate='';
                //invoiceWrapper.FromDate
                //invoiceWrapper.ToDate
                invoiceWrapper.DueDateOverride='';
                invoiceWrapper.ControlTotalAmount=invoice.EQ_TotalTaxAmount__c;
                invoiceWrapper.PaymentTerms='';
                invoiceWrapper.PaymentType='';
                invoiceWrapper.AmountDue='';
                invoiceWrapper.IncludeCustomerWorktags='';
                invoiceWrapper.Memo='';
                lstInvoiceHistory.add(invoiceWrapper);
             }
        return lstInvoiceHistory;
    }
    
    
    global class APTS_WorkdayIntegrationWrapper
    {
    
        public String InvoiceSourceSystem;
        public String ExternalCompanyId;
        public integer TotalNumberOfInvoices;
        public DecimAL HeaderKey;        
        public String AddOnly;
        public String AutoComplete;
        public String CustomerInvoiceID;
        public String Submit;
        public String LockedinWorkday;
       // public List<Invoices> Invoices;
        public String Company;
        public String CurrencyISOCode;
        public String Customer;
        public String SoldToCustomer;
        public String BillToContact;
        public String BillToAddress;
        public String RowID;
        public String InvoiceNumber;
        public DateTime InvoiceDate;
        public String AccountingDate;
        public String FromDate;
        public String ToDate;
        public String DueDateOverride;
        public Decimal ControlTotalAmount;
        public String PaymentTerms;
        public String PaymentType;
        public String AmountDue;
        public String IncludeCustomerWorktags;
        public String Memo;
        
      
    } 
     public class fromJSON
    {
        public String Parm1;    //Value1
        public String Parm2;    //Value2
    }
      
}