Class TimesheetsController
In: app/controllers/timesheets_controller.rb
Parent: ApplicationController
File:timesheets_controller.rb
(C):Hipposoft 2008, 2009
Purpose:Manage Timesheet objects. See models/timesheet.rb for more.

          07-Jan-2008 (ADH): Created.

Methods

create   delete   delete_confirm   edit   index   new   show   update  

Public Instance methods

Create a blank timesheet based on the year and week_number values in the params hash. Save and redirect to edit the timesheet immediately. Certain defaults are set up here - the model would be a better place, but it does not have access to the right instance variables or methods required to determine the appropriate values.

[Source]

     # File app/controllers/timesheets_controller.rb, line 122
122:   def create
123:     @timesheet             = Timesheet.new()
124:     @timesheet.year        = params[ :year ]
125:     @timesheet.week_number = params[ :week_number ]
126:     @timesheet.user        = @current_user
127:     @timesheet.committed   = false
128: 
129:     # Protect against people hacking around with forms submissions and
130:     # attempting to create new timesheets for already-claimed weeks
131: 
132:     clash = Timesheet.find_by_user_id_and_year_and_week_number(
133:       @current_user.id,
134:       @timesheet.year,
135:       @timesheet.week_number
136:     )
137: 
138:     if ( clash )
139:       flash[ :error ] = "A timesheet for week #{ @timesheet.week_number } has already been created."
140:     elsif ( @timesheet.save )
141:       flash[ :notice ] = 'New timesheet created and ready for editing.'
142:       redirect_to( edit_timesheet_path( @timesheet ) )
143:       return
144:     end
145: 
146:     render( :action => 'new' )
147:   end

Timesheets should not normally be destroyed. Only administrators can do this.

[Source]

     # File app/controllers/timesheets_controller.rb, line 241
241:   def delete
242:     appctrl_delete( 'Timesheet' )
243:   end

[Source]

     # File app/controllers/timesheets_controller.rb, line 245
245:   def delete_confirm
246:     appctrl_delete_confirm( 'Timesheet' )
247:   end

Prepare to edit a timesheet. Any defaults are established by the models automatically. Rows and work packets are included in the editing form.

[Source]

     # File app/controllers/timesheets_controller.rb, line 153
153:   def edit
154:     @timesheet = Timesheet.find( params[ :id ] )
155:     return appctrl_not_permitted() unless @timesheet.can_be_modified_by?( @current_user )
156: 
157:     set_next_prev_week_variables( @timesheet )
158:   end

List timesheets.

[Source]

    # File app/controllers/timesheets_controller.rb, line 24
24:   def index
25: 
26:     # Set up the column data; see the index helper functions in
27:     # application_helper.rb for details.
28: 
29:     @columns = [
30:       { :header_text  => 'Year',        :value_method => 'year',
31:         :header_align => 'center',      :value_align  => 'center'                                                       },
32:       { :header_text  => 'Week',        :value_method => 'week_number',
33:         :header_align => 'center',      :value_align  => 'center'                                                       },
34:       { :header_text  => 'Start day',   :value_method => 'start_day',                 :sort_by => 'year, week_number'   },
35:       { :header_text  => 'Owner',       :value_helper => :timesheethelp_owner,        :sort_by => 'users.name'          },
36:       { :header_text  => 'Last edited', :value_helper => :timesheethelp_updated_at,   :sort_by => 'updated_at'          },
37:       { :header_text  => 'Committed',   :value_helper => :timesheethelp_committed_at, :sort_by => 'committed_at'        },
38:       { :header_text  => 'Hours',       :value_helper => :timesheethelp_hours,
39:         :header_align => 'center',      :value_align  => 'center'                                                       },
40:     ]
41: 
42:     # Get the basic options hash from ApplicationController, then work out
43:     # the conditions on objects being fetched, including handling the search
44:     # form data.
45: 
46:     options              = appctrl_index_assist( Timesheet )
47:     committed_vars       = { :committed => true,  :user_id => @current_user.id }
48:     not_committed_vars   = { :committed => false, :user_id => @current_user.id }
49:     user_conditions_sql  = "WHERE ( timesheets.committed = :committed ) AND ( users.id  = :user_id )\n"
50:     other_conditions_sql = "WHERE ( timesheets.committed = :committed ) AND ( users.id != :user_id )\n"
51: 
52:     # If asked to search for something, build extra conditions to do so.
53: 
54:     unless ( params[ :search ].nil? )
55:       if ( params[ :search ].empty? or params[ :search_cancel ] )
56:         params.delete( :search )
57:       else
58:         search_num     = params[ :search ].to_i
59:         search_str     = "%#{ params[ :search ] }%" # SQL wildcards either side of the search string
60:         conditions_sql = "AND ( timesheets.year = :search_num OR timesheets.week_number = :search_num OR users.name ILIKE :search_str )"
61:         vars           = { :search_num => search_num, :search_str => search_str }
62: 
63:         user_conditions_sql  << conditions_sql
64:         other_conditions_sql << conditions_sql
65: 
66:         committed_vars.merge!( vars )
67:         not_committed_vars.merge!( vars )
68:       end
69:     end
70: 
71:     # Sort order is already partially compiled in 'options' from the earlier
72:     # call to 'appctrl_index_assist'.
73: 
74:     order_sql = "ORDER BY #{ options[ :order ] }"
75:     options.delete( :order )
76: 
77:     # Compile the main SQL statement. Select all columns of the project, fetching
78:     # customers where the project's customer ID matches those customer IDs, with
79:     # only projects containing tasks in the user's permitted task list (if any)
80:     # are included, returned in the required order.
81:     #
82:     # Due to restrictions in the way that DISTINCT works, I just cannot figure out
83:     # ANY way in SQL to only return unique projects while still matching the task
84:     # permitted ID requirement for restricted users. So, fetch duplicates, then
85:     # strip them out in Ruby afterwards (ouch).
86: 
87:     basic_sql = "SELECT timesheets.* FROM timesheets\n" <<
88:                 "INNER JOIN users ON ( timesheets.user_id = users.id )"
89: 
90:     user_finder_sql  = "#{ basic_sql }\n#{ user_conditions_sql  }\n#{ order_sql }"
91:     other_finder_sql = "#{ basic_sql }\n#{ other_conditions_sql }\n#{ order_sql }"
92: 
93:     # Now paginate using this SQL query.
94: 
95:     @user_committed_timesheets      = Timesheet.paginate_by_sql( [ user_finder_sql,  committed_vars     ], options )
96:     @user_not_committed_timesheets  = Timesheet.paginate_by_sql( [ user_finder_sql,  not_committed_vars ], options )
97:     @other_committed_timesheets     = Timesheet.paginate_by_sql( [ other_finder_sql, committed_vars     ], options )
98:     @other_not_committed_timesheets = Timesheet.paginate_by_sql( [ other_finder_sql, not_committed_vars ], options )
99:   end

