top of page

Mass Contract Creation : Transforming Quotes into Contracts: A Streamlined Process in Salesforce

Updated: Dec 1, 2023




Github Link : https://github.com/AourLegacy/AourFactory/tree/MassContractCreation


Introduction

In the world of business, efficiency and accuracy are key. This is especially true when it comes to generating contracts from quotes. Salesforce offers a robust solution for this, allowing you to create multiple contracts with ease, customize them with different parameters, and ensure all relevant details are carried over from the original quote.


The Process Overview

The process starts with a quote, which forms the basis of your contract. Here's a step-by-step guide on how this transformation occurs:


1. Cloning the Quote

- Cloning Mechanism: Using an automated flow, the original quote is cloned. This includes all the quote lines, ensuring that every detail is replicated in the new contract.


2. Selecting Additional Parameters

- User Interaction: A screen in the flow allows users to select a 'dummyObject' and an 'order'. These selections are crucial as they define additional contract terms.

- Customization: This step demonstrates the flexibility of the process, where different parameters can be chosen for each contract.


3. Linking to the Cloned Quote

- Data Integration: The cloned quote is then linked to the new contract, ensuring a seamless transition of data.

- Consistency: This step guarantees that all the information from the quote is accurately reflected in the contract.


4. Utilizing Apex Classes

- Backend Processing: An Apex class takes the input data (DummyObject ID, Order ID, and Quote ID) and performs the cloning and contract creation.

- Screenshots and Code Snippets:

Here is The Flow :













The Apex Classe :


