I am trying to create a report on one to many Master-Detail relationships. I need to get results on Opportunity(Master) related to the many financiers(Detail). The financiers have a picklist field that can approve or deny or approve conditionally. Some opportunities can have one financier approved and others denied. some have denied by all the financiers. I need to get results for the opportunities that were denied by all the financiers they have applied for. When I tried to use the filter to show denied financiers I am getting results for opportunities that were denied but some of the results were approved by another financer. How do I run a logic to discard the opportunities that were approved by at least one financier and denied by all the financiers? I know that this can be achieved by creating a new field on opportunity or by creating a custom report using a visualforce page. Which is the more subtle and feasible solution?
This is a SF admin question rather than coding. You might have better luck at https://salesforce.stackexchange.com.
As a rule of thumb - si this report going to be the only place you need this kind of data. For "clean" solution I'd be tempted to make up to 3 rollup summary fields on Opportunity, something like "count all financiers", "count approved", "count rejected". And then your report gets significantly simpler.
But if it's one-off requirement or other reason you can't do rollups (for example reaching limit of rollup fields / not wanting to waste them on something considered trivial) you might still be able to pull it off with report.
I need to get results for the opportunities that were denied by all
the financiers they have applied for
I'd try with something called "cross filter". Try help articles or this might be a good start: https://salesforce.stackexchange.com/a/23697/799
Maybe "Opportunities with Financiers" report, filtered on Financiers.Status = Declined. Plus cross filter saying "Opportunities without Financiers where status != Declined".
Or maybe 2 cross filters. You'll have to experiment a bit.
Related
[Note: There is a Teacher Object with the fields such as Teacher Name, DateofJoining, and also a formula field called Experience]
My Task was to create a Public Group consisting of another user
and this user should only see teachers who have experience greater than 2 years
But when i create a sharing rule based on criteria the field name called Experience doesn't show up as it is a formula field.
So i got an idea of creating a new field(maybe a text or number data type) which would have the value of Experience in it. (But i have no idea on how to implement this)
Is there a way to implement this?
Any other solution is also well appreciated!
Hard to say.
Normal trick would be to create a helper field (text, number, whatever) and have piece of functionality that populates it. An "early flow" or "before insert, before update" trigger ideally. Worst case a normal flow, process builder or "after insert, after update" trigger. Something like "if Experience__c != 'your formula here' then Experience__c = 'your formula here'". Consult normal SF help and trailhead if you never used early flows
You'd make an one-off data fix to populate existing records and job done, normal field should be selectable as sharing rule criteria.
=====
But I smell trouble with your formula. What exactly you have there, something like Experience__c = (TODAY() - DateofJoining__c) / 365? That's bit evil. Formulas with TODAY(), NOW() or anything with $ (roughly speaking who's looking at the data, user's name, profile role... not what's actually on the record itself) are "nondeterministic". Unpredictable.
A "today()" changes just like that, without updating the record. Sure, when you watch the record a fresh value will be calculated but other than that LastModifiedDate doesn't change, there's no magical trigger running at midnight that rechecks sharing. (especially that there's no single midnight, you could have users in multiple timezones). SF just doesn't allow nondeterministic fields in many places, see https://salesforce.stackexchange.com/q/32122/799
So if you do rely on TODAY() in your formula you might have to make a "scheduled flow" or read about schedulable, batchable apex. Create nightly job that would run and recalculate your helper field with right experience. You'd probably even need both solutions, a "before save" flow for new data created today and nightly job to advance the clock on existing old data...
I am getting
Retrieve and Rank failed to handle question even though documents and training questions with answers are available as shown follows :
and the Questions are as follows :
Thank you,
Sandhya
The full error being returned by the Retrieve and Rank service that is causing this is:
Can not rerank results. Verify your query does not contain any special
characters or that your schema has not changed in incompatible ways
(Although this isn't being well handled by the UI. We'll improve that, so thanks for letting us know.)
What it means is that you're using submitting queries and requesting that they be sorted by a ranker that was trained/created with a different collection, with a different configuration and schema. That doesn't work.
It is possible to use a ranker across different collections, but not in such circumstances. As I say, we'll improve the UI to make this clearer in future.
But for now, the reason you're not getting results is because that ranker you're trying to use cannot be used with this particular collection, because they are incompatible. Once you've collected enough of a ground truth to train a ranker for this particular collection, with it's own config and schema, you'll be able to submit queries using that new ranker just fine.
I want to make sure I understand something.
One of the users created a report, and it returned 1 record. When I ran her report, it also returned 1 record. When I rebuilt the report from scratch (I'm a system Admin) I got 130 records, and when I did a SOQL search it returned 130 records.
This makes me think that there is something going on in terms of permissions associated with this report.
Can someone tell me what's going on here?
Thanks!
AHHH- I got it, and it's a frustrating one!!
The report was on a m-d-r, and it was built to return records with 1 child (inner join). The user's report had fields from the master and the detail.
My report only had fields from the master, and therefore it returned all the records. when i added fields from the detail, it went back down to 1.
Fix: change the report type from an inner join to a left join
Does the report say something like "My Opportunities" and what you have built says "All Opportunities".
Some reports remember their creator's position in Role/Territory hierarchy (especially the ones associated to Accounts and Opportunities I think). You can read about it a bit more here. So if the user was somewhere down the food chain but you're on the top that might explain it. I don't think it can be changed anywhere in the report editor - just run it, examine the hierarchy listed on the top of the report, change hierarchy to the top Role and save.
Are any of the Opportunities owned by users without Role (WHERE Owner.UserRoleId = null)? If they've completely fallen outside the hierarchy (or if you have 2 branches) this might be the reason. It's stupid but sometimes IT is told to move deactivated users out of the Roles tree without transferring records to their managers/peers.
Same for Territories if they're enabled in the org.
If none of these works - have you by any chance accessed the report by clicking a chart in dashboard?
Are you 100% all "quick access" filters on the report are set in same way in both the reports and the SOQL:
Date filter (set to all time?)
Status (all? closed? closed won?)
Probability (all?)
Opportunity teams...
etc.
Anything special about your sharing? Org-Wide Defaults? Sharing rules? Is it really opportunities or some custom object (maybe even one that's a detail in M-D?)...
For example I have Documents A, B, C. User 1 must only be able to see Documents A, B. User 2 must only be able to see Document C. Is it possible to do it in SOLR without filtering by metadata? If I use metadata filter, everytime there are access right changes, I have to reindex.
[update 2/14/2012] Unfortunately, in the client's case, change is frequent. Data is confidential and usually only managed by the owners which are internal users. Then the specific case is they need to be able to share those documents to certain external users and specify access levels for those users. And most of the time this is an adhoc task, and not identified ahead of time
I would suggest storing the access roles (yes, its plural) as document metadata. Here the required field access_roles is a facet-able multi-valued string field.
Doc1: access_roles:[user_jane, manager_vienna] // Jane and the Vienna branch manager may see it
Doc2: access_roles:[user_john, manager_vienna, special_team] // Jane, the Vienna branch manager and a member of special team may see it
The user owning the document is a default access role for that document.
To change the access roles of a document, you edit access_roles.
When Jane searches, the access roles she belongs to will be part of the query. Solr will retrieve only the documents that match the user's access role.
When Jane (user_jane), manager at vienna office (manager_vienna) searches, her searches go like:
q=mainquery
&fq=access_roles:user_jane
&fq=access_roles:manager_vienna
&facet=on
&facet.field=access_roles
which fetches all documents which contains user_jane OR manager_vienna in access_roles; Doc1 and Doc2.
When Bob, (user_bob), member of a special team (specia_team) searches,
q=mainquery
&fq=access_roles:user_bob
&fq=access_roles:special_team
&facet=on
&facet.field=access_roles
which fetches Doc2 for him.
Queries adapted from http://wiki.apache.org/solr/SimpleFacetParameters#Multi-Select_Faceting_and_LocalParams
Might want to check the Document level Security patches.
https://issues.apache.org/jira/browse/SOLR-1872
https://issues.apache.org/jira/browse/SOLR-1834
I think my approach would be similar to #aitchnyu's answer. I would however NOT use individual users in the meta data.
If you create groups for each document, then you will have to reindex for security reason less often.
For a given document, you might have access_roles: group_1, group_3
In this way, the group_1 and group_3 always retain rights to the document. However, I can vary what groups each user belongs to and adjust the query accordingly.
When the query then is generated, it always passes as a part of the query the user's groups. If I belong to group_1 and group_2, my query will look like this:
q=mainquery
&fq=access_roles:group_1
&fq=access_roles:group_2
Since the groups are dynamically generated in the query, I simply remove a user from the group, and when a new query is issued, they will no longer include the removed group in the query. So removing the user from group_1 would new create a query like this:
q=mainquery
&fq=access_roles:group_2
All documents that require group 1 will no longer be accessible to the user.
This allows most changes to be done in real-time w/out the need to reindex the documents. The only reason you would have to reindex for security reasons is if you decided that a particular group should no longer have access to a document.
In many real-world scenarios, that should be a relatively uncommon occurrence. It seems much more likely that HR documents will always be available to the HR department, however a specific user may not always be part of the HR group.
Hope that helps.
You can implement your security model using Solr's PostFilter. For more information see http://searchhub.org/2012/02/22/custom-security-filtering-in-solr/
Note: you should probably cache your access rights otherwise performance will be terrible.
Keeping in mind that solr is pure text based search engine,indexing system,to facilitate fast searching, you should not expect RDMS style capabilities from it. solr does not provide security for documents being indexed, you have to write such an implementation if you want. In that case you have two options.
1)Just index documents into solr and keep authorization details into RDBMS.Now query solr for your search and collect the results returned.Now fire another query to DB for the doc ids returned by solr to see if the user has an access to them or not.Filter out those documents on which user in action has no access.You are done ! But not really, your problem starts from here only.Assume, what if all results returned by solr gets filtered out ? (Assuming you are not accessing all the documents at a time,means you are retrieving top 1000 results only from solr result set,otherwise you can not get fast search) You have to query solr again for next bunch of result set and have to iterate these steps until you get enough results to display.
2)Second approach to this is to index authorization meta data along with document in solr.Same as aitchnyu has explained.But to answer your query for document sharing to an external user,along with usergroup and role detail, you index these external user's userid into access_roles field or you can just add an another field to your schema 'access_user' too. Now you can modify search queries for external user's sharing to include access_user field into your filter query.
e.g
q=mainquery
&fq=access_roles:group_1
&fq=access_user:externaluserid
Now the most important thing, update to an indexed documents.Well its off course tedious task, but with careful design and async processing along with solrs partial document update feature(solr 4.0=>), you can achieve reasonably good TPS with solr. If you are using solr <4.0 you can have separate systems for both searching and updates and with care full use of load balancer and master slave replication strategies you will have smile on your face !
There are no built in mechanisms for Solr that I am aware of that will allow you to control access to documents without maintaining the rights in the metadata. The approach outlined by aitchnyu seems reasonable if you keep it a true role level and not assign user specific permissions to a document. That way you can assign roles to users and this will grant them the ability to see documents in the index. Granted you will still need to reindex documents when the roles change, but hopefully you can identify most of the needed roles ahead if time and reduce the need for frequent reindexing.
I need an efficient way to search through my models to find a specific User, here's a list,
User - list of users, their names, etc.
Events - table of events for all users, on when they're not available
Skills - many-to-many relationship with the User, a User could have a lot of skills
Contracts - many-to-one with User, a User could work on multiple contracts, each with a rating (if completed)
... etc.
So I got a lot of tables linked to the User table. I need to search for a set of users fitting certain criteria; for example, he's available from next Thurs through Fri, has x/y/z skills, and has received an average 4 rating on all his completed contracts.
Is there some way to do this search efficiently while minimizing the # of times I hit the database? Sorry if this is a very newb question.
Thanks!
Not sure if this method will solve you issue for all 4 cases, but at least it should help you out in the first one - querying users data efficiently.
I usually find using values or values_list query function faster because it slims down the SELECT part of the actual SQL, and therefore you will get results faster. Django docs regarding this.
Also worth mentioning that starting with new dev version within values and values_list you can query any type of relationship, including many_to_one.
And finally you might find in_bulk also useful. If I do a complex query, you might try to query the ids first of some models using values or values_list and then use in_bulk to get the model instances faster. Django docs about that.