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 29 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 227 def actualEnd @expectedEnd end
The reporting remaining effort in days.
# File lib/taskjuggler/TimeSheets.rb, line 211 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 194 def actualWorkPercent (@work.to_f / @timeSheet.totalGrossWorkingSlots) * 100.0 end
Perform all kinds of consistency checks.
# File lib/taskjuggler/TimeSheets.rb, line 62 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 232 def planEnd @task['end', @timeSheet.scenarioIdx] end
The remaining effort according to the plan.
# File lib/taskjuggler/TimeSheets.rb, line 217 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 199 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 189 def taskId @task.is_a?(Task) ? @task.fullId : task end
# File lib/taskjuggler/TimeSheets.rb, line 130 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 52 def work=(value) if value.is_a?(Integer) @work = value else # Must be percent value @work = @timeSheet.percentToSlots(value) end end