Quotes & Workflow Groups

Hi All,

This topic has multiple parts to it.

Our end goal is setting up a quote approval process. I’ve got a BPM set up that looks at a quote’s total value and discount percentages, then sends out an email based on certain criterion based on a hierarchy of personnel needed to approve the quote. The issue I face with that, is it seems to be all or nothing with the way we have the tasks laid out.

The task set is as follows: Quote Customer (sales rep), Review Quote (Sales Manager), Approve Quote (Sales Manager) (Winnable).

Just for example sake, say the quote does not meet any of the criteria required for approval (less than dollar amount, less than discount amount requiring approval). The rep still cannot convert the quote to an order because the next tasks require a sales manager role to win the quote. This is what I mean by all or nothing.

My next thought was to create a different task set, and use another condition within the BPM. If the quote does not meet any criteria that would require approval, update the table with a query to a separate task set which would allow a win, but there’s no configuration I can map between task and quote head so that didn’t work either.

The final idea was to keep that separate task set and enforce workflow groups to use the winnable quote task set for users that do not typically quote above the threshold i.e. parts sales versus outside sales reps. I know you can define task sets on the territories, but our territories are not well defined so we’d rather use workflow groups than modify the territories to work. After attempting multiple scenarios, I cannot get the workflow group default task sets to work when creating quotes. I have a test user setup as a sales rep linked to a territory, default task set removed from said territory, and a workflow group (CRM) setup with the test user as the primary member in that workflow group. When I create a quote with that user, it does not pull in the default task set for that workflow group.

Another caveat to this is that we have different sites within this company that will not use the approval process, so we can’t just set this to the default company task set.

If there are any ideas out there, or any other ways that I can set this up, I’m all ears. Keep in mind that this is all in our test environment so I’m willing to try about anything.

1 Like

I think you’re on the right track here. You should be able to change the task set in the Quote Header based on criteria. Possibly using the Quote.Update() method. Example:

/* 
    Start with a Conditional Widget
    
    The ds.QuoteHed.Quoted value of the Changed Row is equal to false
    AND (The ds.QuoteHed.TotalGrossValue has been changed from Any to Another
    OR The ds.QuoteHed.DiscountPercent has been changed from Any to Another)
*/

// If the above evaluates true, add a Custom Code block:

var quoteHed = ds.QuoteHed.FirstOrDefault( x => x.Added() || x.Updated() );

if ( quoteHed == null )
    return;

decimal VALUE_THRESHOLD = 5000.00m;
decimal DISCOUNT_THRESHOLD = 20.00m;

string MGR_APPROVAL_SET = "TaskSet1";
string NO_APPROVAL_SET = "TaskSet2";

bool RequiresApproval = quoteHed.TotalGrossValue > VALUE_THRESHOLD || quoteHed.DiscountPercent > DISCOUNT_THRESHOLD;

quoteHed.TaskSetID = RequiresApproval? MGR_APPROVAL_SET: NO_APPROVAL_SET;

You’d probably want to add some additional validation in here, like checking to see if there are already-completed tasks. And it would probably be smart to move the thresholds and TaskSets into UD Codes, rather than hard-coding them, but it would work similarly.

1 Like

I recall we had a similar process back in 9… but we added an approved checkbox and used a BAM with a .p which used the user codes as a means of storing the approvers and the values.

The .p sent an email with the record link for approval and the approver would click on the link to open Epicor up if it was closed and the quote form with the specific quote for review. If they set it to approved then the quote was set to quoted and the rest was history.

Can’t recall what the process was if it was not approved.

After extensive testing, I couldn’t get this to work how I needed it to. I reduced everything down to bare bones, and set a condition: if quotehed.quoted changed from any to another, set TaskSetID = “OurTaskSet”, and it failed.

In the end, I was able to write a series of branches for every possible condition (roughly 10 branches), then use a widget to set the TaskSetID field to “OurTaskSet” rather than executing code.

Thank you for helping me get there.

1 Like

I’m really glad you were able to get it to work. I really don’t know why the custom code wouldn’t have worked. I have a very similar BPM set up to add the TaskSetID when the quote is created, and another that changes it based on changes to the Customer (QuoteHed.CustNum), and I’ve never had any issues. I wonder if it has something to do with triggering on the change to Quoted. There might very well be methods that execute ahead of the Update method when that change is made, similar to how Quote.ChangePartNum executes before Update when a part number on a line is changed.

1 Like

I was thinking the same thing about the Q"uoted" change. I haven’t ran a trace on my finished product yet, but that will be my next series of steps to see which methods are updating, and when to see where I can make improvements.