Download PDF
Download page Enabling Auto-Reapproval on Proposal and Proposal Line Items.
Enabling Auto-Reapproval on Proposal and Proposal Line Items
This API takes several parameters and updates the reapproval data in the process instance so that proposal line items can be automatically reapproved when resubmitted after finalizing new items in the cart. This API is available in the base Approvals package,
API | Signature |
---|---|
updateApprovalData | webService static Boolean updateApprovalData(Id instanceId, String sObjectType, Id contextObjId, List oldContextObjIds, List newContextObjIds) |
Request Parameters | |||
---|---|---|---|
Name | Type | Required? | Description |
instanceId | ID | Yes | The process instance ID currently running in the system |
sObjectType | String | Yes | The sObject type used to identify the object type |
contextObjId | ID | Yes | The ID of the context object |
oldContextObjIds | List<ID>oldContextObjIds | Yes | The list of approval data context object IDs to be replaced |
newContextObjIds | List<ID> newContextObjIds | Yes | The list of new approval data context object IDs |
Response Parameter | |||
---|---|---|---|
Name | Type | Required | Description |
Ok | Boolean | Yes | Defines if the operation was successful. Returns true if yes, otherwise false. |
Code Sample
The sample below enables you to execute auto-reapprovals over proposal line items by considering input parameters such as process instance, sObject type, context object, and lists of old and new context object IDs. These IDs represent the proposal line-item IDs before and after the cart is finalized. You can use this API, for example, when a quote or proposal is approved but the approvals manager changes the discount from 10 to 15% on a proposal line item. You can resubmit the approval request for reapproval. The system honors the auto-reapproval criteria, using which, a request once approved by certain assignees is auto-approved.
/**
*Apttus Approvals Management
*CustomProposalLineItemTrigger
*@2017 Apttus Inc. All rights reserved.
*/
trigger CustomProposalLineItemTrigger on Apttus_Proposal__Proposal_Line_Item__c (before delete, after insert)
{
if (Trigger.isBefore && Trigger.isDelete)
{
// save map of old line items to attributes before they are deleted
CustomProposalLineItemSupport.doBeforeDelete(Trigger.old, Trigger.oldMap);
}
if (Trigger.isAfter && Trigger.isInsert)
{
// update reapproval data with new line items after they are inserted
CustomProposalLineItemSupport.doAfterInsert(Trigger.new, Trigger.newMap);
}
}
/**
*Apttus Approvals Management
*CustomProposalLineItemSupport
* @2017 Apttus Inc. All rights reserved.
*/
public with sharing class CustomProposalLineItemSupport extends CustomApprovalsConstants
{
// line item types
private static final String LINETYPE_PRODUCT = 'Product/Service';
private static final String LINETYPE_OPTION = 'Option';
// proposal
private static final String PROPOSAL_SOBJECT_TYPE = 'Apttus_Proposal__Proposal__c';
private static ID quoteId = null;
// associated process instance
private static Apttus_Approval__ApprovalProcessInstance__c quoteProcessInstance = null;
// map of old line item ids to attribute key
private static Map<ID,String> oldLineId2KeyMap = new Map<ID,String>();
// map of new line item attribute key to id
private static Map<String,ID> newLineKey2IdMap = new Map<String,ID>();
// map of old line item ids to new line item ids
private static Map<ID,ID> lineOldId2NewIdMap = new Map<ID,ID>();
/**
* Process old ProposalLineItems before they are deleted when a cart is finalized
* @param oldLineItems - a list of the old versions of the sObject records
* @param oldLineItemsMap - a map of IDs to the old versions of the sObject records
*/
public static void doBeforeDelete( List<Apttus_Proposal__Proposal_Line_Item__c> oldLineItems, Map<ID, Apttus_Proposal__Proposal_Line_Item__c> oldLineItemsMap)
{
// iterate over line items about to deleted
for (Integer i=0; i<oldLineItems.size(); i++)
{
Apttus_Proposal__Proposal_Line_Item__c oldLineItem = oldLineItems[i];
// get quote from line item
quoteId = oldLineItem.Apttus_Proposal__Proposal__c;
// get line item attributes
String lineNumber = String.valueOf(oldLineItem.Apttus_QPConfig__PrimaryLineNumber__c);
String lineType = oldLineItem.Apttus_QPConfig__LineType__c;
String productId = null;
if (lineType == LINETYPE_PRODUCT)
{
productId = oldLineItem.Apttus_Proposal__Product__c;
}
else if (lineType == LINETYPE_OPTION)
{
productId = oldLineItem.Apttus_QPConfig__OptionId__c;
//productId = oldLineItem.Apttus_QPConfig__ProductOptionId__c;
}
String chargeType = oldLineItem.Apttus_QPConfig__ChargeType__c;
// create attribute key
String oldLineKey = lineNumber + ':' + productId + ':' + chargeType;
// save in map
oldLineId2KeyMap.put(oldLineItem.Id, oldLineKey);
}
}
/**
* Process new ProposalLineItems after they are inserted when a cart is finalized
* @param newLineItems - a list of the new versions of the sObject records
* @param newLineItemsMap - a map of IDs to the new versions of the sObject records
*/
public static void doAfterInsert(List<Apttus_Proposal__Proposal_Line_Item__c> newLineItems, Map<ID, Apttus_Proposal__Proposal_Line_Item__c> newLineItemsMap)
{
// iterate over line items about to deleted
for (Integer i=0; i<newLineItems.size(); i++)
{
Apttus_Proposal__Proposal_Line_Item__c newLineItem = newLineItems[i];
// get quote from line item
quoteId = newLineItem.Apttus_Proposal__Proposal__c;
// get line item attributes
String lineNumber = String.valueOf(newLineItem.Apttus_QPConfig__PrimaryLineNumber__c);
String lineType = newLineItem.Apttus_QPConfig__LineType__c;
String productId = null;
if (lineType == LINETYPE_PRODUCT)
{
productId = newLineItem.Apttus_Proposal__Product__c;
}
else if(lineType == LINETYPE_OPTION)
{
productId = newLineItem.Apttus_QPConfig__OptionId__c;
//productId = newLineItem.Apttus_QPConfig__ProductOptionId__c;
}
String chargeType = newLineItem.Apttus_QPConfig__ChargeType__c;
// create attribute key
String newLineKey = lineNumber + ':' + productId + ':' + chargeType;
// save in map
newLineKey2IdMap.put(newLineKey, newLineItem.Id);
}
// create map of old line item ids to new line item ids
Set<ID> oldLineItemIds = oldLineId2KeyMap.keySet();
List<ID> newLineItemIds = new List<ID>();
for (String oldLineItemId : oldLineItemIds)
{
// get attribute key
String attrKey = oldLineId2KeyMap.get(oldLineItemId);
// lookup key in new line items map
String newLineItemId = null;
if(newLineKey2IdMap.containsKey(attrKey))
{
newLineItemId = newLineKey2IdMap.get(attrKey);
newLineItemIds.add(newLineItemId);
// associate old key with new one
lineOldId2NewIdMap.put(oldLineItemId, newLineItemId);
}
}
// update reapprovals data by calling API in approvals package
List<ID> oldContextObjIds = new List<ID>(oldLineItemIds);
List<ID> newContextObjIds = newLineItemIds;
system.debug(LoggingLevel.INFO,'sObjectType='+PROPOSAL_SOBJECT_TYPE);
system.debug(LoggingLevel.INFO,'contextObjId='+quoteId);
system.debug(LoggingLevel.INFO,'oldContextObjIds='+oldContextObjIds);
system.debug(LoggingLevel.INFO,'newContextObjIds='+newContextObjIds);
if (!oldContextObjIds.isEmpty() && !newContextObjIds.isEmpty() && oldContextObjIds.size() == newContextObjIds.size())
{
// get process instance associated with the old quote
Apttus_Approval__ApprovalProcessInstance__c instanceSO = getProcessInstance(quoteId);
system.debug(LoggingLevel.INFO,'instanceSO='+instanceSO);
// call API to update reapproval data
Boolean ok = Apttus_Approval.ApprovalsWebService.updateApprovalData(instanceSO.Id, PROPOSAL_SOBJECT_TYPE, quoteId, oldContextObjIds, newContextObjIds);
system.debug(LoggingLevel.INFO,'Apttus_Approval.ApprovalsWebService.updateApprovalData='+ok);
}
}
/**
* Get process instance for the given proposal id
* @param proposalId
* @return process instance object
*/
private static Apttus_Approval__ApprovalProcessInstance__c getProcessInstance(ID proposalId)
{
List<Apttus_Approval__ApprovalProcessInstance__c> instanceList = [select Id, Name, LastModifiedDate, LastModifiedById, LastActivityDate, CreatedDate, CreatedById, Apttus_Approval__Status__c, Apttus_Approval__StartTime__c, Apttus_Approval__ReassignmentEmailTemplate__c, Apttus_Approval__PrevProcessInstanceId__c, Apttus_Approval__NotifyOnlyEmailTemplate__c, Apttus_Approval__InstanceNumber__c, Apttus_Approval__EscalationEmailTemplate__c, Apttus_Approval__EndTime__c, Apttus_Approval__Data__c, Apttus_Approval__ConsolidationVersionNumber__c, Apttus_Approval__CancellationEmailTemplate__c, Apttus_Approval__BusinessObjectType__c, Apttus_Approval__BusinessObjectLink__c, Apttus_Approval__BusinessObjectId__c, Apttus_Approval__AssignmentEmailTemplate__c, Apttus_Approval__ApprovalProcessId__c From Apttus_Approval__ApprovalProcessInstance__c where Apttus_Approval__BusinessObjectId__c = :proposalId order by CreatedDate DESC limit 1];
if ( ! nullOrEmpty(instanceList))
{
return instanceList[0];
}
return null;
}
/**
* Checks if the given string value is null or empty.
* @param strValue the string to check
* @return <code>true</code> if the string value is null or empty, <code>false</code> otherwise
*/
public static Boolean nullOrEmpty(String strValue)
{
// check if null or zero length string
return (strValue == null || strValue.trim().length() == 0);
}
/**
* Checks if the given list of objects is null or empty.
* @param objList the list of objects to check
* @return <code>true</code> if the list is null or empty, <code>false</code> otherwise
*/
public static Boolean nullOrEmpty(List<Object> objList)
{
// check if null or empty
return (objList == null || objList.isEmpty());
}
}