backlog 0.23.1 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. data/History.txt +17 -4
  2. data/app/controllers/absences_controller.rb +64 -0
  3. data/app/controllers/periods_controller.rb +1 -1
  4. data/app/controllers/tasks_controller.rb +6 -4
  5. data/app/controllers/user_controller.rb +7 -0
  6. data/app/controllers/works_controller.rb +21 -16
  7. data/app/helpers/absences_helper.rb +2 -0
  8. data/app/models/absence.rb +14 -0
  9. data/app/models/task.rb +3 -2
  10. data/app/models/work.rb +33 -21
  11. data/app/views/absences/_form.rhtml +10 -0
  12. data/app/views/absences/edit.rhtml +9 -0
  13. data/app/views/absences/list.rhtml +27 -0
  14. data/app/views/absences/new.rhtml +8 -0
  15. data/app/views/absences/show.rhtml +8 -0
  16. data/app/views/layouts/absences.rhtml +17 -0
  17. data/app/views/tasks/_task.rhtml +1 -1
  18. data/app/views/tasks/edit.rhtml +1 -1
  19. data/app/views/user/edit.rhtml +36 -1
  20. data/app/views/works/_row.rhtml +19 -5
  21. data/app/views/works/_row_field.rhtml +14 -3
  22. data/app/views/works/daily_work_sheet.rhtml +81 -12
  23. data/app/views/works/list_excel.rhtml +1 -1
  24. data/app/views/works/timeliste.rhtml +3 -3
  25. data/app/views/works/update_row.rjs +3 -1
  26. data/app/views/works/update_time.rjs +2 -2
  27. data/app/views/works/weekly_work_sheet.rhtml +3 -3
  28. data/db/migrate/028_create_absences.rb +34 -0
  29. data/db/schema.rb +11 -2
  30. data/lang/en.yaml +4 -0
  31. data/lang/no.yaml +4 -0
  32. data/lib/change_column_null_migration_fix.rb +2 -0
  33. data/test/fixtures/absences.yml +11 -0
  34. data/test/fixtures/works.yml +10 -5
  35. data/test/functional/absences_controller_test.rb +93 -0
  36. data/test/functional/tasks_controller_test.rb +3 -2
  37. data/test/functional/works_controller_test.rb +33 -6
  38. data/test/test_helper.rb +3 -2
  39. data/test/unit/absence_test.rb +31 -0
  40. data/test/unit/work_test.rb +7 -0
  41. data/vendor/plugins/rails_time/MIT-LICENSE +20 -0
  42. data/vendor/plugins/rails_time/README +28 -0
  43. data/vendor/plugins/rails_time/init.rb +2 -0
  44. data/vendor/plugins/rails_time/lib/activerecord_time_extension.rb +28 -0
  45. data/vendor/plugins/rails_time/lib/time_of_day.rb +81 -0
  46. data/vendor/plugins/rails_time/test/database.yml +18 -0
  47. data/vendor/plugins/rails_time/test/rails_time_test.rb +122 -0
  48. data/vendor/plugins/rails_time/test/schema.rb +10 -0
  49. data/vendor/plugins/rails_time/test/test_helper.rb +17 -0
  50. metadata +28 -3
  51. data/app/views/works/daily_work_sheet_old.rhtml +0 -93
data/lang/en.yaml CHANGED
@@ -40,6 +40,7 @@ friday: Friday
40
40
  grab_task: Grab task
41
41
  group: Group
42
42
  groups: Groups
43
+ holidays_used: Holidays used
43
44
  home: Home
44
45
  hours: Hours
45
46
  invite: Invite
@@ -72,6 +73,7 @@ no_pending_tasks: There are no pending tasks in this sprint.
72
73
  no_pending_tasks_in_backlog: There are no pending tasks in this backlog.
73
74
  not_grabbed: Not grabbed by anyone
74
75
  notes: Notes
76
+ ownership: Ownership
75
77
  paging: Paging
76
78
  password: Password
77
79
  period: Sprint
@@ -93,6 +95,7 @@ search: Search
93
95
  search_results_for: "Search results for '%s'"
94
96
  select: Select
95
97
  shortcuts: Shortcuts
98
+ sick_days_used: Sick days
96
99
  signup: Sign Up
97
100
  specify: Specify
98
101
  spreadsheet: Spreadsheet
