diff --git a/app/controllers/deliverables_controller.rb b/app/controllers/deliverables_controller.rb index bf819a7..ea66f7c 100644 --- a/app/controllers/deliverables_controller.rb +++ b/app/controllers/deliverables_controller.rb @@ -38,7 +38,6 @@ class DeliverablesController < ApplicationController # Action to preview the Deliverable description def preview @text = params[:deliverable][:description] - render :partial => 'common/preview' end # Saves a new Deliverable @@ -57,9 +56,9 @@ class DeliverablesController < ApplicationController if @deliverable.save @flash = l(:notice_successful_create) format.html { redirect_to :action => 'index' } - format.js { render :action => 'create.js.rjs'} + format.js else - format.js { render :action => 'create_error.js.rjs'} + format.js end end @@ -67,7 +66,7 @@ class DeliverablesController < ApplicationController # Builds the edit form for the Deliverable def edit - @deliverable = Deliverable.find_by_id_and_project_id(params[:deliverable_id], params[:id]) + @deliverable = Deliverable.find_by_id_and_project_id(params[:deliverable_id], @project.id) end # Updates an existing Deliverable, optionally changing it's type @@ -81,9 +80,9 @@ class DeliverablesController < ApplicationController respond_to do |format| if @deliverable.update_attributes(params[:deliverable]) @flash = l(:notice_successful_create) - format.html { redirect_to :action => 'index', :id => @project.id } + format.html { redirect_to :action => 'index', :id => @project.identifier } else - format.html { render :action => 'edit', :id => @project.id} + format.html { render :action => 'edit', :id => @project.identifier } end end @@ -98,7 +97,7 @@ class DeliverablesController < ApplicationController render_403 and return unless @deliverable.editable_by?(User.current) @deliverable.destroy flash[:notice] = l(:notice_successful_delete) - redirect_to :action => 'index', :id => @project.id + redirect_to :action => 'index', :id => @project.identifier end # Create a query in the session and redirects to the issue list with that query @@ -114,7 +113,7 @@ class DeliverablesController < ApplicationController session[:query] = {:project_id => @query.project_id, :filters => @query.filters} - redirect_to :controller => 'issues', :action => 'index', :project_id => @project.id + redirect_to :controller => 'issues', :action => 'index', :project_id => @project.identifier end # Assigns issues to the Deliverable based on their Version @@ -127,12 +126,12 @@ class DeliverablesController < ApplicationController number_updated = @deliverable.assign_issues_by_version(params[:version][:id]) flash[:notice] = l(:message_updated_issues, number_updated) - redirect_to :action => 'index', :id => @project.id + redirect_to :action => 'index', :id => @project.identifier end private def find_project - @project = Project.find(params[:id]) + @project = Project.where(:identifier => params[:id]).first || Project.find(params[:id]) end def get_settings @@ -152,13 +151,13 @@ class DeliverablesController < ApplicationController def sort_if_needed(deliverables) if session[@sort_name] && %w(score spent progress labor_budget).include?(session[@sort_name][:key]) case session[@sort_name][:key] - when "score": + when "score" then sorted = deliverables.sort {|a,b| a.score <=> b.score} - when "spent": + when "spent" then sorted = deliverables.sort {|a,b| a.spent <=> b.spent} - when "progress": + when "progress" then sorted = deliverables.sort {|a,b| a.progress <=> b.progress} - when "labor_budget": + when "labor_budget" then sorted = deliverables.sort {|a,b| a.labor_budget <=> b.labor_budget} end diff --git a/app/helpers/deliverables_helper.rb b/app/helpers/deliverables_helper.rb index ea563b2..562478e 100644 --- a/app/helpers/deliverables_helper.rb +++ b/app/helpers/deliverables_helper.rb @@ -5,7 +5,7 @@ module DeliverablesHelper # TODO Later: Refactor since observers are not used anymore def field_with_budget_observer_and_totals(form, object, field, percent_field, default_value='') content_tag(:tr, - content_tag(:td, "") + + content_tag(:td, "".html_safe) + content_tag(:td, number_or_percent_field(object, field, percent_field, default_value, :size => 7)) + content_tag(:td, content_tag(:span, @@ -15,27 +15,27 @@ module DeliverablesHelper ), :class => "calculation-column" )) - + end def number_or_percent_field(object, number_field, percent_field, default_value, options) # Build a text_field by hand named after the number field but with the percent_field and % as the value - return text_field_tag('deliverable_' + number_field.to_s, + return text_field_tag('deliverable_' + number_field.to_s, object.read_attribute(percent_field).to_s + "%", options.merge({ :name => "deliverable[#{number_field.to_s}]"})) unless object.read_attribute(percent_field).blank? - + # Number and fallback with no values value = object.read_attribute(number_field) || default_value || '' return text_field(:deliverable, number_field, options.merge({ :value => value})) end - + # Helper to generate a consistant HTML format for displaying basic data def paragraph_with_data(label, data) content_tag(:p, content_tag(:span, label, :class => 'title') + content_tag(:span, h(data), :class => 'data')) end - + def row_with_data(label, data, css_class='') content_tag(:tr, content_tag(:td, label, :class => 'title') + @@ -51,7 +51,7 @@ module DeliverablesHelper content_tag(:span, h(data1), :class => 'left-data') + content_tag(:span, h(data2), :class => 'right-data'), :class => 'fake-table')) - + end # Helper to generate a consistant HTML format for displaying basic data @@ -67,11 +67,11 @@ module DeliverablesHelper def allowed_management? return User.current.allowed_to?(:manage_budget, @project) end - + def l_field(field, prefix='') l((prefix + field.to_s).to_sym) end - + def toggle_arrows(deliverable_id) open_js = "expandRow(#{deliverable_id})" close_js = "collapseRow(#{deliverable_id})" @@ -79,7 +79,7 @@ module DeliverablesHelper return toggle_arrow(deliverable_id, "toggle-arrow-closed.gif", open_js, false) + toggle_arrow(deliverable_id, "toggle-arrow-open.gif", close_js, true) end - + def toggle_arrow(deliverable_id, image, js, hide=false) style = "display:none;" if hide style ||= '' @@ -89,9 +89,9 @@ module DeliverablesHelper :class => "toggle toggle_" + deliverable_id.to_s, :style => style ) - + end - + def number_or_percent(number_field, percent_field) return number_to_currency(number_field, :unit => l(:label_currency), :precision => 0) unless number_field.blank? return number_to_percentage(percent_field, :precision => 0) unless percent_field.blank? diff --git a/app/views/deliverables/_deliverable_description_row.html.erb b/app/views/deliverables/_deliverable_description_row.html.erb index 160aa20..3c207db 100644 --- a/app/views/deliverables/_deliverable_description_row.html.erb +++ b/app/views/deliverables/_deliverable_description_row.html.erb @@ -2,5 +2,5 @@
- <%= l(:message_budget_settings) %> + <%= l(:message_budget_settings).html_safe %>
diff --git a/assets/javascripts/budget.js b/assets/javascripts/budget.js index f8c77d9..c00af7a 100644 --- a/assets/javascripts/budget.js +++ b/assets/javascripts/budget.js @@ -1,8 +1,5 @@ /* Used to calculate the Budget */ -var BudgetModule = Class.create(); -Object.extend(BudgetModule.prototype, { - initialize: function () {}, - +var Budget = { toAmount: function(value) { var amount = value.replace(/[^1234567890.]/ig,''); if (amount) { @@ -13,66 +10,65 @@ Object.extend(BudgetModule.prototype, { }, updateAmounts: function() { - if ($('deliverable_type').checked) { + if ($('#deliverable_type').checked) { // Fixed cost - var cost = Budget.toAmount($('deliverable_fixed_cost').value); - Budget.updateAmount($('fixedCost'), cost); + var cost = Budget.toAmount($('#deliverable_fixed_cost').val()); + Budget.updateAmount($('#fixedCost'), cost); } else { // Variable cost - var perHour = Budget.toAmount($('deliverable_cost_per_hour').value); - var hours = Budget.toAmount($('deliverable_total_hours').value); + var perHour = Budget.toAmount($('#deliverable_cost_per_hour').val()); + var hours = Budget.toAmount($('#deliverable_total_hours').val()); var cost = perHour * hours; - Budget.updateAmount($('variableCost'), cost); + Budget.updateAmount($('#variableCost'), cost); } - if ($('deliverable_overhead').value.match('%')) { - var overhead_subtotal = (Budget.toAmount($('deliverable_overhead').value) / 100) * cost; + if ($('#deliverable_overhead').val().match('%')) { + var overhead_subtotal = (Budget.toAmount($('#deliverable_overhead').val()) / 100) * cost; } else { - var overhead_subtotal = Budget.toAmount($('deliverable_overhead').value); + var overhead_subtotal = Budget.toAmount($('#deliverable_overhead').val()); } - if ($('deliverable_materials').value.match('%')) { - var materials_subtotal = (Budget.toAmount($('deliverable_materials').value) / 100) * cost; + if ($('#deliverable_materials').val().match('%')) { + var materials_subtotal = (Budget.toAmount($('#deliverable_materials').val()) / 100) * cost; } else { - var materials_subtotal = Budget.toAmount($('deliverable_materials').value); + var materials_subtotal = Budget.toAmount($('#deliverable_materials').val()); } // Profit uses labor cost and overhead - if ($('deliverable_profit').value.match('%')) { - var profit_subtotal = (Budget.toAmount($('deliverable_profit').value) / 100) * (cost + overhead_subtotal); + if ($('#deliverable_profit').val().match('%')) { + var profit_subtotal = (Budget.toAmount($('#deliverable_profit').val()) / 100) * (cost + overhead_subtotal); } else { - var profit_subtotal = Budget.toAmount($('deliverable_profit').value); + var profit_subtotal = Budget.toAmount($('#deliverable_profit').val()); } // Amounts - Budget.updateAmount($('overhead_subtotal'), overhead_subtotal); - Budget.updateAmount($('materials_subtotal'), materials_subtotal); - Budget.updateAmount($('profit_subtotal'), profit_subtotal); + Budget.updateAmount($('#overhead_subtotal'), overhead_subtotal); + Budget.updateAmount($('#materials_subtotal'), materials_subtotal); + Budget.updateAmount($('#profit_subtotal'), profit_subtotal); var total = cost + overhead_subtotal + materials_subtotal + profit_subtotal; - $('deliverable_budget').value = total; - $('total-budget-calculation').innerHTML = Budget.number_to_currency(total); + $('#deliverable_budget').val(total); + $('#total-budget-calculation').html(Budget.number_to_currency(total)); }, updateAmount: function(element, value) { if (element) { - element.innerHTML = Budget.number_to_currency(value); + element.html(Budget.number_to_currency(value)); } }, changeType: function() { - if ($('deliverable_type').checked) { + if ($('#deliverable_type').checked) { // Fixed - $$('.budget-hourly').each(function(ele) { ele.hide(); }); - $$('.budget-fixed').each(function(ele) { ele.show(); }); + $('.budget-hourly').hide(); + $('.budget-fixed').show(); } else { // Variable - $$('.budget-hourly').each(function(ele) { ele.show(); }); - $$('.budget-fixed').each(function(ele) { ele.hide(); }); + $('.budget-hourly').show(); + $('.budget-fixed').hide(); } - Budget.updateAmounts(); }, // Rails-like number_to_currency currency formatting @@ -104,31 +100,20 @@ Object.extend(BudgetModule.prototype, { return number } } -}); -Budget = new BudgetModule(); +}; function toggleAll() { - $$('.deliverable-details').each(function(ele) { - ele.toggle(); - }); - $$('.toggle').each(function(e) { - e.toggle(); - }); + $('.deliverable-details, .toggle').toggle(); } - function expandRow(deliverable_id) { - $('deliverable-details-'+ deliverable_id).show(); - $('deliverable-description-'+ deliverable_id).show(); - $$('.toggle_' + deliverable_id).each(function(e) { - e.toggle(); - }); + $('#deliverable-details-'+ deliverable_id).show(); + $('#deliverable-description-'+ deliverable_id).show(); + $('.toggle_' + deliverable_id).toggle(); } function collapseRow(deliverable_id) { - $('deliverable-details-'+ deliverable_id).hide(); - $('deliverable-description-'+ deliverable_id).hide(); - $$('.toggle_' + deliverable_id).each(function(e) { - e.toggle(); - }); + $('#deliverable-details-'+ deliverable_id).hide(); + $('#deliverable-description-'+ deliverable_id).hide(); + $('.toggle_' + deliverable_id).toggle(); } diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml new file mode 100644 index 0000000..95af01a --- /dev/null +++ b/config/locales/pt-BR.yml @@ -0,0 +1,50 @@ +pt-BR: + budget_title: Orçamento + field_cost_per_hour: Custo por hora + field_total_hours: Total de horas + field_overhead: Despesas + label_overhead: "Despesas: " + field_materials: Custos com materiais + label_materials: "Materiais: " + field_profit: Lucro + field_budget: Orçamento Total + label_budget: "Orçamento Total: " + field_fixed_cost: Lance Fixo + field_project_manager_signoff: Assinatura do Gerente de Projeto + field_client_signoff: Assinatura do Cliente + field_deliverable: Produto + field_deliverable_subject: Produto + field_due: Data Prevista + label_member_rate: Custo (R$) + label_currency: R$ + message_updated_issues: Atualizou %d tarefas + message_budget_settings: Informe um valor total ou porcentagem em cada campo para definir o Total padrão. Use %% para porcentagens. + label_non_billable_overhead: Despesas não faturáveis + label_materials: Materiais + label_profit: Orçamento + label_new_deliverable: Novo produto + label_fixed_cost: Custo fixo + caption_due: Data prevista + caption_progress: Progresso + caption_subject: Assunto + caption_score: Classificacao + caption_budget: Orçamento + caption_labor_budget: Orçamento de Trabalho + caption_spent: Gasto + label_update_deliverable: Atualizar Produto + label_labor_budget: "Orçamento de Trabalho: " + label_labor_budget_spent: "Orçamento de Trabalho Gasto: " + label_labor_budget_remaining: "Orçamento de Trabalho Remanescente: " + label_progress: "Progresso: " + label_budget_score: "Classificacao do Orçamento: " + label_overruns: "Excedente: " + label_missing_on: Ausente no + label_next_due_date: "Proxima Data Prevista: " + label_completion: "Conclusao: " + label_potential_profit: "Lucro Potencial: " + label_bulk_assign: Atribuicao em massa + label_labor: "Trabalho: " + label_fixed_amount: "Montante Total: " + label_hours_estimated: "Horas Estimatadas: " + label_hours_used: "Horas Usadas: " + label_toggle_all: "Expandir todas as linhas de produtos" \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..9bdf86b --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,8 @@ +match '/projects/:id/deliverables/index', :to => "deliverables#index" +match '/projects/:id/deliverables/preview', :to => "deliverables#preview", :as => :preview_deliverable +match '/projects/:id/deliverables', :to => "deliverables#create", :via => "post", :as => :create_deliverable +match '/projects/:id/deliverables/:deliverable_id/edit', :to => "deliverables#edit", :via => "get", :as => :edit_deliverable +match '/projects/:id/deliverables/:deliverable_id', :to => "deliverables#update", :via => "put", :as => :update_deliverable +match '/projects/:id/deliverables/:deliverable_id/bulk_assign_issues', :to => "deliverables#bulk_assign_issues", :via => "post", :as => :bulk_assign_issues_deliverable +match '/projects/:id/deliverables/:deliverable_id/issues', :to => "deliverables#issues", :as => :issues_deliverable +match '/projects/:id/deliverables/:deliverable_id', :to => "deliverables#destroy", :via => "delete", :as => :destroy_deliverable \ No newline at end of file diff --git a/init.rb b/init.rb index c400da8..f9ea956 100644 --- a/init.rb +++ b/init.rb @@ -5,14 +5,13 @@ begin require 'rate' unless Object.const_defined?('Rate') rescue LoadError # rate_plugin is not installed - raise Exception.new("ERROR: The Rate plugin is not installed. Please install the Rate plugin from https://projects.littlestreamsoftware.com/projects/redmine-rate") + # raise Exception.new("ERROR: The Rate plugin is not installed. Please install the Rate plugin from https://projects.littlestreamsoftware.com/projects/redmine-rate") end # Patches to the Redmine core. -require 'dispatcher' require 'issue_patch' require 'query_patch' -Dispatcher.to_prepare do +ActionDispatch::Callbacks.to_prepare do Issue.send(:include, IssuePatch) unless Issue.included_modules.include? IssuePatch Query.send(:include, QueryPatch) unless Query.included_modules.include? QueryPatch end @@ -30,19 +29,19 @@ Redmine::Plugin.register :budget_plugin do version '0.2.0' requires_redmine :version_or_higher => '0.8.0' - + settings :default => { 'budget_nonbillable_overhead' => '', 'budget_materials' => '', 'budget_profit' => '' }, :partial => 'settings/budget_settings' - + project_module :budget_module do permission :view_budget, { :deliverables => [:index, :issues]} permission :manage_budget, { :deliverables => [:new, :edit, :create, :update, :destroy, :preview, :bulk_assign_issues]} end - - menu :project_menu, :budget, {:controller => "deliverables", :action => 'index'}, :caption => :budget_title + + menu :project_menu, :budget, {:controller => "deliverables", :action => 'index'}, :caption => :budget_title, :after => :activity, :param => :id end require 'redmine_budget/hooks/controller_timelog_available_criterias_hook'