Merge pull request #1356 from consul/budget-emails

Budget emails
This commit is contained in:
Raimond Garcia
2017-01-15 19:15:39 +01:00
committed by GitHub
13 changed files with 270 additions and 12 deletions

View File

@@ -46,6 +46,7 @@ module Budgets
@investment.author = current_user
if @investment.save
Mailer.budget_investment_created(@investment).deliver_later
redirect_to budget_investment_path(@budget, @investment),
notice: t('flash.actions.create.budget_investment')
else

View File

@@ -21,6 +21,11 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController
def valuate
if valid_price_params? && @investment.update(valuation_params)
if @investment.unfeasible_email_pending?
@investment.send_unfeasible_email
end
redirect_to valuation_budget_budget_investment_path(@budget, @investment), notice: t('valuation.budget_investments.notice.valuate')
else
render action: :edit

View File

@@ -74,6 +74,23 @@ class Mailer < ApplicationMailer
end
end
def budget_investment_created(investment)
@investment = investment
with_user(@investment.author) do
mail(to: @investment.author.email, subject: t('mailers.budget_investment_created.subject'))
end
end
def budget_investment_unfeasible(investment)
@investment = investment
@author = investment.author
with_user(@author) do
mail(to: @author.email, subject: t('mailers.budget_investment_unfeasible.subject', code: @investment.code))
end
end
private
def with_user(user, &block)

View File

@@ -136,12 +136,21 @@ class Budget
unfeasible? && valuation_finished?
end
def unfeasible_email_pending?
unfeasible_email_sent_at.blank? && unfeasible? && valuation_finished?
end
def total_votes
cached_votes_up + physical_votes
end
def code
"B#{budget.id}I#{id}"
"#{created_at.strftime('%Y')}-#{id}" + (administrator.present? ? "-A#{administrator.id}" : "")
end
def send_unfeasible_email
Mailer.budget_investment_unfeasible(self).deliver_later
update(unfeasible_email_sent_at: Time.current)
end
def reason_for_not_being_selectable_by(user)

View File

@@ -95,7 +95,8 @@
<div class="social-share-full">
<%= social_share_button_tag("#{investment.title} #{setting['twitter_hashtag']}") %>
<% if browser.device.mobile? %>
<a href="whatsapp://send?text=<%= investment.title %> <%= budget_investment_url(budget_id: investment.budget_id, id: investment.id) %>" data-action="share/whatsapp/share">
<a href="whatsapp://send?text=<%= investment.title %> <%= budget_investment_url(budget_id: investment.budget_id, id: investment.id) %>"
data-action="share/whatsapp/share">
<span class="icon-whatsapp whatsapp"></span>
</a>
<% end %>
@@ -104,11 +105,23 @@
<% else %>
<div class="small-12 medium-3 column">
<div class="float-right">
<span class="label-budget-investment float-left"><%= t("budgets.investments.show.title") %></span>
<span class="label-budget-investment float-left">
<%= t("budgets.investments.show.title") %>
</span>
<span class="icon-budget"></span>
</div>
<br>
<% end %>
<div id="social-share" class="sidebar-divider"></div>
<h2><%= t("budgets.investments.show.share") %></h2>
<div class="social-share-full">
<%= social_share_button_tag("#{investment.title} #{setting['twitter_hashtag']}") %>
<% if browser.device.mobile? %>
<a href="whatsapp://send?text=<%= investment.title %> <%= budget_investment_url(budget_id: investment.budget_id, id: investment.id) %>" data-action="share/whatsapp/share">
<span class="icon-whatsapp whatsapp"></span>
</a>
<% end %>
</div>
<% end %>
</aside>
</div>
</section>

View File

@@ -0,0 +1,42 @@
<td style="padding-bottom: 20px; padding-left: 10px;">
<h1 style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;">
<%= t("mailers.budget_investment_created.title") %>
</h1>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.budget_investment_created.intro_html",
author: @investment.author.name).html_safe %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.budget_investment_created.text_html",
investment: @investment.title,
budget: @investment.budget.name).html_safe %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.budget_investment_created.follow_html",
link: link_to(t("mailers.budget_investment_created.follow_link"), budgets_url)).html_safe %>
</p>
<table style="width: 100%;">
<tbody>
<tr>
<td style="padding-bottom: 12px; text-align: center;">
<%= link_to budget_investment_url(@investment.budget, @investment, anchor: "social-share"), style: "font-family: 'Open Sans','Helvetica Neue',arial,sans-serif; background: #f7f5f2; border-radius: 6px; color: #3d3d66!important; font-weight: bold; margin: 0px; padding: 10px 15px; text-align: center; text-decoration: none; min-width: 160px; display: inline-block;" do %>
<%= image_tag('icon_mailer_share.png', style: "border: 0; display: inline-block; width: 100%; max-width: 16px", alt: "") %>
<%= t('mailers.budget_investment_created.share') %>
<% end %>
</td>
</tr>
</tbody>
</table>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.budget_investment_created.sincerely") %>
<br>
<span style="color: #ccc; font-size: 12px;">
<%= t("mailers.budget_investment_created.signatory") %>
</span>
</p>

View File

@@ -0,0 +1,35 @@
<td style="padding-bottom: 20px; padding-left: 10px;">
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.budget_investment_unfeasible.hi") %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.budget_investment_unfeasible.unfeasible_html",
title: @investment.title) %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px; padding-left: 12px; border-left: 2px solid #ccc;">
<%= @investment.unfeasibility_explanation %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.budget_investment_unfeasible.new_html",
url: link_to(t("mailers.budget_investment_unfeasible.new_href"),
new_budget_investment_url(@investment.budget), style: "color: #2895F1; text-decoration: underline;")) %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.budget_investment_unfeasible.reconsider_html", code: @investment.code) %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.budget_investment_unfeasible.sorry") %>
</p>
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
<%= t("mailers.budget_investment_unfeasible.sincerely") %><br>
<span style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 12px;font-weight: normal;line-height: 24px; color: #ccc;">
<%= t("mailers.budget_investment_unfeasible.signatory") %></span>
</p>
</td>

View File

@@ -31,6 +31,16 @@ en:
sorry: "Sorry for the inconvenience and we again thank you for your invaluable participation."
subject: "Your investment project '%{code}' has been marked as unfeasible"
unfeasible_html: "From the City Council we want to thank you for your participation in the <strong>participatory budgets</strong>. We regret to inform you that your proposal <strong>'%{title}'</strong> will be excluded from this participatory process for the following reason:"
budget_investment_unfeasible:
hi: "Dear user,"
new_html: "For all these, we invite you to elaborate a <strong>new proposal</strong> that ajusts to the conditions of this process. You can do it following this link: %{url}."
new_href: "new investment project"
reconsider_html: "If you believe that the rejected proposal meets the requirements to be an investment proposal, you can communicate this, within 48 hours, responding to the email address examples@consul.es. Including the code %{code} in the subject of the email."
sincerely: "Sincerely"
signatory: "DEPARTMENT OF PUBLIC PARTICIPATION"
sorry: "Sorry for the inconvenience and we again thank you for your invaluable participation."
subject: "Your investment project '%{code}' has been marked as unfeasible"
unfeasible_html: "From the City Council we want to thank you for your participation in the <strong>participatory budgets</strong>. We regret to inform you that your proposal <strong>'%{title}'</strong> will be excluded from this participatory process for the following reason:"
proposal_notification_digest:
info: "Here are the new notifications that have been published by authors of the proposals that you have supported in %{org_name}."
title: "Proposal notifications in %{org_name}"
@@ -52,4 +62,24 @@ en:
thanks: "Thank you very much."
title: "Welcome to %{org}"
button: Complete registration
subject: "Invitation to %{org_name}"
subject: "Invitation to %{org_name}"
budget_investment_created:
subject: "Thank you for creating an investment!"
title: "Thank you for creating an investment!"
intro_html: "Hi <strong>%{author}</strong>,"
text_html: "Thank you for creating your investment <strong>%{investment}</strong> for Participatory Budgets <strong>%{budget}</strong>."
follow_html: "We will inform you about how the process progresses, which you can also follow on <strong>%{link}</strong>."
follow_link: "Participatory Budgets"
sincerely: "Sincerely,"
signatory: "DEPARTMENT OF PUBLIC PARTICIPATION"
share: "Comparte tu proyecto"
budget_investment_unfeasible:
hi: "Dear user,"
new_html: "For all these, we invite you to elaborate a <strong>new investment</strong> that ajusts to the conditions of this process. You can do it following this link: %{url}."
new_href: "new investment project"
reconsider_html: "If you believe that the rejected investment meets the requirements to be an investment project, you can communicate this, within 48 hours, responding to the email address examples@consul.es. Including the code %{code} in the subject of the email."
sincerely: "Sincerely"
signatory: "DEPARTMENT OF PUBLIC PARTICIPATION"
sorry: "Sorry for the inconvenience and we again thank you for your invaluable participation."
subject: "Your investment project '%{code}' has been marked as unfeasible"
unfeasible_html: "From the City Council we want to thank you for your participation in the <strong>participatory budgets</strong>. We regret to inform you that your investment <strong>'%{title}'</strong> will be excluded from this participatory process for the following reason:"

View File

@@ -52,4 +52,24 @@ es:
thanks: "Muchas gracias."
title: "Bienvenido a %{org}"
button: Completar registro
subject: "Invitación a %{org_name}"
subject: "Invitación a %{org_name}"
budget_investment_created:
subject: "¡Gracias por crear un proyecto!"
title: "¡Gracias por crear un proyecto!"
intro_html: "Hola <strong>%{author}</strong>,"
text_html: "Muchas gracias por crear tu proyecto <strong>%{investment}</strong> para los Presupuestos Participativos <strong>%{budget}</strong>."
follow_html: "Te informaremos de cómo avanza el proceso, que también puedes seguir en la página de <strong>%{link}</strong>."
follow_link: "Presupuestos participativos"
sincerely: "Atentamente,"
signatory: "DIRECCIÓN GENERAL DE PARTICIPACIÓN CIUDADANA"
share: "Comparte tu proyecto"
budget_investment_unfeasible:
hi: "Estimado usuario,"
new_html: "Por todo ello, te invitamos a que elabores un <strong>nuevo proyecto de gasto</strong> que se ajuste a las condiciones de este proceso. Esto lo puedes hacer en este enlace: %{url}."
new_href: "nueva propuesta de inversión"
reconsider_html: "Si consideras que el proyecto rechazado cumple los requisitos para mantenerlo como proyecto de gasto, podrás comunicarlo, en el plazo de 48 horas, al correo example@consul.es, indicando necesariamente para su tramitación el código %{code} como asunto del correo, correspondiente a tu proyecto."
sincerely: "Atentamente"
signatory: "DIRECCIÓN GENERAL DE PARTICIPACIÓN CIUDADANA"
sorry: "Sentimos las molestias ocasionadas y volvemos a darte las gracias por tu inestimable participación."
subject: "Tu propuesta de inversión '%{code}' ha sido marcada como inviable"
unfeasible_html: "Desde el Ayuntamiento queremos agradecer tu participación en los <strong>Presupuestos Participativos</strong>. Lamentamos informarte de que tu proyecto <strong>'%{title}'</strong> quedará excluido de este proceso participativo por el siguiente motivo:"

View File

@@ -0,0 +1,5 @@
class AddUnfeasibleEmailSentAtToBudgetInvestments < ActiveRecord::Migration
def change
add_column :budget_investments, :unfeasible_email_sent_at, :datetime
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170106130838) do
ActiveRecord::Schema.define(version: 20170114154421) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -143,6 +143,7 @@ ActiveRecord::Schema.define(version: 20170106130838) do
t.boolean "selected", default: false
t.string "location"
t.string "organization_name"
t.datetime "unfeasible_email_sent_at"
end
add_index "budget_investments", ["administrator_id"], name: "index_budget_investments_on_administrator_id", using: :btree

View File

@@ -261,4 +261,65 @@ feature 'Emails' do
end
context "Budgets" do
background do
Setting["feature.budgets"] = true
end
let(:author) { create(:user, :level_two) }
let(:budget) { create(:budget) }
let(:group) { create(:budget_group, name: "Health", budget: budget) }
let!(:heading) { create(:budget_heading, name: "More hospitals", group: group) }
scenario "Investment created" do
login_as(author)
visit new_budget_investment_path(budget_id: budget.id)
select 'Health: More hospitals', from: 'budget_investment_heading_id'
fill_in 'budget_investment_title', with: 'Build a hospital'
fill_in 'budget_investment_description', with: 'We have lots of people that require medical attention'
fill_in 'budget_investment_external_url', with: 'http://http://hospitalsforallthepeople.com/'
check 'budget_investment_terms_of_service'
click_button 'Create Investment'
expect(page).to have_content 'Investment created successfully'
email = open_last_email
investment = Budget::Investment.last
expect(email).to have_subject("Thank you for creating an investment!")
expect(email).to deliver_to(investment.author.email)
expect(email).to have_body_text(author.name)
expect(email).to have_body_text(investment.title)
expect(email).to have_body_text(investment.budget.name)
expect(email).to have_body_text(budget_path(budget))
end
scenario "Unfeasible investment" do
investment = create(:budget_investment, author: author, budget: budget)
valuator = create(:valuator)
investment.valuators << valuator
login_as(valuator.user)
visit edit_valuation_budget_budget_investment_path(budget, investment)
choose 'budget_investment_feasibility_unfeasible'
fill_in 'budget_investment_unfeasibility_explanation', with: 'This is not legal as stated in Article 34.9'
check 'budget_investment_valuation_finished'
click_button 'Save changes'
expect(page).to have_content "Dossier updated"
investment.reload
email = open_last_email
expect(email).to have_subject("Your investment project '#{investment.code}' has been marked as unfeasible")
expect(email).to deliver_to(investment.author.email)
expect(email).to have_body_text(investment.title)
expect(email).to have_body_text(investment.code)
expect(email).to have_body_text(investment.unfeasibility_explanation)
end
end
end

View File

@@ -58,10 +58,29 @@ describe Budget::Investment do
end
describe "#code" do
it "returns the investment and budget id" do
investment = create(:budget_investment)
expect(investment.code).to include("#{investment.id}")
expect(investment.code).to include("#{investment.budget.id}")
let(:investment) { create(:budget_investment) }
it "returns the proposal id" do
expect(investment.code).to include("#{investment.id}")
end
it "returns the administrator id when assigned" do
investment.administrator = create(:administrator)
expect(investment.code).to include("#{investment.id}-A#{investment.administrator.id}")
end
end
describe "#send_unfeasible_email" do
let(:investment) { create(:budget_investment) }
it "sets the time when the unfeasible email was sent" do
expect(investment.unfeasible_email_sent_at).to_not be
investment.send_unfeasible_email
expect(investment.unfeasible_email_sent_at).to be
end
it "send an email" do
expect {investment.send_unfeasible_email}.to change { ActionMailer::Base.deliveries.count }.by(1)
end
end