@@ -102,6 +105,7 @@ start_work: Start
102
105
  started_at: Started at
103
106
  started_tasks: Started tasks
104
107
  stop: Stop
108
+ work_lock_subscriptions: Work Lock Subscriptions
105
109
  sunday: Sunday
106
110
  task: Task
107
111
  tasks: Tasks
data/lang/no.yaml CHANGED
@@ -40,6 +40,7 @@ friday: Fredag
40
40
  grab_task: Grip oppgave
41
41
  group: Gruppe
42
42
  groups: Grupper
43
+ holidays_used: Brukte feriedager
43
44
  home: Hjem
44
45
  hours: Timer
45
46
  invite: Invitèr
@@ -72,6 +73,7 @@ no_pending_tasks: Det er ingen ventende oppgaver i denne perioden.
72
73
  no_pending_tasks_in_backlog: Det er ingen ventende oppgaver i denne oppgavelisten.
73
74
  not_grabbed: Ikke tatt av noen
74
75
  notes: Notater
76
+ ownership: Eierskap
75
77
  paging: Del opp i flere sider
76
78
  password: Passord
77
79
  period: Periode
@@ -93,6 +95,7 @@ search: Søk
93
95
  search_results_for: "Søkeresultater for '%s'"
94
96
  select: Velg
95
97
  shortcuts: Knapper
98
+ sick_days_used: Sykedager
96
99
  signup: Innmelding
97
100
  specify: Spesifisèr
98
101
  spreadsheet: Regneark
@@ -101,6 +104,7 @@ start_on: Start på
101
104
  start_work: Start arbeid
102
105
  started_at: Start tid
103
106
  stop: Stopp
107
+ work_lock_subscriptions: Abonenter på timelister
104
108
  sunday: Søndag
105
109
  task: Oppgave
106
110
  tasks: Oppgaver
@@ -7,6 +7,8 @@ class ActiveRecord::Migration
7
7
  execute("ALTER TABLE #{table_name} ALTER #{column_name} #{null ? 'DROP' : 'SET'} NOT NULL")
8
8
  elsif ActiveRecord::Base.connection.adapter_name.downcase == "mysql"
9
9
  execute("ALTER TABLE #{table_name} MODIFY COLUMN #{column_name} #{column_type} #{null ? 'NULL' : 'NOT NULL'}")
10
+ else
11
+ raise "'change_column_null' is not supported for connection adapter #{ActiveRecord::Base.connection.adapter_name}."
10
12
  end
11
13
  end
12
14
 
@@ -0,0 +1,11 @@
1
+ # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2
+ one:
3
+ id: 1
4
+ user_id: 1000001
5
+ "on": 2007-06-10
6
+ reason: HOLIDAY
7
+ two:
8
+ id: 2
9
+ user_id: 1000001
10
+ "on": 2007-06-11
11
+ reason: SICK
@@ -2,19 +2,22 @@
2
2
  first:
3
3
  id: 1
4
4
  task_id: 1
5
- started_at: 2007-06-12T13:35:00
5
+ started_on: 2007-06-12
6
+ start_time: !time 13:35:00
6
7
  completed_at: 2007-06-12T14:35:00
7
8
  hours: 30.0
8
9
  work_account_id: 1
9
10
  started:
10
11
  id: 2
11
12
  task_id: 4
12
- started_at: 2007-06-12T13:35:00
13
+ started_on: 2007-06-12
14
+ start_time: !time 13:35:00
13
15
  work_account_id: 1
14
16
  personal:
15
17
  id: 3
16
18
  task_id: 1
17
- started_at: 2007-06-12T13:35:00
19
+ started_on: 2007-06-12
20
+ start_time: !time 13:35:00
18
21
  completed_at: 2007-06-12T14:35:00
19
22
  user_id: 1000001
20
23
  hours: 40.0
@@ -22,13 +25,15 @@ personal:
22
25
  brother_of_started:
23
26
  id: 5
24
27
  task_id: 4
25
- started_at: 2007-06-12T13:35:00
28
+ started_on: 2007-06-12
29
+ start_time: !time 13:35:00
26
30
  completed_at: 2007-06-12T14:35:00
27
31
  work_account_id: 1
28
32
  without_task:
29
33
  id: 6
30
34
  work_account_id: 1
31
- started_at: 2007-06-13T13:35:00
35
+ started_on: 2007-06-13
36
+ start_time: !time 13:35:00
32
37
  completed_at: 2007-06-13T14:35:00
