aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/open311-update-reports66
-rw-r--r--perllib/FixMyStreet/DB/Result/Problem.pm82
-rw-r--r--t/app/model/problem.t108
3 files changed, 191 insertions, 65 deletions
diff --git a/bin/open311-update-reports b/bin/open311-update-reports
index 81a0394b8..3dfb89feb 100644
--- a/bin/open311-update-reports
+++ b/bin/open311-update-reports
@@ -71,71 +71,7 @@ while ( my $council = $council_list->next ) {
->search( { external_id => $request_id, } );
if (my $p = $problem->first) {
- my ( $updated, $status_notes );
-
- if ( ! ref $request->{updated_datetime} ) {
- $updated = $request->{updated_datetime};
- }
-
- if ( ! ref $request->{status_notes} ) {
- $status_notes = $request->{status_notes};
- }
-
- my $update = FixMyStreet::App->model('DB::Comment')->new(
- {
- problem_id => $p->id,
- state => 'confirmed',
- created => $updated || \'ms_current_timestamp()',
- confirmed => \'ms_current_timestamp()',
- text => $status_notes,
- mark_open => 0,
- mark_fixed => 0,
- user => $system_user,
- anonymous => 0,
- name => $council_details->{name},
- }
- );
-
- my $w3c = DateTime::Format::W3CDTF->new;
- my $req_time = $w3c->parse_datetime( $request->{updated_datetime} );
-
- # update from open311 is older so skip
- if ( $req_time < $p->lastupdate ) {
- next;
- }
-
- if ( $request->{status} eq 'closed' ) {
- if ( $p->state ne 'fixed' ) {
- $p->state('fixed');
- $update->mark_fixed(1);
-
- if ( !$status_notes ) {
-
- # FIXME - better text here
- $update->text( _('Closed by council') );
- }
-
- $p->update;
- $update->insert;
- }
- }
- # FIXME - if the council never marks as closed then
- # we will always re-open problems.
- else {
- if ( $p->state eq 'fixed' ) {
- $p->state('confirmed');
- $update->mark_open(1);
-
- if ( !$status_notes ) {
-
- # FIXME - better text here
- $update->text( _('Re-opened by council') );
- }
-
- $p->update;
- $update->insert;
- }
- }
+ $p->update_from_open311_service_request( $request, $council_details );
}
}
}
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
index 567ae9388..bff3f88a2 100644
--- a/perllib/FixMyStreet/DB/Result/Problem.pm
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -420,6 +420,88 @@ sub duration_string {
);
}
+=head2 update_from_open311_service_request
+
+ $p->update_from_open311_service_request( $request, $council_details, $system_user );
+
+Updates the problem based on information in the passed in open311 request. If the request
+has an older update time than the problem's lastupdate time then nothing happens.
+
+Otherwise a comment will be created if there is status update text in the open311 request.
+If the open311 request has a state of closed then the problem will be marked as fixed.
+
+NB: a comment will always be created if the problem is being marked as fixed.
+
+Fixed problems will not be re-opened by this method.
+
+=cut
+
+sub update_from_open311_service_request {
+ my ( $self, $request, $council_details, $system_user ) = @_;
+
+ my ( $updated, $status_notes );
+
+ if ( ! ref $request->{updated_datetime} ) {
+ $updated = $request->{updated_datetime};
+ }
+
+ if ( ! ref $request->{status_notes} ) {
+ $status_notes = $request->{status_notes};
+ }
+
+ my $update = FixMyStreet::App->model('DB::Comment')->new(
+ {
+ problem_id => $self->id,
+ state => 'confirmed',
+ created => $updated || \'ms_current_timestamp()',
+ confirmed => \'ms_current_timestamp()',
+ text => $status_notes,
+ mark_open => 0,
+ mark_fixed => 0,
+ user => $system_user,
+ anonymous => 0,
+ name => $council_details->{name},
+ }
+ );
+
+
+ my $w3c = DateTime::Format::W3CDTF->new;
+ my $req_time = $w3c->parse_datetime( $request->{updated_datetime} );
+
+ # set a timezone here as the $req_time will have one and if we don't
+ # use a timezone then the date comparisons are invalid.
+ # of course if local timezone is not the one that went into the data
+ # base then we're also in trouble
+ my $lastupdate = $self->lastupdate;
+ $lastupdate->set_time_zone( DateTime::TimeZone->new( name => 'local' ) );
+
+ # update from open311 is older so skip
+ if ( $req_time < $lastupdate ) {
+ return 0;
+ }
+
+ if ( $request->{status} eq 'closed' ) {
+ if ( $self->state ne 'fixed' ) {
+ $self->state('fixed');
+ $update->mark_fixed(1);
+
+ if ( !$status_notes ) {
+ # FIXME - better text here
+ $status_notes = _('Closed by council');
+ }
+ }
+ }
+
+ if ( $status_notes ) {
+ $update->text( $status_notes );
+ $self->lastupdate( $req_time );
+ $self->update;
+ $update->insert;
+ }
+
+ return 1;
+}
+
# we need the inline_constructor bit as we don't inherit from Moose
__PACKAGE__->meta->make_immutable( inline_constructor => 0 );
diff --git a/t/app/model/problem.t b/t/app/model/problem.t
index 1b8804fce..4d93729ea 100644
--- a/t/app/model/problem.t
+++ b/t/app/model/problem.t
@@ -152,4 +152,112 @@ for my $test (
};
}
+my $user = FixMyStreet::App->model('DB::User')->find_or_create(
+ {
+ email => 'system_user@example.com'
+ }
+);
+
+$problem->user( $user );
+$problem->created( DateTime->now()->subtract( days => 1 ) );
+$problem->lastupdate( DateTime->now()->subtract( days => 1 ) );
+$problem->anonymous(1);
+$problem->insert;
+
+my $tz_local = DateTime::TimeZone->new( name => 'local' );
+
+for my $test (
+ {
+ desc => 'request older than problem ignored',
+ lastupdate => '',
+ request => {
+ updated_datetime => DateTime::Format::W3CDTF->new()->format_datetime( DateTime->now()->set_time_zone( $tz_local )->subtract( days => 2 ) ),
+ },
+ council => {
+ name => 'Edinburgh City Council',
+ },
+ created => 0,
+ },
+ {
+ desc => 'request newer than problem created',
+ lastupdate => '',
+ request => {
+ updated_datetime => DateTime::Format::W3CDTF->new()->format_datetime( DateTime->now()->set_time_zone( $tz_local ) ),
+ status => 'open',
+ status_notes => 'this is an update from the council',
+ },
+ council => {
+ name => 'Edinburgh City Council',
+ },
+ created => 1,
+ state => 'confirmed',
+ mark_fixed => 0,
+ mark_open => 0,
+ },
+ {
+ desc => 'update with state of closed fixes problem',
+ lastupdate => '',
+ request => {
+ updated_datetime => DateTime::Format::W3CDTF->new()->format_datetime( DateTime->now()->set_time_zone( $tz_local ) ),
+ status => 'closed',
+ status_notes => 'the council have fixed this',
+ },
+ council => {
+ name => 'Edinburgh City Council',
+ },
+ created => 1,
+ state => 'fixed',
+ mark_fixed => 1,
+ mark_open => 0,
+ },
+ {
+ desc => 'update with state of open leaves problem as fixed',
+ lastupdate => '',
+ request => {
+ updated_datetime => DateTime::Format::W3CDTF->new()->format_datetime( DateTime->now()->set_time_zone( $tz_local ) ),
+ status => 'open',
+ status_notes => 'the council do not think this is fixed',
+ },
+ council => {
+ name => 'Edinburgh City Council',
+ },
+ created => 1,
+ start_state => 'fixed',
+ state => 'fixed',
+ mark_fixed => 0,
+ mark_open => 0,
+ },
+) {
+ subtest $test->{desc} => sub {
+ # makes testing easier;
+ $problem->comments->delete;
+ $problem->created( DateTime->now()->subtract( days => 1 ) );
+ $problem->lastupdate( DateTime->now()->subtract( days => 1 ) );
+ $problem->state( $test->{start_state} || 'confirmed' );
+ $problem->update;
+ my $w3c = DateTime::Format::W3CDTF->new();
+
+ my $ret = $problem->update_from_open311_service_request( $test->{request}, $test->{council}, $user );
+ is $ret, $test->{created}, 'return value';
+
+ return unless $test->{created};
+
+ $problem->discard_changes;
+ is $problem->lastupdate, $w3c->parse_datetime($test->{request}->{updated_datetime}), 'lastupdate time';
+
+ my $update = $problem->comments->first;
+
+ ok $update, 'updated created';
+
+ is $problem->state, $test->{state}, 'problem state';
+
+ is $update->text, $test->{request}->{status_notes}, 'update text';
+ is $update->mark_open, $test->{mark_open}, 'update mark_open flag';
+ is $update->mark_fixed, $test->{mark_fixed}, 'update mark_fixed flag';
+ };
+}
+
+$problem->comments->delete;
+$problem->delete;
+
done_testing();