I would like to selectively hide some customers in Customer Tracker, depending on the user.
When a customer is retrieved in Customer Tracker, I would like for it to block the display of all data if:
-the customer belongs to a specific price list, and
-the user is not a member of a specific security group
This seems to me like it’s something that could be handled with a Method Directive. Is this a good approach? How do I find the Method that populates Customer Tracker?
Turn on tracing and do the transaction then load the trace file and search for <meth to follow the flow. There will also be entries from when you turn tracking on or off that you can ignore. It is likely to be GetByID, but getting the customer via search maybe different. By block do you mean stop anything from loading as in an exception or hide some or all of the data?
A condition widget with two rows. One to check the group, and the other to check if user is in (or is not in) specific security group.
An exception widget to halt processing when condition is true.
One thing to consider is those users do anything that requires the UI to fetch the customer - even if nothing is displayed - as that could cause issues in what would seem like unrelated areas of Epicor
If your users have workforce records linked you could use territory security for this also, put the customers to restrict in a territory and only give access to that territory to those users workforce records that should be able to view them.
If you go the BPM route also put a post directive on GetList, and remove any restricted customers from the results. That will filter the customer searches everywhere so they cannot be selected.
Here’s what I got. I have all of it except throwing the exception. Not sure the proper way to do that within Epicor. Apologies if the C# is sloppy - it’s not my native language.
string assemblyName = callContextClient.AssemblyName.ToString();
//validate the method was called by Customer Tracker
if (assemblyName == "Erp.UI.CustomerTracker") {
int iCustID = int.Parse(custID);
var customerRow = (from CustomerRow in Db.Customer where CustomerRow.CustID == custID select CustomerRow).FirstOrDefault();
int i_dbCustNum = (int)customerRow["CustNum"];
var customerPriceLstRows = (from customerPriceListsRow in Db.CustomerPriceLst where customerPriceListsRow.CustNum == i_dbCustNum select customerPriceListsRow).ToList();
bool isPriceListType = false;
foreach (var cplRow in customerPriceLstRows) {
string priceListStr = cplRow["ListCode"].ToString();
Epicor.Hosting.Trace.ServerLog.WriteTraceMessage("trace://ice/log","Debug",() => ("Price List: " + priceListStr));
if (priceListStr == "somePriceList1" || priceListStr == "somePriceList2" ) {
isPriceListType = true;
}
}
if (isPriceListType == true) {
string activeUserId = callContextClient.CurrentUserId;
var activeUserFile = (from userFileRow in Db.UserFile where userFileRow.DcdUserID == activeUserId select userFileRow).FirstOrDefault();
var userGroups = activeUserFile["GroupList"].ToString();
if (!(userGroups.Contains("someSecurityGroup"))) {
//dbg print not allowed
Epicor.Hosting.Trace.ServerLog.WriteTraceMessage("trace://ice/log","Debug",() => "not allowed to view this customer");
//***throw an exception here
}
else {
//dbg print allowed
Epicor.Hosting.Trace.ServerLog.WriteTraceMessage("trace://ice/log","Debug",() => "access granted");
}
}
}
else {
//dbg show this was not called by customer tracker
Epicor.Hosting.Trace.ServerLog.WriteTraceMessage("trace://ice/log","Debug",() => "Method not called by Customer Tracker.");
}
One way:
Create a BPM variable in the widgets side, set it in your code, and use a condition widget to
check it after the code runs. If the variable is true, use the raise exception widget.