33
38
  hours: 8.0
34
39
  user_id: 1000001
@@ -0,0 +1,93 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ require 'absences_controller'
3
+
4
+ # Re-raise errors caught by the controller.
5
+ class AbsencesController; def rescue_action(e) raise e end; end
6
+
7
+ class AbsencesControllerTest < Test::Unit::TestCase
8
+ fixtures :absences
9
+
10
+ def setup
11
+ @controller = AbsencesController.new
12
+ @request = ActionController::TestRequest.new
13
+ @response = ActionController::TestResponse.new
14
+ @request.session[:user_id] = 1000001
15
+
16
+ @first_id = absences(:one).id
17
+ end
18
+
19
+ def test_index
20
+ get :index
21
+ assert_response :success
22
+ assert_template 'list'
23
+ end
24
+
25
+ def test_list
26
+ get :list
27
+
28
+ assert_response :success
29
+ assert_template 'list'
30
+
31
+ assert_not_nil assigns(:absences)
32
+ end
33
+
34
+ def test_show
35
+ get :show, :id => @first_id
36
+
37
+ assert_response :success
38
+ assert_template 'show'
39
+
40
+ assert_not_nil assigns(:absence)
41
+ assert assigns(:absence).valid?
42
+ end
43
+
44
+ def test_new
45
+ get :new
46
+
47
+ assert_response :success
48
+ assert_template 'new'
49
+
50
+ assert_not_nil assigns(:absence)
51
+ end
52
+
53
+ def test_create
54
+ num_absences = Absence.count
55
+
56
+ post :create, :absence => {:on => '2007-06-09', :reason => 'HOLIDAY'}
57
+
58
+ assert_response :redirect
59
+ assert_redirected_to :action => 'list'
60
+
61
+ assert_equal num_absences + 1, Absence.count
62
+ end
63
+
64
+ def test_edit
65
+ get :edit, :id => @first_id
66
+
67
+ assert_response :success
68
+ assert_template 'edit'
69
+
70
+ assert_not_nil assigns(:absence)
71
+ assert assigns(:absence).valid?
72
+ end
73
+
74
+ def test_update
75
+ post :update, :id => @first_id
76
+ assert_response :redirect
77
+ assert_redirected_to :action => 'show', :id => @first_id
78
+ end
79
+
80
+ def test_destroy
81
+ assert_nothing_raised {
82
+ Absence.find(@first_id)
83
+ }
84
+
85
+ post :destroy, :id => @first_id
86
+ assert_response :redirect
87
+ assert_redirected_to :action => 'list'
88
+
89
+ assert_raise(ActiveRecord::RecordNotFound) {
90
+ Absence.find(@first_id)
91
+ }
92
+ end
93
+ end
@@ -177,13 +177,14 @@ class TasksControllerTest < Test::Unit::TestCase
177
177
  before = Task.find(1)
178
178
  assert_equal 70, before.total_done
179
179
 
180
- post :end_work, :id => 1, :work => {:work_started_at_time => (Time.now - 3600).strftime('%H:%M')}
180
+ post :end_work, :id => 1, :work => {:work_start_time => (TimeOfDay.now - 3600).to_s}
181
181
  assert_response :redirect
182
182
  assert_redirected_to :controller => 'works', :action => :new,
183
183
  'work[hours]' => "0.25",
184
184
  'work[task_id]' => 1,
185
+ 'work[started_on]' => Time.previous_quarter.to_date.to_s,
186
+ 'work[start_time]' => Time.previous_quarter.time_of_day.to_s,
185
187
  'work[completed_at]' => Time.next_quarter.iso8601,
186
- 'work[started_at]' => Time.previous_quarter.iso8601,
187
188
  'estimate[todo]' => 1
188
189
 
189
190
  after = Task.find(1)
@@ -8,6 +8,7 @@ class WorksControllerTest < Test::Unit::TestCase
8
8
  main_scenario
9
9
 
10
10
  def setup
11
+ #super
11
12
  @controller = WorksController.new
12
13
  @request = ActionController::TestRequest.new
13
14
  @response = ActionController::TestResponse.new
@@ -16,6 +17,7 @@ class WorksControllerTest < Test::Unit::TestCase
16
17
  end
17
18
 
18
19
  def teardown
