Search code examples
salesforceapexapex-codesfdc

How to perform a batch update using apex to do uplifts?


Firstly sorry as I am new to Apex and not sure where to start and what I need to do. My background is from Java and although it looks familiar I am unsure of what to do or how to start it.

I am trying to do a batch apex job that:

If uplift start date(new filed) is 10 months from start date(existing field) then:

  • create an amendment quote for the contract and set the amendment date to uplift date (a new field)
  • Copy the products that was previously added, set the existing quote line item to quantity of 0 and set the end date field to uplift start date and add a new start date (uplift) and keep original end date
  • Complete quote by by-passing validation.

I do apologies, from what I have seen I know people show a code sample of what they have done and tried but as I am unfamiliar, I am not sure what I need to do or how to even find where to code in Apex.


Solution

  • Your question is very specific to your org, full of jargon that won't make much sense in other Salesforce orgs. We don't even know what's your link between quote and contract? Out of the box there's no direct link as far as I know, I guess you could go "up" to Opportunity then "down" to Quotes... What does it even mean to "by-passing validation", do you set some special field on Quote or what.

    You'll need to throw a proper business analyst at it or ask the user to demonstrate what they need manually (maybe record user's screen even) and then you can have a stab at automating it.

    What's "amendment quote", a "record type"?

    I mean "If uplift start date(new filed) is 10 months from start date(existing field)" - where are these fields, on Opportunity? Quote? Contract? lets say 10 contracts meet this condition. Let's say you have this batch wrtitten and it runs every night. What will happen tomorrow? Will it take same 10 records and process them again, kill & create new quotes? Where's some "today" element in this spec?


    As for technicalities... you'll need few moving parts.

    A skeleton of a batch job that can be scheduled to run daily

    public class Stack74373895 implements Database.Batchable<SObject>, Schedulable {
      public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator([SELECT Id FROM ...]);
      }
    
      public void execute(Database.BatchableContext bc, List<sObject> scope) {
        ...
      }
    
      public void finish(Database.BatchableContext bc) {
      }
    
      public void execute(SchedulableContext sc) {
        Database.executeBatch(this);
      }
    }
    

    Some way to identify eligible... contracts? Experiment with queries in Developer Console and put one in start() method once you're happy. SOQL doesn't let you compare field to field (only field to literal) so if you really need 2 fields - you could cheat by making a formula field of type Checkbox (boolean) and something like ADDMONTHS(StartDate__c, 10) = UpliftStartDate__c. Then in your query you can SELECT Id FROM Contract WHERE MyField__c = true (although as I said above, this sounds bit naive and if your batch will run every night - will it keep creating quotes every time?)

    Actual code to "deep clone" 1 quote with line items? Something like this should be close enough, no promises it compiles!

    Id quoteId = '0Q0...';
    Quote original = [SELECT Id, AccountId, ContractId, OpportunityId, Pricebook2Id, 
      (SELECT Id, Description, OpportunityLineItemId, PricebookEntryId, Product2Id, Quantity, UnitPrice
      FROM QuoteLineItems 
      ORDER BY LineNumber)
      FROM Quote
      WHERE Id = :quoteId];
    
    Quote clone = original.clone(false, true);
    insert clone;
    List<QuoteLineItem> lineItems = original.QuoteLineItems.deepClone(false);
    for(QuoteLineItem li : lineItems){
      li.QuoteId = clone.Id;
    }
    insert lineItems;
    
    // set quantities on old line items to 0?
    for(QuoteLineItem li : original.QuoteLineItems){
      li.Quantity = 0;
    }
    update original.QuoteLineItems;