decidim-budgets 0.0.3

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.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +23 -0
  3. data/Rakefile +2 -0
  4. data/app/assets/config/decidim_budgets_manifest.js +1 -0
  5. data/app/assets/images/decidim/budgets/icon.svg +4 -0
  6. data/app/assets/javascripts/decidim/budgets/projects.js.es6 +28 -0
  7. data/app/assets/stylesheets/decidim/budgets/_budgets.scss +1 -0
  8. data/app/assets/stylesheets/decidim/budgets/budget/_budget-list.scss +32 -0
  9. data/app/assets/stylesheets/decidim/budgets/budget/_budget-meter.scss +78 -0
  10. data/app/assets/stylesheets/decidim/budgets/budget/_progress.scss +17 -0
  11. data/app/commands/decidim/budgets/add_line_item.rb +43 -0
  12. data/app/commands/decidim/budgets/admin/create_project.rb +52 -0
  13. data/app/commands/decidim/budgets/admin/update_project.rb +56 -0
  14. data/app/commands/decidim/budgets/cancel_order.rb +36 -0
  15. data/app/commands/decidim/budgets/checkout.rb +34 -0
  16. data/app/commands/decidim/budgets/remove_line_item.rb +35 -0
  17. data/app/controllers/concerns/decidim/budgets/needs_current_order.rb +27 -0
  18. data/app/controllers/decidim/budgets/admin/application_controller.rb +14 -0
  19. data/app/controllers/decidim/budgets/admin/projects_controller.rb +69 -0
  20. data/app/controllers/decidim/budgets/application_controller.rb +13 -0
  21. data/app/controllers/decidim/budgets/line_items_controller.rb +43 -0
  22. data/app/controllers/decidim/budgets/orders_controller.rb +38 -0
  23. data/app/controllers/decidim/budgets/projects_controller.rb +44 -0
  24. data/app/forms/decidim/budgets/admin/project_form.rb +44 -0
  25. data/app/helpers/decidim/budgets/application_helper.rb +12 -0
  26. data/app/helpers/decidim/budgets/projects_helper.rb +29 -0
  27. data/app/models/decidim/budgets/application_record.rb +9 -0
  28. data/app/models/decidim/budgets/line_item.rb +20 -0
  29. data/app/models/decidim/budgets/order.rb +52 -0
  30. data/app/models/decidim/budgets/project.rb +15 -0
  31. data/app/services/decidim/budgets/project_search.rb +58 -0
  32. data/app/views/decidim/budgets/admin/projects/_form.html.erb +31 -0
  33. data/app/views/decidim/budgets/admin/projects/edit.html.erb +9 -0
  34. data/app/views/decidim/budgets/admin/projects/index.html.erb +27 -0
  35. data/app/views/decidim/budgets/admin/projects/new.html.erb +9 -0
  36. data/app/views/decidim/budgets/line_items/update_budget.js.erb +21 -0
  37. data/app/views/decidim/budgets/projects/_budget_confirm.html.erb +30 -0
  38. data/app/views/decidim/budgets/projects/_budget_excess.html.erb +14 -0
  39. data/app/views/decidim/budgets/projects/_budget_summary.html.erb +46 -0
  40. data/app/views/decidim/budgets/projects/_count.html.erb +1 -0
  41. data/app/views/decidim/budgets/projects/_filters.html.erb +24 -0
  42. data/app/views/decidim/budgets/projects/_linked_projects.html.erb +12 -0
  43. data/app/views/decidim/budgets/projects/_order_progress.html.erb +34 -0
  44. data/app/views/decidim/budgets/projects/_order_selected_projects.html.erb +25 -0
  45. data/app/views/decidim/budgets/projects/_order_total_budget.html.erb +1 -0
  46. data/app/views/decidim/budgets/projects/_project.html.erb +40 -0
  47. data/app/views/decidim/budgets/projects/_project_budget_button.html.erb +9 -0
  48. data/app/views/decidim/budgets/projects/_projects.html.erb +8 -0
  49. data/app/views/decidim/budgets/projects/_tags.html.erb +10 -0
  50. data/app/views/decidim/budgets/projects/index.html.erb +26 -0
  51. data/app/views/decidim/budgets/projects/index.js.erb +2 -0
  52. data/app/views/decidim/budgets/projects/show.html.erb +48 -0
  53. data/config/i18n-tasks.yml +4 -0
  54. data/config/locales/ca.yml +84 -0
  55. data/config/locales/en.yml +95 -0
  56. data/config/locales/es.yml +84 -0
  57. data/db/migrate/20170127114122_create_projects.rb +15 -0
  58. data/db/migrate/20170130095615_create_orders.rb +13 -0
  59. data/db/migrate/20170130101825_create_line_items.rb +10 -0
  60. data/lib/decidim/budgets/admin.rb +9 -0
  61. data/lib/decidim/budgets/admin_engine.rb +22 -0
  62. data/lib/decidim/budgets/feature.rb +59 -0
  63. data/lib/decidim/budgets/list_engine.rb +30 -0
  64. data/lib/decidim/budgets/test/factories.rb +43 -0
  65. data/lib/decidim/budgets.rb +11 -0
  66. metadata +210 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: aa8f0db3125a7ddb93f9076d6e4fff7256cb1934
