Revision 1298:4f746d8966dd .svn/pristine/0c

View differences:

.svn/pristine/0c/0c07ac7fadf7713b8982de217779de9a2084825c.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
class Group < Principal
19
  has_and_belongs_to_many :users, :after_add => :user_added,
20
                                  :after_remove => :user_removed
21

  
22
  acts_as_customizable
23

  
24
  validates_presence_of :lastname
25
  validates_uniqueness_of :lastname, :case_sensitive => false
26
  validates_length_of :lastname, :maximum => 30
27

  
28
  before_destroy :remove_references_before_destroy
29

  
30
  def to_s
31
    lastname.to_s
32
  end
33

  
34
  alias :name :to_s
35

  
36
  def user_added(user)
37
    members.each do |member|
38
      next if member.project.nil?
39
      user_member = Member.find_by_project_id_and_user_id(member.project_id, user.id) || Member.new(:project_id => member.project_id, :user_id => user.id)
40
      member.member_roles.each do |member_role|
41
        user_member.member_roles << MemberRole.new(:role => member_role.role, :inherited_from => member_role.id)
42
      end
43
      user_member.save!
44
    end
45
  end
46

  
47
  def user_removed(user)
48
    members.each do |member|
49
      MemberRole.find(:all, :include => :member,
50
                            :conditions => ["#{Member.table_name}.user_id = ? AND #{MemberRole.table_name}.inherited_from IN (?)", user.id, member.member_role_ids]).each(&:destroy)
51
    end
52
  end
53

  
54
  def self.human_attribute_name(attribute_key_name)
55
    attr_name = attribute_key_name
56
    if attr_name == 'lastname'
57
      attr_name = "name"
58
    end
59
    super(attr_name)
60
  end
61

  
62
  private
63

  
64
  # Removes references that are not handled by associations
65
  def remove_references_before_destroy
66
    return if self.id.nil?
67

  
68
    Issue.update_all 'assigned_to_id = NULL', ['assigned_to_id = ?', id]
69
  end
70
end
.svn/pristine/0c/0c1341a53592418e4a2dd8783234ed2bf47a5fde.svn-base
1
$('#principals_for_new_member').html('<%= escape_javascript(render_principals_for_new_members(@project)) %>');
.svn/pristine/0c/0c3d44b905a542240e7c616a63f74580e8cbbb9d.svn-base
1
<% diff = Redmine::UnifiedDiff.new(
2
            diff, :type => diff_type,
3
            :max_lines => Setting.diff_max_lines_displayed.to_i) -%>
4

  
5
<% diff.each do |table_file| -%>
6
<div class="autoscroll">
7
<% if diff.diff_type == 'sbs' -%>
8
<table class="filecontent">
9
<thead>
10
<tr>
11
  <th colspan="4" class="filename">
12
    <%= h(Redmine::CodesetUtil.to_utf8_by_setting(table_file.file_name)) %>
13
  </th>
14
</tr>
15
</thead>
16
<tbody>
17
<% table_file.each_line do |spacing, line| -%>
18
<% if spacing -%>
19
<tr class="spacing">
20
  <th class="line-num">...</th><td></td><th class="line-num">...</th><td></td>
21
</tr>
22
<% end -%>
23
<tr>
24
  <th class="line-num"><%= line.nb_line_left %></th>
25
  <td class="line-code <%= line.type_diff_left %>">
26
    <pre><%= Redmine::CodesetUtil.to_utf8_by_setting(line.html_line_left) %></pre>
27
  </td>
28
  <th class="line-num"><%= line.nb_line_right %></th>
29
  <td class="line-code <%= line.type_diff_right %>">
30
    <pre><%= Redmine::CodesetUtil.to_utf8_by_setting(line.html_line_right) %></pre>
31
  </td>
32
</tr>
33
<% end -%>
34
</tbody>
35
</table>
36

  
37
<% else -%>
38
<table class="filecontent">
39
<thead>
40
  <tr>
41
    <th colspan="3" class="filename">
42
      <%= h(Redmine::CodesetUtil.to_utf8_by_setting(table_file.file_name)) %>
43
    </th>
44
  </tr>
45
</thead>
46
<tbody>
47
<% table_file.each_line do |spacing, line| %>
48
<% if spacing -%>
49
<tr class="spacing">
50
  <th class="line-num">...</th><th class="line-num">...</th><td></td>
51
</tr>
52
<% end -%>
53
<tr>
54
  <th class="line-num"><%= line.nb_line_left %></th>
55
  <th class="line-num"><%= line.nb_line_right %></th>
56
  <td class="line-code <%= line.type_diff %>">
57
    <pre><%= Redmine::CodesetUtil.to_utf8_by_setting(line.html_line) %></pre>
58
  </td>
59
</tr>
60
<% end -%>
61
</tbody>
62
</table>
63
<% end -%>
64
</div>
65
<% end -%>
66

  
67
<%= l(:text_diff_truncated) if diff.truncated? %>
.svn/pristine/0c/0c683f18d0752b5b1c900f3d3bf34e0652a0c13f.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
class Version < ActiveRecord::Base
19
  include Redmine::SafeAttributes