20
+ super
19
21
  assert_sequences
20
22
  end
21
23
 
@@ -56,7 +58,18 @@ class WorksControllerTest < Test::Unit::TestCase
56
58
  def test_create
57
59
  num_works = Work.count
58
60
 
59
- post :create, :work => {:task_id => 1, :started_at => Time.now.iso8601, :work_account_id => '1'}
61
+ post :create, :work => {:task_id => 1, :started_on => Date.today.to_s, :start_time => Time.now.time_of_day.to_s, :work_account_id => '1'}
62
+
63
+ assert_response :redirect
64
+ assert_redirected_to :controller => 'periods', :action => 'show', :id => periods(:past).id, :task_id => 1
65
+
66
+ assert_equal num_works + 1, Work.count
67
+ end
68
+
69
+ def test_create_without_start_date
70
+ num_works = Work.count
71
+
72
+ post :create, :work => {:task_id => 1, :start_time => Time.now.time_of_day.to_s, :work_account_id => '1'}
60
73
 
61
74
  assert_response :redirect
62
75
  assert_redirected_to :controller => 'periods', :action => 'show', :id => periods(:past).id, :task_id => 1
@@ -76,17 +89,31 @@ class WorksControllerTest < Test::Unit::TestCase
76
89
 
77
90
  def test_update
78
91
  post :update, :id => 1
92
+ assert_not_nil assigns(:work)
93
+ assert_equal([], assigns(:work).errors.full_messages, assigns(:work).inspect)
79
94
  assert_response :redirect
80
95
  assert_redirected_to :controller => 'periods', :action => 'show', :id => periods(:past).id
81
96
  end
82
97
 
83
98
  def test_update_time
84
99
  before = works(:first)
85
- old_start_time = before.started_at
86
- expected_time = Time.local(old_start_time.year , old_start_time.month, old_start_time.day, 8, 15)
87
- post :update_time, :id => 1, :work => {"started_at_time"=>"8:15"}
100
+ old_start_date = before.started_on
101
+ expected_time = TimeOfDay.new(8, 15)
102
+ post :update_time, :id => 1, :work => {"start_time"=>"8:15"}
103
+ assert_response :success
104
+ assert_equal old_start_date, assigns(:work).started_on
105
+ assert_equal expected_time, assigns(:work).start_time
106
+ end
107
+
108
+ def test_update_row_with_empty_start_time
109
+ before = works(:first)
110
+ old_start_date = before.started_on
111
+
112
+ post :update_time, :id => 1, :work => {"start_time"=>""}
113
+
88
114
  assert_response :success
89
- assert_equal expected_time.iso8601, assigns(:work).started_at.iso8601
115
+ assert_equal old_start_date, assigns(:work).started_on
116
+ assert_equal nil, assigns(:work).start_time
90
117
  end
91
118
 
92
119
  def test_destroy
@@ -107,7 +134,7 @@ class WorksControllerTest < Test::Unit::TestCase
107
134
  task = tasks(:started)
108
135
  work = works(:started)
109
136
 
110
- post :update, "commit"=>"Lagre", "action"=>"update", "id"=>work.id.to_s, "controller"=>"works", "estimate"=>{"todo"=>"0"}, "work"=>{"completed_at"=>"2007-08-02 14:15", "task_id"=> task.id.to_s, "user_id"=>"1000001", "started_at"=>"2007-08-02 14:00"}
137
+ post :update, "commit"=>"Lagre", "action"=>"update", "id"=>work.id.to_s, "controller"=>"works", "estimate"=>{"todo"=>"0"}, "work"=>{"completed_at"=>"2007-08-02 14:15", "task_id"=> task.id.to_s, "user_id"=>"1000001", "started_on"=>"2007-08-02", "start_time"=>"14:00"}
111
138
 
112
139
  assert_response :redirect
113
140
  assert_redirected_to :controller => 'periods', :action => :show, :id => task.period, :task => nil
data/test/test_helper.rb CHANGED
@@ -5,7 +5,8 @@ require 'user_notify'
5
5
 
6
6
  class Test::Unit::TestCase
7
7
  def self.main_scenario
8
- fixtures :parties, :users, :groups, :groups_users, :work_accounts, :backlogs, :periods, :tasks, :task_files, :works, :estimates, :work_lock_subscriptions, :work_locks
8
+ fixtures :parties, :users, :groups, :groups_users, :work_accounts, :backlogs, :periods, :tasks,
9
+ :task_files, :works, :estimates, :work_lock_subscriptions, :work_locks, :absences
9
10
  end
