diff --git a/app/controllers/deliverables_controller.rb b/app/controllers/deliverables_controller.rb
index 8b532a9..bf819a7 100644
--- a/app/controllers/deliverables_controller.rb
+++ b/app/controllers/deliverables_controller.rb
@@ -13,8 +13,8 @@ class DeliverablesController < ApplicationController
@deliverable_count = Deliverable.count(:conditions => { :project_id => @project.id})
@deliverable_pages = Paginator.new self, @deliverable_count, per_page_option, params['page']
- @deliverables = Deliverable.find(:all,
- {
+ @deliverables = Deliverable.find(:all,
+ {
:conditions => { :project_id => @project.id},
:limit => per_page_option,
:offset => @deliverable_pages.current.offset
@@ -22,7 +22,7 @@ class DeliverablesController < ApplicationController
)
@deliverables = sort_if_needed @deliverables
-
+
@deliverable = Deliverable.new
@budget = Budget.new(@project.id)
@@ -32,14 +32,15 @@ class DeliverablesController < ApplicationController
respond_to do |format|
format.html { render :action => 'index', :layout => !request.xhr? }
end
+
end
-
+
# Action to preview the Deliverable description
def preview
@text = params[:deliverable][:description]
render :partial => 'common/preview'
end
-
+
# Saves a new Deliverable
def create
if params[:deliverable][:type] == FixedDeliverable.name
@@ -49,7 +50,7 @@ class DeliverablesController < ApplicationController
else
@deliverable = Deliverable.new(params[:deliverable])
end
-
+
@deliverable.project = @project
@budget = Budget.new(@project.id)
respond_to do |format|
@@ -72,11 +73,11 @@ class DeliverablesController < ApplicationController
# Updates an existing Deliverable, optionally changing it's type
def update
@deliverable = Deliverable.find(params[:deliverable_id])
-
+
if params[:deliverable][:type] != @deliverable.class
@deliverable = @deliverable.change_type(params[:deliverable][:type])
end
-
+
respond_to do |format|
if @deliverable.update_attributes(params[:deliverable])
@flash = l(:notice_successful_create)
@@ -86,20 +87,20 @@ class DeliverablesController < ApplicationController
end
end
-
+
end
-
+
# Removes the Deliverable
def destroy
@deliverable = Deliverable.find_by_id_and_project_id(params[:deliverable_id], @project.id)
-
+
render_404 and return unless @deliverable
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
end
-
+
# Create a query in the session and redirects to the issue list with that query
def issues
@query = Query.new(:name => "_")
@@ -115,25 +116,25 @@ class DeliverablesController < ApplicationController
redirect_to :controller => 'issues', :action => 'index', :project_id => @project.id
end
-
+
# Assigns issues to the Deliverable based on their Version
def bulk_assign_issues
@deliverable = Deliverable.find_by_id_and_project_id(params[:deliverable_id], @project.id)
-
+
render_404 and return unless @deliverable
render_403 and return unless @deliverable.editable_by?(User.current)
-
+
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
end
-
+
private
def find_project
@project = Project.find(params[:id])
end
-
+
def get_settings
@settings = Setting.plugin_budget_plugin
end
@@ -146,7 +147,7 @@ class DeliverablesController < ApplicationController
return { :order => sort_clause }
end
end
-
+
# Sort +deliverables+ manually using the virtual fields
def sort_if_needed(deliverables)
if session[@sort_name] && %w(score spent progress labor_budget).include?(session[@sort_name][:key])
@@ -167,5 +168,4 @@ class DeliverablesController < ApplicationController
return deliverables
end
end
-
end
diff --git a/app/views/deliverables/index.html.erb b/app/views/deliverables/index.html.erb
index aa0c280..28f69d5 100644
--- a/app/views/deliverables/index.html.erb
+++ b/app/views/deliverables/index.html.erb
@@ -6,7 +6,7 @@
<%= l(:label_new_deliverable) %>
<% remote_form_for :deliverable, @deliverable, :url => {:controller => 'deliverables', :action => 'create', :id => @project },
- :method => :post, :builder => TabularFormBuilder, :lang => 'cs',
+ :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 } %>
<% end %>
@@ -28,5 +28,147 @@
<% content_for :header_tags do %>
<%= stylesheet_link_tag "budget.css", :plugin => "budget_plugin", :media => "screen" %>
- <%= javascript_include_tag('budget.js', :plugin => 'budget_plugin') %>
+
+ <% javascript_tag do %>
+ /* Used to calculate the Budget */
+ var BudgetModule = Class.create();
+ Object.extend(BudgetModule.prototype, {
+ initialize: function () {},
+
+ toAmount: function(value) {
+ var amount = value.replace(/[^1234567890.]/ig,'');
+ if (amount) {
+ return parseFloat(amount);
+ } else {
+ return 0;
+ }
+ },
+
+ updateAmounts: function() {
+ if ($('deliverable_type').checked) {
+ // Fixed cost
+ var cost = Budget.toAmount($('deliverable_fixed_cost').value);
+ 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 cost = perHour * hours;
+ Budget.updateAmount($('variableCost'), cost);
+ }
+
+
+ if ($('deliverable_overhead').value.match('%')) {
+ var overhead_subtotal = (Budget.toAmount($('deliverable_overhead').value) / 100) * cost;
+ } else {
+ var overhead_subtotal = Budget.toAmount($('deliverable_overhead').value);
+ }
+
+ if ($('deliverable_materials').value.match('%')) {
+ var materials_subtotal = (Budget.toAmount($('deliverable_materials').value) / 100) * cost;
+ } else {
+ var materials_subtotal = Budget.toAmount($('deliverable_materials').value);
+ }
+
+ // Profit uses labor cost and overhead
+ if ($('deliverable_profit').value.match('%')) {
+ var profit_subtotal = (Budget.toAmount($('deliverable_profit').value) / 100) * (cost + overhead_subtotal);
+ } else {
+ var profit_subtotal = Budget.toAmount($('deliverable_profit').value);
+ }
+
+ // Amounts
+ 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);
+ },
+
+ updateAmount: function(element, value) {
+ if (element) {
+ element.innerHTML = Budget.number_to_currency(value);
+ }
+ },
+
+ changeType: function() {
+ if ($('deliverable_type').checked) {
+ // Fixed
+ $$('.budget-hourly').each(function(ele) { ele.hide(); });
+ $$('.budget-fixed').each(function(ele) { ele.show(); });
+ } else {
+ // Variable
+ $$('.budget-hourly').each(function(ele) { ele.show(); });
+ $$('.budget-fixed').each(function(ele) { ele.hide(); });
+ }
+
+ Budget.updateAmounts();
+ },
+ // Rails-like number_to_currency currency formatting
+ // http://snippets.dzone.com/posts/show/4646
+ number_to_currency: function (number, options) {
+ try {
+ var options = options || {};
+ var precision = options["precision"] || 2;
+ var unit = options["unit"] || "<%= number_to_currency(0, :precision => 0).gsub('0', '') %>";
+ var separator = precision > 0 ? options["separator"] || "." : "";
+ var delimiter = options["delimiter"] || " ";
+
+ var parts = parseFloat(number).toFixed(precision).split('.');
+
+ <% if I18n.locale != :en %>
+ <%= "return Budget.number_with_delimiter(parts[0], delimiter) + separator + parts[1].toString() + unit;" %>
+ <% else %>
+ <%= "return unit + Budget.number_with_delimiter(parts[0], delimiter) + separator + parts[1].toString();" %>
+ <% end %>
+ } catch(e) {
+ return number;
+ }
+ },
+
+ number_with_delimiter: function (number, delimiter, separator) {
+ try {
+ var delimiter = delimiter || ",";
+ var separator = separator || ".";
+
+ var parts = number.toString().split('.');
+ parts[0] = parts[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1" + delimiter);
+ return parts.join(separator);
+ } catch(e) {
+ return number
+ }
+ }
+ });
+ Budget = new BudgetModule();
+
+ function toggleAll() {
+ $$('.deliverable-details').each(function(ele) {
+ ele.toggle();
+ });
+ $$('.toggle').each(function(e) {
+ e.toggle();
+ });
+ }
+
+
+ function expandRow(deliverable_id) {
+ $('deliverable-details-'+ deliverable_id).show();
+ $('deliverable-description-'+ deliverable_id).show();
+ $$('.toggle_' + deliverable_id).each(function(e) {
+ e.toggle();
+ });
+ }
+
+ function collapseRow(deliverable_id) {
+ $('deliverable-details-'+ deliverable_id).hide();
+ $('deliverable-description-'+ deliverable_id).hide();
+ $$('.toggle_' + deliverable_id).each(function(e) {
+ e.toggle();
+ });
+ }
+
+ <% end %>
<% end %>
diff --git a/assets/javascripts/budget.js b/assets/javascripts/budget.js
index 61a5c89..f8c77d9 100644
--- a/assets/javascripts/budget.js
+++ b/assets/javascripts/budget.js
@@ -3,10 +3,6 @@ var BudgetModule = Class.create();
Object.extend(BudgetModule.prototype, {
initialize: function () {},
- // number to currency options
-// var options = new Hash();
-// options.set('delimiter', ' ');
-//// options.set('unit', ' ');
toAmount: function(value) {
var amount = value.replace(/[^1234567890.]/ig,'');
if (amount) {