Only Managers/ bosses can view their sub ordinate in the hierarchy in the employee dashboard except some department employees. e.g. HR in Odoo - odoo

This rule in the employee module works for the employee's(manager) respective own sub-hierarchy only.
[('id', 'child_of', [employee.id for employee in user.employee_ids ])]
But it also applies to all department employees e.g. HR.
While HR dep./users(employees) need to view all employees for their operations.
So have to overwrite the above rule or tweak the Above rule or any other method that works.
['|',('id', 'child_of', [employee.id for employee in user.employee_ids ]),('department_id', '!=', 3)]
I've applied the above but it shows HR(dep id = 3) all their sub-hierarchy, and not their dep employees because it covers in the first part but it shows other departments members all employees for which I initially applied this record rule.
Your Help will be much appreciated.

If i understand your goal (For department!=3: Displaying flat hierarchy instead of vertical hierarchy?), it will solve your problem:
['|',('id', 'child_of', [employee.id for employee in user.employee_ids ]),'&',('department_id', '!=', 3),('id', 'in', [employee.id for employee in user.employee_ids ])]

There is an option in Odoo to apply record rules to a specific group of users and also empty domains against the other users so rule is not applied to other users.
the solution by #sylvain worked but for applying it and filtering but don't filter user groups so that this rule will not apply to the specific user's group.
following are the Steps I followed to solve this.
I created a new user group as Hr_staff for the employee model.
Go to the Employee record rule add the record rule and from below assign a group to this user e.g. Employee officer (maybe already checked)
['|',('id', 'child_of', [employee.id for employee in user.employee_ids ]),('user_id','=',user.id)]
Go to the Employee record rule add the record rule and from below assign a group to this user as Hr_staff(can be any name).
add an empty Domain as
[]
Hr_staff has to see all the employees.
the first rule will be applied to all users who are employee officers and can be set from users in settings.
the second rule will be applied to the Hr_staff (a newly created user group).
After applying this the HR staff can be able to see all employees. while the employee officer group or an employee that has sub employees can be able to see his sub employees and his own employee in view when he logged in and go to the employees' module.
Got help from this youtube video
Youtube video link

Related

Adding Sum into Details view for Crystal Report