20
  after_update :update_issues_from_sharing_change
21
  belongs_to :project
22
  has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify
23
  acts_as_customizable
24
  acts_as_attachable :view_permission => :view_files,
25
                     :delete_permission => :manage_files
26

  
27
  VERSION_STATUSES = %w(open locked closed)
28
  VERSION_SHARINGS = %w(none descendants hierarchy tree system)
29

  
30
  validates_presence_of :name
31
  validates_uniqueness_of :name, :scope => [:project_id]
32
  validates_length_of :name, :maximum => 60
33
  validates :effective_date, :date => true
34
  validates_inclusion_of :status, :in => VERSION_STATUSES
35
  validates_inclusion_of :sharing, :in => VERSION_SHARINGS
36

  
37
  scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
38
  scope :open, lambda { where(:status => 'open') }
39
  scope :visible, lambda {|*args|
40
    includes(:project).where(Project.allowed_to_condition(args.first || User.current, :view_issues))
41
  }
42

  
43
  safe_attributes 'name', 
44
    'description',
45
    'effective_date',
46
    'due_date',
47
    'wiki_page_title',
48
    'status',
49
    'sharing',
50
    'custom_field_values',
51
    'custom_fields'
52

  
53
  # Returns true if +user+ or current user is allowed to view the version
54
  def visible?(user=User.current)
55
    user.allowed_to?(:view_issues, self.project)
56
  end
57

  
58
  # Version files have same visibility as project files
59
  def attachments_visible?(*args)
60
    project.present? && project.attachments_visible?(*args)
61
  end
62

  
63
  def start_date
64
    @start_date ||= fixed_issues.minimum('start_date')
65
  end
66

  
67
  def due_date
68
    effective_date
69
  end
70

  
71
  def due_date=(arg)
72
    self.effective_date=(arg)
73
  end
74

  
75
  # Returns the total estimated time for this version
76
  # (sum of leaves estimated_hours)
77
  def estimated_hours
78
    @estimated_hours ||= fixed_issues.leaves.sum(:estimated_hours).to_f
79
  end
80

  
81
  # Returns the total reported time for this version
82
  def spent_hours
83
    @spent_hours ||= TimeEntry.joins(:issue).where("#{Issue.table_name}.fixed_version_id = ?", id).sum(:hours).to_f
84
  end
85

  
86
  def closed?
87
    status == 'closed'
88
  end
89

  
90
  def open?
91
    status == 'open'
92
  end
93

  
94
  # Returns true if the version is completed: due date reached and no open issues
95
  def completed?
96
    effective_date && (effective_date < Date.today) && (open_issues_count == 0)
97
  end
98

  
99
  def behind_schedule?
100
    if completed_percent == 100
101
      return false
102
    elsif due_date && start_date
103
      done_date = start_date + ((due_date - start_date+1)* completed_percent/100).floor
104
      return done_date <= Date.today
105
    else
106
      false # No issues so it's not late
107
    end
108
  end
109

  
110
  # Returns the completion percentage of this version based on the amount of open/closed issues
111
  # and the time spent on the open issues.
112
  def completed_percent
113
    if issues_count == 0
114
      0
115
    elsif open_issues_count == 0
116
      100
117
    else
118
      issues_progress(false) + issues_progress(true)
119
    end
120
  end
121

  
122
  # TODO: remove in Redmine 3.0
123
  def completed_pourcent
124
    ActiveSupport::Deprecation.warn "Version#completed_pourcent is deprecated and will be removed in Redmine 3.0. Please use #completed_percent instead."
125
    completed_percent
126
  end
127

  
128
  # Returns the percentage of issues that have been marked as 'closed'.
129
  def closed_percent
130
    if issues_count == 0
131
      0
132
    else
133
      issues_progress(false)
134
    end
135
  end
136

  
137
  # TODO: remove in Redmine 3.0
138
  def closed_pourcent
139
    ActiveSupport::Deprecation.warn "Version#closed_pourcent is deprecated and will be removed in Redmine 3.0. Please use #closed_percent instead."
140
    closed_percent
141
  end
142

  
143
  # Returns true if the version is overdue: due date reached and some open issues
144
  def overdue?
145
    effective_date && (effective_date < Date.today) && (open_issues_count > 0)
146
  end
147

  
148
  # Returns assigned issues count
149
  def issues_count
150
    load_issue_counts
151
    @issue_count
152
  end
153

  
154
  # Returns the total amount of open issues for this version.
155
  def open_issues_count
156
    load_issue_counts
157
    @open_issues_count
158
  end
159

  
160
  # Returns the total amount of closed issues for this version.
161
  def closed_issues_count
162
    load_issue_counts
163
    @closed_issues_count
164
  end
165

  
166
  def wiki_page
167
    if project.wiki && !wiki_page_title.blank?
168
      @wiki_page ||= project.wiki.find_page(wiki_page_title)
169
    end
170
    @wiki_page
171
  end
172

  
173
  def to_s; name end
174

  
175
  def to_s_with_project
176
    "#{project} - #{name}"
177
  end
178

  
179
  # Versions are sorted by effective_date and name
