class Task




Hipposoft 2007


Describe the behaviour of Task objects. See below for more details.

24-Dec-2007 (ADH): Created.



Public Class Methods

generate_xml_code( id ) click to toggle source

Given an ID, generate a task code for an XML-imported task based on the current date.

# File app/models/task.rb, line 130
def self.generate_xml_code( id )
  today = Date.current
  "XML-%04d%02d%02d-#{ id }" % [ today.year, today.month, ]
new( params = nil, user = nil ) click to toggle source

Some default properties are dynamic, so assign these here rather than as defaults in a migration.


Optional hash used for instance initialisation in the traditional way
for an ActiveRecord subclass.

Optional User object. A default project is taken from that user's
control panel data, if available.
# File app/models/task.rb, line 96
def initialize( params = nil, user = nil )
  super( params )

  if ( params.nil? )
    self.duration = 0   = true
    self.code     = "TID%05d" % Task.count

    if ( user and user.control_panel )
      cp = user.control_panel
      self.project = cp.project if ( cp.project and )
sort_by_augmented_title( list ) click to toggle source

Class method - sort an array of tasks by the augmented title. Since this isn’t done by the database, it’s slow.

# File app/models/task.rb, line 153
def self.sort_by_augmented_title( list )
  list.sort! { | x, y | x.augmented_title <=> y.augmented_title }

Public Instance Methods

augmented_title() click to toggle source

Return the ‘augmented’ task title; that is, the task name, with the project and customer names appended if available.

# File app/models/task.rb, line 138
def augmented_title
  if ( self.project )
    if ( self.project.customer )
      return "#{ self.project.customer.title } - #{ self.project.title }: #{ self.title }"

    return "#{ self.project.title }: #{ self.title }"

  return "#{ self.title }"
can_be_modified_by?( user ) click to toggle source

Is the given user permitted to update this task? Restricted users cannot modify tasks. Administrators always can. Managers only can if the task is still active.

# File app/models/task.rb, line 121
def can_be_modified_by?( user )
  return false if ( user.restricted? )
  return true  if ( user.admin?      )
committed_worked() click to toggle source

Number of committed hours worked on this task.

# File app/models/task.rb, line 222
def committed_worked
  joins      = { :timesheet_row => :timesheet }
  conditions = { :timesheets => { :committed => true } }

  return self.work_packets.joins( joins ).where( conditions ).sum( :worked_hours )
is_permitted_for?( user ) click to toggle source

Is the given user permitted to do anything with this task?

# File app/models/task.rb, line 113
def is_permitted_for?( user )
  return ( user.privileged? or user.tasks.include?( self ) )
not_committed_worked() click to toggle source

Number of not committed hours worked on this task.

# File app/models/task.rb, line 231
def not_committed_worked
  joins      = { :timesheet_row => :timesheet }
  conditions = { :timesheets => { :committed => false } }

  return self.work_packets.joins( joins ).where( conditions ).sum( :worked_hours )
split_user_types() click to toggle source

Return an array with two elements - the first is the restricted associated users, the second the unrestricted associated users. Arrays will be empty if there are no associated users. Does this the slow way, asking each user if it is restricted, rather than making assumptions about how to quickly find restricted types.

# File app/models/task.rb, line 163
def split_user_types
  restricted   = []
  unrestricted = []

  self.users.all.each do | user |
    if ( user.restricted? )
      restricted.push( user )
      unrestricted.push( user )

  return [ restricted, unrestricted ]
sum_hours_over_range( date_range, user = nil ) click to toggle source

Number of hours worked on the task between the given start and end Dates as a Range. Optionally pass a User object; work packets will only be counted if they’re in a timesheet belonging to that user.

Returns an object with fields ‘committed’ and ‘not_committed’, giving sums for those types of hours.

# File app/models/task.rb, line 246
def sum_hours_over_range( date_range, user = nil )
  joins         = { :timesheet_row => { :timesheet => :user } }
  committed     = { :timesheets => { :committed => true  } }
  not_committed = { :timesheets => { :committed => false } }
  conditions    = { :date => date_range }

  conditions[ :users ] = { :id => } unless user.nil?

  return {
        :committed => self.work_packets.joins( joins ).where(     committed ).where( conditions ).sum( :worked_hours ),
    :not_committed => self.work_packets.joins( joins ).where( not_committed ).where( conditions ).sum( :worked_hours )
total_worked() click to toggle source

Number of hours worked on this task, committed or otherwise

# File app/models/task.rb, line 216
def total_worked
  return self.work_packets.sum( :worked_hours )
update_with_side_effects!( attrs ) click to toggle source

Update an object with the given attributes. This is done by a special model method because changes of the ‘active’ flag have side effects for other associated objects. THE CALLER *MUST* USE A TRANSACTION around a call to this method. There is no need to call here unless the ‘active’ flag state is changing.

# File app/models/task.rb, line 184
def update_with_side_effects!( attrs )
  active =
  self.update_attributes!( attrs )

  # If the active flag has changed and it *was* 'true', then the task
  # has just been made inactive.

  if ( attrs[ :active ] != active and active == true )

    # When tasks are made inactive, remove them from each of the Task lists
    # in User and ControlPanel objects. There are checks for this elsewhere,
    # but they're only to try and catch cases where this code has gone wrong.
    # Although only restricted users make use of this list, other user types
    # may have a list set up either accidentally or because the user's type
    # is due to be changed to one with lower permissions. As a result, we
    # must update every user.

    User.all.each do | user |

    ControlPanel.all.each do | cp |