diff options
-rw-r--r-- | bin/open311-update-reports | 66 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/Problem.pm | 82 | ||||
-rw-r--r-- | t/app/model/problem.t | 108 |
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(); |