backlog 0.18.0 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +19 -0
- data/app/controllers/periods_controller.rb +0 -14
- data/app/controllers/tasks_controller.rb +15 -4
- data/app/controllers/user_controller.rb +15 -1
- data/app/controllers/work_accounts_controller.rb +1 -1
- data/app/controllers/work_locks_controller.rb +88 -0
- data/app/controllers/works_controller.rb +29 -5
- data/app/helpers/work_locks_helper.rb +2 -0
- data/app/models/task.rb +1 -1
- data/app/models/user.rb +1 -0
- data/app/models/user_notify.rb +15 -0
- data/app/models/work.rb +28 -6
- data/app/models/work_account.rb +2 -0
- data/app/models/work_lock.rb +3 -0
- data/app/models/work_lock_notify.rb +27 -0
- data/app/models/work_lock_subscription.rb +3 -0
- data/app/views/display_notice.rjs +1 -0
- data/app/views/layouts/_left_top.rhtml +1 -0
- data/app/views/tasks/_task.rhtml +2 -2
- data/app/views/user/edit.rhtml +15 -2
- data/app/views/user/toggle_work_lock_monitoring.rjs +2 -0
- data/app/views/user_notify/monitoring_en.rhtml +3 -0
- data/app/views/user_notify/monitoring_no.rhtml +3 -0
- data/app/views/work_lock_notify/lock_en.rhtml +7 -0
- data/app/views/work_lock_notify/lock_no.rhtml +7 -0
- data/app/views/work_locks/_form.rhtml +10 -0
- data/app/views/work_locks/edit.rhtml +9 -0
- data/app/views/work_locks/list.rhtml +27 -0
- data/app/views/work_locks/new.rhtml +8 -0
- data/app/views/work_locks/show.rhtml +8 -0
- data/app/views/works/_buttons.rhtml +5 -0
- data/app/views/works/_form.rhtml +4 -1
- data/app/views/works/_row.rhtml +14 -17
- data/app/views/works/_row_field.rhtml +1 -1
- data/app/views/works/daily_work_sheet.rhtml +16 -25
- data/app/views/works/timeliste.rhtml +12 -12
- data/app/views/works/update_row.rjs +2 -4
- data/app/views/works/weekly_work_sheet.rhtml +17 -17
- data/app/views/works/weekly_work_sheet_by_work_account.rhtml +57 -0
- data/db/migrate/027_create_work_locks.rb +25 -0
- data/db/schema.rb +25 -1
- data/public/images/delete.png +0 -0
- data/public/images/email.png +0 -0
- data/public/images/email_grey.png +0 -0
- data/public/images/refresh.png +0 -0
- data/test/fixtures/work_lock_subscriptions.yml +7 -0
- data/test/fixtures/work_locks.yml +11 -0
- data/test/functional/estimates_controller_test.rb +1 -1
- data/test/functional/groups_controller_test.rb +1 -1
- data/test/functional/user_controller_test.rb +2 -2
- data/test/functional/work_locks_controller_test.rb +93 -0
- data/test/integration/user_system_test.rb +1 -1
- data/test/test_helper.rb +1 -1
- data/test/unit/estimate_test.rb +1 -1
- data/test/unit/group_test.rb +1 -1
- data/test/unit/period_test.rb +1 -1
- data/test/unit/task_test.rb +1 -1
- data/test/unit/user_test.rb +1 -1
- data/test/unit/work_account_test.rb +1 -1
- data/test/unit/work_lock_subscription_test.rb +10 -0
- data/test/unit/work_lock_test.rb +10 -0
- data/test/unit/work_test.rb +1 -1
- metadata +31 -2
data/app/views/works/_row.rhtml
CHANGED
@@ -1,19 +1,15 @@
|
|
1
|
-
<tr id="work_<%=@work.id%>">
|
1
|
+
<tr id="work_<%=@work.id%>" style="border: 1px solid black">
|
2
2
|
<td>
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
<% if @work.task %>
|
7
|
-
<%=link_to(@work.task.root_task.backlog.name, :controller => 'backlogs', :action => :show)%> /
|
8
|
-
<%=link_to(@work.task.description, :controller => 'tasks', :action => :edit)%>
|
9
|
-
<% end %>
|
10
|
-
</td>
|
11
|
-
<td>
|
12
|
-
<%=link_to(@work.work_account.name, :controller => 'work_accounts', :action => :show, :id => @work.work_account.id) if @work.work_account%>
|
3
|
+
<% remote_form_for :work, :url => {:action => :update_row, :id => @work.id, :field => :description}, :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}?field=description', {asynchronous:true, evalScripts:true, parameters:Form.serialize(form)})"%>
|
5
|
+
<% end %>
|
13
6
|
</td>
|
14
7
|
<td>
|
15
|
-
|
16
|
-
|
8
|
+
<!--
|
9
|
+
<%=text_field :work, :description, :id => "work_#{@work.id}_description", :size => 16, :class => :task_description%>
|
10
|
+
-->
|
11
|
+
<%=render :partial => 'row_field', :locals => {:field => 'description'} %>
|
12
|
+
</span>
|
17
13
|
<td align="right">
|
18
14
|
<%=render :partial => 'row_field', :locals => {:field => 'started_at_time'} %>
|
19
15
|
</td>
|
@@ -25,9 +21,10 @@
|
|
25
21
|
<%=f.text_field :hours_time, :value => t(@work.hours), :class => 'task_hours'%>
|
26
22
|
<% end %>
|
27
23
|
</td>
|
28
|
-
<td
|
29
|
-
|
30
|
-
|
31
|
-
|
24
|
+
<td>
|
25
|
+
<%=image_detour_to('delete.png', l(:delete), {:controller => 'works', :action => :destroy, :id => @work, :confirm => true}, nil, true)%>
|
26
|
+
<% if @work.task %>
|
27
|
+
<%=image_detour_to('task.png', "#{l :task}: #{@work.task.description}", {:controller => 'tasks', :action => :edit, :id => @work.task.id})%>
|
28
|
+
<% end %>
|
32
29
|
</td>
|
33
30
|
</tr>
|
@@ -1,3 +1,3 @@
|
|
1
1
|
<% remote_form_for :work, :url => {:action => :update_row, :id => @work.id, :field => field} do |f|%>
|
2
|
-
<%=text_field :work, field, :class => ('task_time' if field=~/_at_time$/) %>
|
2
|
+
<%=text_field :work, field, :id => "work_#{@work.id}_#{field}", :class => ('task_time' if field=~/_at_time$/) %>
|
3
3
|
<% end %>
|
@@ -2,17 +2,15 @@
|
|
2
2
|
|
3
3
|
<div id="spotlight">
|
4
4
|
|
5
|
-
<div style="float: left"><%=
|
6
|
-
<div style="float: left"><%=
|
7
|
-
<div style="float: right"><%=
|
8
|
-
<div style="float: right"><%=
|
5
|
+
<div style="float: left"><%=image_link_to('arrow_left.png', l(:previous_week), {:id => @date - 7}, :class => nil)%></div>
|
6
|
+
<div style="float: left"><%=image_link_to('arrow_left.png', l(:previous_day), {:id => @date-1}, :class => nil)%></div>
|
7
|
+
<div style="float: right"><%=image_link_to('arrow_right.png', l(:next_week), {:id => @date + 7}, :class => nil)%></div>
|
8
|
+
<div style="float: right"><%=image_link_to('arrow_right.png', l(:next_day), {:id => @date+1}, :class => nil)%></div>
|
9
9
|
|
10
10
|
<br clear="all" />
|
11
11
|
|
12
12
|
<table sstyle="width: 100%" border="0">
|
13
13
|
<tr>
|
14
|
-
<td/>
|
15
|
-
<th><%=l :backlog %> / <%=l :task %></th>
|
16
14
|
<th><%=l :account %></th>
|
17
15
|
<th><%=l :description %></th>
|
18
16
|
<th><%=l :started_at %></th>
|
@@ -26,24 +24,15 @@
|
|
26
24
|
<% day_total += @work.hours if @work %>
|
27
25
|
<%=render :partial => 'row'%>
|
28
26
|
<% end %>
|
27
|
+
<% last_work = @work %>
|
28
|
+
<% @work = nil %>
|
29
29
|
|
30
|
-
|
30
|
+
<% if last_work.completed_at %>
|
31
31
|
<% form_tag with_detour(:controller => 'works', :action => 'create') do %>
|
32
32
|
<%=submit_tag('checkmark', :value => l(:save), :style => 'display: none')%>
|
33
|
-
<%=hidden_field :work, :completed_at, :value =>
|
33
|
+
<%=hidden_field :work, :completed_at, :value => @date %>
|
34
34
|
|
35
35
|
<tr>
|
36
|
-
<td width="22"/>
|
37
|
-
<td>
|
38
|
-
<script type="text/javascript">
|
39
|
-
function set_backlog_for_task() {
|
40
|
-
work_task_description_auto_completer.url = '<%=url_for(:action => :auto_complete_for_work_task_description)%>?backlog_name=' + $('work_backlog_name').value;
|
41
|
-
}
|
42
|
-
|
43
|
-
</script>
|
44
|
-
<%=text_field_with_auto_complete :work, :backlog_name, {:value => '', :size => 16}, {:after_update_element => "function(element, value) {set_backlog_for_task()}"} %>
|
45
|
-
<%=text_field_with_auto_complete(:work, :task_description, {:value => '', :size => 16, :class => :task_description}, :url => url_for({:action => :auto_complete_for_work_task_description, :backlog_name => "' + $('work_backlog_name').value + '", :escape => false}), :after_update_element => "function(element,value) {if ($('work_backlog_name').value == '') { $('work_backlog_name').value = element.value.split(/: /)[0];element.value = element.value.split(/: /)[1]};set_backlog_for_task();return true; }") %>
|
46
|
-
</td>
|
47
36
|
<td valign="bottom">
|
48
37
|
<%=text_field_with_auto_complete :work, :work_account_name, {:value => '', :size => 16, :class => :task_description} %>
|
49
38
|
</td>
|
@@ -51,16 +40,15 @@ function set_backlog_for_task() {
|
|
51
40
|
<%=text_field_with_auto_complete :work, :description, {:size => 16, :class => :task_description} %>
|
52
41
|
</td>
|
53
42
|
<td align="right" valign="bottom">
|
54
|
-
<%=text_field :work, :started_at_time, :value =>
|
43
|
+
<%=text_field :work, :started_at_time, :value => last_work && last_work.completed_at.strftime('%H:%M'), :class => 'task_time' %>
|
55
44
|
</td>
|
56
45
|
<td align="right" valign="bottom">
|
57
|
-
<%=text_field :work, :completed_at_time, :class => 'task_time', :value => @work.completed_at.strftime('%H:%M') %>
|
46
|
+
<%=text_field :work, :completed_at_time, :class => 'task_time', :value => @work && @work.completed_at.strftime('%H:%M') %>
|
58
47
|
</td>
|
59
48
|
<td align="right" valign="bottom">
|
60
49
|
<%=text_field :work, :hours_time, :value => '', :class => 'task_hours' %>
|
61
50
|
</td>
|
62
51
|
<td valign="bottom">
|
63
|
-
<%=image_button_to('arrow_left.png', l(:calculate), :controller => 'backlogs', :action => :show) %>
|
64
52
|
</td>
|
65
53
|
</tr>
|
66
54
|
<tr>
|
@@ -68,10 +56,9 @@ function set_backlog_for_task() {
|
|
68
56
|
<th><%=l :totals %></th>
|
69
57
|
<th/>
|
70
58
|
<th/>
|
71
|
-
<th/>
|
72
|
-
<th/>
|
73
59
|
<th class="hours"><%='%.2f' % day_total %></th>
|
74
60
|
</tr>
|
61
|
+
<% end %>
|
75
62
|
</table>
|
76
63
|
<%= submit_tag l(:save) %>
|
77
64
|
<%= back_or_link_to l(:back), '' %>
|
@@ -89,7 +76,11 @@ function set_backlog_for_task() {
|
|
89
76
|
|
90
77
|
<script type="text/JavaScript">
|
91
78
|
//<!--
|
92
|
-
|
79
|
+
<% if last_work.completed_at %>
|
80
|
+
start_field = $('work_work_account_name')
|
81
|
+
<% else %>
|
82
|
+
start_field = $('work_<%=last_work.id%>_completed_at_time')
|
83
|
+
<% end %>
|
93
84
|
start_field.focus();
|
94
85
|
start_field.select();
|
95
86
|
//-->
|
@@ -449,11 +449,11 @@
|
|
449
449
|
<Cell ss:StyleID="s37"><Data ss:Type="String">Merknad</Data></Cell>
|
450
450
|
</Row>
|
451
451
|
|
452
|
-
<% for
|
453
|
-
<% invoice_works_per_day = @
|
452
|
+
<% for work_account_id in @work_totals_per_work_account.keys %>
|
453
|
+
<% invoice_works_per_day = @work_totals_per_work_account[work_account_id][0]%>
|
454
454
|
<% if invoice_works_per_day.find{|total| total > 0} %>
|
455
455
|
<Row>
|
456
|
-
<Cell ss:StyleID="s24"><Data ss:Type="Number"><%=Backlog.find(
|
456
|
+
<Cell ss:StyleID="s24"><Data ss:Type="Number"><%=Backlog.find(work_account_id).invoice_code %></Data></Cell>
|
457
457
|
<Cell ss:StyleID="s25"/>
|
458
458
|
<Cell ss:StyleID="s25"><Data ss:Type="String"> X</Data></Cell>
|
459
459
|
<Cell ss:StyleID="s25"/>
|
@@ -468,10 +468,10 @@
|
|
468
468
|
</Row>
|
469
469
|
<% end %>
|
470
470
|
|
471
|
-
<% internal_works_per_day = @
|
471
|
+
<% internal_works_per_day = @work_totals_per_work_account[work_account_id][1]%>
|
472
472
|
<% if internal_works_per_day.find{|total| total > 0} %>
|
473
473
|
<Row>
|
474
|
-
<Cell ss:StyleID="s24"><Data ss:Type="String"><%=
|
474
|
+
<Cell ss:StyleID="s24"><Data ss:Type="String"><%=WorkAccount.find(work_account_id).name %></Data></Cell>
|
475
475
|
<Cell ss:StyleID="s25"><Data ss:Type="String">Mesta2</Data></Cell>
|
476
476
|
<Cell ss:StyleID="s25"/>
|
477
477
|
<Cell ss:StyleID="s25"/>
|
@@ -527,25 +527,25 @@
|
|
527
527
|
<Cell ss:StyleID="s46"/>
|
528
528
|
<Cell ss:StyleID="s46"/>
|
529
529
|
<Cell ss:StyleID="s46"
|
530
|
-
ss:Formula="=IF(SUM(R[-<%=@
|
530
|
+
ss:Formula="=IF(SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),"")"><Data
|
531
531
|
ss:Type="String"></Data></Cell>
|
532
532
|
<Cell ss:StyleID="s46"
|
533
|
-
ss:Formula="=IF(SUM(R[-<%=@
|
533
|
+
ss:Formula="=IF(SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),"")"><Data
|
534
534
|
ss:Type="String"></Data></Cell>
|
535
535
|
<Cell ss:StyleID="s46"
|
536
|
-
ss:Formula="=IF(SUM(R[-<%=@
|
536
|
+
ss:Formula="=IF(SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),"")"><Data
|
537
537
|
ss:Type="String"></Data></Cell>
|
538
538
|
<Cell ss:StyleID="s46"
|
539
|
-
ss:Formula="=IF(SUM(R[-<%=@
|
539
|
+
ss:Formula="=IF(SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),"")"><Data
|
540
540
|
ss:Type="String"></Data></Cell>
|
541
541
|
<Cell ss:StyleID="s46"
|
542
|
-
ss:Formula="=IF(SUM(R[-<%=@
|
542
|
+
ss:Formula="=IF(SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),"")"><Data
|
543
543
|
ss:Type="String"></Data></Cell>
|
544
544
|
<Cell ss:StyleID="s46"
|
545
|
-
ss:Formula="=IF(SUM(R[-<%=@
|
545
|
+
ss:Formula="=IF(SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),"")"><Data
|
546
546
|
ss:Type="String"></Data></Cell>
|
547
547
|
<Cell ss:StyleID="s46"
|
548
|
-
ss:Formula="=IF(SUM(R[-<%=@
|
548
|
+
ss:Formula="=IF(SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),SUM(R[-<%=@work_totals_per_work_account.size*2+2%>]C:R[-1]C),"")"><Data
|
549
549
|
ss:Type="String"></Data></Cell>
|
550
550
|
<Cell ss:StyleID="s47"/>
|
551
551
|
</Row>
|
@@ -1,6 +1,4 @@
|
|
1
1
|
page.replace "work_#{@work.id}", :partial => 'row', :object => @work
|
2
2
|
page.replace "notice", :partial => '/layouts/notice'
|
3
|
-
page
|
4
|
-
|
5
|
-
# elem.focus
|
6
|
-
end
|
3
|
+
page["work_#{@work.id}_#{@field}"].select
|
4
|
+
page["work_#{@work.id}_#{@field}"].focus
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<div id="spotlight">
|
4
4
|
<% track_times = @rows.find {|r| r.find {|w| w && w.work_account.track_times?}} %>
|
5
5
|
<% invoicing = @rows.find {|r| r.find {|w| w && w.work_account.enable_invoicing?}} %>
|
6
|
-
<% columns = 2 + (track_times ?
|
6
|
+
<% columns = 2 + (track_times ? 1 : 0) + (invoicing ? 1 : 0) %>
|
7
7
|
|
8
8
|
<div style="float: left"><%=link_to(image_tag('arrow_left.png'), :year => (@week > 1 ? @year : @year - 1), :week => (@week > 1 ? @week - 1 : 52))%></div>
|
9
9
|
<div style="float: right"><%=link_to(image_tag('arrow_right.png'), :year => (@week < 52 ? @year : @year + 1), :week => (@week < 52 ? @week + 1 : 1))%></div>
|
@@ -11,6 +11,8 @@
|
|
11
11
|
<h1>Work for week <%=@week%><%=user? ? " for #{user.login}" : ''%></h1>
|
12
12
|
|
13
13
|
<div align="right">
|
14
|
+
<% lock_action = @lock ? :unlock : :lock %>
|
15
|
+
[<%=link_to l(lock_action), :controller => 'work_locks', :action => lock_action %>]
|
14
16
|
[<%=detour_to l(:new_work), :controller => 'works', :action => :new %>]
|
15
17
|
[<%=link_to 'Timeliste', :action => :timeliste, :id => @week %>]
|
16
18
|
[<%= if params[:with_empty]
|
@@ -22,24 +24,19 @@ end %>]
|
|
22
24
|
|
23
25
|
<table border="1">
|
24
26
|
<tr>
|
25
|
-
|
26
|
-
<th colspan="<%=columns%>" align="center"><%=l :
|
27
|
-
|
28
|
-
<th colspan="<%=columns%>" align="center"><%=l :thursday %> <%=week_date(4)%></th>
|
29
|
-
<th colspan="<%=columns%>" align="center"><%=l :friday %> <%=week_date(5)%></th>
|
30
|
-
<th colspan="<%=columns%>" align="center"><%=l :saturday %> <%=week_date(6)%></th>
|
31
|
-
<th colspan="<%=columns%>" align="center"><%=l :sunday %> <%=week_date(7)%></th>
|
27
|
+
<% [:monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday].each_with_index do |day, i| %>
|
28
|
+
<th colspan="<%=columns%>" align="center"><%=detour_to "#{l(day)} #{week_date(i+1)}", :action => :daily_work_sheet, :id => (@first_date + i).strftime('%Y-%m-%d') %></th>
|
29
|
+
<% end %>
|
32
30
|
<th align="center" nowrap="true"><%=l :week %> <%=@week%></th>
|
33
31
|
</tr>
|
34
32
|
<tr>
|
35
33
|
<% (1..7).each do %>
|
36
|
-
<th><%=l :
|
34
|
+
<th><%=l :work_account %></th>
|
37
35
|
<% if invoicing %>
|
38
36
|
<th><%=l :invoice_short %></th>
|
39
37
|
<% end %>
|
40
38
|
<% if track_times %>
|
41
|
-
<th><%=l(:start) if track_times %></th>
|
42
|
-
<th><%=l(:stop) if track_times %></th>
|
39
|
+
<th><%=l(:start) if track_times %> - <%=l(:stop) if track_times %></th>
|
43
40
|
<% end %>
|
44
41
|
<th><%=l :done %></th>
|
45
42
|
<% end %>
|
@@ -55,28 +52,31 @@ end %>]
|
|
55
52
|
<% day_totals[day] += @work.hours %>
|
56
53
|
<% week_total += @work.hours %>
|
57
54
|
<td valign="top">
|
58
|
-
<%=image_detour_to('hammer.png', l(:edit), {:controller => 'works', :action => :edit, :id => @work.id}, {:style => "float:
|
55
|
+
<%=image_detour_to('hammer.png', l(:edit), {:controller => 'works', :action => :edit, :id => @work.id}, {:style => "float: left; border: 1px solid black"}) %>
|
56
|
+
<!--
|
59
57
|
<%=detour_to(h(@work.task.period.name), :controller => 'periods', :action => :show, :id => @work.task.period) if @work.task && @work.task.period %>
|
58
|
+
-->
|
60
59
|
<%=detour_to(h(@work.work_account.name), :controller => 'work_accounts', :action => :show, :id => @work.work_account_id) %>:
|
60
|
+
<!--
|
61
61
|
<%=detour_to(h(@work.task.description), :controller => 'tasks', :action => :edit, :id => @work.task_id) if @work.task_id%>
|
62
|
+
-->
|
62
63
|
</td>
|
63
64
|
<% if invoicing %>
|
64
65
|
<td id="invoice_<%=@work.id%>" valign="top">
|
65
|
-
<%=check_box(:work, :invoice, :onchange => "new Ajax.Updater('invoice_#{@work}', '#{url_for(:action => :set_work_invoice, :id => @work)}' + '?value=' + this.checked);") if @work.work_account.enable_invoicing? %>
|
66
|
+
<%=check_box(:work, :invoice, :onchange => "new Ajax.Updater('invoice_#{@work}', '#{url_for(:action => :set_work_invoice, :id => @work)}' + '?value=' + this.checked);", :disabled => @lock) if @work.work_account.enable_invoicing? %>
|
66
67
|
</td>
|
67
68
|
<% end %>
|
68
69
|
<% if track_times %>
|
69
|
-
<td align="
|
70
|
-
|
70
|
+
<td align="left" valign="top"><%=text_field(:work, :started_at_time, :class => :task_time, :disabled => @lock) %> -
|
71
|
+
<%=text_field(:work, :completed_at_time, :class => :task_time, :disabled => @lock) %></td>
|
71
72
|
<% end %>
|
72
|
-
<td align="right" valign="top"><%=
|
73
|
+
<td align="right" valign="top"><%=text_field(:work, :hours, :value => '%.2f' % @work.hours, :class => 'task_hours') %></td>
|
73
74
|
<% else %>
|
74
75
|
<td/>
|
75
76
|
<% if invoicing %>
|
76
77
|
<td/>
|
77
78
|
<% end %>
|
78
79
|
<% if track_times %>
|
79
|
-
<td/>
|
80
80
|
<td/>
|
81
81
|
<% end %>
|
82
82
|
<td/>
|
@@ -0,0 +1,57 @@
|
|
1
|
+
<% @page_title = l(:weekly_work_sheet) + " " + @week.to_s + (user? ? " for #{user.login}" : '')%>
|
2
|
+
|
3
|
+
<div id="spotlight">
|
4
|
+
<% columns = 2 %>
|
5
|
+
|
6
|
+
<div style="float: left"><%=link_to(image_tag('arrow_left.png'), :year => (@week > 1 ? @year : @year - 1), :week => (@week > 1 ? @week - 1 : 52))%></div>
|
7
|
+
<div style="float: right"><%=link_to(image_tag('arrow_right.png'), :year => (@week < 52 ? @year : @year + 1), :week => (@week < 52 ? @week + 1 : 1))%></div>
|
8
|
+
|
9
|
+
<div align="right">
|
10
|
+
<% lock_action = @lock ? :unlock : :lock %>
|
11
|
+
[<%=link_to l(lock_action), with_detour(:controller => 'work_locks', :action => lock_action, :year => @year, :week => @week) %>]
|
12
|
+
<% if @lock %>
|
13
|
+
[<%=link_to l(:spreadsheet), :action => :timeliste, :year => @year, :week => @week %>]
|
14
|
+
<% else %>
|
15
|
+
[<%=detour_to l(:new_work), :controller => 'works', :action => :new %>]
|
16
|
+
<% end %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<br clear="all" />
|
20
|
+
|
21
|
+
<table border="1">
|
22
|
+
<tr>
|
23
|
+
<th><%=l :work_account %></th>
|
24
|
+
<% [:monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday].each_with_index do |day, i| %>
|
25
|
+
<th align="center"><%=detour_to "#{l(day)} #{week_date(i+1)}", :action => :daily_work_sheet, :id => (@first_date + i).strftime('%Y-%m-%d') %></th>
|
26
|
+
<% end %>
|
27
|
+
<th align="center" nowrap="true"><%=l :week %> <%=@week%></th>
|
28
|
+
</tr>
|
29
|
+
|
30
|
+
<% week_totals = Hash.new(0) %>
|
31
|
+
<% day_totals = Array.new(7, 0) %>
|
32
|
+
<% for work_account, totals in @work_accounts %>
|
33
|
+
<tr>
|
34
|
+
<td valign="top">
|
35
|
+
<%=detour_to(h(work_account.name), :controller => 'work_accounts', :action => :show, :id => work_account.id) %>
|
36
|
+
</td>
|
37
|
+
<% totals.each_with_index do |total, day| %>
|
38
|
+
<% if total %>
|
39
|
+
<% day_totals[day] += total %>
|
40
|
+
<% week_totals[work_account] += total %>
|
41
|
+
<td align="right" valign="top"><%='%.2f' % total%></td>
|
42
|
+
<% else %>
|
43
|
+
<td/>
|
44
|
+
<% end %>
|
45
|
+
<% end %>
|
46
|
+
<td align="right"><%=week_totals[work_account]%></td>
|
47
|
+
</tr>
|
48
|
+
<% end %>
|
49
|
+
<tr>
|
50
|
+
<th><%=l :totals%></th>
|
51
|
+
<% (0..6).each do |day| %>
|
52
|
+
<th class="hours"><%='%.2f' % day_totals[day] if day_totals[day] > 0%></th>
|
53
|
+
<% end %>
|
54
|
+
<th class="hours"><%= '%.2f' % week_totals.values.inject(0) {|total, work_account_total| total + work_account_total} %></th>
|
55
|
+
</tr>
|
56
|
+
</table>
|
57
|
+
</div>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class CreateWorkLocks < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :work_locks do |t|
|
4
|
+
t.column :user_id, :integer, :null => false, :references => [:users, :party_id]
|
5
|
+
t.column :start_on, :date, :null => false
|
6
|
+
t.column :end_on, :date, :null => false
|
7
|
+
end
|
8
|
+
|
9
|
+
create_table :work_lock_subscriptions, :id => false do |t|
|
10
|
+
t.column :subscriber_user_id, :integer, :null => false, :references => [:users, :party_id]
|
11
|
+
t.column :work_account_id, :integer, :null => false
|
12
|
+
end
|
13
|
+
|
14
|
+
create_table :user_work_lock_subscriptions, :id => false do |t|
|
15
|
+
t.column :subscriber_user_id, :integer, :null => false, :references => [:users, :party_id]
|
16
|
+
t.column :user_id, :integer, :null => false, :references => [:users, :party_id]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.down
|
21
|
+
drop_table :user_work_lock_subscriptions
|
22
|
+
drop_table :work_lock_subscriptions
|
23
|
+
drop_table :work_locks
|
24
|
+
end
|
25
|
+
end
|
data/db/schema.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
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 =>
|
5
|
+
ActiveRecord::Schema.define(:version => 27) do
|
6
6
|
|
7
7
|
create_table "backlogs", :force => true do |t|
|
8
8
|
t.column "name", :string, :limit => 64, :null => false
|
@@ -87,6 +87,11 @@ ActiveRecord::Schema.define(:version => 26) do
|
|
87
87
|
t.column "user_id", :integer, :null => false
|
88
88
|
end
|
89
89
|
|
90
|
+
create_table "user_work_lock_subscriptions", :id => false, :force => true do |t|
|
91
|
+
t.column "subscriber_user_id", :integer, :null => false
|
92
|
+
t.column "user_id", :integer, :null => false
|
93
|
+
end
|
94
|
+
|
90
95
|
create_table "users", :primary_key => "party_id", :force => true do |t|
|
91
96
|
t.column "login", :string, :limit => 80, :null => false
|
92
97
|
t.column "salted_password", :string, :limit => 40, :null => false
|
@@ -107,6 +112,17 @@ ActiveRecord::Schema.define(:version => 26) do
|
|
107
112
|
t.column "invoice_code", :string
|
108
113
|
end
|
109
114
|
|
115
|
+
create_table "work_lock_subscriptions", :id => false, :force => true do |t|
|
116
|
+
t.column "subscriber_user_id", :integer, :null => false
|
117
|
+
t.column "work_account_id", :integer, :null => false
|
118
|
+
end
|
119
|
+
|
120
|
+
create_table "work_locks", :force => true do |t|
|
121
|
+
t.column "user_id", :integer, :null => false
|
122
|
+
t.column "start_on", :date, :null => false
|
123
|
+
t.column "end_on", :date, :null => false
|
124
|
+
end
|
125
|
+
|
110
126
|
create_table "works", :force => true do |t|
|
111
127
|
t.column "task_id", :integer
|
112
128
|
t.column "hours", :decimal, :precision => 6, :scale => 2, :default => 0.0, :null => false
|
@@ -148,8 +164,16 @@ ActiveRecord::Schema.define(:version => 26) do
|
|
148
164
|
add_foreign_key "tasks_users", ["task_id"], "tasks", ["id"], :name => "tasks_users_task_id_fkey"
|
149
165
|
add_foreign_key "tasks_users", ["user_id"], "users", ["party_id"], :name => "tasks_users_user_id_fkey"
|
150
166
|
|
167
|
+
add_foreign_key "user_work_lock_subscriptions", ["subscriber_user_id"], "users", ["party_id"], :name => "user_work_lock_subscriptions_subscriber_user_id_fkey"
|
168
|
+
add_foreign_key "user_work_lock_subscriptions", ["user_id"], "users", ["party_id"], :name => "user_work_lock_subscriptions_user_id_fkey"
|
169
|
+
|
151
170
|
add_foreign_key "users", ["party_id"], "parties", ["id"], :name => "users_party_id_fkey"
|
152
171
|
|
172
|
+
add_foreign_key "work_lock_subscriptions", ["subscriber_user_id"], "users", ["party_id"], :name => "work_lock_subscriptions_subscriber_user_id_fkey"
|
173
|
+
add_foreign_key "work_lock_subscriptions", ["work_account_id"], "work_accounts", ["id"], :name => "work_lock_subscriptions_work_account_id_fkey"
|
174
|
+
|
175
|
+
add_foreign_key "work_locks", ["user_id"], "users", ["party_id"], :name => "work_locks_user_id_fkey"
|
176
|
+
|
153
177
|
add_foreign_key "works", ["work_account_id"], "work_accounts", ["id"], :name => "works_work_account_id_fkey"
|
154
178
|
add_foreign_key "works", ["customer_id"], "customers", ["id"], :name => "works_customer_id_fkey"
|
155
179
|
add_foreign_key "works", ["user_id"], "users", ["party_id"], :name => "works_user_id_fkey"
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -4,7 +4,7 @@ require 'estimates_controller'
|
|
4
4
|
class EstimatesController; def rescue_action(e) raise e end; end
|
5
5
|
|
6
6
|
class EstimatesControllerTest < Test::Unit::TestCase
|
7
|
-
|
7
|
+
main_scenario
|
8
8
|
|
9
9
|
def setup
|
10
10
|
@controller = EstimatesController.new
|
@@ -4,7 +4,7 @@ require 'groups_controller'
|
|
4
4
|
class GroupsController; def rescue_action(e) raise e end; end
|
5
5
|
|
6
6
|
class GroupsControllerTest < Test::Unit::TestCase
|
7
|
-
|
7
|
+
main_scenario
|
8
8
|
|
9
9
|
def setup
|
10
10
|
@controller = GroupsController.new
|
@@ -33,7 +33,7 @@ class UserControllerTest < Test::Unit::TestCase
|
|
33
33
|
post :login, :user => { :login => "tesla", :password => "atest" }
|
34
34
|
assert_logged_in users(:tesla)
|
35
35
|
assert_response :redirect
|
36
|
-
assert_equal @controller.url_for(:controller => '
|
36
|
+
assert_equal @controller.url_for(:controller => 'welcome', :action => :index), @response.redirect_url
|
37
37
|
end
|
38
38
|
|
39
39
|
def test_login__wrong_password
|
@@ -219,7 +219,7 @@ class UserControllerTest < Test::Unit::TestCase
|
|
219
219
|
|
220
220
|
assert_logged_in users(:tesla)
|
221
221
|
assert_response :redirect
|
222
|
-
assert_equal @controller.url_for(:controller => '
|
222
|
+
assert_equal @controller.url_for(:controller => 'welcome', :action => :index), @response.redirect_url
|
223
223
|
assert_cookie :autologin, :value => '1000001'
|
224
224
|
assert_cookie :token
|
225
225
|
assert_not_equal 'random_token_string', cookies['token'].value
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
require 'work_locks_controller'
|
3
|
+
|
4
|
+
# Re-raise errors caught by the controller.
|
5
|
+
class WorkLocksController; def rescue_action(e) raise e end; end
|
6
|
+
|
7
|
+
class WorkLocksControllerTest < Test::Unit::TestCase
|
8
|
+
fixtures :work_locks
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@controller = WorkLocksController.new
|
12
|
+
@request = ActionController::TestRequest.new
|
13
|
+
@response = ActionController::TestResponse.new
|
14
|
+
@request.session[:user_id] = 1000001
|
15
|
+
|
16
|
+
@first_id = work_locks(: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(:work_locks)
|
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(:work_lock)
|
41
|
+
assert assigns(:work_lock).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(:work_lock)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_create
|
54
|
+
num_work_locks = WorkLock.count
|
55
|
+
|
56
|
+
post :create, :work_lock => {:user_id => '1000001', :start_on => '2008-01-28', :end_on => '2008-01-28'}
|
57
|
+
|
58
|
+
assert_response :redirect
|
59
|
+
assert_redirected_to :action => 'list'
|
60
|
+
|
61
|
+
assert_equal num_work_locks + 1, WorkLock.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(:work_lock)
|
71
|
+
assert assigns(:work_lock).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
|
+
WorkLock.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
|
+
WorkLock.find(@first_id)
|
91
|
+
}
|
92
|
+
end
|
93
|
+
end
|
@@ -4,7 +4,7 @@ require 'user_notify'
|
|
4
4
|
|
5
5
|
class UserSystemTest < ActionController::IntegrationTest
|
6
6
|
self.use_transactional_fixtures = false
|
7
|
-
|
7
|
+
main_scenario
|
8
8
|
|
9
9
|
def setup
|
10
10
|
ActionMailer::Base.inject_one_error = false
|
data/test/test_helper.rb
CHANGED
@@ -5,7 +5,7 @@ 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
|
8
|
+
fixtures :parties, :users, :groups, :groups_users, :work_accounts, :backlogs, :periods, :tasks, :task_files, :works, :estimates, :work_lock_subscriptions, :work_locks
|
9
9
|
end
|
10
10
|
|
11
11
|
# Transactional fixtures accelerate your tests by wrapping each test method
|
data/test/unit/estimate_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../test_helper'
|
2
2
|
|
3
3
|
class EstimateTest < Test::Unit::TestCase
|
4
|
-
|
4
|
+
main_scenario
|
5
5
|
|
6
6
|
# Replace this with your real tests.
|
7
7
|
def test_truth
|