Feature #1953 ยป issue_1953.diff
| app/controllers/issues_controller.rb | ||
|---|---|---|
| 14 | 14 | # You should have received a copy of the GNU General Public License | 
| 15 | 15 | # along with this program; if not, write to the Free Software | 
| 16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
| 17 | require 'date' | |
| 17 | 18 | |
| 18 | 19 | class IssuesController < ApplicationController | 
| 19 | 20 | menu_item :new_issue, :only => :new | 
| ... | ... | |
| 168 | 169 | UPDATABLE_ATTRS_ON_TRANSITION = %w(status_id assigned_to_id fixed_version_id done_ratio) unless const_defined?(:UPDATABLE_ATTRS_ON_TRANSITION) | 
| 169 | 170 |  | 
| 170 | 171 | def edit | 
| 172 | if ! manage_issue_due_date params | |
| 173 | flash[:error] = l(:error_update_due_date_fields_required) | |
| 174 |       redirect_to(params[:back_to] || {:action => 'show', :id => @issue}) and return | |
| 175 | end | |
| 176 | ||
| 171 | 177 | @allowed_statuses = @issue.new_statuses_allowed_to(User.current) | 
| 172 | 178 | @priorities = IssuePriority.all | 
| 173 | 179 | @edit_allowed = User.current.allowed_to?(:edit_issues, @project) | 
| ... | ... | |
| 459 | 465 | end | 
| 460 | 466 |  | 
| 461 | 467 | private | 
| 468 | def manage_issue_due_date(params) | |
| 469 | if params[:issue][:update_due_date_based_on_estimated_hours].to_i == 1 | |
| 470 | if params[:issue][:estimated_hours].blank? or params[:issue][:start_date].blank? | |
| 471 | return false | |
| 472 | else | |
| 473 | additional_days = 0 | |
| 474 | if params[:issue][:estimated_hours].to_f % Setting.hours_in_work_day.to_f != 0 && params[:issue][:estimated_hours].to_f > Setting.hours_in_work_day.to_f | |
| 475 | additional_days += 1 | |
| 476 | end | |
| 477 | work_days_needed = (params[:issue][:estimated_hours].to_f / Setting.hours_in_work_day.to_f).to_i | |
| 478 | work_days_needed += additional_days | |
| 479 | params[:issue][:due_date] = (Date.parse(params[:issue][:start_date]) + work_days_needed-1) | |
| 480 | ||
| 481 | # In the span from start date to due date, add additional days for every non-work day | |
| 482 | number_of_non_work_days = 0 | |
| 483 | (Date.parse(params[:issue][:start_date])..params[:issue][:due_date]).each do |date| | |
| 484 | if ! Setting.days_in_work_week.include?(Date::DAYNAMES[date.wday].downcase) | |
| 485 | number_of_non_work_days += 1 | |
| 486 | end | |
| 487 | end | |
| 488 | params[:issue][:due_date] = params[:issue][:due_date] + number_of_non_work_days | |
| 489 | # Now make sure our end date isn't a non-work day... | |
| 490 | while ! Setting.days_in_work_week.include?(Date::DAYNAMES[params[:issue][:due_date].wday].downcase) | |
| 491 | params[:issue][:due_date] = params[:issue][:due_date] + 1 | |
| 492 | end | |
| 493 |         params[:issue][:due_date] = params[:issue][:due_date].strftime('%Y-%m-%d') | |
| 494 | end | |
| 495 | end | |
| 496 | ||
| 497 | return true | |
| 498 | end | |
| 499 | ||
| 462 | 500 | def find_issue | 
| 463 | 501 | @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category]) | 
| 464 | 502 | @project = @issue.project | 
| app/models/issue.rb | ||
|---|---|---|
| 60 | 60 | |
| 61 | 61 | before_save :update_done_ratio_from_issue_status | 
| 62 | 62 | after_save :create_journal | 
| 63 | ||
| 64 | attr_accessor :update_due_date_based_on_estimated_hours | |
| 63 | 65 |  | 
| 64 | 66 | # Returns true if usr or current user is allowed to view the issue | 
| 65 | 67 | def visible?(usr=nil) | 
| app/views/issues/_attributes.rhtml | ||
|---|---|---|
| 34 | 34 | <p><%= f.text_field :start_date, :size => 10 %><%= calendar_for('issue_start_date') %></p> | 
| 35 | 35 | <p><%= f.text_field :due_date, :size => 10 %><%= calendar_for('issue_due_date') %></p> | 
| 36 | 36 | <p><%= f.text_field :estimated_hours, :size => 3 %> <%= l(:field_hours) %></p> | 
| 37 | <p><%= f.check_box :update_due_date_based_on_estimated_hours %></p> | |
| 37 | 38 | <% if Issue.use_field_for_done_ratio? %> | 
| 38 | 39 | <p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p> | 
| 39 | 40 | <% end %> | 
| app/views/settings/_issues.rhtml | ||
|---|---|---|
| 15 | 15 | <%= select_tag 'settings[issue_done_ratio]', | 
| 16 | 16 | 								options_for_select(Issue::DONE_RATIO_OPTIONS.collect {|i| [l("setting_issue_done_ratio_#{i}"), i]}, Setting.issue_done_ratio) %></p> | 
| 17 | 17 | |
| 18 | <p><label><%= l(:setting_hours_in_work_day) %></label> | |
| 19 | <%= text_field_tag 'settings[hours_in_work_day]', Setting.hours_in_work_day, :size => 2 %></p> | |
| 20 | ||
| 18 | 21 | <p><label><%= l(:setting_issues_export_limit) %></label> | 
| 19 | 22 | <%= text_field_tag 'settings[issues_export_limit]', Setting.issues_export_limit, :size => 6 %></p> | 
| 20 | 23 | </div> | 
| 21 | 24 | |
| 25 | <fieldset class="box settings"><legend><%= l(:setting_days_in_work_week) %></legend> | |
| 26 | <%= hidden_field_tag 'settings[days_in_work_week][]', '' %> | |
| 27 | <% l('date.day_names').map{|d| d.downcase}.each do |day| %> | |
| 28 | <label><%= check_box_tag 'settings[days_in_work_week][]', day, Setting.days_in_work_week.include?(day) %> | |
| 29 | <%= day.capitalize %></label><br /> | |
| 30 | <% end %> | |
| 31 | </fieldset> | |
| 32 | ||
| 22 | 33 | <fieldset class="box settings"><legend><%= l(:setting_issue_list_default_columns) %></legend> | 
| 23 | 34 | <%= hidden_field_tag 'settings[issue_list_default_columns][]', '' %> | 
| 24 | 35 | <% Query.new.available_columns.each do |column| %> | 
| config/locales/en.yml | ||
|---|---|---|
| 161 | 161 | error_issue_done_ratios_not_updated: "Issue done ratios not updated." | 
| 162 | 162 | error_workflow_copy_source: 'Please select a source tracker or role' | 
| 163 | 163 | error_workflow_copy_target: 'Please select target tracker(s) and role(s)' | 
| 164 | error_update_due_date_fields_required: Start date and estimated time are required in order to update due date based on estimated hours. | |
| 164 | 165 |  | 
| 165 | 166 |   warning_attachments_not_saved: "{{count}} file(s) could not be saved." | 
| 166 | 167 |  | 
| ... | ... | |
| 272 | 273 | field_content: Content | 
| 273 | 274 | field_group_by: Group results by | 
| 274 | 275 | field_sharing: Sharing | 
| 276 | field_update_due_date_based_on_estimated_hours: Update Due Date Based On Estimated Hours | |
| 275 | 277 |  | 
| 276 | 278 | setting_app_title: Application title | 
| 277 | 279 | setting_app_subtitle: Application subtitle | 
| ... | ... | |
| 323 | 325 | setting_issue_done_ratio_issue_field: Use the issue field | 
| 324 | 326 | setting_issue_done_ratio_issue_status: Use the issue status | 
| 325 | 327 | setting_start_of_week: Start calendars on | 
| 328 | setting_hours_in_work_day: Hours in work day | |
| 329 | setting_days_in_work_week: Days in work week | |
| 326 | 330 |  | 
| 327 | 331 | permission_add_project: Create project | 
| 328 | 332 | permission_edit_project: Edit project | 
| config/settings.yml | ||
|---|---|---|
| 118 | 118 | default: 0 | 
| 119 | 119 | mail_handler_api_key: | 
| 120 | 120 | default: | 
| 121 | days_in_work_week: | |
| 122 | default: | |
| 123 | - monday | |
| 124 | - tuesday | |
| 125 | - wednesday | |
| 126 | - thursday | |
| 127 | - friday | |
| 121 | 128 | issue_list_default_columns: | 
| 122 | 129 | serialized: true | 
| 123 | 130 | default: | 
| ... | ... | |
| 131 | 138 | default: 1 | 
| 132 | 139 | issue_done_ratio: | 
| 133 | 140 | default: 'issue_field' | 
| 141 | hours_in_work_day: | |
| 142 | default: 8 | |
| 134 | 143 | default_projects_public: | 
| 135 | 144 | default: 1 | 
| 136 | 145 | default_projects_modules: |