decidim-budgets 0.21.0 → 0.23.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +38 -3
- data/app/assets/images/decidim/budgets/icon.svg +1 -11
- data/app/assets/javascripts/decidim/budgets/projects.js.es6 +26 -4
- data/app/assets/stylesheets/decidim/budgets/budget/_budget-list.scss +152 -24
- data/app/cells/decidim/budgets/base_cell.rb +22 -0
- data/app/cells/decidim/budgets/budget_cell.rb +21 -0
- data/app/cells/decidim/budgets/budget_information_modal/show.erb +28 -0
- data/app/cells/decidim/budgets/budget_information_modal_cell.rb +22 -0
- data/app/cells/decidim/budgets/budget_list_item/show.erb +22 -0
- data/app/cells/decidim/budgets/budget_list_item_cell.rb +40 -0
- data/app/cells/decidim/budgets/budget_m/data.erb +12 -0
- data/app/cells/decidim/budgets/budget_m/footer.erb +5 -0
- data/app/cells/decidim/budgets/budget_m_cell.rb +16 -0
- data/app/cells/decidim/budgets/budgets_header/show.erb +7 -0
- data/app/cells/decidim/budgets/budgets_header_cell.rb +14 -0
- data/app/cells/decidim/budgets/budgets_list/card_list.erb +7 -0
- data/app/cells/decidim/budgets/budgets_list/highlighted.erb +11 -0
- data/app/cells/decidim/budgets/budgets_list/show.erb +20 -0
- data/app/cells/decidim/budgets/budgets_list/voted.erb +43 -0
- data/app/cells/decidim/budgets/budgets_list_cell.rb +39 -0
- data/app/cells/decidim/budgets/limit_announcement_cell.rb +52 -0
- data/app/cells/decidim/budgets/project_list_item/project_data.erb +19 -0
- data/app/cells/decidim/budgets/project_list_item/project_data_vote_button.erb +15 -0
- data/app/cells/decidim/budgets/project_list_item/project_image.erb +5 -0
- data/app/cells/decidim/budgets/project_list_item/project_text.erb +23 -0
- data/app/cells/decidim/budgets/project_list_item/show.erb +5 -0
- data/app/cells/decidim/budgets/project_list_item_cell.rb +66 -0
- data/app/cells/decidim/budgets/project_m/data.erb +3 -3
- data/app/cells/decidim/budgets/project_m/footer.erb +1 -1
- data/app/cells/decidim/budgets/project_m_cell.rb +4 -0
- data/app/cells/decidim/budgets/project_selected_status_cell.rb +28 -0
- data/app/cells/decidim/budgets/project_tags/show.erb +5 -0
- data/app/cells/decidim/budgets/project_tags_cell.rb +18 -0
- data/app/cells/decidim/budgets/project_voted_hint_cell.rb +33 -0
- data/app/cells/decidim/budgets/project_votes_count_cell.rb +44 -0
- data/app/commands/decidim/budgets/add_line_item.rb +7 -10
- data/app/commands/decidim/budgets/admin/create_budget.rb +48 -0
- data/app/commands/decidim/budgets/admin/create_project.rb +26 -11
- data/app/commands/decidim/budgets/admin/destroy_budget.rb +42 -0
- data/app/commands/decidim/budgets/admin/import_proposals_to_budgets.rb +26 -25
- data/app/commands/decidim/budgets/admin/update_budget.rb +48 -0
- data/app/commands/decidim/budgets/admin/update_project.rb +20 -2
- data/app/commands/decidim/budgets/checkout.rb +7 -6
- data/app/commands/decidim/budgets/remove_line_item.rb +3 -2
- data/app/controllers/concerns/decidim/budgets/needs_current_order.rb +18 -2
- data/app/controllers/concerns/decidim/budgets/orderable.rb +57 -0
- data/app/controllers/decidim/budgets/admin/application_controller.rb +10 -2
- data/app/controllers/decidim/budgets/admin/attachment_collections_controller.rb +1 -1
- data/app/controllers/decidim/budgets/admin/attachments_controller.rb +2 -2
- data/app/controllers/decidim/budgets/admin/budgets_controller.rb +82 -0
- data/app/controllers/decidim/budgets/admin/projects_controller.rb +15 -12
- data/app/controllers/decidim/budgets/admin/proposals_imports_controller.rb +10 -2
- data/app/controllers/decidim/budgets/application_controller.rb +23 -0
- data/app/controllers/decidim/budgets/budgets_controller.rb +24 -0
- data/app/controllers/decidim/budgets/line_items_controller.rb +10 -6
- data/app/controllers/decidim/budgets/orders_controller.rb +20 -6
- data/app/controllers/decidim/budgets/projects_controller.rb +24 -19
- data/app/forms/decidim/budgets/admin/budget_form.rb +39 -0
- data/app/forms/decidim/budgets/admin/component_form.rb +44 -0
- data/app/forms/decidim/budgets/admin/project_form.rb +25 -9
- data/app/forms/decidim/budgets/admin/project_import_proposals_form.rb +4 -0
- data/app/helpers/decidim/budgets/admin/application_helper.rb +13 -0
- data/app/helpers/decidim/budgets/application_helper.rb +10 -0
- data/app/helpers/decidim/budgets/projects_helper.rb +13 -0
- data/app/jobs/decidim/budgets/send_order_summary_job.rb +15 -0
- data/app/mailers/decidim/budgets/order_summary_mailer.rb +36 -0
- data/app/models/decidim/budgets/budget.rb +34 -0
- data/app/models/decidim/budgets/line_item.rb +4 -4
- data/app/models/decidim/budgets/order.rb +47 -16
- data/app/models/decidim/budgets/project.rb +37 -4
- data/app/permissions/decidim/budgets/admin/permissions.rb +23 -10
- data/app/permissions/decidim/budgets/permissions.rb +28 -6
- data/app/presenters/decidim/budgets/admin_log/budget_presenter.rb +42 -0
- data/app/queries/decidim/budgets/filtered_projects.rb +9 -1
- data/app/queries/decidim/budgets/metrics/budget_followers_metric_measure.rb +3 -2
- data/app/queries/decidim/budgets/metrics/budget_participants_metric_measure.rb +6 -5
- data/app/serializers/decidim/budgets/data_portability_budgets_order_serializer.rb +3 -2
- data/app/services/decidim/budgets/project_search.rb +12 -24
- data/app/types/decidim/budgets/budget_type.rb +24 -0
- data/app/types/decidim/budgets/budgets_type.rb +6 -6
- data/app/types/decidim/budgets/project_type.rb +2 -1
- data/app/views/decidim/budgets/admin/budgets/_form.html.erb +23 -0
- data/app/views/decidim/budgets/admin/budgets/edit.html.erb +7 -0
- data/app/views/decidim/budgets/admin/budgets/index.html.erb +58 -0
- data/app/views/decidim/budgets/admin/budgets/new.html.erb +7 -0
- data/app/views/decidim/budgets/admin/projects/_form.html.erb +15 -10
- data/app/views/decidim/budgets/admin/projects/edit.html.erb +2 -2
- data/app/views/decidim/budgets/admin/projects/index.html.erb +20 -7
- data/app/views/decidim/budgets/admin/projects/new.html.erb +2 -2
- data/app/views/decidim/budgets/admin/projects/proposals_picker.html.erb +1 -0
- data/app/views/decidim/budgets/admin/proposals_imports/new.html.erb +1 -1
- data/app/views/decidim/budgets/budgets/index.html.erb +5 -0
- data/app/views/decidim/budgets/order_summary_mailer/order_summary.html.erb +22 -0
- data/app/views/decidim/budgets/projects/_budget_confirm.html.erb +3 -3
- data/app/views/decidim/budgets/projects/_budget_summary.html.erb +26 -7
- data/app/views/decidim/budgets/projects/_filters.html.erb +15 -7
- data/app/views/decidim/budgets/projects/_linked_projects.html.erb +2 -2
- data/app/views/decidim/budgets/projects/_order_progress.html.erb +14 -18
- data/app/views/decidim/budgets/projects/_order_selected_projects.html.erb +3 -3
- data/app/views/decidim/budgets/projects/_project.html.erb +1 -57
- data/app/views/decidim/budgets/projects/_project_budget_button.html.erb +36 -7
- data/app/views/decidim/budgets/projects/_projects.html.erb +8 -1
- data/app/views/decidim/budgets/projects/index.html.erb +15 -7
- data/app/views/decidim/budgets/projects/index.js.erb +8 -0
- data/app/views/decidim/budgets/projects/show.html.erb +22 -13
- data/config/locales/am-ET.yml +1 -0
- data/config/locales/ar.yml +2 -16
- data/config/locales/bg-BG.yml +7 -0
- data/config/locales/bg.yml +6 -0
- data/config/locales/ca.yml +125 -11
- data/config/locales/cs.yml +148 -34
- data/config/locales/da-DK.yml +1 -0
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +143 -29
- data/config/locales/el.yml +168 -0
- data/config/locales/en.yml +125 -11
- data/config/locales/eo.yml +1 -0
- data/config/locales/es-MX.yml +125 -11
- data/config/locales/es-PY.yml +125 -11
- data/config/locales/es.yml +125 -11
- data/config/locales/et-EE.yml +1 -0
- data/config/locales/et.yml +1 -0
- data/config/locales/eu.yml +5 -13
- data/config/locales/fi-plain.yml +126 -12
- data/config/locales/fi.yml +136 -22
- data/config/locales/fr-CA.yml +267 -0
- data/config/locales/fr.yml +125 -11
- data/config/locales/ga-IE.yml +1 -0
- data/config/locales/gl.yml +70 -15
- data/config/locales/hr-HR.yml +1 -0
- data/config/locales/hr.yml +1 -0
- data/config/locales/hu.yml +18 -12
- data/config/locales/id-ID.yml +2 -11
- data/config/locales/is-IS.yml +0 -11
- data/config/locales/is.yml +114 -0
- data/config/locales/it.yml +96 -12
- data/config/locales/ja-JP.yml +172 -0
- data/config/locales/ja.yml +262 -0
- data/config/locales/ko-KR.yml +1 -0
- data/config/locales/ko.yml +1 -0
- data/config/locales/lt-LT.yml +1 -0
- data/config/locales/lt.yml +1 -0
- data/config/locales/lv.yml +164 -0
- data/config/locales/mt-MT.yml +1 -0
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +112 -12
- data/config/locales/no.yml +42 -13
- data/config/locales/om-ET.yml +1 -0
- data/config/locales/pl.yml +175 -61
- data/config/locales/pt-BR.yml +3 -13
- data/config/locales/pt.yml +62 -46
- data/config/locales/ro-RO.yml +172 -0
- data/config/locales/ru.yml +2 -14
- data/config/locales/si-LK.yml +1 -0
- data/config/locales/sk-SK.yml +180 -0
- data/config/locales/sk.yml +166 -0
- data/config/locales/sl.yml +1 -0
- data/config/locales/so-SO.yml +1 -0
- data/config/locales/sr-CS.yml +27 -0
- data/config/locales/sv.yml +125 -11
- data/config/locales/sw-KE.yml +1 -0
- data/config/locales/ti-ER.yml +1 -0
- data/config/locales/tr-TR.yml +152 -38
- data/config/locales/uk.yml +2 -14
- data/config/locales/vi-VN.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +260 -0
- data/config/locales/zh-TW.yml +1 -0
- data/db/migrate/20200617105120_create_decidim_budgets.rb +15 -0
- data/db/migrate/20200629072626_rename_budget_to_budget_ammount.rb +7 -0
- data/db/migrate/20200629134013_add_budget_reference_to_project.rb +7 -0
- data/db/migrate/20200706142609_add_budget_reference_to_order.rb +7 -0
- data/db/migrate/20200714103519_move_budgets_to_own_model.rb +109 -0
- data/db/migrate/20200717140012_add_scope_to_budgets.rb +7 -0
- data/db/migrate/20200728075039_add_selected_at_to_project.rb +7 -0
- data/db/migrate/20200804175222_votes_enabled_to_votes_choices.rb +35 -0
- data/db/migrate/20200827154129_add_commentable_counter_cache_to_projects.rb +9 -0
- data/lib/decidim/budgets.rb +1 -0
- data/lib/decidim/budgets/admin_engine.rb +12 -5
- data/lib/decidim/budgets/component.rb +87 -38
- data/lib/decidim/budgets/engine.rb +8 -6
- data/lib/decidim/budgets/seeds/city.jpeg +0 -0
- data/lib/decidim/budgets/test/factories.rb +71 -9
- data/lib/decidim/budgets/version.rb +1 -1
- data/lib/decidim/budgets/workflows.rb +17 -0
- data/lib/decidim/budgets/workflows/all.rb +20 -0
- data/lib/decidim/budgets/workflows/base.rb +132 -0
- data/lib/decidim/budgets/workflows/one.rb +33 -0
- metadata +123 -19
@@ -8,6 +8,29 @@ module Decidim
|
|
8
8
|
# Note that it inherits from `Decidim::Components::BaseController`, which
|
9
9
|
# override its layout and provide all kinds of useful methods.
|
10
10
|
class ApplicationController < Decidim::Components::BaseController
|
11
|
+
helper_method :current_workflow, :voting_finished?, :voting_open?
|
12
|
+
|
13
|
+
def current_workflow
|
14
|
+
@current_workflow ||= Decidim::Budgets.workflows[workflow_name].new(current_component, current_user)
|
15
|
+
end
|
16
|
+
|
17
|
+
def voting_open?
|
18
|
+
current_settings.votes == "enabled"
|
19
|
+
end
|
20
|
+
|
21
|
+
def voting_finished?
|
22
|
+
current_settings.votes == "finished"
|
23
|
+
end
|
24
|
+
|
25
|
+
def show_votes_count?
|
26
|
+
current_settings.show_votes?
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def workflow_name
|
32
|
+
@workflow_name ||= current_component.settings.workflow.to_sym
|
33
|
+
end
|
11
34
|
end
|
12
35
|
end
|
13
36
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Budgets
|
5
|
+
# Exposes the budget resources so users can participate on them
|
6
|
+
class BudgetsController < Decidim::Budgets::ApplicationController
|
7
|
+
def index
|
8
|
+
redirect_to budget_projects_path(current_workflow.single) if current_workflow.single?
|
9
|
+
end
|
10
|
+
|
11
|
+
def show
|
12
|
+
raise ActionController::RoutingError, "Not Found" unless budget
|
13
|
+
|
14
|
+
redirect_to budget_projects_path(budget)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def budget
|
20
|
+
@budget ||= Budget.where(component: current_component).includes(:projects).find_by(id: params[:id])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -6,16 +6,16 @@ module Decidim
|
|
6
6
|
class LineItemsController < Decidim::Budgets::ApplicationController
|
7
7
|
include NeedsCurrentOrder
|
8
8
|
|
9
|
-
helper_method :project
|
9
|
+
helper_method :budget, :project
|
10
10
|
|
11
11
|
def create
|
12
|
-
enforce_permission_to :vote, :project, project: project
|
12
|
+
enforce_permission_to :vote, :project, project: project, budget: budget, workflow: current_workflow
|
13
13
|
|
14
14
|
respond_to do |format|
|
15
|
-
AddLineItem.call(
|
15
|
+
AddLineItem.call(persisted_current_order, project, current_user) do
|
16
16
|
on(:ok) do |order|
|
17
17
|
self.current_order = order
|
18
|
-
format.html {
|
18
|
+
format.html { redirect_back(fallback_location: budget_path(budget)) }
|
19
19
|
format.js { render "update_budget" }
|
20
20
|
end
|
21
21
|
|
@@ -30,7 +30,7 @@ module Decidim
|
|
30
30
|
respond_to do |format|
|
31
31
|
RemoveLineItem.call(current_order, project) do
|
32
32
|
on(:ok) do |_order|
|
33
|
-
format.html {
|
33
|
+
format.html { redirect_back(fallback_location: budget_path(budget)) }
|
34
34
|
format.js { render "update_budget" }
|
35
35
|
end
|
36
36
|
|
@@ -44,7 +44,11 @@ module Decidim
|
|
44
44
|
private
|
45
45
|
|
46
46
|
def project
|
47
|
-
@project ||= Project.find_by(id: params[:project_id],
|
47
|
+
@project ||= Project.includes(:budget).find_by(id: params[:project_id], decidim_budgets_budget_id: params[:budget_id])
|
48
|
+
end
|
49
|
+
|
50
|
+
def budget
|
51
|
+
@budget ||= project.budget
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
@@ -7,17 +7,17 @@ module Decidim
|
|
7
7
|
include NeedsCurrentOrder
|
8
8
|
|
9
9
|
def checkout
|
10
|
-
enforce_permission_to :vote, :project, order: current_order
|
10
|
+
enforce_permission_to :vote, :project, order: current_order, budget: budget, workflow: current_workflow
|
11
11
|
|
12
|
-
Checkout.call(current_order
|
12
|
+
Checkout.call(current_order) do
|
13
13
|
on(:ok) do
|
14
14
|
flash[:notice] = I18n.t("orders.checkout.success", scope: "decidim")
|
15
|
-
redirect_to
|
15
|
+
redirect_to budgets_path
|
16
16
|
end
|
17
17
|
|
18
18
|
on(:invalid) do
|
19
19
|
flash.now[:alert] = I18n.t("orders.checkout.error", scope: "decidim")
|
20
|
-
redirect_to
|
20
|
+
redirect_to budgets_path
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -26,15 +26,29 @@ module Decidim
|
|
26
26
|
CancelOrder.call(current_order) do
|
27
27
|
on(:ok) do
|
28
28
|
flash[:notice] = I18n.t("orders.destroy.success", scope: "decidim")
|
29
|
-
redirect_to
|
29
|
+
redirect_to redirect_path
|
30
30
|
end
|
31
31
|
|
32
32
|
on(:invalid) do
|
33
33
|
flash.now[:alert] = I18n.t("orders.destroy.error", scope: "decidim")
|
34
|
-
redirect_to
|
34
|
+
redirect_to redirect_path
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def budget
|
42
|
+
@budget ||= Budget.find_by(id: params[:budget_id])
|
43
|
+
end
|
44
|
+
|
45
|
+
def redirect_path
|
46
|
+
if params.dig(:return_to) == "budget"
|
47
|
+
budget_path(budget)
|
48
|
+
else
|
49
|
+
budgets_path
|
50
|
+
end
|
51
|
+
end
|
38
52
|
end
|
39
53
|
end
|
40
54
|
end
|
@@ -6,18 +6,34 @@ module Decidim
|
|
6
6
|
class ProjectsController < Decidim::Budgets::ApplicationController
|
7
7
|
include FilterResource
|
8
8
|
include NeedsCurrentOrder
|
9
|
-
include Orderable
|
9
|
+
include Decidim::Budgets::Orderable
|
10
10
|
|
11
|
-
helper_method :projects, :project
|
11
|
+
helper_method :projects, :project, :budget
|
12
|
+
|
13
|
+
def index
|
14
|
+
raise ActionController::RoutingError, "Not Found" unless budget
|
15
|
+
end
|
16
|
+
|
17
|
+
def show
|
18
|
+
raise ActionController::RoutingError, "Not Found" unless budget
|
19
|
+
raise ActionController::RoutingError, "Not Found" unless project
|
20
|
+
end
|
12
21
|
|
13
22
|
private
|
14
23
|
|
24
|
+
def budget
|
25
|
+
@budget ||= Budget.where(component: current_component).includes(:projects).find_by(id: params[:budget_id])
|
26
|
+
end
|
27
|
+
|
15
28
|
def projects
|
16
|
-
@projects
|
29
|
+
return @projects if @projects
|
30
|
+
|
31
|
+
@projects = search.results.page(params[:page]).per(current_component.settings.projects_per_page)
|
32
|
+
@projects = reorder(@projects)
|
17
33
|
end
|
18
34
|
|
19
35
|
def project
|
20
|
-
@project ||=
|
36
|
+
@project ||= Project.find_by(id: params[:id])
|
21
37
|
end
|
22
38
|
|
23
39
|
def search_klass
|
@@ -27,29 +43,18 @@ module Decidim
|
|
27
43
|
def default_filter_params
|
28
44
|
{
|
29
45
|
search_text: "",
|
46
|
+
status: default_filter_status_params,
|
30
47
|
scope_id: default_filter_scope_params,
|
31
48
|
category_id: default_filter_category_params
|
32
49
|
}
|
33
50
|
end
|
34
51
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
["all"] + current_component.participatory_space.categories.map { |category| category.id.to_s }
|
39
|
-
end
|
40
|
-
|
41
|
-
def default_filter_scope_params
|
42
|
-
return "all" unless current_component.participatory_space.scopes.any?
|
43
|
-
|
44
|
-
if current_component.participatory_space.scope
|
45
|
-
["all", current_component.participatory_space.scope.id] + current_component.participatory_space.scope.children.map { |scope| scope.id.to_s }
|
46
|
-
else
|
47
|
-
%w(all global) + current_component.participatory_space.scopes.map { |scope| scope.id.to_s }
|
48
|
-
end
|
52
|
+
def default_filter_status_params
|
53
|
+
voting_finished? ? %w(selected) : %w(all)
|
49
54
|
end
|
50
55
|
|
51
56
|
def context_params
|
52
|
-
{ component: current_component, organization: current_organization }
|
57
|
+
{ budget: budget, component: current_component, organization: current_organization }
|
53
58
|
end
|
54
59
|
end
|
55
60
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Budgets
|
5
|
+
module Admin
|
6
|
+
# This class holds a Form to create/update budgets from Decidim's admin panel.
|
7
|
+
class BudgetForm < Decidim::Form
|
8
|
+
include TranslatableAttributes
|
9
|
+
|
10
|
+
mimic :budget
|
11
|
+
|
12
|
+
translatable_attribute :title, String
|
13
|
+
attribute :weight, Integer, default: 0
|
14
|
+
translatable_attribute :description, String
|
15
|
+
attribute :total_budget, Integer, default: 0
|
16
|
+
attribute :decidim_scope_id, Integer
|
17
|
+
|
18
|
+
validates :title, translatable_presence: true
|
19
|
+
validates :weight, :total_budget, numericality: { greater_than_or_equal_to: 0 }
|
20
|
+
validates :scope, presence: true, if: ->(form) { form.decidim_scope_id.present? }
|
21
|
+
validates :decidim_scope_id, scope_belongs_to_component: true, if: ->(form) { form.decidim_scope_id.present? }
|
22
|
+
|
23
|
+
# Finds the Scope from the given decidim_scope_id, uses the compoenent scope if missing.
|
24
|
+
#
|
25
|
+
# Returns a Decidim::Scope
|
26
|
+
def scope
|
27
|
+
@scope ||= @decidim_scope_id ? current_component.scopes.find_by(id: @decidim_scope_id) : current_component.scope
|
28
|
+
end
|
29
|
+
|
30
|
+
# Scope identifier
|
31
|
+
#
|
32
|
+
# Returns the scope identifier related to the meeting
|
33
|
+
def decidim_scope_id
|
34
|
+
@decidim_scope_id || scope&.id
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Budgets
|
5
|
+
module Admin
|
6
|
+
# A form object for the budgets component. Used to attach the component
|
7
|
+
# to a participatory process from the admin panel.
|
8
|
+
#
|
9
|
+
class ComponentForm < Decidim::Admin::ComponentForm
|
10
|
+
validate :budget_voting_rule_enabled_setting, :budget_voting_rule_value_setting
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
# Validations on budget settings:
|
15
|
+
# - a voting rule must be enabled.
|
16
|
+
def budget_voting_rule_enabled_setting
|
17
|
+
return unless manifest&.name == :budgets
|
18
|
+
|
19
|
+
i18n_error_scope = "decidim.components.budgets.settings.global.form.errors"
|
20
|
+
if settings.vote_rule_threshold_percent_enabled.blank? && settings.vote_rule_minimum_budget_projects_enabled.blank?
|
21
|
+
settings.errors.add(:vote_rule_threshold_percent_enabled, I18n.t(:budget_voting_rule_required, scope: i18n_error_scope))
|
22
|
+
settings.errors.add(:vote_rule_minimum_budget_projects_enabled, I18n.t(:budget_voting_rule_required, scope: i18n_error_scope))
|
23
|
+
end
|
24
|
+
|
25
|
+
if settings.vote_rule_threshold_percent_enabled && settings.vote_rule_minimum_budget_projects_enabled
|
26
|
+
settings.errors.add(:vote_rule_threshold_percent_enabled, I18n.t(:budget_voting_rule_only_one, scope: i18n_error_scope))
|
27
|
+
settings.errors.add(:vote_rule_minimum_budget_projects_enabled, I18n.t(:budget_voting_rule_only_one, scope: i18n_error_scope))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# - the value must be a valid number
|
32
|
+
def budget_voting_rule_value_setting
|
33
|
+
return unless manifest&.name == :budgets
|
34
|
+
|
35
|
+
invalid_percent_number = settings.vote_threshold_percent.blank? || settings.vote_threshold_percent.to_i.negative?
|
36
|
+
settings.errors.add(:vote_threshold_percent) if settings.vote_rule_threshold_percent_enabled && invalid_percent_number
|
37
|
+
|
38
|
+
invalid_minimum_number = settings.vote_minimum_budget_projects_number.blank? || (settings.vote_minimum_budget_projects_number.to_i < 1)
|
39
|
+
settings.errors.add(:vote_minimum_budget_projects_number) if settings.vote_rule_minimum_budget_projects_enabled && invalid_minimum_number
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -12,24 +12,30 @@ module Decidim
|
|
12
12
|
translatable_attribute :title, String
|
13
13
|
translatable_attribute :description, String
|
14
14
|
|
15
|
-
attribute :
|
15
|
+
attribute :budget_amount, Integer
|
16
16
|
attribute :decidim_scope_id, Integer
|
17
17
|
attribute :decidim_category_id, Integer
|
18
18
|
attribute :proposal_ids, Array[Integer]
|
19
|
+
attribute :attachment, AttachmentForm
|
20
|
+
attribute :photos, Array[String]
|
21
|
+
attribute :add_photos, Array
|
22
|
+
attribute :selected, Boolean
|
19
23
|
|
20
24
|
validates :title, translatable_presence: true
|
21
25
|
validates :description, translatable_presence: true
|
22
|
-
validates :
|
26
|
+
validates :budget_amount, presence: true, numericality: { greater_than: 0 }
|
23
27
|
|
24
28
|
validates :category, presence: true, if: ->(form) { form.decidim_category_id.present? }
|
25
29
|
validates :scope, presence: true, if: ->(form) { form.decidim_scope_id.present? }
|
30
|
+
validates :decidim_scope_id, scope_belongs_to_component: true, if: ->(form) { form.decidim_scope_id.present? }
|
26
31
|
|
27
|
-
validate :
|
32
|
+
validate :notify_missing_attachment_if_errored
|
28
33
|
|
29
34
|
delegate :categories, to: :current_component
|
30
35
|
|
31
36
|
def map_model(model)
|
32
37
|
self.proposal_ids = model.linked_resources(:proposals, "included_proposals").pluck(:id)
|
38
|
+
self.selected = model.selected?
|
33
39
|
|
34
40
|
return unless model.categorization
|
35
41
|
|
@@ -38,9 +44,15 @@ module Decidim
|
|
38
44
|
|
39
45
|
def proposals
|
40
46
|
@proposals ||= Decidim.find_resource_manifest(:proposals).try(:resource_scope, current_component)
|
41
|
-
&.
|
47
|
+
&.where(id: proposal_ids)
|
42
48
|
&.order(title: :asc)
|
43
|
-
|
49
|
+
end
|
50
|
+
|
51
|
+
# Finds the Budget from the decidim_budgets_budget_id.
|
52
|
+
#
|
53
|
+
# Returns a Decidim::Budgets:Budget
|
54
|
+
def budget
|
55
|
+
@budget ||= context[:budget]
|
44
56
|
end
|
45
57
|
|
46
58
|
# Finds the Category from the decidim_category_id.
|
@@ -50,11 +62,11 @@ module Decidim
|
|
50
62
|
@category ||= categories.find_by(id: decidim_category_id)
|
51
63
|
end
|
52
64
|
|
53
|
-
# Finds the Scope from the given decidim_scope_id, uses
|
65
|
+
# Finds the Scope from the given decidim_scope_id, uses the component scope if missing.
|
54
66
|
#
|
55
67
|
# Returns a Decidim::Scope
|
56
68
|
def scope
|
57
|
-
@scope ||= @decidim_scope_id ?
|
69
|
+
@scope ||= @decidim_scope_id ? current_component.scopes.find_by(id: @decidim_scope_id) : current_component.scope
|
58
70
|
end
|
59
71
|
|
60
72
|
# Scope identifier
|
@@ -66,8 +78,12 @@ module Decidim
|
|
66
78
|
|
67
79
|
private
|
68
80
|
|
69
|
-
|
70
|
-
|
81
|
+
# This method will add an error to the `attachment` field only if there's
|
82
|
+
# any error in any other field. This is needed because when the form has
|
83
|
+
# an error, the attachment is lost, so we need a way to inform the user of
|
84
|
+
# this problem.
|
85
|
+
def notify_missing_attachment_if_errored
|
86
|
+
errors.add(:add_photos, :needs_to_be_reattached) if errors.any? && add_photos.present?
|
71
87
|
end
|
72
88
|
end
|
73
89
|
end
|
@@ -9,6 +9,16 @@ module Decidim
|
|
9
9
|
include Decidim::Comments::CommentsHelper
|
10
10
|
include ProjectsHelper
|
11
11
|
include Decidim::CheckBoxesTreeHelper
|
12
|
+
|
13
|
+
def filter_status_values
|
14
|
+
TreeNode.new(
|
15
|
+
TreePoint.new("", t("decidim.budgets.projects.filters.status_values.all")),
|
16
|
+
[
|
17
|
+
TreePoint.new("selected", t("decidim.budgets.projects.filters.status_values.selected")),
|
18
|
+
TreePoint.new("not_selected", t("decidim.budgets.projects.filters.status_values.not_selected"))
|
19
|
+
]
|
20
|
+
)
|
21
|
+
end
|
12
22
|
end
|
13
23
|
end
|
14
24
|
end
|
@@ -16,6 +16,19 @@ module Decidim
|
|
16
16
|
current_order&.budget_percent.to_f.floor
|
17
17
|
end
|
18
18
|
|
19
|
+
# Return the minimum percentage of the current order budget from the total budget
|
20
|
+
def current_order_budget_percent_minimum
|
21
|
+
return 0 if current_order.minimum_projects_rule?
|
22
|
+
|
23
|
+
component_settings.vote_threshold_percent
|
24
|
+
end
|
25
|
+
|
26
|
+
def budget_confirm_disabled_attr
|
27
|
+
return if current_order_can_be_checked_out?
|
28
|
+
|
29
|
+
%( disabled="disabled" ).html_safe
|
30
|
+
end
|
31
|
+
|
19
32
|
# Return true if the current order is checked out
|
20
33
|
delegate :checked_out?, to: :current_order, prefix: true, allow_nil: true
|
21
34
|
|