Class: TaskJuggler::StatusSheetReport

Inherits:
ReportBase show all
Defined in:
lib/taskjuggler/reports/StatusSheetReport.rb

Overview

This specialization of ReportBase implements a template generator for status sheets. The status sheet is structured using the TJP file syntax.

Instance Method Summary collapse

Methods inherited from ReportBase

#a, #filterAccountList, #filterResourceList, #filterTaskList

Constructor Details

#initialize(report) ⇒ StatusSheetReport

Create a new object and set some default values.



61
62
63
64
65
66
# File 'lib/taskjuggler/reports/StatusSheetReport.rb', line 61

def initialize(report)
  super(report)

  # A list of ManagerStatusRecord objects, one for each manager.
  @managers = []
end

Instance Method Details

#generateIntermediateFormatObject

In the future we might want to generate other output than TJP synatx. So we generate an abstract version of the status sheet first.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/taskjuggler/reports/StatusSheetReport.rb', line 70

def generateIntermediateFormat
  super

  # Prepare the resource list.
  resourceList = PropertyList.new(@project.resources)
  resourceList.setSorting(@report.get('sortResources'))
  resourceList = filterResourceList(resourceList, nil,
                                    @report.get('hideResource'),
                                    @report.get('rollupResource'),
                                    @report.get('openNodes'))
  # Prepare a template for the Query we will use to get all the data.
  scenarioIdx = a('scenarios')[0]
  queryAttrs = { 'project' => @project,
                 'scopeProperty' => nil,
                 'scenarioIdx' => scenarioIdx,
                 'loadUnit' => :days,
                 'numberFormat' => RealFormat.new([ '-', '', '', '.', 1]),
                 'timeFormat' => "%Y-%m-%d",
                 'currencyFormat' => a('currencyFormat'),
                 'start' => a('start'), 'end' => a('end'),
                 'hideJournalEntry' => a('hideJournalEntry'),
                 'journalMode' => a('journalMode'),
                 'journalAttributes' => a('journalAttributes'),
                 'sortJournalEntries' => a('sortJournalEntries'),
                 'costAccount' => a('costaccount'),
                 'revenueAccount' => a('revenueaccount') }
  resourceList.query = Query.new(queryAttrs)
  resourceList.sort!

  # Prepare the task list.
  taskList = PropertyList.new(@project.tasks)
  taskList.setSorting(@report.get('sortTasks'))
  taskList = filterTaskList(taskList, nil, @report.get('hideTask'),
                            @report.get('rollupTask'),
                            @report.get('openNodes'))
  taskList.sort!

  resourceList.each do |resource|
    # Status sheets only make sense for leaf resources.
    next unless resource.leaf?

    # Collect a list of tasks that the Resource is responsible for and
    # don't have a parent task that the Resource is responsible for.
    topLevelTasks = []
    taskList.each do |task|
      if task['responsible', scenarioIdx].include?(resource) &&
         (task.parent.nil? ||
          !task.parent['responsible', scenarioIdx].include?(resource))
        topLevelTasks << task
      end
    end

    next if topLevelTasks.empty?

    # Store the list of top-level responsibilities.
    @managers << (manager = ManagerStatusRecord.new(resource))

    topLevelTasks.each do |task|
      # Get a list of all the current Journal entries for this task and
      # all it's sub tasks.
      entries = @project['journal'].
        currentEntriesR(a('end'), task, 0, a('start') + 1,
                        resourceList.query)
      next if entries.empty?

      manager.responsibilities << ManagerResponsibilities.new(task, entries)
    end
    # Sort the responsibilities list according to the original taskList.
    manager.sort!(taskList)
  end
end

#to_tjpObject

Generate a time sheet in TJP syntax format.



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/taskjuggler/reports/StatusSheetReport.rb', line 143

def to_tjp

  # This String will hold the result.
  @file = ''

  # Iterate over all the ManagerStatusRecord objects.
  @managers.each do |manager|
    resource = manager.resource
    @file << "# --------8<--------8<--------\n"
    # Generate the time sheet header
    @file << "statussheet #{resource.fullId} " +
             "#{a('start')} - #{a('end')} {\n\n"

    if manager.responsibilities.empty?
      # If there were no assignments, just write a comment.
      @file << "  # This resource is not responsible for any task.\n\n"
    else
      manager.responsibilities.each do |responsibility|
        task = responsibility.task
        @file << "  # Task: #{task.name}\n"

        responsibility.journalEntries.each do |entry|
          task = entry.property
          @file << "  task #{task.fullId} {\n"
          alertLevel = @project['alertLevels'][entry.alertLevel].id
          @file << "    # status #{alertLevel} \"#{entry.headline}\" {\n"
          @file << "    #   # Date: #{entry.date}\n"
          if (tsRecord = entry.timeSheetRecord)
            @file << "    #   # "
            @file << "Work: #{tsRecord.actualWorkPercent.to_i}% "
            if tsRecord.actualWorkPercent != tsRecord.planWorkPercent
              @file << "(#{tsRecord.planWorkPercent.to_i}%) "
            end
            if tsRecord.remaining
              @file << "   Remaining: #{tsRecord.actualRemaining}d "
              if tsRecord.actualRemaining !=  tsRecord.planRemaining
                @file << "(#{tsRecord.planRemaining}d) "
              end
            else
              @file << "   End: " +
                       "#{tsRecord.actualEnd.to_s(a('timeFormat'))} "
              if tsRecord.actualEnd != tsRecord.planEnd
                @file << "(#{tsRecord.planEnd.to_s(a('timeFormat'))}) "
              end
            end
            @file << "\n"
          end
          @file << "    #   author #{entry.author.fullId}\n" if entry.author
          unless entry.flags.empty?
            @file << "    #   flags #{entry.flags.join(', ')}\n"
          end
          if entry.summary
            @file << "    #   summary -8<-\n" +
                     indentBlock(4, entry.summary.richText.inputText) +
                     "    #   ->8-\n"
          end
          if entry.details
            @file << "    #   details -8<-\n" +
                     indentBlock(4, entry.details.richText.inputText) +
                     "    #   ->8-\n"
          end
          @file << "    # }\n  }\n\n"

        end
      end
    end
    @file << "}\n# -------->8-------->8--------\n\n"
  end
  @file
end