aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/update-schema1
-rw-r--r--db/downgrade_0046---0045.sql6
-rw-r--r--db/schema.sql3
-rw-r--r--db/schema_0046-user-add-extra.sql6
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm3
-rw-r--r--perllib/FixMyStreet/App/Controller/Report.pm7
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm28
-rw-r--r--perllib/FixMyStreet/Script/Reports.pm9
-rw-r--r--t/app/controller/report_inspect.t30
-rw-r--r--t/app/sendreport/inspection_required.t32
-rw-r--r--templates/web/base/admin/category_edit.html11
-rw-r--r--templates/web/base/admin/user-form.html8
-rw-r--r--templates/web/base/report/display_tools.html2
-rw-r--r--web/js/fixmystreet-admin.js10
14 files changed, 144 insertions, 12 deletions
diff --git a/bin/update-schema b/bin/update-schema
index bb0360fb2..500e771f1 100755
--- a/bin/update-schema
+++ b/bin/update-schema
@@ -194,6 +194,7 @@ else {
# By querying the database schema, we can see where we're currently at
# (assuming schema change files are never half-applied, which should be the case)
sub get_db_version {
+ return '0046' if column_exists('users', 'extra');
return '0045' if table_exists('response_priorities');
return '0044' if table_exists('contact_response_templates');
return '0043' if column_exists('users', 'area_id');
diff --git a/db/downgrade_0046---0045.sql b/db/downgrade_0046---0045.sql
new file mode 100644
index 000000000..c0cc566af
--- /dev/null
+++ b/db/downgrade_0046---0045.sql
@@ -0,0 +1,6 @@
+BEGIN;
+
+ALTER TABLE users
+ DROP COLUMN extra;
+
+COMMIT;
diff --git a/db/schema.sql b/db/schema.sql
index 27f4bad13..fe45fb4aa 100644
--- a/db/schema.sql
+++ b/db/schema.sql
@@ -31,7 +31,8 @@ create table users (
title text,
twitter_id bigint unique,
facebook_id bigint unique,
- area_id integer
+ area_id integer,
+ extra text
);
-- Record details of reporting bodies, including open311 configuration details
diff --git a/db/schema_0046-user-add-extra.sql b/db/schema_0046-user-add-extra.sql
new file mode 100644
index 000000000..06937237c
--- /dev/null
+++ b/db/schema_0046-user-add-extra.sql
@@ -0,0 +1,6 @@
+BEGIN;
+
+ALTER TABLE users
+ ADD COLUMN extra TEXT;
+
+COMMIT;
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index 46ac10d36..8ec9eeaab 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -385,6 +385,9 @@ sub update_contacts : Private {
else {
$contact->unset_extra_metadata( 'inspection_required' );
}
+ if ( $c->get_param('reputation_threshold') ) {
+ $contact->set_extra_metadata( reputation_threshold => int($c->get_param('reputation_threshold')) );
+ }
if ( %errors ) {
$c->stash->{updated} = _('Please correct the errors below');
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm
index 34392782b..d56521fde 100644
--- a/perllib/FixMyStreet/App/Controller/Report.pm
+++ b/perllib/FixMyStreet/App/Controller/Report.pm
@@ -270,6 +270,8 @@ sub delete :Local :Args(1) {
$p->lastupdate( \'current_timestamp' );
$p->update;
+ $p->user->update_reputation(-1);
+
$c->model('DB::AdminLog')->create( {
admin_user => $c->user->email,
object_type => 'problem',
@@ -315,6 +317,7 @@ sub inspect : Private {
my $valid = 1;
my $update_text;
+ my $reputation_change = 0;
if ($permissions->{report_inspect}) {
foreach (qw/detailed_location detailed_information traffic_information/) {
@@ -325,6 +328,7 @@ sub inspect : Private {
$update_text = Utils::cleanup_text( $c->get_param('public_update'), { allow_multiline => 1 } );
if ($update_text) {
$problem->set_extra_metadata( inspected => 1 );
+ $reputation_change = 1;
} else {
$valid = 0;
$c->stash->{errors} ||= [];
@@ -362,6 +366,9 @@ sub inspect : Private {
}
if ($valid) {
+ if ( $reputation_change != 0 ) {
+ $problem->user->update_reputation($reputation_change);
+ }
$problem->update;
if ( defined($update_text) ) {
$problem->add_to_comments( {
diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm
index 2a2d0d5e3..8d42d5926 100644
--- a/perllib/FixMyStreet/DB/Result/User.pm
+++ b/perllib/FixMyStreet/DB/Result/User.pm
@@ -26,20 +26,22 @@ __PACKAGE__->add_columns(
{ data_type => "text", is_nullable => 1 },
"password",
{ data_type => "text", default_value => "", is_nullable => 0 },
- "flagged",
- { data_type => "boolean", default_value => \"false", is_nullable => 0 },
"from_body",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
+ "flagged",
+ { data_type => "boolean", default_value => \"false", is_nullable => 0 },
"title",
{ data_type => "text", is_nullable => 1 },
- "facebook_id",
- { data_type => "bigint", is_nullable => 1 },
"twitter_id",
{ data_type => "bigint", is_nullable => 1 },
+ "facebook_id",
+ { data_type => "bigint", is_nullable => 1 },
"is_superuser",
{ data_type => "boolean", default_value => \"false", is_nullable => 0 },
"area_id",
{ data_type => "integer", is_nullable => 1 },
+ "extra",
+ { data_type => "text", is_nullable => 1 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint("users_email_key", ["email"]);
@@ -100,11 +102,17 @@ __PACKAGE__->has_many(
);
-# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-08-03 13:52:28
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:SX8BS91mWHoOm2oWdNth1w
+# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-09-16 14:22:10
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:7wfF1VnZax2QTXCIPXr+vg
+
+__PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn");
+__PACKAGE__->rabx_column('extra');
use Moo;
use mySociety::EmailUtil;
+use namespace::clean -except => [ 'meta' ];
+
+with 'FixMyStreet::Roles::Extra';
__PACKAGE__->many_to_many( planned_reports => 'user_planned_reports', 'report' );
@@ -370,4 +378,12 @@ sub is_planned_report {
return $self->active_planned_reports->find({ id => $problem->id });
}
+sub update_reputation {
+ my ( $self, $change ) = @_;
+
+ my $reputation = $self->get_extra_metadata('reputation') || 0;
+ $self->set_extra_metadata( reputation => $reputation + $change);
+ $self->update;
+}
+
1;
diff --git a/perllib/FixMyStreet/Script/Reports.pm b/perllib/FixMyStreet/Script/Reports.pm
index 8d3b2ddbc..7d614bc30 100644
--- a/perllib/FixMyStreet/Script/Reports.pm
+++ b/perllib/FixMyStreet/Script/Reports.pm
@@ -145,9 +145,16 @@ sub send(;$) {
my $inspection_required = $sender_info->{contact}->get_extra_metadata('inspection_required') if $sender_info->{contact};
if ( $inspection_required ) {
+ my $reputation_threshold = $sender_info->{contact}->get_extra_metadata('reputation_threshold') || 0;
+ my $reputation_threshold_met = 0;
+ if ( $reputation_threshold > 0 ) {
+ my $user_reputation = $row->user->get_extra_metadata('reputation') || 0;
+ $reputation_threshold_met = $user_reputation >= $reputation_threshold;
+ }
unless (
$row->get_extra_metadata('inspected') ||
- $row->user->has_permission_to( trusted => $row->bodies_str_ids )
+ $row->user->has_permission_to( trusted => $row->bodies_str_ids ) ||
+ $reputation_threshold_met
) {
$skip = 1;
debug_print("skipped because not yet inspected", $row->id) if $debug_mode;
diff --git a/t/app/controller/report_inspect.t b/t/app/controller/report_inspect.t
index 6d6ec6559..393a8beb2 100644
--- a/t/app/controller/report_inspect.t
+++ b/t/app/controller/report_inspect.t
@@ -6,8 +6,8 @@ use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;
-my $brum = $mech->create_body_ok(2514, 'Birmingham City Council');
-my $oxon = $mech->create_body_ok(2237, 'Oxfordshire County Council');
+my $brum = $mech->create_body_ok(2514, 'Birmingham City Council', id => 2514);
+my $oxon = $mech->create_body_ok(2237, 'Oxfordshire County Council', id => 2237);
my $contact = $mech->create_contact_ok( body_id => $oxon->id, category => 'Cows', email => 'cows@example.net' );
my $rp = FixMyStreet::DB->resultset("ResponsePriority")->create({
body => $oxon,
@@ -62,6 +62,16 @@ FixMyStreet::override_config {
is $report->get_extra_metadata('inspected'), 1, 'report marked as inspected';
};
+ subtest "test positive reputation" => sub {
+ $report->unset_extra_metadata('inspected');
+ $report->update;
+ my $reputation = $report->user->get_extra_metadata("reputation");
+ $mech->get_ok("/report/$report_id/inspect");
+ $mech->submit_form_ok({ button => 'save_inspected', with_fields => { public_update => "This is a public update." } });
+ $report->discard_changes;
+ is $report->user->get_extra_metadata('reputation'), $reputation+1, "User reputation was increased";
+ };
+
subtest "test update is required when instructing" => sub {
$report->unset_extra_metadata('inspected');
$report->update;
@@ -107,6 +117,22 @@ FixMyStreet::override_config {
}
};
+FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.mysociety.org/',
+ ALLOWED_COBRANDS => 'oxfordshire',
+}, sub {
+ subtest "test negative reputation" => sub {
+ my $reputation = $report->user->get_extra_metadata("reputation");
+
+ $mech->get_ok("/report/$report_id");
+ $mech->submit_form( button => 'remove_from_site' );
+
+ $report->discard_changes;
+ is $report->user->get_extra_metadata('reputation'), $reputation-1, "User reputation was decreased";
+ };
+};
+
+
END {
$mech->delete_body($oxon);
$mech->delete_body($brum);
diff --git a/t/app/sendreport/inspection_required.t b/t/app/sendreport/inspection_required.t
index 88a48e991..f9d40d39f 100644
--- a/t/app/sendreport/inspection_required.t
+++ b/t/app/sendreport/inspection_required.t
@@ -69,6 +69,38 @@ subtest 'Uninspected report is sent when made by trusted user' => sub {
$report->discard_changes;
$mech->email_count_is( 1 );
ok $report->whensent, 'Report marked as sent';
+ is $report->get_extra_metadata('inspected'), undef, 'Report not marked as inspected';
+};
+
+subtest 'Uninspected report isn’t sent when user rep is too low' => sub {
+ $mech->clear_emails_ok;
+ $report->whensent( undef );
+ $report->update;
+
+ $user->user_body_permissions->delete;
+ $user->set_extra_metadata(reputation => 15);
+ $user->update;
+
+ $contact->set_extra_metadata(reputation_threshold => 20);
+ $contact->update;
+
+ FixMyStreet::DB->resultset('Problem')->send_reports();
+
+ $report->discard_changes;
+ $mech->email_count_is( 0 );
+ is $report->whensent, undef, 'Report hasn’t been sent';
+};
+
+subtest 'Uninspected report is sent when user rep is high enough' => sub {
+ $user->set_extra_metadata(reputation => 21);
+ $user->update;
+
+ FixMyStreet::DB->resultset('Problem')->send_reports();
+
+ $report->discard_changes;
+ $mech->email_count_is( 1 );
+ ok $report->whensent, 'Report marked as sent';
+ is $report->get_extra_metadata('inspected'), undef, 'Report not marked as inspected';
};
done_testing();
diff --git a/templates/web/base/admin/category_edit.html b/templates/web/base/admin/category_edit.html
index 6aec0c132..05fa2ca4e 100644
--- a/templates/web/base/admin/category_edit.html
+++ b/templates/web/base/admin/category_edit.html
@@ -19,7 +19,7 @@
[% END %]
</p>
-<form method="post" action="[% c.uri_for('body', body_id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8">
+<form method="post" action="[% c.uri_for('body', body_id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8" id="category_edit">
<p><strong>[% loc('Category:') %] </strong>[% contact.category | html %]
<input type="hidden" name="category" value="[% contact.category | html %]" >
<input type="hidden" name="token" value="[% csrf_token %]" >
@@ -47,6 +47,15 @@
[% END %]
</p>
+ [% IF c.cobrand.moniker != 'zurich' %]
+ <p [% 'class=hidden' UNLESS contact.get_extra_metadata('inspection_required') %]>
+ <label>
+ [% loc('Reputation threshold:') %]
+ <input type="text" name="reputation_threshold" id="reputation_threshold" value="[% contact.get_extra_metadata('reputation_threshold') | html %]" size="30">
+ </label>
+ </p>
+ [% END %]
+
<p><strong>[% loc('Note:') %] </strong><textarea name="note" rows="3" cols="40"></textarea>
[% IF body.can_be_devolved %]
diff --git a/templates/web/base/admin/user-form.html b/templates/web/base/admin/user-form.html
index 40e0b510a..87324666d 100644
--- a/templates/web/base/admin/user-form.html
+++ b/templates/web/base/admin/user-form.html
@@ -110,6 +110,14 @@
</label>
[% END %]
</li>
+ <li>
+ <div class="admin-hint">
+ <p>
+ [% loc("Reports from users with high enough reputation will be sent immediately without requiring inspection. Each category's threshold can be managed on its edit page. Users earn reputation when a report they have made is marked as inspected by inspectors.") %]
+ </p>
+ </div>
+ [% loc('Reputation:') %] [% user.get_extra_metadata('reputation') %]
+ </li>
[% END %]
[% IF c.user.is_superuser %]
diff --git a/templates/web/base/report/display_tools.html b/templates/web/base/report/display_tools.html
index 052ffb8a5..82f7d0ac3 100644
--- a/templates/web/base/report/display_tools.html
+++ b/templates/web/base/report/display_tools.html
@@ -3,7 +3,7 @@
[% IF c.user_exists AND c.cobrand.users_can_hide AND c.user.belongs_to_body( problem.bodies_str ) %]
<li><form method="post" action="/report/delete/[% problem.id %]" id="remove-from-site-form">
<input type="hidden" name="token" value="[% csrf_token %]">
- <input type="submit" id="key-tool-report-abuse" class="abuse" data-confirm="[% loc('Are you sure?') %]" value="[% loc('Remove from site') %]">
+ <input type="submit" id="key-tool-report-abuse" class="abuse" data-confirm="[% loc('Are you sure?') %]" name="remove_from_site" value="[% loc('Remove from site') %]">
</form></li>
[% ELSIF c.cobrand.moniker != 'zurich' %]
<li><a rel="nofollow" id="key-tool-report-abuse" class="abuse" href="[% c.uri_for( '/contact', { id => problem.id } ) %]">[% loc('Report abuse' ) %]</a></li>
diff --git a/web/js/fixmystreet-admin.js b/web/js/fixmystreet-admin.js
index aa79a9b46..6f4580feb 100644
--- a/web/js/fixmystreet-admin.js
+++ b/web/js/fixmystreet-admin.js
@@ -79,5 +79,15 @@ $(function(){
var show_area = $(this).val() == $(this).find("[data-originally-selected]").val();
$("form#user_edit select#area_id").closest("li").toggle(show_area);
});
+
+ // On category edit page, hide the reputation input if inspection isn't required
+ $("form#category_edit #inspection_required").change(function() {
+ var $p = $("form#category_edit #reputation_threshold").closest("p");
+ if (this.checked) {
+ $p.removeClass("hidden");
+ } else {
+ $p.addClass("hidden");
+ }
+ });
});