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
@@ -0,0 +1,8 @@
1
+ <h1>New absence</h1>
2
+
3
+ <% form_tag :action => 'create' do %>
4
+ <%= render :partial => 'form' %>
5
+ <%= submit_tag "Create" %>
6
+ <% end %>
7
+
8
+ <%= link_to 'Back', :action => 'list' %>
@@ -0,0 +1,8 @@
1
+ <% for column in Absence.content_columns %>
2
+ <p>
3
+ <b><%= column.human_name %>:</b> <%=h @absence.send(column.name) %>
4
+ </p>
5
+ <% end %>
6
+
7
+ <%= link_to 'Edit', :action => 'edit', :id => @absence %> |
8
+ <%= link_to 'Back', :action => 'list' %>
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
+ <head>
6
+ <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
7
+ <title>Absences: <%= controller.action_name %></title>
8
+ <%= stylesheet_link_tag 'scaffold' %>
9
+ </head>
10
+ <body>
11
+
12
+ <p style="color: green"><%= flash[:notice] %></p>
13
+
14
+ <%= yield %>
15
+
16
+ </body>
17
+ </html>
@@ -31,7 +31,7 @@
31
31
  <% if @task.work_started? -%>
32
32
  <% remote_form_for(:work, :url => {:controller => 'works', :action => 'update_time', :id => @task.started_work}) do |f| %>
33
33
  <%=submit_tag('checkmark', :value => l(:save), :style => 'display: none')%>
34
- <%=f.text_field 'started_at_time', :id => "work_#{@task.started_work.id}_started_at_time", :tabindex => i+1, :value => @task.started_work.started_at.strftime('%H:%M'),
34
+ <%=f.text_field 'start_time', :id => "work_#{@task.started_work.id}_start_time", :tabindex => i+1, :value => @task.started_work.start_time.strftime('%H:%M'),
35
35
  :class => :task_time, :maxlength => 5 %>
36
36
  <% end %>
37
37
  <% elsif @task.track_times? && (@task.period_id.nil? || @task.period.active?) %>
@@ -31,7 +31,7 @@
31
31
  <% if @task.work_started? -%>
32
32
  <% remote_form_for(:work, :url => {:controller => 'works', :action => 'update_time', :id => @task.started_work}) do |f| %>
33
33
  <%=submit_tag('checkmark', :value => l(:save), :style => 'display: none')%>
34
- <%=l :started_at%> <%=f.text_field 'started_at_time', :id => "work_#{@task.started_work.id}_started_at_time", :value => @task.started_work.started_at.strftime('%H:%M'),
34
+ <%=l :started_at%> <%=f.text_field 'start_time', :id => "work_#{@task.started_work.id}_start_time", :value => @task.started_work.started_at.strftime('%H:%M'),
35
35
  :class => :task_time, :maxlength => 5 %>
36
36
  <% end %>
37
37
  <% elsif @task.track_times? && (@task.period_id.nil? || @task.period.active?) %>
@@ -52,7 +52,7 @@
52
52
 
53
53
  <div id="lfeature">
54
54
  <div class="btitle">
55
- <h4><%=l :subscriptions %></h4>
55
+ <h4><%=l :work_lock_subscriptions %></h4>
56
56
  </div>
57
57
 
58
58
  <% if @user == current_user %>
@@ -79,3 +79,38 @@
79
79
  <%=image_link_to_remote "email#{'_grey' unless monitoring}.png", "#{l(monitoring ? :stop : :start)} #{l(:monitoring)}", {:action => :toggle_work_lock_monitoring, :id => @user.id}, {:id => "work_lock_monitor_icon_#{current_user.id}", :style => 'float: right'} %>
80
80
  <% end %>
81
81
  </div>
