Mercurial > hg > soundsoftware-site
comparison app/models/project.rb @ 1517:dffacf8a6908 redmine-2.5
Update to Redmine SVN revision 13367 on 2.5-stable branch
author | Chris Cannam |
---|---|
date | Tue, 09 Sep 2014 09:29:00 +0100 |
parents | e248c7af89ec |
children | a1bdbf8a87d5 |
comparison
equal
deleted
inserted
replaced
1516:b450a9d58aed | 1517:dffacf8a6908 |
---|---|
37 has_many :enabled_modules, :dependent => :delete_all | 37 has_many :enabled_modules, :dependent => :delete_all |
38 has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position" | 38 has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position" |
39 has_many :issues, :dependent => :destroy, :include => [:status, :tracker] | 39 has_many :issues, :dependent => :destroy, :include => [:status, :tracker] |
40 has_many :issue_changes, :through => :issues, :source => :journals | 40 has_many :issue_changes, :through => :issues, :source => :journals |
41 has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC" | 41 has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC" |
42 has_many :time_entries, :dependent => :delete_all | 42 has_many :time_entries, :dependent => :destroy |
43 has_many :queries, :class_name => 'IssueQuery', :dependent => :delete_all | 43 has_many :queries, :class_name => 'IssueQuery', :dependent => :delete_all |
44 has_many :documents, :dependent => :destroy | 44 has_many :documents, :dependent => :destroy |
45 has_many :news, :dependent => :destroy, :include => :author | 45 has_many :news, :dependent => :destroy, :include => :author |
46 has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name" | 46 has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name" |
47 has_many :boards, :dependent => :destroy, :order => "position ASC" | 47 has_many :boards, :dependent => :destroy, :order => "position ASC" |
54 :class_name => 'IssueCustomField', | 54 :class_name => 'IssueCustomField', |
55 :order => "#{CustomField.table_name}.position", | 55 :order => "#{CustomField.table_name}.position", |
56 :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", | 56 :join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", |
57 :association_foreign_key => 'custom_field_id' | 57 :association_foreign_key => 'custom_field_id' |
58 | 58 |
59 acts_as_nested_set :order => 'name', :dependent => :destroy | 59 acts_as_nested_set :dependent => :destroy |
60 acts_as_attachable :view_permission => :view_files, | 60 acts_as_attachable :view_permission => :view_files, |
61 :delete_permission => :manage_files | 61 :delete_permission => :manage_files |
62 | 62 |
63 acts_as_customizable | 63 acts_as_customizable |
64 acts_as_searchable :columns => ['name', 'identifier', 'description'], :project_key => 'id', :permission => nil | 64 acts_as_searchable :columns => ['name', 'identifier', 'description'], :project_key => 'id', :permission => nil |
247 # | 247 # |
248 # This will raise a ActiveRecord::Rollback if the TimeEntryActivity | 248 # This will raise a ActiveRecord::Rollback if the TimeEntryActivity |
249 # does not successfully save. | 249 # does not successfully save. |
250 def create_time_entry_activity_if_needed(activity) | 250 def create_time_entry_activity_if_needed(activity) |
251 if activity['parent_id'] | 251 if activity['parent_id'] |
252 | |
253 parent_activity = TimeEntryActivity.find(activity['parent_id']) | 252 parent_activity = TimeEntryActivity.find(activity['parent_id']) |
254 activity['name'] = parent_activity.name | 253 activity['name'] = parent_activity.name |
255 activity['position'] = parent_activity.position | 254 activity['position'] = parent_activity.position |
256 | |
257 if Enumeration.overridding_change?(activity, parent_activity) | 255 if Enumeration.overridding_change?(activity, parent_activity) |
258 project_activity = self.time_entry_activities.create(activity) | 256 project_activity = self.time_entry_activities.create(activity) |
259 | |
260 if project_activity.new_record? | 257 if project_activity.new_record? |
261 raise ActiveRecord::Rollback, "Overridding TimeEntryActivity was not successfully saved" | 258 raise ActiveRecord::Rollback, "Overridding TimeEntryActivity was not successfully saved" |
262 else | 259 else |
263 self.time_entries.update_all("activity_id = #{project_activity.id}", ["activity_id = ?", parent_activity.id]) | 260 self.time_entries. |
261 where(["activity_id = ?", parent_activity.id]). | |
262 update_all("activity_id = #{project_activity.id}") | |
264 end | 263 end |
265 end | 264 end |
266 end | 265 end |
267 end | 266 end |
268 | 267 |
420 # Used in BuildProjectsTree migration | 419 # Used in BuildProjectsTree migration |
421 def self.rebuild_tree! | 420 def self.rebuild_tree! |
422 transaction do | 421 transaction do |
423 update_all "lft = NULL, rgt = NULL" | 422 update_all "lft = NULL, rgt = NULL" |
424 rebuild!(false) | 423 rebuild!(false) |
424 all.each { |p| p.set_or_update_position_under(p.parent) } | |
425 end | 425 end |
426 end | 426 end |
427 | 427 |
428 # Returns an array of the trackers used by the project and its active sub projects | 428 # Returns an array of the trackers used by the project and its active sub projects |
429 def rolled_up_trackers | 429 def rolled_up_trackers |
438 end | 438 end |
439 | 439 |
440 # Closes open and locked project versions that are completed | 440 # Closes open and locked project versions that are completed |
441 def close_completed_versions | 441 def close_completed_versions |
442 Version.transaction do | 442 Version.transaction do |
443 versions.where(:status => %w(open locked)).all.each do |version| | 443 versions.where(:status => %w(open locked)).each do |version| |
444 if version.completed? | 444 if version.completed? |
445 version.update_attribute(:status, 'closed') | 445 version.update_attribute(:status, 'closed') |
446 end | 446 end |
447 end | 447 end |
448 end | 448 end |
478 end | 478 end |
479 end | 479 end |
480 | 480 |
481 # Returns a hash of project users grouped by role | 481 # Returns a hash of project users grouped by role |
482 def users_by_role | 482 def users_by_role |
483 members.includes(:user, :roles).all.inject({}) do |h, m| | 483 members.includes(:user, :roles).inject({}) do |h, m| |
484 m.roles.each do |r| | 484 m.roles.each do |r| |
485 h[r] ||= [] | 485 h[r] ||= [] |
486 h[r] << m.user | 486 h[r] << m.user |
487 end | 487 end |
488 h | 488 h |
620 else | 620 else |
621 allowed_permissions.include? action | 621 allowed_permissions.include? action |
622 end | 622 end |
623 end | 623 end |
624 | 624 |
625 def module_enabled?(module_name) | 625 # Return the enabled module with the given name |
626 module_name = module_name.to_s | 626 # or nil if the module is not enabled for the project |
627 enabled_modules.detect {|m| m.name == module_name} | 627 def enabled_module(name) |
628 name = name.to_s | |
629 enabled_modules.detect {|m| m.name == name} | |
630 end | |
631 | |
632 # Return true if the module with the given name is enabled | |
633 def module_enabled?(name) | |
634 enabled_module(name).present? | |
628 end | 635 end |
629 | 636 |
630 def enabled_module_names=(module_names) | 637 def enabled_module_names=(module_names) |
631 if module_names && module_names.is_a?(Array) | 638 if module_names && module_names.is_a?(Array) |
632 module_names = module_names.collect(&:to_s).reject(&:blank?) | 639 module_names = module_names.collect(&:to_s).reject(&:blank?) |
849 version.update_attribute :status, 'open' | 856 version.update_attribute :status, 'open' |
850 end | 857 end |
851 | 858 |
852 # Get issues sorted by root_id, lft so that parent issues | 859 # Get issues sorted by root_id, lft so that parent issues |
853 # get copied before their children | 860 # get copied before their children |
854 project.issues.reorder('root_id, lft').all.each do |issue| | 861 project.issues.reorder('root_id, lft').each do |issue| |
855 new_issue = Issue.new | 862 new_issue = Issue.new |
856 new_issue.copy_from(issue, :subtasks => false, :link => false) | 863 new_issue.copy_from(issue, :subtasks => false, :link => false) |
857 new_issue.project = self | 864 new_issue.project = self |
858 # Changing project resets the custom field values | 865 # Changing project resets the custom field values |
859 # TODO: handle this in Issue#project= | 866 # TODO: handle this in Issue#project= |
993 end | 1000 end |
994 end | 1001 end |
995 | 1002 |
996 # Returns the systemwide active activities merged with the project specific overrides | 1003 # Returns the systemwide active activities merged with the project specific overrides |
997 def system_activities_and_project_overrides(include_inactive=false) | 1004 def system_activities_and_project_overrides(include_inactive=false) |
998 if include_inactive | 1005 t = TimeEntryActivity.table_name |
999 return TimeEntryActivity.shared. | 1006 scope = TimeEntryActivity.where( |
1000 where("id NOT IN (?)", self.time_entry_activities.collect(&:parent_id)).all + | 1007 "(#{t}.project_id IS NULL AND #{t}.id NOT IN (?)) OR (#{t}.project_id = ?)", |
1001 self.time_entry_activities | 1008 time_entry_activities.map(&:parent_id), id |
1002 else | 1009 ) |
1003 return TimeEntryActivity.shared.active. | 1010 unless include_inactive |
1004 where("id NOT IN (?)", self.time_entry_activities.collect(&:parent_id)).all + | 1011 scope = scope.active |
1005 self.time_entry_activities.active | 1012 end |
1006 end | 1013 scope |
1007 end | 1014 end |
1008 | 1015 |
1009 # Archives subprojects recursively | 1016 # Archives subprojects recursively |
1010 def archive! | 1017 def archive! |
1011 children.each do |subproject| | 1018 children.each do |subproject| |
1015 end | 1022 end |
1016 | 1023 |
1017 def update_position_under_parent | 1024 def update_position_under_parent |
1018 set_or_update_position_under(parent) | 1025 set_or_update_position_under(parent) |
1019 end | 1026 end |
1027 | |
1028 public | |
1020 | 1029 |
1021 # Inserts/moves the project so that target's children or root projects stay alphabetically sorted | 1030 # Inserts/moves the project so that target's children or root projects stay alphabetically sorted |
1022 def set_or_update_position_under(target_parent) | 1031 def set_or_update_position_under(target_parent) |
1023 parent_was = parent | 1032 parent_was = parent |
1024 sibs = (target_parent.nil? ? self.class.roots : target_parent.children) | 1033 sibs = (target_parent.nil? ? self.class.roots : target_parent.children) |