Prepare for the ‘new timesheet’ view.

[Source]

     # File app/controllers/timesheets_controller.rb, line 103
103:   def new
104:     @years = Timesheet.allowed_range()
105: 
106:     @year  = params[ :menu ][ :year ].to_i if ( params[ :menu ] )
107:     @year  = @year || ( Time.new ).year
108: 
109:     @year -= 1 unless( params[ :previous ].nil? )
110:     @year += 1 unless( params[ :next     ].nil? )
111: 
112:     @year  = @years.first if ( @year < @years.first )
113:     @year  = @years.last  if ( @year > @years.last  )
114:   end

Show timesheet details.

[Source]

     # File app/controllers/timesheets_controller.rb, line 231
231:   def show
232:     @timesheet = Timesheet.find( params[ :id ] )
233:     return appctrl_not_permitted() unless ( @timesheet and ( @current_user.privileged? or @timesheet.user_id == @current_user.id ) )
234: 
235:     set_next_prev_week_variables_for_show( @timesheet )
236:   end

Update a timesheet, its rows and work packets.

[Source]

     # File app/controllers/timesheets_controller.rb, line 162
162:   def update
163: 
164:     @timesheet = Timesheet.find( params[ :id ] )
165:     return appctrl_not_permitted() unless @timesheet.can_be_modified_by?( @current_user )
166: 
167:     @errors = update_backend( @timesheet )
168: 
169:     if ( @errors.nil? )
170:       flash[ :error ] = 'This timesheet was modified by someone else while you were making changes. Please examine the updated information before editing again.'
171:       redirect_to( timesheet_path( @timesheet ) )
172:       return
173:     end
174: 
175:     @timesheet.reload()
176: 
177:     if ( @errors.empty? )
178:       flash[ :notice ] = "Week #{ @timesheet.week_number } changes saved."
179:     else
180:       render( :action => :edit )
181:       return
182:     end
183: 
184:     set_next_prev_week_variables( @timesheet )
185: 
186:     # Save and edit next or previous editable week, creating a clone
187:     # timesheet for a previously unused week if need be?
188: 
189:     if ( params[ :next ] or params[ :previous ] )
190:       another = params[ :next ] ? @next_week : @prev_week
191: 
192:       if ( another.nil? )
193:         flash[ :error ] = "Cannot find another week to edit in #{ @timesheet.year }."
194:         redirect_to( new_timesheet_path() )
195:         return
196:       end
197: 
198:       new_week      = another[ :week_number ]
199:       new_timesheet = another[ :timesheet   ]
200: 
201:       if ( new_timesheet.nil? )
202:         new_timesheet           = clone_timesheet( @timesheet, new_week )
203:         new_timesheet.committed = false
204: 
205:         if ( new_timesheet.nil? )
206:           flash[ :error ] = "Unable to create a new timesheet for week #{ new_week }."
207:         else
208:           flash[ :notice ] << " Now editing a new timesheet for week #{ new_week }."
209:         end
210:       else
211:         flash[ :notice ] << " Now editing the timesheet for week #{ new_week }."
212:       end
213: 
214:       if ( new_timesheet.nil? )
215:         redirect_to( new_timesheet_path() )
216:       else
217:         redirect_to( edit_timesheet_path( new_timesheet ) )
218:       end
219: 
220:     elsif ( @timesheet.committed || params[ :commit ] == 'Save changes and exit' )
221:       redirect_to( new_timesheet_path() )
222: 
223:     else
224:       render( :action => :edit )
225: 
226:     end
227:   end

[Validate]