aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/controllers/request_controller.rb168
-rw-r--r--app/models/info_request.rb147
-rw-r--r--app/models/info_request_event.rb34
-rw-r--r--app/models/request_mailer.rb10
-rw-r--r--app/views/request/_describe_state.rhtml1
-rw-r--r--app/views/request/_other_describe_state.rhtml1
-rw-r--r--app/views/request/describe_state_message.rhtml30
-rw-r--r--app/views/request_mailer/requires_admin.rhtml2
8 files changed, 195 insertions, 198 deletions
diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb
index fe948db19..ec5c9d055 100644
--- a/app/controllers/request_controller.rb
+++ b/app/controllers/request_controller.rb
@@ -374,93 +374,77 @@ class RequestController < ApplicationController
# Submitted to the describing state of messages form
def describe_state
- @info_request = InfoRequest.find(params[:id].to_i)
- set_last_request(@info_request)
-
- # If this isn't a form submit, go to the request page
- if params[:submitted_describe_state].nil?
- redirect_to request_url(@info_request)
- return
- end
+ info_request = InfoRequest.find(params[:id].to_i)
+ set_last_request(info_request)
# If this is an external request, go to the request page - we don't allow
# state change from the front end interface.
- if @info_request.is_external?
- redirect_to request_url(@info_request)
+ if info_request.is_external?
+ redirect_to request_url(info_request)
return
end
- @is_owning_user = @info_request.is_owning_user?(authenticated_user)
- @last_info_request_event_id = @info_request.last_event_id_needing_description
- @old_unclassified = @info_request.is_old_unclassified? && !authenticated_user.nil?
-
- # Check authenticated, and parameters set. We check is_owning_user
- # to get admin overrides (see is_owning_user? above)
- if !@old_unclassified && !@is_owning_user && !authenticated_as_user?(@info_request.user,
+ # Check authenticated, and parameters set.
+ unless Ability::can_update_request_state?(authenticated_user, info_request)
+ authenticated_as_user?(info_request.user,
:web => _("To classify the response to this FOI request"),
- :email => _("Then you can classify the FOI response you have got from ") + @info_request.public_body.name + ".",
- :email_subject => _("Classify an FOI response from ") + @info_request.public_body.name
- )
+ :email => _("Then you can classify the FOI response you have got from ") + info_request.public_body.name + ".",
+ :email_subject => _("Classify an FOI response from ") + info_request.public_body.name)
# do nothing - as "authenticated?" has done the redirect to signin page for us
return
end
if !params[:incoming_message]
flash[:error] = _("Please choose whether or not you got some of the information that you wanted.")
- redirect_to request_url(@info_request)
+ redirect_to request_url(info_request)
return
end
- if params[:last_info_request_event_id].to_i != @last_info_request_event_id
+ if params[:last_info_request_event_id].to_i != info_request.last_event_id_needing_description
flash[:error] = _("The request has been updated since you originally loaded this page. Please check for any new incoming messages below, and try again.")
- redirect_to request_url(@info_request)
+ redirect_to request_url(info_request)
+ return
+ end
+
+ described_state = params[:incoming_message][:described_state]
+ message = params[:incoming_message][:message]
+ # For requires_admin and error_message states we ask for an extra message to send to
+ # the administrators.
+ # If this message hasn't been included then ask for it
+ if ["error_message", "requires_admin"].include?(described_state) && message.nil?
+ redirect_to describe_state_message_url(:url_title => info_request.url_title, :described_state => described_state)
return
end
# Make the state change
- old_described_state = @info_request.described_state
- @info_request.set_described_state(params[:incoming_message][:described_state])
+ info_request.set_described_state(described_state, authenticated_user, message)
# If you're not the *actual* requester. e.g. you are playing the
# classification game, or you're doing this just because you are an
# admin user (not because you also own the request).
- if !@info_request.is_actual_owning_user?(authenticated_user)
- # Log the status change by someone other than the requester
- event = @info_request.log_event("status_update",
- { :user_id => authenticated_user.id,
- :old_described_state => old_described_state,
- :described_state => @info_request.described_state,
- })
- # Create a classification event for league tables
- RequestClassification.create!(:user_id => authenticated_user.id,
- :info_request_event_id => event.id)
-
+ if !info_request.is_actual_owning_user?(authenticated_user)
# Don't give advice on what to do next, as it isn't their request
- RequestMailer.deliver_old_unclassified_updated(@info_request) if !@info_request.is_external?
if session[:request_game]
- flash[:notice] = _('Thank you for updating the status of the request \'<a href="{{url}}">{{info_request_title}}</a>\'. There are some more requests below for you to classify.',:info_request_title=>CGI.escapeHTML(@info_request.title), :url=>CGI.escapeHTML(request_path(@info_request)))
+ flash[:notice] = _('Thank you for updating the status of the request \'<a href="{{url}}">{{info_request_title}}</a>\'. There are some more requests below for you to classify.',:info_request_title=>CGI.escapeHTML(info_request.title), :url=>CGI.escapeHTML(request_path(info_request)))
redirect_to categorise_play_url
else
flash[:notice] = _('Thank you for updating this request!')
- redirect_to request_url(@info_request)
+ redirect_to request_url(info_request)
end
return
end
- calculated_status = @info_request.calculate_status
# Display advice for requester on what to do next, as appropriate
- if calculated_status == 'waiting_response'
- flash[:notice] = _("<p>Thank you! Hopefully your wait isn't too long.</p> <p>By law, you should get a response promptly, and normally before the end of <strong>
-{{date_response_required_by}}</strong>.</p>",:date_response_required_by=>simple_date(@info_request.date_response_required_by))
- redirect_to request_url(@info_request)
- elsif calculated_status == 'waiting_response_overdue'
- flash[:notice] = _("<p>Thank you! Hope you don't have to wait much longer.</p> <p>By law, you should have got a response promptly, and normally before the end of <strong>{{date_response_required_by}}</strong>.</p>",:date_response_required_by=>simple_date(@info_request.date_response_required_by))
- redirect_to request_url(@info_request)
- elsif calculated_status == 'waiting_response_very_overdue'
- flash[:notice] = _("<p>Thank you! Your request is long overdue, by more than {{very_late_number_of_days}} working days. Most requests should be answered within {{late_number_of_days}} working days. You might like to complain about this, see below.</p>", :very_late_number_of_days => Configuration::reply_very_late_after_days, :late_number_of_days => Configuration::reply_late_after_days)
- redirect_to unhappy_url(@info_request)
- elsif calculated_status == 'not_held'
- flash[:notice] = _("<p>Thank you! Here are some ideas on what to do next:</p>
+ flash[:notice] = case info_request.calculate_status
+ when 'waiting_response'
+ _("<p>Thank you! Hopefully your wait isn't too long.</p> <p>By law, you should get a response promptly, and normally before the end of <strong>
+{{date_response_required_by}}</strong>.</p>",:date_response_required_by=>simple_date(info_request.date_response_required_by))
+ when 'waiting_response_overdue'
+ _("<p>Thank you! Hope you don't have to wait much longer.</p> <p>By law, you should have got a response promptly, and normally before the end of <strong>{{date_response_required_by}}</strong>.</p>",:date_response_required_by=>simple_date(info_request.date_response_required_by))
+ when 'waiting_response_very_overdue'
+ _("<p>Thank you! Your request is long overdue, by more than {{very_late_number_of_days}} working days. Most requests should be answered within {{late_number_of_days}} working days. You might like to complain about this, see below.</p>", :very_late_number_of_days => Configuration::reply_very_late_after_days, :late_number_of_days => Configuration::reply_late_after_days)
+ when 'not_held'
+ _("<p>Thank you! Here are some ideas on what to do next:</p>
<ul>
<li>To send your request to another authority, first copy the text of your request below, then <a href=\"{{find_authority_url}}\">find the other authority</a>.</li>
<li>If you would like to contest the authority's claim that they do not hold the information, here is
@@ -471,44 +455,60 @@ class RequestController < ApplicationController
</li>
</ul>",
:find_authority_url => "/new",
- :complain_url => CGI.escapeHTML(unhappy_url(@info_request)),
- :other_means_url => CGI.escapeHTML(unhappy_url(@info_request)) + "#other_means")
- redirect_to request_url(@info_request)
- elsif calculated_status == 'rejected'
- flash[:notice] = _("Oh no! Sorry to hear that your request was refused. Here is what to do now.")
- redirect_to unhappy_url(@info_request)
- elsif calculated_status == 'successful'
- flash[:notice] = _("<p>We're glad you got all the information that you wanted. If you write about or make use of the information, please come back and add an annotation below saying what you did.</p><p>If you found {{site_name}} useful, <a href=\"{{donation_url}}\">make a donation</a> to the charity which runs it.</p>", :site_name=>site_name, :donation_url => "http://www.mysociety.org/donate/")
- redirect_to request_url(@info_request)
- elsif calculated_status == 'partially_successful'
- flash[:notice] = _("<p>We're glad you got some of the information that you wanted. If you found {{site_name}} useful, <a href=\"{{donation_url}}\">make a donation</a> to the charity which runs it.</p><p>If you want to try and get the rest of the information, here's what to do now.</p>", :site_name=>site_name, :donation_url=>"http://www.mysociety.org/donate/")
- redirect_to unhappy_url(@info_request)
- elsif calculated_status == 'waiting_clarification'
- flash[:notice] = _("Please write your follow up message containing the necessary clarifications below.")
- redirect_to respond_to_last_url(@info_request)
- elsif calculated_status == 'gone_postal'
- redirect_to respond_to_last_url(@info_request) + "?gone_postal=1"
- elsif calculated_status == 'internal_review'
- flash[:notice] = _("<p>Thank you! Hopefully your wait isn't too long.</p><p>You should get a response within {{late_number_of_days}} days, or be told if it will take longer (<a href=\"{{review_url}}\">details</a>).</p>",:late_number_of_days => Configuration.reply_late_after_days, :review_url => unhappy_url(@info_request) + "#internal_review")
- redirect_to request_url(@info_request)
- elsif calculated_status == 'error_message'
- flash[:notice] = _("<p>Thank you! We'll look into what happened and try and fix it up.</p><p>If the error was a delivery failure, and you can find an up to date FOI email address for the authority, please tell us using the form below.</p>")
- redirect_to help_general_url(:action => 'contact')
- elsif calculated_status == 'requires_admin'
- flash[:notice] = _("Please use the form below to tell us more.")
- redirect_to help_general_url(:action => 'contact')
- elsif calculated_status == 'user_withdrawn'
- flash[:notice] = _("If you have not done so already, please write a message below telling the authority that you have withdrawn your request. Otherwise they will not know it has been withdrawn.")
- redirect_to respond_to_last_url(@info_request)
+ :complain_url => CGI.escapeHTML(unhappy_url(info_request)),
+ :other_means_url => CGI.escapeHTML(unhappy_url(info_request)) + "#other_means")
+ when 'rejected'
+ _("Oh no! Sorry to hear that your request was refused. Here is what to do now.")
+ when 'successful'
+ _("<p>We're glad you got all the information that you wanted. If you write about or make use of the information, please come back and add an annotation below saying what you did.</p><p>If you found {{site_name}} useful, <a href=\"{{donation_url}}\">make a donation</a> to the charity which runs it.</p>", :site_name=>site_name, :donation_url => "http://www.mysociety.org/donate/")
+ when 'partially_successful'
+ _("<p>We're glad you got some of the information that you wanted. If you found {{site_name}} useful, <a href=\"{{donation_url}}\">make a donation</a> to the charity which runs it.</p><p>If you want to try and get the rest of the information, here's what to do now.</p>", :site_name=>site_name, :donation_url=>"http://www.mysociety.org/donate/")
+ when 'waiting_clarification'
+ _("Please write your follow up message containing the necessary clarifications below.")
+ when 'gone_postal'
+ nil
+ when 'internal_review'
+ _("<p>Thank you! Hopefully your wait isn't too long.</p><p>You should get a response within {{late_number_of_days}} days, or be told if it will take longer (<a href=\"{{review_url}}\">details</a>).</p>",:late_number_of_days => Configuration.reply_late_after_days, :review_url => unhappy_url(info_request) + "#internal_review")
+ when 'error_message', 'requires_admin'
+ _("Thank you! We'll look into what happened and try and fix it up.")
+ when 'user_withdrawn'
+ _("If you have not done so already, please write a message below telling the authority that you have withdrawn your request. Otherwise they will not know it has been withdrawn.")
+ end
+
+ case info_request.calculate_status
+ when 'waiting_response', 'waiting_response_overdue', 'not_held', 'successful',
+ 'internal_review', 'error_message', 'requires_admin'
+ redirect_to request_url(info_request)
+ when 'waiting_response_very_overdue', 'rejected', 'partially_successful'
+ redirect_to unhappy_url(info_request)
+ when 'waiting_clarification', 'user_withdrawn'
+ redirect_to respond_to_last_url(info_request)
+ when 'gone_postal'
+ redirect_to respond_to_last_url(info_request) + "?gone_postal=1"
else
if @@custom_states_loaded
- return self.theme_describe_state(@info_request)
+ return self.theme_describe_state(info_request)
else
- raise "unknown calculate_status " + calculated_status
+ raise "unknown calculate_status #{info_request.calculate_status}"
end
end
end
+ # Collect a message to include with the change of state
+ def describe_state_message
+ @info_request = InfoRequest.find_by_url_title!(params[:url_title])
+ @described_state = params[:described_state]
+ @last_info_request_event_id = @info_request.last_event_id_needing_description
+ @title = case @described_state
+ when "error_message"
+ _("I've received an error message")
+ when "requires_admin"
+ _("This request requires administrator attention")
+ else
+ raise "Unsupported state"
+ end
+ end
+
# Used for links from polymorphic URLs e.g. in Atom feeds - just redirect to
# proper URL for the message the event refers to
def show_request_event
@@ -882,7 +882,7 @@ class RequestController < ApplicationController
:email_subject => _("Log in to download a zip file of {{info_request_title}}",
:info_request_title=>@info_request.title)
)
- updated = Digest::SHA1.hexdigest(@info_request.get_last_event.created_at.to_i.to_s + @info_request.updated_at.to_i.to_s)
+ updated = Digest::SHA1.hexdigest(@info_request.info_request_events.last.created_at.to_i.to_s + @info_request.updated_at.to_i.to_s)
@url_path = File.join("/download",
request_dirs(@info_request),
updated,
diff --git a/app/models/info_request.rb b/app/models/info_request.rb
index cee9eb959..237364f56 100644
--- a/app/models/info_request.rb
+++ b/app/models/info_request.rb
@@ -543,20 +543,16 @@ public
# states which require administrator action (hence email administrators
# when they are entered, and offer state change dialog to them)
- def InfoRequest.requires_admin_states
- return ['requires_admin', 'error_message', 'attention_requested']
- end
-
def requires_admin?
- return true if InfoRequest.requires_admin_states.include?(described_state)
- return false
+ ['requires_admin', 'error_message', 'attention_requested'].include?(described_state)
end
# change status, including for last event for later historical purposes
- def set_described_state(new_state, set_by = nil)
+ def set_described_state(new_state, set_by = nil, message = "")
+ old_described_state = described_state
ActiveRecord::Base.transaction do
self.awaiting_description = false
- last_event = self.get_last_event
+ last_event = self.info_request_events.last
last_event.described_state = new_state
self.described_state = new_state
last_event.save!
@@ -568,9 +564,23 @@ public
if self.requires_admin?
# Check there is someone to send the message "from"
if !set_by.nil? || !self.user.nil?
- RequestMailer.deliver_requires_admin(self, set_by)
+ RequestMailer.deliver_requires_admin(self, set_by, message)
end
end
+
+ unless set_by.nil? || is_actual_owning_user?(set_by) || described_state == 'attention_requested'
+ # Log the status change by someone other than the requester
+ event = log_event("status_update",
+ { :user_id => set_by.id,
+ :old_described_state => old_described_state,
+ :described_state => described_state,
+ })
+ # Create a classification event for league tables
+ RequestClassification.create!(:user_id => set_by.id,
+ :info_request_event_id => event.id)
+
+ RequestMailer.deliver_old_unclassified_updated(self) if !is_external?
+ end
end
# Work out what the situation of the request is. In addition to values of
@@ -719,41 +729,28 @@ public
self.info_request_events.create!(:event_type => type, :params => params)
end
+ def response_events
+ self.info_request_events.select{|e| e.response?}
+ end
+
# The last response is the default one people might want to reply to
def get_last_response_event_id
- for e in self.info_request_events.reverse
- if e.event_type == 'response'
- return e.id
- end
- end
- return nil
-
+ get_last_response_event.id if get_last_response_event
end
def get_last_response_event
- for e in self.info_request_events.reverse
- if e.event_type == 'response'
- return e
- end
- end
- return nil
+ response_events.last
end
def get_last_response
- last_response_event = self.get_last_response_event
- if last_response_event.nil?
- return nil
- else
- return last_response_event.incoming_message
- end
+ get_last_response_event.incoming_message if get_last_response_event
+ end
+
+ def outgoing_events
+ info_request_events.select{|e| e.outgoing? }
end
# The last outgoing message
def get_last_outgoing_event
- for e in self.info_request_events.reverse
- if [ 'sent', 'followup_sent' ].include?(e.event_type)
- return e
- end
- end
- return nil
+ outgoing_events.last
end
# Text from the the initial request, for use in summary display
@@ -794,16 +791,6 @@ public
end
end
- # Returns last event
- def get_last_event
- events = self.info_request_events
- if events.size == 0
- return nil
- else
- return events[-1]
- end
- end
-
# Get previous email sent to
def get_previous_email_sent_to(info_request_event)
last_email = nil
@@ -821,46 +808,31 @@ public
# Display version of status
def InfoRequest.get_status_description(status)
- if status == 'waiting_classification'
- _("Awaiting classification.")
- elsif status == 'waiting_response'
- _("Awaiting response.")
- elsif status == 'waiting_response_overdue'
- _("Delayed.")
- elsif status == 'waiting_response_very_overdue'
- _("Long overdue.")
- elsif status == 'not_held'
- _("Information not held.")
- elsif status == 'rejected'
- _("Refused.")
- elsif status == 'partially_successful'
- _("Partially successful.")
- elsif status == 'successful'
- _("Successful.")
- elsif status == 'waiting_clarification'
- _("Waiting clarification.")
- elsif status == 'gone_postal'
- _("Handled by post.")
- elsif status == 'internal_review'
- _("Awaiting internal review.")
- elsif status == 'error_message'
- _("Delivery error")
- elsif status == 'requires_admin'
- _("Unusual response.")
- elsif status == 'attention_requested'
- _("Reported for administrator attention.")
- elsif status == 'user_withdrawn'
- _("Withdrawn by the requester.")
- elsif status == 'vexatious'
- _("Considered by administrators as vexatious and hidden from site.")
- elsif status == 'not_foi'
- _("Considered by administrators as not an FOI request and hidden from site.")
+ descriptions = {
+ 'waiting_classification' => _("Awaiting classification."),
+ 'waiting_response' => _("Awaiting response."),
+ 'waiting_response_overdue' => _("Delayed."),
+ 'waiting_response_very_overdue' => _("Long overdue."),
+ 'not_held' => _("Information not held."),
+ 'rejected' => _("Refused."),
+ 'partially_successful' => _("Partially successful."),
+ 'successful' => _("Successful."),
+ 'waiting_clarification' => _("Waiting clarification."),
+ 'gone_postal' => _("Handled by post."),
+ 'internal_review' => _("Awaiting internal review."),
+ 'error_message' => _("Delivery error"),
+ 'requires_admin' => _("Unusual response."),
+ 'attention_requested' => _("Reported for administrator attention."),
+ 'user_withdrawn' => _("Withdrawn by the requester."),
+ 'vexatious' => _("Considered by administrators as vexatious and hidden from site."),
+ 'not_foi' => _("Considered by administrators as not an FOI request and hidden from site."),
+ }
+ if descriptions[status]
+ descriptions[status]
+ elsif respond_to?(:theme_display_status)
+ theme_display_status(status)
else
- begin
- return self.theme_display_status(status)
- rescue NoMethodError
- raise _("unknown status ") + status
- end
+ raise _("unknown status ") + status
end
end
@@ -987,13 +959,8 @@ public
end
def is_old_unclassified?
- return false if is_external?
- return false if !awaiting_description
- return false if url_title == 'holding_pen'
- last_response_event = get_last_response_event
- return false unless last_response_event
- return false if last_response_event.created_at >= Time.now - OLD_AGE_IN_DAYS
- return true
+ !is_external? && awaiting_description && url_title != 'holding_pen' && get_last_response_event &&
+ Time.now > get_last_response_event.created_at + OLD_AGE_IN_DAYS
end
# List of incoming messages to followup, by unique email
diff --git a/app/models/info_request_event.rb b/app/models/info_request_event.rb
index 09eba31ab..871b81b1f 100644
--- a/app/models/info_request_event.rb
+++ b/app/models/info_request_event.rb
@@ -77,17 +77,18 @@ class InfoRequestEvent < ActiveRecord::Base
end
def user_can_view?(user)
- if !self.info_request.user_can_view?(user)
+ unless info_request.user_can_view?(user)
raise "internal error, called user_can_view? on event when there is not permission to view entire request"
end
- if self.prominence == 'hidden'
- return User.view_hidden_requests?(user)
- end
- if self.prominence == 'requester_only'
- return self.info_request.is_owning_user?(user)
+ case prominence
+ when 'hidden'
+ User.view_hidden_requests?(user)
+ when 'requester_only'
+ info_request.is_owning_user?(user)
+ else
+ true
end
- return true
end
@@ -363,16 +364,19 @@ class InfoRequestEvent < ActiveRecord::Base
end
def is_sent_sort?
- if [ 'sent', 'resent'].include?(self.event_type)
- return true
- end
- return false
+ ['sent', 'resent'].include?(event_type)
end
+
def is_followup_sort?
- if [ 'followup_sent', 'followup_resent'].include?(self.event_type)
- return true
- end
- return false
+ ['followup_sent', 'followup_resent'].include?(event_type)
+ end
+
+ def outgoing?
+ ['sent', 'followup_sent'].include?(event_type)
+ end
+
+ def response?
+ event_type == 'response'
end
def same_email_as_previous_send?
diff --git a/app/models/request_mailer.rb b/app/models/request_mailer.rb
index 6f8d88a1a..955f73ef4 100644
--- a/app/models/request_mailer.rb
+++ b/app/models/request_mailer.rb
@@ -62,18 +62,14 @@ class RequestMailer < ApplicationMailer
end
# An FOI response is outside the scope of the system, and needs admin attention
- def requires_admin(info_request, set_by = nil)
- if !set_by.nil?
- user = set_by
- else
- user = info_request.user
- end
+ def requires_admin(info_request, set_by = nil, message = "")
+ user = set_by || info_request.user
@from = user.name_and_email
@recipients = contact_from_name_and_email
@subject = _("FOI response requires admin ({{reason}}) - {{title}}", :reason => info_request.described_state, :title => info_request.title)
url = request_url(info_request)
admin_url = admin_request_show_url(info_request)
- @body = {:reported_by => user, :info_request => info_request, :url => url, :admin_url => admin_url }
+ @body = {:reported_by => user, :message => message, :info_request => info_request, :url => url, :admin_url => admin_url }
end
# Tell the requester that a new response has arrived
diff --git a/app/views/request/_describe_state.rhtml b/app/views/request/_describe_state.rhtml
index fde1cdfa7..0b65024fd 100644
--- a/app/views/request/_describe_state.rhtml
+++ b/app/views/request/_describe_state.rhtml
@@ -97,7 +97,6 @@
<p>
<%= hidden_field_tag 'last_info_request_event_id', @last_info_request_event_id, :id => 'last_info_request_event_id' + id_suffix %>
- <%= hidden_field_tag 'submitted_describe_state', 1, :id => 'submitted_describe_state' + id_suffix %>
<%= submit_tag _("Submit status") %> (<%= _('and we\'ll suggest <strong>what to do next</strong>') %>)
</p>
<% end %>
diff --git a/app/views/request/_other_describe_state.rhtml b/app/views/request/_other_describe_state.rhtml
index e274fe8c9..3a80823c6 100644
--- a/app/views/request/_other_describe_state.rhtml
+++ b/app/views/request/_other_describe_state.rhtml
@@ -75,7 +75,6 @@
<p>
<%= hidden_field_tag 'last_info_request_event_id', @last_info_request_event_id, :id => 'last_info_request_event_id' + id_suffix %>
- <%= hidden_field_tag 'submitted_describe_state', 1, :id => 'submitted_describe_state' + id_suffix %>
<%= submit_tag "Submit status" %>
</p>
<% end %>
diff --git a/app/views/request/describe_state_message.rhtml b/app/views/request/describe_state_message.rhtml
new file mode 100644
index 000000000..1427fea22
--- /dev/null
+++ b/app/views/request/describe_state_message.rhtml
@@ -0,0 +1,30 @@
+<h1><%= @title %></h1>
+
+
+<p>
+ <% if @described_state == "error_message" %>
+ <%= _("If the error was a delivery failure, and you can find an up to date FOI email address for the authority, please tell us using the form below.") %>
+ <% else %>
+ <%= _("Just one more thing") %>
+ <% end %>
+</p>
+
+<% form_for :incoming_message, :url => describe_state_url(:id => @info_request.id) do |f| %>
+
+ <p>
+ <label class="form_label" for="incoming_message_message">Please tell us more:</label>
+ <%= f.text_area :message, :rows => 10, :cols => 60 %>
+ </p>
+
+ <div>
+ <%= hidden_field_tag "incoming_message[described_state]", @described_state %>
+ <%= hidden_field_tag :last_info_request_event_id, @last_info_request_event_id %>
+ </div>
+
+ <div class="form_button">
+ <%= submit_tag _("Submit status and send message") %>
+ </div>
+
+<% end %>
+
+
diff --git a/app/views/request_mailer/requires_admin.rhtml b/app/views/request_mailer/requires_admin.rhtml
index e7ab53c59..b2e58295e 100644
--- a/app/views/request_mailer/requires_admin.rhtml
+++ b/app/views/request_mailer/requires_admin.rhtml
@@ -1,3 +1,5 @@
+<%= raw @message %>
+
---------------------------------------------------------------------
<%= raw @reported_by.name %> <%= _('has reported an')%> <%= raw @info_request.law_used_short %>
<%= _('response as needing administrator attention. Take a look, and reply to this