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 222 222: def actualEnd 223: @expectedEnd 224: end
The reporting remaining effort in days.
# File lib/TimeSheets.rb, line 205 205: def actualRemaining 206: project = @timeSheet.resource.project 207: project.convertToDailyLoad(@remaining * project['scheduleGranularity']) 208: end
The reported work in % (0.0 - 100.0) of the average working time.
# File lib/TimeSheets.rb, line 188 188: def actualWorkPercent 189: (@work.to_f / @timeSheet.totalGrossWorkingSlots) * 100.0 190: 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 227 227: def planEnd 228: @task['end', @timeSheet.scenarioIdx] 229: end
The remaining effort according to the plan.
# File lib/TimeSheets.rb, line 211 211: def planRemaining 212: resource = @timeSheet.resource 213: project = resource.project 214: scenarioIdx = @timeSheet.scenarioIdx 215: startIdx = project.dateToIdx(project['now'], true) 216: endIdx = project.dateToIdx(@task['end', scenarioIdx]) 217: remainingWork = @task.getEffectiveWork(scenarioIdx, startIdx, endIdx, 218: resource) 219: end
The planned work in % (0.0 - 100.0) of the average working time.
# File lib/TimeSheets.rb, line 193 193: def planWorkPercent 194: resource = @timeSheet.resource 195: project = resource.project 196: scenarioIdx = @timeSheet.scenarioIdx 197: startIdx = project.dateToIdx(@timeSheet.interval.start) 198: endIdx = project.dateToIdx(@timeSheet.interval.end) 199: (@timeSheet.resource.getAllocatedSlots(scenarioIdx, startIdx, endIdx, 200: @task).to_f / 201: @timeSheet.totalGrossWorkingSlots) * 100.0 202: end
# File lib/TimeSheets.rb, line 183 183: def taskId 184: @task.is_a?(Task) ? @task.fullId : task 185: 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 for task #{@task.fullId}") 179: end 180: end 181: 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.