diff --git a/app/controllers/admin/system_emails_controller.rb b/app/controllers/admin/system_emails_controller.rb index 689425569..f70c4bd53 100644 --- a/app/controllers/admin/system_emails_controller.rb +++ b/app/controllers/admin/system_emails_controller.rb @@ -14,7 +14,8 @@ class Admin::SystemEmailsController < Admin::BaseController direct_message_for_receiver: %w[view edit_info], direct_message_for_sender: %w[view edit_info], email_verification: %w[view edit_info], - user_invite: %w[view edit_info] + user_invite: %w[view edit_info], + evaluation_comment: %w[view edit_info] } end @@ -34,6 +35,8 @@ class Admin::SystemEmailsController < Admin::BaseController load_sample_user when "user_invite" @subject = t("mailers.user_invite.subject", org_name: Setting["org_name"]) + when "evaluation_comment" + load_sample_valuation_comment end end @@ -97,6 +100,17 @@ class Admin::SystemEmailsController < Admin::BaseController end end + def load_sample_valuation_comment + comment = Comment.where(commentable_type: "Budget::Investment").last + if comment + @email = EvaluationCommentEmail.new(comment) + @email_to = @email.to.first + else + redirect_to admin_system_emails_path, + alert: t("admin.system_emails.alert.no_evaluation_comments") + end + end + def load_sample_user @user = User.last @token = @user.email_verification_token || SecureRandom.hex diff --git a/app/helpers/mailer_helper.rb b/app/helpers/mailer_helper.rb index c3bda48b9..d850b8dd3 100644 --- a/app/helpers/mailer_helper.rb +++ b/app/helpers/mailer_helper.rb @@ -8,4 +8,16 @@ module MailerHelper return budget_investment_url(commentable.budget_id, commentable) if commentable.is_a?(Budget::Investment) end + def valuation_comments_url(commentable) + admin_budget_budget_investment_url( commentable.budget, commentable, anchor: "comments") + end + + def valuation_comments_link(commentable) + link_to( + commentable.title, + valuation_comments_url(@email.commentable), + target: :blank, + style: "color: #2895F1; text-decoration:none;" + ) + end end diff --git a/app/mailers/mailer.rb b/app/mailers/mailer.rb index d8fa120a4..9defb0f15 100644 --- a/app/mailers/mailer.rb +++ b/app/mailers/mailer.rb @@ -120,6 +120,13 @@ class Mailer < ApplicationMailer mail(to: @email_to, from: @newsletter.from, subject: @newsletter.subject) end + def evaluation_comment(comment, to) + @email = EvaluationCommentEmail.new(comment) + @email_to = to + + mail(to: @email_to.email, subject: @email.subject) if @email.can_be_sent? + end + private def with_user(user, &block) diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index 2eaf801c1..6750d2d75 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -377,6 +377,12 @@ class Budget milestones.published.with_status.order_by_publication_date.last&.status_id end + def admin_and_valuator_users_associated + valuator_users = (valuator_groups.map(&:valuators) + valuators).flatten + all_users = valuator_users << administrator + all_users.compact.uniq + end + private def set_denormalized_ids diff --git a/app/views/mailer/evaluation_comment.html.erb b/app/views/mailer/evaluation_comment.html.erb new file mode 100644 index 000000000..0d695766d --- /dev/null +++ b/app/views/mailer/evaluation_comment.html.erb @@ -0,0 +1,19 @@ + + +

+ <%= t("mailers.evaluation_comment.title", investment: @email.commentable.title) %> +

+ +

+ <%= t("mailers.evaluation_comment.hi") %> <%= @email_to.name %>, +

+ +

+ <%= t("mailers.evaluation_comment.new_comment_by_html", commenter: @email.comment.author.name, investment: valuation_comments_link(@email.commentable)) %> +

+ + <%= t("mailers.evaluation_comment.commenter_info", commenter: @email.comment.author.name, time: l(@email.comment.created_at)) %> +
+ <%= simple_format text_with_links(@email.comment.body), {}, sanitize: false %> +
+ diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index e3c5c597b..54958daac 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -875,6 +875,9 @@ en: user_invite: title: "User Invitation" description: "Sent to the person that has been invited to register an account." + evaluation_comment: + title: "New evaluation comment" + description: "Sent to administrators and evaluators related to commented investment" edit_info: "You can edit this email in" message_title: "Message's Title" message_body: "This is a sample of message's content." @@ -882,6 +885,7 @@ en: no_investments: "There aren't any budget investment created. Some example data is needed in order to preview the email." no_comments: "There aren't any comments created. Some example data is needed in order to preview the email." no_replies: "There aren't any replies created. Some example data is needed in order to preview the email." + no_evaluation_comments: "There aren't any evaluation comments created. Some example data is needed in order to preview the email." emails_download: index: title: Emails download diff --git a/config/locales/en/mailers.yml b/config/locales/en/mailers.yml index c92660de4..2a0e23da2 100644 --- a/config/locales/en/mailers.yml +++ b/config/locales/en/mailers.yml @@ -70,6 +70,12 @@ en: hi: "Dear user," thanks: "Thank you again for participating." sincerely: "Sincererly" + evaluation_comment: + subject: "New evaluation comment" + title: New evaluation comment for %{investment} + hi: Hi + new_comment_by_html: There is a new evaluation comment from %{commenter} to the budget investment %{investment} + commenter_info: "%{commenter}, %{time}:" new_actions_notification_rake_created: subject: "More news about your citizen proposal" hi: "Hello %{name}," diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index 34fc7510b..4f7feb768 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -874,6 +874,9 @@ es: user_invite: title: "Invitación de usuarios" description: "Enviado a la persona que ha sido invitada a registrar una cuenta." + evaluation_comment: + title: "Nuevo comentario de evaluación" + description: "Enviado a administradores y evaluadores del presupuesto." edit_info: "Puedes editar este email en" message_title: "Título del mensaje" message_body: "Este es un ejemplo de contenido de un mensaje." @@ -881,6 +884,7 @@ es: no_investments: "No se ha creado ningún proyecto de gasto. Se necesita algún ejemplo para poder previsualizar el email." no_comments: "No se ha creado ningún comentario. Se necesita algún ejemplo para poder previsualizar el email." no_replies: "No se ha creado ninguna respuesta. Se necesita algún ejemplo para poder previsualizar el email." + no_evaluation_comments: "No se ha creado ningún comentario de evaluación. Se necesita algún ejemplo para poder previsualizar el email." emails_download: index: title: Descarga de emails diff --git a/config/locales/es/mailers.yml b/config/locales/es/mailers.yml index b1d0de74b..1483c1fae 100644 --- a/config/locales/es/mailers.yml +++ b/config/locales/es/mailers.yml @@ -70,6 +70,12 @@ es: hi: "Estimado/a usuario/a" thanks: "Gracias de nuevo por tu participación." sincerely: "Atentamente" + evaluation_comment: + subject: "Nuevo comentario de evaluación" + title: Nuevo comentario de evaluación para %{investment} + hi: Hola + new_comment_by_html: Hay un nuevo comentario de evaluación de %{commenter} en el presupuesto participativo %{investment} + commenter_info: "%{commenter}, %{time}" new_actions_notification_rake_created: subject: "Más novedades de tu propuesta ciudadana" hi: "Hola %{name}," diff --git a/lib/evaluation_comment_email.rb b/lib/evaluation_comment_email.rb new file mode 100644 index 000000000..6321e43dd --- /dev/null +++ b/lib/evaluation_comment_email.rb @@ -0,0 +1,31 @@ +class EvaluationCommentEmail + attr_reader :comment + + def initialize(comment) + @comment = comment + end + + def commentable + comment.commentable + end + + def to + @to ||= related_users + end + + def subject + I18n.t("mailers.evaluation_comment.subject") + end + + def can_be_sent? + commentable.present? && to.any? + end + + private + def related_users + return [] if comment.commentable.nil? + comment.commentable + .admin_and_valuator_users_associated + .reject { |associated_user| associated_user.user == comment.author } + end +end diff --git a/spec/features/admin/system_emails_spec.rb b/spec/features/admin/system_emails_spec.rb index 4c71f4f3f..b1aed5bed 100644 --- a/spec/features/admin/system_emails_spec.rb +++ b/spec/features/admin/system_emails_spec.rb @@ -14,7 +14,8 @@ describe "System Emails" do let(:system_emails) do %w[proposal_notification_digest budget_investment_created budget_investment_selected budget_investment_unfeasible budget_investment_unselected comment reply - direct_message_for_receiver direct_message_for_sender email_verification user_invite] + direct_message_for_receiver direct_message_for_sender email_verification user_invite + evaluation_comment] end context "System emails" do @@ -243,6 +244,31 @@ describe "System Emails" do visit admin_system_email_view_path("reply") expect(page).to have_content "There aren't any replies created." expect(page).to have_content "Some example data is needed in order to preview the email." + + visit admin_system_email_view_path("evaluation_comment") + expect(page).to have_content "There aren't any evaluation comments created." + expect(page).to have_content "Some example data is needed in order to preview the email." + end + + scenario "#evaluation_comment" do + admin = create(:administrator, user: create(:user, username: "Baby Doe")) + investment = create(:budget_investment, + title: "Cleaner city", + heading: heading, + author: user, + administrator: admin) + comment = create(:comment, :valuation, commentable: investment) + + visit admin_system_email_view_path("evaluation_comment") + + expect(page).to have_content "New evaluation comment for Cleaner city" + expect(page).to have_content "Hi #{admin.name}" + expect(page).to have_content "There is a new evaluation comment from #{comment.user.name} "\ + "to the budget investment Cleaner city" + expect(page).to have_content comment.body + + expect(page).to have_link "Cleaner city", + href: admin_budget_budget_investment_url( investment.budget, investment, anchor: "comments") end end diff --git a/spec/features/comments/budget_investments_valuation_spec.rb b/spec/features/comments/budget_investments_valuation_spec.rb index 1acb5819c..fd9bf56c7 100644 --- a/spec/features/comments/budget_investments_valuation_spec.rb +++ b/spec/features/comments/budget_investments_valuation_spec.rb @@ -171,7 +171,7 @@ describe "Internal valuation comments on Budget::Investments" do scenario "Create comment", :js do visit valuation_budget_budget_investment_path(budget, investment) - fill_in "comment-body-budget_investment_#{investment.id}", with: "Have you thought about...?" + fill_in "Leave your comment", with: "Have you thought about...?" click_button "Publish comment" within "#comments" do @@ -199,7 +199,7 @@ describe "Internal valuation comments on Budget::Investments" do click_link "Reply" within "#js-comment-form-comment_#{comment.id}" do - fill_in "comment-body-comment_#{comment.id}", with: "It will be done next week." + fill_in "Leave your comment", with: "It will be done next week." click_button "Publish reply" end @@ -261,8 +261,8 @@ describe "Internal valuation comments on Budget::Investments" do login_as(admin_user) visit valuation_budget_budget_investment_path(budget, investment) - fill_in "comment-body-budget_investment_#{investment.id}", with: "I am your Admin!" - check "comment-as-administrator-budget_investment_#{investment.id}" + fill_in "Leave your comment", with: "I am your Admin!" + check "Comment as admin" click_button "Publish comment" within "#comments" do @@ -282,8 +282,8 @@ describe "Internal valuation comments on Budget::Investments" do click_link "Reply" within "#js-comment-form-comment_#{comment.id}" do - fill_in "comment-body-comment_#{comment.id}", with: "Top of the world!" - check "comment-as-administrator-comment_#{comment.id}" + fill_in "Leave your comment", with: "Top of the world!" + check "Comment as admin" click_button "Publish reply" end @@ -298,4 +298,25 @@ describe "Internal valuation comments on Budget::Investments" do end end + scenario "Send email notification", :js do + ActionMailer::Base.deliveries = [] + + login_as(admin_user) + + expect(ActionMailer::Base.deliveries).to eq([]) + + visit valuation_budget_budget_investment_path(budget, investment) + fill_in "Leave your comment", with: "I am your Admin!" + check "Comment as admin" + click_button "Publish comment" + + within "#comments" do + expect(page).to have_content("I am your Admin!") + end + + expect(ActionMailer::Base.deliveries.count).to eq(1) + expect(ActionMailer::Base.deliveries.first.to).to eq([valuator_user.email]) + expect(ActionMailer::Base.deliveries.first.subject).to eq("New evaluation comment") + end + end diff --git a/spec/lib/evaluation_comment_email_spec.rb b/spec/lib/evaluation_comment_email_spec.rb new file mode 100644 index 000000000..18b85c197 --- /dev/null +++ b/spec/lib/evaluation_comment_email_spec.rb @@ -0,0 +1,57 @@ +require "rails_helper" + +describe EvaluationCommentEmail do + + let(:author) { create(:user) } + let(:administrator) { create(:administrator)} + let(:investment) { create(:budget_investment, author: author, administrator: administrator) } + let(:commenter) { create(:user, email: "email@commenter.org") } + let(:comment) { create(:comment, commentable: investment, user: commenter) } + let(:comment_email) { EvaluationCommentEmail.new(comment) } + + describe "#commentable" do + it "returns the commentable object that contains the replied comment" do + expect(comment_email.commentable).to eq investment + end + end + + describe "#to" do + it "returns an array of users related to investment" do + expect(comment_email.to).to eq [administrator] + end + + it "returns empty array if commentable not exists" do + allow(comment).to receive(:commentable).and_return(nil) + expect(comment_email.to).to eq [] + end + + it "returns empty array if not associated users" do + allow(investment).to receive(:admin_and_valuator_users_associated).and_return([]) + expect(comment_email.to).to eq [] + end + end + + describe "#subject" do + it "returns the translation for a evaluation comment email subject" do + expect(comment_email.subject).to eq "New evaluation comment" + end + end + + describe "#can_be_sent?" do + it "returns true if investment has any associated users" do + expect(comment_email.can_be_sent?).to be true + end + + it "returns false if the comment doesn't exist" do + comment.update(commentable: nil) + + expect(comment_email.can_be_sent?).to be false + end + + it "returns false if recipients are empty" do + investment.administrator = nil + expect(comment_email.can_be_sent?).to be false + end + end + +end diff --git a/spec/models/budget/investment_spec.rb b/spec/models/budget/investment_spec.rb index 044dead99..c842621ff 100644 --- a/spec/models/budget/investment_spec.rb +++ b/spec/models/budget/investment_spec.rb @@ -1218,4 +1218,31 @@ describe Budget::Investment do end end end + + describe "admin_and_valuator_users_associated" do + let(:investment) { create(:budget_investment) } + let(:valuator_group) { create(:valuator_group) } + let(:valuator) { create(:valuator) } + let(:administrator) { create(:administrator) } + + it "returns empty array if not valuators or administrator assigned" do + expect(investment.admin_and_valuator_users_associated).to eq([]) + end + + it "returns all valuator and administrator users" do + valuator_group.valuators << valuator + investment.valuator_groups << valuator_group + expect(investment.admin_and_valuator_users_associated).to eq([valuator]) + investment.administrator = administrator + expect(investment.admin_and_valuator_users_associated).to eq([valuator, administrator]) + end + + it "returns uniq valuators or administrator users" do + valuator_group.valuators << valuator + investment.valuator_groups << valuator_group + investment.valuators << valuator + investment.administrator = administrator + expect(investment.admin_and_valuator_users_associated).to eq([valuator, administrator]) + end + end end