Redmine is being introduced not only to ensure a predictable process of work on tasks. An important point is the analysis of the actions to improve the work and to develop a KPI for employees.
You can use a simple Custom report generator to visualize analytical information. Reports are simple, but better than nothing. You can assign a report to an employee with a specific role.
Go to State
In case the work on the task is cyclical, for example, design-coding-testing-an important characteristic to assess the quality of the department can be the number of transitions to a specific state, showing how many times the task Back for revision. For example, you need to track how well testers test the layout. In this case, look at the number of transitions from any status other than "Testing".
# ID for status "Testing"-10 if (CFS. Blank?) CFS = 0 end if (self. status_id = = 10 & & self. Status_id_was! = 10) CFS + 1; Else Cfs end
It is Interesting to see how long it takes a certain stage of development. For Example, how much time was spent on the Test phase when the task was run.
Let's Create a variable date of the last stage with the DateTime type, where we will record the date and time when the previous stage in the process was started:
The #Переменная in the list of custom fields should be at the very end. if (self. status_id! = self. Status_id_was) CFS = DateTime. Now; Else cfs end
It is Important that this variable from the list of custom fields is followed by the custom fields where its value is used. This is important because if you put it before, the variable will be overwritten by the new data just before the script is run calculating the time elapsed since the last operation.
Let's Create another computed custom field with the type Float. For the Test status, the script will be:
# ID for status "Testing"-10 if (CFS. Blank?) CFS = 0 end if (cfs. Blank? | |! cfs. Present?) CFS = DateTime. Now; end if ((self. status_id = = 10 & & self. Status_id_was! = 10) | | (self. Status_id_was = = 10 & & self. status_id! = 10)) diff = DateTime. now. To _time-CFS. to _time; #self. Description = (diff). to _s + "rn"; CFS = (cfs + diff)/60; #In minutes Else Cfs end
The Key status of the time cutoff is "Testing". Accordingly, from the moment when other departments have transferred from any other status to the status "Start testing" the date and time of transition to this status is saved. As soon as the status is changed, the time spent on transition from the status "Start testing" to the status "Testing" is calculated.
With the status of "Testing" the task can go to different statuses, but any of these transitions means that the test phase is complete. You need to fix the time spent on the stage and add it to the previously saved one.
It is Clear that such a simple version of the timing of the stage gives the total value that was needed for the stage. If the status has been transferred before the end of the working day, the nonworking time is also taken into account. Correctly isolate nonworking time-the thing is quite laborious for the case when the schedule is relatively free. Let's say the employee can come a couple of hours later than the rest and linger for this time.
In The simplest case, if more or less time to rest, say, the employee left work in 18.00 and came in 9.00, and if left in 20.00, then came to work in 11.00, the code for correction will be simple:
NumOfDays = (DateTime. Now. To _data-CFS. to_date). to _i; Excludetime = numofdays * 15 * 3600; CFS = (cfs + diff-Excludetime)/60; #In minutes
15 is an approximate number of non-working hours. Accordingly, if both statuses were translated in one day, the difference between the dates would be 0 and no amendment would be made. If one day has passed between the change of statuses, the 15-hour correction will be deducted from the calculated total amount of time in seconds.
Several people can work On the task. Since Redmine can filter only on values in columns, in order to quickly conduct some kind of analytics, like what percentage of tasks for the Opredeennyj period of time made by employees, you need to create a field in which will be recorded last name Employee who performed the work.
Suppose There is a group of designers. You need to make a calculated field that will be filled with a reference to the employee performing the design. Accordingly, a calculated field with the User type is created.
There are several statuses which in the standard process clearly characterize that the design was carried out by this employee: design development and redesign. First status when the task only fell on the designer and he took it to work. Second status-When the design was previously made, but it was sent to rework. In The analysis we believe that the task was done by the employee who performed the work last. This is not very correct, because the edits can be very small, respectively, the analysis may result in the way that the employee who did not work for a long period will get all the honor. But for simplification we believe that the situation when the task is transferred to the redesign of another designer is extremely rare.
According to the idea, the task hit in two marked statuses is a guarantee of correct filling of the field "Designer". To Insure, you can add that when you care for any other status from the status of "Design" and "Redesign" is also a change of responsibility. The idea could only be limited to the last conditions, but in this case, when building the dimension until the design is finished, the's responsibility field would not be filled.
Therefore, the code will look like this:
# ID for the "Designer" role-10 # ID for the status of "Redesign"-27 # ID for "design Development" status-18 # ID for "Design developed" status-17 # ID for "design Approval" status-19 # ID for the "Start layout" status-20 # ID custom field for the current field-34 if (User. Current. Roles_for_project (Project). Map (&: ID). include? 10) & & ((self. status_id = = 17) | | #Дизайн developed (self. status_id = = 18) | | Design #Разработка (self. status_id = = 27) | | #Редизайн (self. Status_id_was = = 18) | | Design #Разработка (self. Status_id_was = = 27) #Редизайн ) User.current.id Else Cfs end
If the user is a member of a group of designers (check the line (User. Current. Roles_for_project (Project). Map (&: ID). include? 10)), then the installation of any of the 5 previously voiced statuses will result in the field with ID = 34 will be registered the current User. Accordingly, it will be possible to unload the report using standard Redmine tools, for example, in CSV and analyze PivotTable tables in Excel, for example, how many tasks each of the employees of the design department did.
In this case, it is extremely important for the code to work correctly, so that the task designer is transferred to the "design" or "Redesign" status change. Otherwise, you need to add to the conditions all the statuses to which the designer can translate the task.
The Moment, important for analytics-what date to take for grouping by periods: date of creation of a task, date of start of work on it, date of completion, special date of work on a stage or something else.
Suppose that the project lasts several months and at each stage for some time different departments work on it. Say, in January, the manager made the design, responsible agreed it in February, and in March the task was accepted by the client. It is Obvious that with its part of the task, for example, the designer finished working in January, in a pinch in February, if corrections were made. Question, what date to use?
Considering that in Redmine for analysis the date should be put in a column, it is necessary to add the calculated field in which the date when the stage has been finally finished by the designer will be written. In essence, it is enough to add some computed field of type DateTime and to write in it a value every time when the designer changes the status with the values "Redesign", "Design Development", "Design is developed" on any other, actually indicating that its work Completed.
# ID for the "Designer" role-10 # ID for the status of "Redesign"-27 # ID for "design Development" status-18 # ID for "Design developed" status-17 # ID custom field for the current field-97 if (User. Current. Roles_for_project (Project). Map (&: ID). include? 10) If # (self. status_id! = self. Status_id_was) & & (self. Status_id_was = = 18) | | Design #Разработка (self. Status_id_was = = 27) #Редизайн ) CFS = DateTime. Now; Else Cfs end Else Cfs end
In this case, if an employee from a group of designers goes from the status of "design" or "Redesign" to any other, the field is the current date.
Displaying Analytic fields
Ordinary employees do not need to display analytical fields, so in the field settings you need to put Visibility ("Visible") only for individual roles. For example, managers.