Workflow permissioning criterias matching - drools

Currently, I have a workflow table quite complex containing multiple values that combine between each others. It is basically a workflow to find the right approver for the right user in permission model
Here is a simplified example of workflow table
Country
Department
Role
Approver
ALL
ALL
ALL
Bob
UK
IT
Developper
Tim
US
IT
Developper
Mike
ALL
ALL
Analyst
John
Those workflow steps always follow pre-requisite :
It always exist the default approvers with matching ALL criterias
Any criteria matching take precedence on the ALL criteria
If no criteria match, it will fall inside the default approvers
I have users that need to be approved according to above matrix
User
Country
Department
Role
U1
UK
IT
UX designer
U2
US
HR
Analyst
I am trying to figure out how i can extract the following matching :
User
Approver
Reason
U1
Bob
User U1 does not match the criterias so its climb to the default approver
U2
Tim
User U2 match workflow step because Tim validate all UK Developpers belonging to IT department
Of course for this example there is few criterias so a simple if / else would solve it.
But I have 6 criterias which I believe would reach an important number of combinaisons if applying this naive approach.
In this situation, does a rule engine would apply this problem ? (for instance drools?)
I would think the engine would take user / and list of workflow step as a fact.
Should a decision table more applicable in this situation ?
Any help in structuring the problem would be more than appreciated :)
Here is a really simple example of matching a user to its approver country
rule "Has country approver"
when
$user : User( $country : country )
$wf : WorkflowStep(country == $country) from $userAccess.steps
then
//take the approver for the matching step
$userAccess.setApprover($wf.getApprover());
//insertLogical ?
end

A rule engine is a perfect fit for your solution, you have to decide how to use it though.
The example you provided using Drools directly is very low-level, it works but it'll require you to write the rules in DRL.
Since you already know your evaluation is stateless and your input are literally formatted as a table, a Decision Table would be a better fit in my opinion. Given that you have two flavours of Decision Tables, Drools' and DMN.
I'll suggest you to try with DMN's as it's easier to start, Kogito provides a quick-start that let you experiment with the whole system and even write a test scenario for that, which is basically your second table.

Related

Project Academic Knowlede | Query for and list papers by AA.AuId?