82
+
83
+ <div id="lfeature">
84
+ <div class="btitle">
85
+ <h4><%=l :holidays_used %></h4>
86
+ </div>
87
+
88
+ <table align="right">
89
+ <tr>
90
+ <th>Date</th>
91
+ </tr>
92
+ <% for date in @holidays %>
93
+ <tr>
94
+ <td align="center"><%=date%></td>
95
+ </tr>
96
+ <% end %>
97
+ </table>
98
+ </div>
99
+
100
+ <div id="lfeature">
101
+ <div class="btitle">
102
+ <h4><%=l :sick_days_used %></h4>
103
+ </div>
104
+
105
+ <table align="right">
106
+ <tr>
107
+ <th>Date</th>
108
+ </tr>
109
+ <% for date in @sick_days %>
110
+ <tr>
111
+ <td align="center"><%=date%></td>
112
+ </tr>
113
+ <% end %>
114
+ </table>
115
+ </div>
116
+
@@ -1,7 +1,7 @@
1
1
  <tr id="work_<%=@work.id%>" style="border: 1px solid black">
2
2
  <td>
3
3
  <% remote_form_for :work, :url => {:action => :update_row, :id => @work.id, :next_field => :customer_name}, :html => {:id => "work_#{@work.id}_form"} do |f|%>
4
- <%=f.select :work_account_id, @work_accounts.map {|wa| [wa.name, wa.id]}, {}, :onchange => "new Ajax.Request('/works/update_row/#{@work.id}?next_field=customer_name', {asynchronous:true, evalScripts:true, parameters:Form.serialize(form)})"%>
4
+ <%=f.select :work_account_id, @work_accounts.map {|wa| [wa.name, wa.id]}, {}, :onchange => "form.submit()"%>
5
5
  <% end %>
6
6
  </td>
7
7
  <td>
@@ -10,17 +10,31 @@
10
10
  <% end %>
11
11
  </td>
12
12
  <td>
13
- <%=render :partial => 'row_field', :locals => {:field => 'description', :next_field => 'started_at_time'} %>
13
+ <%=render :partial => 'row_field', :locals => {:field => 'description',
14
+ :next_field => 'start_time', :next_row_id => next_row_id, :previous_row_id => previous_row_id} %>
14
15
  </span>
15
16
  <td align="right">
16
- <%=render :partial => 'row_field', :locals => {:field => 'started_at_time', :next_field => 'completed_at_time'} %>
17
+ <%=render :partial => 'row_field', :locals => {:field => 'start_time',
18
+ :next_field => 'completed_at_time', :next_row_id => next_row_id, :previous_row_id => previous_row_id} %>
17
19
  </td>
18
20
  <td align="left">
19
- <%=render :partial => 'row_field', :locals => {:field => 'completed_at_time', :next_field => 'hours_time'} %>
21
+ <%=render :partial => 'row_field', :locals => {:field => 'completed_at_time',
22
+ :next_field => 'hours_time', :next_row_id => next_row_id, :previous_row_id => previous_row_id} %>
20
23
  </td>
21
24
  <td align="right">
22
25
  <% remote_form_for :work, :url => {:action => :update_row, :id => @work.id, :next_field => :invoice} do |f|%>
23
- <%=f.text_field :hours_time, :value => (@work.hours && @work.hours > 0 ? t(@work.hours) : ''), :id => "work_#{@work.id}_hours_time", :class => 'task_hours', :onchange => "new Ajax.Request('/works/update_row/#{@work.id}?next_field=invoice', {asynchronous:true, evalScripts:true, parameters:Form.serialize(form)})"%>
26
+ <%=f.text_field :hours_time, :value => (@work.hours && @work.hours > 0 ? t(@work.hours) : ''), :id => "work_#{@work.id}_hours_time", :class => 'task_hours',
27
+ :onkeypress => "
28
+ if(event.keyCode == 40) {
29
+ e = $('work#{"_#{next_row_id}" if next_row_id}_hours_time');
30
+ e.focus();
31
+ e.select();
32
+ } else if(event.keyCode == 38) {
33
+ e = $('work#{"_#{previous_row_id}" if previous_row_id}_hours_time');
34
+ e.focus();
35
+ e.select();
36
+ }",
37
+ :onchange => "new Ajax.Request('/works/update_row/#{@work.id}?next_field=invoice', {asynchronous:true, evalScripts:true, parameters:Form.serialize(form)})"%>
24
38
  <% end %>
25
39
  </td>
26
40
  <td style="text-align: left">