4
+ data.tar.gz: 109c2f3e91977e116a7d5baccf9fa142a78e100f
5
+ SHA512:
6
+ metadata.gz: 673eb952dde2972556bdcb286255d7a456f9f738764901f0c832adea7b8ea3d606b248cf4f6a33fc166ef4ed21b95f53c71d4f112745be53228e445acb7f04fd
7
+ data.tar.gz: 4e22d0bb6a0acc9a3c8820ef305eefb3a273521063908895e84f0b6a2c65c9a692e05986047949c5faaa54e396e2c9c522642be4e331d869552cfd7e215a8779
data/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # Decidim::Budgets
2
+ The Budgets module adds projects to any participatory process. It adds a CRUD engine to the admin and public views scoped inside the participatory process. Projects will link to related proposals and have a budget. The users should be able to distribute a budget between these projects.
3
+
4
+ ## Usage
5
+ Budgets will be available as a Feature for a Participatory Process.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'decidim-budgets
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ ## Contributing
20
+ See [Decidim](https://github.com/AjuntamentdeBarcelona/decidim).
21
+
22
+ ## License
23
+ See [Decidim](https://github.com/AjuntamentdeBarcelona/decidim).
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ # frozen_string_literal: true
2
+ require "decidim/dev/common_rake"
@@ -0,0 +1 @@
1
+ //= link decidim/budgets/projects.js
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
2
+ <path d="M2 0v1h-.75c-.68 0-1.25.57-1.25 1.25v.5c0 .68.44 1.24 1.09 1.41l2.56.66c.14.04.34.29.34.44v.5c0 .14-.11.25-.25.25h-2.5c-.12 0-.21-.04-.25-.06v-.94h-1v1c0 .34.2.63.44.78.23.16.52.22.81.22h.75v1h1v-1h.75c.69 0 1.25-.56 1.25-1.25v-.5c0-.68-.44-1.24-1.09-1.41l-2.56-.66c-.14-.04-.34-.29-.34-.44v-.5c0-.14.11-.25.25-.25h2.5c.11 0 .21.04.25.06v.94h1v-1c0-.34-.2-.63-.44-.78-.23-.16-.52-.22-.81-.22h-.75v-1h-1z"
3
+ transform="translate(1)" />
4
+ </svg>
@@ -0,0 +1,28 @@
1
+ // = require_self
2
+
3
+ $(() => {
4
+ const $projects = $('#projects, #project');
5
+ const $budgetSummaryTotal = $('.budget-summary__total');
6
+ const $budgetExceedModal = $('#budget-excess');
7
+
8
+ const totalBudget = $budgetSummaryTotal.data('total-budget');
9
+
10
+ const cancelEvent = (event) => {
11
+ event.stopPropagation();
12
+ event.preventDefault();
13
+ };
14
+
15
+ $projects.on('click', '.budget--list__action', (event) => {
16
+ const currentBudget = $('.budget-summary__progressbox').data('current-budget');
17
+ const $currentTarget = $(event.currentTarget);
18
+ const projectBudget = $currentTarget.data('budget');
19
+
20
+ if ($currentTarget.attr('disabled')) {
21
+ cancelEvent(event);
22
+
23
+ } else if ($currentTarget.data('add') && ((currentBudget + projectBudget) > totalBudget)) {
24
+ $budgetExceedModal.foundation('toggle');
25
+ cancelEvent(event);
26
+ }
27
+ });
28
+ });
@@ -0,0 +1 @@
1
+ @import "budget/*";
@@ -0,0 +1,32 @@
1
+ .budget-list__title{
2
+ @include breakpoint(smallmedium down){
3
+ font-size: $global-font-size;
4
+ }
5
+ }
6
+ .budget-list__data{
7
+ flex-basis: 9rem;
8
+ @include breakpoint(medium){
9
+ flex-direction: row;
10
+ flex-basis: 16rem;
11
+ }
12
+ }
13
+ .budget-list__data--added{
14
+ background-color: mix(white, $success, 80%);
15
+ }
16
+
17
+ .budget-list__number{
18
+ @include breakpoint(medium down){
19
+ font-size: 1rem;
20
+ }
21
+ @include breakpoint(medium){
22
+ flex-grow: 1;
23
+ font-size: 1.5rem;
24
+ margin-right: 1rem;
25
+ margin-bottom: 0;
26
+ text-align: right;
27
+ }
28
+ }
29
+
30
+ .budget--list__action{
31
+ margin-bottom: 0;
32
+ }
@@ -0,0 +1,78 @@
1
+ .budget-summary__total{
2
+ margin-bottom: .5rem;
3
+ }
4
+
5
+ .budget-summary__progressbox{
6
+ align-items: stretch;
7
+ margin-bottom: .5rem;
8
+ @include breakpoint(smallmedium down){
9
+ text-align: center;
10
+ }
11
+ @include breakpoint(medium){
12
+ display: flex;
13
+ }
14
+ .button{
15
+ margin-bottom: 0;
16
+ }
17
+ }
18
+
19
+ .progressbox-fixed-wrapper{
20
+ position: fixed;
21
+ top: 0;
22
+ left: 0;
23
+ right: 0;
24
+ z-index: 2;
25
+ background: $white;
26
+ box-shadow: 0 2px 7px rgba(black,.1);
27
+ display: none;
28
+ &.is-progressbox-visible{
29
+ display: block;
30
+ }
31
+
32
+ }
33
+
34
+ .budget-summary__progressbox--fixed{
35
+ margin: auto;
36
+ max-width: $global-width;
37
+ padding: 1rem 2rem;
38
+ @include breakpoint(mediumlarge){
39
+ padding: 1rem 4rem;
40
+ }
41
+ display: flex;
42
+ }
43
+
44
+ .budget-progress{
45
+ flex-grow: 1;
46
+ margin-bottom: .5rem;
47
+ min-height: 1.5rem;
48
+ @include breakpoint(medium){
49
+ min-height: 2rem;
50
+ margin-bottom: 0;
51
+ margin-right: 1rem;
52
+ }
53
+ }
54
+
55
+ .budget-progress--fixed{
56
+ min-height: 2rem;
57
+ margin-bottom: 0;
58
+ margin-right: 1rem;
59
+ }
60
+
61
+
62
+ .budget-progress__meter{
63
+ min-width: 0.1%;
64
+ }
65
+
66
+ .budget-summary__selected{
67
+ border-top: $border;
68
+ padding-top: .5rem;
69
+ padding-bottom: .5rem;
70
+ }
71
+
72
+ .budget-summary__selected-list{
73
+ margin-top: 2rem;
74
+ }
75
+
76
+ .budget-summary__selected-number{
77
+ margin: 0 .5rem;
78
+ }
@@ -0,0 +1,17 @@
1
+ //Foundation progress extension
2
+ .progress{
3
+ position: relative;
4
+ }
5
+ .progress-meter--minimum{
6
+ background: repeating-linear-gradient(-55deg, rgba(white, 0.2), rgba(white, 0.2) 8px, rgba(black, 0.03) 8px, rgba(black, 0.03) 16px);
7
+ position: absolute;
8
+ }
9
+
10
+ .progress-meter-text--right{
11
+ left: auto;
12
+ min-width: 100%;
13
+ transform: translate(0, -50%);
14
+ text-align: right;
15
+ padding-left: 1rem;
16
+ padding-right: .5rem;
17
+ }
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Budgets
4
+ # A command with all the business to add new line items to orders
5
+ class AddLineItem < Rectify::Command
6
+ # Public: Initializes the command.
7
+ #
8
+ # order - The current order for the user or nil if it is not created yet.
9
+ # project - The the project to include in the order
10
+ # current_user - The current user logged in
11
+ def initialize(current_order, project, current_user)
12
+ @order = current_order
13
+ @project = project
14
+ @current_user = current_user
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
+ transaction do
25
+ return broadcast(:invalid) if order.checked_out?
26
+ add_line_item
27
+ broadcast(:ok, order)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def order
34
+ @order ||= Order.create!(user: @current_user, feature: @project.feature)
35
+ end
36
+
37
+ def add_line_item
38
+ order.projects << @project
39
+ order.save!
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Budgets
4
+ module Admin
5
+ # This command is executed when the user creates a Project from the admin
6
+ # panel.
7
+ class CreateProject < Rectify::Command
8
+ def initialize(form)
9
+ @form = form
10
+ end
11
+
12
+ # Creates the project if valid.
13
+ #
14
+ # Broadcasts :ok if successful, :invalid otherwise.
15
+ def call
16
+ return broadcast(:invalid) if @form.invalid?
17
+
18
+ transaction do
19
+ create_project
20
+ link_proposals
21
+ end
22
+
23
+ broadcast(:ok)
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :project
29
+
30
+ def create_project
31
+ @project = Project.create!(
32
+ scope: @form.scope,
33
+ category: @form.category,
34
+ feature: @form.current_feature,
35
+ title: @form.title,
36
+ short_description: @form.short_description,
37
+ description: @form.description,
38
+ budget: @form.budget
39
+ )
40
+ end
41
+
42
+ def proposals
43
+ @proposals ||= project.sibling_scope(:proposals).where(id: @form.proposal_ids)
44
+ end
45
+
46
+ def link_proposals
47
+ project.link_resources(proposals, "included_proposals")
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Budgets
4
+ module Admin
5
+ # This command is executed when the user changes a Project from the admin
6
+ # panel.
7
+ class UpdateProject < Rectify::Command
8
+ # Initializes an UpdateProject Command.
9
+ #
10
+ # form - The form from which to get the data.
11
+ # project - The current instance of the project to be updated.
12
+ def initialize(form, project)
13
+ @form = form
14
+ @project = project
15
+ end
16
+
17
+ # Updates the project if valid.
18
+ #
19
+ # Broadcasts :ok if successful, :invalid otherwise.
20
+ def call
21
+ return broadcast(:invalid) if form.invalid?
22
+
23
+ transaction do
24
+ update_project
25
+ link_proposals
26
+ end
27
+
28
+ broadcast(:ok)
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :project, :form
34
+
35
+ def update_project
36
+ project.update_attributes!(
37
+ scope: form.scope,
38
+ category: form.category,
39
+ title: form.title,
40
+ short_description: form.short_description,
41
+ description: form.description,
42
+ budget: form.budget
43
+ )
44
+ end
45
+
46
+ def proposals
47
+ @proposals ||= project.sibling_scope(:proposals).where(id: form.proposal_ids)
48
+ end
49
+
50
+ def link_proposals
51
+ project.link_resources(proposals, "included_proposals")
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Budgets
4
+ # A command with all the business to cancel an order.
5
+ class CancelOrder < Rectify::Command
6
+ # Public: Initializes the command.
7
+ #
8
+ # order - The current order for the user.
9
+ def initialize(order)
10
+ @order = order
11
+ end
12
+
13
+ # Executes the command. Broadcasts these events:
14
+ #
15
+ # - :ok when everything is valid.
16
+ # - :invalid if the there is an error.
17
+ #
18
+ # Returns nothing.
19
+ def call
20
+ return broadcast(:invalid) if invalid_order?
21
+ cancel_order!
22
+ broadcast(:ok, @order)
23
+ end
24
+
25
+ private
26
+
27
+ def invalid_order?
28
+ !@order&.checked_out?
29
+ end
30
+
31
+ def cancel_order!
32
+ @order.destroy!
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Budgets
4
+ # A command with all the business to checkout.
5
+ class Checkout < Rectify::Command
6
+ # Public: Initializes the command.
7
+ #
8
+ # order - The current order for the user.
9
+ # feature - The current feature.
10
+ def initialize(order, feature)
11
+ @order = order
12
+ @feature = feature
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) unless @order&.can_checkout?
23
+ checkout!
24
+ broadcast(:ok, @order)
25
+ end
26
+
27
+ private
28
+
29
+ def checkout!
30
+ @order.update_attributes!(checked_out_at: Time.current)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Budgets
4
+ # A command with all the business to add remove line items from orders
5
+ class RemoveLineItem < Rectify::Command
6
+ # Public: Initializes the command.
7
+ #
8
+ # order - The current order for the user
9
+ # project - The the project to remove from the order
10
+ def initialize(order, project)
11
+ @order = order
12
+ @project = project
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) if @order.checked_out?
23
+ remove_line_item
24
+ broadcast(:ok, @order)
25
+ end
26
+
27
+ private
28
+
29
+ def remove_line_item
30
+ @order.projects.destroy(@project)
31
+ @order.save!
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module Decidim
6
+ module Budgets
7
+ # Shared behaviour for controllers that need the current order to be present.
8
+ module NeedsCurrentOrder
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ helper_method :current_order
13
+
14
+ # The current order created by the user.
15
+ #
16
+ # Returns an Order.
17
+ def current_order
18
+ @current_order ||= Order.includes(:projects).find_by(user: current_user, feature: current_feature)
19
+ end
20
+
21
+ def current_order=(order)
22
+ @current_order = order
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Budgets
4
+ module Admin
5
+ # This controller is the abstract class from which all other controllers of
6
+ # this engine inherit.
7
+ #
8
+ # Note that it inherits from `Decidim::Features::BaseController`, which
9
+ # override its layout and provide all kinds of useful methods.
10
+ class ApplicationController < Decidim::Admin::Features::BaseController
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Budgets
4
+ module Admin
5
+ # This controller allows an admin to manage projects from a Participatory Process
6
+ class ProjectsController < Admin::ApplicationController
7
+ helper_method :projects
8
+
9
+ def new
10
+ @form = form(ProjectForm).instance
11
+ end
12
+
13
+ def create
14
+ @form = form(ProjectForm).from_params(params)
15
+
16
+ CreateProject.call(@form) do
17
+ on(:ok) do
18
+ flash[:notice] = I18n.t("projects.create.success", scope: "decidim.budgets.admin")
19
+ redirect_to projects_path
20
+ end
21
+
22
+ on(:invalid) do
23
+ flash.now[:alert] = I18n.t("projects.create.invalid", scope: "decidim.budgets.admin")
24
+ render action: "new"
25
+ end
26
+ end
27
+ end
28
+
29
+ def edit
30
+ @form = form(ProjectForm).from_model(project)
31
+ end
32
+
33
+ def update
34
+ @form = form(ProjectForm).from_params(params)
35
+
36
+ UpdateProject.call(@form, project) do
37
+ on(:ok) do
38
+ flash[:notice] = I18n.t("projects.update.success", scope: "decidim.budgets.admin")
39
+ redirect_to projects_path
40
+ end
41
+
42
+ on(:invalid) do
43
+ flash.now[:alert] = I18n.t("projects.update.invalid", scope: "decidim.budgets.admin")
44
+ render action: "edit"
45
+ end
46
+ end
47
+ end
48
+
49
+ def destroy
50
+ project.destroy!
51
+
52
+ flash[:notice] = I18n.t("projects.destroy.success", scope: "decidim.budgets.admin")
53
+
54
+ redirect_to projects_path
55
+ end
56
+
57
+ private
58
+
59
+ def projects
60
+ @projects ||= Project.where(feature: current_feature)
61
+ end
62
+
63
+ def project
64
+ @project ||= projects.find(params[:id])
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Budgets
5
+ # This controller is the abstract class from which all other controllers of
6
+ # this engine inherit.
7
+ #
8
+ # Note that it inherits from `Decidim::Components::BaseController`, which
9
+ # override its layout and provide all kinds of useful methods.
10
+ class ApplicationController < Decidim::Features::BaseController
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Budgets
5
+ # Exposes the line items resource so users can create and remove from orders.
6
+ class LineItemsController < Decidim::Budgets::ApplicationController
7
+ include NeedsCurrentOrder
8
+
9
+ helper_method :project
10
+
11
+ def create
12
+ AddLineItem.call(current_order, project, current_user) do
13
+ on(:ok) do |order|
14
+ self.current_order = order
15
+ render "update_budget"
16
+ end
17
+
18
+ on(:invalid) do
19
+ render nothing: true, status: 422
20
+ end
21
+ end
22
+ end
23
+
24
+ def destroy
25
+ RemoveLineItem.call(current_order, project) do
26
+ on(:ok) do |_order|
27
+ render "update_budget"
28
+ end
29
+
30
+ on(:invalid) do
31
+ render nothing: true, status: 422
32
+ end
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def project
39
+ @project ||= Project.where(id: params[:project_id], feature: current_feature).first
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Budgets
5
+ # Exposes the order resource so users can checkout it.
6
+ class OrdersController < Decidim::Budgets::ApplicationController
7
+ include NeedsCurrentOrder
8
+
9
+ def checkout
10
+ Checkout.call(current_order, current_feature) do
11
+ on(:ok) do
12
+ flash[:notice] = I18n.t("orders.checkout.success", scope: "decidim")
13
+ redirect_to projects_path
14
+ end
15
+
16
+ on(:invalid) do
17
+ flash.now[:alert] = I18n.t("orders.checkout.error", scope: "decidim")
18
+ redirect_to projects_path
19
+ end
20
+ end
21
+ end
22
+
23
+ def destroy
24
+ CancelOrder.call(current_order) do
25
+ on(:ok) do
26
+ flash[:notice] = I18n.t("orders.destroy.success", scope: "decidim")
27
+ redirect_to projects_path
28
+ end
29
+
30
+ on(:invalid) do
31
+ flash.now[:alert] = I18n.t("orders.destroy.error", scope: "decidim")
32
+ redirect_to projects_path
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end