decidim-budgets 0.22.0 → 0.23.0

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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -3
  3. data/app/assets/stylesheets/decidim/budgets/budget/_budget-list.scss +5 -0
  4. data/app/cells/decidim/budgets/base_cell.rb +22 -0
  5. data/app/cells/decidim/budgets/budget_cell.rb +21 -0
  6. data/app/cells/decidim/budgets/budget_information_modal/show.erb +28 -0
  7. data/app/cells/decidim/budgets/budget_information_modal_cell.rb +22 -0
  8. data/app/cells/decidim/budgets/budget_list_item/show.erb +22 -0
  9. data/app/cells/decidim/budgets/budget_list_item_cell.rb +40 -0
  10. data/app/cells/decidim/budgets/budget_m/data.erb +12 -0
  11. data/app/cells/decidim/budgets/budget_m/footer.erb +5 -0
  12. data/app/cells/decidim/budgets/budget_m_cell.rb +16 -0
  13. data/app/cells/decidim/budgets/budgets_header/show.erb +7 -0
  14. data/app/cells/decidim/budgets/budgets_header_cell.rb +14 -0
  15. data/app/cells/decidim/budgets/budgets_list/card_list.erb +7 -0
  16. data/app/cells/decidim/budgets/budgets_list/highlighted.erb +11 -0
  17. data/app/cells/decidim/budgets/budgets_list/show.erb +20 -0
  18. data/app/cells/decidim/budgets/budgets_list/voted.erb +43 -0
  19. data/app/cells/decidim/budgets/budgets_list_cell.rb +39 -0
  20. data/app/cells/decidim/budgets/limit_announcement_cell.rb +52 -0
  21. data/app/cells/decidim/budgets/project_list_item/project_data.erb +17 -3
  22. data/app/cells/decidim/budgets/project_list_item/project_data_vote_button.erb +2 -2
  23. data/app/cells/decidim/budgets/project_list_item/project_text.erb +11 -5
  24. data/app/cells/decidim/budgets/project_list_item/show.erb +3 -3
  25. data/app/cells/decidim/budgets/project_list_item_cell.rb +8 -28
  26. data/app/cells/decidim/budgets/project_m/data.erb +1 -1
  27. data/app/cells/decidim/budgets/project_m_cell.rb +4 -0
  28. data/app/cells/decidim/budgets/project_selected_status_cell.rb +28 -0
  29. data/app/cells/decidim/budgets/project_tags/show.erb +5 -0
  30. data/app/cells/decidim/budgets/project_tags_cell.rb +18 -0
  31. data/app/cells/decidim/budgets/project_voted_hint_cell.rb +33 -0
  32. data/app/cells/decidim/budgets/project_votes_count_cell.rb +44 -0
  33. data/app/commands/decidim/budgets/add_line_item.rb +7 -10
  34. data/app/commands/decidim/budgets/admin/create_budget.rb +48 -0
  35. data/app/commands/decidim/budgets/admin/create_project.rb +12 -7
  36. data/app/commands/decidim/budgets/admin/destroy_budget.rb +42 -0
  37. data/app/commands/decidim/budgets/admin/import_proposals_to_budgets.rb +26 -25
  38. data/app/commands/decidim/budgets/admin/update_budget.rb +48 -0
  39. data/app/commands/decidim/budgets/admin/update_project.rb +8 -1
  40. data/app/commands/decidim/budgets/checkout.rb +6 -6
  41. data/app/commands/decidim/budgets/remove_line_item.rb +3 -2
  42. data/app/controllers/concerns/decidim/budgets/needs_current_order.rb +14 -2
  43. data/app/controllers/concerns/decidim/budgets/orderable.rb +3 -7
  44. data/app/controllers/decidim/budgets/admin/application_controller.rb +10 -2
  45. data/app/controllers/decidim/budgets/admin/attachment_collections_controller.rb +1 -1
  46. data/app/controllers/decidim/budgets/admin/attachments_controller.rb +2 -2
  47. data/app/controllers/decidim/budgets/admin/budgets_controller.rb +82 -0
  48. data/app/controllers/decidim/budgets/admin/projects_controller.rb +7 -7
  49. data/app/controllers/decidim/budgets/admin/proposals_imports_controller.rb +10 -2
  50. data/app/controllers/decidim/budgets/application_controller.rb +23 -0
  51. data/app/controllers/decidim/budgets/budgets_controller.rb +24 -0
  52. data/app/controllers/decidim/budgets/line_items_controller.rb +9 -5
  53. data/app/controllers/decidim/budgets/orders_controller.rb +20 -6
  54. data/app/controllers/decidim/budgets/projects_controller.rb +19 -18
  55. data/app/forms/decidim/budgets/admin/budget_form.rb +39 -0
  56. data/app/forms/decidim/budgets/admin/project_form.rb +14 -10
  57. data/app/forms/decidim/budgets/admin/project_import_proposals_form.rb +4 -0
  58. data/app/helpers/decidim/budgets/admin/application_helper.rb +13 -0
  59. data/app/helpers/decidim/budgets/application_helper.rb +10 -0
  60. data/app/helpers/decidim/budgets/projects_helper.rb +0 -4
  61. data/app/mailers/decidim/budgets/order_summary_mailer.rb +5 -3
  62. data/app/models/decidim/budgets/budget.rb +34 -0
  63. data/app/models/decidim/budgets/line_item.rb +4 -4
  64. data/app/models/decidim/budgets/order.rb +22 -19
  65. data/app/models/decidim/budgets/project.rb +34 -5
  66. data/app/permissions/decidim/budgets/admin/permissions.rb +23 -10
  67. data/app/permissions/decidim/budgets/permissions.rb +28 -6
  68. data/app/presenters/decidim/budgets/admin_log/budget_presenter.rb +42 -0
  69. data/app/queries/decidim/budgets/filtered_projects.rb +9 -1
  70. data/app/queries/decidim/budgets/metrics/budget_followers_metric_measure.rb +3 -2
  71. data/app/queries/decidim/budgets/metrics/budget_participants_metric_measure.rb +6 -5
  72. data/app/serializers/decidim/budgets/data_portability_budgets_order_serializer.rb +3 -2
  73. data/app/services/decidim/budgets/project_search.rb +12 -24
  74. data/app/types/decidim/budgets/budget_type.rb +24 -0
  75. data/app/types/decidim/budgets/budgets_type.rb +6 -6
  76. data/app/types/decidim/budgets/project_type.rb +2 -1
  77. data/app/views/decidim/budgets/admin/budgets/_form.html.erb +23 -0
  78. data/app/views/decidim/budgets/admin/budgets/edit.html.erb +7 -0
  79. data/app/views/decidim/budgets/admin/budgets/index.html.erb +58 -0
  80. data/app/views/decidim/budgets/admin/budgets/new.html.erb +7 -0
  81. data/app/views/decidim/budgets/admin/projects/_form.html.erb +12 -4
  82. data/app/views/decidim/budgets/admin/projects/edit.html.erb +2 -2
  83. data/app/views/decidim/budgets/admin/projects/index.html.erb +20 -7
  84. data/app/views/decidim/budgets/admin/projects/new.html.erb +2 -2
  85. data/app/views/decidim/budgets/admin/proposals_imports/new.html.erb +1 -1
  86. data/app/views/decidim/budgets/budgets/index.html.erb +5 -0
  87. data/app/views/decidim/budgets/order_summary_mailer/order_summary.html.erb +1 -0
  88. data/app/views/decidim/budgets/projects/_budget_confirm.html.erb +3 -3
  89. data/app/views/decidim/budgets/projects/_budget_summary.html.erb +19 -6
  90. data/app/views/decidim/budgets/projects/_filters.html.erb +6 -2
  91. data/app/views/decidim/budgets/projects/_linked_projects.html.erb +1 -1
  92. data/app/views/decidim/budgets/projects/_order_progress.html.erb +10 -6
  93. data/app/views/decidim/budgets/projects/_order_selected_projects.html.erb +3 -3
  94. data/app/views/decidim/budgets/projects/_project_budget_button.html.erb +36 -7
  95. data/app/views/decidim/budgets/projects/index.html.erb +12 -4
  96. data/app/views/decidim/budgets/projects/show.html.erb +17 -10
  97. data/config/locales/am-ET.yml +1 -0
  98. data/config/locales/ar.yml +2 -11
  99. data/config/locales/bg.yml +6 -0
  100. data/config/locales/ca.yml +102 -10
  101. data/config/locales/cs.yml +105 -13
  102. data/config/locales/da.yml +1 -0
  103. data/config/locales/de.yml +90 -9
  104. data/config/locales/el.yml +3 -9
  105. data/config/locales/en.yml +101 -9
  106. data/config/locales/eo.yml +1 -0
  107. data/config/locales/es-MX.yml +101 -9
  108. data/config/locales/es-PY.yml +101 -9
  109. data/config/locales/es.yml +102 -10
  110. data/config/locales/et.yml +1 -0
  111. data/config/locales/eu.yml +3 -8
  112. data/config/locales/fi-plain.yml +102 -10
  113. data/config/locales/fi.yml +103 -11
  114. data/config/locales/fr-CA.yml +100 -9
  115. data/config/locales/fr.yml +100 -9
  116. data/config/locales/gl.yml +2 -7
  117. data/config/locales/hr.yml +1 -0
  118. data/config/locales/hu.yml +2 -7
  119. data/config/locales/id-ID.yml +2 -6
  120. data/config/locales/is-IS.yml +0 -6
  121. data/config/locales/is.yml +114 -0
  122. data/config/locales/it.yml +71 -9
  123. data/config/locales/ja-JP.yml +1 -0
  124. data/config/locales/ja.yml +262 -0
  125. data/config/locales/ko-KR.yml +1 -0
  126. data/config/locales/ko.yml +1 -0
  127. data/config/locales/lt.yml +1 -0
  128. data/config/locales/{lv-LV.yml → lv.yml} +2 -10
  129. data/config/locales/mt.yml +1 -0
  130. data/config/locales/nl.yml +88 -10
  131. data/config/locales/no.yml +22 -9
  132. data/config/locales/om-ET.yml +1 -0
  133. data/config/locales/pl.yml +113 -22
  134. data/config/locales/pt-BR.yml +2 -7
  135. data/config/locales/pt.yml +3 -9
  136. data/config/locales/ro-RO.yml +3 -10
  137. data/config/locales/ru.yml +2 -9
  138. data/config/locales/sk.yml +2 -11
  139. data/config/locales/sl.yml +0 -4
  140. data/config/locales/so-SO.yml +1 -0
  141. data/config/locales/sr-CS.yml +0 -2
  142. data/config/locales/sv.yml +80 -9
  143. data/config/locales/ti-ER.yml +1 -0
  144. data/config/locales/tr-TR.yml +2 -7
  145. data/config/locales/uk.yml +2 -9
  146. data/config/locales/vi-VN.yml +1 -0
  147. data/config/locales/vi.yml +1 -0
  148. data/config/locales/zh-CN.yml +260 -0
  149. data/config/locales/zh-TW.yml +1 -0
  150. data/db/migrate/20200617105120_create_decidim_budgets.rb +15 -0
  151. data/db/migrate/20200629072626_rename_budget_to_budget_ammount.rb +7 -0
  152. data/db/migrate/20200629134013_add_budget_reference_to_project.rb +7 -0
  153. data/db/migrate/20200706142609_add_budget_reference_to_order.rb +7 -0
  154. data/db/migrate/20200714103519_move_budgets_to_own_model.rb +109 -0
  155. data/db/migrate/20200717140012_add_scope_to_budgets.rb +7 -0
  156. data/db/migrate/20200728075039_add_selected_at_to_project.rb +7 -0
  157. data/db/migrate/20200804175222_votes_enabled_to_votes_choices.rb +35 -0
  158. data/db/migrate/20200827154129_add_commentable_counter_cache_to_projects.rb +9 -0
  159. data/lib/decidim/budgets.rb +1 -0
  160. data/lib/decidim/budgets/admin_engine.rb +10 -5
  161. data/lib/decidim/budgets/component.rb +83 -38
  162. data/lib/decidim/budgets/engine.rb +8 -6
  163. data/lib/decidim/budgets/test/factories.rb +42 -13
  164. data/lib/decidim/budgets/version.rb +1 -1
  165. data/lib/decidim/budgets/workflows.rb +17 -0
  166. data/lib/decidim/budgets/workflows/all.rb +20 -0
  167. data/lib/decidim/budgets/workflows/base.rb +132 -0
  168. data/lib/decidim/budgets/workflows/one.rb +33 -0
  169. metadata +84 -17
  170. data/app/cells/decidim/budgets/project_list_item/project_data_number.erb +0 -3
  171. data/app/cells/decidim/budgets/project_list_item/project_data_votes.erb +0 -7
