Skip to main content

#Advanced Approvals4 人正在讨论

1 个回答
  1. 昨天,16:43

    Hey Mohit, 

     

    Classic Approval Process's standard Reject button can't launch a screen flow, it only has a plain Comments text box, no way to force a required field or picklist before rejecting. 

     

    The real fix is to move this to a Flow Approval Process instead of Classic Approval Process, that's what Salesforce built specifically for this use case. With Flow Approval Processes, you build the approve/reject screen yourself: 

     

    - Create a Screen Flow with a radio button (Approve/Reject) 

    - Use a Decision element, when Reject is selected, show a Rejection_Reason picklist as a required field on that same screen 

    - Use the "Resolve Approval Request" flow action (or Update Records if you're setting the field directly) to set Application_Status__c = Rejected and Rejection_Reason__c from what the user entered 

    - This entire screen replaces the standard Approve/Reject buttons, so your rejection reason requirement is enforced right there in the flow, no separate popup needed 

     

    If you're on Classic Approval Process and don't want to migrate, there's no native way to inject a screen flow into the Reject button, that part's a real platform limitation. Migrating to Flow Approval Process is the supported path here, not a workaround. 

     

    Reference:

    https://help.salesforce.com/s/articleView?id=sf.approvals_step_rejection.htm&language=en_US&type=5

0/9000

Programmatically Approving/Rejecting Flow Orchestration Approval Steps (and why ConnectApi.FlowApprovalProcesses won't work)

 

The problem

If you're using Flow Orchestration with Approval Steps and need to let users approve or reject work items from somewhere other than the standard Work Guide component — for example, from a custom mobile experience, since Work Guide does not render in the Salesforce mobile app despite showing up fine in Lightning App Builder's phone preview — you'll hit a wall pretty fast.

Here's what doesn't work, and why, so you don't have to burn the hours we did finding out:

Dead end #1: ConnectApi.FlowApprovalProcesses.getFlowApprovalProcessWithStatus()

This looks like exactly the right API — it's documented specifically for retrieving the status and available actions of a flow approval process. In practice, for Orchestration-embedded Approval Steps specifically (as opposed to standalone autolaunched Flow Approval Processes invoked via a "Request an Approval" flow element), we found:

  • Calling it via Apex throws ConnectApi.ConnectApiException: Id=null when passed the Flow API name for processNames
  • Calling the identical request via raw REST (same org, same inputs) succeeds and returns correct data — ruling out an Apex-only bug
  • When it does succeed, it consistently returns isApprovalInProgress: true but only exposes a "Recall" action — never Approve/Reject, even when querying as the actual assigned approver, not the submitter

We filed this with Salesforce Support and it's now a tracked Known Issue: W-23702762. Support confirmed this API path does not currently support returning Approve/Reject actions for Orchestration Approval Steps.

Dead end #2: Classic Approval.process()

The older, well-documented Approval.ProcessWorkitemRequest / Approval.process() Apex API only works against classic ProcessInstanceWorkitem records. Flow Orchestration Approval Steps create ApprovalWorkItem records instead — a different object entirely. Attempting to use the classic API against an ApprovalWorkItem Id throws INVALID_CROSS_REFERENCE_KEY.

The actual solution: reviewApprovalWorkItem

There's a standard invocable action — not prominently linked from the API you'd naturally start with — that does exactly what's needed:

  • Action name: reviewApprovalWorkItem
  • Inputs: approvalWorkItemId (String), approvalDecision (String — must be exactly "Approve" or "Reject", capitalized), comments (String, optional)
  • Preconditions: the work item's Status must be Assigned, and the calling user must be the assignee (or a delegate, or hold a higher role)

Calling it from Apex:

apex

Invocable.Action action = Invocable.Action.createStandardAction('reviewApprovalWorkItem');

action.setInvocationParameter('approvalWorkItemId', workItemId);

action.setInvocationParameter('approvalDecision', 'Approve'); // or 'Reject' — exact capitalization required

action.setInvocationParameter('comments', 'Optional comment text');

List<Invocable.Action.Result> results = action.invoke();

Boolean success = results[0].isSuccess();

We found the documentation for this action almost by accident, linked from the "Recall Approval Submission Action" doc page — it's filed under Salesforce's "Advanced Approvals Standard Invocable Actions" documentation, not anywhere near the ConnectApi Orchestration docs where we were originally looking.

The gotcha that will still bite you: field update sequencing

Getting reviewApprovalWorkItem working is not the end of the story. If your orchestration has logic downstream of the approval step — for example, a Decision element that checks a field on the related record (like "does this need Finance approval next?") to determine routing — that field must already reflect the correct value before you call reviewApprovalWorkItem, not after.

Why: the native Work Guide component's "Approve" button doesn't just mark the work item complete — it runs the entire underlying subflow tied to that approval step (in our case, a subflow that included a Decision element, a field update on the related record, and a Slack notification, all before marking the work item done). When you call reviewApprovalWorkItem directly, you bypass all of that subflow logic and only get the equivalent of "mark this work item done." Any Orchestration Decision element gated on your related record's fields will evaluate immediately once the work item is marked complete — using whatever the field's value is at that exact moment, which may still be stale if you haven't updated it yourself first.

Concretely, for us this meant:

apex

// WRONG ORDER — orchestration's Decision evaluates before the field is updated

Invocable.Action action = Invocable.Action.createStandardAction('reviewApprovalWorkItem');

// ...invoke...

opp.Approval_Status__c = 'Pending Finance Approval'; // too late — Decision already ran

update opp;

apex

// CORRECT ORDER

opp.Approval_Status__c = 'Pending Finance Approval'; // set first

update opp;

Invocable.Action action = Invocable.Action.createStandardAction('reviewApprovalWorkItem');

// ...invoke — Decision now evaluates the correct, already-updated value

We only caught this because the orchestration instance showed Status: Completed (successfully!) but the expected next-stage work item never got created — it took querying the FlowOrchestrationInstance and reading the underlying subflow's Decision logic directly to figure out why.

If your orchestration's subflow also sends notifications (Slack, email) as part of that same subflow logic, be aware those will also be skipped when you bypass the subflow via reviewApprovalWorkItem directly — you'll need to replicate any such notification yourself (as a Flow Action or Apex callout) alongside the field update.

Summary checklist if you're building this yourself

  1. Don't use ConnectApi.FlowApprovalProcesses for Orchestration Approval Steps — it's a known, tracked bug (W-23702762) for retrieving Approve/Reject actions.
  2. Don't use classic Approval.process() — wrong object type entirely.
  3. Do use the standard invocable action reviewApprovalWorkItem, called via Invocable.Action.createStandardAction().
  4. Capitalize approvalDecision exactly as "Approve" or "Reject".
  5. Update any fields your orchestration's downstream Decision logic depends on before calling reviewApprovalWorkItem, not after.
  6. Check whether your approval step's native subflow sends any notifications (Slack/email) as part of its own logic — if so, replicate that separately, since bypassing the subflow means bypassing those too.

Hope this saves someone the hours it cost us to piece together!!!

 

#Flow-Orchestration  #Advanced Approvals  #Salesforce_Mobile_App

0/9000

Hi - What are some ways that you are making you approval processes for Quotes more efficient? 

 

Smart Approvals is one thing to think about but what are some others? 

 

Any thoughts are appreciated -  Thanks! 

 

#Quotes  #Advanced Approvals

0/9000

We use advanced approvals for CPQ. If the sales rep recalls the approval to make changes to the quote and then resubmits, the recalled approvals still show up in approval list view. It is causing confusion all around.

I know based on https://help.salesforce.com/s/articleView?id=000380239&type=1 that we can't delete the recalled approvals. Is there a way to hide them from view? 

 

#Salesforce  #CPQ  #Advanced Approvals

1 个回答
  1. 2024年3月4日 10:08

    Deanna, you could create a custom list view with criteria that filters out the recalled approvals, the filter criteria could be based on the status or any other related fields

0/9000

I have two approval processes that need to be on an opportunity.

 

1 -  if a checkbox (service checkbox) is true, send approval processes to x employee for approval.

 

2 - if an approval process field contains (2.3 - 2.5) send approval process to x employee(s)for approval.  This is for pricing, discounts, etc.

 

I cannot seem to get both to work on the opportunity.  Some will have both, some will only have one selection that meets the criteria.

 

Any suggestions would be greatly appreciated.

 

#Advanced Approvals  #Approvals User

4 个回答
  1. 2024年2月26日 22:10
    If you want both processes to fire when both conditions are true I think you need to create a third process. Its entry conditions should be when both are true and you would need to combine all the actions into it. Make it the first in the order. That way if both are true it fires. If not it falls through to the individual ones
0/9000

Hello,

We have a user that has the ability to approver for all other approvers without using the delegate path or the reassign path. They have a permission set that allows them to Modify All Data.

 

We now have another user that needs that same access. So, I gave them the Modify All Data permission set and they cannot approver for other approvers.

 

Except for a few difference in the permission sets these users look to be setup the same.

 

What else should I look at to determine why they cannot approve (or reject) on others behalf?

Thank you.

 

#CPQ  #Salesforce CPQ & Billing  #Advanced Approvals

1 个回答
  1. 2024年2月22日 21:22

    To update this the user can change to approved (ore rejected0 if they go into the actual Approval record. They cannot approve or reject via the hyperlinks for approved or rejected. 

0/9000
2 个回答
  1. Josh Priem (Freelance) Forum Ambassador
    2023年11月13日 16:37

    you can add them to a group or use a flow to send out an email when the approval record is created

0/9000

Hello all,

 

We came across a situation where the approval request was send that quote was now pending approval.  However, the approver (Sales Engineer) is no longer with the company but we can't remove that person as the SE on the deal due to reporting requirements. So my SalesOps team tried to change the approver on the actual approval that was sent out but they see lock icons on "Approver" and "Assigned to" fields in the approval record.  They have CPQ and AA user and admin permission sets as well as their ops profile has modify all permission enabled.

As an admin, i can change the "Appover" and "Assigned to" fields.

 

What permission are they missing?

 

#Sales Cloud

2 个回答
0/9000

Hi,

 

Need some help to figure out how to make multiple approval chains dependent on each other.  I'm doing multiple approval chains because we need two approvers to approve at the same discount level.  If I put them in a approval group, only one has to approve when we want both to have to approve.  So we are investigating using multiple approval chains.

 

Issue is that we don't want the approval request from the second approval chain to be requested until the first approval level in the first approval chain has been approved.

 

For example - 

 

Chain 1                               Chain 2

Level 1 - requested

Level 2 - assigned              Level 2 - assigned

 

Then once Level 1 approves in Chain 1, then:

Chain 1                                Chain 2

Level 1 - approved

Level 2 - Requested           Level 2 - Requested

 

Only when both level 2 approvers have approved, then the quote is approved.

 

Ideas greatly appreciated.  #Salesforce CPQ & Billing

 

@Salesforce CPQ

2 个回答
  1. 2021年9月22日 22:48

    Hi Emily,

    If you want to use groups for approval and require that all members of a group must approve before the Approval is approved, you can set the Unanimous field on the group's Approver record to TRUE. This will ensure that all members of the group must approve.

     

    When using Approval Steps and Chains, it is my understanding that Advanced Approvals will always trigger the "first" approval in a chain, regardless of step (which is consistent with your diagram and reported results).

     

    If you set the Approver group to be unanimous with the Level 2 approval in Step 2, would that meet the requirement?

0/9000

Hello,

I created an approval process on the opportunity and I am running into this issue. So  When a record gets approved I have it setup that the record gets unlocked pending approval. the record does lock when the approval process is submitted and the submitter get to choose their delegated approver. So in some case after a record is approved it is still giving this error message for users: This record is locked, please contact your administrator. This shouldn't be happening. Upon more investigating when I go to the OPP related list under approval history the approval request shows pending even tho it was verified and approved. So I have to approve each one that comes in. Can anyone help??  

3 个回答
  1. 2021年9月23日 07:48

    @Eric Pulliam - Hi Eric, having the same exact issue here. Found that if I de-activate the process and re-activate it, it releases the record, but can't possibly do that every time a record goes through this process. Have you found a solution?

    Thanks.

0/9000