10
11
 
11
12
  # Transactional fixtures accelerate your tests by wrapping each test method
@@ -60,7 +61,7 @@ class Test::Unit::TestCase
60
61
  def users(login)
61
62
  User.find_by_login(login.to_s)
62
63
  end
63
-
64
+
64
65
  def set_logged_in( user )
65
66
  @request.session[:user_id] = user.id
66
67
  end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class AbsenceTest < Test::Unit::TestCase
4
+ main_scenario
5
+
6
+ def teardown
7
+ Thread.current[:user] = nil
8
+ end
9
+
10
+ def test_illegal_to_mark_date_as_absent_if_there_is_registered_work_on_same_date
11
+ Thread.current[:user] = users(:tesla)
12
+ assert_raise ActiveRecord::RecordInvalid do
13
+ Absence.create!({:on => '2007-06-12', :user_id => 1000001, :reason => 'lazy'})
14
+ end
15
+ end
16
+
17
+ def test_create_with_anonymous_not_allowed
18
+ assert_raise ActiveRecord::RecordInvalid do
19
+ Absence.create!({:on => '2007-06-12', :user_id => nil, :reason => 'lazy'})
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ # TODO (uwe): This method should be removed
26
+ # It is here only because ClassTableInheritanceInRails broke reading fixtures by name
27
+ def users(login)
28
+ super(login)
29
+ end
30
+
31
+ end
@@ -61,6 +61,13 @@ class WorkTest < Test::Unit::TestCase
61
61
  assert_equal({work_accounts(:light_control) => [nil, BigDecimal('30'), nil, nil, nil, nil, nil]}, work_totals)
62
62
  end
63
63
 
64
+ def test_illegal_to_register_work_if_the_same_date_is_marked_as_absent
65
+ Thread.current[:user] = users(:tesla)
66
+ assert_raise ActiveRecord::RecordInvalid do
67
+ Work.create!({:started_on => '2007-06-10', :user_id => 1000001, :work_account => work_accounts(:light_control)})
68
+ end
69
+ end
70
+
64
71
  private
65
72
 
66
73
  # TODO (uwe): This method should be removed
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006 Jerrett Taylor
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+ = Rails Time
2
+
3
+ A handler for storing TimeOfDay objects in ActiveRecord objects as sql time values.
4
+
5
+
6
+ == Installation
7
+
8
+ ./script/plugin install svn://rubyforge.org/var/svn/backlog/vendor/plugins/rails_time
9
+
10
+
11
+ == Usage
12
+
13
+ Create your tables with fields with type :time and you will be able to access them as
14
+ TimeOfDay objects.
15
+
16
+ add_column :schedule, :start_time, :time
17
+
18
+ schedule = Schedule.find_first
19
+ schedule.start_time = TimeOfDay.parse('08:34')
20
+ schedule.price >> "08:34:00"
21
+
22
+
23
+ Creating a Money can be done from a Fixnum (dollars) or a Float (dollars.cents). To create a money
24
+ object from just cents, do Money.create_from_cents(100)
25
+
26
+ == Feedback
27
+
28
+ Any suggestions, fixes, or improvements - lemme know, jerrett at gmail
@@ -0,0 +1,2 @@
1
+ require 'time_of_day'
2
+ require 'activerecord_time_extension'
@@ -0,0 +1,28 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class Column
4
+ def klass_with_time_of_day
5
+ return TimeOfDay if :time === type
6
+ klass_without_time_of_day
7
+ end
8
+ alias_method_chain :klass, :time_of_day
9
+
10
+ def self.string_to_dummy_time(string)
11
+ return string if string.is_a? TimeOfDay
12
+ return nil if string.empty?
13
+ TimeOfDay.parse(string)
14
+ end
15
+ end
16
+ module Quoting
17
+ def quote_with_time_of_day(value, column = nil)
18
+ return "'#{quoted_time(value)}'" if TimeOfDay === value
19
+ quote_without_time_of_day(value, column)
20
+ end
21
+ alias_method_chain :quote, :time_of_day
22
+
23
+ def quoted_time(value)
24
+ value.to_s
25
+ end
26
+ end
27
+ end
28
+ end