feat: implement organization working days and hours settings
- Added functionality to fetch and update organization working days and hours in the admin center. - Introduced a form for saving working days and hours, with validation and error handling. - Updated the reporting allocation logic to utilize organization-specific working hours for accurate calculations. - Enhanced localization files to support new settings in English, Spanish, and Portuguese.
This commit is contained in:
@@ -118,7 +118,7 @@ BEGIN
|
||||
SELECT SUM(time_spent)
|
||||
FROM task_work_log
|
||||
WHERE task_id = t.id
|
||||
), 0) as logged_minutes
|
||||
), 0) / 60.0 as logged_minutes
|
||||
FROM tasks t
|
||||
WHERE t.id = _task_id
|
||||
)
|
||||
|
||||
@@ -415,15 +415,20 @@ export default class ReportingController extends WorklenzControllerBase {
|
||||
|
||||
@HandleExceptions()
|
||||
public static async getMyTeams(req: IWorkLenzRequest, res: IWorkLenzResponse): Promise<IWorkLenzResponse> {
|
||||
const selectedTeamId = req.user?.team_id;
|
||||
if (!selectedTeamId) {
|
||||
return res.status(400).send(new ServerResponse(false, "No selected team"));
|
||||
}
|
||||
const q = `SELECT team_id AS id, name
|
||||
FROM team_members tm
|
||||
LEFT JOIN teams ON teams.id = tm.team_id
|
||||
WHERE tm.user_id = $1
|
||||
AND tm.team_id = $2
|
||||
AND role_id IN (SELECT id
|
||||
FROM roles
|
||||
WHERE (admin_role IS TRUE OR owner IS TRUE))
|
||||
ORDER BY name;`;
|
||||
const result = await db.query(q, [req.user?.id]);
|
||||
const result = await db.query(q, [req.user?.id, selectedTeamId]);
|
||||
result.rows.forEach((team: any) => team.selected = true);
|
||||
return res.status(200).send(new ServerResponse(true, result.rows));
|
||||
}
|
||||
|
||||
@@ -445,27 +445,44 @@ export default class ReportingAllocationController extends ReportingControllerBa
|
||||
}
|
||||
}
|
||||
|
||||
// Count only weekdays (Mon-Fri) in the period
|
||||
// Fetch organization_id from the selected team
|
||||
const selectedTeamId = req.user?.team_id;
|
||||
let organizationId: string | undefined = undefined;
|
||||
if (selectedTeamId) {
|
||||
const orgIdQuery = `SELECT organization_id FROM teams WHERE id = $1`;
|
||||
const orgIdResult = await db.query(orgIdQuery, [selectedTeamId]);
|
||||
organizationId = orgIdResult.rows[0]?.organization_id;
|
||||
}
|
||||
|
||||
// Fetch organization working hours and working days
|
||||
let orgWorkingHours = 8;
|
||||
let orgWorkingDays: { [key: string]: boolean } = {
|
||||
monday: true, tuesday: true, wednesday: true, thursday: true, friday: true, saturday: false, sunday: false
|
||||
};
|
||||
if (organizationId) {
|
||||
const orgHoursQuery = `SELECT working_hours FROM organizations WHERE id = $1`;
|
||||
const orgHoursResult = await db.query(orgHoursQuery, [organizationId]);
|
||||
if (orgHoursResult.rows[0]?.working_hours) {
|
||||
orgWorkingHours = orgHoursResult.rows[0].working_hours;
|
||||
}
|
||||
const orgDaysQuery = `SELECT monday, tuesday, wednesday, thursday, friday, saturday, sunday FROM organization_working_days WHERE organization_id = $1 ORDER BY created_at DESC LIMIT 1`;
|
||||
const orgDaysResult = await db.query(orgDaysQuery, [organizationId]);
|
||||
if (orgDaysResult.rows[0]) {
|
||||
orgWorkingDays = orgDaysResult.rows[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Count only organization working days in the period
|
||||
let workingDays = 0;
|
||||
let current = startDate.clone();
|
||||
while (current.isSameOrBefore(endDate, 'day')) {
|
||||
const day = current.isoWeekday();
|
||||
if (day >= 1 && day <= 5) workingDays++;
|
||||
const weekday = current.format('dddd').toLowerCase(); // e.g., 'monday'
|
||||
if (orgWorkingDays[weekday]) workingDays++;
|
||||
current.add(1, 'day');
|
||||
}
|
||||
|
||||
// Get hours_per_day for all selected projects
|
||||
const projectHoursQuery = `SELECT id, hours_per_day FROM projects WHERE id IN (${projectIds})`;
|
||||
const projectHoursResult = await db.query(projectHoursQuery, []);
|
||||
const projectHoursMap: Record<string, number> = {};
|
||||
for (const row of projectHoursResult.rows) {
|
||||
projectHoursMap[row.id] = row.hours_per_day || 8;
|
||||
}
|
||||
// Sum total working hours for all selected projects
|
||||
let totalWorkingHours = 0;
|
||||
for (const pid of Object.keys(projectHoursMap)) {
|
||||
totalWorkingHours += workingDays * projectHoursMap[pid];
|
||||
}
|
||||
// Use organization working hours for total working hours
|
||||
const totalWorkingHours = workingDays * orgWorkingHours;
|
||||
|
||||
const durationClause = this.getDateRangeClause(duration || DATE_RANGES.LAST_WEEK, date_range);
|
||||
const archivedClause = archived
|
||||
|
||||
Reference in New Issue
Block a user