3 Commits
Author SHA1 Message Date
Richard Říman b7e2e8ba86 fixed syntax error in fr.yml 2012-11-23 15:46:54 +01:00
Richard Říman f9906a563d Merge https://github.com/daviscabral/redmine-budget-plugin into rm2.x
Conflicts:
	app/controllers/deliverables_controller.rb
2012-11-23 15:06:54 +01:00
Davis Zanetti Cabral d041809113 Redmine 2.x support - Initial work 2012-10-23 02:02:28 -02:00
21 changed files with 180 additions and 142 deletions
+13 -14
View File
@@ -38,7 +38,6 @@ class DeliverablesController < ApplicationController
# Action to preview the Deliverable description # Action to preview the Deliverable description
def preview def preview
@text = params[:deliverable][:description] @text = params[:deliverable][:description]
render :partial => 'common/preview'
end end
# Saves a new Deliverable # Saves a new Deliverable
@@ -57,9 +56,9 @@ class DeliverablesController < ApplicationController
if @deliverable.save if @deliverable.save
@flash = l(:notice_successful_create) @flash = l(:notice_successful_create)
format.html { redirect_to :action => 'index' } format.html { redirect_to :action => 'index' }
format.js { render :action => 'create.js.rjs'} format.js
else else
format.js { render :action => 'create_error.js.rjs'} format.js
end end
end end
@@ -67,7 +66,7 @@ class DeliverablesController < ApplicationController
# Builds the edit form for the Deliverable # Builds the edit form for the Deliverable
def edit 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 end
# Updates an existing Deliverable, optionally changing it's type # Updates an existing Deliverable, optionally changing it's type
@@ -81,9 +80,9 @@ class DeliverablesController < ApplicationController
respond_to do |format| respond_to do |format|
if @deliverable.update_attributes(params[:deliverable]) if @deliverable.update_attributes(params[:deliverable])
@flash = l(:notice_successful_create) @flash = l(:notice_successful_create)
format.html { redirect_to :action => 'index', :id => @project.id } format.html { redirect_to :action => 'index', :id => @project.identifier }
else else
format.html { render :action => 'edit', :id => @project.id} format.html { render :action => 'edit', :id => @project.identifier }
end end
end end
@@ -98,7 +97,7 @@ class DeliverablesController < ApplicationController
render_403 and return unless @deliverable.editable_by?(User.current) render_403 and return unless @deliverable.editable_by?(User.current)
@deliverable.destroy @deliverable.destroy
flash[:notice] = l(:notice_successful_delete) flash[:notice] = l(:notice_successful_delete)
redirect_to :action => 'index', :id => @project.id redirect_to :action => 'index', :id => @project.identifier
end end
# Create a query in the session and redirects to the issue list with that query # 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} 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 end
# Assigns issues to the Deliverable based on their Version # 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]) number_updated = @deliverable.assign_issues_by_version(params[:version][:id])
flash[:notice] = l(:message_updated_issues, number_updated) flash[:notice] = l(:message_updated_issues, number_updated)
redirect_to :action => 'index', :id => @project.id redirect_to :action => 'index', :id => @project.identifier
end end
private private
def find_project def find_project
@project = Project.find(params[:id]) @project = Project.where(:identifier => params[:id]).first || Project.find(params[:id])
end end
def get_settings def get_settings
@@ -152,13 +151,13 @@ class DeliverablesController < ApplicationController
def sort_if_needed(deliverables) def sort_if_needed(deliverables)
if session[@sort_name] && %w(score spent progress labor_budget).include?(session[@sort_name][:key]) if session[@sort_name] && %w(score spent progress labor_budget).include?(session[@sort_name][:key])
case session[@sort_name][:key] case session[@sort_name][:key]
when "score": when "score" then
sorted = deliverables.sort {|a,b| a.score <=> b.score} sorted = deliverables.sort {|a,b| a.score <=> b.score}
when "spent": when "spent" then
sorted = deliverables.sort {|a,b| a.spent <=> b.spent} sorted = deliverables.sort {|a,b| a.spent <=> b.spent}
when "progress": when "progress" then
sorted = deliverables.sort {|a,b| a.progress <=> b.progress} 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} sorted = deliverables.sort {|a,b| a.labor_budget <=> b.labor_budget}
end end
+12 -12
View File
@@ -5,7 +5,7 @@ module DeliverablesHelper
# TODO Later: Refactor since observers are not used anymore # TODO Later: Refactor since observers are not used anymore
def field_with_budget_observer_and_totals(form, object, field, percent_field, default_value='') def field_with_budget_observer_and_totals(form, object, field, percent_field, default_value='')
content_tag(:tr, content_tag(:tr,
content_tag(:td, "<label for='deliverable_#{field.to_s}'>#{l_field(field, 'field_')}</label>") + content_tag(:td, "<label for='deliverable_#{field.to_s}'>#{l_field(field, 'field_')}</label>".html_safe) +
content_tag(:td, number_or_percent_field(object, field, percent_field, default_value, :size => 7)) + content_tag(:td, number_or_percent_field(object, field, percent_field, default_value, :size => 7)) +
content_tag(:td, content_tag(:td,
content_tag(:span, content_tag(:span,
@@ -15,27 +15,27 @@ module DeliverablesHelper
), ),
:class => "calculation-column" :class => "calculation-column"
)) ))
end end
def number_or_percent_field(object, number_field, percent_field, default_value, options) 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 # 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 + "%", object.read_attribute(percent_field).to_s + "%",
options.merge({ :name => "deliverable[#{number_field.to_s}]"})) unless object.read_attribute(percent_field).blank? options.merge({ :name => "deliverable[#{number_field.to_s}]"})) unless object.read_attribute(percent_field).blank?
# Number and fallback with no values # Number and fallback with no values
value = object.read_attribute(number_field) || default_value || '' value = object.read_attribute(number_field) || default_value || ''
return text_field(:deliverable, number_field, options.merge({ :value => value})) return text_field(:deliverable, number_field, options.merge({ :value => value}))
end end
# Helper to generate a consistant HTML format for displaying basic data # Helper to generate a consistant HTML format for displaying basic data
def paragraph_with_data(label, data) def paragraph_with_data(label, data)
content_tag(:p, content_tag(:p,
content_tag(:span, label, :class => 'title') + content_tag(:span, label, :class => 'title') +
content_tag(:span, h(data), :class => 'data')) content_tag(:span, h(data), :class => 'data'))
end end
def row_with_data(label, data, css_class='') def row_with_data(label, data, css_class='')
content_tag(:tr, content_tag(:tr,
content_tag(:td, label, :class => 'title') + content_tag(:td, label, :class => 'title') +
@@ -51,7 +51,7 @@ module DeliverablesHelper
content_tag(:span, h(data1), :class => 'left-data') + content_tag(:span, h(data1), :class => 'left-data') +
content_tag(:span, h(data2), :class => 'right-data'), content_tag(:span, h(data2), :class => 'right-data'),
:class => 'fake-table')) :class => 'fake-table'))
end end
# Helper to generate a consistant HTML format for displaying basic data # Helper to generate a consistant HTML format for displaying basic data
@@ -67,11 +67,11 @@ module DeliverablesHelper
def allowed_management? def allowed_management?
return User.current.allowed_to?(:manage_budget, @project) return User.current.allowed_to?(:manage_budget, @project)
end end
def l_field(field, prefix='') def l_field(field, prefix='')
l((prefix + field.to_s).to_sym) l((prefix + field.to_s).to_sym)
end end
def toggle_arrows(deliverable_id) def toggle_arrows(deliverable_id)
open_js = "expandRow(#{deliverable_id})" open_js = "expandRow(#{deliverable_id})"
close_js = "collapseRow(#{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) + return toggle_arrow(deliverable_id, "toggle-arrow-closed.gif", open_js, false) +
toggle_arrow(deliverable_id, "toggle-arrow-open.gif", close_js, true) toggle_arrow(deliverable_id, "toggle-arrow-open.gif", close_js, true)
end end
def toggle_arrow(deliverable_id, image, js, hide=false) def toggle_arrow(deliverable_id, image, js, hide=false)
style = "display:none;" if hide style = "display:none;" if hide
style ||= '' style ||= ''
@@ -89,9 +89,9 @@ module DeliverablesHelper
:class => "toggle toggle_" + deliverable_id.to_s, :class => "toggle toggle_" + deliverable_id.to_s,
:style => style :style => style
) )
end end
def number_or_percent(number_field, percent_field) 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_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? return number_to_percentage(percent_field, :precision => 0) unless percent_field.blank?
@@ -2,5 +2,5 @@
<td colspan="9" style="text-align: left;"> <td colspan="9" style="text-align: left;">
<%= l(:field_description) %>: <%= textilizable deliverable.description %> <%= l(:field_description) %>: <%= textilizable deliverable.description %>
</td> </td>
<%= Redmine::Hook.call_hook(:plugin_budget_view_deliverable_description_row, { :deliverable => deliverable }) %> <% Redmine::Hook.call_hook(:plugin_budget_view_deliverable_description_row, { :deliverable => deliverable }) %>
</tr> </tr>
@@ -1,12 +1,11 @@
<tr id="deliverable-details-<%= deliverable.id %>" class="deliverable deliverable-details <%= css %>" style="display:none;"> <tr id="deliverable-details-<%= deliverable.id %>" class="deliverable deliverable-details <%= css %>" style="display:none;">
<td class="deliverable-actions"> <td class="deliverable-actions">
<%= content_tag(:p,link_to(l(:button_edit), :action => 'edit', :id => @project.id, :deliverable_id => deliverable.id)) if allowed_management? -%> <%= content_tag(:p,link_to(l(:button_edit), :action => 'edit', :id => @project.identifier, :deliverable_id => deliverable.id)) if allowed_management? -%>
<%= content_tag(:p,link_to(l(:button_delete), { :action => 'destroy', :id => @project.id, :deliverable_id => deliverable.id}, :confirm => l(:text_are_you_sure))) if allowed_management? %> <%= content_tag(:p,link_to(l(:button_delete), { :action => 'destroy', :id => @project.identifier, :deliverable_id => deliverable.id}, :confirm => l(:text_are_you_sure))) if allowed_management? %>
<%= content_tag(:p,link_to(l(:label_issue_plural), :action => 'issues', :id => @project.id, :deliverable_id => deliverable.id)) -%> <%= content_tag(:p,link_to(l(:label_issue_plural), :action => 'issues', :id => @project.identifier, :deliverable_id => deliverable.id)) -%>
<% if allowed_management? && @project.versions.size > 0 %> <% if allowed_management? && @project.versions.size > 0 %>
<div> <div>
<% form_for :deliverable, deliverable, :url => { :action => "bulk_assign_issues", :id => @project.id, :deliverable_id => deliverable.id} do |f| %> <%= form_tag({ :action => "bulk_assign_issues", :id => @project.identifier, :deliverable_id => deliverable.id}) do %>
<%= select("version", "id", @project.versions.sort.collect {|v| [v.name, v.id ] }, { :prompt => '-- Version --' }) %><br /> <%= select("version", "id", @project.versions.sort.collect {|v| [v.name, v.id ] }, { :prompt => '-- Version --' }) %><br />
<%= submit_tag(l(:label_bulk_assign)) %> <%= submit_tag(l(:label_bulk_assign)) %>
<% end %> <% end %>
@@ -18,9 +17,8 @@
<table class="progress-table"> <table class="progress-table">
<%= row_with_double_data l(:label_progress), number_to_percentage(deliverable.progress, :precision => 0), '' %> <%= row_with_double_data l(:label_progress), number_to_percentage(deliverable.progress, :precision => 0), '' %>
<% if allowed_management? %> <% if allowed_management? %>
<% if deliverable.hourly? %> <% if deliverable.hourly? %>
<%= row_with_double_data l(:label_hours_estimated), number_with_precision(deliverable.total_hours, 0), '' %> <%= row_with_double_data l(:label_hours_estimated), number_with_precision(deliverable.total_hours, :precision => 0), '' %>
<% end %> <% end %>
<% if deliverable.fixed? %> <% if deliverable.fixed? %>
<%= row_with_double_data l(:label_fixed_amount), '', number_to_currency(deliverable.fixed_cost, :unit => l(:label_currency), :precision => 0) %> <%= row_with_double_data l(:label_fixed_amount), '', number_to_currency(deliverable.fixed_cost, :unit => l(:label_currency), :precision => 0) %>
@@ -61,5 +59,5 @@
<% end %> <% end %>
</table> </table>
</td> </td>
<%= Redmine::Hook.call_hook(:plugin_budget_view_deliverable_details_row, { :deliverable => deliverable }) %> <% Redmine::Hook.call_hook(:plugin_budget_view_deliverable_details_row, { :deliverable => deliverable }) %>
</tr> </tr>
@@ -11,5 +11,5 @@
<%= content_tag(:td, number_to_currency(deliverable.spent, :unit => l(:label_currency), :precision => 0), :class => 'spent') if allowed_management? %> <%= content_tag(:td, number_to_currency(deliverable.spent, :unit => l(:label_currency), :precision => 0), :class => 'spent') if allowed_management? %>
<%= content_tag(:td, format_date(deliverable.due), :class => 'due_date') %> <%= content_tag(:td, format_date(deliverable.due), :class => 'due_date') %>
<%= content_tag(:td, progress_bar(deliverable.progress, :width => '100%', :class => 'done_ratio')) %> <%= content_tag(:td, progress_bar(deliverable.progress, :width => '100%', :class => 'done_ratio')) %>
<%= Redmine::Hook.call_hook(:plugin_budget_view_deliverable_summary_row, { :deliverable => deliverable }) %> <% Redmine::Hook.call_hook(:plugin_budget_view_deliverable_summary_row, { :deliverable => deliverable }) %>
</tr> </tr>
+14 -12
View File
@@ -23,7 +23,11 @@
</td> </td>
<td> <td>
<%= check_box(:deliverable, :type, {}, FixedDeliverable.name, HourlyDeliverable.name) %> <%= check_box(:deliverable, :type, {}, FixedDeliverable.name, HourlyDeliverable.name) %>
<%= observe_field('deliverable_type', :function => "new Budget.changeType();") %> <script type="text/javascript">
$("#deliverable_type").change(function() {
new Budget.changeType();
});
</script>
</td> </td>
<td class="calculation-column"> <td class="calculation-column">
</td> </td>
@@ -75,12 +79,10 @@
<%= content_tag(:span, 0, :id => 'total-budget-calculation', :class => "budget-calculation") %> <%= content_tag(:span, 0, :id => 'total-budget-calculation', :class => "budget-calculation") %>
</td> </td>
</tr> </tr>
</table> </table>
<%= f.hidden_field :budget %> <%= f.hidden_field :budget %>
<%= observe_form('deliverable-form', :function => "new Budget.updateAmounts();", :on => 'blur') %>
</div> </div>
<script type="text/javascript">new Budget.changeType();</script> <script type="text/javascript">new Budget.changeType();</script>
<script type="text/javascript">new Budget.updateAmounts();</script> <script type="text/javascript">new Budget.updateAmounts();</script>
@@ -93,18 +95,18 @@
</div> </div>
<%= mode == :create ? submit_tag(l(:button_create)) : submit_tag(l(:button_update)) %> <%= mode == :create ? submit_tag(l(:button_create)) : submit_tag(l(:button_update)) %>
<%= link_to_remote l(:label_preview), <%= link_to l(:label_preview), preview_deliverable_path(:id => @project), :id => "budget_preview_link", :accesskey => accesskey(:preview) %>
{ :url => { :controller => 'deliverables', :action => 'preview', :id => @project }, <script type="text/javascript">
:method => 'post', $("#budget_preview_link").click(function() {
:update => 'preview', $.post($(this).attr("href"), $("#deliverable-form").serializeArray(), 'script');
:with => "Form.serialize('deliverable-form')", return false;
:complete => "Element.scrollTo('preview')" });
}, :accesskey => accesskey(:preview) %> </script>
<%# Same as `wikitoolbar_for 'deliverable_description'` but without the help link %> <%# Same as `wikitoolbar_for 'deliverable_description'` but without the help link %>
<%= javascript_include_tag('jstoolbar/jstoolbar') %> <%= javascript_include_tag('jstoolbar/jstoolbar') %>
<%= javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language}") %> <%= javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language}") %>
<%= javascript_tag("var toolbar = new jsToolBar($('deliverable_description'));toolbar.draw();") %> <%= javascript_tag("var toolbar = new jsToolBar($('#deliverable_description')[0]);toolbar.draw();") %>
<div id="preview" class="wiki"></div> <div id="preview" class="wiki"></div>
+1 -1
View File
@@ -9,7 +9,7 @@
<%= sort_header_tag("spent", :caption => l(:caption_spent)) if allowed_management? %> <%= sort_header_tag("spent", :caption => l(:caption_spent)) if allowed_management? %>
<%= sort_header_tag("#{Deliverable.table_name}.due", :caption => l(:caption_due)) %> <%= sort_header_tag("#{Deliverable.table_name}.due", :caption => l(:caption_due)) %>
<%= sort_header_tag("progress", :caption => l(:caption_progress)) %> <%= sort_header_tag("progress", :caption => l(:caption_progress)) %>
<%= Redmine::Hook.call_hook(:plugin_budget_view_deliverable_list_header, { }) %> <% Redmine::Hook.call_hook(:plugin_budget_view_deliverable_list_header, { }) %>
</tr></thead> </tr></thead>
<tbody> <tbody>
<% deliverables.each do |deliverable| -%> <% deliverables.each do |deliverable| -%>
+1 -1
View File
@@ -1,3 +1,3 @@
<h3><%= l(:budget_title) %></h3> <h3><%= l(:budget_title) %></h3>
<%= link_to_function l(:label_new_deliverable), "$('new-deliverable').toggle();" if allowed_management? %><br /> <%= link_to_function l(:label_new_deliverable), "$('#new-deliverable').toggle();" if allowed_management? %><br />
<%= link_to_function l(:label_toggle_all), "toggleAll();" if allowed_management? %><br /> <%= link_to_function l(:label_toggle_all), "toggleAll();" if allowed_management? %><br />
+24
View File
@@ -0,0 +1,24 @@
# If there is no deliverable list, refresh the page
if ($('#deliverable-list').length == 0) { document.location.reload() }
# Add deliverable to list
$("#deliverable-list").prepend("<%= escape_javascript render(:partial => 'deliverable', :locals => {:deliverable => @deliverable}) %>");
# Update budget
$('#budget-summary').html("<%= escape_javascript render(:partial => 'budget', :object => @budget) %>");
$("#budget-summary").effect("highlight", {}, 300);
# Remove errors if found
$("#errorExplanation").remove();
var form = $('#deliverable-form');
form.find('input:text, input:password, input:file, select, textarea').val('');
form.find('input:radio, input:checkbox').removeAttr('checked').removeAttr('selected');
Budget.updateAmounts();
# Add a fading out flash
$('#new-deliverable').before('<%= escape_javascript content_tag(:div, @flash, :class => "flash notice", :id => "rjs-flash") %>');
setTimeout(function() { $("#rjs-flash").effect("fade", {}, 300) }, 3000);
$("#preview").remove();
-26
View File
@@ -1,26 +0,0 @@
# If there is no deliverable list, refresh the page
page << "if ($('deliverable-list') == null) {document.location.reload()}"
# Add deliverable to list
page.insert_html :top, 'deliverable-list', :partial => 'deliverable', :locals => {:deliverable => @deliverable}
# Update budget
page.replace_html 'budget-summary', :partial => 'budget', :object => @budget
page.visual_effect :highlight, 'budget-summary'
# Remove errors if found
page.select('#errorExplanation').each do |value|
page.remove value
end
page << "Form.reset($('deliverable-form'))"
page << "Budget.updateAmounts()"
# Add a fading out flash
page.insert_html :before, 'new-deliverable', content_tag(:div, @flash, :class => "flash notice", :id => 'rjs-flash')
page.delay(3) do
page.visual_effect :fade, 'rjs-flash'
end
# Clear preview
page.replace_html 'preview', ''
@@ -0,0 +1,2 @@
$('#new-deliverable').html("<%= escape_javascript render(:partial => 'form') %>");
Budget.updateAmounts();
@@ -1,2 +0,0 @@
page.replace_html 'new-deliverable', :partial => 'form'
page << "Budget.updateAmounts()"
+2 -2
View File
@@ -1,6 +1,6 @@
<h2><%= l(:label_update_deliverable) %></h2> <h2><%= l(:label_update_deliverable) %></h2>
<% form_for :deliverable, @deliverable, :url => {:controller => 'deliverables', :action => 'update', :id => @project, :deliverable_id => @deliverable.id }, <%= form_for @deliverable, :url => {:controller => 'deliverables', :action => 'update', :id => @project, :deliverable_id => @deliverable.id },
:method => :post, :builder => TabularFormBuilder, :lang => current_language, :method => :put, :builder => Redmine::Views::LabelledFormBuilder, :lang => current_language,
:html => {:multipart => true, :id => 'deliverable-form', :class => 'tabular'} do |f| %> :html => {:multipart => true, :id => 'deliverable-form', :class => 'tabular'} do |f| %>
<%= render :partial => 'form', :locals => { :mode => :update, :f => f } %> <%= render :partial => 'form', :locals => { :mode => :update, :f => f } %>
+1 -3
View File
@@ -5,9 +5,7 @@
<% if allowed_management? %> <% if allowed_management? %>
<div id="new-deliverable" style="<%= @display_form ? '' : 'display:none;' -%>"> <div id="new-deliverable" style="<%= @display_form ? '' : 'display:none;' -%>">
<h2><%= l(:label_new_deliverable) %></h2> <h2><%= l(:label_new_deliverable) %></h2>
<% remote_form_for :deliverable, @deliverable, :url => {:controller => 'deliverables', :action => 'create', :id => @project }, <%= form_for @deliverable, :url => create_deliverable_path(params[:id]), :method => :post, :builder => Redmine::Views::LabelledFormBuilder, :remote => true, :lang => current_language, :html => {:multipart => true, :id => 'deliverable-form', :class => 'tabular'} do |f| %>
:method => :post, :builder => TabularFormBuilder, :lang => current_language,
:html => {:multipart => true, :id => 'deliverable-form', :class => 'tabular'} do |f| %>
<%= render :partial => 'form', :locals => { :mode => :create, :f => f } %> <%= render :partial => 'form', :locals => { :mode => :create, :f => f } %>
<% end %> <% end %>
</div> </div>
+1
View File
@@ -0,0 +1 @@
$("#preview").html("<%= escape_javascript render(:partial => 'common/preview') %>");
@@ -1,5 +1,5 @@
<p> <p>
<%= l(:message_budget_settings) %> <%= l(:message_budget_settings).html_safe %>
</p> </p>
<p> <p>
+35 -50
View File
@@ -1,8 +1,5 @@
/* Used to calculate the Budget */ /* Used to calculate the Budget */
var BudgetModule = Class.create(); var Budget = {
Object.extend(BudgetModule.prototype, {
initialize: function () {},
toAmount: function(value) { toAmount: function(value) {
var amount = value.replace(/[^1234567890.]/ig,''); var amount = value.replace(/[^1234567890.]/ig,'');
if (amount) { if (amount) {
@@ -13,66 +10,65 @@ Object.extend(BudgetModule.prototype, {
}, },
updateAmounts: function() { updateAmounts: function() {
if ($('deliverable_type').checked) { if ($('#deliverable_type').checked) {
// Fixed cost // Fixed cost
var cost = Budget.toAmount($('deliverable_fixed_cost').value); var cost = Budget.toAmount($('#deliverable_fixed_cost').val());
Budget.updateAmount($('fixedCost'), cost); Budget.updateAmount($('#fixedCost'), cost);
} else { } else {
// Variable cost // Variable cost
var perHour = Budget.toAmount($('deliverable_cost_per_hour').value); var perHour = Budget.toAmount($('#deliverable_cost_per_hour').val());
var hours = Budget.toAmount($('deliverable_total_hours').value); var hours = Budget.toAmount($('#deliverable_total_hours').val());
var cost = perHour * hours; var cost = perHour * hours;
Budget.updateAmount($('variableCost'), cost); Budget.updateAmount($('#variableCost'), cost);
} }
if ($('deliverable_overhead').value.match('%')) { if ($('#deliverable_overhead').val().match('%')) {
var overhead_subtotal = (Budget.toAmount($('deliverable_overhead').value) / 100) * cost; var overhead_subtotal = (Budget.toAmount($('#deliverable_overhead').val()) / 100) * cost;
} else { } else {
var overhead_subtotal = Budget.toAmount($('deliverable_overhead').value); var overhead_subtotal = Budget.toAmount($('#deliverable_overhead').val());
} }
if ($('deliverable_materials').value.match('%')) { if ($('#deliverable_materials').val().match('%')) {
var materials_subtotal = (Budget.toAmount($('deliverable_materials').value) / 100) * cost; var materials_subtotal = (Budget.toAmount($('#deliverable_materials').val()) / 100) * cost;
} else { } else {
var materials_subtotal = Budget.toAmount($('deliverable_materials').value); var materials_subtotal = Budget.toAmount($('#deliverable_materials').val());
} }
// Profit uses labor cost and overhead // Profit uses labor cost and overhead
if ($('deliverable_profit').value.match('%')) { if ($('#deliverable_profit').val().match('%')) {
var profit_subtotal = (Budget.toAmount($('deliverable_profit').value) / 100) * (cost + overhead_subtotal); var profit_subtotal = (Budget.toAmount($('#deliverable_profit').val()) / 100) * (cost + overhead_subtotal);
} else { } else {
var profit_subtotal = Budget.toAmount($('deliverable_profit').value); var profit_subtotal = Budget.toAmount($('#deliverable_profit').val());
} }
// Amounts // Amounts
Budget.updateAmount($('overhead_subtotal'), overhead_subtotal); Budget.updateAmount($('#overhead_subtotal'), overhead_subtotal);
Budget.updateAmount($('materials_subtotal'), materials_subtotal); Budget.updateAmount($('#materials_subtotal'), materials_subtotal);
Budget.updateAmount($('profit_subtotal'), profit_subtotal); Budget.updateAmount($('#profit_subtotal'), profit_subtotal);
var total = cost + overhead_subtotal + materials_subtotal + profit_subtotal; var total = cost + overhead_subtotal + materials_subtotal + profit_subtotal;
$('deliverable_budget').value = total; $('#deliverable_budget').val(total);
$('total-budget-calculation').innerHTML = Budget.number_to_currency(total); $('#total-budget-calculation').html(Budget.number_to_currency(total));
}, },
updateAmount: function(element, value) { updateAmount: function(element, value) {
if (element) { if (element) {
element.innerHTML = Budget.number_to_currency(value); element.html(Budget.number_to_currency(value));
} }
}, },
changeType: function() { changeType: function() {
if ($('deliverable_type').checked) { if ($('#deliverable_type').checked) {
// Fixed // Fixed
$$('.budget-hourly').each(function(ele) { ele.hide(); }); $('.budget-hourly').hide();
$$('.budget-fixed').each(function(ele) { ele.show(); }); $('.budget-fixed').show();
} else { } else {
// Variable // Variable
$$('.budget-hourly').each(function(ele) { ele.show(); }); $('.budget-hourly').show();
$$('.budget-fixed').each(function(ele) { ele.hide(); }); $('.budget-fixed').hide();
} }
Budget.updateAmounts(); Budget.updateAmounts();
}, },
// Rails-like number_to_currency currency formatting // Rails-like number_to_currency currency formatting
@@ -104,31 +100,20 @@ Object.extend(BudgetModule.prototype, {
return number return number
} }
} }
}); };
Budget = new BudgetModule();
function toggleAll() { function toggleAll() {
$$('.deliverable-details').each(function(ele) { $('.deliverable-details, .toggle').toggle();
ele.toggle();
});
$$('.toggle').each(function(e) {
e.toggle();
});
} }
function expandRow(deliverable_id) { function expandRow(deliverable_id) {
$('deliverable-details-'+ deliverable_id).show(); $('#deliverable-details-'+ deliverable_id).show();
$('deliverable-description-'+ deliverable_id).show(); $('#deliverable-description-'+ deliverable_id).show();
$$('.toggle_' + deliverable_id).each(function(e) { $('.toggle_' + deliverable_id).toggle();
e.toggle();
});
} }
function collapseRow(deliverable_id) { function collapseRow(deliverable_id) {
$('deliverable-details-'+ deliverable_id).hide(); $('#deliverable-details-'+ deliverable_id).hide();
$('deliverable-description-'+ deliverable_id).hide(); $('#deliverable-description-'+ deliverable_id).hide();
$$('.toggle_' + deliverable_id).each(function(e) { $('.toggle_' + deliverable_id).toggle();
e.toggle();
});
} }
+1 -1
View File
@@ -17,7 +17,7 @@ fr:
field_due: "Date d'echeance" field_due: "Date d'echeance"
label_member_rate: Tarif (€) label_member_rate: Tarif (€)
label_currency: € label_currency: €
message_updated_issues: %d demandes mises à jour message_updated_issues: "%d demandes mises à jour"
message_budget_settings: Entrez un montant en euros ou un pourcentage dans chaque champs pour régler le montant par defaut. Utilisez <strong>%%</strong> dans le champ pour des pourcentages. message_budget_settings: Entrez un montant en euros ou un pourcentage dans chaque champs pour régler le montant par defaut. Utilisez <strong>%%</strong> dans le champ pour des pourcentages.
label_non_billable_overhead: Frais géneraux non facturables label_non_billable_overhead: Frais géneraux non facturables
label_materials: Matières premières label_materials: Matières premières
+50
View File
@@ -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 <strong>%%</strong> 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"
+8
View File
@@ -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
+6 -7
View File
@@ -5,14 +5,13 @@ begin
require 'rate' unless Object.const_defined?('Rate') require 'rate' unless Object.const_defined?('Rate')
rescue LoadError rescue LoadError
# rate_plugin is not installed # 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 end
# Patches to the Redmine core. # Patches to the Redmine core.
require 'dispatcher'
require 'issue_patch' require 'issue_patch'
require 'query_patch' require 'query_patch'
Dispatcher.to_prepare do ActionDispatch::Callbacks.to_prepare do
Issue.send(:include, IssuePatch) unless Issue.included_modules.include? IssuePatch Issue.send(:include, IssuePatch) unless Issue.included_modules.include? IssuePatch
Query.send(:include, QueryPatch) unless Query.included_modules.include? QueryPatch Query.send(:include, QueryPatch) unless Query.included_modules.include? QueryPatch
end end
@@ -30,19 +29,19 @@ Redmine::Plugin.register :budget_plugin do
version '0.2.0' version '0.2.0'
requires_redmine :version_or_higher => '0.8.0' requires_redmine :version_or_higher => '0.8.0'
settings :default => { settings :default => {
'budget_nonbillable_overhead' => '', 'budget_nonbillable_overhead' => '',
'budget_materials' => '', 'budget_materials' => '',
'budget_profit' => '' 'budget_profit' => ''
}, :partial => 'settings/budget_settings' }, :partial => 'settings/budget_settings'
project_module :budget_module do project_module :budget_module do
permission :view_budget, { :deliverables => [:index, :issues]} permission :view_budget, { :deliverables => [:index, :issues]}
permission :manage_budget, { :deliverables => [:new, :edit, :create, :update, :destroy, :preview, :bulk_assign_issues]} permission :manage_budget, { :deliverables => [:new, :edit, :create, :update, :destroy, :preview, :bulk_assign_issues]}
end 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 end
require 'redmine_budget/hooks/controller_timelog_available_criterias_hook' require 'redmine_budget/hooks/controller_timelog_available_criterias_hook'