@@ -1,6 +1,17 @@
1
- <% remote_form_for :work, :url => {:action => :update_row, :id => @work.id, :next_field => next_field} do |f|%>
1
+ <% remote_form_for :work, :url => {:action => :update_row, :id => @work.id, :field=>field, :next_field => next_field} do |f|%>
2
2
  <%=text_field :work, field, :id => "work_#{@work.id}_#{field}",
3
- :class => ('task_time' if field=~/_at_time$/),
4
- :onchange => "new Ajax.Request('/works/update_row/#{@work.id}?next_field=#{next_field}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(form)});"
3
+ :class => ('task_time' if field=~/_time$/),
4
+ :onchange => "new Ajax.Request('/works/update_row/#{@work.id}?field=#{field}&next_field=#{next_field}', {asynchronous:true, evalScripts:true, parameters:Form.serialize(form)});",
5
+ :onkeypress => "
6
+ if(event.keyCode == 40) {
7
+ e = $('work#{"_#{next_row_id}" if next_row_id}_#{field}');
8
+ e.focus();
9
+ e.select();
10
+ } else if(event.keyCode == 38) {
11
+ e = $('work#{"_#{previous_row_id}" if previous_row_id}_#{field}');
12
+ e.focus();
13
+ e.select();
14
+ }",
15
+ :value => (field=~/_time$/ ? @work.send(field) && @work.send(field).strftime('%H:%M') : @work.send(field) )
5
16
  %>
6
17
  <% end %>
@@ -4,18 +4,26 @@
4
4
 
5
5
  <div style="float: left"><%=image_link_to('arrow_left.png', l(:previous_week), {:id => @date - 7}, :class => nil)%></div>
6
6
  <div style="float: left"><%=image_link_to('arrow_left.png', l(:previous_day), {:id => @date-1}, :class => nil)%></div>
7
+ <%=link_to l(:weekly_work_sheet), :action => :weekly_work_sheet_by_work_account%>
7
8
  <div style="float: right"><%=image_link_to('arrow_right.png', l(:next_week), {:id => @date + 7}, :class => nil)%></div>
8
9
  <div style="float: right"><%=image_link_to('arrow_right.png', l(:next_day), {:id => @date+1}, :class => nil)%></div>
9
10
 
10
11
  <br clear="all" />
11
12
 
13
+ <div id="absence">
14
+ <% form_for :absence, :html => {:id => :absence_form}, :url => with_detour({:controller => 'absences', :action => :create}) do |f| %>
15
+ <%=f.hidden_field :on, :value => @date %>
16
+ <%=f.radio_button :reason, '', :disabled => !@works.empty?, :onchange => 'form.submit()' %><label for="absence_reason_">Work day</label>
17
+ <%=f.radio_button :reason, 'HOLIDAY', :disabled => !@works.empty?, :onchange => 'form.submit()' %><label for="absence_reason_holiday">Holiday</label>
18
+ <%=f.radio_button :reason, 'SICK', :disabled => !@works.empty?, :onchange => 'form.submit()' %><label for="absence_reason_sick">Sick day</label>
19
+ <% end %>
20
+ </div>
21
+
22
+ <br clear="all" />
23
+
12
24
  <table sstyle="width: 100%" border="0">
13
- <tr>
14
- <th align="right" colspan="5">
15
- <%=link_to l(:weekly_work_sheet), :action => :weekly_work_sheet_by_work_account%>
16
- </th>
17
- </tr>
18
25
 
26
+ <% if @absence.nil? || @works.size > 0 %>
19
27
  <tr>
20
28
  <th><%=l :account %></th>
21
29
  <th><%=l :customer %></th>
@@ -26,13 +34,17 @@
26
34
  <th><%=l :invoice %></th>
27
35
  <th/>
28
36
  </tr>
37
+ <% end %>
29
38
 
30
39
  <% day_total = 0 %>
31
- <% for @work in @works %>
40
+ <% @works.each_with_index do |@work, i| %>
32
41
  <% day_total += @work.hours if @work %>
33
- <%=render :partial => 'row'%>
42
+ <%=render :partial => 'row', :locals => {:next_row_id => @works[i+1] && @works[i+1].id,
43
+ :previous_row_id => @works[i-1] && @works[i-1].id} %>
34
44
  <% end %>
35
45
  <% last_work = @work %>