I've got a list of author names but I don't have Id's for any of them.
I'd like to:
Query by author name and store the most probable AuId.
List all papers written by a given AuId.
Is there any way to do this with the current interpret/evaluate APIs? It seems like everything is tied to a paper entity and I want to be sure I am only ever selecting and using one AuId.
Thanks.
I am not aware of such a feature. But indirectly, you could first search for the author name (AA.AuN in the expr-field), obtain all the (unique) various author IDs (AA.AuId in the attributes field), and search for their publications.
(You could even add orderby=logprob:desc, but to be honest, I am not 100% sure what logprob does.)
So, the first step could be to search for the author name (e.g. John Smith) like this and fetch all those AA.AuId where the names (AA.AuN) seem to fit John Smith (let's just add the orderby=logprob:desc):
https://api.labs.cognitive.microsoft.com/academic/v1.0/evaluate?&expr=Composite(AA.AuN=%27john%20smith%27)&count=100&attributes=AA.AuN,AA.AuId&orderby=logprob:desc&subscription-key={YOUR-KEY}
As a second step, if you have an Author ID AA.AuId (here, for example, 3038752200), use this to list their papers (ordered by year, in a descending manner orderby=Y:desc):
https://api.labs.cognitive.microsoft.com/academic/v1.0/evaluate?&expr=Composite(AA.AuId=3038752200)&count=100&attributes=AA.AuN,AA.AuId,DOI,Ti,VFN,Y&orderby=Y:desc&subscription-key={YOUR-KEY}
The approach would be more promising if you had an institutional affiliation as well. Then you could change the expr field to Composite(And(AA.AuN='{AUTHOR-NAME}',AA.AfId={AFFILIATION-ID})) so as to search for all {AUTHOR-NAMES} affiliated to {AFFILIATION-ID}.

Restrict Submission on Cognito Forms' Form Based on Previous Entries

I built a form in Cognito Forms for employees to reserve company vehicles. The following are important fields on the form:
Employee Name
Employee Email
Vehicle (selection)
Pick Up Date = date the user will get the car
Mileage = how many miles the user put on the car, entered after returning the car
We want to restrict the user from entering a new car reservation if they have a past entry that has not had Mileage entered. I was considering using a calculated field of some kind and then using the quantities feature to restrict duplicate entries but not sure what could be used in the form as comparison for duplicates. I know that currently Cognito Forms does not have a method for doing lookups of previous entries or else there wouldn't be a question. Has anyone else found a workaround before?

TSQL list of business rules in MDS

I need help with querying my business rules in SQL!
I have created couple of business rules in MDS web service to validate my master data and found out that 2 % of my data is not complying with the rules. Now I have created a SQL subscription view to report on the invalid data in PowerBI. In my PowerBI report I need to tell the business user why the data is invalid but I cannot since the subscription view only tells where the data is invalid but not why the data is invalid. So I need to know how I might query my business rules from MDS database in SQL and map it with my PowerBI data model. Is there a way to query the list of business rules from MDS database?
OK, so there are multiple ways to go about this. Here are some solutions, pls choose one that suits your scenario.
1. SQL - List of all Business Rules
The following query will retrieve the list of all Active Business Rules created in MDS.
SELECT *
FROM [MDM].[mdm].[viw_SYSTEM_SCHEMA_BUSINESSRULES]
WHERE Model_Name = 'YourModelName'
AND BusinessRule_StatusName = 'Active'
You can, of course, further filter by Entity_Name, etc.
The important columns in your case are going to be:
[BusinessRule_Name]
[BusinessRule_Description]
[BusinessRule_RuleConditionText]
[BusinessRule_RuleActionText]
Note: The challenge in your scenario, I think, is going to be that the Subscription View of the entity does not have IDs of the exact Business Rules that failed. So I'm not sure how you'll tie these 2 together (failing Rows -> List of Business Rules). Also remember that each row may have more than 1 business rule that failed.
2. using View viw_SYSTEM_USER_VALIDATION
This is a view that has a historical list of all business rules (+row info) that failed. You may use the view in this way:
SELECT
DISTINCT ValidationIssue_ID, Version_ID, VersionName, Model_ID, ModelName, Entity_ID, EntityName, Hierarchy_ID, HierarchyName, Member_ID, MemberCode, MemberType_ID, MemberType, ConditionText, ActionText, BusinessRuleID, BusinessRuleName, PriorityRank, DateCreated, NotificationStatus_ID, NotificationStatus
FROM [MDM].[mdm].[viw_SYSTEM_USER_VALIDATION]
WHERE --CAST(DateCreated as DATE) = CAST(GETDATE() as DATE) AND
ModelName = 'YourModelName'
--AND EntityName IN ('Entity_1','Entity_2') -- Use this to Filter on specific Entities
Here, use the columns Model_ID, Entity_ID and Member_ID/MemberCode to identify the specific model, entity & row that failed.
Columns BusinessRuleName, ConditionText & ActionText will give your users additional info on the Business Rule that failed.
Note:
One issue with using this view is that even though, let's say, your failure condition was resolved the next day by the user, the view will still show that on a certain date, a validation had failed. (via column DateCreated).
Also note that the same failed data row will appear multiple times here if multiple Business Rules on the same row failed validation (there will be different BusinessRuleID/Name, etc). Just something to take note of.
Similarly, the same row may appear multiple times if it has failed again & again at different times. To workaround this, and if your final report can do with that, add a WHERE clause on the DateCreated column so that you only get to see any row that Failed today. The commented out line of code <--CAST(DateCreated as DATE) = CAST(GETDATE() as DATE) AND> does the same. If you can't use that, just make sure the data row are distinct. However, if you do this, remember that if something Failed yesterday (and is still in the Failed status), it may not show up.
My suggestion would be to use a slightly modified version of Solution #2:
Get the list of Failed Rows from your Subscription View (the data row's ValidationStatus is actually still 'Failed'), then JOIN with viw_SYSTEM_USER_VALIDATION making sure that you only select the row with MAX(DateCreated) value (of course for the same data row AND Business Rule).
Best of luck and if you find anything else while solving this issue, do share your learning here with all of us.
Lastly, if you found this useful, pls remember to Mark it as the Answer :)

Modeling hierarchical data with authentication using DynamoDB

I'm looking for some best practices when it comes to modeling confidential hierarchical data in general and specifically with DynamoDB.
The scenario is best explained with an example:
Let's say we have a number of users. Each user has a number of products. Each product consists of a number of parts.
Typical use cases:
List all products for a given user
List all parts for a given product
So far I have modeled this in DynamoDB like this:
Users
----------------
HashKey: UserId
Products
-------------------
HashKey: UserId
RangeKey: ProductId
Parts
-------------------
HashKey: ProductId
RangeKey: PartId
The data is confidential and accessed through authenticated REST endpoints where an authentication token can be mapped to a UserId. Each user may be allowed to view other users' data through some group concept.
Listing all products for a given user is simple since UserId is a key in the products table:
GET /users/111/products becomes a simple Query(Table=Products, UserId=111)
But consider the case of listing all parts for a given product:
GET /users/111/products/222/parts
If I simply do a Query(Table=Parts, ProductId=222) then I will get the desired data fast, but I am not protecting against other users querying for data belonging to user 111, provided they somehow know about ProductId 222 (in reality, ID:s will of course be UUID:s or similar so not so easily guessable):
GET /users/119/products/222/parts
... would result in malicious user 119 retrieving data that doesn't belong to him, provided nothing is done to address this.
So here I imagine I need to do something like one of these:
First make another query to make sure product 222 in fact belongs to the given user
Duplicate the UserId in the Parts table and include it in the query condition (which basically means it will match either all rows or no rows when scanning through the set identified by ProductId): Query(Table=Parts, ProductId=222, UserId=111)
Use UserId as the hash key also in the Parts table and instead keep ProductId as a secondary index
Use a composite HashKey such as UserId_ProductId ("111_222") on the Parts table
If I need to return a 401 as opposed to just empty data, option 1 seems like the only approach. But if we imagine a deeper hierarchy of data, e.g. "users having inboxes having messages having parts having attachments" it seems this approach could eventually be expensive (listing all attachments for part P might result in a query to check that part P belongs to message M, that message M belongs to inbox I and that inbox I belongs to user U, and so on).
Does anyone have any good arguments for which approach is most favorable? Or am I doing something stupid and should be modeling my data in some other way completely?

Use form to create multiple fields in Access 2010

So I have a form I have Vendors fill out when they want to ship to us. It's an excel form that I then import into Access so I can run reports. Sometimes when they send the form back it's in a format in which I have to manually enter the data into our database.
The form looks like this:
The middle section is just for example purposes so it's a rectangle with text in it.
So everything seemed simple enough until I got to the middle section. See in my excel form I have a section for multiple PO's and units. So essentially each shipment can have one to many PO's and Units. Currently I can approach this task with the redundant method of reentering information per PO on the form. But I want to make this simple.
So the task at hand is that I want to have a form field for PO's and Units where I can input multiple lines of information so that when I hit a submit button. It appears in the database on separate lines with the same vendor information.
So if I filled out my form had this in the middle section:
PO | Units
111111 22
222222 33
333333 44
When I hit submit I want it to attach the rest of the forms information to each PO on separate lines so it'd be like:
Vendor | City | State | PO | Units
Nike Memphis TN 111111 22
Nike Memphis TN 222222 33
Nike Memphis TN 333333 44
So how would I go about accomplishing this task?
From your description of the problem and your example of how the data appears to ultimately be stored in Access it looks to me like you are using Access as a spreadsheet and not as a database. This is ok, but you might want to consider normalizing the data to take advantage of the power of databases in general.
For example:
Create a Vendors table whose sole purpose is to keep details about each Vendor you work with. A very basic implementation would have an ID field to uniquely identify each vendor and a Name field for the vendor name.
If Vendors will only ever have a single location you could also store City, State, ZipCode and Email in this same Vendor table, but I suspect having a separate VendorLocation or VendorAddress table would be a better fit long term.
Create a VendorShipment table that tracks the higher level information on your mockup, such as:
ShipmentID (primary key of this table)
VendorID (foreign key back to Vendor table)
Ready Date
Carrier
Estimated Cost
FreightClass
Tracking #
Estimated Transit Time
Finally, create a VendorShipmentDetail table that tracks the information of each shipment, including:
ShipmentDetailID (primary key of this table)
ShipmentID (foreign key back to VendorShipment table)
PO
Units
Any other details that you want to or need to track
Organizing and storing the data in a normalized fashion would ultimately help simplify your data entry \ data management process and potentially make for a better user experience.
For example, rather than having to enter the Vendor Name, Address information, etc. each time you could instead use a combo box control that is tied to the Vendor table. If the Vendor exists in the table you select it from the list and you already have the Address information, no need to re-enter it each time. If the Vendor did not already exist you enter it once (probably on a Vendor screen where you maintain the details for each Vendor) and draw upon the information in the future.
You would then use queries to tie the information back together for reporting purposes (de-normalize the information).
The art of database design can take a while to pick up, but a good starting point might be to check out the Northwind database that Microsoft has maintained over the years. It has some examples you could draw from immediately to get a practical understanding of how to use normalization within Access. You can find more information here: http://office.microsoft.com/en-us/templates/northwind-sales-web-database-TC101114818.aspx