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.
# File lib/TimeSheets.rb, line 26 26: def initialize(timeSheet, task) 27: # This is a reference to a Task object for existing tasks or an ID as 28: # String for new tasks. 29: @task = task 30: # Add the new TimeSheetRecord to the TimeSheet it belongs to. 31: (@timeSheet = timeSheet) << self 32: # Work done will be measured in time slots. 33: @work = nil 34: # Remaining work will be measured in time slots. 35: @remaining = nil 36: @expectedEnd = nil 37: # For new task, we also need to store the name. 38: @name = nil 39: # Reference to the JournalEntry object that holds the status for this 40: # record. 41: @status = nil 42: @priority = 0 43: @sourceFileInfo = nil 44: end
The reported expected end of the task.
# File lib/TimeSheets.rb, line 223 223: def actualEnd 224: @expectedEnd 225: end
The reporting remaining effort in days.
# File lib/TimeSheets.rb, line 207 207: def actualRemaining 208: project = @timeSheet.resource.project 209: project.convertToDailyLoad(@remaining * project['scheduleGranularity']) 210: end
The reported work in % (0.0 - 100.0) of the average working time.
# File lib/TimeSheets.rb, line 190 190: def actualWorkPercent 191: (@work.to_f / @timeSheet.totalGrossWorkingSlots) * 100.0 192: end
Perform all kinds of consistency checks.
# File lib/TimeSheets.rb, line 59 59: def check 60: scIdx = @timeSheet.scenarioIdx 61: taskId = @task.is_a?(Task) ? @task.fullId : @task 62: # All TimeSheetRecords must have a 'work' attribute. 63: if @work.nil? 64: error('ts_no_work', 65: "The time sheet record for task #{taskId} must " + 66: "have a 'work' attribute to specify how much was done " + 67: "for this task during the reported period.") 68: end 69: if @task.is_a?(Task) 70: # This is already known tasks. 71: if @task['effort', scIdx] > 0 72: unless @remaining 73: error('ts_no_remaining', 74: "The time sheet record for task #{taskId} must " + 75: "have a 'remaining' attribute to specify how much " + 76: "effort is left for this task.") 77: end 78: else 79: unless @expectedEnd 80: error('ts_no_expected_end', 81: "The time sheet record for task #{taskId} must " + 82: "have an 'end' attribute to specify the expected end " + 83: "of this task.") 84: end 85: end 86: else 87: # This is for new tasks. 88: if @remaining.nil? && @expectedEnd.nil? 89: error('ts_no_rem_or_end', 90: "New task #{taskId} requires either a 'remaining' or a " + 91: "'end' attribute.") 92: end 93: end 94: 95: if @work >= @timeSheet.daysToSlots(1) && @status.nil? 96: error('ts_no_status_work', 97: "You must specify a status for task #{taskId}.") 98: end 99: 100: if @status 101: if @status.headline.empty? 102: error('ts_no_headline', 103: "You must provide a headline for the status of " + 104: "task #{@task.fullId}") 105: end 106: if @status.summary && 107: @status.summary.richText.inputText == "A summary text\n" 108: error('ts_default_summary', 109: "You must change the default summary text of the status " + 110: "for task #{taskId}.") 111: end 112: if @status.alertLevel > 0 && @status.summary.nil? && 113: @status.details.nil? 114: error('ts_alert1_more_details', 115: "Task #{taskId} has an elevated alert level and must " + 116: "have a summary or details section.") 117: end 118: if @status.alertLevel > 1 && @status.details.nil? 119: error('ts_alert2_more_details', 120: "Task #{taskId} has a high alert level and must have " + 121: "a details section.") 122: end 123: end 124: end
The planned end of the task.
# File lib/TimeSheets.rb, line 228 228: def planEnd 229: @task['end', @timeSheet.scenarioIdx] 230: end
The remaining effort according to the plan.
# File lib/TimeSheets.rb, line 213 213: def planRemaining 214: resource = @timeSheet.resource 215: project = resource.project 216: scenarioIdx = @timeSheet.scenarioIdx 217: startIdx = project.dateToIdx(project['now'], true) 218: endIdx = project.dateToIdx(@task['end', scenarioIdx]) 219: @task.getEffectiveWork(scenarioIdx, startIdx, endIdx, resource) 220: end
The planned work in % (0.0 - 100.0) of the average working time.
# File lib/TimeSheets.rb, line 195 195: def planWorkPercent 196: resource = @timeSheet.resource 197: project = resource.project 198: scenarioIdx = @timeSheet.scenarioIdx 199: startIdx = project.dateToIdx(@timeSheet.interval.start) 200: endIdx = project.dateToIdx(@timeSheet.interval.end) 201: (@timeSheet.resource.getAllocatedSlots(scenarioIdx, startIdx, endIdx, 202: @task).to_f / 203: @timeSheet.totalGrossWorkingSlots) * 100.0 204: end
# File lib/TimeSheets.rb, line 185 185: def taskId 186: @task.is_a?(Task) ? @task.fullId : task 187: end
# File lib/TimeSheets.rb, line 126 126: def warnOnDelta(startIdx, endIdx) 127: # Ignore personal entries. 128: return unless @task 129: 130: resource = @timeSheet.resource 131: if @task.is_a?(String) 132: # A resource has requested a new Task to be created. 133: warning('ts_res_new_task', 134: "#{resource.name} is requesting a new task:\n" + 135: " ID: #{@task}\n" + 136: " Name: #{@name}\n" + 137: " Work: #{@timeSheet.slotsToDays(@work)}d " + 138: (@remaining ? 139: "Remaining: #{@timeSheet.slotsToDays(@remaining)}d" : 140: "End: #{@end.to_s}")) 141: return 142: end 143: 144: scenarioIdx = @timeSheet.scenarioIdx 145: project = resource.project 146: plannedWork = @task.getEffectiveWork(scenarioIdx, startIdx, endIdx, 147: resource) 148: # Convert the @work slots into a daily load. 149: work = project.convertToDailyLoad(@work * project['scheduleGranularity']) 150: 151: if work != plannedWork 152: warning('ts_res_work_delta', 153: "#{resource.name} worked " + 154: "#{work < plannedWork ? 'less' : 'more'} " + 155: "on #{@task.fullId}\n" + 156: "#{work}d instead of #{plannedWork}d") 157: end 158: if @task['effort', scenarioIdx] > 0 159: startIdx = endIdx 160: endIdx = project.dateToIdx(@task['end', scenarioIdx]) 161: remainingWork = @task.getEffectiveWork(scenarioIdx, startIdx, endIdx, 162: resource) 163: # Convert the @remaining slots into a daily load. 164: remaining = project.convertToDailyLoad(@remaining * 165: project['scheduleGranularity']) 166: if remaining != remainingWork 167: warning('ts_res_remain_delta', 168: "#{resource.name} requests " + 169: "#{remaining < remainingWork ? 'less' : 'more'} " + 170: "remaining effort for task #{@task.fullId}\n" + 171: "#{remaining}d instead of #{remainingWork}d") 172: end 173: else 174: if @expectedEnd != @task['end', scenarioIdx] 175: warning('ts_res_end_delta', 176: "#{resource.name} requests " + 177: "#{@expectedEnd < @task['end', scenarioIdx] ? 178: 'earlier' : 'later'} end (#{@expectedEnd}) for task " + 179: "#{@task.fullId}. Planned end is " + 180: "#{@task['end', scenarioIdx]}.") 181: end 182: end 183: end
Store the number of worked time slots. If the value is a Fixnum, 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/TimeSheets.rb, line 49 49: def work=(value) 50: if value.is_a?(Fixnum) 51: @work = value 52: else 53: # Must be percent value 54: @work = @timeSheet.percentToSlots(value) 55: end 56: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.