46
+
47
+ <% unless @absence %>
36
48
  <% @work = nil %>
37
49
 
38
50
  <% form_tag with_detour(:controller => 'works', :action => 'create') do %>
@@ -47,19 +59,74 @@
47
59
  <%=text_field_with_auto_complete :work, :customer_name, {:value => '', :size => 16, :class => :task_description} %>
48
60
  </td>
49
61
  <td valign="bottom">
50
- <%=text_field_with_auto_complete :work, :description, {:class => :task_description} %>
62
+ <%=text_field_with_auto_complete :work, :description, :class => :task_description,
63
+ :onkeypress => "
64
+ if(event.keyCode == 38) {
65
+ e = $('work#{"_#{last_work.id}" if last_work}_description');
66
+ e.focus();
67
+ e.select();
68
+ } else if(event.keyCode == 13) {
69
+ e = $('work_work_account_name');
70
+ if(e.value == '') {
71
+ e.focus();
72
+ e.select();
73
+ return false;
74
+ }
75
+ }"
76
+ %>
51
77
  </td>
52
78
  <td align="right" valign="bottom">
53
- <%=text_field :work, :started_at_time, :value => last_work && last_work.completed_at && last_work.completed_at.strftime('%H:%M'), :class => 'task_time' %>
79
+ <%=text_field :work, :start_time, :value => last_work && last_work.completed_at && last_work.completed_at.strftime('%H:%M'), :class => 'task_time',
80
+ :onkeypress => "
81
+ if(event.keyCode == 38) {
82
+ e = $('work#{"_#{last_work.id}" if last_work}_start_time');
83
+ e.focus();
84
+ e.select();
85
+ } else if(event.keyCode == 13) {
86
+ e = $('work_work_account_name');
87
+ if(e.value == '') {
88
+ e.focus();
89
+ e.select();
90
+ return false;
91
+ }
92
+ }"
93
+ %>
54
94
  </td>
55
95
  <td align="left" valign="bottom">
56
- <%=text_field :work, :completed_at_time, :class => 'task_time',
96
+ <%=text_field :work, :completed_at_time, :class => 'task_time',
97
+ :onkeypress => "
98
+ if(event.keyCode == 38) {
99
+ e = $('work#{"_#{last_work.id}" if last_work}_completed_at_time');
100
+ e.focus();
101
+ e.select();
102
+ } else if(event.keyCode == 13) {
103
+ e = $('work_work_account_name');
104
+ if(e.value == '') {
105
+ e.focus();
106
+ e.select();
107
+ return false;
108
+ }
109
+ }",
57
110
  :value => @work && @work.completed_at.strftime('%H:%M'),
58
111
  :onchange => "update_hours(this.form);"
59
112
  %>
60
113
  </td>
61
114
  <td align="right" valign="bottom">
62
- <%=text_field :work, :hours_time, :value => '', :class => 'task_hours' %>
115
+ <%=text_field :work, :hours_time, :value => '', :class => 'task_hours',
116
+ :onkeypress => "
117
+ if(event.keyCode == 38) {
118
+ e = $('work#{"_#{last_work.id}" if last_work}_hours_time');
119
+ e.focus();
120
+ e.select();
121
+ } else if(event.keyCode == 13) {
122
+ e = $('work_work_account_name');
123
+ if(e.value == '') {
124
+ e.focus();
125
+ e.select();
126
+ return false;
127
+ }
128
+ }"
129
+ %>
63
130
  </td>
64
131
  <td align="left" valign="bottom">
65
132
  <%=check_box :work, :invoice %>
@@ -67,6 +134,8 @@
67
134
  <td valign="bottom">
68
135
  </td>
69
136
  </tr>
137
+ <% end %>
138
+
70
139
  <tr>
71
140
  <td/>
72
141
  <th><%=l :totals %></th>
@@ -101,7 +170,7 @@ function update_hours(form, id) {
101
170
  id_str = '_' + id;
102
171
  }
103
172
 
104
- var started_at = $('work' + id_str + '_started_at_time');
173
+ var started_at = $('work' + id_str + '_start_time');
105
174
  var completed_at = $('work' + id_str + '_completed_at_time');
106
175
  var hours_field = $('work' + id_str + '_hours_time');