@@ -2,19 +2,19 @@
2
2
 
3
3
  module Decidim
4
4
  module Budgets
5
- # The data store for a LineItem in the Decidim::Budgets component. It describes an
5
+ # The data store for a LineItem in the Budget resource. It describes an
6
6
  # association between an order and a project.
7
7
  class LineItem < Budgets::ApplicationRecord
8
8
  belongs_to :order, class_name: "Decidim::Budgets::Order", foreign_key: "decidim_order_id"
9
9
  belongs_to :project, class_name: "Decidim::Budgets::Project", foreign_key: "decidim_project_id"
10
10
 
11
11
  validates :order, uniqueness: { scope: :project }
12
- validate :same_component
12
+ validate :same_budget
13
13
 
14
- def same_component
14
+ def same_budget
15
15
  return unless order && project
16
16
 
17
- errors.add(:order, :invalid) unless order.component == project.component
17
+ errors.add(:order, :invalid) unless order.budget == project.budget
18
18
  end
19
19
  end
20
20
  end
@@ -5,18 +5,17 @@ module Decidim
5
5
  # The data store for a Order in the Decidim::Budgets component. It is unique for each
6
6
  # user and component and contains a collection of projects
7
7
  class Order < Budgets::ApplicationRecord
8
- include Decidim::HasComponent
9
8
  include Decidim::DataPortability
