diff --git a/modules/budgets/app/components/budgets/child_budgets_row_component.rb b/modules/budgets/app/components/budgets/child_budgets_row_component.rb deleted file mode 100644 index b283249fb09..00000000000 --- a/modules/budgets/app/components/budgets/child_budgets_row_component.rb +++ /dev/null @@ -1,61 +0,0 @@ -# frozen_string_literal: true - -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -#++ - -module Budgets - class ChildBudgetsRowComponent < ::OpPrimer::BorderBoxRowComponent - def budget_relation - model - end - - def budget - budget_relation.child_budget - end - - def id - link_to "##{budget.id}", budget_path(budget) - end - - def subject - link_to budget.subject, budget_path(budget) - end - - def project - link_to budget.project.name, project_path(budget.project) - end - - def relation_type - I18n.t(budget_relation.relation_type, scope: %i[activerecord attributes budget_relation relation_types]) - end - - def budget_amount - number_to_currency(budget.budget) - end - end -end diff --git a/modules/budgets/app/components/budgets/child_budgets_table_component.rb b/modules/budgets/app/components/budgets/child_budgets_table_component.rb deleted file mode 100644 index cffbb38a800..00000000000 --- a/modules/budgets/app/components/budgets/child_budgets_table_component.rb +++ /dev/null @@ -1,70 +0,0 @@ -# frozen_string_literal: true - -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -#++ - -module Budgets - class ChildBudgetsTableComponent < ::OpPrimer::BorderBoxTableComponent - columns :id, :subject, :project, :relation_type, :budget_amount - main_column :subject, :proejct, :relation_type, :budget_amount - - def sortable? - false - end - - def paginated? - false - end - - def has_actions? - false - end - - def empty_row_message - I18n.t :no_results_title_text - end - - def row_class - Budgets::ChildBudgetsRowComponent - end - - def mobile_title - I18n.t(:label_budget_child_budgets) - end - - def headers - [ - [:id, { caption: Budget.human_attribute_name(:id) }], - [:subject, { caption: Budget.human_attribute_name(:subject) }], - [:project, { caption: Budget.human_attribute_name(:project) }], - [:relation_type, { caption: BudgetRelation.human_attribute_name(:relation_type) }], - [:budget_amount, { caption: Budget.human_attribute_name(:budget) }] - ] - end - end -end diff --git a/modules/budgets/app/components/budgets/parent_page_header_component.rb b/modules/budgets/app/components/budgets/parent_page_header_component.rb deleted file mode 100644 index 8525edb658d..00000000000 --- a/modules/budgets/app/components/budgets/parent_page_header_component.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -# -- copyright -# OpenProject is an open source project management software. -# Copyright (C) the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -# ++ - -module Budgets - class ParentPageHeaderComponent < ApplicationComponent - include OpPrimer::ComponentHelpers - include ApplicationHelper - - def initialize(budget:, project:) - super - - @budget = budget - @project = project - end - - def breadcrumb_items - [ - { href: project_overview_path(@project.id), text: @project.name }, - { href: projects_budgets_path(@project.id), text: t(:label_budget_plural) }, - { href: budget_path(@budget.id), text: t(:label_budget_id, id: @budget.id) }, - t(:button_manage_parent) - ] - end - - def call - render(Primer::OpenProject::PageHeader.new) do |header| - header.with_title { t(:button_manage_parent) } - header.with_breadcrumbs(breadcrumb_items) - end - end - end -end diff --git a/modules/budgets/app/components/budgets/show_page_header_component.html.erb b/modules/budgets/app/components/budgets/show_page_header_component.html.erb index 52bba5f1a95..14de313d793 100644 --- a/modules/budgets/app/components/budgets/show_page_header_component.html.erb +++ b/modules/budgets/app/components/budgets/show_page_header_component.html.erb @@ -18,21 +18,6 @@ t(:button_update) end end - if authorize_for(:budgets, :parent) && @budget.project.parent_id.present? - header.with_action_button( - tag: :a, - mobile_icon: "git-pull-request", - mobile_label: t(:button_manage_parent), - size: :medium, - href: url_for({ controller: "budgets", action: "parent", id: @budget }), - aria: { label: t(:button_manage_parent) }, - data: { test_selector: "budget-parent-button" }, - title: t(:button_manage_parent) - ) do |button| - button.with_leading_visual_icon(icon: "git-pull-request") - t(:button_manage_parent) - end - end if authorize_for(:budgets, :copy) header.with_action_button( tag: :a, diff --git a/modules/budgets/app/contracts/budgets/base_contract.rb b/modules/budgets/app/contracts/budgets/base_contract.rb index cfebe9302c7..d9f4fb254aa 100644 --- a/modules/budgets/app/contracts/budgets/base_contract.rb +++ b/modules/budgets/app/contracts/budgets/base_contract.rb @@ -38,7 +38,6 @@ module Budgets attribute :description attribute :fixed_date attribute :project - attribute :state attribute :base_amount attribute :new_material_budget_item_attributes, readable: false diff --git a/modules/budgets/app/controllers/budgets_controller.rb b/modules/budgets/app/controllers/budgets_controller.rb index 15f971b6188..2e729949eae 100644 --- a/modules/budgets/app/controllers/budgets_controller.rb +++ b/modules/budgets/app/controllers/budgets_controller.rb @@ -29,7 +29,7 @@ class BudgetsController < ApplicationController include AttachableServiceCall - before_action :find_budget, only: %i[show edit update copy destroy_info parent update_parent destroy_parent] + before_action :find_budget, only: %i[show edit update copy destroy_info] before_action :find_budgets, only: :destroy before_action :check_and_update_belonging_work_packages, only: :destroy before_action :find_project_by_project_id, only: %i[new create update_material_budget_item update_labor_budget_item] @@ -47,12 +47,16 @@ class BudgetsController < ApplicationController helper :sort include SortHelper + helper :projects include ProjectsHelper + helper :attachments include AttachmentsHelper + helper :costlog include CostlogHelper + helper :budgets include BudgetsHelper include PaginationHelper @@ -74,7 +78,6 @@ class BudgetsController < ApplicationController def show @edit_allowed = User.current.allowed_in_project?(:edit_budgets, @project) - @child_budget_relations = @budget.child_budget_relations.includes(child_budget: :project) respond_to do |format| format.html { render action: "show", layout: !request.xhr? } @@ -195,35 +198,6 @@ class BudgetsController < ApplicationController end end - def parent - @parent_projects = @project.ancestors - @budget_candidates = Budget.visible(User.current).where(project_id: @parent_projects) - - @parent_budget_relation = @budget.parent_budget_relation || BudgetRelation.new - end - - def update_parent - parent_relation = @budget.parent_budget_relation || @budget.build_parent_budget_relation - - if parent_relation.update(budget_relation_params) - flash[:notice] = t(:notice_successful_update) - redirect_to budget_path(@budget) - else - flash[:error] = t(:notice_failed_update) - render action: :parent, status: :unprocessable_entity - end - end - - def destroy_parent - if @budget.parent_budget_relation.destroy - flash[:notice] = t(:notice_relation_destroyed) - redirect_to budget_path(@budget), method: :get - else - flash[:error] = t(:notice_failed_delete) - render action: :parent, status: :unprocessable_entity - end - end - private def find_budget @@ -265,10 +239,6 @@ class BudgetsController < ApplicationController response end - def budget_relation_params - params.expect(budget_relation: %i[parent_budget_id relation_type]) - end - def default_budget_sort { "id" => "#{Budget.table_name}.id", diff --git a/modules/budgets/app/models/budget.rb b/modules/budgets/app/models/budget.rb index cbeb41d5561..2ccfd2e834f 100644 --- a/modules/budgets/app/models/budget.rb +++ b/modules/budgets/app/models/budget.rb @@ -46,18 +46,6 @@ class Budget < ApplicationRecord has_many :cost_entries, through: :work_packages has_many :time_entries, through: :work_packages - has_one :parent_budget_relation, class_name: "BudgetRelation", - foreign_key: "child_budget_id", - dependent: :destroy, - inverse_of: :child_budget - - has_one :parent_budget, through: :parent_budget_relation, source: :parent_budget - - has_many :child_budget_relations, class_name: "BudgetRelation", - foreign_key: "parent_budget_id", - dependent: :destroy, - inverse_of: :parent_budget - include ActiveModel::ForbiddenAttributesProtection acts_as_attachable @@ -68,16 +56,7 @@ class Budget < ApplicationRecord url: Proc.new { |o| { controller: "budgets", action: "show", id: o.id } } validates :subject, :project, :author, :fixed_date, presence: true - validates :subject, length: { maximum: 255 } - validates :subject, length: { minimum: 1 } - - enum :state, { - planned: "planned", - draft: "draft", - submitted: "submitted", - approved: "approved", - rejected: "rejected" - }, validate: { allow_nil: true } + validates :subject, length: { minimum: 1, maximum: 255 } class << self def visible(user) @@ -99,8 +78,10 @@ class Budget < ApplicationRecord protected def copy_attributes(source) - source.attributes.slice("project_id", "subject", "description", "fixed_date", "state", - "base_amount").merge("author" => User.current) + source + .attributes + .slice("project_id", "subject", "description", "fixed_date", "base_amount") + .merge("author" => User.current) end def copy_budget_items(source, sink, items:) @@ -119,34 +100,7 @@ class Budget < ApplicationRecord end def budget - base_amount + material_budget + labor_budget + budget_added_by_children - end - - def budget_added_by_children - # TODO: Efficient with query - @budget_added_by_children ||= child_budget_relations.add.includes(:child_budget).sum do |rel| - rel.child_budget.budget - end - end - - def allocated_to_children - # TODO: Efficient with query - @allocated_to_children ||= child_budget_relations.includes(:child_budget).sum { |rel| rel.child_budget.budget } - end - - def allocated_unused - allocated_to_children - spent_on_children - end - - def spent_with_children - spent + spent_on_children - end - - def spent_on_children - # TODO: Efficient with query - @spent_on_children ||= child_budget_relations.includes(:child_budget).sum do |rel| - rel.child_budget.spent_with_children - end + base_amount + material_budget + labor_budget end def type_label @@ -161,9 +115,7 @@ class Budget < ApplicationRecord def budget_ratio return 0.0 if budget.nil? || budget == 0.0 - gone = spent + allocated_to_children - - ((gone / budget) * 100).round + ((spent / budget) * 100).round end def css_classes @@ -215,7 +167,7 @@ class Budget < ApplicationRecord end def available - budget - spent - allocated_to_children + budget - spent end def new_material_budget_item_attributes=(material_budget_item_attributes) diff --git a/modules/budgets/app/models/budget_relation.rb b/modules/budgets/app/models/budget_relation.rb deleted file mode 100644 index c55c142e672..00000000000 --- a/modules/budgets/app/models/budget_relation.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -#++ - -class BudgetRelation < ApplicationRecord - belongs_to :parent_budget, class_name: "Budget" - belongs_to :child_budget, class_name: "Budget" - - enum :relation_type, { add: "add", subtract: "subtract" }, default: :subtract - - validates :child_budget, uniqueness: true - validates :child_budget, :parent_budget, :relation_type, presence: true -end diff --git a/modules/budgets/app/models/queries/projects/selects/budget_allocated.rb b/modules/budgets/app/models/queries/projects/selects/budget_allocated.rb deleted file mode 100644 index 2f5998741ee..00000000000 --- a/modules/budgets/app/models/queries/projects/selects/budget_allocated.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -# -- copyright -# OpenProject is an open source project management software. -# Copyright (C) the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -# ++ - -class Queries::Projects::Selects::BudgetAllocated < Queries::Selects::Base - def self.key - :budget_allocated - end - - def caption - I18n.t(:label_budget_allocated) - end -end diff --git a/modules/budgets/app/views/budgets/_form.html.erb b/modules/budgets/app/views/budgets/_form.html.erb index 679a0d3789e..4a047edc603 100644 --- a/modules/budgets/app/views/budgets/_form.html.erb +++ b/modules/budgets/app/views/budgets/_form.html.erb @@ -50,12 +50,6 @@ See COPYRIGHT and LICENSE files for more details. value: unitless_currency_number(@budget.base_amount) %> -
- <%= f.select :state, - Budget.states.keys.map { |state| [I18n.t(state, scope: %i[activerecord attributes budget states]), state] }, - { include_blank: true } %> -
- <%= render partial: "budgets/subform/material_budget_subform" %> <%= render partial: "budgets/subform/labor_budget_subform" %> diff --git a/modules/budgets/app/views/budgets/_list.html.erb b/modules/budgets/app/views/budgets/_list.html.erb index 05dd8186a11..cb3b8db4a50 100644 --- a/modules/budgets/app/views/budgets/_list.html.erb +++ b/modules/budgets/app/views/budgets/_list.html.erb @@ -39,13 +39,11 @@ See COPYRIGHT and LICENSE files for more details. - <%= sort_header_tag("id", caption: "#", default_order: "desc") %> <%= sort_header_tag("subject", caption: Budget.human_attribute_name(:subject)) %> - <%= sort_header_tag("state", caption: Budget.human_attribute_name(:state)) %>
@@ -93,11 +91,6 @@ See COPYRIGHT and LICENSE files for more details. <%= link_to budget.id, budget_path(budget.id) %> <%= content_tag(:td, link_to(h(budget.subject), budget_path(budget.id)), class: "subject") %> - - <% if budget.state.present? %> - <%= I18n.t(budget.state, scope: %i[activerecord attributes budget states]) %> - <% else %> - <% end %> - <%= content_tag(:td, number_to_currency(budget.budget, precision: 0), class: "currency") %> <%= content_tag(:td, number_to_currency(budget.spent, precision: 0), class: "currency") %> <%= content_tag(:td, number_to_currency(budget.available, precision: 0), class: "currency") %> @@ -112,7 +105,6 @@ See COPYRIGHT and LICENSE files for more details. <% end %> <% if budgets.length > 0 %> - <%= number_to_currency(total_budget, precision: 0) %> diff --git a/modules/budgets/app/views/budgets/parent.html.erb b/modules/budgets/app/views/budgets/parent.html.erb deleted file mode 100644 index c67e4ad9ee6..00000000000 --- a/modules/budgets/app/views/budgets/parent.html.erb +++ /dev/null @@ -1,70 +0,0 @@ -<% html_title "#{t(:button_manage_parent)} #{t(:label_budget_id, id: @budget.id)}: #{@budget.subject}" %> - -<%= render Budgets::ParentPageHeaderComponent.new(budget: @budget, project: @project) %> -<%- - parent_budget_relation = @parent_budget_relation - parent_candidates = @budget_candidates -%> -<%= - primer_form_with(scope: :budget_relation, action: :update_parent, method: :post) do |budget_parent_form| - render_inline_form(budget_parent_form) do |form| - form.html_content do - render(Primer::Beta::Subhead.new(hide_border: true)) do |subhead| - subhead.with_heading(tag: :h3, size: :medium) { I18n.t("budgets.parent_relation.heading") } - subhead.with_description { I18n.t("budgets.parent_relation.description") } - end - end - - form.select_list( - name: :parent_budget_id, - label: BudgetRelation.human_attribute_name(:parent_budget), - required: true, - input_width: :large - ) do |select| - parent_candidates.each do |budget| - select.option( - label: "#{budget.project.name}: ##{budget.id} - #{budget.subject}", - value: budget.id, - selected: budget.id == parent_budget_relation.parent_budget_id - ) - end - end - - form.radio_button_group(name: :relation_type) do |group| - group.radio_button( - value: :add, - checked: parent_budget_relation.add?, - label: I18n.t("budgets.relation_types.add.label"), - caption: I18n.t("budgets.relation_types.add.helptext") - ) - - group.radio_button( - value: :subtract, - checked: parent_budget_relation.subtract?, - label: I18n.t("budgets.relation_types.subtract.label"), - caption: I18n.t("budgets.relation_types.subtract.helptext") - ) - end - - form.submit(name: :submit, label: I18n.t(:button_set_parent)) - end - end -%> - -<% if @budget.parent_budget_relation.present? %> - <%= render(Primer::Beta::Subhead.new(mt: 5, hide_border: true)) do |subhead| - subhead.with_heading(tag: :h3, size: :medium) { I18n.t("budgets.delete_parent_relation.heading") } - subhead.with_description { I18n.t("budgets.delete_parent_relation.description") } - end %> - -<%= render Primer::Beta::Button.new( - tag: :a, - scheme: :danger, - title: I18n.t(:button_delete_link_to_parent), - href: parent_budget_path(@budget), - data: { "method" => :delete } - ) do |button| - button.with_leading_visual_icon(icon: :trash) - I18n.t(:button_delete_link_to_parent) - end %> -<% end %> diff --git a/modules/budgets/app/views/budgets/show.html.erb b/modules/budgets/app/views/budgets/show.html.erb index d39d7624053..460f456fd49 100644 --- a/modules/budgets/app/views/budgets/show.html.erb +++ b/modules/budgets/app/views/budgets/show.html.erb @@ -47,21 +47,6 @@ See COPYRIGHT and LICENSE files for more details. key: Budget.human_attribute_name(:budget_ratio), value: extended_progress_bar(@budget.budget_ratio, width: "80px", legend: @budget.budget_ratio) ) - component.with_attribute( - key: Budget.human_attribute_name(:state), - value: @budget.state.present? ? I18n.t(@budget.state, scope: %i[activerecord attributes budget states]) : "-" - ) - component.with_attribute( - key: Budget.human_attribute_name(:parent_budget), - value: if @budget.parent_budget_relation.present? - link_to( - "#{@budget.parent_budget.project.name}: #{@budget.parent_budget.subject} (#{I18n.t(@budget.parent_budget_relation.relation_type, scope: %i[activerecord attributes budget_relation relation_types])})", - budget_path(@budget.parent_budget) - ) - else - "-" - end - ) component.with_attribute( key: Budget.human_attribute_name(:description), value: content_tag(:div, class: "op-uc-container") do @@ -86,12 +71,6 @@ See COPYRIGHT and LICENSE files for more details. key: Budget.human_attribute_name(:labor_budget), value: number_to_currency(@budget.labor_budget) ) - if @budget.child_budget_relations.add.any? - component.with_attribute( - key: Budget.human_attribute_name(:budget_added_by_children), - value: number_to_currency(@budget.budget_added_by_children) - ) - end component.with_attribute( key: Budget.human_attribute_name(:budget), value: content_tag(:strong, number_to_currency(@budget.budget)) @@ -100,12 +79,6 @@ See COPYRIGHT and LICENSE files for more details. key: Budget.human_attribute_name(:spent), value: number_to_currency(@budget.spent * -1) ) - if @budget.child_budget_relations.subtract.any? - component.with_attribute( - key: Budget.human_attribute_name(:allocated_to_children), - value: number_to_currency(@budget.allocated_to_children * -1) - ) - end component.with_attribute( key: Budget.human_attribute_name(:available), value: content_tag(:strong, number_to_currency(@budget.available)) @@ -118,14 +91,6 @@ See COPYRIGHT and LICENSE files for more details. <%= list_attachments(resource) %> <%= render partial: "budget_items" %> - -
- - <%= I18n.t(:label_budget_child_budgets) %> - - <%= render(Budgets::ChildBudgetsTableComponent.new(rows: @child_budget_relations)) %> -
-
diff --git a/modules/budgets/config/locales/en.yml b/modules/budgets/config/locales/en.yml index 2e03c703e3e..02305b16ccd 100644 --- a/modules/budgets/config/locales/en.yml +++ b/modules/budgets/config/locales/en.yml @@ -36,8 +36,6 @@ en: budget: author: "Author" available: "Available" - allocated_to_children: "Allocated" - budget_added_by_children: "Added by children" budget: "Planned" budget_ratio: "Spent (ratio)" description: "Description" @@ -48,23 +46,8 @@ en: labor_budget: "Planned labor costs" material_budget: "Planned unit costs" base_amount: "Base amount" - parent_budget: "Parent budget" - state: "State" - states: - planned: "Planned" - draft: "Draft" - submitted: "Submitted" - approved: "Approved" - rejected: "Rejected" work_package: budget_subject: "Budget title" - budget_relation: - parent_budget: "Parent budget" - child_budget: "Child budget" - relation_type: "Relation to this" - relation_types: - add: "add budget to parent" - subtract: "allocated budget from parent" models: budget: "Budget" material_budget_item: "Unit" @@ -81,9 +64,6 @@ en: button_add_cost_type: "Add cost type" button_cancel_edit_budget: "Cancel editing budget" button_cancel_edit_costs: "Cancel editing costs" - button_manage_parent: "Manage parent budget" - button_set_parent: "Set parent" - button_delete_link_to_parent: "Delete link to parent budget" caption_labor: "Labor" caption_labor_costs: "Actual labor costs" @@ -105,18 +85,15 @@ en: label_budget_plural: "Budgets" label_budget_spent: "Budget spent" label_budget_spent_ratio: "Budget spent ratio" - label_budget_allocated: "Budget allocated to children" label_deliverable: "Budget" label_example_placeholder: "e.g., %{decimal}" label_view_all_budgets: "View all budgets" label_yes: "Yes" - label_budget_child_budgets: "Child budgets" label_budget_totals: "Totals" label_budget_details: "Budget details" notice_budget_conflict: "Work packages must be of the same project." notice_no_budgets_available: "No budgets available." - notice_relation_destroyed: "The budget relation has been removed." permission_edit_budgets: "Edit budgets" permission_view_budgets: "View budgets" @@ -125,18 +102,3 @@ en: text_budget_reassign_to: "Reassign them to this budget:" text_budget_delete: "Delete the budget from all work packages" text_budget_destroy_assigned_wp: "There are %{count} work packages assigned to this budget. What do you want to do?" - - budgets: - parent_relation: - heading: "Mark this project as a child budget to another budget" - description: "This will set up a dependency from this budget to its parent. Depending on the type of relation, the budgeted amount will be added to or subtracted from the parent's budget." - delete_parent_relation: - heading: "Delete parent budget relation" - description: "This will remove the dependency from this budget to its parent. The budgeted amount of the parent budget and all its ancestors will also change!" - relation_types: - add: - label: "Add budget to parent" - helptext: "The budgeted amount for this budget will be added to the parent's budget and also mark the amount as allocated to this budget." - subtract: - label: "Subtract budget from parent" - helptext: "The budgeted amount for this budget will be subtracted from the parent's budget and marked as allocated to this budget." diff --git a/modules/budgets/config/routes.rb b/modules/budgets/config/routes.rb index bfe1716e7ed..66504fe6dc8 100644 --- a/modules/budgets/config/routes.rb +++ b/modules/budgets/config/routes.rb @@ -36,9 +36,6 @@ Rails.application.routes.draw do resources :budgets, only: %i[show update destroy edit] do member do - get :parent - post :parent, to: "budgets#update_parent" - delete :parent, to: "budgets#destroy_parent" get :copy get :destroy_info end diff --git a/modules/budgets/db/migrate/20250714113219_create_budget_relation.rb b/modules/budgets/db/migrate/20250714113219_create_budget_relation.rb deleted file mode 100644 index 14cfa430dfd..00000000000 --- a/modules/budgets/db/migrate/20250714113219_create_budget_relation.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -#++ - -class CreateBudgetRelation < ActiveRecord::Migration[8.0] - def change - create_table :budget_relations do |t| - t.references :parent_budget, null: false, foreign_key: { to_table: :budgets } - t.references :child_budget, null: false, foreign_key: { to_table: :budgets } - t.references :cost_type, null: true, foreign_key: { to_table: :cost_types } - - t.string :relation_type, null: false, default: "add" - - t.timestamps - end - end -end diff --git a/modules/budgets/db/migrate/20250714123836_add_budget_state.rb b/modules/budgets/db/migrate/20250714123836_add_budget_state.rb deleted file mode 100644 index 552eeab8952..00000000000 --- a/modules/budgets/db/migrate/20250714123836_add_budget_state.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -#++ - -class AddBudgetState < ActiveRecord::Migration[8.0] - def change - add_column :budgets, :state, :string, null: true - add_column :budget_journals, :state, :string, null: true - end -end diff --git a/modules/budgets/db/migrate/20250714123904_add_budget_state_index.rb b/modules/budgets/db/migrate/20250714123904_add_budget_state_index.rb deleted file mode 100644 index 5ddb0942421..00000000000 --- a/modules/budgets/db/migrate/20250714123904_add_budget_state_index.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -#++ - -class AddBudgetStateIndex < ActiveRecord::Migration[8.0] - disable_ddl_transaction! - - def change - add_index :budgets, :state, algorithm: :concurrently - end -end diff --git a/modules/budgets/db/migrate/20250716121743_unique_budget_relation_child.rb b/modules/budgets/db/migrate/20250716121743_unique_budget_relation_child.rb deleted file mode 100644 index 10561f4e224..00000000000 --- a/modules/budgets/db/migrate/20250716121743_unique_budget_relation_child.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -class UniqueBudgetRelationChild < ActiveRecord::Migration[8.0] - disable_ddl_transaction! - - def change - remove_index :budget_relations, :child_budget_id, if_exists: true, algorithm: :concurrently - add_index :budget_relations, :child_budget_id, unique: true, algorithm: :concurrently - end -end diff --git a/modules/budgets/db/migrate/20250716122318_remove_cost_type_from_budget_relation.rb b/modules/budgets/db/migrate/20250716122318_remove_cost_type_from_budget_relation.rb deleted file mode 100644 index 68be7bfee56..00000000000 --- a/modules/budgets/db/migrate/20250716122318_remove_cost_type_from_budget_relation.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -class RemoveCostTypeFromBudgetRelation < ActiveRecord::Migration[8.0] - def change - remove_reference(:budget_relations, :cost_type, foreign_key: true) - end -end diff --git a/modules/budgets/lib/budgets/engine.rb b/modules/budgets/lib/budgets/engine.rb index 66b4f7b242b..dafc95709a4 100644 --- a/modules/budgets/lib/budgets/engine.rb +++ b/modules/budgets/lib/budgets/engine.rb @@ -13,7 +13,7 @@ module Budgets permissible_on: :project permission :edit_budgets, { - budgets: %i[index show edit update destroy destroy_info new create copy parent destroy_parent update_parent] + budgets: %i[index show edit update destroy destroy_info new create copy] }, permissible_on: :project end @@ -72,7 +72,6 @@ module Budgets select Queries::Projects::Selects::BudgetSpent select Queries::Projects::Selects::BudgetSpentRatio select Queries::Projects::Selects::BudgetAvailable - select Queries::Projects::Selects::BudgetAllocated end end end diff --git a/modules/budgets/lib/budgets/patches/projects/row_component_patch.rb b/modules/budgets/lib/budgets/patches/projects/row_component_patch.rb index a6a24060032..9ea970302f4 100644 --- a/modules/budgets/lib/budgets/patches/projects/row_component_patch.rb +++ b/modules/budgets/lib/budgets/patches/projects/row_component_patch.rb @@ -55,12 +55,7 @@ module Budgets::Patches::Projects::RowComponentPatch end def total_ratio - gone = total_spent + total_allocated - @total_ratio ||= total_planned.zero? ? 0 : ((gone / total_planned) * 100).round - end - - def total_allocated - @total_allocated ||= budgets.sum(&:allocated_to_children) + @total_ratio ||= total_planned.zero? ? 0 : ((total_spent / total_planned) * 100).round end def budgets @@ -88,12 +83,6 @@ module Budgets::Patches::Projects::RowComponentPatch end end - def budget_allocated - with_project_budgets do |project_budgets| - number_to_currency(project_budgets.total_allocated, precision: 0) - end - end - def budget_available with_project_budgets do |project_budgets| number_to_currency(project_budgets.total_available, precision: 0) diff --git a/modules/budgets/spec/factories/budget_factory.rb b/modules/budgets/spec/factories/budget_factory.rb index f1725cb1f34..a6585dc8807 100644 --- a/modules/budgets/spec/factories/budget_factory.rb +++ b/modules/budgets/spec/factories/budget_factory.rb @@ -38,10 +38,8 @@ FactoryBot.define do created_at { 3.days.ago } updated_at { 3.days.ago } - traits_for_enum(:state) - trait :with_base_amount do - base_amount { BigDecimal(250000000) } + base_amount { BigDecimal(250_000) } end end end diff --git a/modules/budgets/spec/factories/budget_relation_factory.rb b/modules/budgets/spec/factories/budget_relation_factory.rb deleted file mode 100644 index 3671d0261db..00000000000 --- a/modules/budgets/spec/factories/budget_relation_factory.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -#++ - -FactoryBot.define do - factory :budget_relation do - parent_budget factory: :budget - child_budget factory: :budget - - traits_for_enum(:relation_type) - end -end diff --git a/modules/budgets/spec/models/budget_relation_spec.rb b/modules/budgets/spec/models/budget_relation_spec.rb deleted file mode 100644 index 48a50ab0045..00000000000 --- a/modules/budgets/spec/models/budget_relation_spec.rb +++ /dev/null @@ -1,407 +0,0 @@ -# frozen_string_literal: true - -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) the OpenProject GmbH -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License version 3. -# -# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: -# Copyright (C) 2006-2013 Jean-Philippe Lang -# Copyright (C) 2010-2013 the ChiliProject Team -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# See COPYRIGHT and LICENSE files for more details. -#++ - -require_relative "../spec_helper" - -RSpec.describe BudgetRelation do - shared_let(:admin) { create(:admin) } - before do - allow(User).to receive(:current).and_return(admin) - end - - describe "calculation logic" do - describe "bottom->up" do - let(:portfolio) { create(:project, project_type: :portfolio, name: "Portfolio") } - let(:portfolio_budget) do - create(:budget, project: portfolio, base_amount: 0, subject: "Portfolio Budget") - end - - let(:program1) { create(:project, project_type: :program, parent: portfolio, name: "Program 1") } - let(:program1_budget) { create(:budget, project: program1, base_amount: 0, subject: "Program 1 Budget") } - - let(:project1) { create(:project, project_type: :project, parent: program1, name: "Project 1") } - let(:project1_budget) { create(:budget, project: project1, base_amount: 5_000, subject: "Project 1 Budget") } - - let(:project2) { create(:project, project_type: :project, parent: program1, name: "Project 2") } - let(:project2_budget) { create(:budget, project: project2, base_amount: 2_500, subject: "Project 2 Budget") } - - context "without any relations" do - it "calculates the correct values" do - expect(portfolio_budget).to have_attributes(budget: 0, - allocated_to_children: 0, - spent: 0, - available: 0) - - expect(program1_budget).to have_attributes(budget: 0, - allocated_to_children: 0, - spent: 0, - available: 0) - - expect(project1_budget).to have_attributes(budget: 5_000, - allocated_to_children: 0, - spent: 0, - available: 5_000) - - expect(project2_budget).to have_attributes(budget: 2_500, - allocated_to_children: 0, - spent: 0, - available: 2_500) - end - end - - context "when setting up project1 to add itself to the program1 budget" do - before do - described_class.create!(parent_budget: program1_budget, - child_budget: project1_budget, - relation_type: :add) - end - - it "allocates the project's budget to the program's budget" do - expect(portfolio_budget).to have_attributes(budget: 0, - allocated_to_children: 0, - spent: 0, - available: 0) - - expect(program1_budget).to have_attributes(budget: 5_000, - allocated_to_children: 5_000, - spent: 0, - available: 0) - - expect(project1_budget).to have_attributes(budget: 5_000, - allocated_to_children: 0, - spent: 0, - available: 5_000) - - expect(project2_budget).to have_attributes(budget: 2_500, - allocated_to_children: 0, - spent: 0, - available: 2_500) - end - - context "when also setting up project2 to add itself to the program1 budget" do - before do - described_class.create!(parent_budget: program1_budget, - child_budget: project2_budget, - relation_type: :add) - end - - it "allocates both project's budget to the program's budget" do - expect(portfolio_budget).to have_attributes(budget: 0, - allocated_to_children: 0, - spent: 0, - available: 0) - - expect(program1_budget).to have_attributes(budget: 7_500, - allocated_to_children: 7_500, - spent: 0, - available: 0) - - expect(project1_budget).to have_attributes(budget: 5_000, - allocated_to_children: 0, - spent: 0, - available: 5_000) - - expect(project2_budget).to have_attributes(budget: 2_500, - allocated_to_children: 0, - spent: 0, - available: 2_500) - end - - context "when setting program1 to add itself to the portfolio budget" do - before do - described_class.create!(parent_budget: portfolio_budget, - child_budget: program1_budget, - relation_type: :add) - end - - it "allocates the program's budget to the portfolio's budget" do - expect(portfolio_budget).to have_attributes(budget: 7_500, - allocated_to_children: 7_500, - spent: 0, - available: 0) - - expect(program1_budget).to have_attributes(budget: 7_500, - allocated_to_children: 7_500, - spent: 0, - available: 0) - - expect(project1_budget).to have_attributes(budget: 5_000, - allocated_to_children: 0, - spent: 0, - available: 5_000) - - expect(project2_budget).to have_attributes(budget: 2_500, - allocated_to_children: 0, - spent: 0, - available: 2_500) - end - - context "when adding some costs to the projects" do - let(:work_package1) { create(:work_package, project: project1, budget: project1_budget) } - let!(:cost_entry1) do - create(:cost_entry, project: project1, entity: work_package1, overridden_costs: 500) - end - - let(:work_package2) { create(:work_package, project: project2, budget: project2_budget) } - let!(:cost_entry2) do - create(:cost_entry, project: project2, entity: work_package2, overridden_costs: 750) - end - - it "subtracts the costs from the budgets" do - expect(portfolio_budget).to have_attributes(spent: 0, - spent_with_children: 1_250) - - expect(program1_budget).to have_attributes(spent: 0, - spent_with_children: 1_250) - - expect(project1_budget).to have_attributes(budget: 5_000, - spent: 500, - available: 4_500) - - expect(project2_budget).to have_attributes(budget: 2_500, - spent: 750, - available: 1_750) - end - end - end - end - end - end - - describe "top->down" do - let(:portfolio) { create(:project, project_type: :portfolio, name: "Portfolio") } - let(:portfolio_budget) { create(:budget, project: portfolio, base_amount: 10_000, subject: "Portfolio Budget") } - - let(:program1) { create(:project, project_type: :program, parent: portfolio, name: "Program 1") } - let(:program1_budget) { create(:budget, project: program1, base_amount: 7_000, subject: "Program 1 Budget") } - - let(:project1) { create(:project, project_type: :project, parent: program1, name: "Project 1") } - let(:project1_budget) { create(:budget, project: project1, base_amount: 5_000, subject: "Project 1 Budget") } - - let(:program2) { create(:project, project_type: :program, parent: portfolio, name: "Program 2") } - let(:program2_budget) { create(:budget, project: program2, base_amount: 3_000, subject: "Program 2 Budget") } - - let(:project2) { create(:project, project_type: :project, parent: program2, name: "Project 2") } - let(:project2_budget) { create(:budget, project: project2, base_amount: 2_000, subject: "Project 2 Budget") } - - context "without any relations" do - it "calculates the correct values" do - expect(portfolio_budget).to have_attributes(budget: 10_000, - allocated_to_children: 0, - spent: 0, - available: 10_000) - end - end - - context "with the portfolio -> program1 relation" do - before do - described_class.create!(parent_budget: portfolio_budget, - child_budget: program1_budget, - relation_type: :subtract) - end - - it "allocates the program's budget out of the portfolio budget" do - expect(portfolio_budget).to have_attributes(budget: 10_000, - allocated_to_children: 7_000, - spent: 0, - available: 3_000) - - expect(program1_budget).to have_attributes(budget: 7_000, - allocated_to_children: 0, - spent: 0, - available: 7_000) - end - - context "with the program1 -> project1 relation" do - before do - described_class.create!(parent_budget: program1_budget, - child_budget: project1_budget, - relation_type: :subtract) - end - - it "allocates the project's budget out of the program's budget" do - expect(portfolio_budget).to have_attributes(budget: 10_000, - allocated_to_children: 7_000, - spent: 0, - available: 3_000) - - expect(program1_budget).to have_attributes(budget: 7_000, - allocated_to_children: 5_000, - spent: 0, - available: 2_000) - - expect(project1_budget).to have_attributes(budget: 5_000, - allocated_to_children: 0, - spent: 0, - available: 5_000) - end - end - - context "with the portfolio -> program1, program2 relation" do - before do - described_class.create!(parent_budget: portfolio_budget, - child_budget: program2_budget, - relation_type: :subtract) - end - - it "allocates the program's budget out of the portfolio's budget" do - expect(portfolio_budget).to have_attributes(budget: 10_000, - allocated_to_children: 10_000, - spent: 0, - available: 0) - - expect(program1_budget).to have_attributes(budget: 7_000, - allocated_to_children: 0, - spent: 0, - available: 7_000) - - expect(program2_budget).to have_attributes(budget: 3_000, - allocated_to_children: 0, - spent: 0, - available: 3_000) - end - - context "with the program2 -> project2 relation" do - before do - described_class.create!(parent_budget: program2_budget, - child_budget: project2_budget, - relation_type: :subtract) - end - - it "allocates the project's budget out of the program's budget" do - expect(portfolio_budget).to have_attributes(budget: 10_000, - allocated_to_children: 10_000, - spent: 0, - available: 0) - - expect(program2_budget).to have_attributes(budget: 3_000, - allocated_to_children: 2_000, - spent: 0, - available: 1_000) - - expect(project2_budget).to have_attributes(budget: 2_000, - allocated_to_children: 0, - spent: 0, - available: 2_000) - end - - context "with logged costs on project1" do - let(:work_package) { create(:work_package, project: project2, budget: project2_budget) } - let!(:cost_entry) do - create(:cost_entry, project: project2, entity: work_package, overridden_costs: 500) - end - - it "subtracts the cost from project2's budget" do - expect(portfolio_budget.spent).to eq(0) - expect(portfolio_budget.spent_with_children).to eq(500) - - expect(program2_budget.spent).to eq(0) - expect(program2_budget.spent_with_children).to eq(500) - - expect(project2_budget).to have_attributes(budget: 2_000, - allocated_to_children: 0, - spent: 500, - available: 1_500) - end - end - end - end - end - end - - describe "bottom->up and top->down mixed" do - # - The portfolio has a budget of 10.000€. - # - The program does not have an assigned budget but is the sum of the project's budgets. - # - The program budget is taken out of the portfolio budget. - # - The projects have budgets of 5.000€ and 2.500€. - # - The projects have half of their budgets already spent. - - let!(:portfolio) { create(:project, project_type: :portfolio, name: "Portfolio") } - let!(:portfolio_budget) { create(:budget, project: portfolio, base_amount: 10_000, subject: "Portfolio Budget") } - - let!(:program1) { create(:project, project_type: :program, parent: portfolio, name: "Program 1") } - let!(:program1_budget) { create(:budget, project: program1, base_amount: 0, subject: "Program 1 Budget") } - - let!(:portfolio_program_relation) do - create(:budget_relation, parent_budget: portfolio_budget, child_budget: program1_budget, relation_type: :subtract) - end - - let!(:project1) { create(:project, project_type: :project, parent: program1, name: "Project 1") } - let!(:project1_budget) { create(:budget, project: project1, base_amount: 5_000, subject: "Project 1 Budget") } - - let!(:project1_program_relation) do - create(:budget_relation, parent_budget: program1_budget, child_budget: project1_budget, relation_type: :add) - end - - let!(:work_package1) { create(:work_package, project: project1, budget: project1_budget) } - let!(:cost_entry1) do - create(:cost_entry, project: project1, entity: work_package1, overridden_costs: 2_500) - end - - let!(:project2) { create(:project, project_type: :project, parent: program1, name: "Project 2") } - let!(:project2_budget) { create(:budget, project: project2, base_amount: 2_500, subject: "Project 2 Budget") } - - let!(:project2_program_relation) do - create(:budget_relation, parent_budget: program1_budget, child_budget: project2_budget, relation_type: :add) - end - - let!(:work_package2) { create(:work_package, project: project2, budget: project2_budget) } - let!(:cost_entry2) do - create(:cost_entry, project: project2, entity: work_package2, overridden_costs: 1_250) - end - - it "calculates the correct values" do - expect(portfolio_budget).to have_attributes(budget: 10_000, - allocated_to_children: 7_500, - spent: 0, - spent_with_children: 3_750, - available: 2_500) - - expect(program1_budget).to have_attributes(budget: 7_500, - allocated_to_children: 7_500, - spent: 0, - spent_with_children: 3_750, - available: 0) - - expect(project1_budget).to have_attributes(budget: 5_000, - allocated_to_children: 0, - spent: 2_500, - spent_with_children: 2_500, - available: 2_500) - - expect(project2_budget).to have_attributes(budget: 2_500, - allocated_to_children: 0, - spent: 1_250, - spent_with_children: 1_250, - available: 1_250) - end - end - end -end diff --git a/modules/budgets/spec/models/permitted_params_spec.rb b/modules/budgets/spec/models/permitted_params_spec.rb index e0ffaa90f06..bb79819991d 100644 --- a/modules/budgets/spec/models/permitted_params_spec.rb +++ b/modules/budgets/spec/models/permitted_params_spec.rb @@ -57,40 +57,34 @@ RSpec.describe PermittedParams do end end - describe "#budget" do + describe "budget" do let(:attribute) { :budget } - context "subject" do + describe "#subject" do let(:hash) { { "subject" => "subject_test" } } it_behaves_like "allows params" end - context "description" do + describe "#description" do let(:hash) { { "description" => "description_test" } } it_behaves_like "allows params" end - context "fixed_date" do + describe "#fixed_date" do let(:hash) { { "fixed_date" => "2017-03-01" } } it_behaves_like "allows params" end - context "base_amount" do + describe "#base_amount" do let(:hash) { { "base_amount" => "250000.00" } } it_behaves_like "allows params" end - context "state" do - let(:hash) { { "state" => "approved" } } - - it_behaves_like "allows params" - end - - context "project_id" do + describe "#project_id" do let(:hash) { { "project_id" => 42 } } it_behaves_like "allows params" do @@ -98,7 +92,7 @@ RSpec.describe PermittedParams do end end - context "existing material budget item" do + describe "#existing_material_budget_item" do let(:hash) do { "existing_material_budget_item_attributes" => { "1" => { "units" => "100.0", @@ -111,7 +105,7 @@ RSpec.describe PermittedParams do it_behaves_like "allows params" end - context "new material budget item" do + describe "#new_material_budget_item" do let(:hash) do { "new_material_budget_item_attributes" => { "1" => { "units" => "20", @@ -124,7 +118,7 @@ RSpec.describe PermittedParams do it_behaves_like "allows params" end - context "existing labor budget item" do + describe "#existing_labor_budget_item" do let(:hash) do { "existing_labor_budget_item_attributes" => { "1" => { "hours" => "20.0", @@ -137,7 +131,7 @@ RSpec.describe PermittedParams do it_behaves_like "allows params" end - context "new labor budget item" do + describe "#new_labor_budget_item" do let(:hash) do { "new_labor_budget_item_attributes" => { "1" => { "hours" => "5.0", diff --git a/modules/costs/lib/costs/patches/permitted_params_patch.rb b/modules/costs/lib/costs/patches/permitted_params_patch.rb index f5e68579ce1..5f5d9f9dd30 100644 --- a/modules/costs/lib/costs/patches/permitted_params_patch.rb +++ b/modules/costs/lib/costs/patches/permitted_params_patch.rb @@ -44,11 +44,11 @@ module Costs::Patches::PermittedParamsPatch def budget params.require(:budget).permit(:subject, :description, - :fixed_date, :base_amount, :state, + :fixed_date, :base_amount, { new_material_budget_item_attributes: %i[units cost_type_id comments amount] }, { new_labor_budget_item_attributes: %i[hours user_id comments amount] }, { existing_material_budget_item_attributes: %i[units cost_type_id comments amount] }, - existing_labor_budget_item_attributes: %i[hours user_id comments amount]) + { existing_labor_budget_item_attributes: %i[hours user_id comments amount] }) end def cost_type diff --git a/spec/models/queries/projects/project_query_spec.rb b/spec/models/queries/projects/project_query_spec.rb index 8953303b06c..5bc9ae43991 100644 --- a/spec/models/queries/projects/project_query_spec.rb +++ b/spec/models/queries/projects/project_query_spec.rb @@ -149,7 +149,6 @@ RSpec.describe ProjectQuery do budget_planned budget_spent budget_spent_ratio - budget_allocated ]) end end @@ -177,7 +176,6 @@ RSpec.describe ProjectQuery do budget_available budget_planned budget_spent - budget_allocated budget_spent_ratio ]) end