public class MassContractCreation {

@InvocableMethod(callout=true label='Mass Contract Creation')

public static void QuoteRefenerenceMain(List<FlowInput> inputs ) {


Id recordId = inputs[0].recordId;

Id DummyObjectId = inputs[0].DummyObjectId;

Id OrderId = inputs[0].OrderId;

cloneQuote(recordId,DummyObjectId,OrderId);


}

public static void cloneQuote(Id quoteId, Id DummyObjectId,Id OrderId) {

// Retrieve the quote and its quote lines

SBQQ__Quote__c originalQuote = [SELECT BillingAdresse__c, BundleDiscountAmount__c, BundleDiscountPercentage__c, DiscountAmount__c, Discount1__c, DifficultytoMaintainCustomer__c, DeltaDiscount__c, CreatedDate, CreatedById, IsDeleted, NBbundle__c, NetAfterTva__c, NombreDevisiteur__c, NombreUtilisateur__c, Objectif__c, Optional__c, OwnerId, PartnerLevel__c, Pricehold__c, PricingMethods__c, PrixNegocie__c, Process__c, SBQQ__AdditionalDiscountAmount__c, SBQQ__Account__c, Promotion__c, SBQQ__AverageCustomerDiscount__c, SBQQ__AveragePartnerDiscount__c, SBQQ__Distributor__c, SBQQ__DeliveryMethod__c, SBQQ__DefaultTemplate__c, SBQQ__DaysQuoteOpen__c, SBQQ__CustomerDiscount__c, SBQQ__CustomerAmount__c, SBQQ__ContractingMethod__c, SBQQ__ConsumptionRateOverride__c, SBQQ__DistributorDiscount__c, SBQQ__EndDate__c, SBQQ__ExpirationDate__c, SBQQ__FirstSegmentTermEndDate__c, SBQQ__MarkupRate__c, SBQQ__ListAmount__c, SBQQ__LineItemsPrinted__c, SBQQ__LineItemsGrouped__c, SBQQ__LineItemCount__c, SBQQ__MasterEvergreenContract__c, SBQQ__NetAmount__c, SBQQ__Notes__c, SBQQ__Opportunity2__c, SBQQ__OrderBy__c, SBQQ__OrderByQuoteLineGroup__c, SBQQ__Ordered__c, SBQQ__Primary__c, SBQQ__PricebookId__c, SBQQ__PriceBook__c, SBQQ__PaymentTerms__c, SBQQ__PartnerDiscount__c, SBQQ__Partner__c, SBQQ__OriginalQuote__c, SBQQ__PrimaryContact__c, SBQQ__RegularAmount__c, SBQQ__RenewalTerm__c, SBQQ__StartDate__c, SBQQ__Source__c , SBQQ__SalesRep__c, SBQQ__Status__c, SBQQ__SubscriptionTerm__c, SBQQ__Type__c, SBQQ__Uncalculated__c FROM SBQQ__Quote__c WHERE Id = :quoteId LIMIT 1];

List<SBQQ__QuoteLine__c> originalQuoteLines = [SELECT SBQQ__MaximumPrice__c, SBQQ__Bundle__c, SBQQ__Bundled__c, SBQQ__BundledQuantity__c, SBQQ__AdditionalDiscountAmount__c, SBQQ__AdditionalDiscount__c, SBQQ__AdditionalQuantity__c, SBQQ__Product__c, SBQQ__Quote__c, SBQQ__NetPrice__c, SBQQ__ListPrice__c, SBQQ__ListTotal__c, SBQQ__OriginalPrice__c FROM SBQQ__QuoteLine__c WHERE SBQQ__Quote__c = :quoteId];

SBQQ__Quote__c clonedQuote = originalQuote.clone(false, true, false, false);

clonedQuote.SBQQ__Primary__c = false;

insert clonedQuote;


List<SBQQ__QuoteLine__c> clonedQuoteLines = new List<SBQQ__QuoteLine__c>();


for (SBQQ__QuoteLine__c line : originalQuoteLines) {

SBQQ__QuoteLine__c newLine = line.clone(false, true, false, false);

newLine.SBQQ__Quote__c = clonedQuote.Id; // Associate with the new quote

clonedQuoteLines.add(newLine);

}



// Insert the cloned quote lines

if(clonedQuoteLines!= null && !clonedQuoteLines.isEmpty()) Insert clonedQuoteLines;

Set<Id> newIds = new Set<Id>();

for(SBQQ__QuoteLine__c newQli : clonedQuoteLines) {

newIds.add(newQli.Id);

}

List<SBQQ__QuoteLine__c> clonedQlis = [Select Id, SBQQ__Source__c, SBQQ__Source__r.SBQQ__RequiredBy__c , SBQQ__RequiredBy__c FROM SBQQ__QuoteLine__c WHERE Id In :newIds];

Map<Id, Id> newLineToRequiredBySrcMap = new Map<Id, Id>();

Map<Id, Id> srcReqMap = new Map<Id, Id>();

for(SBQQ__QuoteLine__c newQli : clonedQlis) {

newLineToRequiredBySrcMap.put(newQli.Id, newQli.SBQQ__Source__r.SBQQ__RequiredBy__c);

srcReqMap.put(newQli.SBQQ__Source__c, newQli.Id);

}

for(SBQQ__QuoteLine__c newQli : clonedQlis) {

newQli.SBQQ__RequiredBy__c = srcReqMap.get(newLineToRequiredBySrcMap.get(newQli.Id));

}

if(clonedQlis!= null && !clonedQlis.isEmpty()) update clonedQlis;


Contract newContract = new Contract(AccountId = originalQuote.SBQQ__Account__c, StartDate = System.today(), Status = 'Draft',DummyObject__c = DummyObjectId, SBQQ__Order__c = OrderId , SBQQ__Quote__c = clonedQuote.Id );

insert newContract;




}


public class FlowInput {

@InvocableVariable(label='Record ID' required=true)

public Id recordId;

@InvocableVariable(label='DummyObject Id' required=true)

public Id DummyObjectId;

@InvocableVariable(label='Order Id' required=true)

public Id OrderId ;

}

}


Benefits of the Process

- Efficiency: This automated process saves significant time and reduces manual errors.

- Flexibility: Ability to customize contracts with different parameters.

- Scalability: Easily create multiple contracts from a single quote.


Conclusion

This streamlined process in Salesforce not only makes contract creation efficient but also customizable and error-free. By integrating user choices at the flow level and employing Apex classes for backend processing, businesses can ensure that their contracts are always in sync with their quotes, tailored to their specific needs.



0 views0 comments

Recent Posts

See All

Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
bottom of page