class TaskJuggler::TimeSheetRecord
This class holds the work related bits of a time sheet that are specific to a single Task
. This can be an existing Task
or a new one identified by it’s ID String
. For effort based task, it stores the remaining effort, for other task the expected end date. For all tasks it stores the completed work during the reporting time frame.
Attributes
Public Class Methods
# File lib/taskjuggler/TimeSheets.rb, line 30 def initialize(timeSheet, task) # This is a reference to a Task object for existing tasks or an ID as # String for new tasks. @task = task # Add the new TimeSheetRecord to the TimeSheet it belongs to. (@timeSheet = timeSheet) << self # Work done will be measured in time slots. @work = nil # Remaining work will be measured in time slots. @remaining = nil @expectedEnd = nil # For new task, we also need to store the name. @name = nil # Reference to the JournalEntry object that holds the status for this # record. @status = nil @priority = 0 @sourceFileInfo = nil end
Public Instance Methods
The reported expected end of the task.
# File lib/taskjuggler/TimeSheets.rb, line 228 def actualEnd @expectedEnd end
The reporting remaining effort in days.
# File lib/taskjuggler/TimeSheets.rb, line 212 def actualRemaining project = @timeSheet.resource.project project.convertToDailyLoad(@remaining * project['scheduleGranularity']) end
The reported work in % (0.0 - 100.0) of the average working time.
# File lib/taskjuggler/TimeSheets.rb, line 195 def actualWorkPercent (@work.to_f / @timeSheet.totalGrossWorkingSlots) * 100.0 end
Perform all kinds of consistency checks.
# File lib/taskjuggler/TimeSheets.rb, line 63 def check scIdx = @timeSheet.scenarioIdx taskId = @task.is_a?(Task) ? @task.fullId : @task # All TimeSheetRecords must have a 'work' attribute. if @work.nil? error('ts_no_work', "The time sheet record for task #{taskId} must " + "have a 'work' attribute to specify how much was done " + "for this task during the reported period.") end if @task.is_a?(Task) # This is already known tasks. if @task['effort', scIdx] > 0 unless @remaining error('ts_no_remaining', "The time sheet record for task #{taskId} must " + "have a 'remaining' attribute to specify how much " + "effort is left for this task.") end else unless @expectedEnd error('ts_no_expected_end', "The time sheet record for task #{taskId} must " + "have an 'end' attribute to specify the expected end " + "of this task.") end end else # This is for new tasks. if @remaining.nil? && @expectedEnd.nil? error('ts_no_rem_or_end', "New task #{taskId} requires either a 'remaining' or a " + "'end' attribute.") end end if @work >= @timeSheet.daysToSlots(1) && @status.nil? error('ts_no_status_work', "You must specify a status for task #{taskId}. It was worked " + "on for a day or more.") end if @status if @status.headline.empty? error('ts_no_headline', "You must provide a headline for the status of " + "task #{taskId}") end if @status.summary && @status.summary.richText.inputText == "A summary text\n" error('ts_default_summary', "You must change the default summary text of the status " + "for task #{taskId}.") end if @status.alertLevel > 0 && @status.summary.nil? && @status.details.nil? error('ts_alert1_more_details', "Task #{taskId} has an elevated alert level and must " + "have a summary or details section.") end if @status.alertLevel > 1 && @status.details.nil? error('ts_alert2_more_details', "Task #{taskId} has a high alert level and must have " + "a details section.") end end end
The planned end of the task.
# File lib/taskjuggler/TimeSheets.rb, line 233 def planEnd @task['end', @timeSheet.scenarioIdx] end
The remaining effort according to the plan.
# File lib/taskjuggler/TimeSheets.rb, line 218 def planRemaining resource = @timeSheet.resource project = resource.project scenarioIdx = @timeSheet.scenarioIdx startIdx = project.dateToIdx(project['now']) endIdx = project.dateToIdx(@task['end', scenarioIdx]) @task.getEffectiveWork(scenarioIdx, startIdx, endIdx, resource) end
The planned work in % (0.0 - 100.0) of the average working time.
# File lib/taskjuggler/TimeSheets.rb, line 200 def planWorkPercent resource = @timeSheet.resource project = resource.project scenarioIdx = @timeSheet.scenarioIdx startIdx = project.dateToIdx(@timeSheet.interval.start) endIdx = project.dateToIdx(@timeSheet.interval.end) (@timeSheet.resource.getAllocatedSlots(scenarioIdx, startIdx, endIdx, @task).to_f / @timeSheet.totalGrossWorkingSlots) * 100.0 end
# File lib/taskjuggler/TimeSheets.rb, line 190 def taskId @task.is_a?(Task) ? @task.fullId : task end
# File lib/taskjuggler/TimeSheets.rb, line 131 def warnOnDelta(startIdx, endIdx) # Ignore personal entries. return unless @task resource = @timeSheet.resource if @task.is_a?(String) # A resource has requested a new Task to be created. warning('ts_res_new_task', "#{resource.name} is requesting a new task:\n" + " ID: #{@task}\n" + " Name: #{@name}\n" + " Work: #{@timeSheet.slotsToDays(@work)}d " + (@remaining ? "Remaining: #{@timeSheet.slotsToDays(@remaining)}d" : "End: #{@end.to_s}")) return end scenarioIdx = @timeSheet.scenarioIdx project = resource.project plannedWork = @task.getEffectiveWork(scenarioIdx, startIdx, endIdx, resource) # Convert the @work slots into a daily load. work = project.convertToDailyLoad(@work * project['scheduleGranularity']) if work != plannedWork warning('ts_res_work_delta', "#{resource.name} worked " + "#{work < plannedWork ? 'less' : 'more'} " + "on #{@task.fullId}\n" + "#{work}d instead of #{plannedWork}d") end if @task['effort', scenarioIdx] > 0 startIdx = endIdx endIdx = project.dateToIdx(@task['end', scenarioIdx]) remainingWork = @task.getEffectiveWork(scenarioIdx, startIdx, endIdx, resource) # Convert the @remaining slots into a daily load. remaining = project.convertToDailyLoad(@remaining * project['scheduleGranularity']) if remaining != remainingWork warning('ts_res_remain_delta', "#{resource.name} requests " + "#{remaining < remainingWork ? 'less' : 'more'} " + "remaining effort for task #{@task.fullId}\n" + "#{remaining}d instead of #{remainingWork}d") end else if @expectedEnd != @task['end', scenarioIdx] warning('ts_res_end_delta', "#{resource.name} requests " + "#{@expectedEnd < @task['end', scenarioIdx] ? 'earlier' : 'later'} end (#{@expectedEnd}) for task " + "#{@task.fullId}. Planned end is " + "#{@task['end', scenarioIdx]}.") end end end
Store the number of worked time slots. If the value is an Integer, it can be directly assigned. A Float is interpreted as percentage and must be in the rage of 0.0 to 1.0.
# File lib/taskjuggler/TimeSheets.rb, line 53 def work=(value) if value.is_a?(Integer) @work = value else # Must be percent value @work = @timeSheet.percentToSlots(value) end end