107
176
 
@@ -69,7 +69,7 @@
69
69
  <Row>
70
70
  <Cell><Data ss:Type="String"><%=[work.task && work.task.description, work.description].compact.join('&#10;') %></Data></Cell>
71
71
  <Cell><Data ss:Type="String"><%=work.user && work.user.name %></Data></Cell>
72
- <Cell><Data ss:Type="Date"><%=work.started_at && work.started_at.strftime('%Y-%m-%d %H:%M:%S') %></Data></Cell>
72
+ <Cell><Data ss:Type="Date"><%=work.started_on.strftime('%Y-%m-%d') %><%=work.start_time && work.start_time.strftime(' %H:%M:%S') %></Data></Cell>
73
73
  <Cell><Data ss:Type="Date"><%=work.completed_at && work.completed_at.strftime('%Y-%m-%d %H:%M:%S') %></Data></Cell>
74
74
  <Cell><Data ss:Type="Number"><%=work.hours %> %></Data></Cell>
75
75
  </Row>
@@ -454,8 +454,8 @@
454
454
  <% invoice_works_per_day = @work_totals_per_work_account[work_account_id][0]%>
455
455
  <% if invoice_works_per_day.find{|total| total > 0} %>
456
456
  <Row>
457
- <Cell ss:StyleID="s24"><Data ss:Type="Number"><%=Backlog.find(work_account_id).invoice_code %></Data></Cell>
458
- <Cell ss:StyleID="s25"/>
457
+ <Cell ss:StyleID="s24"><Data ss:Type="String"><%=WorkAccount.find(work_account_id).invoice_code %></Data></Cell>
458
+ <Cell ss:StyleID="s25"><Data ss:Type="String"><%=WorkAccount.find(work_account_id).name %></Data></Cell>
459
459
  <Cell ss:StyleID="s25"><Data ss:Type="String"> X</Data></Cell>
460
460
  <Cell ss:StyleID="s25"/>
461
461
  <Cell ss:StyleID="s25"/>
@@ -472,7 +472,7 @@
472
472
  <% internal_works_per_day = @work_totals_per_work_account[work_account_id][1]%>
473
473
  <% if internal_works_per_day.find{|total| total > 0} %>
474
474
  <Row>
475
- <Cell ss:StyleID="s24"><Data ss:Type="String"><%=work_account_id%></Data></Cell>
475
+ <Cell ss:StyleID="s24"><Data ss:Type="String"><%=WorkAccount.find(work_account_id).invoice_code%></Data></Cell>
476
476
  <Cell ss:StyleID="s25"><Data ss:Type="String"><%=WorkAccount.find(work_account_id).name %></Data></Cell>
477
477
  <Cell ss:StyleID="s25"/>
478
478
  <Cell ss:StyleID="s25"/>
@@ -1,7 +1,9 @@
1
1
  page.replace "work_#{@work.id}", :partial => 'row', :object => @work
2
2
  page.replace "notice", :partial => '/layouts/notice'
3
3
  page.visual_effect(:highlight, "notice")
4
- page.replace_html "hours_total", "#{'%d:%02d' % [@day_total.to_i, 60 * (@day_total % 1)]}"
4
+ if @day_total
5
+ page.replace_html "hours_total", "#{'%d:%02d' % [@day_total.to_i, 60 * (@day_total % 1)]}"
6
+ end
5
7
  page["work_#{@work.id}_#{@next_field}"].select
6
8
  page["work_#{@work.id}_#{@next_field}"].focus
7
9
 
@@ -1,3 +1,3 @@
1
1
  display_notice(page)
2
- page["work_#{@work.id}_started_at_time"].value = @work.started_at.strftime('%H:%M')
3
- page.visual_effect(:highlight, "work_#{@work.id}_started_at_time")
2
+ page["work_#{@work.id}_start_time"].value = @work.start_time && @work.start_time.strftime('%H:%M')
3
+ page.visual_effect(:highlight, "work_#{@work.id}_start_time")
@@ -63,10 +63,10 @@
63
63
  <% if track_times %>
64
64
  <td align="left" valign="top">
65
65
  <% form_id = "work_#{@work.id}_time_form" %>
