decidim-lausanne-budgets 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +141 -0
- data/Rakefile +93 -0
- data/app/cells/decidim/lausanne/budgets/base_cell.rb +24 -0
- data/app/cells/decidim/lausanne/budgets/budget_cell.rb +23 -0
- data/app/cells/decidim/lausanne/budgets/budget_information_modal/show.erb +21 -0
- data/app/cells/decidim/lausanne/budgets/budget_information_modal_cell.rb +24 -0
- data/app/cells/decidim/lausanne/budgets/budget_list_item/show.erb +21 -0
- data/app/cells/decidim/lausanne/budgets/budget_list_item_cell.rb +43 -0
- data/app/cells/decidim/lausanne/budgets/budget_m/data.erb +12 -0
- data/app/cells/decidim/lausanne/budgets/budget_m/footer.erb +5 -0
- data/app/cells/decidim/lausanne/budgets/budget_m_cell.rb +18 -0
- data/app/cells/decidim/lausanne/budgets/budgets_header/show.erb +7 -0
- data/app/cells/decidim/lausanne/budgets/budgets_header_cell.rb +16 -0
- data/app/cells/decidim/lausanne/budgets/budgets_list/card_list.erb +7 -0
- data/app/cells/decidim/lausanne/budgets/budgets_list/highlighted.erb +11 -0
- data/app/cells/decidim/lausanne/budgets/budgets_list/show.erb +20 -0
- data/app/cells/decidim/lausanne/budgets/budgets_list/voted.erb +43 -0
- data/app/cells/decidim/lausanne/budgets/budgets_list_cell.rb +40 -0
- data/app/cells/decidim/lausanne/budgets/limit_announcement_cell.rb +47 -0
- data/app/cells/decidim/lausanne/budgets/project_cell.rb +23 -0
- data/app/cells/decidim/lausanne/budgets/project_list_item/project_data.erb +19 -0
- data/app/cells/decidim/lausanne/budgets/project_list_item/project_data_vote_button.erb +22 -0
- data/app/cells/decidim/lausanne/budgets/project_list_item/project_image.erb +5 -0
- data/app/cells/decidim/lausanne/budgets/project_list_item/project_text.erb +23 -0
- data/app/cells/decidim/lausanne/budgets/project_list_item/show.erb +5 -0
- data/app/cells/decidim/lausanne/budgets/project_list_item_cell.rb +75 -0
- data/app/cells/decidim/lausanne/budgets/project_m/data.erb +12 -0
- data/app/cells/decidim/lausanne/budgets/project_m/footer.erb +5 -0
- data/app/cells/decidim/lausanne/budgets/project_m_cell.rb +24 -0
- data/app/cells/decidim/lausanne/budgets/project_selected_status_cell.rb +30 -0
- data/app/cells/decidim/lausanne/budgets/project_tags/show.erb +4 -0
- data/app/cells/decidim/lausanne/budgets/project_tags_cell.rb +20 -0
- data/app/cells/decidim/lausanne/budgets/project_voted_hint_cell.rb +35 -0
- data/app/cells/decidim/lausanne/budgets/project_votes_count_cell.rb +46 -0
- data/app/commands/decidim/lausanne/budgets/add_line_item.rb +54 -0
- data/app/commands/decidim/lausanne/budgets/admin/create_budget.rb +50 -0
- data/app/commands/decidim/lausanne/budgets/admin/create_project.rb +71 -0
- data/app/commands/decidim/lausanne/budgets/admin/destroy_budget.rb +44 -0
- data/app/commands/decidim/lausanne/budgets/admin/destroy_project.rb +44 -0
- data/app/commands/decidim/lausanne/budgets/admin/import_proposals_to_budgets.rb +87 -0
- data/app/commands/decidim/lausanne/budgets/admin/update_budget.rb +50 -0
- data/app/commands/decidim/lausanne/budgets/admin/update_project.rb +79 -0
- data/app/commands/decidim/lausanne/budgets/cancel_order.rb +46 -0
- data/app/commands/decidim/lausanne/budgets/checkout.rb +43 -0
- data/app/commands/decidim/lausanne/budgets/command.rb +16 -0
- data/app/commands/decidim/lausanne/budgets/create_user_record.rb +39 -0
- data/app/commands/decidim/lausanne/budgets/remove_line_item.rb +40 -0
- data/app/commands/decidim/lausanne/budgets/update_user_record.rb +40 -0
- data/app/controllers/concerns/decidim/lausanne/budgets/needs_current_order.rb +52 -0
- data/app/controllers/concerns/decidim/lausanne/budgets/orderable.rb +54 -0
- data/app/controllers/decidim/lausanne/budgets/admin/application_controller.rb +34 -0
- data/app/controllers/decidim/lausanne/budgets/admin/attachment_collections_controller.rb +27 -0
- data/app/controllers/decidim/lausanne/budgets/admin/attachments_controller.rb +28 -0
- data/app/controllers/decidim/lausanne/budgets/admin/lausanne_budgets_controller.rb +105 -0
- data/app/controllers/decidim/lausanne/budgets/admin/projects_controller.rb +98 -0
- data/app/controllers/decidim/lausanne/budgets/admin/proposals_imports_controller.rb +43 -0
- data/app/controllers/decidim/lausanne/budgets/application_controller.rb +77 -0
- data/app/controllers/decidim/lausanne/budgets/lausanne_budgets_controller.rb +29 -0
- data/app/controllers/decidim/lausanne/budgets/line_items_controller.rb +63 -0
- data/app/controllers/decidim/lausanne/budgets/orders_controller.rb +59 -0
- data/app/controllers/decidim/lausanne/budgets/projects_controller.rb +103 -0
- data/app/controllers/decidim/lausanne/budgets/user_records_controller.rb +121 -0
- data/app/forms/decidim/lausanne/budgets/admin/component_form.rb +93 -0
- data/app/forms/decidim/lausanne/budgets/admin/lausanne_budget_form.rb +41 -0
- data/app/forms/decidim/lausanne/budgets/admin/project_form.rb +96 -0
- data/app/forms/decidim/lausanne/budgets/admin/project_import_proposals_form.rb +52 -0
- data/app/forms/decidim/lausanne/budgets/user_record_form.rb +61 -0
- data/app/helpers/decidim/lausanne/budgets/admin/application_helper.rb +15 -0
- data/app/helpers/decidim/lausanne/budgets/application_helper.rb +26 -0
- data/app/helpers/decidim/lausanne/budgets/projects_helper.rb +103 -0
- data/app/jobs/decidim/lausanne/budgets/send_order_summary_job.rb +17 -0
- data/app/mailers/decidim/lausanne/budgets/order_summary_mailer.rb +38 -0
- data/app/models/decidim/lausanne/budgets/application_record.rb +12 -0
- data/app/models/decidim/lausanne/budgets/lausanne_budget.rb +37 -0
- data/app/models/decidim/lausanne/budgets/line_item.rb +23 -0
- data/app/models/decidim/lausanne/budgets/order.rb +204 -0
- data/app/models/decidim/lausanne/budgets/project.rb +129 -0
- data/app/models/decidim/lausanne/budgets/user_record.rb +28 -0
- data/app/packs/entrypoints/decidim_lausanne_budgets.js +2 -0
- data/app/packs/images/decidim/lausanne/budgets/icon.svg +1 -0
- data/app/packs/images/decidim/lausanne/budgets/lausanneparticipe.gif +0 -0
- data/app/packs/src/decidim/lausanne/budgets/index.js +1 -0
- data/app/packs/src/decidim/lausanne/budgets/progressFixed.js.es6 +23 -0
- data/app/packs/src/decidim/lausanne/budgets/projects.js.es6 +66 -0
- data/app/packs/stylesheets/decidim/lausanne/budgets/_budgets.scss +13 -0
- data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_budget-list.scss +195 -0
- data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_budget-meter.scss +85 -0
- data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_print.scss +73 -0
- data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_progress.scss +25 -0
- data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_proposal_link.scss +38 -0
- data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_share_buttons.scss +15 -0
- data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_user_record_form.scss +8 -0
- data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_votation-progress.scss +100 -0
- data/app/packs/stylesheets/decidim/lausanne/budgets/budget/_voting-rules.scss +20 -0
- data/app/permissions/decidim/lausanne/budgets/admin/permissions.rb +49 -0
- data/app/permissions/decidim/lausanne/budgets/permissions.rb +63 -0
- data/app/presenters/decidim/lausanne/budgets/admin_log/budget_presenter.rb +44 -0
- data/app/presenters/decidim/lausanne/budgets/admin_log/project_presenter.rb +44 -0
- data/app/queries/decidim/lausanne/budgets/filtered_projects.rb +47 -0
- data/app/queries/decidim/lausanne/budgets/metrics/budget_followers_metric_measure.rb +34 -0
- data/app/queries/decidim/lausanne/budgets/metrics/budget_participants_metric_measure.rb +29 -0
- data/app/queries/decidim/lausanne/budgets/query.rb +16 -0
- data/app/serializers/decidim/lausanne/budgets/data_portability_budgets_order_serializer.rb +46 -0
- data/app/services/decidim/lausanne/budgets/project_search.rb +65 -0
- data/app/services/decidim/lausanne/budgets/project_search_rs.rb +13 -0
- data/app/views/decidim/lausanne/budgets/admin/lausanne_budgets/_form.html.erb +23 -0
- data/app/views/decidim/lausanne/budgets/admin/lausanne_budgets/edit.html.erb +7 -0
- data/app/views/decidim/lausanne/budgets/admin/lausanne_budgets/index.html.erb +75 -0
- data/app/views/decidim/lausanne/budgets/admin/lausanne_budgets/new.html.erb +7 -0
- data/app/views/decidim/lausanne/budgets/admin/projects/_form.html.erb +47 -0
- data/app/views/decidim/lausanne/budgets/admin/projects/edit.html.erb +7 -0
- data/app/views/decidim/lausanne/budgets/admin/projects/index.html.erb +82 -0
- data/app/views/decidim/lausanne/budgets/admin/projects/new.html.erb +7 -0
- data/app/views/decidim/lausanne/budgets/admin/projects/proposals_picker.html.erb +1 -0
- data/app/views/decidim/lausanne/budgets/admin/proposals_imports/new.html.erb +32 -0
- data/app/views/decidim/lausanne/budgets/lausanne_budgets/index.html.erb +5 -0
- data/app/views/decidim/lausanne/budgets/line_items/update_budget.js.erb +41 -0
- data/app/views/decidim/lausanne/budgets/order_summary_mailer/order_summary.html.erb +22 -0
- data/app/views/decidim/lausanne/budgets/orders/show.html.erb +71 -0
- data/app/views/decidim/lausanne/budgets/projects/_budget_confirm.html.erb +37 -0
- data/app/views/decidim/lausanne/budgets/projects/_budget_excess.html.erb +14 -0
- data/app/views/decidim/lausanne/budgets/projects/_budget_summary.html.erb +95 -0
- data/app/views/decidim/lausanne/budgets/projects/_count.html.erb +1 -0
- data/app/views/decidim/lausanne/budgets/projects/_filters.html.erb +34 -0
- data/app/views/decidim/lausanne/budgets/projects/_filters_small_view.html.erb +18 -0
- data/app/views/decidim/lausanne/budgets/projects/_linked_projects.html.erb +12 -0
- data/app/views/decidim/lausanne/budgets/projects/_order_progress.html.erb +32 -0
- data/app/views/decidim/lausanne/budgets/projects/_order_selected_projects.html.erb +27 -0
- data/app/views/decidim/lausanne/budgets/projects/_order_total_budget.html.erb +7 -0
- data/app/views/decidim/lausanne/budgets/projects/_project.html.erb +1 -0
- data/app/views/decidim/lausanne/budgets/projects/_project_budget_button.html.erb +46 -0
- data/app/views/decidim/lausanne/budgets/projects/_projects.html.erb +13 -0
- data/app/views/decidim/lausanne/budgets/projects/_user_record_form.html.erb +40 -0
- data/app/views/decidim/lausanne/budgets/projects/_votation_banner.html.erb +71 -0
- data/app/views/decidim/lausanne/budgets/projects/index.html.erb +36 -0
- data/app/views/decidim/lausanne/budgets/projects/index.js.erb +10 -0
- data/app/views/decidim/lausanne/budgets/projects/show.html.erb +81 -0
- data/app/views/decidim/lausanne/budgets/user_records/edit.html.erb +6 -0
- data/app/views/decidim/proposals/proposals/show.html.erb +172 -0
- data/app/views/layouts/lausanne_budgets/print.erb +12 -0
- data/config/assets.rb +11 -0
- data/config/initializers/social_share.rb +3 -0
- data/config/locales/fr.yml +381 -0
- data/config/routes.rb +7 -0
- data/db/migrate/20170127114122_create_lausanne_projects.rb +15 -0
- data/db/migrate/20170127114123_create_lausanne_user_records.rb +14 -0
- data/db/migrate/20170130095615_create_lausanne_orders.rb +16 -0
- data/db/migrate/20170130101825_create_lausanne_line_items.rb +12 -0
- data/db/migrate/20170215132708_add_lausanne_reference_to_projects.rb +13 -0
- data/db/migrate/20200617105120_create_decidim_lausanne_budgets.rb +15 -0
- data/db/migrate/20200629134013_add_lausanne_budget_reference_to_project.rb +7 -0
- data/db/migrate/20200706142609_add_lausanne_budget_reference_to_order.rb +7 -0
- data/db/migrate/20200714103519_move_lausanne_budgets_to_own_model.rb +109 -0
- data/db/migrate/20200717140012_add_lausanne_scope_to_budgets.rb +7 -0
- data/db/migrate/20200728075039_add_lausanne_selected_at_to_project.rb +7 -0
- data/db/migrate/20200804175222_lausanne_votes_enabled_to_votes_choices.rb +35 -0
- data/db/migrate/20200827154129_add_lausanne_commentable_counter_cache_to_projects.rb +9 -0
- data/db/migrate/20210310120613_add_lausanne_followable_counter_cache_to_budgets.rb +16 -0
- data/db/migrate/20210508180613_add_checkboxes_to_user_record.rb +9 -0
- data/db/migrate/20221001151237_add_excerpt_to_decidim_lausanne_budgets_project.rb +7 -0
- data/lib/decidim/lausanne/budgets/admin.rb +12 -0
- data/lib/decidim/lausanne/budgets/admin_engine.rb +40 -0
- data/lib/decidim/lausanne/budgets/component.rb +107 -0
- data/lib/decidim/lausanne/budgets/current_user_record_middleware.rb +17 -0
- data/lib/decidim/lausanne/budgets/engine.rb +57 -0
- data/lib/decidim/lausanne/budgets/project_serializer.rb +83 -0
- data/lib/decidim/lausanne/budgets/seeds/Exampledocument.pdf +0 -0
- data/lib/decidim/lausanne/budgets/seeds/city.jpeg +0 -0
- data/lib/decidim/lausanne/budgets/test/factories.rb +169 -0
- data/lib/decidim/lausanne/budgets/version.rb +15 -0
- data/lib/decidim/lausanne/budgets/workflows/all.rb +22 -0
- data/lib/decidim/lausanne/budgets/workflows/base.rb +140 -0
- data/lib/decidim/lausanne/budgets/workflows/one.rb +35 -0
- data/lib/decidim/lausanne/budgets/workflows.rb +19 -0
- data/lib/decidim/lausanne/budgets.rb +17 -0
- metadata +372 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
module Admin
|
7
|
+
# A command with all the business logic when an admin imports proposals from
|
8
|
+
# one component to projects of a budget.
|
9
|
+
class ImportProposalsToBudgets < Decidim::Lausanne::Budgets::Command
|
10
|
+
# Public: Initializes the command.
|
11
|
+
#
|
12
|
+
# form - A form object with the params.
|
13
|
+
def initialize(form)
|
14
|
+
@form = form
|
15
|
+
end
|
16
|
+
|
17
|
+
# Executes the command. Broadcasts these events:
|
18
|
+
#
|
19
|
+
# - :ok when everything is valid.
|
20
|
+
# - :invalid if the form wasn't valid and we couldn't proceed.
|
21
|
+
#
|
22
|
+
# Returns nothing.
|
23
|
+
def call
|
24
|
+
return broadcast(:invalid) unless @form.valid?
|
25
|
+
|
26
|
+
broadcast(:ok, create_projects_from_accepted_proposals)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :form
|
32
|
+
|
33
|
+
def create_projects_from_accepted_proposals
|
34
|
+
transaction do
|
35
|
+
proposals.map do |original_proposal|
|
36
|
+
next if proposal_already_copied?(original_proposal)
|
37
|
+
|
38
|
+
new_project = create_project_from_proposal!(original_proposal)
|
39
|
+
|
40
|
+
new_project.link_resources([original_proposal], "included_proposals")
|
41
|
+
end.compact
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def create_project_from_proposal!(original_proposal)
|
46
|
+
params = {
|
47
|
+
budget: form.budget,
|
48
|
+
title: original_proposal.title,
|
49
|
+
description: original_proposal.body,
|
50
|
+
budget_amount: form.default_budget,
|
51
|
+
category: original_proposal.category,
|
52
|
+
scope: original_proposal.scope
|
53
|
+
}
|
54
|
+
|
55
|
+
@project = Decidim.traceability.create!(
|
56
|
+
Project,
|
57
|
+
form.current_user,
|
58
|
+
params,
|
59
|
+
visibility: "all"
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def proposals
|
64
|
+
return all_proposals if form.scope_id.blank?
|
65
|
+
|
66
|
+
all_proposals.where(decidim_scope_id: form.scope_id)
|
67
|
+
end
|
68
|
+
|
69
|
+
def all_proposals
|
70
|
+
Decidim::Proposals::Proposal.where(component: origin_component)
|
71
|
+
.where(state: :accepted)
|
72
|
+
end
|
73
|
+
|
74
|
+
def origin_component
|
75
|
+
form.origin_component
|
76
|
+
end
|
77
|
+
|
78
|
+
def proposal_already_copied?(original_proposal)
|
79
|
+
original_proposal.linked_resources(:projects, "included_proposals").any? do |project|
|
80
|
+
project.budget == form.budget
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
module Admin
|
7
|
+
# This command is executed when the user updates a Budget
|
8
|
+
# from the admin panel.
|
9
|
+
class UpdateBudget < Decidim::Lausanne::Budgets::Command
|
10
|
+
def initialize(form, budget)
|
11
|
+
@form = form
|
12
|
+
@budget = budget
|
13
|
+
end
|
14
|
+
|
15
|
+
# Updates the budget if valid.
|
16
|
+
#
|
17
|
+
# Broadcasts :ok if successful, :invalid otherwise.
|
18
|
+
def call
|
19
|
+
return broadcast(:invalid) if form.invalid?
|
20
|
+
|
21
|
+
update_budget!
|
22
|
+
|
23
|
+
broadcast(:ok, budget)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :form, :budget
|
29
|
+
|
30
|
+
def update_budget!
|
31
|
+
attributes = {
|
32
|
+
scope: form.scope,
|
33
|
+
title: form.title,
|
34
|
+
weight: form.weight,
|
35
|
+
description: form.description,
|
36
|
+
total_budget: form.total_budget
|
37
|
+
}
|
38
|
+
|
39
|
+
Decidim.traceability.update!(
|
40
|
+
budget,
|
41
|
+
form.current_user,
|
42
|
+
attributes,
|
43
|
+
visibility: "all"
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
module Admin
|
7
|
+
# This command is executed when the user changes a Project from the admin
|
8
|
+
# panel.
|
9
|
+
class UpdateProject < Decidim::Lausanne::Budgets::Command
|
10
|
+
include ::Decidim::AttachmentMethods
|
11
|
+
include ::Decidim::GalleryMethods
|
12
|
+
|
13
|
+
# Initializes an UpdateProject Command.
|
14
|
+
#
|
15
|
+
# form - The form from which to get the data.
|
16
|
+
# project - The current instance of the project to be updated.
|
17
|
+
def initialize(form, project)
|
18
|
+
@form = form
|
19
|
+
@project = project
|
20
|
+
@attached_to = project
|
21
|
+
end
|
22
|
+
|
23
|
+
# Updates the project if valid.
|
24
|
+
#
|
25
|
+
# Broadcasts :ok if successful, :invalid otherwise.
|
26
|
+
def call
|
27
|
+
return broadcast(:invalid) if form.invalid?
|
28
|
+
|
29
|
+
if process_gallery?
|
30
|
+
build_gallery
|
31
|
+
return broadcast(:invalid) if gallery_invalid?
|
32
|
+
end
|
33
|
+
|
34
|
+
transaction do
|
35
|
+
update_project
|
36
|
+
link_proposals
|
37
|
+
create_gallery if process_gallery?
|
38
|
+
photo_cleanup!
|
39
|
+
end
|
40
|
+
|
41
|
+
broadcast(:ok)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
attr_reader :project, :form, :gallery
|
47
|
+
|
48
|
+
def update_project
|
49
|
+
Decidim.traceability.update!(
|
50
|
+
project,
|
51
|
+
form.current_user,
|
52
|
+
scope: form.scope,
|
53
|
+
category: form.category,
|
54
|
+
title: form.title,
|
55
|
+
description: form.description,
|
56
|
+
excerpt: form.excerpt,
|
57
|
+
budget_amount: form.budget_amount,
|
58
|
+
selected_at: selected_at
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def proposals
|
63
|
+
@proposals ||= project.sibling_scope(:proposals).where(id: form.proposal_ids)
|
64
|
+
end
|
65
|
+
|
66
|
+
def link_proposals
|
67
|
+
project.link_resources(proposals, "included_proposals")
|
68
|
+
end
|
69
|
+
|
70
|
+
def selected_at
|
71
|
+
return unless form.selected
|
72
|
+
|
73
|
+
Time.current
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
# A command with all the business to cancel an order.
|
7
|
+
class CancelOrder < Decidim::Lausanne::Budgets::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# order - The current order for the user.
|
11
|
+
def initialize(order)
|
12
|
+
@order = order
|
13
|
+
end
|
14
|
+
|
15
|
+
# Executes the command. Broadcasts these events:
|
16
|
+
#
|
17
|
+
# - :ok when everything is valid.
|
18
|
+
#
|
19
|
+
# Returns nothing.
|
20
|
+
def call
|
21
|
+
transaction do
|
22
|
+
cancel_order!
|
23
|
+
end
|
24
|
+
broadcast(:ok, @order)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def user_record
|
29
|
+
@order.user_record
|
30
|
+
end
|
31
|
+
# If the order is not linked to a user,
|
32
|
+
# remove the user_record and the order.
|
33
|
+
# If the order is linked to a user, remove all the votes
|
34
|
+
def cancel_order!
|
35
|
+
@order.line_items.each do |line|
|
36
|
+
line.destroy!
|
37
|
+
end
|
38
|
+
unless user_record.user
|
39
|
+
@order.user_record.destroy!
|
40
|
+
end
|
41
|
+
@order.update(checked_out_at: nil)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
# A command with all the business to checkout.
|
7
|
+
class Checkout < Decidim::Lausanne::Budgets::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# order - The current order for the user.
|
11
|
+
def initialize(order)
|
12
|
+
@order = order
|
13
|
+
end
|
14
|
+
|
15
|
+
# Executes the command. Broadcasts these events:
|
16
|
+
#
|
17
|
+
# - :ok when everything is valid.
|
18
|
+
# - :invalid if the there is an error.
|
19
|
+
#
|
20
|
+
# Returns nothing.
|
21
|
+
def call
|
22
|
+
return broadcast(:invalid, order) unless checkout!
|
23
|
+
|
24
|
+
broadcast(:ok, order)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :order
|
30
|
+
|
31
|
+
def checkout!
|
32
|
+
return unless order && order.valid?
|
33
|
+
|
34
|
+
@order.with_lock do
|
35
|
+
SendOrderSummaryJob.perform_later(@order)
|
36
|
+
@order.checked_out_at = Time.current
|
37
|
+
@order.save
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
# maintains compatibility with v0.26 which uses Rectify
|
7
|
+
if defined? ::Decidim::Command
|
8
|
+
class Command < ::Decidim::Command
|
9
|
+
end
|
10
|
+
else
|
11
|
+
class Command < ::Rectify::Command
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
class CreateUserRecord < Decidim::Lausanne::Budgets::Command
|
7
|
+
attr_reader :user_record, :budget, :current_user
|
8
|
+
def initialize(user_record, budget, current_user)
|
9
|
+
@user_record = user_record
|
10
|
+
@budget = budget
|
11
|
+
@current_user = current_user
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
return broadcast(:invalid) unless budget
|
16
|
+
return broadcast(:invalid) if user_record.invalid?
|
17
|
+
new_user_record = nil
|
18
|
+
transaction do
|
19
|
+
new_user_record = UserRecord.create(
|
20
|
+
first_name: user_record.first_name,
|
21
|
+
last_name: user_record.last_name,
|
22
|
+
birthdate: user_record.birthdate,
|
23
|
+
iam_lausanne: user_record.iam_lausanne,
|
24
|
+
its_me: user_record.its_me,
|
25
|
+
allow_process_data: user_record.allow_process_data,
|
26
|
+
user: current_user || nil,
|
27
|
+
order: Order.create(
|
28
|
+
budget: budget
|
29
|
+
)
|
30
|
+
)
|
31
|
+
rescue e
|
32
|
+
broadcast(:invalid)
|
33
|
+
end
|
34
|
+
broadcast(:ok, new_user_record)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
# A command with all the business to add remove line items from orders
|
7
|
+
class RemoveLineItem < Decidim::Lausanne::Budgets::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# order - The current order for the user
|
11
|
+
# project - The the project to remove from the order
|
12
|
+
def initialize(order, project)
|
13
|
+
@order = order
|
14
|
+
@project = project
|
15
|
+
end
|
16
|
+
|
17
|
+
# Executes the command. Broadcasts these events:
|
18
|
+
#
|
19
|
+
# - :ok when everything is valid.
|
20
|
+
# - :invalid if the there is an error.
|
21
|
+
#
|
22
|
+
# Returns nothing.
|
23
|
+
def call
|
24
|
+
return broadcast(:invalid) if @order.checked_out?
|
25
|
+
|
26
|
+
remove_line_item
|
27
|
+
broadcast(:ok, @order)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :project
|
33
|
+
|
34
|
+
def remove_line_item
|
35
|
+
@order.projects.destroy(project)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
class UpdateUserRecord < Decidim::Lausanne::Budgets::Command
|
7
|
+
attr_reader :user_record, :budget, :current_user
|
8
|
+
def initialize(user_record, budget, current_user)
|
9
|
+
@user_record = user_record
|
10
|
+
@budget = budget
|
11
|
+
@current_user = current_user
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
return broadcast(:invalid) unless budget
|
16
|
+
return broadcast(:invalid) if user_record.invalid?
|
17
|
+
|
18
|
+
new_user_record = nil
|
19
|
+
transaction do
|
20
|
+
new_user_record = UserRecord.create(
|
21
|
+
first_name: user_record.first_name,
|
22
|
+
last_name: user_record.last_name,
|
23
|
+
birthdate: user_record.birthdate,
|
24
|
+
iam_lausanne: user_record.iam_lausanne,
|
25
|
+
its_me: user_record.its_me,
|
26
|
+
allow_process_data: user_record.allow_process_data,
|
27
|
+
user: current_user || nil,
|
28
|
+
order: Order.create(
|
29
|
+
budget: budget
|
30
|
+
)
|
31
|
+
)
|
32
|
+
rescue e
|
33
|
+
broadcast(:invalid)
|
34
|
+
end
|
35
|
+
broadcast(:ok, new_user_record)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module Lausanne
|
7
|
+
module Budgets
|
8
|
+
# Shared behaviour for controllers that need the current order to be present.
|
9
|
+
module NeedsCurrentOrder
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
helper_method :current_order, :can_have_order?, :voted_for?, :user_record_for_budget?,
|
14
|
+
:user_record_submitted?
|
15
|
+
|
16
|
+
def user_record_for_budget?
|
17
|
+
return true if current_user_record.new_record?
|
18
|
+
current_user_record.order.id == current_order.id
|
19
|
+
end
|
20
|
+
def user_record_submitted?
|
21
|
+
!current_user_record.new_record?
|
22
|
+
end
|
23
|
+
|
24
|
+
def current_order
|
25
|
+
@current_order ||= Order.includes(:projects).find_or_initialize_by(
|
26
|
+
user_record: current_user_record,
|
27
|
+
budget: budget
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
def current_order=(order)
|
32
|
+
@current_order = order
|
33
|
+
end
|
34
|
+
|
35
|
+
def persisted_current_order
|
36
|
+
current_order if current_order&.persisted?
|
37
|
+
end
|
38
|
+
|
39
|
+
def can_have_order?
|
40
|
+
voting_open? &&
|
41
|
+
allowed_to?(:create, :order, budget: budget, workflow: current_workflow)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return true if the user has voted the project
|
45
|
+
def voted_for?(project)
|
46
|
+
current_order && current_order.projects.include?(project)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module Lausanne
|
7
|
+
module Budgets
|
8
|
+
# Common logic to sorting resources
|
9
|
+
module Orderable
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
include Decidim::Orderable
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# Available orders based on enabled settings
|
18
|
+
def available_orders
|
19
|
+
@available_orders ||= begin
|
20
|
+
available_orders = []
|
21
|
+
available_orders << "asc"
|
22
|
+
available_orders << "most_voted" if votes_are_visible?
|
23
|
+
available_orders += %w(highest_cost lowest_cost)
|
24
|
+
available_orders
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def default_order
|
29
|
+
available_orders.first
|
30
|
+
end
|
31
|
+
|
32
|
+
def votes_are_visible?
|
33
|
+
current_settings.show_votes?
|
34
|
+
end
|
35
|
+
|
36
|
+
def reorder(projects)
|
37
|
+
case order
|
38
|
+
when "highest_cost"
|
39
|
+
projects.order(budget_amount: :desc)
|
40
|
+
when "lowest_cost"
|
41
|
+
projects.order(budget_amount: :asc)
|
42
|
+
when "asc"
|
43
|
+
projects.order(Arel.sql("title->>'#{I18n.locale}' ASC"))
|
44
|
+
when "random"
|
45
|
+
projects.order_randomly(random_seed)
|
46
|
+
else
|
47
|
+
projects
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
module Admin
|
7
|
+
# This controller is the abstract class from which all other controllers of
|
8
|
+
# this engine inherit.
|
9
|
+
#
|
10
|
+
# Note that it inherits from `Decidim::Components::BaseController`, which
|
11
|
+
# override its layout and provide all kinds of useful methods.
|
12
|
+
class ApplicationController < Decidim::Admin::Components::BaseController
|
13
|
+
helper_method :budget, :projects, :project
|
14
|
+
|
15
|
+
def budget
|
16
|
+
@budget ||= LausanneBudget.where(component: current_component).includes(:projects).find_by(id: params[:lausanne_budget_id])
|
17
|
+
end
|
18
|
+
|
19
|
+
def projects
|
20
|
+
return unless budget
|
21
|
+
|
22
|
+
@projects ||= budget.projects
|
23
|
+
end
|
24
|
+
|
25
|
+
def project
|
26
|
+
return unless projects
|
27
|
+
|
28
|
+
@project ||= projects.find(params[:id])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
module Admin
|
7
|
+
# Controller that allows managing all the attachment collections for a budget.
|
8
|
+
#
|
9
|
+
class AttachmentCollectionsController < Admin::ApplicationController
|
10
|
+
include Decidim::Admin::Concerns::HasAttachmentCollections
|
11
|
+
|
12
|
+
def after_destroy_path
|
13
|
+
project_attachment_collections_path(project, project.component, current_participatory_space)
|
14
|
+
end
|
15
|
+
|
16
|
+
def collection_for
|
17
|
+
project
|
18
|
+
end
|
19
|
+
|
20
|
+
def project
|
21
|
+
@project ||= Decidim::Lausanne::Budgets::Project.find(params[:project_id])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Lausanne
|
5
|
+
module Budgets
|
6
|
+
module Admin
|
7
|
+
# Controller that allows managing all the attachments for a participatory
|
8
|
+
# process.
|
9
|
+
#
|
10
|
+
class AttachmentsController < Admin::ApplicationController
|
11
|
+
include Decidim::Admin::Concerns::HasAttachments
|
12
|
+
|
13
|
+
def after_destroy_path
|
14
|
+
lausanne_budget_projects_path(project.budget)
|
15
|
+
end
|
16
|
+
|
17
|
+
def attached_to
|
18
|
+
project
|
19
|
+
end
|
20
|
+
|
21
|
+
def project
|
22
|
+
@project ||= Decidim::Lausanne::Budgets::Project.find(params[:project_id])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|