10
9
  include Decidim::NewsletterParticipant
11
10
 
12
- component_manifest_name "budgets"
13
-
14
11
  belongs_to :user, class_name: "Decidim::User", foreign_key: "decidim_user_id"
15
-
12
+ belongs_to :budget, foreign_key: "decidim_budgets_budget_id", class_name: "Decidim::Budgets::Budget", inverse_of: :orders
13
+ has_one :component, through: :budget, foreign_key: "decidim_component_id", class_name: "Decidim::Component"
16
14
  has_many :line_items, class_name: "Decidim::Budgets::LineItem", foreign_key: "decidim_order_id", dependent: :destroy
17
15
  has_many :projects, through: :line_items, class_name: "Decidim::Budgets::Project", foreign_key: "decidim_project_id"
18
16
 
19
- validates :user, uniqueness: { scope: :component }
17
+ validates :user, uniqueness: { scope: :budget }
18
+ validates :budget, presence: true
20
19
  validate :user_belongs_to_organization
21
20
 
22
21
  validates :total_budget, numericality: {
@@ -34,7 +33,7 @@ module Decidim
34
33
 
35
34
  # Public: Returns the sum of project budgets
36
35
  def total_budget
37
- projects.to_a.sum(&:budget)
36
+ projects.to_a.sum(&:budget_amount)
38
37
  end
39
38
 
40
39
  # Public: Returns true if the order has been checked out
@@ -53,36 +52,36 @@ module Decidim
53
52
 
54
53
  # Public: Returns the order budget percent from the settings total budget
55
54
  def budget_percent
56
- (total_budget.to_f / component.settings.total_budget.to_f) * 100
55
+ (total_budget.to_f / budget.total_budget.to_f) * 100
57
56
  end
58
57
 
59
58
  # Public: Returns the required minimum budget to checkout
60
59
  def minimum_budget
61
- return 0 unless component
60
+ return 0 unless budget
62
61
  return 0 if minimum_projects_rule?
63
62
 
64
- component.settings.total_budget.to_f * (component.settings.vote_threshold_percent.to_f / 100)
63
+ budget.total_budget.to_f * (budget.settings.vote_threshold_percent.to_f / 100)
65
64
  end
66
65
 
67
66
  # Public: Returns the required maximum budget to checkout
68
67
  def maximum_budget
69
- return 0 unless component
68
+ return 0 unless budget
70
69
 
71
- component.settings.total_budget.to_f
70
+ budget.total_budget.to_f
72
71
  end
73
72
 
74
73
  # Public: Returns if it is required a minimum projects limit to checkout
75
74
  def minimum_projects_rule?
76
- return unless component
75
+ return unless budget
77
76
 
78
- component.settings.vote_rule_minimum_budget_projects_enabled
77
+ budget.settings.vote_rule_minimum_budget_projects_enabled
79
78
  end
80
79
 
81
80
  # Public: Returns the required minimum projects to checkout
82
81
  def minimum_projects
83
- return 0 unless component
82
+ return 0 unless budget
84
83
 
85
- component.settings.vote_minimum_budget_projects_number
84
+ budget.settings.vote_minimum_budget_projects_number
86
85
  end
87
86
 
88
87
  def self.user_collection(user)
@@ -94,15 +93,19 @@ module Decidim
94
93
  end
95
94
 
96
95
  def self.newsletter_participant_ids(component)
97
- Decidim::Budgets::Order.where(component: component).joins(:component)
98
- .finished
99
- .pluck(:decidim_user_id).flatten.compact.uniq
96
+ Decidim::Budgets::Order.finished
97
+ .joins(budget: [:component])
98
+ .where(budget: {
99
+ decidim_components: { id: component.id }
100
+ })
101
+ .pluck(:decidim_user_id)
102
+ .flatten.compact.uniq
100
103
  end
101
104
 
102
105
  private
103
106
 
104
107
  def user_belongs_to_organization
105
- organization = component&.organization
108
+ organization = budget.try(:component).try(:organization)
106
109
 
107
110
  return if !user || !organization
108
111
 
@@ -6,8 +6,7 @@ module Decidim
6
6
  # title, description and any other useful information to render a custom project.
7
7
  class Project < Budgets::ApplicationRecord
8
8
  include Decidim::Resourceable
9
- include Decidim::HasComponent
10
- include Decidim::ScopableComponent
9
+ include Decidim::ScopableResource
11
10
  include Decidim::HasCategory
12
11
  include Decidim::HasAttachments
13
12
  include Decidim::HasAttachmentCollections
@@ -18,11 +17,17 @@ module Decidim
18
17
  include Decidim::Loggable
19
18
  include Decidim::Randomable
20
19
  include Decidim::Searchable
20
+ include Decidim::TranslatableResource
21
21
 
22
- component_manifest_name "budgets"
22
+ translatable_fields :title, :description
23
+
24
+ belongs_to :budget, foreign_key: "decidim_budgets_budget_id", class_name: "Decidim::Budgets::Budget", inverse_of: :projects
25
+ has_one :component, through: :budget, foreign_key: "decidim_component_id", class_name: "Decidim::Component"
23
26
  has_many :line_items, class_name: "Decidim::Budgets::LineItem", foreign_key: "decidim_project_id", dependent: :destroy
24
27
  has_many :orders, through: :line_items, foreign_key: "decidim_project_id", class_name: "Decidim::Budgets::Order"
25
28
 
29
+ delegate :organization, :participatory_space, to: :component
30
+
26
31
  searchable_fields(
27
32
  scope_id: :decidim_scope_id,
28
33
  participatory_space: { component: :participatory_space },
@@ -32,13 +37,25 @@ module Decidim
32
37
  )
33
38
 
34
39
  def self.ordered_ids(ids)
35
- order(Arel.sql("position(id::text in '#{ids.join(",")}')"))
40
+ # Make sure each ID in the matching text has a "," character as their
41
+ # delimiter. Otherwise e.g. ID 2 would match ID "26" in the original
42
+ # array. This is why we search for match ",2," instead to get the actual
43
+ # position for ID 2.
44
+ order(Arel.sql("position(concat(',', id::text, ',') in ',#{ids.join(",")},')"))
36
45
  end
37
46
 
38
47
  def self.log_presenter_class_for(_log)
39
48
  Decidim::Budgets::AdminLog::ProjectPresenter
40
49
  end
41
50
 
51
+ def polymorphic_resource_path(url_params)
52
+ ::Decidim::ResourceLocatorPresenter.new([budget, self]).path(url_params)
53
+ end
54
+
55
+ def polymorphic_resource_url(url_params)
56
+ ::Decidim::ResourceLocatorPresenter.new([budget, self]).url(url_params)
57
+ end
58
+
42
59
  # Public: Overrides the `commentable?` Commentable concern method.
43
60
  def commentable?
44
61
  component.settings.comments_enabled?
@@ -71,7 +88,19 @@ module Decidim
71
88
 
72
89
  # Public: Whether the object can have new comments or not.
73
90
  def user_allowed_to_comment?(user)
74
- can_participate_in_space?(user)
91
+ component.can_participate_in_space?(user)
92
+ end
93
+
94
+ # Public: Checks if the project has been selected or not.
95
+ #
96
+ # Returns Boolean.
97
+ def selected?
98
+ selected_at.present?
99
+ end
100
+
101
+ # Public: Returns the attachment context for this record.
102
+ def attachment_context
103
+ :admin
75
104
  end
76
105
  end
77
106
  end
@@ -5,18 +5,27 @@ module Decidim
5
5
  module Admin
6
6
  class Permissions < Decidim::DefaultPermissions
7
7
  def permissions
8
- # The public part needs to be implemented yet
9
8
  return permission_action if permission_action.scope != :admin
10
9
 
11
- return permission_action unless [:project, :projects].include?(permission_action.subject)
12
-
13
- case permission_action.action
14
- when :create
15
- permission_action.allow!
16
- when :import_proposals
17
- permission_action.allow!
18
- when :update, :destroy
19
- permission_action.allow! if project.present?
10
+ case permission_action.subject
11
+ when :budget
12
+ case permission_action.action
13
+ when :create, :read
14
+ allow!
15
+ when :update
16
+ toggle_allow(budget)
17
+ when :delete, :publish, :unpublish
18
+ toggle_allow(budget && budget.projects.empty?)
19
+ end
20
+ when :project, :projects
21
+ case permission_action.action
22
+ when :create
23
+ permission_action.allow!
24
+ when :import_proposals
25
+ permission_action.allow!
26
+ when :update, :destroy
27
+ permission_action.allow! if project.present?
28
+ end
20
29
  end
21
30
 
22
31
  permission_action
@@ -24,6 +33,10 @@ module Decidim
24
33
 
25
34
  private
26
35
 
36
+ def budget
37
+ @budget ||= context.fetch(:budget, nil)
38
+ end
39
+
27
40
  def project
28
41
  @project ||= context.fetch(:project, nil)
29
42
  end
@@ -10,15 +10,19 @@ module Decidim
10
10
  return Decidim::Budgets::Admin::Permissions.new(user, permission_action, context).permissions if permission_action.scope == :admin
11
11
  return permission_action if permission_action.scope != :public
12
12
 
13
- return permission_action if permission_action.subject != :project
13
+ return permission_action unless [:project, :order].include? permission_action.subject
14
14
 
15
- case permission_action.action
16
- when :vote
17
- can_vote_project?(project || order&.projects&.first)
18
- when :report
19
- permission_action.allow!
15
+ if permission_action.subject == :project
16
+ case permission_action.action
17
+ when :vote
18
+ can_vote?(false) if can_vote_project?(project || order&.projects&.first)
19
+ when :report
20
+ permission_action.allow!
21
+ end
20
22
  end
21
23
 
24
+ can_vote?(true) if permission_action.action == :create && permission_action.subject == :order
25
+
22
26
  permission_action
23
27
  end
24
28
 
@@ -32,6 +36,24 @@ module Decidim
32
36
  @order ||= context.fetch(:order, nil)
33
37
  end
34
38
 
39
+ def budget
40
+ @budget ||= context.fetch(:budget, nil)
41
+ end
42
+
43
+ def workflow
44
+ @workflow ||= context.fetch(:workflow, nil)
45
+ end
46
+
47
+ def can_vote?(active_allow)
48
+ is_allowed = workflow.vote_allowed?(budget)
49
+
50
+ if !is_allowed
51
+ disallow!
52
+ elsif active_allow
53
+ allow!
54
+ end
55
+ end
56
+
35
57
  def can_vote_project?(a_project)
36
58
  is_allowed = a_project && authorized?(:vote, resource: project)
37
59
 
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Budgets
5
+ module AdminLog
6
+ # This class holds the logic to present a `Decidim::Budgets::Budget`
7
+ # for the `AdminLog` log.
8
+ #
9
+ # Usage should be automatic and you shouldn't need to call this class
10
+ # directly, but here's an example:
11
+ #
12
+ # action_log = Decidim::ActionLog.last
13
+ # view_helpers # => this comes from the views
14
+ # BudgetPresenter.new(action_log, view_helpers).present
15
+ class BudgetPresenter < Decidim::Log::BasePresenter
16
+ private
17
+
18
+ def action_string
19
+ case action
20
+ when "create", "delete", "update"
21
+ "decidim.budgets.admin_log.budget.#{action}"
22
+ else
23
+ super
24
+ end
25
+ end
26
+
27
+ def diff_fields_mapping
28
+ {
29
+ title: :i18n,
30
+ weight: :integer,
31
+ description: :i18n,
32
+ total_budget: :currency
33
+ }
34
+ end
35
+
36
+ def i18n_labels_scope
37
+ "activemodel.attributes.budget"
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -27,11 +27,19 @@ module Decidim
27
27
  # Finds the Projects scoped to an array of components and filtered
28
28
  # by a range of dates.
29
29
  def query
30
- projects = Decidim::Budgets::Project.where(component: @components)
30
+ projects = Decidim::Budgets::Project.where(budget: budgets)
31
31
  projects = projects.where("created_at >= ?", @start_at) if @start_at.present?
32
32
  projects = projects.where("created_at <= ?", @end_at) if @end_at.present?
33
33
  projects
34
34
  end
35
+
36
+ private
37
+
38
+ attr_reader :components
39
+
40
+ def budgets
41
+ @budgets ||= Decidim::Budgets::Budget.where(component: components).order(weight: :asc)
42
+ end
35
43
  end
36
44
  end
37
45
  end
@@ -11,9 +11,10 @@ module Decidim
11
11
  end
12
12
 
13
13
  def calculate
14
- budgets = Decidim::Budgets::Project.where(component: @resource)
14
+ budgets = Decidim::Budgets::Budget.where(component: @resource)
15
+ projects = Decidim::Budgets::Project.where(budget: budgets)
15
16
 
16
- budgets_followers = Decidim::Follow.where(followable: budgets).joins(:user)
17
+ budgets_followers = Decidim::Follow.where(followable: projects).joins(:user)
17
18
  .where("decidim_follows.created_at <= ?", end_time)
18
19
  cumulative_users = budgets_followers.pluck(:decidim_user_id)
19
20
 
@@ -11,13 +11,14 @@ module Decidim
11
11
  end
12
12
 
13
13
  def calculate
14
- budgets = Decidim::Budgets::Order.where(component: @resource).joins(:component)
15
- .finished
16
- .where("decidim_budgets_orders.checked_out_at <= ?", end_time)
14
+ budgets = Decidim::Budgets::Budget.where(component: @resource)
15
+ orders = Decidim::Budgets::Order.where(budget: budgets)
16
+ .finished
17
+ .where("decidim_budgets_orders.checked_out_at <= ?", end_time)
17
18
 
18
19
  {
19
- cumulative_users: budgets.pluck(:decidim_user_id),
20
- quantity_users: budgets.where("decidim_budgets_orders.checked_out_at >= ?", start_time).pluck(:decidim_user_id)
20
+ cumulative_users: orders.pluck(:decidim_user_id),
21
+ quantity_users: orders.where("decidim_budgets_orders.checked_out_at >= ?", start_time).pluck(:decidim_user_id)
21
22
  }
22
23
  end
23
24
  end
@@ -12,7 +12,8 @@ module Decidim
12
12
  def serialize
13
13
  {
14
14
  id: order.id,
15
- component: order.component.name,
15
+ budget: order.budget.title,
16
+ component: order.budget.component.name,
16
17
  checked_out_at: order.checked_out_at,
17
18
  projects: all_projects,
18
19
  created_at: order.created_at,
@@ -30,7 +31,7 @@ module Decidim
30
31
  id: project.id,
31
32
  title: project.title,
32
33
  description: project.description,
33
- budget: project.budget,
34
+ budget_amount: project.budget_amount,
34
35
  scope: project.try(:scope).try(:name),
35
36
  reference: project.reference,
36
37
  created_at: project.created_at,
@@ -6,45 +6,33 @@ module Decidim
6
6
  # `current_component` param with a `Decidim::Component` in order to
7
7
  # find the projects.
8
8
  class ProjectSearch < ResourceSearch
9
+ text_search_fields :title, :description
10
+
9
11
  # Public: Initializes the service.
10
12
  # component - A Decidim::Component to get the projects from.
11
13
  def initialize(options = {})
12
14
  super(Project.all, options)
13
15
  end
14
16
 
15
- # Handle the search_text filter
16
- def search_search_text
17
- query
18
- .where(localized_search_text_in(:title), text: "%#{search_text}%")
19
- .or(query.where(localized_search_text_in(:description), text: "%#{search_text}%"))
20
- end
21
-
22
- def search_category_id
23
- super
24
- end
17
+ # Creates the SearchLight base query.
18
+ def base_query
19
+ raise "Missing budget" unless budget
20
+ raise "Missing component" unless component
25
21
 
26
- def search_scope_id
27
- super
22
+ @scope.where(budget: budget)
28
23
  end
29
24
 
30
25
  # Returns the random projects for the current page.
31
26
  def results
32
- Project.where(id: super.pluck(:id))
27
+ Project.where(id: super.pluck(:id)).includes([:scope, :component, :attachments, :category])
33
28
  end
34
29
 
35
30
  private
36
31
 
37
- # Internal: builds the needed query to search for a text in the organization's
38
- # available locales. Note that it is intended to be used as follows:
39
- #
40
- # Example:
41
- # Resource.where(localized_search_text_for(:title, text: "my_query"))
42
- #
43
- # The Hash with the `:text` key is required or it won't work.
44
- def localized_search_text_in(field)
45
- options[:organization].available_locales.map do |l|
46
- "#{field} ->> '#{l}' ILIKE :text"
47
- end.join(" OR ")
32
+ # Private: Since budget is not used by a search method we need
33
+ # to define the method manually.
34
+ def budget
35
+ options[:budget]
48
36
  end
49
37
  end
50
38
  end