66
- <% field_id = "work_#{@work.id}_started_at_time" %>
66
+ <% field_id = "work_#{@work.id}_start_time" %>
67
67
  <form id="<%=form_id%>">
68
- <%=text_field(:work, :started_at_time, :class => :task_time, :disabled => @lock,
69
- :onchange => "new Ajax.Updater('#{field_id}', '#{url_for(:action => :update, :id => @work.id)}' + '?work[started_at_time]=' + this.value);") %> -
68
+ <%=text_field(:work, :start_time, :class => :task_time, :disabled => @lock,
69
+ :onchange => "new Ajax.Updater('#{field_id}', '#{url_for(:action => :update, :id => @work.id)}' + '?work[start_time]=' + this.value);") %> -
70
70
  <%=text_field(:work, :completed_at_time, :class => :task_time, :disabled => @lock,
71
71
  :onchange => "new Ajax.Updater('work_#{@work.id}_completed_at_time', '#{url_for(:action => :update, :id => @work.id)}' + '?work[completed_at_time]=' + this.value);") %>
72
72
  </form>
@@ -0,0 +1,34 @@
1
+ class CreateAbsences < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :absences do |t|
4
+ t.column :user_id, :integer, :null => false, :references => [:users, :party_id]
5
+ t.column :on, :date, :null => false
6
+ t.column :reason, :string, :null => false
7
+ end
8
+
9
+ add_column :works, :started_on, :date, :null => true
10
+ add_column :works, :start_time, :time, :null => true
11
+ Work.find(:all).each do |w|
12
+ w.started_on = (w.started_at || w.completed_at).to_date
13
+ w.start_time = w.started_at && w.started_at.time_of_day
14
+ w.save!
15
+ end
16
+ change_column_null :works, :started_on, :date, false
17
+ remove_column :works, :started_at
18
+ end
19
+
20
+ def self.down
21
+ add_column :works, :started_at, :timestamp
22
+ Work.find(:all).each do |w|
23
+ w.started_at = w.start_time && w.start_time.on(w.started_on)
24
+ w.save!
25
+ end
26
+ remove_column :works, :started_on
27
+ remove_column :works, :start_time
28
+ drop_table :absences
29
+ end
30
+
31
+ class Work < ActiveRecord::Base
32
+ end
33
+
34
+ end
data/db/schema.rb CHANGED
@@ -2,7 +2,13 @@
2
2
  # migrations feature of ActiveRecord to incrementally modify your database, and
3
3
  # then regenerate this schema definition.
4
4
 
5
- ActiveRecord::Schema.define(:version => 27) do
5
+ ActiveRecord::Schema.define(:version => 28) do
6
+
7
+ create_table "absences", :force => true do |t|
8
+ t.column "user_id", :integer, :null => false
9
+ t.column "on", :date, :null => false
10
+ t.column "reason", :string, :null => false
11
+ end
6
12
 
7
13
  create_table "backlogs", :force => true do |t|
8
14
  t.column "name", :string, :limit => 64, :null => false
@@ -127,16 +133,19 @@ ActiveRecord::Schema.define(:version => 27) do
127
133
  t.column "task_id", :integer
128
134
  t.column "hours", :decimal, :precision => 6, :scale => 2, :default => 0.0, :null => false
129
135
  t.column "completed_at", :datetime
130
- t.column "started_at", :datetime
131
136
  t.column "user_id", :integer
132
137
  t.column "invoice", :boolean
133
138
  t.column "work_account_id", :integer
134
139
  t.column "customer_id", :integer
135
140
  t.column "description", :string
141
+ t.column "started_on", :date, :null => false
142
+ t.column "start_time", :time
136
143
  end
137
144
 
138
145
  add_index "works", ["task_id", "completed_at"], :name => "index_works_on_task_id_and_completed_at"
139
146
 
147
+ add_foreign_key "absences", ["user_id"], "users", ["party_id"], :name => "absences_user_id_fkey"
148
+
140
149
  add_foreign_key "backlogs", ["customer_id"], "customers", ["id"], :name => "backlogs_customer_id_fkey"
141
150
  add_foreign_key "backlogs", ["work_account_id"], "work_accounts", ["id"], :name => "backlogs_work_account_id_fkey"
142
151