Last active
October 12, 2023 10:13
-
-
Save amitastreait/eaadf6aa4be8fbabd7748eabc6a57d4d to your computer and use it in GitHub Desktop.
Approve Reject records from the Apex Class using Lightning Flow or Apex Class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<lightning-card variant="Narrow"> | |
<lightning-spinner alternative-text="Loading" size="small" variant="brand" if:true={isloading} ></lightning-spinner> | |
<div class="slds-p-around_small"> | |
<lightning-button-group> | |
<lightning-button label="Approve" title="Approve" onclick={handleApprove}></lightning-button> | |
<lightning-button label="Reject" title="Reject" onclick={handleReject}></lightning-button> | |
<lightning-button if:true={showRecall} label="Recall" title="Recall" onclick={handleRevoke}></lightning-button> | |
</lightning-button-group> | |
</div> | |
<div class="slds-p-around_small"> | |
<p class="slds-p-around_small" style="color: red;" if:true={errorDetails}> | |
{errorDetails} | |
</p> | |
<lightning-textarea message-when-value-missing="Approval/Rejections comments are required!" | |
name="comments" required label="Comments" | |
placeholder="provide the comments here ......" onchange={handleChange}> | |
</lightning-textarea> | |
</div> | |
</lightning-card> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { LightningElement, api, wire } from 'lwc'; | |
import id from '@salesforce/user/Id'; | |
import approveRejectRecords from '@salesforce/apex/ApprovalUtil.approveRejectRecords'; | |
import getTargetObjectId from '@salesforce/apex/ApprovalUtil.getTargetObjectId'; | |
import { ShowToastEvent } from 'lightning/platformShowToastEvent'; | |
export default class Approval extends LightningElement { | |
@api recordId; | |
@api message = '🤦♂️ You can not Approve/Reject the record as you have submitted the record for Approval'; | |
@api canapprove = false; | |
userId = id; | |
commments; | |
isloading = false; | |
targetObjectId; | |
errorDetails; | |
submitterId; | |
showRecall = false; | |
get approve() { | |
return this.canapprove; | |
} | |
set approve(value) { | |
this.canapprove = value; | |
} | |
@wire(getTargetObjectId, { recordId: '$recordId' }) | |
wiredData({ error, data }) { | |
if (data) { | |
console.log('Data \n ', data); | |
if (data.ProcessInstance && data.ProcessInstance.TargetObjectId) { | |
this.targetObjectId = data.ProcessInstance.TargetObjectId; | |
} | |
this.submitterId = data.CreatedById; | |
if (this.userId === this.submitterId) { | |
this.showRecall = true; | |
} else { | |
this.showRecall = false; | |
} | |
console.log('TargetObjectId ', this.targetObjectId); | |
} else if (error) { | |
console.error('Error: \n ', error); | |
} | |
} | |
handleReject(event) { | |
event.preventDefault(); | |
this.handleApproveRejectRecords('Reject', 'rejected'); | |
} | |
handleApprove(event) { | |
event.preventDefault(); | |
this.handleApproveRejectRecords('Approve', 'approved'); | |
} | |
handleRevoke(event) { | |
event.preventDefault(); | |
this.handleApproveRejectRecords('Removed', 'recalled'); | |
} | |
handleApproveRejectRecords(actionName, title) { | |
let allValid = this.validateInput(); | |
if (!this.canapprove && this.submitterId === this.userId) { | |
this.errorDetails = this.message; | |
return; | |
} | |
if (!allValid) { | |
return; | |
} | |
this.errorDetails = ''; | |
this.isloading = true; | |
let recordIds = []; | |
recordIds.push(this.targetObjectId); | |
let inputParameters = { | |
recordIds: recordIds, | |
actionName: actionName, | |
comments: this.commments, | |
assignNextApprovers: false, | |
submitterId: this.submitterId | |
} | |
approveRejectRecords({ | |
inputWrapper: JSON.stringify(inputParameters) | |
}) | |
.then((response) => { | |
console.log('successfull ', response); | |
this.dispatchEvent(new ShowToastEvent({ | |
title: 'Success', | |
message: 'The record has been ' + title, | |
variant: 'success' | |
})); | |
}) | |
.catch((error) => { | |
console.error('Error while performing the approval action! \n ', JSON.stringify(error)) | |
this.errorDetails = 'Unknown error'; | |
if (Array.isArray(error.body)) { | |
this.errorDetails = error.body.map(e => e.message).join(', '); | |
} else if (typeof error.body.message === 'string') { | |
this.errorDetails = error.body.message; | |
} | |
this.dispatchEvent(new ShowToastEvent({ | |
title: 'Error', | |
message: 'There was an error while processing the approval action', | |
variant: 'error' | |
})); | |
}) | |
.finally(() => { | |
this.isloading = false; | |
}) | |
// Call the Apex Class to do approve or reject records | |
} | |
handleChange(event) { | |
event.preventDefault(); | |
this.commments = event.target.value; | |
} | |
validateInput() { | |
const allValid = [ | |
...this.template.querySelectorAll('lightning-textarea'), | |
].reduce((validSoFar, inputCmp) => { | |
inputCmp.reportValidity(); | |
return validSoFar && inputCmp.checkValidity(); | |
}, true); | |
return allValid; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
global class ApprovalUtil { | |
@AuraEnabled(cacheable=true) | |
global static sObject getTargetObjectId(String recordId){ | |
return [SELECT Id, ProcessInstanceId, | |
ProcessInstance.TargetObjectId, | |
OriginalActorId, | |
ActorId, | |
CreatedById | |
FROM | |
ProcessInstanceWorkitem | |
WHERE | |
Id =: recordId | |
LIMIT | |
1 | |
]; | |
} | |
@AuraEnabled | |
global static void approveRejectRecords(String inputWrapper){ | |
ApprovalWrapper inputWrapperObject = (ApprovalWrapper)JSON.deserialize(inputWrapper, ApprovalWrapper.class); | |
approveRejectRecords(inputWrapperObject); | |
} | |
global static void approveRejectRecords(ApprovalWrapper inputWrapper){ | |
List<Id> recordIds = inputWrapper.recordIds; | |
System.debug('inputWrapper \n '+ JSON.serializePretty(inputWrapper)); | |
Map<Id, ProcessInstance> processIntanceMap = new Map<Id, ProcessInstance>([ | |
SELECT Id, ProcessDefinitionId, TargetObjectId | |
FROM | |
ProcessInstance | |
WHERE | |
TargetObjectId IN : recordIds AND | |
Status = 'Pending' | |
]); | |
Map<Id, ProcessInstanceWorkitem> processInstanceWorkitemsMap = new Map<Id, ProcessInstanceWorkitem>([ | |
SELECT Id, ProcessInstanceId | |
FROM | |
ProcessInstanceWorkitem | |
WHERE | |
ProcessInstanceId IN : processIntanceMap.keySet() | |
]); | |
List<Approval.ProcessWorkitemRequest> allWorkItemRequest = new List<Approval.ProcessWorkitemRequest>(); | |
for (ProcessInstanceWorkitem item : processInstanceWorkitemsMap.values()){ | |
Approval.ProcessWorkitemRequest req2 = new Approval.ProcessWorkitemRequest(); | |
req2.setComments( inputWrapper.comments); | |
req2.setAction(inputWrapper.actionName ); // To Approve Provide Approve & to recall provide Removed | |
if(inputWrapper.assignNextApprovers){ | |
req2.setNextApproverIds( inputWrapper.nextApprovars ); | |
} | |
req2.setWorkitemId(item.Id); | |
// Add the request for approval | |
allWorkItemRequest.add(req2); | |
} | |
Approval.ProcessResult[] result2 = Approval.process(allWorkItemRequest); | |
} | |
@InvocableMethod(label = 'Approve/Reject Records' category ='Approval' description='Approval Process Methods') | |
global static void approveRejectRecords(List<ApprovalWrapper> inputWrapper){ | |
if( inputWrapper != null && inputWrapper.size() > 0){ | |
approveRejectRecords( inputWrapper.get(0) ); | |
} | |
} | |
global class ApprovalWrapper{ | |
@AuraEnabled @InvocableVariable(label='Id of the Record' description='Id of the Record') | |
global List<Id> recordIds; | |
@AuraEnabled @InvocableVariable(label='Action to perform! either Reject or Approve' description='Action to perform! either Reject or Approve') | |
global String actionName; | |
@AuraEnabled @InvocableVariable(label='Rejection or Approval Comments' description='Rejection or Approval Comments') | |
global String comments; | |
@AuraEnabled @InvocableVariable(label='Next Approval User Id' description='Next Approval User Id') | |
global List<Id> nextApprovars; | |
@AuraEnabled @InvocableVariable(label='Assign to next Approver' description='Assign to next Approver') | |
global Boolean assignNextApprovers; | |
@AuraEnabled @InvocableVariable(label='Id of the user who submitted the approval' description='Id of the user who submitted the approval') | |
global String submitterId; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment