diff options
-rw-r--r-- | app/controllers/request_controller.rb | 3 | ||||
-rw-r--r-- | app/models/incoming_message.rb | 4 | ||||
-rw-r--r-- | app/models/info_request.rb | 56 | ||||
-rw-r--r-- | app/models/rejection_reason.rb | 20 | ||||
-rw-r--r-- | app/views/request/show.rhtml | 26 | ||||
-rw-r--r-- | config/routes.rb | 5 | ||||
-rw-r--r-- | db/migrate/018_add_response_type_to_incoming_message.rb | 18 | ||||
-rw-r--r-- | db/migrate/019_create_rejection_reasons.rb | 10 | ||||
-rw-r--r-- | db/schema.rb | 19 | ||||
-rw-r--r-- | spec/controllers/request_controller_spec.rb | 4 | ||||
-rw-r--r-- | spec/fixtures/incoming_messages.yml | 25 | ||||
-rw-r--r-- | spec/models/incoming_message_spec.rb | 10 | ||||
-rw-r--r-- | spec/models/request_mailer_spec.rb | 6 | ||||
-rw-r--r-- | todo.txt | 20 |
14 files changed, 203 insertions, 23 deletions
diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb index 05affaf67..1a1b2be90 100644 --- a/app/controllers/request_controller.rb +++ b/app/controllers/request_controller.rb @@ -4,7 +4,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: request_controller.rb,v 1.15 2007-11-13 12:47:05 francis Exp $ +# $Id: request_controller.rb,v 1.16 2007-11-14 01:01:38 francis Exp $ class RequestController < ApplicationController @@ -12,6 +12,7 @@ class RequestController < ApplicationController @info_request = InfoRequest.find(params[:id]) @correspondences = @info_request.outgoing_messages + @info_request.incoming_messages @correspondences.sort! { |a,b| a.sent_at <=> b.sent_at } + @status = @info_request.calculate_status end def list diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb index 0d051d379..30cd1f74e 100644 --- a/app/models/incoming_message.rb +++ b/app/models/incoming_message.rb @@ -5,7 +5,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: incoming_message.rb,v 1.4 2007-11-13 10:22:14 francis Exp $ +# $Id: incoming_message.rb,v 1.5 2007-11-14 01:01:39 francis Exp $ class IncomingMessage < ActiveRecord::Base belongs_to :info_request @@ -13,6 +13,8 @@ class IncomingMessage < ActiveRecord::Base validates_presence_of :raw_data + has_many :rejection_reasons + # Return the structured TMail::Mail object # Documentation at http://i.loveruby.net/en/projects/tmail/doc/ def mail diff --git a/app/models/info_request.rb b/app/models/info_request.rb index e6b8c2b0a..eb02587a8 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -4,7 +4,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: info_request.rb,v 1.12 2007-11-13 10:22:14 francis Exp $ +# $Id: info_request.rb,v 1.13 2007-11-14 01:01:39 francis Exp $ require 'digest/sha1' @@ -57,6 +57,60 @@ class InfoRequest < ActiveRecord::Base incoming_message.save end + # Work out what the situation of the request is + def calculate_status + # Extract aggregate information for any incoming messages all together + contains_information = false + rejection_reasons = [] + self.incoming_messages.each do |msg| + if msg.user_classified + if msg.contains_information + contains_information = true + end + rejection_reasons += msg.rejection_reasons + end + end + + # See if response would be overdue + overdue = false + # XXX if a second outgoing message is really a new request, then this + # is no good + earliest_sent = self.outgoing_messages.map { |om| om.sent_at }.min + time_left = Time.now - earliest_sent + # XXX use working days + if time_left > 20.days + overdue = true + end + + # Return appropriate status string + if self.incoming_messages.size == 0 + if overdue + return "overdue" + else + return "awaiting" + end + end + if contains_information and rejection_reasons.size > 0 + return "information_and_rejection" + end + if contains_information and rejection_reasons.size == 0 + return "information" + end + if rejection_reasons.size > 0 + return "rejection" + end + return "unknown" + end + # - Awaiting response (in 20 working day limit) + # - Overdue a response (over 20 working day limit) + # + # - Has a response but not sure what to think of it + # - Received a positive response + # - Received a partly positive response w/ rejection reasons + # - Received an entirely negative response w/ rejection reasons + # + # - Have sent a follow up + end diff --git a/app/models/rejection_reason.rb b/app/models/rejection_reason.rb new file mode 100644 index 000000000..c3cc55d7d --- /dev/null +++ b/app/models/rejection_reason.rb @@ -0,0 +1,20 @@ +# app/models/rejection_reasons.rb +# Give one reason under the Freedom of Information Act 2000 as to why +# a particular incoming message was rejected. An incoming message can +# have multiple such reasons. +# +# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. +# Email: francis@mysociety.org; WWW: http://www.mysociety.org/ +# +# $Id: rejection_reason.rb,v 1.1 2007-11-14 01:01:39 francis Exp $ + +class RejectionReason < ActiveRecord::Base + belongs_to :incoming_message + validates_presence_of :incoming_message_id + + def self.all_reasons + ['commerciallyconfidential'] + end + + validates_inclusion_of :reason, :in => RejectionReason.all_reasons +end diff --git a/app/views/request/show.rhtml b/app/views/request/show.rhtml index c880261dc..8b29c3009 100644 --- a/app/views/request/show.rhtml +++ b/app/views/request/show.rhtml @@ -8,6 +8,27 @@ by <%= user_link(@info_request.user) %> </p> +<p class="xspeaker"> +<% if @status == 'awaiting' %> +Currently <strong>waiting for a response</strong> from <%= public_body_link(@info_request.public_body) %> +<% elsif @status == 'overdue' %> +Currently <strong>overdue a response</strong> from <%= +public_body_link(@info_request.public_body) %>. Under section blah of the +Freedom of Information Act 2000 responses must be made within 20 working days. +<% elsif @status == 'information_and_rejection' %> +The request was <strong>partly successful, partly rejected</strong> +<% elsif @status == 'information' %> +The request was <strong>successful</strong> +<% elsif @status == 'rejection' %> +The request was <strong>rejected</strong> +<% elsif @status == 'unknown' %> +<strong>Response received</strong>, but <%= user_link(@info_request.user) %> has not yet reported if it was +successful or a rejection. +<% else %> +<% raise "unknown status " + $status %> +<% end %> +</p> + <% for correspondence in @correspondences %> <div id="correspondence"> @@ -36,8 +57,9 @@ by <p class="xspeaker"> <%= incoming_message.mail.friendly_from %> - wrote a reply - on <strong><%= simple_date(incoming_message.sent_at) %></strong> + of <%= public_body_link(@info_request.public_body) %> + wrote a reply on <strong><%= simple_date(incoming_message.sent_at) + %></strong> </p> <% else %> <% raise "Unknown correspondence type" + correspondence.class.to_s %> diff --git a/config/routes.rb b/config/routes.rb index cb235172f..1d08007b8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,7 +4,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: routes.rb,v 1.20 2007-11-05 16:46:11 francis Exp $ +# $Id: routes.rb,v 1.21 2007-11-14 01:01:39 francis Exp $ ActionController::Routing::Routes.draw do |map| # The priority is based upon order of creation: first created -> highest priority. @@ -18,7 +18,8 @@ ActionController::Routing::Routes.draw do |map| request.request_list '/list', :action => 'list' request.new_request '/new', :action => 'new' request.create_request '/create', :action => 'create' - request.show_request '/request/:id', :action => 'show' + request.show_request '/request/:id', :action => 'show' + request.classify_request '/classify/:id', :action => 'classify' end map.with_options :controller => 'user' do |user| diff --git a/db/migrate/018_add_response_type_to_incoming_message.rb b/db/migrate/018_add_response_type_to_incoming_message.rb new file mode 100644 index 000000000..c841b599a --- /dev/null +++ b/db/migrate/018_add_response_type_to_incoming_message.rb @@ -0,0 +1,18 @@ +class AddResponseTypeToIncomingMessage < ActiveRecord::Migration + def self.up + add_column :incoming_messages, :user_classified, :boolean, :default => false + add_column :incoming_messages, :contains_information, :boolean, :default => false + + create_table :rejection_reasons do |t| + t.column :incoming_message_id, :integer + t.column :reason, :string + t.column :created_at, :datetime + t.column :updated_at, :datetime + end + end + + def self.down + remove_column :incoming_messages, :contains_information + drop_table :rejection_reasons + end +end diff --git a/db/migrate/019_create_rejection_reasons.rb b/db/migrate/019_create_rejection_reasons.rb new file mode 100644 index 000000000..a1c8a4c89 --- /dev/null +++ b/db/migrate/019_create_rejection_reasons.rb @@ -0,0 +1,10 @@ +class CreateRejectionReasons < ActiveRecord::Migration + def self.up + create_table :rejection_reasons do |t| + end + end + + def self.down + drop_table :rejection_reasons + end +end diff --git a/db/schema.rb b/db/schema.rb index 9f05fd4b4..188c180f1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -2,13 +2,15 @@ # migrations feature of ActiveRecord to incrementally modify your database, and # then regenerate this schema definition. -ActiveRecord::Schema.define(:version => 17) do +ActiveRecord::Schema.define(:version => 18) do create_table "incoming_messages", :force => true do |t| - t.column "info_request_id", :integer - t.column "raw_data", :text - t.column "created_at", :datetime - t.column "updated_at", :datetime + t.column "info_request_id", :integer + t.column "raw_data", :text + t.column "created_at", :datetime + t.column "updated_at", :datetime + t.column "user_classified", :boolean, :default => false + t.column "contains_information", :boolean, :default => false end create_table "info_requests", :force => true do |t| @@ -64,6 +66,13 @@ ActiveRecord::Schema.define(:version => 17) do t.column "last_edit_comment", :string end + create_table "rejection_reasons", :force => true do |t| + t.column "incoming_message_id", :integer + t.column "reason", :string + t.column "created_at", :datetime + t.column "updated_at", :datetime + end + create_table "sessions", :force => true do |t| t.column "session_id", :string t.column "data", :text diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index bca0a2a57..5758e2b2a 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -49,7 +49,7 @@ end describe RequestController, "when showing one request" do integrate_views - fixtures :info_requests, :public_bodies, :users # all needed as integrating views + fixtures :info_requests, :public_bodies, :users, :incoming_messages # all needed as integrating views it "should be successful" do get :show, :id => 101 @@ -70,7 +70,7 @@ describe RequestController, "when showing one request" do ir = info_requests(:fancy_dog_request) receive_incoming_mail('incoming-request-plain.email', ir.incoming_email) get :show, :id => 101 - assigns[:correspondences].size.should == 1 + assigns[:correspondences].size.should == 2 end end diff --git a/spec/fixtures/incoming_messages.yml b/spec/fixtures/incoming_messages.yml index cb3dfa5e6..2e3c74f69 100644 --- a/spec/fixtures/incoming_messages.yml +++ b/spec/fixtures/incoming_messages.yml @@ -1,4 +1,23 @@ -new_request_message: +useless_incoming_message: id: 1 - info_request_id: 1 - raw_data: xxxx
\ No newline at end of file + info_request_id: 101 + updated_at: 2007-11-13 18:09:20.042061 + raw_data: | + From: Francis Irving <frabcus@fastmail.fm> + To: FOI Person <foiperson@localhost> + Date: Tue, 13 Nov 2007 11:39:55 +0000 + NoCc: foi+request-1-4b571715@cat + Bcc: + Subject: Re: Freedom of Information Request - Why do you have such a fancy dog? + Reply-To: + In-Reply-To: <471f1eae5d1cb_7347..fdbe67386163@cat.tmail> + + No way! I'm not going to tell you that in a month of Thursdays. + + The Geraldine Quango + + On Wed, Oct 24, 2007 at 11:30:06AM +0100, Bob Smith wrote: + > Why do you have such a fancy dog? + + created_at: 2007-11-13 18:09:20.042061 + diff --git a/spec/models/incoming_message_spec.rb b/spec/models/incoming_message_spec.rb index 25f2fce5f..55c042141 100644 --- a/spec/models/incoming_message_spec.rb +++ b/spec/models/incoming_message_spec.rb @@ -1,8 +1,16 @@ require File.dirname(__FILE__) + '/../spec_helper' -describe IncomingMessage, " when blah" do +describe IncomingMessage, " when dealing with incoming mail" do + fixtures :incoming_messages + before do + @im = incoming_messages(:useless_incoming_message) + end + + it "should return the mail Date header date for sent at" do + @im.sent_at.should == @im.mail.date end + end diff --git a/spec/models/request_mailer_spec.rb b/spec/models/request_mailer_spec.rb index 8bac9e5da..67a9536af 100644 --- a/spec/models/request_mailer_spec.rb +++ b/spec/models/request_mailer_spec.rb @@ -1,7 +1,7 @@ require File.dirname(__FILE__) + '/../spec_helper' describe RequestMailer, " when receiving incoming mail" do - fixtures :info_requests + fixtures :info_requests, :incoming_messages before do @@ -10,13 +10,13 @@ describe RequestMailer, " when receiving incoming mail" do it "should append it to the appropriate request" do ir = info_requests(:fancy_dog_request) receive_incoming_mail('incoming-request-plain.email', ir.incoming_email) - ir.incoming_messages.size.should == 1 + ir.incoming_messages.size.should == 2 end it "should bounce email to admin when the email is not to any information request" do ir = info_requests(:fancy_dog_request) receive_incoming_mail('incoming-request-plain.email', 'dummy@localhost') - ir.incoming_messages.size.should == 0 + ir.incoming_messages.size.should == 1 deliveries = ActionMailer::Base.deliveries deliveries.size.should == 1 @@ -1,14 +1,25 @@ -Check confirmed everywhere in password check etc. +Status outputs for entire request: + +- Awaiting response (in 20 working day limit) +- Overdue a response (over 20 working day limit) + +- Received a positive response +- Received a partly positive response w/ rejection reasons +- Received an entirely negative response w/ rejection reasons + +- Have sent a follow up Next ==== +Check confirmed everywhere in password check etc. + Send email to requestor telling them new information has come in Let them send follow-ups Do something after 20 working days if you get no response Forgotten password link -Email has already been taken hasn't got a link to better place +Email has already been taken hasn't got a way to sign in Link from error page for signin/signup to go to other one Remember me box @@ -20,10 +31,13 @@ Test that actually sending request outgoing mail using deliveries Remove "Outgoing messages is invalid" error +Remove everything from test/ Tidying ======= +Use working days + Bubbles don't validate http://localhost:3000/request/5 @@ -70,6 +84,8 @@ Later Add postal address at City University to request +Lucene for search (ask Louise for plugin) + Read wiki page lots http://www.mysociety.org/moin.cgi/FreedomOfInformation And comments on proposal |