diff --git a/workers/main/src/configs/weeklyFinancialReport.ts b/workers/main/src/configs/weeklyFinancialReport.ts index 0c5ba49..6d02b13 100644 --- a/workers/main/src/configs/weeklyFinancialReport.ts +++ b/workers/main/src/configs/weeklyFinancialReport.ts @@ -5,3 +5,9 @@ export enum GroupNameEnum { export const HIGH_MARGINALITY_THRESHOLD = 55; export const MEDIUM_MARGINALITY_THRESHOLD = 45; + +// ID of the custom field in Redmine used for report filtering +export const REPORT_FILTER_FIELD_ID = 253; + +// ID of the custom field in Redmine used to link issue to Billable project +export const RELATED_PROJECT_FIELD_ID = 20; diff --git a/workers/main/src/services/TargetUnit/queries.ts b/workers/main/src/services/TargetUnit/queries.ts index 7171d67..75f8df3 100644 --- a/workers/main/src/services/TargetUnit/queries.ts +++ b/workers/main/src/services/TargetUnit/queries.ts @@ -1,4 +1,71 @@ -export const TARGET_UNITS_QUERY = `SELECT +import { + GroupNameEnum, + RELATED_PROJECT_FIELD_ID, + REPORT_FILTER_FIELD_ID, +} from '../../configs/weeklyFinancialReport'; + +const groupNamesList = Object.values(GroupNameEnum) + .map((name) => `'${name.replace(/'/g, "''")}'`) + .join(', '); + +const COMMON_SELECT = ` + SELECT + g.id AS group_id, + g.lastname AS group_name, + p.id AS project_id, + p.name AS project_name, + te.user_id AS user_id, + CONCAT(u.firstname, ' ', u.lastname) AS username, + te.spent_on AS spent_on, + cv.value AS filter_name, +`; + +const COMMON_FROM = ` + FROM users AS g + JOIN custom_values as cv ON cv.customized_id = g.id + JOIN members AS m ON m.user_id = g.id + JOIN projects AS p ON p.id = m.project_id +`; + +const COMMON_WHERE = ` + WHERE g.type = 'Group' + AND cv.customized_type = 'Principal' + AND cv.custom_field_id = ${REPORT_FILTER_FIELD_ID} + AND cv.value IN (${groupNamesList}) + AND te.spent_on BETWEEN DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) + 7 DAY) + AND DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) + 1 DAY) +`; + +function buildDirectGroupTimeEntries() { + return ` + ${COMMON_SELECT} + te.hours AS project_hours, + 0 as deptech_hours + ${COMMON_FROM} + JOIN time_entries te ON te.project_id = p.id + JOIN users AS u ON u.id = te.user_id + ${COMMON_WHERE} + `; +} + +function buildRelatedProjectTimeEntries() { + return ` + ${COMMON_SELECT} + 0 as project_hours, + te.hours AS deptech_hours + ${COMMON_FROM} + JOIN custom_values icv ON icv.value = CAST(p.id AS CHAR) + AND icv.customized_type = 'Issue' + AND icv.custom_field_id = ${RELATED_PROJECT_FIELD_ID} + AND icv.value <> "" + JOIN time_entries te ON te.issue_id = icv.customized_id + JOIN users AS u ON u.id = te.user_id + ${COMMON_WHERE} + `; +} + +export const TARGET_UNITS_QUERY = ` + SELECT group_id, group_name, project_id, @@ -6,45 +73,27 @@ export const TARGET_UNITS_QUERY = `SELECT user_id, username, DATE_FORMAT(spent_on, '%Y-%m-%d') AS spent_on, - SUM(total_hours) AS total_hours + SUM(project_hours) AS project_hours, + SUM(deptech_hours) AS deptech_hours, + SUM(project_hours) + SUM(deptech_hours) AS total_hours, + filter_name FROM ( - SELECT - g.id AS group_id, - g.lastname AS group_name, - p.id AS project_id, - p.name AS project_name, - te.user_id AS user_id, - CONCAT(u.firstname, ' ', u.lastname) AS username, - te.spent_on AS spent_on, - te.hours AS total_hours - FROM users AS g - JOIN custom_values as cv ON cv.customized_id = g.id - JOIN members AS m ON m.user_id = g.id - JOIN projects AS p ON p.id = m.project_id - JOIN time_entries te ON te.project_id = p.id - JOIN users AS u ON u.id = te.user_id - WHERE g.type = 'Group' - AND cv.customized_type = 'Principal' and cv.value = ? - AND te.spent_on BETWEEN - DATE_FORMAT( - DATE_SUB( - DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) + 1 DAY), - INTERVAL (MONTH(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) + 1 DAY))-1)%3 MONTH - ), - '%Y-%m-01' - ) - AND DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) + 1 DAY) + ${buildDirectGroupTimeEntries()} + UNION ALL + ${buildRelatedProjectTimeEntries()} ) t GROUP BY - group_id, - group_name, - project_id, - project_name, - user_id, - username, - spent_on + t.group_id, + t.group_name, + t.project_id, + t.project_name, + t.user_id, + t.username, + t.spent_on, + t.filter_name ORDER BY - group_name ASC, - project_name ASC, - username ASC, - spent_on ASC`; + t.group_name ASC, + t.project_name ASC, + t.username ASC, + t.spent_on ASC +`;