I am trying to update a Crystal Report with a new column. This report ("Employee Roster") looks at one table (PREH) and puts out some details, the important ones being Employee, Company, and Craft. The user specifies parameters (Company, Craft, specific Employee [optional]) and the report spits out all employees for that craft/date range and a few other details for them.
I want to add another column for their "HoursWorked" in a given craft, the details of which are found in a different table, PRTH. In PRTH there is one line for each "hours added" entry, and there may be hundreds or thousands of these for a given employee. The SQL for this would be something like:
SELECT SUM(Hours)
FROM dbo.PRTH
WHERE PRTH.Employee=%Employee
AND PRTH.Craft=%Craft
AND PRTH.Company=%Company
AND PRTH.EarnCode NOT IN ('5','6','52','60','100','103')
The main problem I'm finding is that I can't just do a simple join, as that causes a lot of row bloat. Right now the report puts out one line for each employee (grouping by craft) - if I join the table I need, then it makes a LOT of lines for each employee. I want to add just the summary of Hours, based off the current employee that's being looked at in the Details section. I can do what I want in SQL but am not sure how to pass that on in Crystal Reports, ultimately trying to use results of the main report as parameters in this second search.
Any help is greatly appreciated, thank you.
SAMPLE OUTPUT FOR CURRENT REPORT (Parameters=Company 1, Craft=46T)
EE# SortName FullName Co Craft
1553 BOBJONES Jones, Bob 1 46T
1672 RACHELJONES Jones, Rachel 1 46T
2007 TANYAADAMS Adams, Tanya 1 46T
In the above output, I'd be trying to add a new Column "TotalHours". For the first line, I'd expect it to run the SQL statement using Bob Jones' EE for "%Employee", his Craft for "%Craft", and his Company for "%Company".
It sounds like what you're trying to achieve is just this:
SELECT [EE#], SortName, FullName, Co, Craft,
(SELECT SUM(Hours)
FROM dbo.PRTH
WHERE PRTH.Employee=e.Employee
AND PRTH.Craft=e.Craft
AND PRTH.Company=e.Company
AND PRTH.EarnCode NOT IN ('5','6','52','60','100','103')) AS TotalHours
FROM TableWithEmployees AS e
WHERE PRTH.Employee=%Employee
AND PRTH.Craft=%Craft
AND PRTH.Company=%Company;
Is that what you mean?

Aggregate data in a SSAS hierarchy

I have a hierarchy in a dimension in my cube, and a fact table that references that dimension. Let's call that a hierarchy of departments and the fact table contains billing targets set for each department (on a record-per-day basis if that's of any interest).
The data is aggregated as in a usual hierarchy in a multidimensional cube.
The problem is that the data in the fact table is not just limited to the "leaf" departments in the hierarchy tree, and so each node/department may or may not have an actual value for a billing target.
I need to have my measure returning the actual value for any node if there is a value, or the sum of the values of it's descendants (if they themselves have actual values, then ignore their descendants).
I can return the value at any given node by using the .DATAMEMBER property and add a condition to substitute the null (if that is the case) with the sum of descendants as so:
with member DirectD as (iif(([Department].[Departments].currentmember.datamember, [Measures].[Department Billing Target]) = null,
([Measures].[Department Billing Target]),
([Department].[Departments].currentmember.datamember, [Measures].[Department Billing Target])))
The problem is that I cannot ensure that the same logic applies to every node "down" the hierarchy.
The MembersWithData setting is set to NonLeafDataHidden in the dimension.
[Measures].[Department Billing Target] is a calculated member, so it looks like Aggregate is not an option.
As an example, I'd like to get the value of 3000 if I query the billing target for department A (image 1):
For department C on Image 2 I need to get 1400 (E, while having descendants, has an actual value which takes precedence over the sum of it's children).
Any help would be greatly appreciated.
The Hierarchy that you mention seems to be a parentchild hierarchy since you say "The problem is that the data in the fact table is not just limited to the "leaf" departments in the hierarchy tree". Based on this, the problem is that we need to solve is
1)Foreach member of you hierarchy we call the base attribute.
2)If the measure value for the base attribute is null we retuen the summed up value
3)If the measure value for the base attribute is not null then we retuen the indivisual members value. Below is the code piece, there can be some syntax issues but would explain the idea.
The below code is a similar example on adventure works(I did add FullName attribute in the employee dimension). In the picture on right is a parent child hierarchy's, base attribute. This picture show all the employee who had sales. On the left is the hierarchy, notice how the values change in the Test measure for people who are present on the right hand side. For example take a look at "Amy E. Alberts"
The code is
with member [Measures].test as
case when [Employee].[Employees].currentmember.name='All Employees'
then [Measures].[Reseller Sales Amount]
when (strtomember('[Employee].[Full Name].['+[Employee].[Employees].currentmember.name+']'),[Measures].[Reseller Sales Amount])=null
then [Measures].[Reseller Sales Amount]
else (strtomember('[Employee].[Full Name].['+[Employee].[Employees].currentmember.name+']'),[Measures].[Reseller Sales Amount])
end
select {[Measures].[Reseller Sales Amount],[Measures].test}
on columns,
[Employee].[Employees].members
on rows from [Adventure Works]
In the end, I have added the following solution that is working so far:
IIF(NOT ISEMPTY(([Department].[Departments].CURRENTMEMBER.DATABEMBER, [Measures].[Department Billing Target Canonical])),
([Department].[Departments].CURRENTMEMBER.DATABEMBER, [Measures].[Department Billing Target Canonical]),
IIF(ISEMPTY(SUM(descendants([Department].[Departments].CURRENTMEMBER, [Department].[Departments], AFTER), IIF(
ISEMPTY(([Department].[Departments].CURRENTMEMBER.parent.DATABEMBER, [Measures].[Department Billing Target Canonical])),
([Department].[Departments].CURRENTMEMBER.DATABEMBER, [Measures].[Department Billing Target Canonical]),
NULL))),
([Department].[Departments].CURRENTMEMBER.DATABEMBER, [Measures].[Department Billing Target Canonical]),
SUM(descendants([Department].[Departments].CURRENTMEMBER, [Department].[Departments], AFTER), IIF(
ISEMPTY(([Department].[Departments].CURRENTMEMBER.parent.DATABEMBER, [Measures].[Department Billing Target Canonical])),
([Department].[Departments].CURRENTMEMBER.DATABEMBER, [Measures].[Department Billing Target Canonical]),
NULL))))
Granted it may not be the prettiest solution (in fact I'm pretty sure it's one of the ugliest), but it works for me.
The gist of it is that the algorithm checks if the parent node of the current one has any data (currentmember.parent.datamember) and if so, substitutes the current member's value with NULL. All those values are piled up in a set, and the sum of it's "contents" is the resulting value. The outmost IIF is there to cover a sort of an edge case.
EDIT: There is also a feeling that this whole issue is just a matter of some SSAS setting that has to be changed. This setting continues to elude me.

