diff --git a/project_task_actual_report/reports/project_task_actual_report.py b/project_task_actual_report/reports/project_task_actual_report.py index 382174d..302d975 100644 --- a/project_task_actual_report/reports/project_task_actual_report.py +++ b/project_task_actual_report/reports/project_task_actual_report.py @@ -263,42 +263,53 @@ def _get_partitioned_data_from(self): @api.model def _get_filled_data_query(self): """Fill empty values in rows with previous value.""" - # Second part ot the idea coming from - # https://stackoverflow.com/a/19012333/11534960 - return """select - message_id as id, - task_id, - message_id, - date, - case when new_name <> old_name -- Change counts as old value - then old_name - else first_value(new_name) - over (partition by task_id, count_new_name order by message_id) - end "name", - case when new_user_id <> old_user_id - then old_user_id - else first_value(new_user_id) - over (partition by task_id, count_new_user_id order by message_id) - end user_id, - case when new_stage_id <> old_stage_id - then old_stage_id - else first_value(new_stage_id) - over (partition by task_id, count_new_stage_id order by message_id) - end stage_id, - case when new_kanban_state <> old_kanban_state - then old_kanban_state - else first_value(new_kanban_state) - over (partition by task_id, count_new_kanban_state order by message_id) - end kanban_state, - lag(date) over (partition by task_id order by date) as prev_update, - extract(epoch from - (date - lag(date) - over (partition by task_id order by date)))/ 3600 as duration + return """ +{select_clause} from ({partitioned_data}) partitioned_data """.format( + select_clause=self._get_filled_data_select(), partitioned_data=self._get_partitioned_data_query(), ) + def _get_filled_data_select(self): + """ + Select duration of changes using partitions. + + For each tracked field, use a partition over the task id + to record the time passed + from the last change of any other tracked field. + Ordering of partitions is the date of the change. + Some other fields useful for the context + like message_id and task_id are selected. + `message_id` is used as this table's id. + """ + # Second part ot the idea coming from + # https://stackoverflow.com/a/19012333/11534960 + select_clause = ["""select +message_id as id, +task_id, +message_id, +date, +lag(date) over (partition by task_id order by date) as prev_update, +extract(epoch + from (date - lag(date) + over (partition by task_id order by date))) +/ 3600 +as duration + """] + for field_name in TRACKED_TASK_FIELDS: + field_select = """ +case when new_{field_name} <> old_{field_name} -- Change counts as old value +then old_{field_name} +else first_value(new_{field_name}) + over (partition by task_id, count_new_{field_name} order by message_id) +end +"{field_name}" + """.format(field_name=field_name) + select_clause.append(field_select) + select_clause = ', '.join(select_clause) + return select_clause + @api.model def _get_cleaned_data_query(self): """Clan data that are not interesting.