180
  # Those with no effective_date are at the end, sorted by name
181
  def <=>(version)
182
    if self.effective_date
183
      if version.effective_date
184
        if self.effective_date == version.effective_date
185
          name == version.name ? id <=> version.id : name <=> version.name
186
        else
187
          self.effective_date <=> version.effective_date
188
        end
189
      else
190
        -1
191
      end
192
    else
193
      if version.effective_date
194
        1
195
      else
196
        name == version.name ? id <=> version.id : name <=> version.name
197
      end
198
    end
199
  end
200

  
201
  def self.fields_for_order_statement(table=nil)
202
    table ||= table_name
203
    ["(CASE WHEN #{table}.effective_date IS NULL THEN 1 ELSE 0 END)", "#{table}.effective_date", "#{table}.name", "#{table}.id"]
204
  end
205

  
206
  scope :sorted, order(fields_for_order_statement)
207

  
208
  # Returns the sharings that +user+ can set the version to
209
  def allowed_sharings(user = User.current)
210
    VERSION_SHARINGS.select do |s|
211
      if sharing == s
212
        true
213
      else
214
        case s
215
        when 'system'
216
          # Only admin users can set a systemwide sharing
217
          user.admin?
218
        when 'hierarchy', 'tree'
219
          # Only users allowed to manage versions of the root project can
220
          # set sharing to hierarchy or tree
221
          project.nil? || user.allowed_to?(:manage_versions, project.root)
222
        else
223
          true
224
        end
225
      end
226
    end
227
  end
228

  
229
  private
230

  
231
  def load_issue_counts
232
    unless @issue_count
233
      @open_issues_count = 0
234
      @closed_issues_count = 0
235
      fixed_issues.count(:all, :group => :status).each do |status, count|
236
        if status.is_closed?
237
          @closed_issues_count += count
238
        else
239
          @open_issues_count += count
240
        end
241
      end
242
      @issue_count = @open_issues_count + @closed_issues_count
243
    end
244
  end
245

  
246
  # Update the issue's fixed versions. Used if a version's sharing changes.
247
  def update_issues_from_sharing_change
248
    if sharing_changed?
249
      if VERSION_SHARINGS.index(sharing_was).nil? ||
250
          VERSION_SHARINGS.index(sharing).nil? ||
251
          VERSION_SHARINGS.index(sharing_was) > VERSION_SHARINGS.index(sharing)
252
        Issue.update_versions_from_sharing_change self
253
      end
254
    end
255
  end
256

  
257
  # Returns the average estimated time of assigned issues
258
  # or 1 if no issue has an estimated time
259
  # Used to weigth unestimated issues in progress calculation
260
  def estimated_average
261
    if @estimated_average.nil?
262
      average = fixed_issues.average(:estimated_hours).to_f
263
      if average == 0
264
        average = 1
265
      end
266
      @estimated_average = average
267
    end
268
    @estimated_average
269
  end
270

  
271
  # Returns the total progress of open or closed issues.  The returned percentage takes into account
272
  # the amount of estimated time set for this version.
273
  #
274
  # Examples:
275
  # issues_progress(true)   => returns the progress percentage for open issues.
276
  # issues_progress(false)  => returns the progress percentage for closed issues.
277
  def issues_progress(open)
278
    @issues_progress ||= {}
279
    @issues_progress[open] ||= begin
280
      progress = 0
281
      if issues_count > 0
282
        ratio = open ? 'done_ratio' : 100
283

  
284
        done = fixed_issues.open(open).sum("COALESCE(estimated_hours, #{estimated_average}) * #{ratio}").to_f
285
        progress = done / (estimated_average * issues_count)
286
      end
287
      progress
288
    end
289
  end
290
end
.svn/pristine/0c/0ca7bda81025c5f7a9ebad14d8b0c08f3a0b8176.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
require File.expand_path('../../../test_helper', __FILE__)
19

  
20
class RoutingSysTest < ActionController::IntegrationTest
21
  def test_sys
22
    assert_routing(
23
        { :method => 'get', :path => "/sys/projects" },
24
        { :controller => 'sys', :action => 'projects' }
25
      )
26
    assert_routing(
27
        { :method => 'post', :path => "/sys/projects/testid/repository" },
28
        { :controller => 'sys', :action => 'create_project_repository', :id => 'testid' }
29
      )
30
    assert_routing(
31
        { :method => 'get', :path => "/sys/fetch_changesets" },
32
        { :controller => 'sys', :action => 'fetch_changesets' }
33
      )
34
  end
35
end
.svn/pristine/0c/0cc9601ec1a6e3a27ab4a946d394cf4ba82254b4.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
class TimeEntryActivityCustomField < CustomField
19
  def type_name
20
    :enumeration_activities
21
  end
22
end
.svn/pristine/0c/0cd8ee527e2f2ff13b3817238dc6eed2ab240c57.svn-base
1
class <%= class_name %>Controller < ApplicationController
2
  unloadable
3

  
4
<% actions.each do |action| -%>
5

  
6
  def <%= action %>
7
  end
8
<% end -%>
9
end

Also available in: Unified diff