Access/SQL Select Query - Return "Most Like" Value Only

We have a chargeback process in an AccessDB where Departments must approve the expenses entered by another department. We only want a single 'default' approver, but the way the data has been set-up and the query we currently use to fill in the approver returns multiple results.
In the tUserSec table, for example, we have two columns. Name(UserIDX) and UserCode
User1 - 550*
User2 - 55003*
The idea here being that User1 is the Director and so is a 'catchall' for everything in this department, while User2 is a Manager and is specifically assigned to a narrower division. Departments are always 7 characters total.
Say the Department is 5500309, the idea is that User2 should populate as the approver since their code is most closely matched to the Department ID. However, using the "Like" criteria returns both users and the form appears to select one of the two users at random with no rhyme or reason that I can determine. It always selects User1 for 5500309 but always selects User2 for 5500301, despite there being no further delineation - but ideally User1 shouldn't be populating at all unless no one else matches closer.
Below is a simplified version of the SQL, I cut out some other stuff that muddies the situation:
SELECT TDepts.Dept, TDepts.DDescr, tUserSec.UserIDX
FROM tUserSec, TDepts
WHERE (((TDepts.Dept) Like [usercode] & "*"));
How can I change this up so that I only pull in the UserID who is most like the usercode? I tried to figure out a way to pull in the UserID based on the length or max of the usercode, etc. but I wasn't able to find a way that worked. It's a safe assumption that if two users have usercodes that are "like" the department that the usercode that is longest is the one we want.
(This is my first question on here and a struggled with how to best explain this issue. Please be gentle :) )
First, I have to say that the main problem here is when a developer thought that they would be clever and build a lot of logic into the department and user IDs. Hiding this sort of information within a column is a big source of headaches in general (as you're just starting to see).
I don't develop with Access, so I'm not certain of the syntax, but hopefully you'll get the general idea. Please let me know if the syntax needs to be tweaked for future users who find this question:
SELECT
D.Dept,
D.DDescr,
U.UserIDX
FROM
TDepts D
LEFT OUTER JOIN
(
SELECT
SQ_D.Dept,
MAX(LEN(SQ_U.usercode)) AS max_len_usercode
FROM
TDepts SQ_D
INNER JOIN tUserSec SQ_U ON SQ_D.Dept LIKE SQ_U.usercode & "*"
GROUP BY
SQ_D.Dept
) SQ ON SQ_D.Dept = D.Dept
LEFT OUTER JOIN tUserSec U ON
D.Dept LIKE U.usercode & "*" AND
LEN(U.usercode) = SQ.max_len_usercode
The query gets a list of all of the departments along with the length of the longest usercode that matches for that department. Then it uses that to determine which user matches for the "most like" the department.

How to concatenate multiple record data into one record?

A picture is worth a thousand words, so I'll show you what I'm trying to accomplish first:
This is a report representing a schedule over the month of September.
The data is obtained from three tables: Employees, Employees_Shifts, and Shifts.
The Report's RecordSource property uses the following query to get the names:
SELECT DISTINCT
Employees.Employee_ID, Employees.Last_Name, Employees.First_Name
FROM
Shifts
INNER JOIN
(Employees
INNER JOIN
Employees_Shifts ON Employees.Employee_ID = Employees_Shifts.Employee_ID)
ON Shifts.Shift_ID = Employees_Shifts.Shift_ID
WHERE
(((Shifts.Schedule_ID) = 1))
ORDER BY
Employees.Last_Name;
So now I'm at the really tricky part where I need to populate all the textboxes with the appropriate data. Each textbox is supposed to hold one letter: A,B,C,D, etc.
Each of these is a letter "designation" assigned to any given Shift. You can have multiple shifts happening at the same time but in different locations. FYI, notice the "Part 1" in the header. I intend to make a second report that goes more into detail on each shift which you can lookup the letter designation for any given day. But that's not pertinent to this particular problem.
I need to somehow query the database for the "designation" field in the Shifts table so that I can assign all the letters: A,B,C,D, etc. into the appropriate boxes.
For instance the output of such a query maybe looks like this:
Allen Nelli 3A,7B,10A,13A,14B,17B,19C,21A
Barlow_Steeves Donna 1A,3B,7A,13B,18A,23A,25A
Beno Wayne 1B,7B,8A,10A,14B,15C
The number/letter combination would represent day and designation together so that I can somehow assign the right letter into the appropriate textbox.
I don't even know if this is at all possible using SQL. I tried tinkering with this query:
SELECT distinct
Employees.Employee_ID, Employees.Last_Name, Employees.First_Name,
Day(Shifts.Start_Date_Time) & Shifts.Designation AS Expr1
FROM
Shifts
INNER JOIN
(Employees
INNER JOIN
Employees_Shifts ON Employees.Employee_ID = Employees_Shifts.Employee_ID)
ON Shifts.Shift_ID = Employees_Shifts.Shift_ID
WHERE
(((Shifts.Schedule_ID) = 1));
However, this gives me the following output:
8 Allen Nelli 10A
8 Allen Nelli 13A
8 Allen Nelli 14B
etc.
I don't want every employee showing up in the report multiple times like that. That's why I used the DISTINCT operator in the original query.
Surely there is a way to query this database so that I can assign the appropriate letter in each textbox using its ControlSource property? Or even just doing a separate query and assign the letter to the Value property of each textbox using vba code?
Any assistance/direction would be appreciated.
I think it'll be beneficial for you to create a sub query that aggregates the shift designations based on the employeeid. Do an inner join on this sub query with the employee table. Once you have the designations aggregated, you can simply use the aggregated designations instead of "Shifts.Designation". You may also need to do a group by.

Help with SQL aggregate functions

I've been learning SQL for about a day now and I've run into a road bump. Please help me with the following questions:
STUDENT (**StudentNumber**, StudentName, TutorialNumber)
TUTORIAL (**TutorialNumber**, Day, Time, Room, TutorInCharge)
ASSESSMENT (**AssessmentNumber**, AssessmentTitle, MarkOutOf)
MARK (**AssessmentNumber**, **StudentNumber**, RawMark)
PK and FK are identified within "**". I need to generate queries that:
1) List of assessment tasks results showing: Assessment Number, Assessment Title, and average Raw Mark. I know how to use the avg function for a single column, but to display something for multiple columns... a little unsure here.
My attempt:
SELECT RawMark, AssessmentNumber, AsessmentTitle
FROM MARK, ASSESSMENT
WHERE RawMark = (SELECT (RawMark) FROM MARK)
AND MARK.AssessmentNumber = ASSESSMENT.AssessmentNumber;
2) Report on tutorial enrollment showing: Tutorial Number, Day, Room, Tutor in Charge and number of students enrolled. Same as the avg function, now for the count function. Would this require 2 queries?
3) List each student's Raw Mark in each of the assessment tasks showing: Assessment Number, Assessment Title, Student Number, Student Name, Raw Mark, Tutor in Charge and Time. Sort on Tutor in Charge, Day and Time.
Here is an example for the first one, just take the logic and see if you can expand it to the other questions. I find that these things can be hard to lear if you can't find any solid examples but once you get the hang of it you'll sort it out pretty quick.
1)
SELECT a.AssessmentNumber, a.AssessmentTitle, AVG(RawMark)
FROM ASSESSMENT a LEFT JOIN MARK m ON a.AssessmentNumber = m.AssessmentNumber
GROUP BY a.AssessmentNumber, a.AssessmentTitle
OR not using a left join or alias table names
SELECT ASSESSMENT.AssessmentNumber, ASSESSMENT.AssessmentTitle, AVG(RawMark)
FROM ASSESSMENT,MARK
WHERE ASSESSMENT.AssessmentNumber = MARK.AssessmentNumber
GROUP BY ASSESSMENT.AssessmentNumber, ASSESSMENT.AssessmentTitle